Mô đun:Goalscorers
Giao diện
require('strict');local yesno = require('Module:Yesno')local p = {} local g = {} -- for parameters with global scope in this moduleg.goalscorers = {} -- table where selected and sorted players will be placeg.args = {}g.totalGoals = 0local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = ""function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">|_template=</code>' .. p.errorString .. '</span>'; endend-- 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 ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (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.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] endend--[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals()]]function p.main(frame) getArgs(frame) local dataTarget = g.args[1] 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 endfunction p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: 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 outputStringendfunction p.addIntroductorySentence() -- add introductory text local totalGoalString = "Tổng cộng có " .. g.totalGoals .. " bàn thắng đã ghi được." --[Đang|Đang|Đã|Đã] có #GOALS bàn thắng ghi được trong #MATCHES trận đấu, trung bình #GOALS/#MATCHES bàn thắng mỗi trận đấu. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['dmy']) local Date = require('Module:Date')._Date local pluralGoals = "" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "Đã" else text1 = "Đang" end else if dateUpdated == 'complete' then text1 = "Đã" else text1 = "Đang" end end local text = string.format("%s có %s bàn thắng%s ghi được", text1, mw.getLanguage('vi'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "" 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 < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" trong %d trận đấu%s, trung bình %."..precision.."g bàn thắng%s mỗi trận đấu", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "dmy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end local lang = mw.language.getContentLanguage() text = text .. " (tính đến ngày " .. lang:formatDate('j "tháng" n "năm" Y', Date(dateUpdated):text(dateFormat)) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString endfunction p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentenceendfunction 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 round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed 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 elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] 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.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdatedendfunction p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputStringendfunction 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 endfunction p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRoundend--[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u)]]--[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments]]function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- 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(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- 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=v[2], 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 true -- data collected for selected goalscorers end--[[ p.getRoundAndGroup()]]function p.getRoundAndGroup() 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 validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, groupend--[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]]function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) endend--[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column]]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 "không tìm thấy bảng" 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(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Nhập bàn thắng không hợp lệ cho cầu thủ " .. player return 0, "" endendfunction p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|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)endfunction p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Nhập tên không hợp lệ cho cầu thủ " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Nhập tên không hợp lệ cho cầu thủ " .. u or u[1] or "chưa biết" return "", "" endend--[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) 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 alphabeticallyfunction 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 = "trong trận gặp " -- 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 endfunction 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 endend--[[ 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)endfunction p.tabulateGoalscorers(frame, 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{| class="wikitable"' -- start table ..'\n|-' .. '\n!Hạng !! Cầu thủ !! Bàn thắng' -- 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(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. -- 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) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " cầu thủ" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("Không có bàn thắng nào khớp với tiêu chí được yêu cầu.") end endfunction p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " bàn" --if og == "OG" then if goalNumber < 0 then goalString = goalString .. " phản lưới nhà" end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- 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 bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- 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 ("Không có bàn thắng nào khớp với tiêu chí được yêu cầu.") endend-- output icon linked to national team pagefunction 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 {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon endend-- formatting of list under each number of goalsfunction p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns?endfunction p.closeList(frame) return '</div>'endfunction p.firstToUpper(str) return (str:gsub("^%l", string.upper))end-- handles parameters bold, further, extrafunction 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 .. " Các cầu thủ được thể hiện bằng chữ '''in đậm''' vẫn đang thi đấu tại giải." 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 textend-- count number of goals for data in templatefunction 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( "Nhập: " .. list .. "[" .. count .. "]") return totalGoals end--[[ use data supplied by template ]]--function p.list(frame)function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}|| {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|Đang|Đang}} |{{#ifexpr:{{{goals}}}=1|Đã|Đã}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|bàn thắng|bàn thắng}} ghi được{{#if:{{{players|}}}| bởi {{{players}}} {{#ifexpr:{{{players}}}=1|cầu thủ|cầu thủ khác nhau}} {{#if:{{{own goals|}}}| (với {{{own goals}}} trong số đó được ghi nhận là {{#ifexpr:{{{own goals}}}=1|bàn phản lưới nhà|bàn phản lưới nhà}})|}}|}} trong {{{matches}}} {{#ifexpr:{{{matches}}}=1|trận đấu|trận đấu}}, trung bình {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|bàn thắng|bàn thắng}} mỗi trận đấu {{#if:{{{updated|}}}| (tính đến ngày {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}|| }} Các cầu thủ được thể hiện bằng '''chữ đậm''' vẫn đang thi đấu ở giải. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}|| }}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "bàn thắng" if g.args['assists'] then statType = "kiến tạo" end if g.args['clean sheets'] then statType = "giữ sạch lưới" end local ongoing = g.args['ongoing'] local text1 = "" if g.args['lc'] then text1 = "" end local text2 = "Đã" if ongoing then text2 = "Đang" end local updateString = "" local averageString = "" local goalPlural = "" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "Đã" if ongoing then text2 = "Đang" end end local matchPlural = "" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" trong %d trận đấu%s, trung bình %."..precision.."g bàn thắng%s mỗi trận đấu", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" trong %d trận đấu%s, trung bình %.3g bàn thắng%s mỗi trận đấu", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = " (tính đến ngày " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s có %d %s%s ghi được%s", text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|kiến tạo|bàn thắng}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "bàn phản lưới nhà" end local plural = "" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "bàn thắng" or statType == "bàn phản lưới nhà" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("CẢNH BÁO. Không khớp giữa số bàn thắng được liệt kê (" .. totalGoals .. ") và tham số goals (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Nguồn: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Nguồn: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Nguồn: " .. source .. "</small>" end return text .. output .. footer .. sourceendreturn p