Module:Data

local data = {}

-- Load modules local iter = require("Module:Functional").iter

local class = require("Module:Class")

local DurationConverter = require("Module:DurationConverter")

local GameUIBuilder = require("Module:GameUIBuilder") local Label = GameUIBuilder.GameUILabel local List = GameUIBuilder.GameUIList local Menu = GameUIBuilder.GameUIMenu local Tabber = GameUIBuilder.GameUITabber local Table = GameUIBuilder.GameUITable

local GameUITemplates = require("Module:GameUITemplates") local EditButton = GameUITemplates.GameUIEditButton local InfoboxDescription = GameUITemplates.GameUIInfoboxDescription local InfoboxImage = GameUITemplates.GameUIInfoboxImage local SidebarInfobox = GameUITemplates.GameUISidebarInfobox

-- Returns the key to use in Template:Colored Text for the rarity with the given name local RARITY_COLORS = { ["Common"] = "Common", ["Uncommon"] = "Uncommon", ["Rare"] = "Rare", ["Epic"] = "Epic", ["Legendary"] = "Legendary", } data.RARITY_COLORS = RARITY_COLORS

-- Colors a piece of text according to rarity function data.colorTextByRarity(text, rarity) return mw.getCurrentFrame:expandTemplate{ title = "Colored Text", args = {text, RARITY_COLORS[rarity]} } end

-- Colors a link according to rarity function data.colorLinkByRarity(text, rarity, ref) return mw.getCurrentFrame:expandTemplate{ title = "Colored Link", args = {text, RARITY_COLORS[rarity], nil, ref} } end

-- Returns an icon for the faction with the given name local FACTIONS = { "Rebel", "VEGA", "VSec", "Iron Star", "Demon Corps", "Xeno Division", "AXIS", "Marauder", "Altairian", "Umbra", "Pharmakon", "Spectre" } data.FACTIONS = FACTIONS local FACTION_ICONS = { ["Rebel"] = "miner_rebellion.png", ["VEGA"] = "vega_mining.png", ["VSec"] = "vega_security.png", ["Iron Star"] = "iron_star.png", ["Demon Corps"] = "demon_corps.png", ["Xeno Division"] = "xeno_division.png", ["AXIS"] = "axis.png", ["Marauder"] = "marauders.png", ["Altairian"] = "heralds.png", ["Umbra"] = "umbra.png", ["Pharmakon"] = "pharmakon.png", ["Spectre"] = "spectre.png" } data.FACTION_ICONS = FACTION_ICONS

-- Returns an icon for the class with the given name local CLASSES = { "Corvette", "Frigate", "Cruiser", "Destroyer", "Battleship", "Cutter", "Specialist", "Carrier", "Flagship", "Dreadnought" } data.CLASSES = CLASSES local CLASS_ICONS = { ["Corvette"] = "Corvette.png", ["Frigate"] = "Frigate.png", ["Cruiser"] = "Cruiser.png", ["Destroyer"] = "Destroyer.png", ["Battleship"] = "Battleship.png", ["Cutter"] = "Cutter.png", ["Specialist"] = "Specialist.png", ["Carrier"] = "Carrier.png", ["Flagship"] = "Flagship.png", ["Dreadnought"] = "Dreadnought.png", } data.CLASS_ICONS = CLASS_ICONS -- Returns an icon for the role with the given name local ROLES = { "Fighter", "Titan", "Ranger" } data.ROLES = ROLES local ROLE_ICONS = { ["Fighter"] = "Fighter.png", ["Titan"] = "Titan.png", ["Ranger"] = "Ranger.png", } data.ROLE_ICONS = ROLE_ICONS

-- Returns an icon for the equipment slot with the given name local SLOT_ICONS = { ["Weapon"] = "WeaponSlots-Stat.png", ["Hangar"] = "HangarSlots-Stat.png", ["Spawner"] = "SpawnerSlots-Stat.png", ["Armor"] = "ArmorSlots-Stat.png", ["Shield"] = "ShieldSlots-Stat.png", ["Ablative Armor"] = "AblativeArmorSlots-Stat.png", ["Screen"] = "ScreenSlots-Stat.png", ["Special"] = "SpecialSlots-Stat.png", ["Operation"] = "OperationSlots-Stat.png", ["Trigger"] = "TriggerSlots-Stat.png", ["Resistor"] = "ResistanceSlots-Stat.png", ["Skin"] = "SkinSlots-Stat.png", } data.SLOT_ICONS = SLOT_ICONS

-- Returns an icon for the item category with the given name local CATEGORY_ICONS = { ["Ship"] = "Ships.png", ["Module"] = "Modules.png", ["Equipment"] = "ModuleRefit.png", ["Fragment"] = "Fragment.png", ["Formation"] = "Formations.png", ["Strongbox"] = "Strongbox.png", ["Pattern"] = "Patterns.png", ["Part"] = "Parts.png", ["Core"] = "Cores.png", ["Armament"] = "Armaments.png", ["Element"] = "Armaments.png", ["Upgrade Credit"] = "UpgradeCredits.png", } data.CATEGORY_ICONS = CATEGORY_ICONS

-- Returns an icon for the parent item category with the given name local PARENT_CATEGORY_ICONS = { ["Ship"] = "ShipLabResearch.png", ["Module"] = "Module.png", } data.PARENT_CATEGORY_ICONS = PARENT_CATEGORY_ICONS

-- key: The value of the 'applies_to' field -- value: The stats for an item, such that all items with any of the stats are affected. local APPLIES_TO_STATS = { ["Energy"] = {"Energy DPS"}, ["Explosive"] = {"Explosive DPS"}, ["Kinetic"] = {"Kinetic DPS"}, ["Alien"] = {"Alien DPS"}, ["Plasma"] = {"Plasma DPS"}, ["Blight"] = {"Blight DPS"}, ["Void"] = {"Void DPS"}, ["Overcharge"] = { "Overcharge Delay", "Overcharge Amount", "Overcharge Maximum", "Overcharge Duration" }, __index = function return {} end } data.APPLIES_TO_STATS = APPLIES_TO_STATS

-- key: The value of the 'applies_to' field -- value: The substrings of item names, such that all items with any of the substrings are affected. local APPLIES_TO_NAME_SUBSTR = { ["Ray"] = {"Ray"}, ["Cannon"] = {"Cannon"}, ["Beam"] = {"Beam"}, ["Missile"] = {"Missile"}, ["Torpedo"] = {"Torpedo"}, ["Driver"] = {"Driver"}, ["Vulcan"] = {"Vulcan"}, ["Squadron"] = {"Squadron", "Drone", "Wing"}, ["Thruster"] = {"Thruster", "Thrusters"}, __index = function return {} end } data.APPLIES_TO_NAME_SUBSTR = APPLIES_TO_NAME_SUBSTR

-- Abstract class, represents an entity in the game local Entity = class("Entity") data.Entity = Entity

-- The Cargo table that contains all of the primary attributes of the entity Entity.static.ATTRIBUTE_TABLE = nil

-- Constructor -- -- Creates a new Entity instance according to the given attribute/value pairs, -- which should correspond to the attributes in `ATTRIBUTE_TABLE`. function Entity:initialize(attr) assert(attr, "`attr` cannot be nil") if type(attr) ~= type({}) then error(string.format("`attr` is not a table, found it to be: %s", attr)) end iter(attr):each(function (k, v) self[k] = v end) end

-- Other methods -- -- Stores the attribute/value pairs as a Cargo record in the given table. -- Also updates each attribute so that they are converted from strings into Lua objects, making them -- consistent with the attributes obtained from querying the record. Sets metafields if they have not been already. function Entity:storeToTable(tbl) local out_query = {} local store = tbl:store(iter(tbl:getFields):map(function (f) return f, self[f] end):tomap, out_query) iter(out_query):each(function (k, v) self[k] = v end) return store end

-- Attempts to invoke a function of the object, passing no extra parameters. -- Returns nil if the function is not found. local function tryInvoke(obj, attr) local fn = obj[attr] if fn == nil or type(fn) ~= "function" then return nil end return fn(obj) end

local function colorAsStatistic(text) return mw.getCurrentFrame:expandTemplate{ title = "Colored Text", args = { text, "Statistic" }, } end -- Returns an infobox showing the entity's information. -- If `general_only` does not evaluate to `false`, then statistical information will be skipped. -- If `no_categories` does not evaluate to `false`, then categories will not be added. function Entity:generateInfobox(general_only, no_categories) -- Do not import at the module level, otherwise circular dependency will occur local Item = require("Module:Item").Item local Research = require("Module:Research").Research local Blueprint = require("Module:Blueprint").Blueprint local Recipe = require("Module:Recipe").Recipe local Statistic = require("Module:Statistic").Statistic local StatsList = require("Module:Statistic").StatsList

-- Get relational information -- Temporarily set _pageName local unknown_fullpagename = false if self._pageName == nil then unknown_fullpagename = true self._pageName = mw.getCurrentFrame:preprocess("") end local stats = tryInvoke(self, "getStatistics") local modifiers = tryInvoke(self, "getModifiers") local abilities = tryInvoke(self, "getAbilities") local contains = tryInvoke(self, "getContains") local materials = tryInvoke(self, "getMaterials") local title = data.colorLinkByRarity(self.name, self.rarity, self.main_page) local edit_url = mw.getCurrentFrame:preprocess(string.format("", self._pageName)) local infobox = SidebarInfobox(title, EditButton(edit_url)):node(InfoboxImage(self.image)) if (self.description) then local label = InfoboxDescription(Statistic:applyColors(self.description)) infobox:node(label) end if (self.tier or self.faction or self.category) then local tabber, list = Tabber, List if (self.tier) then local tier = "Tier " .. self.tier local args = { ["image_wikitext"] = "", }			if no_categories then args.left_wikitext = string.format("%s", tier, tier) else args.left_wikitext = string.format("%s", tier, tier, tier) end list:insertRowAt(args) end if (self.faction) then local faction = self.faction local args = { ["image_wikitext"] = string.format("", FACTION_ICONS[faction]), }			if no_categories then args.left_wikitext = string.format("%s", faction, faction) else args.left_wikitext = string.format("%s", faction, faction, faction) end list:insertRowAt(args) end if (self.category) then if self.category == "Ship" then if (self.ship_role) then local role = self.ship_role local args = { ["image_wikitext"] = string.format("", ROLE_ICONS[role]), }					if no_categories then args.left_wikitext = string.format("%s", role, role) else args.left_wikitext = string.format("%s", role, role, role) end list:insertRowAt(args) end if (self.ship_class) then local class = self.ship_class local args = { ["image_wikitext"] = string.format("", CLASS_ICONS[class]), }					if no_categories then args.left_wikitext = string.format("%s", class, class) else args.left_wikitext = string.format("%s", class, class, class) end list:insertRowAt(args) end if (self.firing_arc_widths or self.firing_arc_offsets) then local firing_arc_widths = self.firing_arc_widths local firing_arc_offsets = self.firing_arc_offsets local num_firing_arcs = 0 if (firing_arc_widths) then num_firing_arcs = #firing_arc_widths end if (firing_arc_offsets) then num_firing_arcs = #firing_arc_offsets end for i = 1, num_firing_arcs do local firing_arc_width = "???" if (firing_arc_widths) then firing_arc_width = firing_arc_widths[i] end local firing_arc_offset = "???" if (firing_arc_offsets) then firing_arc_offset = firing_arc_offsets[i] end local colored_width = colorAsStatistic(firing_arc_width) local colored_offset = colorAsStatistic(firing_arc_offset) local args = { ["image_wikitext"] = "", ["left_wikitext"] = string.format("Firing Arc %d", i), }						if firing_arc_offset == "???" then args.right_wikitext = string.format("%s deg (offset %s deg)", colored_width, colored_offset) elseif firing_arc_offset > 0 then args.right_wikitext = string.format("%s deg (offset %s deg clockwise)", colored_width, colored_offset) elseif firing_arc_offset < 0 then args.right_wikitext = string.format("%s deg (offset %s deg anticlockwise)", colored_width, colored_offset) elseif firing_arc_offset == 0 then args.right_wikitext = string.format("%s deg", colored_width) end list:insertRowAt(args) end end elseif self.category == "Module" then if (self.module_size) then list:insertRowAt{ ["image_wikitext"] = string.format("", PARENT_CATEGORY_ICONS["Module"]), ["left_wikitext"] = self.module_size, }				end elseif self.category == "Equipment" then if (self.equip_parent or self.equip_slot) then local equip_icon = nil if (self.equip_slot) then equip_icon = string.format("", SLOT_ICONS[self.equip_slot]) else equip_icon = string.format("", PARENT_CATEGORY_ICONS[self.equip_parent]) end local equip_content = string.format("%s %s", self.equip_parent or "", self.equip_slot or "") if (self.equip_parent and self.equip_slot) then if no_categories then aequip_content = string.format("%s", equip_content, equip_content) else equip_content = string.format("%s", equip_content, equip_content, equip_content) end end list:insertRowAt{ ["image_wikitext"] = equip_icon, ["left_wikitext"] = equip_content, }				end else list:insertRowAt{ ["image_wikitext"] = string.format("", CATEGORY_ICONS[self.category]), ["left_wikitext"] = self.category, }			end end if list:getNumRows > 0 then tabber:insertTabAt("General", list) infobox:node(tabber) end end if (self.prereq_items or self.prereq_researches or self.prereq_blueprints or (not self.designation and self.is_auto)) then local tabber, list = Tabber, List for _, v in ipairs(self.prereq_items or {}) do			list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Requires %s", v, v:gsub("^Item:", "")), }		end for _, v in ipairs(self.prereq_researches or {}) do			list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Research %s", v, v:gsub("^Research:", "")), }		end for _, v in ipairs(self.prereq_blueprints or {}) do			list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Complete %s", v, v:gsub("^Blueprint:", "")), }		end if (self.is_auto) then list:insertRowAt{ ["image_wikitext"] = tostring(mw.html.create("span"):css("color", "#5195A2"):wikitext(mw.ustring.char(0x2714))), ["left_wikitext"] = tostring(mw.html.create("span"):css("color", "#5195A2"):wikitext("Automatically unlocked upon player creation")), }		end if list:getNumRows > 0 then tabber:insertTabAt("Prerequisites", list) infobox:node(tabber) end end if (self.pieces) then local tabber, list = Tabber, List list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = "Pieces to Complete", ["right_wikitext"] = colorAsStatistic(string.format("%d", self.pieces)), }		if list:getNumRows > 0 then tabber:insertTabAt("Blueprint", list) infobox:node(tabber) end end if not (general_only) then if (self.xp) then local tabber, list = Tabber, List StatsList:appendStatisticRowToGameUIList(list, "Statistic:Outpost XP", self.xp) if list:getNumRows > 0 then tabber:insertTabAt("Contributes", list) infobox:node(tabber) end end

if (self.weapon_slot_ids or self.hangar_slot_ids or self.spawner_slot_ids or self.armor_slot_ids or self.shield_slot_ids			or self.ablative_armor_slot_ids or self.screen_slot_ids or self.operation_slot_ids or self.skin_slot_ids			or self.trigger_slot_ids or self.resistance_slot_ids) then local tabber, list = Tabber, List local slot_counts = {} if (self.weapon_slot_ids) then slot_counts["Statistic:Weapon Slots"] = iter(self.weapon_slot_ids):length end if (self.hangar_slot_ids) then slot_counts["Statistic:Hangar Slots"] = iter(self.hangar_slot_ids):length end if (self.spawner_slot_ids) then slot_counts["Statistic:Spawner Slots"] = iter(self.spawner_slot_ids):length end if (self.armor_slot_ids) then slot_counts["Statistic:Armor Slots"] = iter(self.armor_slot_ids):length end if (self.shield_slot_ids) then slot_counts["Statistic:Shield Slots"] = iter(self.shield_slot_ids):length end if (self.ablative_armor_slot_ids) then slot_counts["Statistic:Ablative Armor Slots"] = iter(self.ablative_armor_slot_ids):length end if (self.screen_slot_ids) then slot_counts["Statistic:Screen Slots"] = iter(self.screen_slot_ids):length end if (self.operation_slot_ids) then slot_counts["Statistic:Operation Slots"] = iter(self.operation_slot_ids):length end if (self.skin_slot_ids) then slot_counts["Statistic:Skin Slots"] = iter(self.skin_slot_ids):length end if (self.trigger_slot_ids) then slot_counts["Statistic:Trigger Slots"] = iter(self.trigger_slot_ids):length end if (self.resistance_slot_ids) then slot_counts["Statistic:Resistance Slots"] = iter(self.resistance_slot_ids):length end iter(slot_counts):each(function (k, v) if v > 0 then StatsList:appendStatisticRowToGameUIList(list, k, v) end end) if list:getNumRows > 0 then tabber:insertTabAt("Slot Configuration", list) infobox:node(tabber) end end if (stats or modifiers or abilities) then local tabber = Tabber if stats and not iter(stats:get):is_null then local list = stats:asGameUIList if list:getNumRows > 0 then tabber:insertTabAt("Stats", list) end end if modifiers and not iter(modifiers:get):is_null then local list = modifiers:asGameUIList if list:getNumRows > 0 then tabber:insertTabAt("Modifiers", list) end end if abilities and not iter(abilities:get):is_null then local list = abilities:asGameUIList if list:getNumRows > 0 then tabber:insertTabAt("Abilities", list) end end infobox:node(tabber) end if (contains) then for _, bin in ipairs(contains) do				local bin_title = "" if bin.bin_type == '?' then bin_title = "May contain one of" elseif bin.bin_type == '*' then bin_title = "May contain one or more of" elseif bin.bin_type == '1' then bin_title = "Contains one of" elseif bin.bin_type == '+' then bin_title = "Contains one or more of" end local tabber, list = Tabber, List local bin_items = mw.text.split(bin.items, "%s*;%s*") local bin_min_amounts = mw.text.split(bin.min_amounts, "%s*;%s*") local bin_max_amounts = mw.text.split(bin.max_amounts, "%s*;%s*") for i = 1, #bin_items do					local item = Item:fromPageName(bin_items[i]) local min_amount = bin_min_amounts[i] local max_amount = bin_max_amounts[i] list:insertRowAt{ ["image_wikitext"] = string.format("", item.image), ["left_wikitext"] = string.format("%s x%d-%d", item.name, min_amount, max_amount), }				end if list:getNumRows > 0 then tabber:insertTabAt(bin_title, list) infobox:node(tabber) end end end end local classes_with_prereqs = {Item, Research, Recipe} local function getPrereqItems(cls) return cls.ATTRIBUTE_TABLE:query{where = string.format("prereq_items HOLDS '%s'", self._pageName)} end local function getPrereqResearches(cls) return cls.ATTRIBUTE_TABLE:query{where = string.format("prereq_researches HOLDS '%s'", self._pageName)} end local function getPrereqRecipes(cls) return cls.ATTRIBUTE_TABLE:query{where = string.format("prereq_blueprints HOLDS '%s'", self._pageName)} end local unlocks_items = iter(classes_with_prereqs):map(getPrereqItems):flat(1):map(Item):totable local unlocks_researches = iter(classes_with_prereqs):map(getPrereqResearches):flat(1):map(Research):totable local unlocks_blueprints = iter(classes_with_prereqs):map(getPrereqRecipes):flat(1):map(Blueprint):totable if (unlocks_items or unlocks_researches or unlocks_blueprints) then local tabber, list = Tabber, List for _, v in ipairs(unlocks_items or {}) do			list:insertRowAt{ ["image_wikitext"] = string.format("", v.image), ["left_wikitext"] = string.format("[Item] %s", v._pageName, v._pageTitle), }		end for _, v in ipairs(unlocks_researches or {}) do			list:insertRowAt{ ["image_wikitext"] = string.format("", v.image), ["left_wikitext"] = string.format("[Research] %s", v._pageName, v._pageTitle), }		end for _, v in ipairs(unlocks_blueprints or {}) do			list:insertRowAt{ ["image_wikitext"] = string.format("", v.image), ["left_wikitext"] = string.format("[Blueprint] %s", v._pageName, v._pageTitle), }		end if list:getNumRows > 0 then tabber:insertTabAt("Unlocks", list) infobox:node(tabber) end end if (upgrades) then local tabber, list = Tabber, List local upgrades_from = upgrades local upgrades_to, _ = self._pageTitle:gsub(" Upgrade Credit%s*$", "") list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Upgrade %s to %s", upgrades_from, upgrades_from:gsub("^Item:", ""), upgrades_to, upgrades_to:gsub("^Item:", "")), }		if list:getNumRows > 0 then tabber:insertTabAt("Usage", list) infobox:node(tabber) end end

if (self.designation) then local tabber, list = Tabber, List if (self.designation == "Arms Lab") then list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = "Arms Lab", }		elseif (self.designation == "Ship Lab") then list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = "Ship Lab", }		elseif (self.designation == "Tech Lab") then list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = "Tech Lab", }		end if (self.is_auto) then list:insertRowAt{ ["image_wikitext"] = tostring(mw.html.create("span"):css("color", "#5195A2"):wikitext(mw.ustring.char(0x2714))), ["left_wikitext"] = tostring(mw.html.create("span"):css("color", "#5195A2"):wikitext("Automatically completed upon player creation")), }		end if (self.research_helium_3 or self.research_mineral_ore or self.research_antimatter or self.research_seconds) then StatsList:appendStatisticRowToGameUIList(list, "Statistic:Research Helium-3", self.research_helium_3) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Research Mineral Ore", self.research_mineral_ore) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Research Antimatter", self.research_antimatter) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Research Time", DurationConverter.formatInGameTime(self.research_seconds)) end if list:getNumRows > 0 then tabber:insertTabAt("Research", list) infobox:node(tabber) end end local tabber, list = Tabber, List if (self.equip_wl_tiers or self.equip_wl_roles or self.equip_wl_classes or self.equip_wl_factions or self.equip_bl_tiers or self.equip_bl_roles or self.equip_bl_classes or self.equip_bl_factions		or self.build_helium_3 or self.build_mineral_ore or self.build_antimatter or self.build_seconds) then local function addCompatibleRow(list, v)			list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Compatible with %s", v), }		end for _, v in ipairs(self.equip_wl_tiers or {}) do addCompatibleRow(list, v) end for _, v in ipairs(self.equip_wl_roles or {}) do addCompatibleRow(list, v) end for _, v in ipairs(self.equip_wl_classes or {}) do addCompatibleRow(list, v) end for _, v in ipairs(self.equip_wl_factions or {}) do addCompatibleRow(list, v) end

local function addIncompatibleRow(list, v)			list:insertRowAt{ ["image_wikitext"] = "", ["left_wikitext"] = string.format("Inompatible with %s", v), }		end for _, v in ipairs(self.equip_bl_tiers or {}) do addIncompatibleRow(list, v) end for _, v in ipairs(self.equip_bl_roles or {}) do addIncompatibleRow(list, v) end for _, v in ipairs(self.equip_bl_classes or {}) do addIncompatibleRow(list, v) end for _, v in ipairs(self.equip_bl_factions or {}) do addIncompatibleRow(list, v) end end if (self.build_helium_3 or self.build_mineral_ore or self.build_antimatter or self.build_seconds) then StatsList:appendStatisticRowToGameUIList(list, "Statistic:Build Helium-3", self.build_helium_3 or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Build Mineral Ore", self.build_mineral_ore or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Build Antimatter", self.build_antimatter or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Build Time", DurationConverter.formatInGameTime(self.build_seconds or 0)) end if list:getNumRows > 0 then tabber:insertTabAt("Build", list) infobox:node(tabber) end if (materials or self.craft_helium_3 or self.craft_mineral_ore or self.craft_antimatter or self.craft_seconds) then local tabber, list = Tabber, List for _, v in ipairs(materials or {}) do			local item = Item:fromPageName(v.item) list:insertRowAt{ ["image_wikitext"] = string.format("", item.image), ["left_wikitext"] = string.format("%s", item._pageName, v.item._pageTitle), ["right_wikitext"] = mw.getCurrentFrame:expandTemplate{ title = "Colored Text", args = { colorStatText("x" .. v.amount), "Statistic" } } }		end if (self.craft_helium_3 or self.craft_mineral_ore or self.craft_antimatter) then StatsList:appendStatisticRowToGameUIList(list, "Statistic:Craft Helium-3", self.craft_helium_3 or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Craft Mineral Ore", self.craft_mineral_ore or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Craft Antimatter", self.craft_antimatter or 0) end StatsList:appendStatisticRowToGameUIList(list, "Statistic:Craft Time", DurationConverter.formatInGameTime(self.craft_seconds or 0)) if list:getNumRows > 0 then tabber:insertTabAt("Crafting", list) infobox:node(tabber) end end if (self.upgrade_helium_3 or self.upgrade_mineral_ore or self.upgrade_antimatter or self.upgrade_seconds) then local tabber, list = Tabber, List StatsList:appendStatisticRowToGameUIList(list, "Statistic:Upgrade Helium-3", self.upgrade_helium_3 or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Upgrade Mineral Ore", self.upgrade_mineral_ore or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Upgrade Antimatter", self.upgrade_antimatter or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Upgrade Time", DurationConverter.formatInGameTime(self.upgrade_seconds or 0)) tabber:insertTabAt("Upgrade", list) infobox:node(tabber) end if (self.repair_helium_3 or self.repair_mineral_ore or self.repair_antimatter or self.repair_seconds) then local tabber, list = Tabber, List StatsList:appendStatisticRowToGameUIList(list, "Statistic:Repair Helium-3", self.repair_helium_3 or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Repair Mineral Ore", self.repair_mineral_ore or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Repair Antimatter", self.repair_antimatter or 0) StatsList:appendStatisticRowToGameUIList(list, "Statistic:Repair Time", DurationConverter.formatInGameTime(self.repair_seconds or 0)) if list:getNumRows > 0 then tabber:insertTabAt("Repair", list) infobox:node(tabber) end end return infobox:as_mw_html end

-- Module call from Template:Entity Lookup function data.generateLookupResultsMenu( frame ) local args = require("Module:Args").getCleanArgs return data.generateLookupResultsMenu_Lua(args) end

function data.generateLookupResultsMenu_Lua(args) assert(args.format == nil, "The argument `format` is not allowed") local tables = assert(args.tables, "Missing argument `tables`") args.tables = nil local info_label_cls = { "game-ui-info-label" } local info_label_css = { ["position"] = "relative", ["left"] = "50%", ["transform"] = "translate(-50%, 0)", }	local fields = args.fields args.fields = nil if fields == nil then return Label(info_label_cls, info_label_css, "No fields were queried."):as_mw_html end local results = mw.ext.cargo.query(tables, fields, args) if #results == 0 then return Label(info_label_cls, info_label_css, "No results were found."):as_mw_html end local field_names = iter(iter(results):flat(-1):tomap):keys:totable local aliases = {} if args.aliases then aliases = mw.text.split(args.aliases, ',') end if #aliases ~= #field_names then error(string.format("Expected %d elements in `aliases`, but found %d", #field_names, #aliases)) end aliases = iter(aliases):map(mw.text.trim):totable local row_headers = {} local unindexed_results = {} for _, v in ipairs(results) do		-- Pop first field from v		local k = v[aliases[1]] v[aliases[1]] = nil -- Avoid overwriting columns while unindexed_results[k] ~= nil do k = k .. " " end table.insert(row_headers, k)		unindexed_results[k] = v	end local tbl = Table(nil, nil, aliases[1], unindexed_results) local row_priorities = iter(row_headers):enumerate:map(function (i, e) return e, i end):tomap tbl:sortRows(function (a, b) return (row_priorities[a] or 9999) < (row_priorities[b] or 9999) end) local col_priorities = iter(aliases):enumerate:map(function (i, e) return e, i end):tomap tbl:sortCols(function (a, b) return (col_priorities[a] or 9999) < (col_priorities[b] or 9999) end) return tbl:as_mw_html end

return data