Module:Calc

local U = require("Module:Utils") local format = require("Module:Utils").format local Formatting = require("Module:Formatting") local Equipment = require("Module:Equipment") local ShipIterator = require("Module:ShipIterator") local ShipCapabilities = require("Module:ShipCapabilities") local ShipBattleCardKai = require("Module:ShipBattleCardKai") local Combat2 = require("Module:Combat2") local EquipmentCardKai = require("Module:EquipmentCardKai") local EquipmentGraphicKai = require("Module:EquipmentGraphicKai") local EquipmentCollection = require("Module:Collection/Equipment") local Development = require("Module:Development")

local Ship = nil

local frame = nil local args = nil local ship = nil local target = nil local shipCapabilities = {} local equipment = nil

-- $('.calc-debug').show.appendTo('#mw-content-text') local debug = {}

function debugLog(k, v)   if args.debug then k = U.trim(tostring(k)) v = U.trim(tostring(v)) table.insert(debug, k .. " = " .. v)   end end

function debugString return #debug > 0 and args.debug and ( ) or "" end

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,

equipment = function return U.imap(EquipmentCollection, function(e) return e._name end) 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, format_opening_torpedo = function(ship) return shipCapabilities:format_opening_torpedo(shipCapabilities:opening_torpedo) end, code = function(obj) return equipment and Formatting:format_equipment_type(obj:type) or           Formatting:format_ship_code(obj:type) end,

-- overrides ShipData:type type = function(obj) return equipment and Formatting:format_equipment_type(obj:type) or           Formatting:format_ship_type(obj:type) end,

icon = function(obj) return <span data-sort-value=" .. obj._type .. " end,

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

-- overrides ShipData:class class = function(ship) return ship:class and ship:class:name or "?" 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,

-- overrides ShipData:card card = function(obj) if obj.hp then return ShipBattleCardKai:Asset({ obj:name("/") }) else return EquipmentCardKai:Asset({ obj:name, size = "75px", link = nil }) end end,

item = function(obj) return EquipmentGraphicKai:Asset({ obj:name, size = "75px", link = nil }) end,

fairy = function(obj) return EquipmentGraphicKai:Asset({ obj:name, size = "75px", fairy = "only", link = nil }) end,

full = function(obj) return EquipmentGraphicKai:Asset({ obj:name, size = "75px", fairy = "true", link = nil }) end,

format_morale = function(ship) local morale = ship:morale or 49 return morale <= 19 and "Red" or morale <= 29 and "Orange" or morale <= 49 and "Normal" or "Sparkle" end,

hit_rate = function(ship, target) local r = Combat2.hit_rate(ship, target) if r then ship.hit_rate = r           return r .. "%"       else return "nil" end end,

critical_hit_rate = function(ship, target) local r = Combat2.critical_hit_rate(ship, target) if r then ship.critical_hit_rate = r           return r .. "%"       else return "nil" end end,

scrap = function(eq) local scrap = eq:scrap return format{ "${fuel}/${ammo}/${steel}/${bauxite}", fuel = scrap.fuel or 0, ammo = scrap.ammo or 0, steel = scrap.steel or 0, bauxite = scrap.bauxite or 0, }   end,

development = function(eq) return Development.formatResources(eq) end,

development_rate = function(eq) return Development.formatRates(eq) end, development_hq = function(eq) return Development.formatHQ(eq) end,

}

function addFormattingFunctions(name, table) for k, v in pairs(table) do       formatting_functions[name .. "." .. k] = v   end end

local Plugins = require("Module:Calc/Plugins")

for _, name in ipairs(Plugins) do   local data = require("Module:Calc/Plugins/" .. name) addFormattingFunctions(name, data) 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, ship, target) local formatting_function = formatting_functions[key] if formatting_function then if ship then return formatting_function(ship, target) else return formatting_function(ship, target) end else if shipCapabilities[key] then local a, b = shipCapabilities[key](shipCapabilities) return format_lua(b or a)       elseif ship then 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 format_arg(arg) return args.format == "table" and ("| " .. arg .. "\n") or arg end

local env = {}

function interpret_setter(s) local kv = mw.text.split(s, "%s*~%s*") local k = kv[1] local v = kv[2] local c = kv[3] if k and v and c then env[c] = env[c] or require("Module:" .. c)       env[k] = env[c](v) if k == "_" then ship = env[k] end return true elseif k and v then if k == "_equipment" then local equipment = {} local accuracy = 0 local ng = 0 for eq in string.gmatch(v, '([^,]+)') do               local eqObj = Equipment(eq) table.insert(equipment, { equipment = eqObj }) accuracy = accuracy + (eqObj:shelling_accuracy or 0) if eqObj:type == 3 then ng = ng + 1 end end ship._equipment = equipment ship._accuracy = accuracy if ng > 0 then ship._ng = ng           end else if v ~= "nil" and ship then ship[k] = tonumber(v) else env[k] = v           end end return true else return false end end

function interpret_arg(arg) local prefix = string.sub(arg, 1, 1) local prefix2 = string.sub(arg, 1, 2) if arg == "_" then return false elseif arg == "-" then return format_arg("") elseif 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) if ship:id then shipCapabilities = ShipCapabilities{ ship = ship } else ship = Equipment(ship_key) equipment = true end elseif prefix2 == "!!" then local key = string.sub(arg, 3) target = Ship(key) elseif prefix == "!" then local key = string.sub(arg, 2) if not interpret_setter(key) then local parts = string.gmatch(key, '([^:]+)') local i = 1 for part in parts do               if i == 1 then key = part ship = Ship(key) if ship:id then shipCapabilities = ShipCapabilities{ ship = ship } else ship = Equipment(key) equipment = true end else interpret_setter(part) end i = i + 1 end end elseif prefix == "#" and args.format == "table" then return "|-\n" elseif prefix == "?" then local prefix2 = string.sub(arg, 1, 2) if prefix2 == "??" then return format_arg(format_value(string.sub(arg, 3), target, ship)) elseif prefix2 == "?#" then return frame:preprocess(format{string.sub(arg, 3), this = env[this] or ""}) else return format_arg(format_value(string.sub(arg, 2), ship, target)) end else return format_arg(arg) end end

function interpret_args Ship = args.enemy and require("Module:EnemyShip") or require("Module:Ship") debugLog("#args", #args) debugLog("type(args)", type(args)) local i = 1 local values = {} repeat for _, arg in ipairs(args) do           debugLog("i", i)            debugLog("arg", arg) local value = interpret_arg(arg) debugLog("value", value) if value then table.insert(values, value) end i = i + 1 end until not sequence or sequence_position > #sequence debugLog("#values", #values) return table.concat(values, args.concat or "") .. debugString end

local Calc = {}

function Calc.format(frame_, args_) frame = frame_ args = args_ or U.getTemplateArgs(frame).explicit for _, arg in ipairs(args) do       debugLog("arg", arg) end return interpret_args end

function Calc.test mw.log(       Calc.format(nil, { format = "table", debug = "true", "!Nagato/Kai Ni", "!_equipment ~ 41cm Triple Gun Mount Kai, 41cm Triple Gun Mount Kai, Type 13 Air Radar Kai", "!_level ~ 99", "!_luck ~ nil", "!_morale ~ 25", "!!Destroyer Ro-Class", "!cl0 ~ 56", "!cl1 ~ 807", "!cl2 ~ 137", "?card", "?level", "?format_morale", "?accuracy", "?luck", "??card", "?cl0", "?cl1", "?cl2", "",           "",            "",            "",            "-",            "?FitData.hit", "?FitData.error", "?FitData.crit", "?hit_rate", "?critical_hit_rate", "?FitData.difference", "?FitData.critical_difference", "?FitData.accuracy_value", "?FitData.fit", })   ) end -- print(p.test)

return Calc