Module:Sandbox/Aurelain/UnitInfobox: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
Created page with "-- This module is intended as a supporting muscle for the UnitInfobox template. local p = {} -- Displays a variable ------------------------------------------------------------------------------------------------------------------------ local function dump(target) return '<pre>' .. mw.dumpObject(target) .. '</pre>' end -- Spawns a safe robotic url from an English name, fit for adding it before the visible name -------------------------------------------------------..."
 
No edit summary
 
(8 intermediate revisions by the same user not shown)
Line 49: Line 49:
         end
         end
     end
     end
     return mw.ext.cargo.query(tables, fields, options)
     local success, result = pcall(function()
        return mw.ext.cargo.query(tables, fields, options)
    end)
    return success and result or {}
end
end


Line 67: Line 70:
             U.id = T.target_id
             U.id = T.target_id
         | where =
         | where =
             U.id = '%s'
             U.id = "%s"
             AND T.language = 'en'
             AND T.language = 'en'
             AND T.type = 'unit'
             AND T.type = 'unit'
Line 80: Line 83:
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
function p.findGrowth(frame)
function p.findGrowth(frame)
    -- TODO: Read this value from MapObject, once we have it in Cargo.
     local unitId = frame.args.id
     local unitId = frame.args.id
     local baseId = getBaseId(unitId)
     local baseId = getBaseId(unitId)
     local table = runQuery([[
     local table = runQuery([[
         tables =
         tables =
             Building = B
             MapObject = M
         | where =
         | where =
             B.units_hire_sid = '%s'
             M.units_hire_sid = '%s'
         | fields =
         | fields =
             B.units_weekly = units_weekly
             M.units_weekly = units_weekly
         | limit =
         | limit =
             1
             1
     ]], baseId);
     ]], baseId);
     local growth = (table[1] or { units_weekly = '' }).units_weekly
     local growth = (table[1] or { units_weekly = '' }).units_weekly
 
     return growth;
     if growth ~= '' then
        return growth
    end
 
    return '';
end
end


Line 114: Line 111:
             B.id = E.target_id
             B.id = E.target_id
         | where =
         | where =
             B.units_hire_sid = '%s'
             B.units_hire_sid = "%s"
             AND T.language = '%s'
             AND T.language = "%s"
             AND E.language = 'en'
             AND E.language = 'en'
         | fields =
         | fields =
Line 152: Line 149:
             E.type = 'map_object'
             E.type = 'map_object'
             AND E.language = 'en'
             AND E.language = 'en'
             AND E.description LIKE '%s %s%%'
             AND E.description LIKE "%s %s%%"
             AND T.type = 'map_object'
             AND T.type = 'map_object'
             AND T.language = '%s'
             AND T.language = "%s"
         | fields =
         | fields =
             E.name = name_en,
             E.name = name_en,
Line 185: Line 182:
     local unitId = frame.args.id
     local unitId = frame.args.id
     local nameEn = getEnglishBaseUnitName(unitId)
     local nameEn = getEnglishBaseUnitName(unitId)
    local nameEnWithSmartApostrophe = nameEn:gsub("'", '’')
     local table = runQuery([[
     local table = runQuery([[
         tables =
         tables =
Line 191: Line 189:
             T.type = 'hero_specialization'
             T.type = 'hero_specialization'
             AND T.language = 'en'
             AND T.language = 'en'
             AND T.description LIKE '%s growth in your cities increases by%%'
             AND (T.description LIKE "%s growth in your cities increases by%%" OR
                T.description LIKE "%s growth in your cities increases by%%")
         | fields =
         | fields =
             T.target_id = target_id
             T.target_id = target_id
         | limit =
         | limit =
             1
             1
     ]], nameEn);
     ]], nameEn, nameEnWithSmartApostrophe);
     local specialist = (table[1] or {target_id = ''}).target_id
     local specialist = (table[1] or {target_id = ''}).target_id
     specialist = specialist:gsub('_specialization', '')
     specialist = specialist:gsub('_specialization', '')

Latest revision as of 08:48, 20 July 2026

Documentation for this module may be created at Module:Sandbox/Aurelain/UnitInfobox/doc

-- This module is intended as a supporting muscle for the UnitInfobox template.
local p = {}

-- Displays a variable
------------------------------------------------------------------------------------------------------------------------
local function dump(target)
    return '<pre>' .. mw.dumpObject(target) .. '</pre>'
end

-- Spawns a safe robotic url from an English name, fit for adding it before the visible name
------------------------------------------------------------------------------------------------------------------------
local function getUrl(nameEn, lang)
    if not nameEn then
        return ''
    end
    local url = nameEn
    if lang ~= 'en' then
        url = url .. '/' .. lang
    end
    return url
end

-- Parses and runs a Cargo query from wiki-like syntax
------------------------------------------------------------------------------------------------------------------------
local function runQuery(query, ...)
    query = string.gsub(query, "%-%-.-\n", "") -- remove "comments"
    query = select('#', ...) > 0 and mw.ustring.format(query, ...) or query
    query = mw.text.trim(query)
    local tables = ''
    local fields = ''
    local options = {}
    for part in query:gmatch('[^|]+') do
        local key, val = part:match('^%s*([^=]+)%s*=%s*(.-)%s*$')
        if key and val then
            key = mw.text.trim(key):lower()
            val = mw.text.trim(val)
            val = val:gsub('%s', ' ')
            if key == 'tables' then
                tables = val
            elseif key == 'fields' then
                fields = val
            elseif key == 'limit' then
                options[key] = tonumber(val) or val
            elseif key == 'join on' then
                options['join'] = val
            else
                options[key] = val
            end
        end
    end
    local success, result = pcall(function()
        return mw.ext.cargo.query(tables, fields, options)
    end)
    return success and result or {}
end

------------------------------------------------------------------------------------------------------------------------
local function getBaseId(unitId)
    return unitId:gsub('_alt$', ''):gsub('_upg$', '')
end

------------------------------------------------------------------------------------------------------------------------
local function getEnglishBaseUnitName(unitId)
    local baseId = getBaseId(unitId)
    local table = runQuery([[
        tables =
            Unit = U,
            Translation = T
        | join on =
            U.id = T.target_id
        | where =
            U.id = "%s"
            AND T.language = 'en'
            AND T.type = 'unit'
        | fields =
            T.name = name
        | limit =
            1
    ]], baseId);
    return (table[1] or {name = ''}).name
end

------------------------------------------------------------------------------------------------------------------------
function p.findGrowth(frame)
    local unitId = frame.args.id
    local baseId = getBaseId(unitId)
    local table = runQuery([[
        tables =
            MapObject = M
        | where =
            M.units_hire_sid = '%s'
        | fields =
            M.units_weekly = units_weekly
        | limit =
            1
    ]], baseId);
    local growth = (table[1] or { units_weekly = '' }).units_weekly
    return growth;
end

------------------------------------------------------------------------------------------------------------------------
local function findTownBuilding(unitId, lang)
    local baseId = getBaseId(unitId)
    local table = runQuery([[
        tables =
            Building = B,
            Translation = T,
            Translation = E,
        | join on =
            B.id = T.target_id,
            B.id = E.target_id
        | where =
            B.units_hire_sid = "%s"
            AND T.language = "%s"
            AND E.language = 'en'
        | fields =
            T.name = name,
            E.name = name_en
        | limit =
            2
    ]], baseId, lang);
    if #table ~= 2 then
        return nil
    end
    local level = unitId == baseId and 1 or 2
    return {
        name_en = table[1].name_en, -- we need the English name of the base!
        name = table[level].name
    }
end

------------------------------------------------------------------------------------------------------------------------
local function findExternalDwelling(unitId, lang, isBank)
    local nameEn = getEnglishBaseUnitName(unitId)
    nameEn = nameEn:gsub('man$', 'men') -- fix 'Swordmen' and 'Crossbowmen'
    nameEn = nameEn:gsub(' of', 's of') -- fix 'Sentinels of Glory'
    nameEn = nameEn:gsub('Waurms', 'Waurmos')

    -- Note: Currently (2026-07-16), the banks are not present in Cargo
    local prefix = isBank == 1 and 'Defeat its guard to obtain' or 'You can recruit'

    local table = runQuery([[
        tables =
            Translation = E,
            Translation = T,
        | join on =
            E.target_id = T.target_id
        | where =
            E.type = 'map_object'
            AND E.language = 'en'
            AND E.description LIKE "%s %s%%"
            AND T.type = 'map_object'
            AND T.language = "%s"
        | fields =
            E.name = name_en,
            T.name = name
        | limit =
            1
    ]], prefix, nameEn, lang);
    if #table ~= 1 then
        return nil
    end
    return table[1]
end

------------------------------------------------------------------------------------------------------------------------
function p.findDwelling(frame)
    local unitId = frame.args.id
    local lang = frame.args.lang
    local names = findTownBuilding(unitId, lang)
    if not names then
        names = findExternalDwelling(unitId, lang, 0)
    end
    if not names then
        return ''
    end
    return '[[' .. getUrl(names.name_en, lang) .. '|' .. names.name .. ']]'
end

------------------------------------------------------------------------------------------------------------------------
function p.findSpecialistId(frame)
    local unitId = frame.args.id
    local nameEn = getEnglishBaseUnitName(unitId)
    local nameEnWithSmartApostrophe = nameEn:gsub("'", '’')
    local table = runQuery([[
        tables =
            Translation = T
        | where =
            T.type = 'hero_specialization'
            AND T.language = 'en'
            AND (T.description LIKE "%s growth in your cities increases by%%" OR
                T.description LIKE "%s growth in your cities increases by%%")
        | fields =
            T.target_id = target_id
        | limit =
            1
    ]], nameEn, nameEnWithSmartApostrophe);
    local specialist = (table[1] or {target_id = ''}).target_id
    specialist = specialist:gsub('_specialization', '')
    return specialist
end

------------------------------------------------------------------------------------------------------------------------
function p.findBank(frame)
    return ''
end

------------------------------------------------------------------------------------------------------------------------
function p.simplifyName(frame)
    return (mw.ustring.gsub(frame.args.name, "[^%a]", ""))
end

return p