Module:Sandbox/Illviljan/Area

-- SMW powered area module

-- -- TODO -- -- invalid tags -> utl? -- spawn_weight* values -- spawnchacne values -- -- i18n for properties

-- -- Imports --

local m_util = require('Module:Util') local getArgs = require('Module:Arguments').getArgs local m_game = require('Module:Game') local f_infocard = require('Module:Infocard')._main

local cargo = mw.ext.cargo

-- -- Localization --

-- Strings local i18n = { images = { waypoint_no = '', waypoint_yes = '', waypoint_town = '', loading_screen = 'File:%s loading screen.png', loading_screen_infobox = '', screenshot = 'File:%s area screenshot.%s', screenshot_infobox = '', },

args = { main_page = 'main_page', id = 'id', name = 'name', act = 'act', area_level = 'level', level_restriction_max = 'level_restriction_max', area_type_tags = 'area_type_tags', tags = 'tags', loading_screen = 'loading_screen', connection_ids = 'connection_ids', parent_area_id = 'parent_area_id', modifier_ids = 'modifier_ids', boss_monster_ids = 'boss_monster_ids', monster_ids = 'monster_ids', entry_text = 'entry_text', entry_npc = 'entry_npc', flavour_text = 'flavour_text', screenshot_ext = 'screenshot_ext', vaal_area_spawn_chance = 'vaal_area_spawn_chance', vaal_area_ids = 'vaal_area_ids', strongbox_spawn_chance = 'strongbox_spawn_chance', strongbox_max_count = 'strongbox_max', strongbox_rarity_weight = 'strongbox_rarity_weight', is_map_area = 'is_map_area', is_unique_map_area = 'is_unique_map_area', is_town_area = 'is_town_area', is_hideout_area = 'is_hideout_area', is_vaal_area = 'is_vaal_area', is_master_daily_area = 'is_master_daily_area', is_labyrinth_area = 'is_labyrinth_area', is_labyrinth_airlock_area = 'is_labyrinth_airlock_area', is_labyrinth_boss_area = 'is_labyrinth_boss_area', has_waypoint = 'has_waypoint', },   errors = { invalid_tag = '%s is not a valid tag', main_page_is_invalid = 'main_page argument got "%s" which is not a valid wiki page', main_page_does_not_exist = 'main_page argument requires the specified page "%s" to exist in the main wiki namespace', },   tooltips = { -- boolean tooltips. Use singular form here, categories makes these plural. is_map_area = 'Map area', is_unique_map_area = 'Unique Map area', is_town_area = 'Town area', is_hideout_area = 'Hideout area', is_vaal_area = 'Vaal area', is_master_daily_area = 'Master daily spawn area', is_labyrinth_area = 'Labyrinth area', is_labyrinth_airlock_area = 'Labyrinth airlock area', is_labyrinth_boss_area = 'Labyrinth boss area', area = 'area', --       entry_message = '%s: %s', },   headers = { id = 'Id', act = 'Act', area_level = 'Area level', level_restriction_max = m_util.html.abbr('Max level', 'Characters above this level can not enter this zone.'), area_type_tags = 'Area type tags', tags = 'Tags', parent_area = m_util.html.abbr('Parent Town', 'Portals will lead to the parent town'), connections = 'Connections', -- monsters -- boss monsters vaal_areas = 'Vaal Areas', }, }

function m_util.args.spawn_weight_list (argtbl, args) -- Parses a weighted pair of lists and sets properties --   -- argtbl: argument table to work with -- args: -- output_argument - if set, set arguments to this value -- frame - if set, automtically set subobjects -- input_argument - input prefix for parsing the arguments from the argtbl -- weight_property - name of the weight property on the subobject -- subobject_name - name of the subobject args = args or {} args.input_argument = 'spawn_weight' args.output_argument = 'spawn_weights' args.weight_property = 'Has spawn weight' args.subobject_name = 'spawn weight' args.cargo_table = 'spawn_weights'

local i = 0 local id = nil local value = nil if args.output_argument then argtbl[args.output_argument] = {} end

repeat i = i + 1 id = { tag = string.format('%s%s_tag', args.input_argument, i), value = string.format('%s%s_value', args.input_argument, i), }       value = { tag = argtbl[id.tag], value = argtbl[id.value], }       if value.tag ~= nil and value.value ~= nil then if args.output_argument then argtbl[args.output_argument][i] = value end if args.frame then if args.cargo_table then m_util.cargo.store(args.frame, {                       _table = args.cargo_table,                        ordinal = i,                        tag = value.tag,                        weight = m_util.cast.number(value.value, {min=0}),                    }) end end elseif not (value.tag == nil and value.value == nil) then error(string.format(i18n.errors.invalid_weight, id.tag, id.value)) end until value.tag == nil end

-- -- Constats --

local c = {} -- TODO: test c.max_area_query = 8

-- -- Utility & helper functions --

local factory = {} function factory.arg_list(k, args) return function (tpl_args, frame) if tpl_args[k] ~= nil then tpl_args[k] = m_util.string.split(tpl_args[k], ', ') end end end

function factory.display_value(k, args) return function(tpl_args, frame) return tpl_args[k] end end

local util = {} util.display = {} function util.display.multiple_areas(tpl_args, frame, area_ids) local out = {} for _, area_id in ipairs(area_ids) do       out[#out+1] = util.display.single_area(tpl_args, frame, area_id) end return table.concat(out, ' ') end

function util.display.single_area(tpl_args, frame, area_id) if tpl_args.areas[area_id] then if tpl_args.areas[area_id]['areas.main_page'] ~= '' then return string.format('%s', tpl_args.areas[area_id]['areas.main_page'], tpl_args.areas[area_id]['areas.name']) else return string.format('%s (%s)', tpl_args.areas[area_id]['areas.name'], tpl_args.areas[area_id]['areas._pageName'], area_id) end else return area_id end end

-- -- Argument & display mapping --

local argument_map = { table = 'areas', --   -- User supplied arguments --    fields = { main_page = { field = 'main_page', type = 'Page', func = function(tpl_args, frame) local page = tpl_args.main_page if page ~= nil then page = mw.title.new(tpl_args.main_page) if page == nil then error(string.format(i18n.errors.main_page_is_invalid, tpl_args.main_page)) elseif not page.exists then error(string.format(i18n.errors.main_page_does_not_exist, tpl_args.main_page)) else -- dont need the title object anymore --tpl_args.main_page = page end end end },       --        -- Can be populated by PyPoE --       id = { field = 'id', type = 'String', func = nil, },       name = { field = 'name', type = 'String', func = nil, },       act = { field = 'act', type = 'Integer', func = m_util.cast.factory.number(i18n.args.act, {key_out='act'}), },       area_level = { field = 'area_level', type = 'Integer', func = m_util.cast.factory.number(i18n.args.area_level, {key_out='area_level'}), },       level_restriction_max = { field = 'level_restriction_max', type = 'Integer', func = m_util.cast.factory.number(i18n.args.level_restriction_max, {key_out='level_restriction_max'}), default = 100, },       area_type_tags = { field = 'area_type_tags', type = 'List of String', func = m_util.cast.factory.assoc_table(i18n.args.area_type_tags, {               tbl = m_game.constants.tags,                errmsg = i18n.errors.invalid_tag,                key_out = 'area_type_tags',            }), },       tags = { field = 'tags', type = 'List of String', func = m_util.cast.factory.assoc_table(i18n.args.tags, {               tbl = m_game.constants.tags,                errmsg = i18n.errors.invalid_tag,                key_out = 'tags',            }), },       loading_screen = { field = 'loading_screen', type = 'Page', func = function (tpl_args, frame) local loading_id = tpl_args[i18n.args.loading_screen] if loading_id ~= nil then tpl_args.loading_screen = string.format(i18n.images.loading_screen, loading_id) tpl_args.loading_screen_infobox = string.format(i18n.images.loading_screen_infobox, loading_id) end end, },       connection_ids = { field = 'connection_ids', type = 'List of String', func = factory.arg_list(i18n.args.connection_ids, {key_out='connection_ids'}), default = {}, },       parent_area_id = { field = 'parent_area_id', type = 'String', },       modifier_ids = { field = 'modifier_ids', type = 'List of String', func = function(tpl_args, frame) factory.arg_list(i18n.args.modifier_ids, {key_out='modifier_ids'})(tpl_args, frame) if tpl_args.modifier_ids == nil then return end local query_ids = {} for i, mod_id in ipairs(tpl_args.modifier_ids) do                   query_ids[#query_ids+1] = string.format('mods.id="%s"', mod_id) end local results = cargo.query(                   'mods',                    'mods.id, mods.stat_text',                    {                        where=table.concat(query_ids, ' OR '),                    }                ) local text = {} for page, row in pairs(results) do                   if row['mods.stat_text'] ~= '' then text[#text+1] = row['mods.stat_text'] end end tpl_args.stat_text = table.concat(text, ' ') end, default = {}, },       monster_ids = { field = 'monster_ids', type = 'List of String', func = factory.arg_list(i18n.args.monster_ids, {key_out='monster_ids'}), default = {}, },       boss_monster_ids = { field = 'boss_monster_ids', type = 'List of String', func = factory.arg_list(i18n.args.boss_monster_ids, {key_out='boss_monster_ids'}), default = {}, },       entry_text = { field = 'entry_text', type = 'Text', },       entry_npc = { field = 'entry_npc', type = 'String', },       flavour_text = { field = 'flavour_text', type = 'Text', },       screenshot_ext = { func = nil, default = 'jpg', },       screenshot = { field = 'screenshot', type = 'Page', func = function(tpl_args, frame) if tpl_args.name ~= nil then local name = tpl_args.screenshot or tpl_args.main_page or tpl_args.name tpl_args.screenshot = string.format(i18n.images.screenshot, name, tpl_args.screenshot_ext) tpl_args.screenshot_infobox = string.format(i18n.images.screenshot_infobox, name, tpl_args.screenshot_ext) end end, },       --        -- Spawn chances --       vaal_area_ids = { field = 'vaal_area_ids', type = 'List of String', func = factory.arg_list(i18n.args.vaal_area_ids, {key_out='vaal_area_ids'}), default = {}, },       vaal_area_spawn_chance = { field = 'vaal_area_spawn_chance', type = 'Integer', func = m_util.cast.factory.number(i18n.args.vaal_area_spawn_chance, {key_out='vaal_area_spawn_chance'}), default = 0, },       strongbox_spawn_chance = { field = 'strongbox_spawn_chance', type = 'Integer', func = m_util.cast.factory.number(i18n.args.strongbox_spawn_chance, {key_out='strongbox_spawn_chance'}), default = 0, },       strongbox_max_count = { field = 'strongbox_max_count', type = 'Integer', func = m_util.cast.factory.number(i18n.args.strongbox_max_count, {key_out='strongbox_max_count'}), default = 0, },       -- fields are handled for this below strongbox_rarity_weight = { func = function (tpl_args, frame) local weights = m_util.string.split(tpl_args[i18n.args.strongbox_rarity_weight] or '', ', ') tpl_args.strongbox_rarity_weight = {} for index, data in ipairs(m_game.constants.item.rarity) do                   local value = tonumber(weights[index]) or 0 tpl_args.strongbox_rarity_weight[data.long_lower] = value tpl_args._properties[string.format('strongbox_weight_%s', data.long_lower)] = value end end, },       --        -- Area flags --       is_map_area = { field = 'is_map_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_map_area, {key_out='is_map_area'}), default = false, },       is_unique_map_area = { field = 'is_unique_map_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_unique_map_area, {key_out='is_unique_map_area'}), default = false, },       is_town_area = { field = 'is_town_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_town_area, {key_out='is_town_area'}), default = false, },       is_hideout_area = { field = 'is_hideout_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_hideout_area, {key_out='is_hideout_area'}), default = false, },       is_vaal_area = { field = 'is_vaal_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_vaal_area, {key_out='is_vaal_area'}), default = false, },       is_master_daily_area = { field = 'is_is_master_daily_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_master_daily_area, {key_out='is_master_daily_area'}), default = false, },       is_labyrinth_area = { field = 'is_labyrinth_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_labyrinth_area, {key_out='is_labyrinth_area'}), default = false, },       is_labyrinth_airlock_area = { field = 'is_labyrinth_airlock_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_labyrinth_airlock_area, {key_out='is_labyrinth_airlock_area'}), default = false, },       is_labyrinth_boss_area = { field = 'is_labyrinth_boss_area', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.is_labyrinth_boss_area, {key_out='is_labyrinth_boss_area'}), default = false, },       has_waypoint = { field = 'has_waypoint', type = 'Boolean', func = m_util.cast.factory.boolean(i18n.args.has_waypoint, {key_out='has_waypoint'}), default = false, },       --        -- Handled elsewhere in the old --       release_version = { field = 'release_version', type = 'String' },       removal_version = { field = 'removal_version', type = 'String', },       mainpage_categories = { field = 'mainpage_categories', type = 'List of String', },       infobox_html = { field = 'infobox_html', type = 'Text', },       strongbox_weight_normal = { field = 'strongbox_weight_normal', type = 'Integer', },       strongbox_weight_magic = { field = 'strongbox_weight_magic', type = 'Integer', },       strongbox_weight_rare = { field = 'strongbox_weight_rare', type = 'Integer', },       strongbox_weight_unique = { field = 'strongbox_weight_unique', type = 'Integer', },       stat_text = { field = 'stat_text', type = 'Text', },       --        -- Not argument to the template, but still parsing arguments --       areas = { func = function(tpl_args, frame) local query_ids = {} for _, arg in ipairs({'parent_area_id', 'connection_ids', 'vaal_area_ids'}) do                    if type(tpl_args[arg]) == 'table' then for _, tbl_id in ipairs(tpl_args[arg]) do                           query_ids[tbl_id] = {} end elseif tpl_args[arg] then query_ids[tpl_args[arg]] = {} end end local query_ids_trimmed = {} for k, _ in pairs(query_ids) do                   if type(k) ~= 'number' then query_ids_trimmed[#query_ids_trimmed+1] = string.format('areas.id="%s"', k)                   end end if #query_ids_trimmed == 0 then tpl_args.areas = {} else local result = cargo.query(                       'areas',                        'areas._pageName, areas.id, areas.name, areas.main_page',                        {                            where=table.concat(query_ids_trimmed, ' OR '),                        }                    ) tpl_args.areas = {} for _, row in ipairs(result) do                       tpl_args.areas[row['areas.id']] = row end end -- TODO: Error/Warning for missing areas? end, },   }, }

local argument_order = { 'main_page', 'id', 'name', 'act', 'area_level', 'level_restriction_max', 'area_type_tags', 'tags', 'loading_screen', 'connection_ids', 'parent_area_id', 'modifier_ids', 'boss_monster_ids', 'monster_ids', 'entry_text', 'entry_npc', 'flavour_text', 'screenshot_ext', 'screenshot', 'vaal_area_spawn_chance', 'vaal_area_ids', 'strongbox_spawn_chance', 'strongbox_max_count', 'strongbox_rarity_weight', 'is_map_area', 'is_unique_map_area', 'is_town_area', 'is_hideout_area', 'is_vaal_area', 'is_master_daily_area', 'is_labyrinth_area', 'is_labyrinth_airlock_area', 'is_labyrinth_boss_area', 'has_waypoint', -- parsed by m_util.args.version: -- 'release_version', -- 'removal_version', -- Non argument, but passed to the script 'areas', }

local display = {} display.area_type = { 'is_map_area', 'is_unique_map_area', 'is_town_area', 'is_hideout_area', 'is_vaal_area', 'is_master_daily_area', 'is_labyrinth_area', 'is_labyrinth_airlock_area', 'is_labyrinth_boss_area', }

display.table_map = { {       args = { id = { },       },        header = i18n.headers.id, func = function(tpl_args, frame) return string.format('%s', mw.title.getCurrentTitle.fullText, tpl_args.id) end, },   {        args = { act = { },       },        header = i18n.headers.act, func = factory.display_value('act'), },    {        args = { area_level = { },       },        header = i18n.headers.area_level, func = factory.display_value('area_level'), },   {        args = { level_restriction_max = { hide = 100, },       },        header = i18n.headers.level_restriction_max, func = factory.display_value('level_restriction_max'), },   {        args = { area_type_tags = { },       },        header = i18n.headers.area_type_tags, func = function(tpl_args, frame) return table.concat(tpl_args.area_type_tags, ', ') end, },   {        args = { tags = { },       },        header = i18n.headers.tags, func = function(tpl_args, frame) return table.concat(tpl_args.tags, ', ') end, },   {        args = { entry_text = {}, entry_npc = {}, },       header = i18n.headers.entry_messsage, func = function(tpl_args, frame) return m_util.html.poe_color('quest', -- Any other alternatives for spoken text?                string.format(i18n.tooltips.entry_message, tpl_args.entry_npc, tpl_args.entry_text)             ) end, },   {        args = { parent_area_ids = {}, },       header = i18n.headers.parent_area, func = function(tpl_args, frame) return util.display.single_area(tpl_args, frame, tpl_args.parent_area) end, },   {        args = { connection_ids = {}, },       header = i18n.headers.connections, func = function(tpl_args, frame) return util.display.multiple_areas(tpl_args, frame, tpl_args.connection_ids) end, },   {        args = { vaal_area_ids = {}, },       header = i18n.headers.vaal_areas, func = function(tpl_args, frame) return util.display.multiple_areas(tpl_args, frame, tpl_args.vaal_area_ids) end, }, }

display.list_map = { {       args = { flavour_text = {}, },       func = function(tpl_args, frame) return m_util.html.poe_color('flavour', tpl_args.flavour_text) end, },   {        args = { loading_screen_infobox = {}, },       func = factory.display_value('loading_screen_infobox'), },   {        args = { screenshot_infobox = {}, },       func = factory.display_value('screenshot_infobox'), },   {        args = { stat_text = {}, },       func = function(tpl_args, frame) return m_util.html.poe_color('mod', tpl_args.stat_text) end, }, }

-- -- display functions --

local d = {}

function d.intro_text(tpl_args, frame) --   Display an introductory text about the area. local out = {} if mw.ustring.find(tpl_args['id'], '_') then out[#out+1] = frame:expandTemplate{ title='Incorrect title', args = {title=tpl_args['id']} }   end if tpl_args['name'] then out[#out+1] = string.format(           "%s is the internal id for the %s area. ",             tpl_args['id'],             tpl_args['main_page'] or tostring(mw.title.getCurrentTitle),             tpl_args['name']        ) else out[#out+1] = string.format(           "%s is the internal id of an unnamed area. ",            tpl_args['id']        ) end

local connected_areas = {} for _, arg in ipairs({'connection_ids', 'vaal_area_ids'}) do         if tpl_args[arg] then for _, id in ipairs(tpl_args[arg]) do               if tpl_args.areas[id] then connected_areas[#connected_areas+1] = string.format(                       '%s (%s)',                         tostring(tpl_args.areas[id]['areas._pageName']),                         id,                         tostring(tpl_args.areas[id]['areas.name'])                    ) end end end end if #connected_areas > 0 then out[#out+1] = string.format(           'It is connected to the following areas:%s',             table.concat(connected_areas)        ) end return table.concat(out) end

function d._check_args(tpl_args, frame, data) local continue = true if data.args ~= nil then for key, key_data in pairs(data.args) do           if tpl_args[key] == nil or (type(tpl_args[key]) == 'table' and #tpl_args[key] == 0) then continue = false break elseif type(key_data.hide) == 'table' then local br = false for _, value in ipairs(key_data.hide) do                   if tpl_args[key] == value then br = true break end end if br then continue = false break end elseif key_data.hide ~= nil and tpl_args[key] == key_data.hide then continue = false break end end end return continue end

function d.area_box(tpl_args, frame) --   Display the area info box. local infocard_args = {} infocard_args.header = tpl_args.name -- Subheader local out = {} for _, key in ipairs(display.area_type) do       if tpl_args[key] == true then out[#out+1] = i18n.tooltips[key] end end

if #out > 0 then infocard_args.subheader = table.concat(out, ', ') else infocard_args.subheader = i18n.tooltips.area end -- Side header if tpl_args.is_town_area then infocard_args.headerright = i18n.images.waypoint_town elseif tpl_args.has_waypoint then infocard_args.headerright = i18n.images.waypoint_yes else infocard_args.headerright = i18n.images.waypoint_no end -- Main sections, loop through local tbl = mw.html.create('table') for _, data in ipairs(display.table_map) do       if d._check_args(tpl_args, frame, data) then tbl :tag('tr') :tag('th') :wikitext(data.header or '') :done :tag('td') :wikitext(data.func(tpl_args, frame) or '') :done :done end end infocard_args[1] = tostring(tbl) local i = 2 for _, data in ipairs(display.list_map) do       if d._check_args(tpl_args, frame, data) then infocard_args[i] = data.func(tpl_args, frame) i = i + 1 end end

return f_infocard(infocard_args) end

function d.subobject_box(tpl_args, frame) --   Display the subobject box. local container = mw.html.create('div') container :attr('class', 'modbox floatright') -- spawn weight table tbl = container:tag('table') tbl :attr('class', 'wikitable sortable') -- :attr('style', 'style="width: 100%;"') :tag('tr') :tag('th') :attr('colspan', 3) :wikitext('Spawn Weights') :done :done :tag('tr') :tag('th') :wikitext('#') :done :tag('th') :wikitext('Tag') :done :tag('th') :wikitext('Has spawn weight') :done :done :done local i = 0 local value = nil repeat i = i + 1 value = { tag = tpl_args[string.format('spawn_weight%s_tag', i)], value = tpl_args[string.format('spawn_weight%s_value', i)], }       if value.tag then tbl :tag('tr') :tag('td') :wikitext(i) :done :tag('td') :wikitext(value.tag) :done :tag('td') :wikitext(value.value) :done :done :done end until value.tag == nil return tostring(container) end

-- -- Page functions --

local p = {}

p.table_areas = m_util.cargo.declare_factory{data=argument_map}

function p.area(frame) --[[   This function adds cargo tables and displays information about the     area.    Examples    = p.area{        id = '1_1_1',         name = 'The Twilight Strand',         act = 1,         level = 1,         tags = 'no_tempests, area_with_water',         loading_screen = 'Act1',         connection_ids = '1_1_town',        parent_area_id = '1_1_town',          boss_monster_ids = 'Metadata/Monsters/ZombieBoss/ZombieBossHillockNormal',         flavour_text = 'Hope was drowned here.',         main_page = 'The Twilight Strand (Act 1)'    }      = p.area{        id = '1_1_1',         name = 'The Twilight Strand',         act = 1,         level = 1,         tags = 'no_tempests, area_with_water',         loading_screen = 'Act1',         connection_ids = '1_1_town',        parent_area_id = '1_1_town',          boss_monster_ids = 'Metadata/Monsters/ZombieBoss/ZombieBossHillockNormal',         flavour_text = 'Hope was drowned here.', main_page = 'The Twilight Strand (Act 1)'    }    = p.area{        id = '1_4_2',         name = 'The Dried Lake',         act = '4',         level = '34',         area_type_tags = 'shore',         tags = 'act_boss_area',         loading_screen = 'Act4',         connection_ids = '1_4_town',         parent_area_id = '1_4_town',         boss_monster_ids = 'Metadata/Monsters/Voll/VollBoss, Metadata/Monsters/SkeletonSoldier/SkeletonSoldierRangedBoss',         vaal_area_spawn_chance = '18',         vaal_area_ids = '1_SideArea4_2, 1_SideArea4_4',         strongbox_spawn_chance = '30',         strongbox_max = '2', strongbox_rarity_weight = '50, 50, 50, 1',         flavour_text = 'Bones of betrayal, ashes of purity.', main_page = 'The Dried Lake'}    ]] local tpl_args = getArgs(frame, {       parentFirst = true    }) frame = m_util.misc.get_frame(frame) --   -- Shared args --

tpl_args._properties = { _table = argument_map.table, }   -- Handle release_version and removal_version m_util.args.version(tpl_args, {frame=frame}) -- Parse args for _, k in ipairs(argument_order) do       local data = argument_map.fields[k] if data == nil then error('Missing data in argument_map: ' .. k)       end if data.func ~= nil then data.func(tpl_args, frame) end if data.default ~= nil and tpl_args[k] == nil then tpl_args[k] = data.default end end -- This should include all values as long they're set, regardless -- of whether they are parsed above for key, data in pairs(argument_map.fields) do       local v = tpl_args[key] if data.field ~= nil and v ~= nil then tpl_args._properties[data.field] = v       end end -- Parse spawn weights m_util.args.spawn_weight_list(tpl_args, {       frame=frame,     }) -- Category handling for main page only by adding the categories in a property: -- Do notice the plural form. -- -- Areas, Act X areas/Map areas, Unique map areas local cats = { 'Category:Areas', }   local cats_ini_len = #cats for _, key in ipairs(display.area_type) do       if tpl_args[key] == true then cats[#cats+1] = string.format('Category:%ss', i18n.tooltips[key]) end end if #cats == cats_ini_len then cats[#cats+1] = string.format('Category:Act %s areas', tpl_args.act) end

tpl_args._properties['mainpage_categories'] = table.concat(cats, ',') -- Category handling for the local data page: local page_cats = { 'Area data', }   -- Display only on main pages: local out = {} out[#out+1] = d.area_box(tpl_args, frame) -- Property to store what's output to main pages: tpl_args._properties['infobox_html'] = out[1] -- Set all semantic properties: mw.logObject('Cargo:' .. m_util.cargo.store(frame, tpl_args._properties)) mw.logObject(tpl_args._properties) -- Display only on data page: out[#out+1] = d.subobject_box(tpl_args, frame) out[#out+1] = d.intro_text(tpl_args, frame) -- Output of function return table.concat(out) .. m_util.misc.add_category(page_cats) end

function p.query_area_info(frame) --   Queries and displays the area infobox. -- = p.query_area_info{conditions = 'Is area id::test', cats='yes'} local tpl_args = getArgs(frame, {       parentFirst = true    }) frame = m_util.misc.get_frame(frame) if tpl_args.where == nil then return end tpl_args.cats = m_util.cast.boolean(tpl_args.cats) local results = cargo.query(       'areas',        'areas.infobox_html, areas.mainpage_categories',        {            where=tpl_args.where,            orderBy=tpl_args.order_by,            -- Temporary fix for cargo duplicating entries            groupBy='areas._pageID',        }    ) local out = {} local cats = {} for _, row in ipairs(results) do       out[#out+1] = row['areas.infobox_html'] if row['areas.mainpage_categories'] ~= '' then for _, cat in ipairs(m_util.string.split(row['areas.mainpage_categories'], ',')) do               cats[#cats+1] = string.gsub(cat, '[Cc]ategory:', '') end end end if tpl_args.cats then return table.concat(out) .. m_util.misc.add_category(cats) else return table.concat(out) end end

return p