Module:DartsRankings

require('strict');local p = {}local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>';-- data for various rankings held in module subpages, e.g. "Module:SportsRankings/data/FIFA World Rankings"local data = {}      --[[ parameters containing data help in three tablesdata.source = {}     -- parameters for using in cite web (title, url, website)data.updated = {}    -- date of latest update (month, day, year)data.rankings = {}   -- the rankings list (country code, ranking, movement)data.alias = {}      -- player list (player, country code [=key], wiki link, proper display)--]]local tcats = ''local tcatsp = ''local templateArgs = {} -- contains arguments from template involking modulelocal function getArgs(frame)    local parents = mw.getCurrentFrame():getParent()    for k,v in pairs(parents.args) do        --check content        if v and v ~= "" then            templateArgs[k] = v --parents.args[k]        end    end    for k,v in pairs(frame.args) do        --check content        if v and v ~= "" then            templateArgs[k] = v --parents.args[k]        end    end    -- allow empty caption to blank default    if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] endendlocal function loadData(frame)    if templateArgs['org'] then        data = mw.loadData('Module:DartsRankings/data/' .. templateArgs['org'] .. ' Rankings');    else    local source = frame.args[1] -- source of rankings e.g. PDC Rankings    data = mw.loadData('Module:DartsRankings/data/'.. source);    endendlocal function getDate(option)    local dateTable = data.updated         -- there must be date table (data.updated)    -- TODO add a warning and/or category    if option == "LAST" then        local lastDateTable = data.previous        if lastDateTable then             -- there might not be a previous data table (data.previous)            dateTable = lastDateTable        else            return "No previous date available (data.updated missing)"        end    end    if templateArgs['mdy'] and templateArgs['mdy'] ~= "" then        return dateTable['month'] .. " " .. dateTable['day'] .. ", " .. dateTable['year']    else        return dateTable['day'] .. " " .. dateTable['month'] .. " " .. dateTable['year']    endendlocal function addCiteWeb(frame)  -- use cite web template    return frame:expandTemplate{ title = 'cite web' , args = {        url = data.source['url'],            --"https://www.fifa.com/fifa-world-ranking/ranking-table/men/index.html",        title = data.source['title'],        -- "The FIFA/Coca-Cola World Ranking",        website = data.source['website'],    --"FIFA",        ['date'] = getDate(),        ['access-date'] = getDate()    }}endlocal function addReference(frame)    local text = ""    if data.source['text'] then text = data.source['text'] end    return frame:expandTemplate{ title = 'refn', args = {        name=frame.args[1],                   --ranking used, e.g. "PDC Rankings",        text .. addCiteWeb(frame)    }}endlocal function noAc(str)    local tableAccents = {        ["À"] = "A",        ["Á"] = "A",        ["Â"] = "A",        ["Ã"] = "A",        ["Ä"] = "A",        ["Å"] = "A",        ["Æ"] = "AE",        ["Ç"] = "C",        ["È"] = "E",        ["É"] = "E",        ["Ê"] = "E",        ["Ë"] = "E",        ["Ì"] = "I",        ["Í"] = "I",        ["Î"] = "I",        ["Ï"] = "I",        ["Ð"] = "D",        ["Ñ"] = "N",        ["Ò"] = "O",        ["Ó"] = "O",        ["Ô"] = "O",        ["Õ"] = "O",        ["Ö"] = "O",        ["ő"] = "O",        ["Ø"] = "O",        ["Ù"] = "U",        ["Ú"] = "U",        ["Û"] = "U",        ["Ü"] = "U",        ["Ý"] = "Y",        ["Þ"] = "P",        ["ß"] = "s",        ["à"] = "a",        ["á"] = "a",        ["â"] = "a",        ["ã"] = "a",        ["ä"] = "a",        ["å"] = "a",        ["æ"] = "ae",        ["ç"] = "c",        ["č"] = "c",        ["ć"] = "c",        ["è"] = "e",        ["é"] = "e",        ["ê"] = "e",        ["ë"] = "e",        ["ì"] = "i",        ["í"] = "i",        ["î"] = "i",        ["ï"] = "i",        ["ł"] = "l",        ["ð"] = "eth",        ["ñ"] = "n",        ["ò"] = "o",        ["ó"] = "o",        ["ô"] = "o",        ["õ"] = "o",        ["ö"] = "o",        ["ø"] = "o",        ["ù"] = "u",        ["ú"] = "u",        ["û"] = "u",        ["ü"] = "u",        ["ý"] = "y",        ["þ"] = "p",        ["ÿ"] = "y"    }    return str:gsub("[%z\1-\127\194-\244][\128-\191]*", tableAccents)endlocal function nameEqual(str1, str2)    return string.lower(noAc(str1)):gsub("%W", "") == string.lower(noAc(str2)):gsub("%W", "")endfunction p.dates(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    --if templateArgs[1]==1 then    return getDate(templateArgs[2])    --else    --return getDate()    --endendlocal function flagPlayer(frame, player, side)    local outputString = ""    local flag, link = '', ''    if player and player ~= '' then link = '[[' .. player .. ']]'        tcatsp='[[Category:Pages using DartsRankings with missing player data|' .. player .. ']]'    end    for _,u in pairs(data.alias) do  -- get country code from name        if nameEqual(u[1], player) then            tcatsp=''            local nlink = ""            if u[5] == 0 then nlink = 1 end            if templateArgs['nolink'] == '1' then nlink = 1 end            if templateArgs['nolink'] == '0' then nlink = "" end            if templateArgs['surname'] =='1' then            if nlink == 1 then            link = u[4]                elseif u[6] and u[6]~="" then                    link = '[[' .. u[3] .. ' ' .. u[4] .. ' (' ..u[6] .. ')' .. '|' .. u[4] ..']]'                else                    link = '[[' .. u[3] .. ' ' ..  u[4] .. '|' .. u[4] ..']]'                end            elseif templateArgs['surname'] then        if nlink == 1 then            link = templateArgs['surname']                elseif u[6] and u[6]~="" then                    link = '[[' .. u[3] .. ' ' .. u[4] .. ' (' ..u[6] .. ')' .. '|' .. templateArgs['surname'] ..']]'                else                    link = '[[' .. u[3] .. ' ' .. u[4] .. '|' .. templateArgs['surname'] ..']]'                end            else                if u[6] and u[6]~="" then                    link = frame:expandTemplate{title= 'sortname', args ={ u[3], u[4] , dab = u[6] , nolink = nlink } }                else                    link = frame:expandTemplate{title= 'sortname', args ={ u[3], u[4], nolink = nlink } }                end            end            flag= u[2] -- Flag string from libarary            break        end    end    if templateArgs['flag'] then        flag = templateArgs['flag']    end    if side == 'right' then        outputString = link .. require('Module:Flagg').luaMain(frame, {'csxr', flag})    elseif side == 'none' then        outputString = link    else        outputString = require('Module:Flagg').luaMain(frame, {'csx', flag}) .. link    end    tcats = tcats .. tcatsp    return outputString .. tcatsendfunction p.playerLink(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    return flagPlayer(frame, frame.args[2], 'left')endfunction p.playerLinkRight(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    return flagPlayer(frame, frame.args[2], 'right')endfunction p.playerLinkNoFlag(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    return flagPlayer(frame, frame.args[2], 'none')endfunction p.main(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    local outputString = ""    local validCode = false    local player = templateArgs[2] -- player name passed as parameter    local rank, move    for _,u in pairs(data.alias) do  -- run through the list        if nameEqual(u[1], player) then        -- if code = passed parameter            validCode = true            break        end    end    -- if no match of code to country name, set category    for _,v in pairs(data.rankings) do        if nameEqual(v[1], player) then            rank = v[2]    -- get rank            break        end    end    if rank then -- no ranking found        for _,v in pairs(data.rankingsold) do            if nameEqual(v[1], player) then                move = v[2] - rank    -- get move from last ranking                break            else                move = 0 - rank            end        end    else        rank = 'NR'    end    local changeString = ""    if rank ~= 'NR' then        outputString = rank        if move < 0 and math.abs( move ) == math.abs( rank ) then -- new teams in ranking: move = -ranking            changeString = frame:expandTemplate{ title = 'new entry' }        elseif move == 0 then                                    -- if no change in ranking            changeString = frame:expandTemplate{ title = 'steady' }        elseif move < 0 then                                 --  if ranking down            changeString = frame:expandTemplate{ title = 'decrease' } .. ' ' .. math.abs(move)        elseif move > 0 then                                 -- if ranking up            changeString = frame:expandTemplate{ title = 'increase' } .. ' ' .. move        end        if not templateArgs['nochange'] or templateArgs['nochange'] == "" then            outputString = outputString .. ' ' .. changeString        end    else        outputString = outputString .. frame:expandTemplate{ title = 'Abbr', args = { "NR", "Not ranked"}  }        --{{Abbr|NR|Not ranked}}    end    if not templateArgs['nodate'] or templateArgs['nodate'] == "" then        outputString = outputString .. ' (' .. getDate() .. ')'    end    if templateArgs['par'] and templateArgs['par'] ~= '' then        outputString = '(' .. outputString .. ')'    end    if not templateArgs['noref'] or templateArgs['noref'] == "" then        outputString = outputString .. addReference(frame)    end    return outputStringendfunction p.rankOnly(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    local outputString = ""    local validCode = false    local player = templateArgs[2] -- player name passed as parameter    local rank ='NR'    local move    for _,u in pairs(data.alias) do  -- run through the list        if nameEqual(u[1], player) then        -- if code = passed parameter            validCode = true            break        end    end    -- if no match of code to country name, set category    for _,v in pairs(data.rankings) do        if nameEqual(v[1], player) then            rank = v[2]    -- get rank            break        end    end    return rankend--[[  outputs a table of the rankingscalled by list() or list2()positional parameters - |ranking|first|last the ranking to use, fist and last in tableother parameters: |style=               -- CSS styling|headerN= footerN=    -- displays header and footer rows with additional information|caption=             -- value of caption to display-- by default it generates a caption-- this can be suppressed with empty |caption=]]local function table(frame, ranking, first,last)    local styleString = ""    if templateArgs['style'] and templateArgs['style'] ~= "" then styleString = templateArgs['style'] end    local lastRank = 0    local selectCount = 0    local selectData = nil    local selectList = nil    -- column header customisation    local rankHeader = templateArgs['rank_header'] or "Rank"    local selectionHeader = templateArgs['selection_header'] or selectList or "Rank"    local teamHeader = templateArgs['team_header'] or "Player"    local pointsHeader = templateArgs['points_header'] or "Earnings"    local changeHeader = templateArgs['change_header'] or "Change"    local noChange = templateArgs['change_col'] or 1    --start table    local outputString = '{| class="wikitable" style="text-align:center;' .. styleString .. '"'    local tabletitle = data.labels['title']    -- add default or custom caption    local caption = tabletitle .. ' as of ' .. getDate() .. '.'    if templateArgs['caption'] and templateArgs['caption']  ~= "" then        caption = templateArgs['caption']        caption = p.replaceKeywords(caption)    end    outputString = outputString ..'\n|+' .. caption .. addReference(frame)    -- add header rows (logo, date of update etc)    local count = 0    local header = {}    local tableWidth = 4    if selectList then tableWidth = 5 end    while count < 5 do        count = count + 1        if templateArgs['header'..count] then            header[count] = templateArgs['header'..count]            header[count] = p.replaceKeywords( header[count])            outputString = outputString ..'\n|-\n| colspan="'.. tableWidth .. '" |' .. header[count]        end    end    -- add the add part of the table    local optionalColumn = ""    if selectList then        optionalColumn = '\n!' .. selectionHeader    end    outputString = outputString .. '\n|-' .. optionalColumn .. '\n!' .. rankHeader    if noChange == 1 then        outputString = outputString .. '\n!' .. changeHeader    end    outputString = outputString .. '\n!' .. teamHeader .. '\n!' .. pointsHeader    local change,player,plink = '', '', ''    --while i<last do    for k,v in pairs(data.rankings) do        --v[2] = tonumber(v[2])        if v[2] >= first and v[2] <= last then            plink = flagPlayer(frame, v[1], 'left')            local continue = true            if continue ==true  then                local rowString = '\n|-'                if selectList then                    local selectRank = selectCount                    if v[2]==lastRank then selectRank = selectCount -1 end -- only handles two at same rank                    rowString = rowString ..  '\n|' .. selectRank                    selectCount = selectCount + 1                end                rowString = rowString .. '\n|' .. v[2]  -- rank                lastRank = v[2]                local move = nil                for _,w in pairs(data.rankingsold) do                    if nameEqual(w[1], v[1]) then                        move = w[2] - lastRank    -- get move from last ranking                        break                    else                        move = 0 - lastRank                    end                end                if move < 0 and math.abs( move ) == math.abs( v[2] ) then -- new teams in ranking: move = -ranking                    change = frame:expandTemplate{ title = 'new entry' }                elseif move == 0 then                                    -- if no change in ranking                    change = frame:expandTemplate{ title = 'steady' }                elseif move < 0 then                                 --  if ranking down                    change = frame:expandTemplate{ title = 'decrease' } .. ' ' .. math.abs(move)                elseif move > 0 then                                 -- if ranking up                    change = frame:expandTemplate{ title = 'increase' } .. ' ' .. move                end                if noChange == 1 then                    rowString = rowString .. '||' .. change                end                rowString = rowString .. '\n|style="text-align:left"|' .. plink                local points = ""                if v[3] then points = v[3] end                rowString = rowString ..  '||' .. points       -- country for now, later points                outputString = outputString .. rowString            end        end    end    -- add footer rows    count = 0    local footer = {}    while count < 5 do        count = count + 1        if templateArgs['footer'..count] then            footer[count] = templateArgs['footer'..count]            footer[count] = p.replaceKeywords(footer[count])            outputString = outputString ..'\n|-\n| colspan="'.. tableWidth .. '" |' .. footer[count]        end    end    outputString = outputString .. "\n|}"    return outputStringendfunction p.replaceKeywords(keyword)    keyword =  string.gsub( keyword, "INSERT_UPDATE_DATE", getDate())    keyword =  string.gsub( keyword, "INSERT_LAST_DATE", getDate("LAST"))    keyword =  string.gsub( keyword, "INSERT_REFERENCE", addReference(mw.getCurrentFrame()))    return keywordend--[[ create a table of rankingsparameters:  |ranking=        -- ranking to display (e.g. FIFA World Rankings)|first= |last=   -- first and last ranking to display (defaults 1-10)]]function p.list(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    local ranking = frame.args[1]    local first, last = 1,10    first = tonumber(frame.args['2'])    last = tonumber(frame.args['3'])    return table(frame, ranking, first, last)endlocal function navlist(frame, ranking, first,last)    local lastRank = 0    local selectCount = 0    local selectData = nil    local selectList = nil    --start list    local outputString = '<ol start="' .. first .. '">'    local change,player,plink = '', '', ''    for k,v in pairs(data.rankings) do        if v[2] >= first and v[2] <= last then            plink = flagPlayer(frame, v[1], 'left')            local rowString = '<li>'  -- rank            lastRank = v[2]            rowString = rowString .. plink            if not templateArgs['nochange'] or templateArgs['nochange'] == "" then                local move = nil                for _,w in pairs(data.rankingsold) do                    if nameEqual(w[1], v[1]) then                        move = w[2] - lastRank    -- get move from last ranking                        break                    else                        move = 0 - lastRank                    end                end                if move < 0 and math.abs( move ) == math.abs( v[2] ) then -- new teams in ranking: move = -ranking                    change = frame:expandTemplate{ title = 'new entry' }                elseif move == 0 then                                    -- if no change in ranking                    change = frame:expandTemplate{ title = 'steady' }                elseif move < 0 then                                 --  if ranking down                    change = frame:expandTemplate{ title = 'decrease' }                elseif move > 0 then                                 -- if ranking up                    change = frame:expandTemplate{ title = 'increase' }                end                rowString = rowString .. ' ' .. change .. '</li>'            end            outputString = outputString .. '\n'.. rowString        end    end    outputString = outputString .. '</ol>'    return outputStringend------ Returns text list for players first,last for PDC top 20 navboxfunction p.nav(frame)    getArgs(frame) -- returns args table having checked for content    loadData(frame)    local ranking = frame.args[1]    local first, last = 1,10    first = tonumber(frame.args['2'])    last = tonumber(frame.args['3'])    return navlist(frame, ranking, first, last)endreturn p