Moduł:H2H
Wygląd
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:H2H/opis
local p = {}
-- =========================================================
-- Module:H2H
--
-- Historia bezpośrednich spotkań dwóch drużyn.
--
-- Drużyny są rozpoznawane po:
-- Mecze.nazwa_statystyki1
-- Mecze.nazwa_statystyki2
--
-- Dzięki temu zmiana sponsora / nazwy drużyny nie rozbija H2H.
--
-- Funkcje:
-- 1. bilans spotkań
-- 2. suma punktów
-- 3. wszystkie mecze
-- 4. najlepsi strzelcy
-- 5. trenerzy
-- 6. rekordy meczowe
-- 7. rekordy indywidualne
-- 8. serie zwycięstw / porażek
-- 9. kwartowe porównanie wyników
--
-- =========================================================
function p.main(frame)
-- =====================================================
-- PARAMETRY
-- =====================================================
local team1 =
mw.text.trim(frame.args.team1 or "")
local team2 =
mw.text.trim(frame.args.team2 or "")
if team1 == "" or team2 == "" then
return "'''Błąd:''' należy podać obie drużyny."
end
-- =====================================================
-- BEZPIECZEŃSTWO SQL
-- =====================================================
local function sql(value)
return mw.ustring.gsub(
value,
"'",
"''"
)
end
local t1 = sql(team1)
local t2 = sql(team2)
-- =====================================================
-- WARUNEK H2H DLA TABELI Mecze
--
-- WAŻNE:
-- tutaj używamy nazwa_statystyki.
-- Dzięki temu zmiana nazwy sponsorskiej nie rozbija H2H.
-- =====================================================
local whereMecze =
"(" ..
"M.nazwa_statystyki1='" .. t1 ..
"' AND M.nazwa_statystyki2='" .. t2 ..
"')" ..
" OR " ..
"(" ..
"M.nazwa_statystyki1='" .. t2 ..
"' AND M.nazwa_statystyki2='" .. t1 ..
"')"
-- =====================================================
-- FUNKCJE POMOCNICZE
-- =====================================================
local function number(value)
if value == nil or value == "" then
return 0
end
value = tostring(value)
value =
mw.ustring.gsub(
value,
"%s+",
""
)
return tonumber(value) or 0
end
local function parseScore(value)
if not value then
return nil
end
local a, b =
tostring(value):match(
"(%d+)%s*:%s*(%d+)"
)
if a and b then
return tonumber(a), tonumber(b)
end
return nil, nil
end
local function matchScore(row)
local g1 =
tonumber(row.gole1 or "")
local g2 =
tonumber(row.gole2 or "")
if g1 and g2 then
return g1, g2
end
return parseScore(row.wynik)
end
local function location(row)
local d1 =
row.nazwa_statystyki1 or ""
local d2 =
row.nazwa_statystyki2 or ""
if d1 == team1 then
return "dom"
end
if d2 == team1 then
return "wyjazd"
end
return nil
end
local function teamScore(row)
local g1, g2 =
matchScore(row)
if not g1 or not g2 then
return nil, nil
end
if location(row) == "dom" then
return g1, g2
end
return g2, g1
end
local function result(row)
local zdobyte, stracone =
teamScore(row)
if not zdobyte or not stracone then
return nil
end
if zdobyte > stracone then
return "W"
end
if zdobyte < stracone then
return "P"
end
return "R"
end
local function matchName(row)
local d1 =
row.druzyna1 or ""
local d2 =
row.druzyna2 or ""
local page =
row.strona_meczu or ""
local text =
d1 ..
" – " ..
d2
if page ~= "" then
return
"[[" ..
page ..
"|" ..
text ..
"]]"
end
return text
end
local function formatPlusMinus(value)
value =
number(value)
if value > 0 then
return "+" .. tostring(value)
end
return tostring(value)
end
-- =====================================================
-- POBRANIE MECZÓW
-- =====================================================
local fieldsMecze =
table.concat({
"M.id=mecz",
"M.data=data",
"M.sezon=sezon",
"M.druzyna1=druzyna1",
"M.druzyna2=druzyna2",
"M.nazwa_statystyki1=ns1",
"M.nazwa_statystyki2=ns2",
"M.gole1=gole1",
"M.gole2=gole2",
"M.wynik=wynik",
"M.kwart1=kwarta1",
"M.kwart2=kwarta2",
"M.kwart3=kwarta3",
"M.kwart4=kwarta4",
"M.dogrywka1=dogrywka1",
"M.dogrywka2=dogrywka2",
"M.hala=hala",
"M.widzowie=widzowie",
"M.sedziowie=sedziowie",
"M.strona_meczu=strona_meczu"
}, ",")
local mecze =
mw.ext.cargo.query(
"Mecze=M",
fieldsMecze,
{
where = whereMecze,
orderBy = "M.data ASC",
limit = 20000
}
)
if not mecze or #mecze == 0 then
return
"'''Brak wyników.'''"
end
-- =====================================================
-- BILANS
-- =====================================================
local liczbaMeczow = 0
local wygrane1 = 0
local wygrane2 = 0
local remisy = 0
local punkty1 = 0
local punkty2 = 0
for _, row in ipairs(mecze) do
local g1, g2 =
matchScore(row)
if g1 and g2 then
liczbaMeczow =
liczbaMeczow + 1
local d1 =
row.nazwa_statystyki1 or ""
local d2 =
row.nazwa_statystyki2 or ""
if d1 == team1 then
punkty1 =
punkty1 + g1
punkty2 =
punkty2 + g2
if g1 > g2 then
wygrane1 =
wygrane1 + 1
elseif g2 > g1 then
wygrane2 =
wygrane2 + 1
else
remisy =
remisy + 1
end
elseif d1 == team2 then
punkty1 =
punkty1 + g2
punkty2 =
punkty2 + g1
if g2 > g1 then
wygrane1 =
wygrane1 + 1
elseif g1 > g2 then
wygrane2 =
wygrane2 + 1
else
remisy =
remisy + 1
end
end
end
end
-- =====================================================
-- WYNIK PODSUMOWANIA
-- =====================================================
local output = {}
table.insert(
output,
"== Bilans bezpośrednich spotkań =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%; text-align:center;"'
)
table.insert(
output,
"! Drużyna !! Mecze !! Wygrane !! Remisy !! Porażki !! Punkty"
)
table.insert(
output,
"|-"
)
table.insert(
output,
"| '''" ..
team1 ..
"''' || " ..
liczbaMeczow ..
" || " ..
wygrane1 ..
" || " ..
remisy ..
" || " ..
wygrane2 ..
" || " ..
punkty1
)
table.insert(
output,
"|-"
)
table.insert(
output,
"| '''" ..
team2 ..
"''' || " ..
liczbaMeczow ..
" || " ..
wygrane2 ..
" || " ..
remisy ..
" || " ..
wygrane1 ..
" || " ..
punkty2
)
table.insert(
output,
"|}"
)
-- =====================================================
-- HISTORIA SPOTKAŃ
-- =====================================================
table.insert(
output,
""
)
table.insert(
output,
"== Historia spotkań =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable sortable" style="width:100%;"'
)
table.insert(
output,
"! Lp. !! Data !! Sezon !! Gospodarz !! Wynik !! Gość !! Hala"
)
local lp = 0
for i = #mecze, 1, -1 do
local row =
mecze[i]
local g1, g2 =
matchScore(row)
if g1 and g2 then
lp =
lp + 1
table.insert(
output,
"|-"
)
table.insert(
output,
"| " ..
lp ..
" || " ..
(row.data or "") ..
" || " ..
(row.sezon or "") ..
" || " ..
(row.druzyna1 or "") ..
" || '''" ..
g1 ..
":" ..
g2 ..
"''' || " ..
(row.druzyna2 or "") ..
" || " ..
(row.hala or "")
)
end
end
table.insert(
output,
"|}"
)
-- =====================================================
-- NAJLEPSI STRZELCY
-- =====================================================
local fieldsStrzelcy =
table.concat({
"U.zawodnik=zawodnik",
"U.druzyna=druzyna",
"SUM(U.gol)=punkty"
}, ",")
local strzelcy1 =
mw.ext.cargo.query(
"UdzialZawodnika=U,Mecze=M",
fieldsStrzelcy,
{
join =
"U.mecz=M.id",
where =
"(" ..
whereMecze ..
")" ..
" AND " ..
"(" ..
"(M.nazwa_statystyki1='" ..
t1 ..
"' AND U.druzyna=M.druzyna1)" ..
" OR " ..
"(M.nazwa_statystyki2='" ..
t1 ..
"' AND U.druzyna=M.druzyna2)" ..
")",
groupBy =
"U.zawodnik,U.druzyna",
orderBy =
"punkty DESC",
limit = 1000
}
)
local strzelcy2 =
mw.ext.cargo.query(
"UdzialZawodnika=U,Mecze=M",
fieldsStrzelcy,
{
join =
"U.mecz=M.id",
where =
"(" ..
whereMecze ..
")" ..
" AND " ..
"(" ..
"(M.nazwa_statystyki1='" ..
t2 ..
"' AND U.druzyna=M.druzyna1)" ..
" OR " ..
"(M.nazwa_statystyki2='" ..
t2 ..
"' AND U.druzyna=M.druzyna2)" ..
")",
groupBy =
"U.zawodnik,U.druzyna",
orderBy =
"punkty DESC",
limit = 1000
}
)
table.insert(
output,
""
)
table.insert(
output,
"== Najlepsi strzelcy rywalizacji =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%;"'
)
table.insert(
output,
"! " ..
team1 ..
" !! Punkty !! " ..
team2 ..
" !! Punkty"
)
local maxStrzelcy =
math.max(
strzelcy1 and #strzelcy1 or 0,
strzelcy2 and #strzelcy2 or 0
)
for i = 1, maxStrzelcy do
local s1 =
strzelcy1 and strzelcy1[i]
local s2 =
strzelcy2 and strzelcy2[i]
table.insert(
output,
"|-"
)
table.insert(
output,
"| " ..
(
s1
and
"[[" ..
s1.zawodnik ..
"]]"
or
""
) ..
" || " ..
(
s1
and
tostring(
number(s1.punkty)
)
or
""
) ..
" || " ..
(
s2
and
"[[" ..
s2.zawodnik ..
"]]"
or
""
) ..
" || " ..
(
s2
and
tostring(
number(s2.punkty)
)
or
""
)
)
end
table.insert(
output,
"|}"
)
-- =====================================================
-- TRENERZY
-- =====================================================
local fieldsTrenerzy =
table.concat({
"S.osoba=osoba",
"S.druzyna=druzyna",
"S.rola=rola"
}, ",")
local trenerzy =
mw.ext.cargo.query(
"SztabMeczu=S,Mecze=M",
fieldsTrenerzy,
{
join =
"S.mecz=M.id",
where =
"(" ..
whereMecze ..
")" ..
" AND " ..
"S.rola IN ('Trener','II trener')",
groupBy =
"S.osoba,S.druzyna,S.rola",
orderBy =
"S.osoba ASC",
limit = 5000
}
)
table.insert(
output,
""
)
table.insert(
output,
"== Trenerzy w historii rywalizacji =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable sortable" style="width:100%;"'
)
table.insert(
output,
"! Trener !! Drużyna !! Rola"
)
if trenerzy then
for _, row in ipairs(trenerzy) do
table.insert(
output,
"|-"
)
table.insert(
output,
"| [[" ..
(row.osoba or "") ..
"]] || " ..
(row.druzyna or "") ..
" || " ..
(row.rola or "")
)
end
end
table.insert(
output,
"|}"
)
-- =====================================================
-- REKORDY MECZOWE
-- =====================================================
local rekordMecz =
{
zwyciestwo =
{
dom = {},
wyjazd = {}
},
porazka =
{
dom = {},
wyjazd = {}
}
}
local function addMatchRecord(
list,
item,
value,
field
)
if #list == 0 then
item[field] =
value
table.insert(
list,
item
)
return
end
local current =
list[1][field]
if value > current then
item[field] =
value
list[1] =
item
elseif value == current then
item[field] =
value
table.insert(
list,
item
)
end
end
for _, row in ipairs(mecze) do
local zdobyte, stracone =
teamScore(row)
local miejsce =
location(row)
if zdobyte and stracone and miejsce then
local roznica =
zdobyte - stracone
local item =
{
tekst =
matchName(row),
wynik =
tostring(
row.gole1 or zdobyte
) ..
":" ..
tostring(
row.gole2 or stracone
),
roznica =
roznica
}
if roznica > 0 then
addMatchRecord(
rekordMecz.zwyciestwo[miejsce],
item,
roznica,
"wartosc"
)
elseif roznica < 0 then
addMatchRecord(
rekordMecz.porazka[miejsce],
item,
math.abs(roznica),
"wartosc"
)
end
end
end
local function formatMatchRecord(list)
if not list or #list == 0 then
return "—"
end
local out = {}
for _, item in ipairs(list) do
table.insert(
out,
item.tekst ..
" (" ..
item.wynik ..
", +" ..
tostring(
item.wartosc
) ..
")"
)
end
return table.concat(
out,
"<br>"
)
end
table.insert(
output,
""
)
table.insert(
output,
"== Rekordy meczowe =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%;"'
)
table.insert(
output,
"! Rekord !! 🏠 Dom !! ✈️ Wyjazd"
)
table.insert(
output,
"|-"
)
table.insert(
output,
"! 🏆 Najwyższe zwycięstwo || " ..
formatMatchRecord(
rekordMecz.zwyciestwo.dom
) ..
" || " ..
formatMatchRecord(
rekordMecz.zwyciestwo.wyjazd
)
)
table.insert(
output,
"|-"
)
table.insert(
output,
"! ❌ Najwyższa porażka || " ..
formatMatchRecord(
rekordMecz.porazka.dom
) ..
" || " ..
formatMatchRecord(
rekordMecz.porazka.wyjazd
)
)
table.insert(
output,
"|}"
)
-- =====================================================
-- REKORDY INDYWIDUALNE
-- =====================================================
local fieldsZaw =
table.concat({
"U.zawodnik=zawodnik",
"U.druzyna=druzyna_zawodnika",
"U.gol=gol",
"U.minuty=minuty",
"U.minuty_format=minuty_format",
"U.asysta=asysta",
"U.zbiorka=zbiorka",
"U.eval=eval",
"U.plusminus=plusminus",
"M.id=mecz",
"M.data=data",
"M.druzyna1=druzyna1",
"M.druzyna2=druzyna2",
"M.gole1=gole1",
"M.gole2=gole2",
"M.wynik=wynik",
"M.nazwa_statystyki1=ns1",
"M.nazwa_statystyki2=ns2",
"M.strona_meczu=strona_meczu"
}, ",")
local zawodnicy =
mw.ext.cargo.query(
"UdzialZawodnika=U,Mecze=M",
fieldsZaw,
{
join =
"U.mecz=M.id",
where =
"(" ..
whereMecze ..
")" ..
" AND U.minuty > 0",
orderBy =
"M.data ASC",
limit = 20000
}
)
local rekordy =
{
punkty =
{
dom = {},
wyjazd = {}
},
minuty =
{
dom = {},
wyjazd = {}
},
asysty =
{
dom = {},
wyjazd = {}
},
zbiorki =
{
dom = {},
wyjazd = {}
},
eval =
{
dom = {},
wyjazd = {}
},
plusminus =
{
dom = {},
wyjazd = {}
}
}
local function addPlayerRecord(
tabela,
miejsce,
wartosc,
item
)
local list =
tabela[miejsce]
if #list == 0 then
item.wartosc =
wartosc
table.insert(
list,
item
)
return
end
local current =
list[1].wartosc
if wartosc > current then
item.wartosc =
wartosc
tabela[miejsce] =
{
item
}
elseif wartosc == current then
item.wartosc =
wartosc
table.insert(
list,
item
)
end
end
if zawodnicy then
for _, row in ipairs(zawodnicy) do
local miejsce =
location(row)
if miejsce then
local item =
{
zawodnik =
row.zawodnik or "",
mecz =
row.mecz or "",
tekst =
matchName(row),
wynik =
row.wynik or "",
punkty =
number(row.gol),
minuty =
number(row.minuty),
minuty_format =
row.minuty_format or "",
asysty =
number(row.asysta),
zbiorki =
number(row.zbiorka),
eval =
number(row.eval),
plusminus =
number(row.plusminus)
}
addPlayerRecord(
rekordy.punkty,
miejsce,
item.punkty,
item
)
addPlayerRecord(
rekordy.minuty,
miejsce,
item.minuty,
item
)
addPlayerRecord(
rekordy.asysty,
miejsce,
item.asysty,
item
)
addPlayerRecord(
rekordy.zbiorki,
miejsce,
item.zbiorki,
item
)
addPlayerRecord(
rekordy.eval,
miejsce,
item.eval,
item
)
addPlayerRecord(
rekordy.plusminus,
miejsce,
item.plusminus,
item
)
end
end
end
local function formatPlayerRecord(
list,
typ
)
if not list or #list == 0 then
return "—"
end
local out = {}
for _, item in ipairs(list) do
local value = ""
if typ == "punkty" then
value =
tostring(item.punkty) ..
" pkt"
elseif typ == "minuty" then
value =
item.minuty_format
if value == "" then
value =
tostring(item.minuty)
end
value =
value ..
" min"
elseif typ == "asysty" then
value =
tostring(item.asysty) ..
" as."
elseif typ == "zbiorki" then
value =
tostring(item.zbiorki) ..
" zb."
elseif typ == "eval" then
value =
tostring(item.eval) ..
" EVAL"
elseif typ == "plusminus" then
value =
formatPlusMinus(
item.plusminus
) ..
" +/-"
end
table.insert(
out,
"[[" ..
item.zawodnik ..
"]] — " ..
value ..
"<br>" ..
item.tekst ..
" (" ..
item.wynik ..
")"
)
end
return table.concat(
out,
"<br>"
)
end
table.insert(
output,
""
)
table.insert(
output,
"== Rekordy indywidualne =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%;"'
)
table.insert(
output,
"! Rekord !! 🏠 Dom !! ✈️ Wyjazd"
)
local rekordyLista =
{
{
nazwa =
"🏀 Najwięcej punktów",
tabela =
rekordy.punkty,
typ =
"punkty"
},
{
nazwa =
"⏱️ Najwięcej minut",
tabela =
rekordy.minuty,
typ =
"minuty"
},
{
nazwa =
"🎯 Najwięcej asyst",
tabela =
rekordy.asysty,
typ =
"asysty"
},
{
nazwa =
"🏀 Najwięcej zbiórek",
tabela =
rekordy.zbiorki,
typ =
"zbiorki"
},
{
nazwa =
"⭐ Najwyższy EVAL",
tabela =
rekordy.eval,
typ =
"eval"
},
{
nazwa =
"➕ Najwyższy +/-",
tabela =
rekordy.plusminus,
typ =
"plusminus"
}
}
for _, rekord in ipairs(rekordyLista) do
table.insert(
output,
"|-"
)
table.insert(
output,
"! " ..
rekord.nazwa ..
" || " ..
formatPlayerRecord(
rekord.tabela.dom,
rekord.typ
) ..
" || " ..
formatPlayerRecord(
rekord.tabela.wyjazd,
rekord.typ
)
)
end
table.insert(
output,
"|}"
)
-- =====================================================
-- SERIE
-- =====================================================
local serie =
{
wszystkie =
{
W = 0,
P = 0,
maxW = 0,
maxP = 0
},
dom =
{
W = 0,
P = 0,
maxW = 0,
maxP = 0
},
wyjazd =
{
W = 0,
P = 0,
maxW = 0,
maxP = 0
}
}
local function updateSerie(
obj,
wynik
)
if wynik == "W" then
obj.W =
obj.W + 1
obj.P =
0
if obj.W > obj.maxW then
obj.maxW =
obj.W
end
elseif wynik == "P" then
obj.P =
obj.P + 1
obj.W =
0
if obj.P > obj.maxP then
obj.maxP =
obj.P
end
else
obj.W =
0
obj.P =
0
end
end
for _, row in ipairs(mecze) do
local wynik =
result(row)
local miejsce =
location(row)
if wynik then
updateSerie(
serie.wszystkie,
wynik
)
if miejsce == "dom" then
updateSerie(
serie.dom,
wynik
)
elseif miejsce == "wyjazd" then
updateSerie(
serie.wyjazd,
wynik
)
end
end
end
table.insert(
output,
""
)
table.insert(
output,
"== Serie zwycięstw i porażek =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%; text-align:center;"'
)
table.insert(
output,
"! Seria !! Wszystkie mecze !! 🏠 Dom !! ✈️ Wyjazd"
)
table.insert(
output,
"|-"
)
table.insert(
output,
"! 🔥 Najdłuższa seria zwycięstw || " ..
serie.wszystkie.maxW ..
" || " ..
serie.dom.maxW ..
" || " ..
serie.wyjazd.maxW
)
table.insert(
output,
"|-"
)
table.insert(
output,
"! 📉 Najdłuższa seria porażek || " ..
serie.wszystkie.maxP ..
" || " ..
serie.dom.maxP ..
" || " ..
serie.wyjazd.maxP
)
table.insert(
output,
"|}"
)
-- =====================================================
-- KWARTY A KOŃCOWY WYNIK
--
-- Nie korzystamy z dogrywka3.
-- Dzięki temu mecz z trzema dogrywkami nie powoduje
-- błędu "No field named dogrywka3".
--
-- Analizujemy wyłącznie kwarty 1-4.
-- =====================================================
local kwartowe =
{
[1] =
{
wygrana = 0,
porazka = 0,
remis = 0,
wszystkie = 0
},
[2] =
{
wygrana = 0,
porazka = 0,
remis = 0,
wszystkie = 0
},
[3] =
{
wygrana = 0,
porazka = 0,
remis = 0,
wszystkie = 0
},
[4] =
{
wygrana = 0,
porazka = 0,
remis = 0,
wszystkie = 0
}
}
local function quarterScore(value)
if not value or value == "" then
return nil, nil
end
return parseScore(value)
end
for _, row in ipairs(mecze) do
local final =
result(row)
if final == "W" or final == "P" then
for q = 1, 4 do
local value =
row["kwarta" .. q]
local a, b =
quarterScore(value)
if a and b then
local teamPoints
local opponentPoints
if location(row) == "dom" then
teamPoints = a
opponentPoints = b
elseif location(row) == "wyjazd" then
teamPoints = b
opponentPoints = a
end
if teamPoints and opponentPoints then
kwartowe[q].wszystkie =
kwartowe[q].wszystkie + 1
if final == "W" then
if teamPoints > opponentPoints then
kwartowe[q].wygrana =
kwartowe[q].wygrana + 1
elseif teamPoints < opponentPoints then
kwartowe[q].porazka =
kwartowe[q].porazka + 1
else
kwartowe[q].remis =
kwartowe[q].remis + 1
end
elseif final == "P" then
if teamPoints < opponentPoints then
kwartowe[q].wygrana =
kwartowe[q].wygrana + 1
elseif teamPoints > opponentPoints then
kwartowe[q].porazka =
kwartowe[q].porazka + 1
else
kwartowe[q].remis =
kwartowe[q].remis + 1
end
end
end
end
end
end
end
table.insert(
output,
""
)
table.insert(
output,
"== Wynik kwarty a końcowy wynik meczu =="
)
table.insert(
output,
""
)
table.insert(
output,
'{| class="wikitable" style="width:100%; text-align:center;"'
)
table.insert(
output,
"! Kwarta !! Mecz zakończony wygraną !! Mecz zakończony porażką !! Remis w kwarcie !! Wszystkie analizowane mecze"
)
for q = 1, 4 do
local data =
kwartowe[q]
table.insert(
output,
"|-"
)
table.insert(
output,
"! " ..
q ..
". kwarta || " ..
data.wygrana ..
" || " ..
data.porazka ..
" || " ..
data.remis ..
" || " ..
data.wszystkie
)
end
table.insert(
output,
"|}"
)
-- =====================================================
-- KONIEC
-- =====================================================
return table.concat(
output,
"\n"
)
end
return p