Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

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

local p = {}
local _id_counter = 0
local html = mw.html

-- Helper: Add ordinal suffix
local function getOrdinal(n)
    local last = n % 10
    local lastTwo = n % 100
    if lastTwo >= 11 and lastTwo <= 13 then return n .. "th" end
    if last == 1 then return n .. "st" end
    if last == 2 then return n .. "nd" end
    if last == 3 then return n .. "rd" end
    return n .. "th"
end

-- ============================================================
-- 1. STAGE TIMELINE (Collapsible Headers)
-- ============================================================
function p.timeline(frame)
    local args = frame:getParent().args
    local container = html.create('div'):addClass('fmt-timeline')

    -- Generate a base random ID to prevent conflicts on same page
_id_counter = _id_counter + 1
local baseID = "fmt-" .. _id_counter

    for i = 1, 15 do
        local name = args['stage' .. i]
        local date = args['date' .. i]
        local desc = args['desc' .. i]
        
        if name and name ~= "" then
            local uniqueID = "stg-" .. baseID .. "-" .. i
            
            local node = container:tag('div'):addClass('fmt-node')
            
            -- Left Marker
            node:tag('div'):addClass('fmt-marker')
            
            -- Content Box
            local content = node:tag('div'):addClass('fmt-content')
            
            -- HEADER (The Trigger)
            local header = content:tag('div')
                :addClass('fmt-header-row')
                :addClass('mw-customtoggle-' .. uniqueID) -- Makes it clickable
                :attr('title', 'Click to expand/collapse')
            
            -- Title Wrapper
            local titleWrap = header:tag('div'):addClass('fmt-title-wrap')
            titleWrap:tag('div'):addClass('fmt-stage-title'):wikitext(name)
            
            -- Right Side (Date + Icon)
            local metaWrap = header:tag('div'):addClass('fmt-meta-wrap')
            
            if date and date ~= "" then
                metaWrap:tag('div'):addClass('fmt-date'):wikitext(date)
            end
            
            -- Chevron Icon (Visual cue)
            if desc and desc ~= "" then
                 metaWrap:tag('i'):addClass('fa-solid fa-chevron-down fmt-toggle-icon')
            end
            
            -- DESCRIPTION (The Target)
            if desc and desc ~= "" then
                content:tag('div')
                    :addClass('fmt-desc mw-collapsible mw-collapsed') -- Hidden by default
                    :attr('id', 'mw-customcollapsible-' .. uniqueID)
                    :wikitext(frame:preprocess(desc))
            end
        end
    end
    
    return tostring(container)
end

-- ============================================================
-- 2. POINTS DISTRIBUTION (Column Major + Dark Mode Ready)
-- ============================================================
function p.points(frame)
    local args = frame:getParent().args
    local system = args.type or "10"
    
    local dist = {}
    local killPts = args.kill_pts or 1
    
    if system == "15" then dist = {15, 12, 10, 8, 6, 4, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0}
    elseif system == "10" then dist = {10, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
    else for i = 1, 20 do if args['p' .. i] then table.insert(dist, tonumber(args['p' .. i])) end end end

    local container = html.create('div'):addClass('fmt-points-container')
    container:tag('div'):addClass('fmt-points-header'):wikitext('Points Distribution')
    
    local groups = {}
    local currentPts = -1
    local rangeStart = 1
    for i = 1, #dist + 1 do
        local pts = dist[i]
        if pts ~= currentPts then
            if i > 1 then
                local rangeEnd = i - 1
                local rankLabel = (rangeStart == rangeEnd) and getOrdinal(rangeStart) or (getOrdinal(rangeStart) .. " – " .. getOrdinal(rangeEnd))
                table.insert(groups, { label = rankLabel, val = currentPts, isTop3 = (rangeStart <= 3) })
            end
            rangeStart = i
            currentPts = pts
        end
    end
    
    local midPoint = math.ceil(#groups / 2)
    local flexWrapper = container:tag('div'):addClass('fmt-points-columns')
    local leftCol = flexWrapper:tag('div'):addClass('fmt-points-col')
    local rightCol = flexWrapper:tag('div'):addClass('fmt-points-col')
    
    for i, grp in ipairs(groups) do
        local target = (i <= midPoint) and leftCol or rightCol
        local row = target:tag('div'):addClass('fmt-pt-row')
        row:tag('div'):addClass('fmt-pt-rank-v'):wikitext(grp.label)
        row:tag('div'):addClass('fmt-pt-val-v'):wikitext(grp.val)
        if grp.isTop3 and grp.val > 0 then row:addClass('row-top3') end
        if grp.val == 0 then row:addClass('row-zero') end
    end
    
    local killBox = container:tag('div'):addClass('fmt-kill-box')
    killBox:wikitext('Each Finish: <b>' .. killPts .. ' Point</b>')
    
    return tostring(container)
end

-- 3. MAP ROTATION (Unchanged)
function p.maps(frame)
    local args = frame:getParent().args
    local container = html.create('div'):addClass('fmt-maps-container')
    if args.title then container:tag('div'):addClass('fmt-maps-header'):wikitext(args.title) end
    local list = container:tag('div'):addClass('fmt-maps-list')
    local mapDict = {
        e = {name="Erangel", class="map-erangel"}, m = {name="Miramar", class="map-miramar"},
        s = {name="Sanhok", class="map-sanhok"}, v = {name="Vikendi", class="map-vikendi"},
        r = {name="Rondo",   class="map-rondo"}, tbd = {name="TBD",   class="map-tbd"}
    }
    for i = 1, 10 do
        local m = args[i] or args['m' .. i]
        if m and m ~= "" then
            local key = m:lower():sub(1,1)
            local data = mapDict[key] or {name=m, class="map-tbd"}
            if m:lower() == "rondo" then data = mapDict['r'] end
            if m:lower() == "erangel" then data = mapDict['e'] end
            if m:lower() == "miramar" then data = mapDict['m'] end
            if m:lower() == "sanhok" then data = mapDict['s'] end
            if m:lower() == "vikendi" then data = mapDict['v'] end
            list:tag('div'):addClass('fmt-map-item'):tag('span'):addClass('fmt-map-badge ' .. data.class):wikitext(data.name)
        end
    end
    return tostring(container)
end

return p