Jump to content

Module:Individual placements table

From Wiki - Scioly.org
Revision as of 05:30, 3 May 2022 by Pepperonipi (talk | contribs) (custom sorting for N/A values)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Individual placements table/doc

local p = {};
local trials = false;
local getArgs = require('Module:Arguments').getArgs

function p.trim(str)
    -- trim string function
    return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
end

function p.split(inputstr, sep)
    -- split string function
    t = {}
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        str = p.trim(str)
        table.insert(t, str)
    end
    return t
end

function p.generateMedalCell(frame, place, limit)
    -- generates mw code for proper medal cell display
    -- if no number if found, no value
    if place == nil then
        return " ";
    end
    if place == "N" then
        return "data-sort-value='1000' | N/A";
    end
    if string.find(place, '%d+') == nil then
        return place;
    end

    -- some number is found
    local number = string.match(place, '%d+');
    local res = number;
    if tonumber(number) <= limit then
        res = "data-sort-value='" .. number .. "' class='place" .. number .. "' | " .. frame:preprocess("{{mdl|" .. number .. "}}");
    end
    if string.find(place, 'T') ~= nil and string.find(place, '%d') then
        res = res .. "<sup>T</sup>";
        trials = true;
    end
    return res
end

-- From: https://stackoverflow.com/a/27028488
function dump(o)
   if type(o) == 'table' then
      local s = '{ '
      for k,v in pairs(o) do
         if type(k) ~= 'number' then k = '"'..k..'"' end
         s = s .. '['..k..'] = ' .. dump(v) .. ','
      end
      return s .. '} '
   else
      return tostring(o)
   end
end

function p.main(frame)
    -- Main function
    local args = getArgs(frame)
    local tournaments = {}; -- {{'name': name, 'count': 3,}, {...}, ...}
    local tournamentTeams = {}; -- {{{'name': 'Team A', 'medals': {3, 4}}, {...}, ...}}
    local teamCount = 0; -- Number of total team columns in table
    local events = {}; -- {'Anatomy and Physiology', 'Boomilever'}
    -- Get tournament names
    for k, v in pairs(args) do
        if string.find(k, "tourney") ~= nil and string.find(k, 'team') == nil and string.find(k, 'medals') == nil then
            -- Tourney name was found
            num = tonumber(string.match(k, '%d+'));
            if tournaments[num] ~= nil then
                tournaments[num]["name"] = v;
            else
                tournaments[num] = {name = v};
            end
        elseif string.find(k, "tourney") ~= nil and string.find(k, "medals") ~= nil then
            -- Number of medals for tourney was found
            num = tonumber(string.match(k, '%d+'));
            if tournaments[num] ~= nil then
                tournaments[num]["medals"] = v;
            else
                tournaments[num] = {medals = v};
            end
        elseif string.find(k, "tourney") ~= nil and string.find(k, "team") ~= nil then
            -- Team placements found
            nums = string.gmatch(k, '%d+');
            numsResult = {};
            for num in nums do
                table.insert(numsResult, tonumber(num));
            end
            tourneyNum, teamNum = numsResult[1], numsResult[2];
            valueArgs = p.split(v, ",");
            name = valueArgs[1];
            medals = {unpack(valueArgs, 2)}
            if tournamentTeams[tourneyNum] ~= nil then
                tournamentTeams[tourneyNum][teamNum] = {name = name, medals = medals};
            else
                tournamentTeams[tourneyNum] = {[teamNum] = {name = name, medals = medals}};
            end
            -- Add one to tournament's team count
            if tournaments[tourneyNum] ~= nil then
                if tournaments[tourneyNum]["count"] == nil then
                    tournaments[tourneyNum]["count"] = 1;
                else
                    tournaments[tourneyNum]["count"] = tournaments[tourneyNum]["count"] + 1;
                end
            else
                tournaments[tourneyNum] = {count = 1};
            end
            teamCount = teamCount + 1;
        elseif string.find(k, "event") ~= nil then
            -- Event found
            num = tonumber(string.match(k, '%d+'))
            events[num] = v;
        else
            tournaments[1][k] = "Not found"
        end
    end
    -- Start table
    local res = "{| class='wikitable sortable' style='text-align: center; font-size: 90%;'\n|-\n"
    res = res .. "!rowspan=2 | Events\n"
    for k, v in pairs(tournaments) do
        res = res .. "!colspan=" .. v["count"] .. " | " .. (v["name"] or "Not Found") .. "\n";
    end
    res = res .. "|-\n";
    for k, v in pairs(tournamentTeams) do
        -- For each tournament with teams
        for k1, v1 in pairs(v) do
            -- For each team 
            res = res .. "! " .. frame:preprocess("{{vertical header|" .. v1["name"] .. "|stp=1}}") .. "\n";
        end
    end
    res = res .. "|-\n";
    -- Add actual placements
    eventCount = 1;
    for i=1,#events do    
        tourneyCount = 1;
        localTeamCount = 0;
        res = res .. "|" .. events[i] ..  "\n"
        for j=1,teamCount do
            localTeamCount = localTeamCount + 1;
            if tournamentTeams[tourneyCount][localTeamCount] == nil then
                tourneyCount = tourneyCount + 1;
                localTeamCount = 1;
            end
            local limit = tonumber(tournaments[tourneyCount]["medals"]);
            res = res .. "|" .. p.generateMedalCell(frame, tournamentTeams[tourneyCount][localTeamCount]["medals"][i], limit) .. "\n";
        end
        res = res .. "|-\n";
    end
    res = res .. "|}";
    if trials then
        res = res .. frame:preprocess("<div style=\"margin-left: 15px;\"><sup>T</sup> indicates a trial event.</div>");
    end
    return res;
end

return p;