Module to display ranking tables and individual rankings for ranked PDC darts players.

Module Data

Rankings Player library org code notes
PDC Rankings PDC Players rowspan=3 Template:N/a can use PDCFlag with no org parameter
PDC Pro Tour Rankings
PDC Euro Tour Rankings
BDO Rankings WDF Players WDF
WDF Rankings
BDO Women's Rankings WDF Women's
WDF Women's Rankings
CDC Rankings CDC Players CDC
DPA Rankings DPA and DPNZ Players DPA {{PDCFlag|Kyle Anderson|org=DPA}} displays AUS flag no matter what: Template:PDCFlag
{{DPAFlag|Kyle Anderson}} displays state flag: Template:DPAFlag
DPNZ Rankings DPNZ player list merged with DPA to reduce duplicates.
EADC Rankings EADC Players EADC
PDCNB Rankings PDCNB Players PDCNB
PDCAsia Rankings PDCAsia Players PDCAsia Orgs are interchangeable since they use a combined player database.
PDCChina Rankings PDCChina
PDJ Rankings PDJ
WSDT Rankings WSDT Players WSDT

Rankings can be updated above and will display for all OOM instances and rankings on individual pages.

Template for individual rankings

Rank & move w/date: {{Template:PDC Rankings}}

UsageEdit

  • List ranking from start ranking to end ranking:

{{#invoke:DartsRankings|list|PDC Rankings|first|last}}

Examples:

Player examples Code Output
PDC OOM Ranking for Michael van Gerwen {{#invoke:DartsRankings|main |PDC Rankings|Michael van Gerwen}} Lua error: expandTemplate: template "steady" does not exist.
PDC OOM Ranking for Peter Wright from template {{PDC Rankings|Peter Wright}} Template:PDC Rankings
WDF Ranking for Larry Butler from template {{WDF Rankings|Larry Butler|mdy=mdy}} Template:WDF Rankings
WDF Ranking for Fallon Sherrock from template {{WDF Women's Rankings|Fallon Sherrock}} Template:WDF Women's Rankings
PDC Ranking only for Gary Anderson from template {{PDC Rankings|Gary Anderson|nochange=1|nodate=1}} Template:PDC Rankings
Flag & link for José de Sousa from template {{PDCFlag|Jose de Sousa}} Template:PDCFlag
PDC Ranking & flag for Simon Whitlock from template {{PDCFlag|Simon Whitlock}} {{PDC Rankings|Simon Whitlock|nochange=1|nodate=1|par=1}} Template:PDCFlag Template:PDC Rankings
PDC Rankings table (1-5) {{#invoke:DartsRankings|list |PDC Rankings |1 |5 }} Lua error: expandTemplate: template "refn" does not exist.
PDC Rankings table (16-20) {{#invoke:DartsRankings|list |PDC Rankings |16 |20 }} Lua error: expandTemplate: template "refn" does not exist.
PDC Pro Tour table (1-5) {{#invoke:DartsRankings|list |PDC Pro Tour Rankings |1 |5 }} Lua error: expandTemplate: template "refn" does not exist.

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 tables
data.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 module

local 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'] end
end

local function loadData(frame)
    local source = frame.args[1] -- source of rankings e.g. PDC Rankings
    data = require('Module:DartsRankings/data/'.. source);
    if templateArgs['org'] then
        data = require('Module:DartsRankings/data/' .. templateArgs['org'] .. ' Rankings');
    end
end

local 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']
    end
end

local 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()
    }}
end

local 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)
    }}
end

local 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)
end

local function nameEqual(str1, str2)
    return string.lower(noAc(str1)):gsub("%W", "") == string.lower(noAc(str2)):gsub("%W", "")
end

function 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()
    --	end
end

local 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
        end
        if templateArgs['flag'] then
            flag = templateArgs['flag']
        end
    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 .. tcats
end

function p.playerLink(frame)
    getArgs(frame) -- returns args table having checked for content
    loadData(frame)
    return flagPlayer(frame, frame.args[2], 'left')
end

function p.playerLinkRight(frame)
    getArgs(frame) -- returns args table having checked for content
    loadData(frame)
    return flagPlayer(frame, frame.args[2], 'right')
end

function p.playerLinkNoFlag(frame)
    getArgs(frame) -- returns args table having checked for content
    loadData(frame)
    return flagPlayer(frame, frame.args[2], 'none')
end

function 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 outputString
end

function 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 rank
end

--[[  outputs a table of the rankings
called by list() or list2()
positional parameters - |ranking|first|last the ranking to use, fist and last in table
other 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 outputString
end

function 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 keyword
end

--[[ create a table of rankings
parameters:  |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)
end

local 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 outputString
end

---
--- Returns text list for players first,last for PDC top 20 navbox
function 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)
end

return p