Module:TopGoalscorers
Appearance
local p = {}
-- Hücre içi metinleri temizleme fonksiyonu (vikilink ve etiketleri sadeleştirir)
local function cleanText(text)
if not text then return '' end
text = text:gsub('%[%[[^%]|]*|([^%]]*)%]%]', '%1') -- [[Sayfa|Görünen]] -> Görünen
text = text:gsub('%[%[([^%]]*)%]%]', '%1') -- [[Sayfa]] -> Sayfa
text = text:gsub('{{[^}]*}}', '') -- Şablonları kaldır
text = text:gsub('<[^>]*>', '') -- HTML etiketlerini kaldır
text = text:gsub(' ', ' ')
text = mw.text.decode(text)
return mw.text.trim(text)
end
-- Hücre başındaki stil ve parametreleri temizleme (örneğin: style="..." | Değer)
local function getCellContent(cellStr)
cellStr = mw.text.trim(cellStr or '')
-- Şablon ve bağlantıların içindeki boru (|) işaretlerini maskele
local masked = cellStr:gsub('%b{}', function(s) return string.rep('_', #s) end)
masked = masked:gsub('%b[]', function(s) return string.rep('_', #s) end)
local pipePos = masked:find('|')
if pipePos then
return mw.text.trim(cellStr:sub(pipePos + 1))
else
return cellStr
end
end
-- Olay türünü (Normal Gol / Penaltı / Geçersiz) belirleme
local function getGoalEventType(cellText)
if not cellText then return 'invalid' end
local s = cellText:lower()
-- Kırmızı kart kontrolü
if s:find('sent off', 1, true) or s:find('sent_off', 1, true) or s:find('red_card', 1, true) or s:find('red card', 1, true) then
return 'invalid'
end
-- Kaçan penaltı kontrolü
if s:find('penmiss', 1, true) or s:find('pen_miss', 1, true) or s:find('penalty miss', 1, true) or s:find('penalty_miss', 1, true) or s:find('missed penalty', 1, true) or s:find('missed_penalty', 1, true) then
return 'invalid'
end
-- Kendi kalesine gol kontrolü
if s:find('o.g.', 1, true) or s:find('own goal', 1, true) or s:find('own_goal', 1, true) then
return 'invalid'
end
-- Sarı kart veya oyuncu değişikliği kontrolü
if s:find('yel', 1, true) or s:find('yellow', 1, true) or s:find('subon', 1, true) or s:find('suboff', 1, true) then
return 'invalid'
end
-- Penaltı golü
if s:find('pengoal', 1, true) or s:find('pen_goal', 1, true) or s:find('penalty goal', 1, true) or s:find('penalty_goal', 1, true) or s:find('goal|pen', 1, true) or s:find('pen|goal', 1, true) then
return 'penalty'
end
-- Normal gol ({{goal}}, goal, top ikonu veya boş hücre)
if s:find('goal', 1, true) or s:find('soccerball', 1, true) or s:find('football', 1, true) or mw.text.trim(cellText) == '' then
return 'goal'
end
return 'invalid'
end
-- Metin içerisindeki {| ve |} arasındaki tabloları hatasız ayıklama
local function extractTables(content)
local tables = {}
local pos = 1
local len = #content
while pos <= len do
local s, e = content:find('{|', pos, true)
if not s then break end
local depth = 1
local cur = e + 1
local tableEnd = nil
while cur <= len do
local nextOpen = content:find('{|', cur, true)
local nextClose = content:find('|}', cur, true)
if not nextClose then break end
if nextOpen and nextOpen < nextClose then
depth = depth + 1
cur = nextOpen + 2
else
depth = depth - 1
if depth == 0 then
tableEnd = nextClose
break
end
cur = nextClose + 2
end
end
if tableEnd then
table.insert(tables, content:sub(e + 1, tableEnd - 1))
pos = tableEnd + 2
else
pos = e + 1
end
end
return tables
end
-- Tabloyu satırlarına ayırma
local function extractRows(tableWikitext)
tableWikitext = tableWikitext:gsub('\r\n', '\n'):gsub('\r', '\n')
local firstNewline = tableWikitext:find('\n')
local body = firstNewline and tableWikitext:sub(firstNewline + 1) or tableWikitext
local rows = {}
local delimited = ('\n' .. body):gsub('\n%s*|%-[^\n]*', '\0')
for row in mw.text.gsplit(delimited, '\0', true) do
row = mw.text.trim(row)
if row ~= '' then
table.insert(rows, row)
end
end
return rows
end
-- Bir satır içerisindeki hücreleri (|| ve \n|) ayıklama
local function parseRowCells(rowStr)
local cells = {}
local lines = mw.text.split(rowStr, '\n')
for _, line in ipairs(lines) do
line = mw.text.trim(line)
if line ~= '' and not line:match('^!') then
if line:match('^|') then
line = line:sub(2)
end
local rawParts = mw.text.split(line, '||', true)
for _, rawPart in ipairs(rawParts) do
table.insert(cells, getCellContent(rawPart))
end
end
end
return cells
end
-- Wikitext'i işleyip golleri sayma
local function processWikitext(content, players, seenGoals)
if not content or content == '' then return end
local tables = extractTables(content)
for _, tableWikitext in ipairs(tables) do
local lowerTable = tableWikitext:lower()
-- JS'teki hariç tutulan tablolar
if not lowerTable:find('id%s*=%s*["\']?world%-cup%-table') and
not lowerTable:find('id%s*=%s*["\']?uefa%-table') and
not lowerTable:find('id%s*=%s*["\']?top%-scorers%-table') and
not lowerTable:find('id%s*=%s*["\']?table%-filter') then
local rows = extractRows(tableWikitext)
for _, row in ipairs(rows) do
local cells = parseRowCells(row)
local N = #cells
-- JS'teki en az 12 hücre şartı
if N >= 12 then
local playerRaw = cells[N]
local playerFlagRaw = cells[N - 1]
local scoringTeamRaw = cells[N - 2]
local eventRaw = cells[N - 3]
local minuteRaw = cells[N - 4]
local team2FlagRaw = cells[N - 5]
local team2Raw = cells[N - 6]
local team1Raw = cells[N - 8]
local team1FlagRaw = cells[N - 9]
local eventType = getGoalEventType(eventRaw)
if eventType == 'goal' or eventType == 'penalty' then
local playerName = cleanText(playerRaw)
local minuteText = cleanText(minuteRaw)
local team1Text = cleanText(team1Raw):lower()
local team2Text = cleanText(team2Raw):lower()
local scoreTeamText = cleanText(scoringTeamRaw):lower()
if playerName ~= '' then
local goalKey = (team1Text .. '|' .. team2Text .. '|' .. minuteText .. '|' .. playerName):lower()
if not seenGoals[goalKey] then
seenGoals[goalKey] = true
local teamFlag = team1FlagRaw
if scoreTeamText == team2Text or (team2Text ~= '' and scoreTeamText:find(team2Text, 1, true)) then
teamFlag = team2FlagRaw
elseif scoreTeamText == team1Text or (team1Text ~= '' and scoreTeamText:find(team1Text, 1, true)) then
teamFlag = team1FlagRaw
end
if not players[playerName] then
players[playerName] = {
name = playerName,
rawName = playerRaw,
teamRaw = scoringTeamRaw,
teamFlag = teamFlag,
flag = playerFlagRaw,
goals = 0,
penGoals = 0
}
end
players[playerName].goals = players[playerName].goals + 1
if eventType == 'penalty' then
players[playerName].penGoals = players[playerName].penGoals + 1
end
end
end
end
end
end
end
end
end
-- Ana fonksiyon
function p.render(frame)
local players = {}
local seenGoals = {}
local mainPageName = 'User:Ozicanbro'
if frame.args[1] and mw.text.trim(frame.args[1]) ~= '' then
mainPageName = mw.text.trim(frame.args[1])
end
local mainTitle = mw.title.new(mainPageName)
local mainContent = mainTitle and mainTitle:getContent() or ''
-- Ana sayfadaki varsa maçları tara
processWikitext(mainContent, players, seenGoals)
-- Sayfadaki tüm Event / Arşiv alt bağlantılarını otomatik tespit et (Büyük/küçük harf duyarsız)
local subpages = {}
local subpageList = {}
for link in mainContent:gmatch('%[%[%s*([^%]|]+)') do
link = mw.text.trim(link)
local lower = link:lower()
if (lower:find('user:ozicanbro/', 1, true) or lower:sub(1,1) == '/') and lower:find('event', 1, true) then
if lower:sub(1, 1) == '/' then
link = mainPageName .. link
end
if not subpages[link] then
subpages[link] = true
table.insert(subpageList, link)
end
end
end
-- Bulunan her bir arşiv sayfasını tara
for _, subpageName in ipairs(subpageList) do
local subTitle = mw.title.new(subpageName)
if subTitle and subTitle.exists and subpageName ~= mainPageName then
local subContent = subTitle:getContent()
processWikitext(subContent, players, seenGoals)
end
end
-- Oyuncuları toplayıp sırala
local sortedPlayers = {}
for _, player in pairs(players) do
table.insert(sortedPlayers, player)
end
if #sortedPlayers == 0 then
return '<div style="color:#777; font-style:italic; padding:10px;">TopGoalscorers: Toplam ' .. #subpageList .. ' arşiv sayfası tarandı ancak henüz listelenecek gol verisi bulunamadı.</div>'
end
table.sort(sortedPlayers, function(a, b)
if a.goals ~= b.goals then
return a.goals > b.goals
end
if a.penGoals ~= b.penGoals then
return a.penGoals > b.penGoals
end
return a.name < b.name
end)
-- Wikitable formatında çıktıyı üret
local out = {}
table.insert(out, '=== Top Goalscorers ===\n')
table.insert(out, '{| id="top-scorers-table" class="wikitable sortable" style="text-align:center; margin-top:20px; font-family:\'Trebuchet MS\', \'Lucida Sans Unicode\', \'Lucida Grande\', Arial, sans-serif;"')
table.insert(out, '|-\n! style="background:#005587; color:#fff;" | #')
table.insert(out, '! style="background:#005587; color:#fff;" | C')
table.insert(out, '! style="background:#005587; color:#fff;" | Player')
table.insert(out, '! style="background:#005587; color:#fff;" | C')
table.insert(out, '! style="background:#005587; color:#fff;" | Team')
table.insert(out, '! style="background:#005587; color:#fff;" | Goals')
table.insert(out, '! style="background:#005587; color:#fff;" | Pen Goals')
for i, pl in ipairs(sortedPlayers) do
table.insert(out, '|-\n| ' .. i ..
' || ' .. (pl.flag ~= '' and pl.flag or ' ') ..
' || style="text-align:center;" | ' .. pl.rawName ..
' || ' .. (pl.teamFlag ~= '' and pl.teamFlag or ' ') ..
' || style="text-align:center;" | ' .. pl.teamRaw ..
' || \'\'\'' .. pl.goals .. '\'\'\'' ..
' || \'\'\'' .. pl.penGoals .. '\'\'\''
)
end
table.insert(out, '|}')
return table.concat(out, '\n')
end
return p