p.getPlayerSortName (playerName, sortName, countryName)
p.sortComment(comment)
p.getCountryName(country)
p.sortGoalscorers -- the main sort funtion  
--[=[ function p.preprocessSortName
stripp off wikitext and
force to lowercase
change special characters to standard letters
]=]
function p.preprocessSortName (name)
name = string.gsub(name, "%[%[", "") -- strip off and
name = string.gsub(name, "%]%]", "")
--name =string.lower(name) -- force lower case and return
name = mw.ustring.lower(name) -- use unicode function  
local specialChars = { -- list of special characters and replacement pairs
{ "ı", "i" } , { "İ", "i" } , { "ß", "ss" },
{ "ý", "y" } , { "ř", "r" } , { "ő", "o" },
{ "é", "e" } , { "è", "e" } , { "þ", "th" },
{ "ē", "e" } , { "ņ", "n" } , { "č", "c" },
{ "ū", "u" } , { "ž", "z" } , { "æ", "ae" },
{ "å", "a" } , { "ø", "o" } , { "ą", "a" },
{ "ń", "n" } , { "ł", "l" } , { "ã", "a" },
{ "ș", "s" } , { "š", "s" } , { "í", "i" },
{ "á", "a" } , { "ä", "a" } , { "ć", "c" },
{ "ç", "c" } , { "ğ", "g" } , { "ö", "o" },
{ "ë", "e" } , { "ú", "u" } , { "ó", "o" },
{ "ð", "d" } , { "ü", "u" } , { "ű", "u" },
{ "ā", "a" } , { "ī", "i" } , { "đ", "d" },
{ "ă", "a" } , { "â", "a" } , { "ż", "z" },
{ "ț", "t" } , { "ş", "s" } , { "ś", "s" },
{ "ǎ", "a" } , { "ě", "e" } , { "ů", "u" },
{ "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" },
{ "ï", "i" } , { "ź", "z" } , { "ô", "o" },
{ "ė", "e" } , { "ľ", "l" } , { "ģ", "g" },
{ "ļ", "l" } , { "ę", "e" } , { "ň", "n" },
{ "ò", "o" }
}
for k,v in pairs(specialChars) do -- replace special characters from supplied list
name = string.gsub(name, v[1], v[2])
end  
return name
end
--[[ return the name for sorting
return supplied alias name for sorting
otherwise
checks for pipe (redirect) and uses name after pipe
splits name into words
returns first name if only name (e.g. Nani)
otherwise returns name in format second_name [.. last name], firstname
function p.getPlayerSortName (playerName, sortName, countryName)  
--dewikify all names before sorting, also forces lowercase
playerName = p.preprocessSortName(playerName)
sortName = p.preprocessSortName(sortName)  
if sortName ~= "" then -- if we have a sort name supplied
return sortName -- then return it
end  
-- players from certain countries will use name in order supplied
local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" }
for k,v in pairs(noSort) do
if v == countryName then
return playerName
end
end  
-- else work it out from the supplied player name  
-- we don't want to test the name in a redirect, so get name after pipe if there is one
if string.find (playerName, "|") then -- test for redirect
local names = mw.text.split( playerName, "|")
playerName = names[2] -- get name after pipe
end  
local names = mw.text.split( playerName, " ") -- we don't want to sort on first name  
if #names == 1 then
return names[1] -- return name of single name player
else
-- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen
local name = names[2] -- set name to second name e.g. Bloggs or van
local i=3
while i <= #names do -- any addition names e.g. Bloggen
name= name .. names[i]
i=i+1
end
name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan  
return name -- sort on second name third name etc, first name
end  
end  
-- sort the list of countries alphabetically
function p.sortComment(comment)  
local items = mw.text.split( comment, ",") -- split comma-delimited list  
for k,v in pairs(items) do
items[k] = mw.text.trim(v) -- trim spaces and coe
end  
table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically  
local list = "against " -- construct the alphabetical list string
for i=1, #items do
local sep = ", " -- separator for comma-delimited list
if i==1 then sep = "" -- first word doesn't need comma
elseif i==#items then sep = " & " -- use "and" before last word
end
list = list .. sep .. items[i]
end
return list  
end
function p.getCountryName(country)  
if string.len(country) == 3 then -- if the country given as a three-letter code
local codes = require('Module:Goalscorers/data/Country codes')  
for k,v in pairs(codes.alias) do
if v[1] == country then
return v[2]
end
end
else
return country -- return the country name as is
end
end
-- sort goalscorers by goals, country and name
the sort first sorts by number of goals
when these are equal, it sorts by country
when these are equal, it sorts by name
Note: the name sort is on the first name
- a split of the name and sort on the last name is possible
- however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names
- would sort on second name be better  
function p.sortGoalscorers  
local sort_function = function( a,b )
if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b
return true
elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a
return false
else -- a.goals == b.goals -- primary sort tied,  
--return a.country < b.country -- resolve with secondary sort on 'country'
local country_a = p.getCountryName(a.country) -- sort on name of country, not the code
local country_b = p.getCountryName(b.country)  
if (country_a < country_b) then -- secondary sort on 'country'
return true
elseif (country_a > country_b) then -- secondary sort on 'country'
return false
else -- a.country == b.country -- secondary sort tied,  
--return a.player < b.player --resolve with tertiary sort on 'player' name  
local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting
local player_b = p.getPlayerSortName(b.player, b.alias, b.country)  
return player_a < player_b --
--[[]
--local test_a, test_b = a.player, b.player  
-- we don't want to test the name in a redirect, so get name after pipe if there is one
if string.find (a.player, "|") then -- test for redirect
local names = mw.text.split( a.player, "|")
test_a = names[2] -- get name after pipe
end
if string.find (b.player, "|") then
local names = mw.text.split( b.player, "|")
test_b = names[2]
end  
local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name
local names_b = mw.text.split( test_b, " ") -- so split names  
if not names_a[2] then names_a[2] = test_a end -- for players with one name
if not names_b[2] then names_b[2] = test_b end  
return names_a[2] < names_b[2] -- sort on second name
end
end
end  
table.sort(g.goalscorers, sort_function)  
end
function p.tabulateGoalscorers(, og)  
-- ==============output the lists of goalscorers by goal======================
local goalNumber = 1000
local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank
local rank = 1
local playerCount = 0
local rankCount = 0
local playerCells = ""
local firstplayerCell = ""  
local tableString = '\n{|' -- start table
..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers
if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header
for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers  
-- is the player active still?
local playerActive = false
if data.active_countries then
for k,v in pairs(data.active_countries) do
if v == u['country'] then
playerActive = true
break;
end
end
end
local _,roundStatus = p.getNumberMatches
if roundStatus == "complete" then playerActive = false end -- overrides active_countries  
-- wikitext for tablulated list
local goalscorerString = p.addLinkedIcon(, u['country']) -- linked flag icon
if playerActive and g.args['bold']~='no' then
goalscorerString = goalscorerString .. " **" .. u['player'] .. "**>" -- bolded name
else
goalscorerString = goalscorerString .. " " .. u['player'] -- name
end
goalscorerString = goalscorerString .. u['comment'] -- comment for o.g.  
-- we have a goalscorer
playerCount = playerCount + 1
rankCount = rankCount + 1  
if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals
-- need to generate code for the previous rowspan (if there is one)