มอดูล:Goalscorers

require('Module:No globals');
local yesno = require('Module:Yesno')
local p = {} 
local g = {}         -- for parameters with global scope in this module
g.goalscorers = {}   -- table where selected and sorted players will be place
g.args = {}
g.totalGoals = 0
local data = {}      -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); 
p.errorString = ""
function p.error_msg()
	if p.errorString ~= "" then
		return 
	         -- '|_template='
	         .. p.errorString .. ;
	end
end
-- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying"
-- parameters containing data help in three tables
						data.rounds = {}   -- group, play-off
						data.goalscorers = {}    -- player, country, goals in each round)
						data.owngoalscorers = {} -- player, country, goals in each round)
						data.updated = {}        -- date of latest update (month, day, year)
					--
-- ############################ Parameter handing  ###############################
this section is currently unused
will be used to take check parameters set in template
local function getArgs(frame)
	local parents = mw.getCurrentFrame():getParent()
		
	for k,v in pairs(parents.args) do
		--check content
		if v and v ~= "" then
			g.argsk=mw.text.trim(v) --parents.argsk
		end
	end
	for k,v in pairs(frame.args) do
		--check content
		if v and v ~= "" then
			g.argsk= mw.text.trim(v)  --parents.argsk
		end
	end
	-- allow empty caption to blank default
	--if parents.args'caption' then templateArgs'caption' = parents.args'caption' end
end
-- ############################## Main function and other functions ######################
main() - simple output of the data in the module in list form
function p.main(frame)
getArgs(frame)
local dataTarget =  g.args1 or  g.args'data'
if dataTarget then
data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' 
	return p.useModuleData(frame)  -- data on goals taken from module subpage
else
	return p.useTemplateData(frame)  -- data on goals/assists taken from template
end

end
function p.useModuleData(frame)
--p.goalscorers = {} -- table where selected and sorted players will be place
g.totalGoals = 0
p.selectGoalscorers() -- selected goalscorers meeting round and group criteris

-- CHANGEe: append own goals to list  (data will now include goals and own goals (negative))  
p.selectGoalscorers("OG")    


p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country


local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence()
--                      .. ""              --TODO add intermediate heading?
--                      .. p._owngoals(frame)  -- output list of goalscorers

return p.error_msg() or outputString
end
function p.addIntroductorySentence()          -- add introductory text
	
	local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored."
	--There were were #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match.
	
	local matches, dateUpdated = p.getNumberMatches()
	local mdyFormat = yesno(g.args'mdy')
	
	local Date = require('Module:Date')._Date
	
	local pluralGoals = "s"
	local text1 = ""
	if g.totalGoals == 1 then
		pluralGoals = ""
		if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end
	else
		if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end
	end
	local text = string.format("มีการทำ %s %s ประตู%s", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals)
	
	local pluralMatches = "es"
	if matches==1 then pluralMatches = "" end
	if matches then
		local average = g.totalGoals/tonumber(matches)
		local precision = 3                        -- display d.dd (three significant disgits)
		if average ' .. footerSentence .. 
end
return footerSentence
end
function p.getNumberMatches()
	local matches = g.args'matches'
	local dateUpdated = data.updated'date' or "1700-01-01" --'complete' -- assume completed if missing

local round = g.args'round' or "all"    -- round =  all(empty)|group|playoffs
local group = g.args'group' or "all"     -- group =  all(empty), A,B,C etc  

local allGroupGames = 0
local latestGroupDate = "1800-01-01" 
if round == "all" or group == "all" then           -- count all the group games
	for k,v in pairs(data.updated.group) do
		allGroupGames = allGroupGames + v1
		if v2 ~= "complete" and v2 > latestGroupDate then latestGroupDate = v2 end -- update if later date
	end
	if latestGroupDate == "1800-01-01" then latestGroupDate = "complete"  end -- no dates so must be complete
end
	if round == "all" then                                       -- all rounds and goals
matches=0
for k,v in pairs(data.updated) do 
if k == "group" then
		matches = matches + allGroupGames
	     	if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then 
	     		dateUpdated = latestGroupDate                -- update if later date
	        end 
	else
		matches = matches + v1
		    if v2 ~= "complete" and v2 > dateUpdated then dateUpdated = v2 end -- update if later date
	end
	
end 
	elseif round == "group" then                                  -- group round only
	    if group == "all" then                            
		   matches = allGroupGames
		   dateUpdated = latestGroupDate  
		else                                                      -- single group only
matches     = data.updated.groupgroup1                 -- number matches
dateUpdated = data.updated.groupgroup2                 -- update date or completed
		end
	else                                                          -- any other round
matches     = data.updatedround1                           -- number matches
dateUpdated = data.updatedround2                           -- update date or completed
end 

if dateUpdated == "1700-01-01" then dateUpdated = "complete"  end -- no dates so must be complete
	return matches, dateUpdated
end
function p.owngoals(frame) -- need to check parameters if external call
getArgs(frame)
data = require('Module:Goalscorers/data/'.. g.args1) --or 'UEFA Euro 2016 qualifying' 
local outputString = p._owngoals(frame)
return  p.error_msg() or outputString
end
function p._owngoals(frame) -- internal call for own goals
--p.goalscorers = {} -- table where selected and sorted players will be place

p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris

p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country
return p.outputGoalscorers(frame, "OG") -- output list of goalscorers

end
-- select players meeting round and goal criteria
function p.selectGoalscorers(og)
--data = require('Module:Goalscorers/data/'.. g.args1) --or 'UEFA Euro 2016 qualifying' 

local goalMinimum = tonumber(g.args'minimum') or -5  -- assume 5 own goals is maximum

-- select all players with goals totals for appropriate rounds
local round = g.args'round' or "all"    -- round =  all(empty)|group|playoffs
local group = g.args'group' or "all"     -- group =  all(empty), A,B,C etc  
local goalsCol = p.getGoalsCol(round) -- 4          -- first column for goals
--local groupCol =  3         -- default column for group
if round then
--	goalsCol = data.roundsround or data.rounds1 or 4  -- get column containing goals for that round or first round listed if all
end
--groupCol = data.groupround or 3    -- get column containing goals for that round

-- select players who have scored in rounds/groups requested
local goalscorerData = data.goalscorers
if og == "OG" then goalscorerData = data.owngoalscorers end

for k,v in pairs(goalscorerData) do
local goals, comment = 0, ""                         -- goals > 0 is the flag to include the player
local playerName, playerAlias = p.getPlayer(v1)                -- player name
local goalsByRound, commentByRound = 0, ""
		if round == "all" then                                                   -- all rounds and goals
		    --local i = 4
		    for i = goalsCol, #v, 1 do        --or while i = goalMinimum and goals ~= 0 then
	    	   if comment ~= "" then 
	    	   	  if og == "OG" then 
	    	   	  	comment = ' (' .. p.sortComment(comment) .. ')' 
	    	   	  else
	    	   	  	comment =  .. comment ..    -- no parenthesis when using notes
	    	      end
	    	   end
	    	   
	    	   if og == "OG" then goals = -goals end  -- make owngoals negative numbers
	    	   
			   g.goalscorers#g.goalscorers+1 = { player=playerName, alias=playerAlias,
			   	                                   country=v2, 
			   	                                   goals=goals, 
			   	                                   comment=p.parseComment(comment)}
			   --g.totalGoals = g.totalGoals + math.abs(goals)    -- increment total goal counter	                                  
	    end
	    g.totalGoals = g.totalGoals + math.abs(goals)    -- increment total goal counter
end
--return p.goalscorers -- it is available anyway
end
-- get column for round or first round listed if "all" 
-allows group column to be omitted from player table when group table provided 
function p.getGoalsCol(round)

if round == "all" then  -- if all need column of first round
for k,v in pairs(data.rounds) do
	  return v; -- return the first one
end
end
return  data.roundsround or 4  -- get column containing goals for that round or first round listed if all
end
-- get group from group table or from player table     
function p.getGroup(country, possibleGroup)             -- row contain player name, country code, group if given, goals
	if data.groups then
for k,v in pairs(data.groups)  do  -- iterate through the groups
--local = gotGroup = false
		for j,u in pairs(v) do       -- for each group
		   if u == country then
		   	  return k
		   end
		end
	end
return "no group found"
else 
	return possibleGroup -- no group table, so assume column three contains the group
	end
	
end
-- get number of goals and any associated comment
the goals can be a single number (the usual case)
or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents }
- if the entry is a table, we want the first entry (a number) and the second (comment string)
- otherwise, if a number, we just want the number and an empty string
function p.getGoals (u, player)
	if type(u) == 'table' and type(u1) == 'number' then
		return u1, u2            -- return number of goals, comment
	elseif type(u) == 'number' then
		return u, ""                 -- return number of goals, empty string
	else
		p.errorString = p.errorString .. " Invalid goals entry for player " .. player
		return 0, ""
	end
end
function p.parseComment(comment)
	
	local frame = mw.getCurrentFrame()
	-- we have something like "name=goals"
	if string.find(comment, "efn" , 1 , true ) then       -- if we have a comment with a note
		g.notes = true                                    -- set flag
	end
	
	
	return frame:preprocess(comment)
end
function p.getPlayer(u)
	if type(u) == 'table'  then
		if type(u1) == 'string' and type(u2) == 'string' then
			--if #u2 >1 then 
				p.errorString = p.errorString  .. "\n\nWe have u1=" .. u1 .. " and u2=" .. u2
			end
			return u1, u2            -- return player name, player sorting alias
		else
			p.errorString = p.errorString .. " Invalid name entry for player " .. u1 .. ", " .. u2 
			return "", ""     --TODO errroer
		end
	elseif type(u) == 'string' then
		return u, ""                 -- return player name
	else
		p.errorString = p.errorString .. " Invalid name entry for player " .. u or u1 or "unknown"
		return "", ""
	end
end
--= 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, v1, v2)
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 = names2                               -- 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 names1                             -- 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 = names2                   -- set name to second name e.g. Bloggs or van
		local i=3
		while i  b.goals) then                -- primary sort on 'goals' -> a before b
		        return true
		    elseif (a.goals  b before a
		        return false
		    else -- a.goals == b.goals 		           -- primary sort tied, 
		        
		        --return a.country  country_b) then    -- secondary sort on 'country'
			        return false
			    else -- a.country == b.country 		   -- secondary sort tied, 
			        --return a.player ' .. p.addLinkedIcon(frame, 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.
	                              
	outputString = outputString .. goalscorerString   --  .. " " .. tostring(u'goals')
end -- reached end of list of goalscorers
	if outputString ~= "" then
	    outputString = outputString .. p.closeList(frame)
		return outputString
	else
		return ("No goals matching requested criteria.")
	end
end
-- output icon linked to national team page
function p.addLinkedIcon(frame, country)
	local icon = data.templates'flag_icon_linked'         -- fbicon etc set in data module
	local level = data.templates'youth_level'  or ""           -- parameter for youth level, ie under-21
-- equivalent to  country     
local flagVariant = ""
if data.templates.flagvar and data.templates.flagvarcountry then
	flagVariant = data.templates.flagvarcountry 
end
if level ~= "" then 
	return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } }   
else
	return frame:expandTemplate{ title = icon , args = { country, flagVariant } }     -- flag icon
end
end
-- formatting of list under each number of goals
function p.openList(frame,og)
	return mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Div col/styles.css' }
	} ..  -- perhaps add "column-count:3;"" to limit max number of columns?
end
function p.closeList(frame)
return 
end
function p.firstToUpper(str)
return (str:gsub("^%l", string.upper))
end
-- handles parameters bold, further, extra
function p.addAdditionHeaderText(text, dateUpdated)
if g.args'inlineref' then
	text = text .. g.args'inlineref'
end
if g.args'bold' and g.args'bold'~='no' then
	text = text .. " Players highlighted in bold are still active in the competition."
end
if g.args'further' then
	if text ~= "" then text = text .. " " end
	text = text .. g.args'further'
end
if g.args'extra' then
	text = text .. "\n\n" .. g.args'extra'
end
return text
end
-- count number of goals for data in template
function p.countGoals(list, number, totalGoals)
local split = mw.text.split( list, "\n", true )  -- split the list for number of goals scorers with N goals
local count = #split  * math.abs(number)         -- calculate number of goals (including own goals)
totalGoals = totalGoals + count

--mw.addWarning( "Entry: " .. list  .. "" .. count .. "")
	return totalGoals 
end
-- use data supplied by template 
--function p.list(frame)
function p.useTemplateData(frame)
--getArgs(frame)

--