Przejdź do zawartości

Moduł:Rekordy sezon

Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Rekordy sezon/opis

local p = {}

-- =========================================================
-- Module:Rekordy_sezon
--
-- Jeden moduł dla wielu dyscyplin.
--
-- Wywołanie:
--
-- {{#invoke:Rekordy_sezon|main
--  |sezon=2026/2027
--  |druzyna=Lech Poznań
--  |dyscyplina=piłka nożna
-- }}
--
-- lub:
--
-- {{#invoke:Rekordy_sezon|main
--  |sezon=2026/2027
--  |druzyna=Enea Basket Poznań
--  |dyscyplina=koszykówka
-- }}
--
-- Opcjonalnie:
--
-- |rozgrywki=Ekstraklasa
--
-- =========================================================


function p.main(frame)

    -- =====================================================
    -- PARAMETRY
    -- =====================================================

    local sezon =
        mw.text.trim(frame.args.sezon or "")

    local druzyna =
        mw.text.trim(frame.args.druzyna or "")

    local dyscyplina =
        mw.text.trim(frame.args.dyscyplina or "koszykówka")

    local rozgrywki =
        mw.text.trim(frame.args.rozgrywki or "")


    if sezon == "" then
        return "'''Błąd:''' nie podano sezonu."
    end

    if druzyna == "" then
        return "'''Błąd:''' nie podano drużyny."
    end


    -- =====================================================
    -- ESCAPOWANIE SQL
    -- =====================================================

    local sezonSQL =
        mw.ustring.gsub(sezon, "'", "''")

    local druzynaSQL =
        mw.ustring.gsub(druzyna, "'", "''")

    local rozgrywkiSQL =
        mw.ustring.gsub(rozgrywki, "'", "''")


    -- =====================================================
    -- FUNKCJE POMOCNICZE
    -- =====================================================

    local function liczba(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 miejsceMeczu(row)

        local d1 =
            row.druzyna1 or ""

        local d2 =
            row.druzyna2 or ""

        if d1 == druzyna then
            return "dom"
        end

        if d2 == druzyna then
            return "wyjazd"
        end

        return nil

    end


    local function wynikMeczu(row)

        local g1 =
            tonumber(row.gole1 or "")

        local g2 =
            tonumber(row.gole2 or "")

        if g1 and g2 then
            return g1, g2
        end

        local wynik =
            row.wynik or ""

        local a, b =
            wynik:match(
                "(%d+)%s*:%s*(%d+)"
            )

        if a and b then
            return tonumber(a), tonumber(b)
        end

        return nil, nil

    end


    local function nazwaMeczu(row)

        local d1 =
            row.druzyna1 or ""

        local d2 =
            row.druzyna2 or ""

        local strona =
            row.strona_meczu or ""

        local tekst =
            d1 .. " – " .. d2

        if strona ~= "" then

            return "[[" ..
                strona ..
                "|" ..
                tekst ..
                "]]"

        end

        return tekst

    end


    local function kopiuj(item)

        local nowy = {}

        for k, v in pairs(item) do
            nowy[k] = v
        end

        return nowy

    end


    local function dodajRekord(
        tabela,
        miejsce,
        wartosc,
        item
    )

        local lista =
            tabela[miejsce]

        local nowy =
            kopiuj(item)

        nowy.wartosc =
            wartosc

        if #lista == 0 then

            table.insert(
                lista,
                nowy
            )

            return

        end

        local obecna =
            lista[1].wartosc

        if wartosc > obecna then

            tabela[miejsce] = {
                nowy
            }

        elseif wartosc == obecna then

            table.insert(
                lista,
                nowy
            )

        end

    end


    -- =====================================================
    -- WYBÓR DYSCYPLINY
    -- =====================================================

    if mw.ustring.lower(dyscyplina)
        == "piłka nożna"
        or
        mw.ustring.lower(dyscyplina)
        == "pilka nozna"
    then

        return p.pilka(
            sezon,
            druzyna,
            sezonSQL,
            druzynaSQL,
            rozgrywki,
            rozgrywkiSQL
        )

    end


    -- Domyślnie koszykówka
    return p.koszykowka(
        sezon,
        druzyna,
        sezonSQL,
        druzynaSQL,
        rozgrywki,
        rozgrywkiSQL
    )

end



-- =========================================================
-- =========================================================
-- KOSZYKÓWKA
-- =========================================================
-- =========================================================


function p.koszykowka(
    sezon,
    druzyna,
    sezonSQL,
    druzynaSQL,
    rozgrywki,
    rozgrywkiSQL
)


    -- =====================================================
    -- POBRANIE MECZÓW
    -- =====================================================

    local fieldsMecze =
        table.concat({

            "Mecze.id=mecz",
            "Mecze.data=data",
            "Mecze.sezon=sezon",
            "Mecze.rozgrywki=rozgrywki",
            "Mecze.druzyna1=druzyna1",
            "Mecze.druzyna2=druzyna2",
            "Mecze.gole1=gole1",
            "Mecze.gole2=gole2",
            "Mecze.wynik=wynik",
            "Mecze.strona_meczu=strona_meczu"

        }, ",")


    local whereMecze =
        "(Mecze.druzyna1='" ..
        druzynaSQL ..
        "' OR Mecze.druzyna2='" ..
        druzynaSQL ..
        "')" ..
        " AND Mecze.sezon='" ..
        sezonSQL ..
        "'"


    if rozgrywki ~= "" then

        whereMecze =
            whereMecze ..
            " AND Mecze.rozgrywki='" ..
            rozgrywkiSQL ..
            "'"

    end


    local mecze =
        mw.ext.cargo.query(
            "Mecze",
            fieldsMecze,
            {
                where = whereMecze,
                orderBy = "Mecze.data ASC",
                limit = 5000
            }
        )


    if not mecze or #mecze == 0 then

        return
            "''Brak wprowadzonych meczów dla tej drużyny w podanym sezonie.''"

    end


    -- =====================================================
    -- REKORDY MECZOWE
    -- =====================================================

    local najwyzszeZwyciestwo = {
        dom = {},
        wyjazd = {}
    }

    local najwyzszaPorazka = {
        dom = {},
        wyjazd = {}
    }


    for _, row in ipairs(mecze) do

        local g1, g2 =
            wynikMeczu(row)

        local miejsce =
            miejsceMeczu(row)

        if g1 and g2 and miejsce then

            local zdobyte
            local stracone

            if miejsce == "dom" then

                zdobyte = g1
                stracone = g2

            else

                zdobyte = g2
                stracone = g1

            end

            local roznica =
                zdobyte - stracone


            local item = {

                mecz = row.mecz or "",
                data = row.data or "",
                miejsce = miejsce,

                zdobyte = zdobyte,
                stracone = stracone,
                roznica = roznica,

                tekst =
                    nazwaMeczu(row),

                wynik =
                    tostring(g1) ..
                    ":" ..
                    tostring(g2)

            }


            if roznica > 0 then

                local lista =
                    najwyzszeZwyciestwo[miejsce]

                if #lista == 0 then

                    table.insert(
                        lista,
                        item
                    )

                elseif roznica >
                    lista[1].roznica then

                    najwyzszeZwyciestwo[miejsce] = {
                        item
                    }

                elseif roznica ==
                    lista[1].roznica then

                    table.insert(
                        lista,
                        item
                    )

                end

            end


            if roznica < 0 then

                local przegrana =
                    math.abs(roznica)

                item.przegrana =
                    przegrana

                local lista =
                    najwyzszaPorazka[miejsce]

                if #lista == 0 then

                    table.insert(
                        lista,
                        item
                    )

                elseif przegrana >
                    lista[1].przegrana then

                    najwyzszaPorazka[miejsce] = {
                        item
                    }

                elseif przegrana ==
                    lista[1].przegrana then

                    table.insert(
                        lista,
                        item
                    )

                end

            end

        end

    end


    -- =====================================================
    -- STATYSTYKI ZAWODNIKÓW
    -- =====================================================

    local fieldsZawodnicy =
        table.concat({

            "UdzialZawodnika.zawodnik=zawodnik",
            "UdzialZawodnika.druzyna=druzyna_zawodnika",
            "UdzialZawodnika.gol=gol",
            "UdzialZawodnika.minuty=minuty",
            "UdzialZawodnika.minuty_format=minuty_format",
            "UdzialZawodnika.asysta=asysta",
            "UdzialZawodnika.zbiorka=zbiorka",
            "UdzialZawodnika.eval=eval",
            "UdzialZawodnika.plusminus=plusminus",

            "Mecze.id=mecz",
            "Mecze.data=data",
            "Mecze.rozgrywki=rozgrywki",
            "Mecze.druzyna1=druzyna1",
            "Mecze.druzyna2=druzyna2",
            "Mecze.gole1=gole1",
            "Mecze.gole2=gole2",
            "Mecze.wynik=wynik",
            "Mecze.strona_meczu=strona_meczu"

        }, ",")


    local whereZawodnicy =
        "UdzialZawodnika.druzyna='" ..
        druzynaSQL ..
        "'" ..
        " AND Mecze.sezon='" ..
        sezonSQL ..
        "'" ..
        " AND UdzialZawodnika.minuty > 0"


    if rozgrywki ~= "" then

        whereZawodnicy =
            whereZawodnicy ..
            " AND Mecze.rozgrywki='" ..
            rozgrywkiSQL ..
            "'"

    end


    local zawodnicy =
        mw.ext.cargo.query(
            "UdzialZawodnika,Mecze",
            fieldsZawodnicy,
            {
                join =
                    "UdzialZawodnika.mecz=Mecze.id",

                where =
                    whereZawodnicy,

                orderBy =
                    "Mecze.data ASC",

                limit = 10000
            }
        )


    local rekordy = {

        punkty = {
            dom = {},
            wyjazd = {}
        },

        minuty = {
            dom = {},
            wyjazd = {}
        },

        asysty = {
            dom = {},
            wyjazd = {}
        },

        zbiorki = {
            dom = {},
            wyjazd = {}
        },

        eval = {
            dom = {},
            wyjazd = {}
        },

        plusminus = {
            dom = {},
            wyjazd = {}
        }

    }


    local function dodaj(
        tabela,
        miejsce,
        wartosc,
        item
    )

        local lista =
            tabela[miejsce]

        local nowy =
            kopiuj(item)

        nowy.wartosc =
            wartosc

        if #lista == 0 then

            table.insert(
                lista,
                nowy
            )

        elseif wartosc >
            lista[1].wartosc then

            tabela[miejsce] = {
                nowy
            }

        elseif wartosc ==
            lista[1].wartosc then

            table.insert(
                lista,
                nowy
            )

        end

    end


    if zawodnicy then

        for _, row in ipairs(zawodnicy) do

            local miejsce =
                miejsceMeczu(row)

            if miejsce then

                local item = {

                    zawodnik =
                        row.zawodnik or "",

                    mecz =
                        row.mecz or "",

                    data =
                        row.data or "",

                    miejsce =
                        miejsce,

                    tekst =
                        nazwaMeczu(row),

                    wynik =
                        row.wynik or "",

                    minuty_format =
                        row.minuty_format or "",

                    punkty =
                        liczba(row.gol),

                    minuty =
                        liczba(row.minuty),

                    asysty =
                        liczba(row.asysta),

                    zbiorki =
                        liczba(row.zbiorka),

                    eval =
                        liczba(row.eval),

                    plusminus =
                        liczba(row.plusminus)

                }


                dodaj(
                    rekordy.punkty,
                    miejsce,
                    item.punkty,
                    item
                )

                dodaj(
                    rekordy.minuty,
                    miejsce,
                    item.minuty,
                    item
                )

                dodaj(
                    rekordy.asysty,
                    miejsce,
                    item.asysty,
                    item
                )

                dodaj(
                    rekordy.zbiorki,
                    miejsce,
                    item.zbiorki,
                    item
                )

                dodaj(
                    rekordy.eval,
                    miejsce,
                    item.eval,
                    item
                )

                dodaj(
                    rekordy.plusminus,
                    miejsce,
                    item.plusminus,
                    item
                )

            end

        end

    end


    -- =====================================================
    -- SERIE
    -- =====================================================

    local serie = {

        wszystkie = {
            wygrane = 0,
            przegrane = 0
        },

        dom = {
            wygrane = 0,
            przegrane = 0
        },

        wyjazd = {
            wygrane = 0,
            przegrane = 0
        }

    }


    local aktualna = {

        wszystkie = {
            W = 0,
            P = 0
        },

        dom = {
            W = 0,
            P = 0
        },

        wyjazd = {
            W = 0,
            P = 0
        }

    }


    for _, row in ipairs(mecze) do

        local g1, g2 =
            wynikMeczu(row)

        local miejsce =
            miejsceMeczu(row)

        if g1 and g2 and miejsce then

            local wynik

            if miejsce == "dom" then

                if g1 > g2 then
                    wynik = "W"
                elseif g1 < g2 then
                    wynik = "P"
                else
                    wynik = "R"
                end

            else

                if g2 > g1 then
                    wynik = "W"
                elseif g2 < g1 then
                    wynik = "P"
                else
                    wynik = "R"
                end

            end


            local zakresy = {
                "wszystkie",
                miejsce
            }


            for _, zakres in ipairs(zakresy) do

                if wynik == "W" then

                    aktualna[zakres].W =
                        aktualna[zakres].W + 1

                    aktualna[zakres].P = 0

                    if aktualna[zakres].W >
                        serie[zakres].wygrane then

                        serie[zakres].wygrane =
                            aktualna[zakres].W

                    end

                elseif wynik == "P" then

                    aktualna[zakres].P =
                        aktualna[zakres].P + 1

                    aktualna[zakres].W = 0

                    if aktualna[zakres].P >
                        serie[zakres].przegrane then

                        serie[zakres].przegrane =
                            aktualna[zakres].P

                    end

                else

                    aktualna[zakres].W = 0
                    aktualna[zakres].P = 0

                end

            end

        end

    end


    -- =====================================================
    -- FORMATOWANIE
    -- =====================================================

    local function tekstMeczow(lista)

        if not lista or #lista == 0 then
            return "—"
        end

        local wynik = {}

        for _, item in ipairs(lista) do

            table.insert(
                wynik,
                item.tekst ..
                " (" ..
                item.wynik ..
                ", " ..
                (item.roznica >= 0
                    and ("+" .. item.roznica)
                    or tostring(item.roznica)) ..
                ")"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    local function tekstZawodnikow(
        lista,
        typ
    )

        if not lista or #lista == 0 then
            return "—"
        end

        local wynik = {}

        for _, item in ipairs(lista) do

            local wartosc = ""

            if typ == "punkty" then

                wartosc =
                    tostring(item.punkty) ..
                    " pkt"

            elseif typ == "minuty" then

                wartosc =
                    item.minuty_format

                if wartosc == "" then
                    wartosc =
                        tostring(item.minuty)
                end

                wartosc =
                    wartosc .. " min"

            elseif typ == "asysty" then

                wartosc =
                    tostring(item.asysty) ..
                    " as."

            elseif typ == "zbiorki" then

                wartosc =
                    tostring(item.zbiorki) ..
                    " zb."

            elseif typ == "eval" then

                wartosc =
                    tostring(item.eval) ..
                    " EVAL"

            elseif typ == "plusminus" then

                if item.plusminus >= 0 then
                    wartosc =
                        "+" ..
                        tostring(item.plusminus)
                else
                    wartosc =
                        tostring(item.plusminus)
                end

                wartosc =
                    wartosc .. " +/-"

            end


            table.insert(
                wynik,
                "[[" ..
                item.zawodnik ..
                "]] — " ..
                wartosc ..
                "<br>" ..
                item.tekst ..
                " (" ..
                item.wynik ..
                ")"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    -- =====================================================
    -- GENEROWANIE
    -- =====================================================

    local wynik = {}

    table.insert(
        wynik,
        "=== Rekordy sezonu ==="
    )

    if rozgrywki ~= "" then

        table.insert(
            wynik,
            "''Rozgrywki: " ..
            rozgrywki ..
            "''"
        )

    end

    table.insert(
        wynik,
        "==== Rekordy meczowe ===="
    )

    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Rekord !! 🏠 Dom !! ✈️ Wyjazd"
    )

    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🏆 Najwyższe zwycięstwo"
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszeZwyciestwo.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszeZwyciestwo.wyjazd
        )
    )

    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! ❌ Najwyższa porażka"
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszaPorazka.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszaPorazka.wyjazd
        )
    )

    table.insert(wynik, "|}")


    table.insert(
        wynik,
        "==== Rekordy indywidualne ===="
    )

    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! 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(wynik, "|-")

        table.insert(
            wynik,
            "! " .. rekord.nazwa
        )

        table.insert(
            wynik,
            "| " ..
            tekstZawodnikow(
                rekord.tabela.dom,
                rekord.typ
            )
        )

        table.insert(
            wynik,
            "| " ..
            tekstZawodnikow(
                rekord.tabela.wyjazd,
                rekord.typ
            )
        )

    end


    table.insert(wynik, "|}")


    table.insert(
        wynik,
        "==== Serie ===="
    )

    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Seria !! Wszystkie mecze !! 🏠 Dom !! ✈️ Wyjazd"
    )

    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🔥 Najdłuższa seria zwycięstw"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.wygrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.wygrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.wygrane
        )
    )

    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 📉 Najdłuższa seria porażek"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.przegrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.przegrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.przegrane
        )
    )

    table.insert(wynik, "|}")

    return table.concat(
        wynik,
        "\n"
    )

end



-- =========================================================
-- =========================================================
-- PIŁKA NOŻNA
-- =========================================================
-- =========================================================


function p.pilka(
    sezon,
    druzyna,
    sezonSQL,
    druzynaSQL,
    rozgrywki,
    rozgrywkiSQL
)


    -- =====================================================
    -- MECZE
    -- =====================================================

    local fieldsMecze =
        table.concat({

            "Mecze.id=mecz",
            "Mecze.data=data",
            "Mecze.sezon=sezon",
            "Mecze.rozgrywki=rozgrywki",
            "Mecze.druzyna1=druzyna1",
            "Mecze.druzyna2=druzyna2",
            "Mecze.gole1=gole1",
            "Mecze.gole2=gole2",
            "Mecze.wynik=wynik",
            "Mecze.strona_meczu=strona_meczu"

        }, ",")


    local whereMecze =
        "(Mecze.druzyna1='" ..
        druzynaSQL ..
        "' OR Mecze.druzyna2='" ..
        druzynaSQL ..
        "')" ..
        " AND Mecze.sezon='" ..
        sezonSQL ..
        "'"


    if rozgrywki ~= "" then

        whereMecze =
            whereMecze ..
            " AND Mecze.rozgrywki='" ..
            rozgrywkiSQL ..
            "'"

    end


    local mecze =
        mw.ext.cargo.query(
            "Mecze",
            fieldsMecze,
            {
                where = whereMecze,
                orderBy = "Mecze.data ASC",
                limit = 5000
            }
        )


    if not mecze or #mecze == 0 then

        return
            "''Brak wprowadzonych meczów dla tej drużyny w podanym sezonie.''"

    end


    -- =====================================================
    -- REKORDY MECZOWE
    -- =====================================================

    local najwyzszeZwyciestwo = {
        dom = {},
        wyjazd = {}
    }

    local najwyzszaPorazka = {
        dom = {},
        wyjazd = {}
    }


    for _, row in ipairs(mecze) do

        local g1, g2 =
            wynikMeczu(row)

        local miejsce =
            miejsceMeczu(row)

        if g1 and g2 and miejsce then

            local zdobyte
            local stracone

            if miejsce == "dom" then

                zdobyte = g1
                stracone = g2

            else

                zdobyte = g2
                stracone = g1

            end

            local roznica =
                zdobyte - stracone


            local item = {

                mecz =
                    row.mecz or "",

                data =
                    row.data or "",

                miejsce =
                    miejsce,

                rozgrywki =
                    row.rozgrywki or "",

                tekst =
                    nazwaMeczu(row),

                wynik =
                    tostring(g1) ..
                    ":" ..
                    tostring(g2),

                zdobyte =
                    zdobyte,

                stracone =
                    stracone,

                roznica =
                    roznica

            }


            if roznica > 0 then

                local lista =
                    najwyzszeZwyciestwo[miejsce]

                if #lista == 0 then

                    table.insert(
                        lista,
                        item
                    )

                elseif roznica >
                    lista[1].roznica then

                    najwyzszeZwyciestwo[miejsce] = {
                        item
                    }

                elseif roznica ==
                    lista[1].roznica then

                    table.insert(
                        lista,
                        item
                    )

                end

            end


            if roznica < 0 then

                local przegrana =
                    math.abs(roznica)

                item.przegrana =
                    przegrana

                local lista =
                    najwyzszaPorazka[miejsce]

                if #lista == 0 then

                    table.insert(
                        lista,
                        item
                    )

                elseif przegrana >
                    lista[1].przegrana then

                    najwyzszaPorazka[miejsce] = {
                        item
                    }

                elseif przegrana ==
                    lista[1].przegrana then

                    table.insert(
                        lista,
                        item
                    )

                end

            end

        end

    end


    -- =====================================================
    -- SERIE
    -- =====================================================

    local serie = {

        wszystkie = {
            wygrane = 0,
            bezwygranej = 0,
            przegrane = 0,
            bezporazki = 0
        },

        dom = {
            wygrane = 0,
            bezwygranej = 0,
            przegrane = 0,
            bezporazki = 0
        },

        wyjazd = {
            wygrane = 0,
            bezwygranej = 0,
            przegrane = 0,
            bezporazki = 0
        }

    }


    local aktualna = {

        wszystkie = {
            W = 0,
            B = 0,
            P = 0,
            BP = 0
        },

        dom = {
            W = 0,
            B = 0,
            P = 0,
            BP = 0
        },

        wyjazd = {
            W = 0,
            B = 0,
            P = 0,
            BP = 0
        }

    }


    -- =====================================================
    -- OBLICZANIE SERII
    --
    -- B = bez porażki
    -- BP = bez zwycięstwa
    -- =====================================================

    for _, row in ipairs(mecze) do

        local g1, g2 =
            wynikMeczu(row)

        local miejsce =
            miejsceMeczu(row)

        if g1 and g2 and miejsce then

            local rezultat

            if miejsce == "dom" then

                if g1 > g2 then
                    rezultat = "W"
                elseif g1 < g2 then
                    rezultat = "P"
                else
                    rezultat = "R"
                end

            else

                if g2 > g1 then
                    rezultat = "W"
                elseif g2 < g1 then
                    rezultat = "P"
                else
                    rezultat = "R"
                end

            end


            local zakresy = {
                "wszystkie",
                miejsce
            }


            for _, zakres in ipairs(zakresy) do

                -- zwycięstwa

                if rezultat == "W" then

                    aktualna[zakres].W =
                        aktualna[zakres].W + 1

                    aktualna[zakres].BP = 0

                else

                    aktualna[zakres].W = 0

                    aktualna[zakres].BP =
                        aktualna[zakres].BP + 1

                end


                -- porażki

                if rezultat == "P" then

                    aktualna[zakres].P =
                        aktualna[zakres].P + 1

                    aktualna[zakres].B = 0

                else

                    aktualna[zakres].P = 0

                    aktualna[zakres].B =
                        aktualna[zakres].B + 1

                end


                if aktualna[zakres].W >
                    serie[zakres].wygrane then

                    serie[zakres].wygrane =
                        aktualna[zakres].W

                end


                if aktualna[zakres].BP >
                    serie[zakres].bezwygranej then

                    serie[zakres].bezwygranej =
                        aktualna[zakres].BP

                end


                if aktualna[zakres].P >
                    serie[zakres].przegrane then

                    serie[zakres].przegrane =
                        aktualna[zakres].P

                end


                if aktualna[zakres].B >
                    serie[zakres].bezporazki then

                    serie[zakres].bezporazki =
                        aktualna[zakres].B

                end

            end

        end

    end


    -- =====================================================
    -- REKORDY STRZELCÓW
    --
    -- StrzelecBramki:
    --   mecz
    --   zawodnik
    --   druzyna
    --   minuta
    -- =====================================================

    local fieldsStrzelcy =
        table.concat({

            "StrzelecBramki.mecz=mecz",
            "StrzelecBramki.zawodnik=zawodnik",
            "StrzelecBramki.druzyna=strzelec_druzyna",
            "StrzelecBramki.minuta=minuta",

            "Mecze.data=data",
            "Mecze.rozgrywki=rozgrywki",
            "Mecze.druzyna1=druzyna1",
            "Mecze.druzyna2=druzyna2",
            "Mecze.gole1=gole1",
            "Mecze.gole2=gole2",
            "Mecze.wynik=wynik",
            "Mecze.strona_meczu=strona_meczu"

        }, ",")


    local whereStrzelcy =
        "Mecze.sezon='" ..
        sezonSQL ..
        "'" ..
        " AND (" ..
        "Mecze.druzyna1='" ..
        druzynaSQL ..
        "'" ..
        " OR " ..
        "Mecze.druzyna2='" ..
        druzynaSQL ..
        "'" ..
        ")"


    if rozgrywki ~= "" then

        whereStrzelcy =
            whereStrzelcy ..
            " AND Mecze.rozgrywki='" ..
            rozgrywkiSQL ..
            "'"

    end


    local strzelcy =
        mw.ext.cargo.query(
            "StrzelecBramki,Mecze",
            fieldsStrzelcy,
            {
                join =
                    "StrzelecBramki.mecz=Mecze.id",

                where =
                    whereStrzelcy,

                orderBy =
                    "Mecze.data ASC",

                limit = 20000
            }
        )


    -- =====================================================
    -- GOLE ZAWODNIKA W JEDNYM MECZU
    -- =====================================================

    local goleZawodnika =
        {}


    if strzelcy then

        for _, row in ipairs(strzelcy) do

            local klucz =
                (row.mecz or "") ..
                "|" ..
                (row.zawodnik or "")


            if row.strzelec_druzyna ==
                druzyna then

                goleZawodnika[klucz] =
                    (goleZawodnika[klucz] or 0) + 1

            end

        end

    end


    local najwiecejGoliMecz = {
        dom = {},
        wyjazd = {}
    }


    for _, row in ipairs(strzelcy or {}) do

        if row.strzelec_druzyna ==
            druzyna then

            local miejsce =
                miejsceMeczu(row)

            if miejsce then

                local klucz =
                    (row.mecz or "") ..
                    "|" ..
                    (row.zawodnik or "")

                local gole =
                    goleZawodnika[klucz] or 0


                local item = {

                    zawodnik =
                        row.zawodnik or "",

                    mecz =
                        row.mecz or "",

                    miejsce =
                        miejsce,

                    gole =
                        gole,

                    tekst =
                        nazwaMeczu(row),

                    wynik =
                        row.wynik or ""

                }


                local lista =
                    najwiecejGoliMecz[miejsce]


                if #lista == 0 then

                    table.insert(
                        lista,
                        item
                    )

                elseif gole >
                    lista[1].gole then

                    najwiecejGoliMecz[miejsce] = {
                        item
                    }

                elseif gole ==
                    lista[1].gole then

                    local istnieje = false

                    for _, stary in ipairs(lista) do

                        if stary.zawodnik ==
                            item.zawodnik
                            and
                            stary.mecz ==
                            item.mecz then

                            istnieje = true
                            break

                        end

                    end

                    if not istnieje then

                        table.insert(
                            lista,
                            item
                        )

                    end

                end

            end

        end

    end


    -- =====================================================
    -- ASYSTY
    -- =====================================================

    local fieldsAsysty =
        table.concat({

            "UdzialZawodnika.zawodnik=zawodnik",
            "UdzialZawodnika.druzyna=druzyna_zawodnika",
            "UdzialZawodnika.asysta=asysta",

            "Mecze.id=mecz",
            "Mecze.data=data",
            "Mecze.rozgrywki=rozgrywki",
            "Mecze.druzyna1=druzyna1",
            "Mecze.druzyna2=druzyna2",
            "Mecze.wynik=wynik",
            "Mecze.strona_meczu=strona_meczu"

        }, ",")


    local whereAsysty =
        "UdzialZawodnika.druzyna='" ..
        druzynaSQL ..
        "'" ..
        " AND Mecze.sezon='" ..
        sezonSQL ..
        "'"


    if rozgrywki ~= "" then

        whereAsysty =
            whereAsysty ..
            " AND Mecze.rozgrywki='" ..
            rozgrywkiSQL ..
            "'"

    end


    local asysty =
        mw.ext.cargo.query(
            "UdzialZawodnika,Mecze",
            fieldsAsysty,
            {
                join =
                    "UdzialZawodnika.mecz=Mecze.id",

                where =
                    whereAsysty,

                orderBy =
                    "Mecze.data ASC",

                limit = 20000
            }
        )


    local najwiecejAsyst = {
        dom = {},
        wyjazd = {}
    }


    if asysty then

        for _, row in ipairs(asysty) do

            local liczbaAsyst =
                liczba(row.asysta)

            if liczbaAsyst > 0 then

                local miejsce =
                    miejsceMeczu(row)

                if miejsce then

                    local item = {

                        zawodnik =
                            row.zawodnik or "",

                        mecz =
                            row.mecz or "",

                        miejsce =
                            miejsce,

                        asysty =
                            liczbaAsyst,

                        tekst =
                            nazwaMeczu(row),

                        wynik =
                            row.wynik or ""

                    }


                    local lista =
                        najwiecejAsyst[miejsce]


                    if #lista == 0 then

                        table.insert(
                            lista,
                            item
                        )

                    elseif liczbaAsyst >
                        lista[1].asysty then

                        najwiecejAsyst[miejsce] = {
                            item
                        }

                    elseif liczbaAsyst ==
                        lista[1].asysty then

                        table.insert(
                            lista,
                            item
                        )

                    end

                end

            end

        end

    end


    -- =====================================================
    -- NAJCZĘSTSZE WYNIKI
    -- =====================================================

    local czestoscWynikow = {

        wszystkie = {},
        dom = {},
        wyjazd = {}

    }


    for _, row in ipairs(mecze) do

        local g1, g2 =
            wynikMeczu(row)

        local miejsce =
            miejsceMeczu(row)

        if g1 and g2 and miejsce then

            local wynik =
                tostring(g1) ..
                ":" ..
                tostring(g2)


            czestoscWynikow.wszystkie[wynik] =
                (czestoscWynikow.wszystkie[wynik] or 0) + 1

            czestoscWynikow[miejsce][wynik] =
                (czestoscWynikow[miejsce][wynik] or 0) + 1

        end

    end


    local function posortujWyniki(tabela)

        local lista = {}

        for wynik, liczbaWystapien in pairs(tabela) do

            table.insert(
                lista,
                {
                    wynik = wynik,
                    liczba = liczbaWystapien
                }
            )

        end


        table.sort(
            lista,
            function(a, b)

                if a.liczba ~= b.liczba then
                    return a.liczba > b.liczba
                end

                return a.wynik < b.wynik

            end
        )


        return lista

    end


    local najczestszeWyniki = {

        wszystkie =
            posortujWyniki(
                czestoscWynikow.wszystkie
            ),

        dom =
            posortujWyniki(
                czestoscWynikow.dom
            ),

        wyjazd =
            posortujWyniki(
                czestoscWynikow.wyjazd
            )

    }


    -- =====================================================
    -- PRZEDZIAŁY CZASOWE
    -- =====================================================

    local przedzialy = {

        {
            klucz = "0-15",
            nazwa = "0–15"
        },

        {
            klucz = "16-30",
            nazwa = "16–30"
        },

        {
            klucz = "31-45",
            nazwa = "31–45"
        },

        {
            klucz = "45+",
            nazwa = "45+"
        },

        {
            klucz = "46-60",
            nazwa = "46–60"
        },

        {
            klucz = "61-75",
            nazwa = "61–75"
        },

        {
            klucz = "76-90",
            nazwa = "76–90"
        },

        {
            klucz = "90+",
            nazwa = "90+"
        },

        {
            klucz = "91-105",
            nazwa = "91–105"
        },

        {
            klucz = "105+",
            nazwa = "105+"
        },

        {
            klucz = "106-120",
            nazwa = "106–120"
        },

        {
            klucz = "120+",
            nazwa = "120+"
        }

    }


    local goleCzas = {}


    for _, przedzial in ipairs(przedzialy) do

        goleCzas[przedzial.klucz] = {

            zdobyte = 0,
            stracone = 0

        }

    end


    -- =====================================================
    -- FUNKCJA OKREŚLAJĄCA PRZEDZIAŁ
    --
    -- Obsługujemy:
    -- 14
    -- 45
    -- 45+
    -- 90
    -- 90+
    -- 105
    -- 105+
    -- itd.
    -- =====================================================

    local function przedzialGola(minuta)

        if minuta == nil then
            return nil
        end

        local tekst =
            tostring(minuta)

        tekst =
            mw.text.trim(tekst)

        local plus =
            tekst:sub(-1) == "+"

        local liczbaMinuty =
            tonumber(
                tekst:gsub("%+$", "")
            )


        if not liczbaMinuty then
            return nil
        end


        if plus then

            if liczbaMinuty == 45 then
                return "45+"
            end

            if liczbaMinuty == 90 then
                return "90+"
            end

            if liczbaMinuty == 105 then
                return "105+"
            end

            if liczbaMinuty == 120 then
                return "120+"
            end

            -- Dodatkowe przypadki
            -- traktujemy zgodnie z najbliższym
            -- standardowym przedziałem.

            if liczbaMinuty < 45 then
                return "45+"
            end

            if liczbaMinuty < 90 then
                return "90+"
            end

            if liczbaMinuty < 105 then
                return "105+"
            end

            if liczbaMinuty < 120 then
                return "120+"
            end

            return "120+"

        end


        if liczbaMinuty <= 15 then
            return "0-15"
        end

        if liczbaMinuty <= 30 then
            return "16-30"
        end

        if liczbaMinuty <= 45 then
            return "31-45"
        end

        if liczbaMinuty <= 60 then
            return "46-60"
        end

        if liczbaMinuty <= 75 then
            return "61-75"
        end

        if liczbaMinuty <= 90 then
            return "76-90"
        end

        if liczbaMinuty <= 105 then
            return "91-105"
        end

        if liczbaMinuty <= 120 then
            return "106-120"
        end

        return "120+"

    end


    -- =====================================================
    -- LICZENIE GOLI W PRZEDZIAŁACH
    -- =====================================================

    if strzelcy then

        for _, row in ipairs(strzelcy) do

            local przedzial =
                przedzialGola(
                    row.minuta
                )

            if przedzial then

                if row.strzelec_druzyna ==
                    druzyna then

                    goleCzas[przedzial].zdobyte =
                        goleCzas[przedzial].zdobyte + 1

                else

                    goleCzas[przedzial].stracone =
                        goleCzas[przedzial].stracone + 1

                end

            end

        end

    end


    -- =====================================================
    -- FORMATOWANIE GOLI
    -- =====================================================

    local function tekstGoliCzas()

        local wynik = {}

        for _, przedzial in ipairs(przedzialy) do

            local dane =
                goleCzas[przedzial.klucz]

            table.insert(
                wynik,
                "|-\n" ..
                "! " ..
                przedzial.nazwa ..
                "\n| " ..
                tostring(dane.zdobyte) ..
                "\n| " ..
                tostring(dane.stracone)
            )

        end

        return table.concat(
            wynik,
            "\n"
        )

    end


    -- =====================================================
    -- FORMATOWANIE REKORDÓW STRZELCÓW
    -- =====================================================

    local function tekstStrzelcow(lista)

        if not lista or #lista == 0 then
            return "—"
        end

        local wynik = {}

        for _, item in ipairs(lista) do

            table.insert(
                wynik,
                "[[" ..
                item.zawodnik ..
                "]] — " ..
                tostring(item.gole) ..
                " gole<br>" ..
                item.tekst ..
                " (" ..
                item.wynik ..
                ")"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    -- =====================================================
    -- FORMATOWANIE ASYST
    -- =====================================================

    local function tekstAsyst(lista)

        if not lista or #lista == 0 then
            return "—"
        end

        local wynik = {}

        for _, item in ipairs(lista) do

            table.insert(
                wynik,
                "[[" ..
                item.zawodnik ..
                "]] — " ..
                tostring(item.asysty) ..
                " as.<br>" ..
                item.tekst ..
                " (" ..
                item.wynik ..
                ")"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    -- =====================================================
    -- NAJCZĘSTSZY WYNIK
    -- =====================================================

    local function tekstNajczestszego(lista)

        if not lista or #lista == 0 then
            return "—"
        end

        local max =
            lista[1].liczba

        local wynik = {}

        for _, item in ipairs(lista) do

            if item.liczba ~= max then
                break
            end

            table.insert(
                wynik,
                item.wynik ..
                " (" ..
                tostring(item.liczba) ..
                "×)"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    -- =====================================================
    -- FORMATOWANIE MECZÓW
    -- =====================================================

    local function tekstMeczow(lista)

        if not lista or #lista == 0 then
            return "—"
        end

        local wynik = {}

        for _, item in ipairs(lista) do

            local roznica =
                item.roznica or 0

            table.insert(
                wynik,
                item.tekst ..
                " (" ..
                item.wynik ..
                ", " ..
                (roznica >= 0
                    and ("+" .. roznica)
                    or tostring(roznica)) ..
                ")"
            )

        end

        return table.concat(
            wynik,
            "<br>"
        )

    end


    -- =====================================================
    -- GENEROWANIE WYNIKU
    -- =====================================================

    local wynik = {}


    table.insert(
        wynik,
        "=== Rekordy sezonu ==="
    )


    if rozgrywki ~= "" then

        table.insert(
            wynik,
            "''Rozgrywki: " ..
            rozgrywki ..
            "''"
        )

    end


    -- =====================================================
    -- REKORDY MECZOWE
    -- =====================================================

    table.insert(
        wynik,
        "==== Rekordy meczowe ===="
    )


    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Rekord !! 🏠 Dom !! ✈️ Wyjazd"
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🏆 Najwyższe zwycięstwo"
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszeZwyciestwo.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszeZwyciestwo.wyjazd
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! ❌ Najwyższa porażka"
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszaPorazka.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstMeczow(
            najwyzszaPorazka.wyjazd
        )
    )


    table.insert(wynik, "|}")


    -- =====================================================
    -- SERIE
    -- =====================================================

    table.insert(
        wynik,
        "==== Serie ===="
    )


    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Seria !! Wszystkie mecze !! 🏠 Dom !! ✈️ Wyjazd"
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🔥 Najdłuższa seria zwycięstw"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.wygrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.wygrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.wygrane
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🛡️ Najdłuższa seria bez porażki"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.bezporazki
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.bezporazki
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.bezporazki
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! ⏳ Najdłuższa seria bez zwycięstwa"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.bezwygranej
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.bezwygranej
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.bezwygranej
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 📉 Najdłuższa seria porażek"
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wszystkie.przegrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.dom.przegrane
        )
    )

    table.insert(
        wynik,
        "| " ..
        tostring(
            serie.wyjazd.przegrane
        )
    )


    table.insert(wynik, "|}")


    -- =====================================================
    -- REKORDY ZAWODNIKÓW
    -- =====================================================

    table.insert(
        wynik,
        "==== Rekordy zawodników ===="
    )


    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Rekord !! 🏠 Dom !! ✈️ Wyjazd"
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! ⚽ Najwięcej goli w jednym meczu"
    )

    table.insert(
        wynik,
        "| " ..
        tekstStrzelcow(
            najwiecejGoliMecz.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstStrzelcow(
            najwiecejGoliMecz.wyjazd
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🎯 Najwięcej asyst w jednym meczu"
    )

    table.insert(
        wynik,
        "| " ..
        tekstAsyst(
            najwiecejAsyst.dom
        )
    )

    table.insert(
        wynik,
        "| " ..
        tekstAsyst(
            najwiecejAsyst.wyjazd
        )
    )


    table.insert(wynik, "|}")


    -- =====================================================
    -- NAJCZĘSTSZE WYNIKI
    -- =====================================================

    table.insert(
        wynik,
        "==== Najczęstsze wyniki ===="
    )


    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Zakres !! Najczęstszy wynik"
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! Wszystkie mecze"
    )

    table.insert(
        wynik,
        "| " ..
        tekstNajczestszego(
            najczestszeWyniki.wszystkie
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! 🏠 Dom"
    )

    table.insert(
        wynik,
        "| " ..
        tekstNajczestszego(
            najczestszeWyniki.dom
        )
    )


    table.insert(wynik, "|-")

    table.insert(
        wynik,
        "! ✈️ Wyjazd"
    )

    table.insert(
        wynik,
        "| " ..
        tekstNajczestszego(
            najczestszeWyniki.wyjazd
        )
    )


    table.insert(wynik, "|}")


    -- =====================================================
    -- GOLE W CZASIE
    -- =====================================================

    table.insert(
        wynik,
        "==== Gole według przedziałów czasowych ===="
    )


    table.insert(
        wynik,
        '{| class="wikitable" style="width:100%; text-align:center;"'
    )

    table.insert(
        wynik,
        "! Przedział czasowy !! ⚽ Zdobyte !! ❌ Stracone"
    )


    table.insert(
        wynik,
        tekstGoliCzas()
    )


    table.insert(
        wynik,
        "|}"
    )


    return table.concat(
        wynik,
        "\n"
    )

end


return p