Module:Final results table

From Wiki - Scioly.org
Jump to navigation Jump to search

Documentation for this module may be created at Module:Final results table/doc

local p = {};
local medals = 6;
local event_num = 1;
local drop_num = 0;
local using_states = false;
local using_numbers = false;
local trial_nums = {};
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.sum(scores)
    sum = 0
    for k, v in pairs(scores) do
        trial = false
        for _, v in pairs(trial_nums) do
            if v == k then
                trial = true
            end
        end
        if trial == false then
            sum = sum + tonumber(v)
        end
    end
    return sum
end

function event_sort(a, b)
    return a['num'] < b['num']
end

function score_sort(a, b)
    return (a['sum'] + a['tie']) < (b['sum'] + b['tie'])
end

function p.get_score_row(row, num)
    str_num = tostring(num)
    if num <= medals then
        return "|class='event" .. row .. " place" .. str_num .. "'|" .. str_num .. "\n"
    else
        return "|class='event" .. row .. "'|" .. str_num .. "\n"
    end
end

function p.main(frame)
    local args = getArgs(frame)
    -- get medals
    if args['medals'] ~= nil then
        medals = tonumber(args['medals'])
    end
    if args['drop'] ~= nil then
        drop_num = tonumber(args['drop'])
    end
    -- make event columns
    eventNames = {}
    for k, v in pairs(args) do
        if string.find(k, "event_") ~= nil and string.find(k, "trial") == nil then
            num = tonumber(string.match(k, '%d+'))
            if args['event_' .. num .. '_trial'] ~= nil then
                table.insert(eventNames, {name=v, trial=true, num=num}) 
                table.insert(trial_nums, num)
            elseif args['event_' .. num .. '_trialed'] ~= nil then
                table.insert(eventNames, {name=v, trialed=true, num=num}) 
                table.insert(trial_nums, num)
            else
                table.insert(eventNames, {name=v, trial=false, num=num})
            end
        end
    end
    event_num = #eventNames
    table.sort(eventNames, event_sort)
    -- get the number of rows to make
    maxRow = 1
    for k, v in pairs(args) do
        num = tonumber(string.match(k, '%d+'))
        if num ~= nil and num > maxRow and string.find(k, "team") ~= nil then
            maxRow = num
        end
    end
    -- get score data for each row 
    tableData = {}
    for i = 1, maxRow do
        scores = p.split(args['team_' .. tostring(i) .. '_scores'], ",")
        unsortedScores = {}
        for k, v in pairs(scores) do
            unsortedScores[k] = v
        end
        scoreSum = p.sum(scores)
        droppedScore = 0
        if drop_num > 0 then
            -- if scores need to be dropped
            for k, v in pairs(scores) do
                -- convert scores to numbers
                scores[k] = tonumber(v)
            end
            table.sort(scores)
            for l, u in pairs(scores) do
                if (l > event_num - drop_num) then
                    -- drop the last drop_num events
                    droppedScore = droppedScore + u
                end
            end
        end
        state = ""
        if args['team_' .. tostring(i) .. '_state'] ~= nil then
            using_states = true
            state = args['team_' .. tostring(i) .. '_state']
        end
        team_number = ""
        if args['team_' .. tostring(i) .. '_number'] ~= nil then
            using_numbers = true
            team_number = args['team_' .. tostring(i) .. '_number']
        end
        tie = 0
        if args['team_' .. tostring(i) .. '_tie'] ~= nil then
            tie = tie + (tonumber(args['team_' .. tostring(i) .. '_tie']) * 0.1)
        end
        scoreSum = scoreSum - droppedScore
        table.insert(tableData, {name=args['team_' .. tostring(i) .. '_name'], scores=unsortedScores, sum=scoreSum, drop=droppedScore, state=state, number=team_number, tie=tie})
    end
    -- start table
    res = "<div class='scoreboard-wrapper'>\n{| class='wikitable sortable scoreboard'\n|-\n"
    -- make header
    header = "! class='unsortable' style='line-height: 1;'| "
    if args['name'] ~= nil then
        header = header .. "<span class='scoreboard-title'><b>" .. args['name'] .. "</b></span>"
        if args['div'] ~= nil or args['date'] ~= nil then
            header = header .. "<span class='scoreboard-tourneyinfo'>"
        end
        if args['div'] ~= nil then
            header = header .. frame:preprocess("{{break}}") .. "<b>Division " .. args['div'] .. "</b>"
        end
        if args['date'] ~= nil then
            header = header .. frame:preprocess("{{break}}") .. args['date']
        end
        header = header .. frame:preprocess("{{break}}") .. #tableData .. " teams"
        if args['scilympiad'] ~= nil or args['duosmium'] ~= nil or args['unosmium'] ~= nil then
            hlistBody = "{{hlist"
            if args['scilympiad'] ~= nil then
                hlistBody = hlistBody .. "|[" .. args['scilympiad'] .. " Scilympiad]"
            end
            if args['duosmium'] ~= nil then
                hlistBody = hlistBody .. "|[" .. args['duosmium'] .. " Duosmium]"
            end
            if args['unosmium'] ~= nil then
                hlistBody = hlistBody .. "|[" .. args['unosmium'] .. " Unosmium]"
            end
            hlistBody = hlistBody .. "}}"
            header = header .. "\n\n<div class=\"noprint\">" .. frame:preprocess(hlistBody) .. "</div>"
        end
        if args['div'] ~= nil or args['date'] ~= nil then
            header = header .. "</span>"
        end
        header = header .. "\n\n"
        header = header .. frame:preprocess("<span class=\"noprint\">{{clickable button|Print|pl_class=scoreboard-print-button|url={{fullurl:{{FULLPAGENAME}}|printable=yes}}}}</span>")
    end
    res = res .. header .. "\n"
    if using_numbers == true then
        res = res .. frame:preprocess("! {{vertical header|Team Number|stp=1}}\n") 
    end
    if using_states == true then
        res = res .. frame:preprocess("! {{vertical header|State|stp=1}}\n") 
    end
    res = res .. frame:preprocess("! {{vertical header|Final Place|stp=1|class=scoreboard-header-place}}\n")
    res = res .. frame:preprocess("! {{vertical header|Points|stp=1}}\n")
    for k, v in pairs(eventNames) do
        if v['trial'] == true then
            res = res .. frame:preprocess("! class='scoreboard-header" .. k .. "' {{vertical header|" .. v['name'] .. " (Trial)|stp=1|cellstyle=background-color: #C0D1E9}}\n")
        elseif v['trialed'] ~= nil then
            res = res .. frame:preprocess("! class='scoreboard-header" .. k .. "' {{vertical header|" .. v['name'] .. " (Trialed)|stp=1|cellstyle=background-color: #ffd7bd}}\n")
        else
            res = res .. frame:preprocess("! class='scoreboard-header" .. k .. "' {{vertical header|" .. v['name'] .. "|stp=1}}\n")
        end
    end
    if drop_num > 0 then
        res = res .. frame:preprocess("! {{vertical header|Dropped Points|stp=1}}\n") 
    end
    -- make table
    table.sort(tableData, score_sort)
    placeCounter = 1
    prevScore = 0
    for k, v in pairs(tableData) do
        -- for each row in the sorted data
        tableRow = ""
        -- add row styling
        tableRow = tableRow .. "|- class='scoreboard-team'\n"
        tableRow = tableRow .. "|class='scoreboard-name'|" .. v['name'] .. "\n"
        if using_numbers == true then
            tableRow = tableRow .. "|class='scoreboard-number'| " .. v['number'] .. "\n"
        end
        -- add team numbers/states
        if using_states == true then
            tableRow = tableRow .. "|class='scoreboard-state'|" .. v['state'] .. "\n"
        end
        place = k
        if (v['sum'] + v['tie']) == prevScore then
            place = placeCounter
        end
        tableRow = tableRow .. "|class='scoreboard-place'|" .. place .. "\n"
        tableRow = tableRow .. "|class='scoreboard-sum'|" .. v['sum'] .. "\n"
        -- add scores
        for l, u in pairs(v['scores']) do
            tableRow = tableRow .. p.get_score_row(l, tonumber(u))
        end
        -- add sum
        if drop_num > 0 then
            -- if scores need to be dropped
            tableRow = tableRow .. "|class='scoreboard-drop'|" .. v['drop'] .. "\n"
        end
        res = res .. tableRow
        placeCounter = place
        prevScore = (v['sum'] + v['tie'])
    end
    res = res .. '|}</div>'
    return res
end

return p;