Module:RenderInfobox
Jump to navigation
Jump to search
This module depends on: |
This module is used to render automatic infoboxes. Parameters not found in Docs.json have to be supplied manually.
Invocation
The preferred way of invocating this module is through the dedicated infobox templates: {{Infobox item}}
and {{Infobox building}}
. Parameters are documented on their respective Doc pages.
require("Module:DocsUtils")
local p = {}
-- Hover tooltips for select labels
loc.tooltips = {
maxSpeed = "Applies on flat terrain, can be exceeded if going downhill",
time0_50 = "Time to reach 50 km/h on flat terrain",
damagePerSecond = "Damage per second",
}
-- Group names
loc.groups = {
item = "Item",
liquid = "Liquid",
gas = "Gas",
unknown = "Unknown",
building = "Building",
vehicle = "Vehicle",
fuel = "Fuel",
equipment = "Equipment",
ingredients = "Ingre­dients",
dimensions = "Dimensions",
}
-- Row labels (may be wiki links)
loc.labels = {
unlockedBy = "Unlocked by",
className = "Class name",
stackSize = "Stack size",
radioactive = "[[Radioactivity|Radioactive]]",
sinkPoints = "[[AWESOME Sink|Sink points]]",
energy = "Energy",
stackEnergy = "Stack energy",
abbreviation = "Abbrev­iation",
fluidColor = "Fluid color",
equipmentSlot = "Equipment slot",
ammo = "Ammo",
damage = "[[Health|Damage]]",
magSize = "Magazine size",
rateOfFire = "Rate of fire",
reloadTime = "Reload time",
damagePerSecond = "DPS",
range = "Range",
powerUsage = "[[Power|Power usage]]",
powerGenerated = "[[Power|Power generated]]",
fuelBurnRate = "Fuel burn rate",
supplementPerMinute = "Supplement input rate",
overclockable = "[[Clock speed|Overclock­able]]",
inventorySize = "Inventory size",
beltInputs = "Conveyor<br/>inputs",
beltOutputs = "Conveyor<br/>outputs",
pipeInputs = "Pipeline<br/>inputs",
pipeOutputs = "Pipeline<br/>outputs",
maxSpeed = "Max speed",
time0_50 = "0-50 km/h",
size_width = "Width",
size_length = "Length",
size_height = "Height",
size_area = "Area",
yes = "Yes",
no = "No",
}
loc.categories = {
items = "[[Category:Items]]",
fluids = "[[Category:Fluids]]",
liquids = "[[Category:Liquids]]",
gases = "[[Category:Gases]]",
buildings = "[[Category:Buildings]]",
vehicles = "[[Category:Vehicles]]",
fuels = "[[Category:Fuels]]",
radioactive = "[[Category:Radioactive]]",
}
loc.fuelSort = function(a, b)
if a.isVehicle ~= b.isVehicle then
return not a.isVehicle
elseif not a.isVehicle then
return a.buildingName < b.buildingName
else
return a.buildingName > b.buildingName
end
end
-- Generate a single <data> row. Automatically get label from loc.labels and format the value.
-- - parameter - string - parameter name from the data JSON
-- - branchValues - table
-- - unit - string - unit to show after the values
-- - nowiki - boolean - whether to escape the values
local function infoboxRow(parameter, branchValues, unit, nowiki)
local output = formatBranchDiff(getBranchValues(parameter, branchValues.stable, branchValues.experimental), nil, nowiki)
if output ~= "" and unit ~= nil then
output = output .. unit
end
return "<data><label>" .. loc.labels[parameter] .. "</label><default>" .. output .. "</default></data>"
end
function p.generateItemInfobox(frame)
local targetClassName = frame:getParent().args.className
local target = getObjectFromClassName(targetClassName, itemsJSON)
if target.stable == nil and target.experimental == nil then
return tostring(mw.html.create("strong"):addClass("error"):wikitext("Item infobox error: invalid target"):allDone())
end
-- image name
local itemLink, _ = getLinkAndName(targetClassName, target.stable, target.experimental)
-- form
local forms = getBranchValues("form", target.stable, target.experimental)
forms.stable = forms.stable ~= nil and (forms.stable == "solid" and loc.groups.item or (forms.stable == "liquid" and loc.groups.liquid or (forms.stable == "gas" and loc.groups.gas or loc.groups.item))) or nil
forms.experimental = forms.experimental ~= nil and (forms.experimental == "solid" and loc.groups.item or (forms.experimental == "liquid" and loc.groups.liquid or (forms.experimental == "gas" and loc.groups.gas or loc.groups.item))) or nil
forms.text = formatBranchDiff(forms)
forms.eitherIsSolid = forms.stable == loc.groups.item or forms.experimental == loc.groups.item
forms.eitherIsFluid = forms.stable == loc.groups.liquid or forms.experimental == loc.groups.liquid or forms.stable == loc.groups.gas or forms.experimental == loc.groups.gas
-- fuel
local fuelValues = getBranchValues("energy", target.stable, target.experimental)
local fuelSection = ""
if fuelValues.stable ~= 0 or fuelValues.experimental ~= 0 then
local fuelConsumers = {}
local fuelConsumersOrder = {}
-- list the item's energy
fuelSection = "<data><label>" .. loc.labels.energy .. "</label><default>" .. formatBranchDiff(fuelValues) .. loc.units.mj .. "</default></data>"
-- if the item is a solid fuel, list the energy per stack
if (target.stable ~= nil and target.stable.form == "solid") or (target.experimental ~= nil and target.experimental.form == "solid") then
fuelSection = fuelSection .. "<data><label>" .. loc.labels.stackEnergy .. "</label><default>" .. formatBranchDiff(
{stable = fuelValues.stable ~= nil and target.stable.form == "solid" and fuelValues.stable * target.stable.stackSize or nil,
experimental = fuelValues.experimental ~= nil and target.experimental.form == "solid" and fuelValues.experimental * target.experimental.stackSize or nil},
target.stable ~= nil and target.experimental ~= nil and target.stable.form ~= target.experimental.form) .. loc.units.mj .. "</default></data>"
end
-- list the buildings that consume the item as fuel
for _,branchBuildings in pairs(buildingsJSON) do
for _,building in pairs(branchBuildings) do
for _,fuelProcess in pairs(building.burnsFuel) do
if fuelProcess.fuel == targetClassName then
if fuelConsumers[building.className] == nil then
fuelConsumers[building.className] = {}
end
if building.stable then
fuelConsumers[building.className].stable = building
end
if building.experimental then
fuelConsumers[building.className].experimental = building
end
end
end
end
end
-- determine the order of the fuel consumers by retrieving names from their classNames, then sorting alphabetically
for className,_ in pairs(fuelConsumers) do
local buildingLink, buildingName = getLinkAndName(className, fuelConsumers[className].stable, fuelConsumers[className].experimental)
table.insert(fuelConsumersOrder, {className = className, buildingName = buildingName, buildingLink = buildingLink, isVehicle = fuelConsumers[className].stable ~= nil and fuelConsumers[className].stable.isVehicle or fuelConsumers[className].experimental ~= nil and fuelConsumers[className].experimental.isVehicle})
end
table.sort(fuelConsumersOrder, loc.fuelSort)
-- list the fuel consumption of each building in both branches, in both per minute and per cycle
for _,namedBuilding in pairs(fuelConsumersOrder) do
local branchBuilding = fuelConsumers[namedBuilding.className]
local buildingPowerGeneration = getBranchValues("powerGenerated", branchBuilding.stable, branchBuilding.experimental)
if buildingPowerGeneration.stable == 0 then
buildingPowerGeneration.stable = nil
end
if buildingPowerGeneration.experimental == 0 then
buildingPowerGeneration.experimental = nil
end
-- calculate the fuel consumption per minute and per cycle
if buildingPowerGeneration.stable ~= nil and buildingPowerGeneration.stable ~= 0 and fuelValues.stable ~= nil then
buildingPowerGeneration.stable = fuelValues.stable/buildingPowerGeneration.stable
buildingPowerGeneration.stablePerMin = formatNumber(60/buildingPowerGeneration.stable)
buildingPowerGeneration.stable = formatNumber(buildingPowerGeneration.stable)
end
if buildingPowerGeneration.experimental ~= nil and fuelValues.experimental ~= nil then
buildingPowerGeneration.experimental = fuelValues.experimental/buildingPowerGeneration.experimental
buildingPowerGeneration.experimentalPerMin = formatNumber(60/buildingPowerGeneration.experimental)
buildingPowerGeneration.experimental = formatNumber(buildingPowerGeneration.experimental)
end
-- manually do EA/EX formatting
local fuelConsumption = ""
-- if it's the same for both branches, list it only once
if buildingPowerGeneration.stable ~= nil and buildingPowerGeneration.stable == buildingPowerGeneration.experimental then
fuelConsumption = "<li>'''" .. buildingPowerGeneration.stable .. loc.units.sec .. " (" .. buildingPowerGeneration.stablePerMin .. loc.units.pmin .. ")'''</li>"
else
-- if it's different for each branch, list it twice, formatted for each branch
if buildingPowerGeneration.stable ~= nil then
fuelConsumption = fuelConsumption .. "<li>{{EA|'''" .. buildingPowerGeneration.stable .. loc.units.sec .. "''' (" .. buildingPowerGeneration.stablePerMin .. loc.units.pmin .. ")}}</li>"
end
if buildingPowerGeneration.experimental ~= nil then
fuelConsumption = fuelConsumption .. "<li>{{EX|'''" .. buildingPowerGeneration.experimental .. loc.units.sec .. "''' (" .. buildingPowerGeneration.experimentalPerMin .. loc.units.pmin .. ")}}</li>"
end
end
fuelSection = fuelSection .. "<data><default><ul><li>{{ItemLink|" .. namedBuilding.buildingLink .. "|" .. namedBuilding.buildingName .. "}}<ul>" .. fuelConsumption .. "</ul><li/></ul></default></data>"
end
-- wrap in a group, end the fuel consumers list and data row
fuelSection = [=[<group collapse="open"><header>]=] .. loc.groups.fuel .. [=[</header>]=] .. fuelSection .. [=[</group>]=]
end
-- infobox
local xml = [=[<infobox>
<title><default>]=] .. formatBranchDiff(getBranchValues("name", target.stable, target.experimental), true) .. [=[</default></title>
<image><default>]=] .. frame:callParserFunction("#setmainimage", itemLink .. ".png") .. [=[</default></image>
<data><default><i>]=] .. formatBranchDiff(getBranchValues("description", target.stable, target.experimental)) .. [=[</i></default></data>
]=] .. infoboxRow("unlockedBy", target) .. [=[
]=] .. infoboxRow("className", target) .. [=[
<group collapse="open"><header>]=] .. forms.text .. [=[</header>
]=] .. (forms.eitherIsSolid and infoboxRow("stackSize", target) or "") .. [=[
]=] .. infoboxRow("radioactive", target) .. [=[
]=] .. (forms.eitherIsSolid and infoboxRow("sinkPoints", target) or "") .. [=[
]=] .. infoboxRow("abbreviation", target) .. [=[
]=] .. (forms.eitherIsFluid and infoboxRow("fluidColor", target, nil, true) or "") .. [=[
</group>]=] .. fuelSection .. [=[
<group collapse="open"><header>]=] .. loc.groups.equipment .. [=[</header>
<data><label>]=] .. loc.labels.equipmentSlot .. [=[</label><default>]=] .. (frame:getParent().args.equipmentSlot or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.ammo .. [=[</label><default>]=] .. (frame:getParent().args.ammo or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.damage .. [=[</label><default>]=] .. (frame:getParent().args.damage or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.magSize .. [=[</label><default>]=] .. (frame:getParent().args.magSize or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.rateOfFire .. [=[</label><default>]=] .. (not (frame:getParent().args.rateOfFire == nil or frame:getParent().args.rateOfFire == "") and (frame:getParent().args.rateOfFire .. "/s") or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.reloadTime .. [=[</label><default>]=] .. (not (frame:getParent().args.reloadTime == nil or frame:getParent().args.reloadTime == "") and (frame:getParent().args.reloadTime .. loc.units.sec) or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.damagePerSecond .. [=[</label><default>]=] .. (frame:getParent().args.damagePerSecond or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.range .. [=[</label><default>]=] .. (frame:getParent().args.range or "") .. [=[</default></data>
</group>
</infobox>]=]
-- categories
local categories = ""
if not (frame:getParent().args.nocat ~= nil and frame:getParent().args.nocat == "1") then
-- individual ifs to cover branch differences
if forms.stable == loc.groups.item or forms.experimental == loc.groups.item then
categories = categories .. loc.categories.items
end
if forms.stable == loc.groups.liquid or forms.experimental == loc.groups.liquid then
categories = categories .. loc.categories.liquids .. loc.categories.fluids
end
if forms.stable == loc.groups.gas or forms.experimental == loc.groups.gas then
categories = categories .. loc.categories.gases .. loc.categories.fluids
end
if fuelValues.stable ~= 0 or fuelValues.experimental ~= 0 then
categories = categories .. loc.categories.fuels
end
local radioactiveValues = getBranchValues("radioactive", target.stable, target.experimental)
if radioactiveValues.stable ~= 0 or radioactiveValues.experimental ~= 0 then
categories = categories .. loc.categories.radioactive
end
end
return mw.getCurrentFrame():preprocess(xml) .. categories
end
function p.generateBuildingInfobox(frame)
local targetClassName = frame:getParent().args.className
local target = getObjectFromClassName(targetClassName, buildingsJSON)
if target.stable == nil and target.experimental == nil then
return tostring(mw.html.create("strong"):addClass("error"):wikitext("Building infobox error: invalid target"):allDone())
end
-- image name
local buildingLink, _ = getLinkAndName(targetClassName, target.stable, target.experimental)
-- fuel
local fuelSection = ""
local fuelValues = getBranchValues("burnsFuel", target.stable, target.experimental)
if (fuelValues.stable ~= nil and fuelValues.stable[1] ~= nil) or (fuelValues.experimental ~= nil and fuelValues.experimental[1] ~= nil) then
local fuels = {}
local fuelsOrder = {}
-- if a fuel is burnable in a branch, set its name and energy
for branchName,branch in pairs(getBranchValues("burnsFuel", target.stable, target.experimental)) do
for _,fuel in pairs(branch) do
if fuels[fuel.fuel] == nil then
fuels[fuel.fuel] = {fuel = {}, energy = {}, supplement = {}, byproduct = {}, byproductAmount = {}}
end
local fuelItem = getObjectFromClassName(fuel.fuel, itemsJSON)
fuels[fuel.fuel].fuel[branchName] = fuel.fuel
fuels[fuel.fuel].energy[branchName] = fuelItem[branchName].energy
fuels[fuel.fuel].supplement[branchName] = fuel.supplement
fuels[fuel.fuel].byproduct[branchName] = fuel.byproduct
fuels[fuel.fuel].byproductAmount[branchName] = fuel.byproductAmount
end
end
-- order fuels by their energy
for fuelClassName,_ in pairs(fuels) do
table.insert(fuelsOrder, fuelClassName)
end
table.sort(fuelsOrder, function(a,b) return (fuels[a].energy.stable or fuels[a].energy.experimental or 0) < (fuels[b].energy.stable or fuels[b].energy.experimental or 0) end)
-- generate infobox fuel section
for _,fuelClassName in pairs(fuelsOrder) do
local supplement = fuels[fuelClassName].supplement.stable or fuels[fuelClassName].supplement.experimental
local byproduct = fuels[fuelClassName].byproduct.stable or fuels[fuelClassName].byproduct.experimental
fuelSection = fuelSection .. "<li>'''" .. generateItemLink(fuelClassName, fuels[fuelClassName].fuel.stable, fuels[fuelClassName].fuel.experimental, false) .. "'''"
fuelSection = fuelSection .. (supplement and (" + " .. generateItemLink(supplement, fuels[fuelClassName].supplement.stable, fuels[fuelClassName].supplement.experimental, false)) or "") .. "</li>"
fuelSection = fuelSection .. (byproduct and ("<ul><li>→ " .. formatBranchDiff(fuels[fuelClassName].byproductAmount) .. "× " .. generateItemLink(byproduct, fuels[fuelClassName].byproduct.stable, fuels[fuelClassName].byproduct.experimental, false) .. "</li></ul>") or "")
end
fuelSection = [=[<group collapse="open"><header>]=] .. loc.groups.fuel .. [=[</header>]=] .. infoboxRow("supplementPerMinute", target, loc.units.pmin) .. [=[<data><default><ul>]=] .. fuelSection .. [=[</ul></default></data></group>]=]
end
-- ingredients
local ingredientSection = ""
local recipes = {}
-- get all recipes that produce the target building (should be only one, or two if EA/EX)
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
for _,product in pairs(recipe.products) do
if targetClassName == product.item then
if recipe.stable then
recipes.stable = recipe
end
if recipe.experimental then
recipes.experimental = recipe
end
end
end
end
end
-- if there is only one recipe, show ingredients in a group
if (recipes.stable == recipes.experimental) or (recipes.stable == nil and recipes.experimental ~= nil) or (recipes.stable ~= nil and recipes.experimental == nil) then
recipes.stable = recipes.stable or recipes.experimental
for _,ingredient in pairs(recipes.stable.ingredients) do
local itemLink, itemName = getLinkAndName(ingredient.item, true, true)
ingredientSection = ingredientSection .. "<data><default>'''" .. formatNumber(ingredient.amount) .. " × {{ItemLink|" .. itemLink .. "|" .. itemName .. "}}'''</default></data>"
end
ingredientSection = [=[<group collapse="open"><header>]=] .. loc.groups.ingredients .. [=[</header>]=] .. ingredientSection .. [=[</group>]=]
-- else use a tabber section to show branch recipes completely separately
elseif recipes.stable ~= nil and recipes.stable ~= recipes.experimental then
ingredientSection = "<panel>"
-- ensure stable is always first
for _,branchName in ipairs({"stable", "experimental"}) do
local recipe = recipes[branchName]
if recipe ~= nil then
ingredientSection = ingredientSection .. [=[<section><label>]=] .. loc.branches[branchName] .. [=[</label><group collapse="open"><header>]=] .. loc.groups.ingredients .. [=[</header>]=]
-- list ingredients in individual data rows
for _,ingredient in pairs(recipe.ingredients) do
local itemLink, itemName = getLinkAndName(ingredient.item, true, true)
ingredientSection = ingredientSection .. "<data><default>'''" .. formatNumber(ingredient.amount) .. " × {{ItemLink|" .. itemLink .. "|" .. itemName .. "}}'''</default></data>"
end
end
ingredientSection = ingredientSection .. "</group></section>"
end
ingredientSection = ingredientSection .. "</panel>"
end
-- whether is a vehicle or a building
local isVehicle = getBranchValues("isVehicle", target.stable, target.experimental)
isVehicle = {(isVehicle.stable or isVehicle.experimental) and loc.groups.vehicle or loc.groups.building}
local powerGenerated = formatBranchDiff(getBranchValues("powerGenerated", target.stable, target.experimental))
if powerGenerated ~= "" then
powerGenerated = powerGenerated .. loc.units.mw
end
-- infobox
local xml = [=[<infobox>
<title><default>]=] .. formatBranchDiff(getBranchValues("name", target.stable, target.experimental), true) .. [=[</default></title>
<image><default>]=] .. frame:callParserFunction("#setmainimage", buildingLink .. ".png") .. [=[</default></image>
<data><default><i>]=] .. formatBranchDiff(getBranchValues("description", target.stable, target.experimental)) .. [=[</i></default></data>
]=] .. infoboxRow("unlockedBy", target) .. [=[
]=] .. infoboxRow("className", target) .. [=[
<group collapse="open"><header>]=] .. isVehicle[1] .. [=[</header>
]=] .. (isVehicle[1] == loc.groups.building and infoboxRow("powerUsage", target, loc.units.mw) or "") .. [=[
<data><label>]=] .. (isVehicle[1] == loc.groups.vehicle and loc.labels.fuelBurnRate or loc.labels.powerGenerated) .. [=[</label><default>]=] .. powerGenerated .. [=[</default></data>
<data><label>]=] .. loc.labels.overclockable .. [=[</label><default>]=] .. (not (frame:getParent().args.overclockable == nil or frame:getParent().args.overclockable == "") and (frame:getParent().args.overclockable == "1" and loc.labels.yes or loc.labels.no) or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.inventorySize .. [=[</label><default>]=] .. (frame:getParent().args.inventorySize or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.beltInputs .. [=[</label><default>]=] .. (frame:getParent().args.beltInputs or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.beltOutputs .. [=[</label><default>]=] .. (frame:getParent().args.beltOutputs or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.pipeInputs .. [=[</label><default>]=] .. (frame:getParent().args.pipeInputs or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.pipeOutputs .. [=[</label><default>]=] .. (frame:getParent().args.pipeOutputs or "") .. [=[</default></data>
<data><label><span title="]=] .. loc.tooltips.maxSpeed .. [=[">]=] .. loc.labels.maxSpeed .. [=[</span></label><default>]=] .. (not (frame:getParent().args.maxSpeed == nil or frame:getParent().args.maxSpeed == "") and (frame:getParent().args.maxSpeed .. loc.units.kmh) or "") .. [=[</default></data>
<data><label><span title="]=] .. loc.tooltips.time0_50 .. [=[">]=] .. loc.labels.time0_50 .. [=[</span></label><default>]=] .. (not (frame:getParent().args.time0_50 == nil or frame:getParent().args.time0_50 == "") and (frame:getParent().args.time0_50 .. loc.units.sec) or "") .. [=[</default></data>
</group>
<group collapse="open"><header>]=] .. loc.groups.dimensions .. [=[</header>
<data><label>]=] .. loc.labels.size_width .. [=[</label><default>]=] .. (not (frame:getParent().args.size_width == nil or frame:getParent().args.size_width == "") and (frame:getParent().args.size_width .. loc.units.m) or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.size_length .. [=[</label><default>]=] .. (not (frame:getParent().args.size_length == nil or frame:getParent().args.size_length == "") and (frame:getParent().args.size_length .. loc.units.m) or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.size_height .. [=[</label><default>]=] .. (not (frame:getParent().args.size_height == nil or frame:getParent().args.size_height == "") and (frame:getParent().args.size_height .. loc.units.m) or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.size_area .. [=[</label><default>]=] .. ((tonumber(frame:getParent().args.size_width) and tonumber(frame:getParent().args.size_length)) and (tonumber(frame:getParent().args.size_width)*tonumber(frame:getParent().args.size_length) .. loc.units.m2) or "") .. [=[</default></data>
<data><default>]=] .. (frame:getParent().args.size_note or "") .. [=[</default></data>
</group>]=] .. fuelSection .. ingredientSection .. [=[
</infobox>]=]
-- categories
local categories = ""
if not (frame:getParent().args.nocat ~= nil and frame:getParent().args.nocat == "1") then
if isVehicle[1] == loc.groups.vehicle then
categories = loc.categories.vehicles
else
categories = loc.categories.buildings
end
end
return mw.getCurrentFrame():preprocess(xml) .. categories
end
return p