Module:SportsRankings

require('strict');

local p = {}

local error_msg = ' missing or empty ';

-- 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 = {}      -- alias list (country code, country name [=key])					--

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 if frame.args['caption'] then templateArgs['caption'] = frame.args['caption'] end end

local function loadData(frame) local source = frame.args[1] -- source of rankings e.g. FIFA World Rankings data = require('Module:SportsRankings/data/'.. source); 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. "FIFA World Rankings", text .. addCiteWeb(frame) }}

end

-- movement |date function p.main(frame) getArgs(frame) -- returns args table having checked for content loadData(frame) local outputString = "" local validCode = false local country = templateArgs[2] -- country name or county code passed as parameter local rank, move if string.len( country) == 3 then -- if we have a three letter country code for _,u in pairs(data.alias) do -- run through alias list { 3-letter code, country name } if u[1]==country then       -- if code = passed parameter country = u[2]          -- set country name as key for ranking table validCode = true break end end -- if no match of code to country name, set category if not validCode then outputString="" .. outputString end end for _,v in pairs(data.rankings) do   	if v[1]==country then rank = v[2]   -- get rank move = v[3]   -- get move from last ranking break end end if not rank then -- no ranking found (do we want a tracking for no rank found?) rank = 'NR' --outputString="" .. outputString --outputString="" .. outputString end if rank ~= 'NR' then outputString = outputString .. ' ' .. rank .. ' '		if move < 0 and math.abs( move ) == math.abs( rank ) then -- new teams in ranking: move = -ranking outputString = outputString .. frame:expandTemplate{ title = 'new entry' } elseif move == 0 then                                   -- if no change in ranking outputString = outputString .. frame:expandTemplate{ title = 'steady' } elseif move < 0 then                                --  if ranking down outputString = outputString .. frame:expandTemplate{ title = 'decrease' } if move ~= -1000 then outputString = outputString .. ' ' .. math.abs(move) end elseif move > 0 then                                -- if ranking up outputString = outputString .. frame:expandTemplate{ title = 'increase' } if move ~= 1000 then outputString = outputString .. ' ' .. move end end else outputString = outputString .. frame:expandTemplate{ title = 'Abbr', args = { "NR", "Not ranked"} } --	NR end outputString = outputString .. ' (' .. getDate .. ')' outputString = outputString .. addReference(frame) return outputString end

--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 sublist2 = { "ENG", "SCO", "WAL", "IRE", "NIR", "FRA", "England", "France", "Germany" } local sublist3 = { "AFG","AUS","BAN","BHR","BHU","BRU","CAM","CHN","GUM","HKG","IDN","IND","IRN","IRQ","JOR", "JPN","KGZ","KOR","KSA","KUW","LAO","LIB","MAC","MAS","MDV","MNG","MYA","NEP","OMA","PAK", "PHI","PLE","PRK","QAT","SIN","SRI","SYR","THA","TJK","TKM","TLS","TPE","UAE","UZB","VIE", "YEM" } local lastRank = 0 local selectCount = 0 local selectData = nil local selectList = nil if templateArgs['select'] then if data.confederation[templateArgs['select']] then selectList = templateArgs['select'] selectData = data.confederation[selectList] selectCount = 1 end end -- 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 "Team" local pointsHeader = templateArgs['points_header'] or "Points" local changeHeader = templateArgs['change_header'] or "Change" --start table local outputString = '{| class="wikitable" style="text-align:center;' .. styleString .. '"' -- add default or custom caption local caption = ranking .. ' as of ' .. getDate .. '.'   if templateArgs['caption'] and templateArgs['caption']  ~= "" then caption = templateArgs['caption'] caption = p.replaceKeywords(caption) end if not (templateArgs['caption'] and templateArgs['caption'] == "") then outputString = outputString .. '\n|+' .. caption .. addReference(frame) end -- 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 .. '\n!' .. changeHeader .. '\n!' .. teamHeader .. '\n!' .. pointsHeader local change,code = ,  --while i= first and v[2] <= last then

for _,u in pairs(data.alias) do -- get country code from name if u[2]==v[1] then code = u[1]   -- if alias (country code) then use country name as key break end end local continue = true if selectList then                -- select from list continue = false for _,u in pairs(selectData) do	  				if u == v[1] or u == code then continue = true break end end end 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 = v[3] 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 rowString = rowString .. '||' .. change --		  for _,u in pairs(data.alias) do			    	if u[2]==v[1] then 			       		code = u[1]    -- if alias (country code) then use country name as key			       		break			       	end			    end --TODO reorganise the following with better logic -- template to display flag icon and team link (e.g. fb, fbw, bk, ih)			      e.g.  "FIFA World Rankings" = 'fb', "FIFA Women's World Rankings" 'fbw',			             "FIBA World Rankings" = 'bk', "IIHF World Ranking"  = 'ih'  			       tries with country code, then if error, tried with country name local countryTemplate = data.templates['flagged_team_link'] local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[code] then flagVariant = data.templates.flagvar[code] end local flagCode = code if data.templates.flag_codes then flagCode = data.templates.flag_codes[code] or code end local countryIconString = frame:expandTemplate{ title = countryTemplate, args = {flagCode, flagVariant} }   -- country

local _,test = string.gsub( countryIconString, "Template:Country data", "") -- page does not exist if test == 1 then -- if error try country name countryIconString = frame:expandTemplate{ title = countryTemplate, args = {v[1]} } --countryIconString = "testing" else -- countryIconString = "exists" end rowString = rowString .. '\n|style="text-align:left"|' .. countryIconString local points = "" if v[4] then points = v[4] 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")) if string.find(keyword, "INSERT_REFERENCE") then keyword = string.gsub( keyword, "INSERT_REFERENCE", addReference(mw.getCurrentFrame)) end return keyword end

--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 = tonumber(frame.args['2']) or 1 local last = tonumber(frame.args['3']) or 10 return table(frame, ranking, first, last) end

--ranking |country |span                                                  -- ranking - the ranking to display (e.g. FIFA World Rankings)                                              -- country - country table is centred around                                              -- span=   - rows to display above and below country function p.list2(frame)

getArgs(frame) -- returns args table having checked for content loadData(frame) local ranking = frame.args[1] local first, last = 1,10 local country = frame.args[2]          -- name or code of country to center table around local span = frame.args[3] or 2        -- number of rows to display above and below country (default:2) if string.len(country) == 3 then       -- if three letter country code for _,u in pairs(data.alias) do		   	if u[1]==country then country = u[2]         -- if country code then use country name break end end end for k,v in pairs(data.rankings) do     -- find position of country in rankings if v[1] == country then first = v[2]-span last = v[2]+span end end return table(frame, ranking, first, last) end

return p