模組:滿意RenderInfobox

可在模組:滿意RenderInfobox/doc建立此模組的說明文件

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<br/>usage]]",
    powerGenerated = "[[Power|Power<br/>generated]]",
    fuelBurnRate = "Fuel burn rate",
    supplementPerMinute = "Supplement<br/>input rate",
    overclockable = "[[Clock speed|Overclock&shy;able]]",
    somersloopSlots = "[[Production amplifier|Somersloop<br/>slots]]",
    inventorySize = "Inventory size",
    inputBufferSize = "Input<br/>buffer&nbsp;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)
    
    -- somersloop slots
    local somersloopValues = getBranchValues("somersloopSlots", 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 (" +&nbsp;" .. generateItemLink(supplement, fuels[fuelClassName].supplement.stable, fuels[fuelClassName].supplement.experimental, false)) or "") .. "</li>"
            fuelSection = fuelSection .. (byproduct and ("<ul><li>→&nbsp;" .. 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) .. " &times; {{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) .. " &times; {{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>
]=] .. ((somersloopValues.stable ~= 0 or somersloopValues.experimental ~= 0) and infoboxRow("somersloopSlots", target) or "") .. [=[
<data><label>]=] .. loc.labels.inventorySize .. [=[</label><default>]=] .. (frame:getParent().args.inventorySize or "") .. [=[</default></data>
<data><label>]=] .. loc.labels.inputBufferSize .. [=[</label><default>]=] .. (frame:getParent().args.inputBufferSize 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