Jump to content

Module:MobVariants: Difference between revisions

From Drifters Almanac
No edit summary
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 42: Line 42:
     end
     end


     local output = { '<ul style="margin-left: 1em;">' }
    local itemCount = #items
    local columnCount = 1
 
    if itemCount >= 16 then
        columnCount = 3
    elseif itemCount >= 8 then
        columnCount = 2
    end
 
     local output = {
        string.format('<div style="column-count: %d; column-gap: 1.5em;">', columnCount),
        '<ul style="margin: 0; padding-left: 1.5em;">'
    }
 
     for _, item in ipairs(items) do
     for _, item in ipairs(items) do
         table.insert(output, string.format('<li>[[%s]]</li>', item))
         table.insert(output, string.format('<li style="break-inside: avoid;">[[%s]]</li>', item))
     end
     end
     table.insert(output, '</ul>')
     table.insert(output, '</ul>')
    table.insert(output, '</div>')


     return table.concat(output, "\n")
     return table.concat(output)
end
end



Latest revision as of 14:50, 27 March 2026

Documentation for this module may be created at Module:MobVariants/doc

local p = {}

local variantKeys = { "a", "b", "c" }

local function trim(s)
    if not s then
        return ""
    end
    return mw.text.trim(s)
end

local function hasValue(s)
    return trim(s) ~= ""
end

local function splitAndSort(raw, delimiter)
    delimiter = delimiter or ","
    local results = {}

    if not hasValue(raw) then
        return results
    end

    local items = mw.text.split(raw, delimiter)
    for _, item in ipairs(items) do
        local value = trim(item)
        if value ~= "" then
            table.insert(results, value)
        end
    end

    table.sort(results, function(a, b)
        return mw.ustring.lower(a) < mw.ustring.lower(b)
    end)

    return results
end

local function makeBulletedList(items)
    if not items or #items == 0 then
        return ""
    end

    local itemCount = #items
    local columnCount = 1

    if itemCount >= 16 then
        columnCount = 3
    elseif itemCount >= 8 then
        columnCount = 2
    end

    local output = {
        string.format('<div style="column-count: %d; column-gap: 1.5em;">', columnCount),
        '<ul style="margin: 0; padding-left: 1.5em;">'
    }

    for _, item in ipairs(items) do
        table.insert(output, string.format('<li style="break-inside: avoid;">[[%s]]</li>', item))
    end

    table.insert(output, '</ul>')
    table.insert(output, '</div>')

    return table.concat(output)
end

local function makeBulletedListCompact(items)
    if not items or #items == 0 then
        return ""
    end

    local itemCount = #items
    local columnCount = 1

    if itemCount >= 8 then
        columnCount = 2
    end

    local output = {
        string.format('<div style="column-count: %d; column-gap: 2em;">', columnCount),
        '<ul style="margin: 0; padding-left: 1.2em;">'
    }

    for _, item in ipairs(items) do
        table.insert(output, string.format('<li style="break-inside: avoid;">[[%s]]</li>', item))
    end

    table.insert(output, '</ul>')
    table.insert(output, '</div>')

    return table.concat(output)
end

local function makeInlineList(items)
    if not items or #items == 0 then
        return ""
    end

    local linked = {}
    for _, item in ipairs(items) do
        table.insert(linked, string.format('[[%s]]', item))
    end

    return table.concat(linked, ", ")
end

local function formatLevelRange(low, high)
    low = trim(low)
    high = trim(high)

    if low ~= "" and high ~= "" then
        if low == high then
            return low
        end
        return low .. " - " .. high
    elseif low ~= "" then
        return low
    elseif high ~= "" then
        return high
    end

    return ""
end

local function collectVariants(frame)
    local args = frame.args
    local variants = {}

    for _, key in ipairs(variantKeys) do
        local region = trim(args["region_" .. key] or "")
        local levelLow = trim(args["level_low_" .. key] or "")
        local levelHigh = trim(args["level_high_" .. key] or "")
        local lootRaw = trim(args["loot_table_" .. key] or "")
        local harvestRaw = trim(args["harvest_table_" .. key] or "")

        local hasData =
            region ~= "" or
            levelLow ~= "" or
            levelHigh ~= "" or
            lootRaw ~= "" or
            harvestRaw ~= ""

        if hasData then
            table.insert(variants, {
                key = key,
                region = region,
                levelLow = levelLow,
                levelHigh = levelHigh,
                levelDisplay = formatLevelRange(levelLow, levelHigh),
                lootItems = splitAndSort(lootRaw, ","),
                harvestItems = splitAndSort(harvestRaw, ",")
            })
        end
    end

    return variants
end

local function renderSingleVariant(variant)
    local output = {}

    local details = {}
    if variant.region ~= "" then
        table.insert(details, "'''Region:''' " .. variant.region)
    end
    if variant.levelDisplay ~= "" then
        table.insert(details, "'''Level:''' " .. variant.levelDisplay)
    end

    if #details > 0 then
        table.insert(output, '<div style="margin-left: 1em;">')
        table.insert(output, table.concat(details, "<br />\n"))
        table.insert(output, '</div>')
    end

    if variant.harvestItems and #variant.harvestItems > 0 then
        table.insert(output, '==Harvest==')
        table.insert(output, '<div style="margin-left: 1em;">')
        table.insert(output, makeBulletedList(variant.harvestItems))
        table.insert(output, '</div>')
    end

    if variant.lootItems and #variant.lootItems > 0 then
        table.insert(output, '==Drops==')
        table.insert(output, '<div style="margin-left: 1em;">')
        table.insert(output, makeBulletedList(variant.lootItems))
        table.insert(output, '</div>')
    end

    return table.concat(output, "\n")
end

local function renderMultipleVariants(variants)
    local output = {}

    table.insert(output, '==Variants==')
    table.insert(output, '{| class="wikitable" style="width: 100%;"')
    table.insert(output, '! Region')
    table.insert(output, '! Level')
    table.insert(output, '! Harvest')
    table.insert(output, '! Drops')

    for _, variant in ipairs(variants) do
        local region = variant.region ~= "" and variant.region or "—"
        local level = variant.levelDisplay ~= "" and variant.levelDisplay or "—"
        local harvest = (#variant.harvestItems > 0) and makeBulletedListCompact(variant.harvestItems) or "—"
        local loot = (#variant.lootItems > 0) and makeBulletedListCompact(variant.lootItems) or "—"

        table.insert(output, '|-')
        table.insert(output, '| ' .. region)
        table.insert(output, '| ' .. level)
        table.insert(output, '| ' .. harvest)
        table.insert(output, '| ' .. loot)
    end

    table.insert(output, '|}')

    return table.concat(output, "\n")
end

function p.render(frame)
    local variants = collectVariants(frame)

    if #variants == 0 then
        return ""
    elseif #variants == 1 then
        return renderSingleVariant(variants[1])
    else
        return renderMultipleVariants(variants)
    end
end

return p