• Welcome to the Kancolle Wiki!
  • If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord

Difference between revisions of "Module:Calc"

From Kancolle Wiki
Jump to navigation Jump to search
Line 8: Line 8:
 
local args = nil
 
local args = nil
 
local ship = nil
 
local ship = nil
 +
local target = nil
 
local shipCapabilities = nil
 
local shipCapabilities = nil
 
local frame = nil
 
local frame = nil
Line 61: Line 62:
 
             day = date[3] < 10 and "0" .. date[3] or date[3],
 
             day = date[3] < 10 and "0" .. date[3] or date[3],
 
         }
 
         }
 +
    end,
 +
 +
    test = function(ship, target)
 +
        return ship:level() + ship._accuracy - target:evasion()
 
     end,
 
     end,
  
Line 76: Line 81:
 
     local formatting_function = formatting_functions[key]
 
     local formatting_function = formatting_functions[key]
 
     if formatting_function then
 
     if formatting_function then
         return formatting_function(ship)
+
         return formatting_function(ship, target)
 
     else
 
     else
 
         if shipCapabilities[key] then
 
         if shipCapabilities[key] then
Line 97: Line 102:
 
function interpret_arg(arg)
 
function interpret_arg(arg)
 
     local prefix = string.sub(arg, 1, 1)
 
     local prefix = string.sub(arg, 1, 1)
 +
    local prefix2 = string.sub(arg, 1, 2)
 
     if prefix == "@" then
 
     if prefix == "@" then
 
         local enumerator = string.sub(arg, 2)
 
         local enumerator = string.sub(arg, 2)
Line 109: Line 115:
 
         ship = Ship(ship_key)
 
         ship = Ship(ship_key)
 
         shipCapabilities = ShipCapabilities{ ship = ship }
 
         shipCapabilities = ShipCapabilities{ ship = ship }
 +
    elseif prefix2 == "!!" then
 +
        local key = string.sub(arg, 3)
 +
        target = Ship(key)
 
     elseif prefix == "!" then
 
     elseif prefix == "!" then
 
         local ship_key = string.sub(arg, 2)
 
         local ship_key = string.sub(arg, 2)
         if string.sub(ship_key, 1, 3) == "eq:" and ship then
+
         if string.sub(ship_key, 1, 1) == "_" and ship then
             local eqs = string.sub(ship_key, 4)
+
             local kv = mw.text.split(ship_key, "%s*=%s*")
             local equipment = {}
+
             local k = kv[1]
            for eq in string.gmatch(eqs, '([^,]+)') do
+
            local v = kv[2]
                table.insert(equipment, { equipment = eq })
+
            if k and v then
 +
                if k == "_equipment" then
 +
                    local equipment = {}
 +
                    for eq in string.gmatch(v, '([^,]+)') do
 +
                        table.insert(equipment, { equipment = eq })
 +
                    end
 +
                    ship._equipment = equipment
 +
                else
 +
                    ship[k] = tonumber(v)
 +
                end
 
             end
 
             end
            ship._equipment = equipment
 
 
         else
 
         else
 
             local parts = string.gmatch(ship_key, '([^:]+)')
 
             local parts = string.gmatch(ship_key, '([^:]+)')
Line 126: Line 143:
 
                     ship = Ship(ship_key)
 
                     ship = Ship(ship_key)
 
                     shipCapabilities = ShipCapabilities{ ship = ship }
 
                     shipCapabilities = ShipCapabilities{ ship = ship }
                 elseif i == 2 then
+
                 else
                    local equipment = {}
+
                    local kv = mw.text.split(part, "%s*=%s*")
                    for eq in string.gmatch(part, '([^,]+)') do
+
                    local k = kv[0]
                        table.insert(equipment, { equipment = eq })
+
                    local v = kv[1]
 +
                    if k and v then
 +
                        if k == "_equipment" then
 +
                            local equipment = {}
 +
                            for eq in string.gmatch(part, '([^,]+)') do
 +
                                table.insert(equipment, { equipment = eq })
 +
                            end
 +
                            ship._equipment = equipment
 +
                        else
 +
                            ship[k] = tonumber(v)
 +
                        end
 
                     end
 
                     end
                    ship._equipment = equipment               
 
 
                 end
 
                 end
 
                 i = i + 1
 
                 i = i + 1
Line 206: Line 232:
 
     mw.log(
 
     mw.log(
 
         Calc.format(nil, {
 
         Calc.format(nil, {
             "!Nagato/Kai Ni: Prototype 41cm Triple Gun Mount, Prototype 41cm Triple Gun Mount",
+
             "!Nagato/Kai Ni",
             "?day_battle"
+
            "!_level = 99",
 +
            "!_accuracy = 10",
 +
            "!!Destroyer Ro-Class",
 +
             "?test"
 
         })
 
         })
 
     )
 
     )

Revision as of 17:07, 4 November 2017

Documentation for this module may be created at Module:Calc/doc

local Utils = require("Module:Utils")
local format = require("Module:StringOperations").format
local Formatting = require("Module:Formatting")
local Ship = require("Module:Ship")
local ShipIterator = require("Module:ShipIterator")
local ShipCapabilities = require("Module:ShipCapabilities")

local args = nil
local ship = nil
local target = nil
local shipCapabilities = nil
local frame = nil

local enumerating_functions = {

    args = function()
        return mw.text.split(args.args, "%s*,%s*")
    end,

    base_names = function()
        return ShipIterator.baseForms
    end,

    all_names = function()
        return ShipIterator.allForms
    end,
    
    enemy = function()
        return ShipIterator.enemyForms
    end,

}

-- TODO: have a syntax for calling Module:Formatting functions?
local formatting_functions = {

    night_battle_power = function(ship)
        return (ship:firepower_max() or 0) + (ship:torpedo_max() or 0)
    end,
    
    code = function(ship)
        return Formatting:format_ship_code(ship:type())
    end,

    -- overrides ShipData:type
    type = function(ship)
        return Formatting:format_ship_type(ship:type())
    end,

    -- overrides ShipData:link
    link = function(ship)
        return Formatting:format_link(ship:link())
    end,

    -- overrides ShipData:implementation_date
    implementation_date = function(ship)
        local date = ship:implementation_date()
        return not date and "??" or format{
            "${year}/${month}/${day}",
            year = date[1],
            month = date[2] < 10 and "0" .. date[2] or date[2],
            day = date[3] < 10 and "0" .. date[3] or date[3],
        }
    end,

    test = function(ship, target)
        return ship:level() + ship._accuracy - target:evasion()
    end,

}

function format_lua(lua)
    if type(lua) == "table" then
        return tostring(table.concat(lua, args.concat_value or ", "))
    else
        return tostring(lua)
    end
end

function format_value(key)
    local formatting_function = formatting_functions[key]
    if formatting_function then
        return formatting_function(ship, target)
    else
        if shipCapabilities[key] then
            local a, b = shipCapabilities[key](shipCapabilities)
            return format_lua(b or a)
        else
            local lua = ship[key]
            if type(lua) == "function" then
                return format_lua(lua(ship))
            else
                return format_lua(lua)
            end
        end
    end
end

local sequence = nil
local sequence_position = nil

function interpret_arg(arg)
    local prefix = string.sub(arg, 1, 1)
    local prefix2 = string.sub(arg, 1, 2)
    if prefix == "@" then
        local enumerator = string.sub(arg, 2)
        local enumerating_function = enumerating_functions[enumerator]
        if enumerating_function and not sequence then
            sequence = enumerating_function()
            sequence_position = 1
        end
    elseif arg == "!@" then
        local ship_key = sequence[sequence_position]
        sequence_position = sequence_position + 1
        ship = Ship(ship_key)
        shipCapabilities = ShipCapabilities{ ship = ship }
    elseif prefix2 == "!!" then
        local key = string.sub(arg, 3)
        target = Ship(key)
    elseif prefix == "!" then
        local ship_key = string.sub(arg, 2)
        if string.sub(ship_key, 1, 1) == "_" and ship then
            local kv = mw.text.split(ship_key, "%s*=%s*")
            local k = kv[1]
            local v = kv[2]
            if k and v then
                if k == "_equipment" then
                    local equipment = {}
                    for eq in string.gmatch(v, '([^,]+)') do
                        table.insert(equipment, { equipment = eq })
                    end
                    ship._equipment = equipment
                else
                    ship[k] = tonumber(v)
                end
            end
        else
            local parts = string.gmatch(ship_key, '([^:]+)')
            local i = 1
            for part in parts do
                if i == 1 then
                    ship_key = part
                    ship = Ship(ship_key)
                    shipCapabilities = ShipCapabilities{ ship = ship }
                else
                    local kv = mw.text.split(part, "%s*=%s*")
                    local k = kv[0]
                    local v = kv[1]
                    if k and v then
                        if k == "_equipment" then
                            local equipment = {}
                            for eq in string.gmatch(part, '([^,]+)') do
                                table.insert(equipment, { equipment = eq })
                            end
                            ship._equipment = equipment
                        else
                            ship[k] = tonumber(v)
                        end
                    end
                end
                i = i + 1
            end
        end
    elseif prefix == "#" and args.format == "table" then
        return "|-\n"
    elseif prefix == "?" then
        prefix = string.sub(arg, 2, 2)
        if prefix == "?" then
            local key = string.sub(arg, 3)
            return frame:preprocess(format{
                '{{${template}|${ship}}}',
                template = key,
                ship = ship:name('/')
            })
        else
            local key = string.sub(arg, 2)
            local value = format_value(key)
            if args.format == "table" then
                return "|" .. value .. "\n"
            else
                return value
            end
        end
    else
        return arg
    end
end

local special_functions = {
    apply = function(args_)
        local frame_ = frame:getParent()
        local template = args_[2]
        local values = {}
        for i = 3, #args_ do
            table.insert(values, format{
                '{{${template}|${arg}}}',
                template = template,
                arg = args_[i]
            })
        end
        return frame_:preprocess(table.concat(values, args.concat or ""))
    end
}

function interpret_args(args_)
    args = args_
    local special_function = special_functions[args[1]]
    if special_function then
        return special_function(args)
    else
        local values = {}
        repeat
            for _, arg in ipairs(args_) do
                local value = interpret_arg(arg)
                if value then
                    table.insert(values, value)
                end
            end
        until not sequence or sequence_position > #sequence
        return table.concat(values, args.concat or "")
    end
end

local Calc = {}

function Calc.format(frame_, args_)
    frame = frame_
    return interpret_args(args_ or Utils.getTemplateArgs(frame_).explicit)
end

function Calc.test()
    mw.log(
        Calc.format(nil, {
            "!Nagato/Kai Ni",
            "!_level = 99",
            "!_accuracy = 10",
            "!!Destroyer Ro-Class",
            "?test"
        })
    )
end

return Calc