#!/usr/bin/perl
# Zobrazí seznam přihlášených na konkrétní akci.
# Copyright © 2004-2011 Dan Zeman <zeman@ufal.mff.cuni.cz>
# Licence: GNU GPL

use utf8; # říct Perlu, že konstantní řetězce ve zdrojáku jsou v UTF
use DBI; # spolupráce se serverem MySQL
# Říct Perlu, kde najde Danovy sdílené knihovny.
# CGI skripty běží pod uživatelem apache, který nemá tyto knihovny v cestě.
use lib '/s/w/lib/dan';
use dancgi; # čtení parametrů z webu nebo z ARGV
use jazyky; # jazykové verze textů
use csort; # české a anglické abecední řazení UTF znaků
use mso; # funkce pro generování stránek o olympiádě
binmode(STDOUT, ":utf8"); # říct Perlu, že UTF chceme i na výstupu

# Připojit se k databázi.
$databaze = mso::pripojit_se_k_databazi();

# Výchozí nastavení parametru. Muže být pořbito parametry z URL/ARGV.
mso::provest_vychozi_nastaveni_parametru(\%konfig, $databaze);
# Načíst parametry z URL.
dancgi::cist_parametry(\%konfig);
# Umožnit volat skript z příkazového řádku a předat parametry tam (např. perl prihlaseni.pl akce=caroly).
dancgi::rozebrat_parametry($ARGV[0], \%konfig);
if($konfig{jazyk} eq "")
{
    $konfig{jazyk} = "cs";
}
$jazyky::jazyk = $konfig{jazyk};



# Získat HTML kód seznamu přihlášených a doprovodné informace.
$stranka = sestavit_seznam_prihlasenych($konfig{rok}, $konfig{hra}, $konfig{turnaj});



# Vypsat stránku.
mso::vypsat_stranku(
{
    "nazev"  => "MSO: $konfig{rok}: ".jazyky::zjistit("prihlaseni"), 
    "nadpis" => jazyky::zjistit("prihlaseni_nadpis", $stranka->{typ_prihlasky}, $stranka->{nazev_akce}),
    "telo"   => $stranka->{html},
    "rok"    => $konfig{rok}
});



###############################################################################
# PODPROGRAMY
###############################################################################



#------------------------------------------------------------------------------
# Načte z databáze seznam přihlášek na danou akci.
#------------------------------------------------------------------------------
sub sestavit_seznam_prihlasenych
{
    my $rok = shift;
    my $hra = shift;
    my $turnaj = shift;
    my $tabulka;
    # Připravit filtr pro databázi. Není-li uvedena hra a turnaj, chceme seznam všech přihlášek na daný ročník.
    my $filtr = "WHERE (rok = '$rok')";
    $filtr .= " AND (kod_hry = '$hra')" unless($hra eq "");
    $filtr .= " AND (kod_turnaje = '$turnaj')" unless($turnaj eq "");
    # Načíst přihlášky vyexportované z Accessu.
    my $prihlasky = mso::dotazat_se_databaze($databaze, 'jmeno', 'prijmeni', 'rok', 'kod_hry', 'kod_turnaje', 'prihlasky.datum_prihlasky', 'volitelny_turnaj', 'zpusob_placeni AS zaplaceno_dne', "prihlasky $filtr");
    # Načíst přihlášky, které ještě v Accessu nejsou, ale přihlašovací skript je uložil do MySQL.
    my $prihlasky1 = mso::dotazat_se_databaze($databaze, 'jmeno', 'prijmeni', 'rok', 'kod_hry', 'kod_turnaje', 'prihlasky.datum_prihlasky', 'volitelny_turnaj', 'zaplaceno_dne', "prihlasky_auto AS prihlasky INNER JOIN osoby_auto ON prihlasky.datum_prihlasky = osoby_auto.cas_odeslani_access $filtr");
    push(@{$prihlasky}, @{$prihlasky1});
    # Načíst změny přihlášek, provedené přes webové rozhraní k databázi MySQL.
    my $prihlasky2 = mso::dotazat_se_databaze($databaze, 'jmeno', 'prijmeni', 'rok', 'kod_hry', 'kod_turnaje', 'odhlasit', 'prihlasky.datum_zmeny', 'ma_dati', 'dal', 'zpusob_placeni', "prihlasky_zmeny AS prihlasky INNER JOIN osoby ON prihlasky.kod_osoby = osoby.kod $filtr");
    # Nyní je potřeba projít přihlášky načtené z prvních dvou zdrojů.
    # Pokud se někdo odhlásil, příslušnou načtenou přihlášku (kód osoby + rok + hra + turnaj) vyhodit.
    # Naopak změnové přihlášky, kde se nikdo neodhlásil, připsat na konec a navíc správně zhodnotit placení (je uvedeno jinak než u osoby_auto).
    my %odhlaseni;
    foreach my $p (@{$prihlasky2})
    {
        if($p->{odhlasit})
        {
            $odhlaseni{$p->{jmeno}}{$p->{prijmeni}}{$p->{rok}}{$p->{kod_hry}}{$p->{kod_turnaje}} = 1;
        }
        else
        {
            my %prihlaska =
            (
                'jmeno' => $p->{jmeno},
                'prijmeni' => $p->{prijmeni},
                'rok' => $p->{rok},
                'kod_hry' => $p->{kod_hry},
                'kod_turnaje' => $p->{kod_turnaje},
                'prihlasky.datum_prihlasky' => $p->{"prihlasky.datum_zmeny"},
                'zaplaceno_dne' => $p->{zpusob_placeni}
            );
            ###!!! DEBUG
            #my $vse = join(', ', map {"$_=$p->{$_}"} (keys(%{$p})));
            #$prihlaska{jmeno} = $vse;
            push(@{$prihlasky}, \%prihlaska);
        }
    }
    for(my $i = 0; $i<=$#{$prihlasky}; $i++)
    {
        my $p = $prihlasky->[$i];
        if($odhlaseni{$p->{jmeno}}{$p->{prijmeni}}{$p->{rok}}{$p->{kod_hry}}{$p->{kod_turnaje}})
        {
            splice(@{$prihlasky}, $i--, 1);
        }
    }
    # Seřadit přihlášky chronologicky nebo abecedně podle příjmení a jména hráčů.
    my $abc = "<a ".mso::odkaz($konfig, "telo=prihlaseni.pl", "trid=abecedne").">".jazyky::zjistit("abecedne")."</a>";
    my $chr = "<a ".mso::odkaz($konfig, "telo=prihlaseni.pl", "trid=chronologicky").">".jazyky::zjistit("chronologicky")."</a>";
    map
    {
        $_->{_tridici_jmeno} = csort::zjistit_tridici_hodnoty($_->{prijmeni}, $jazyky::jazyk).csort::zjistit_tridici_hodnoty($_->{jmeno}, $jazyky::jazyk);
        $_->{datum_prihlasky} = $_->{"prihlasky.datum_prihlasky"};
        my $cas = cas::esek2hash(cas::datumcas2esek($_->{datum_prihlasky}));
        $_->{_tridici_cas} = $cas->{rmdhms};
    }
    (@{$prihlasky});
    # Třídicí hodnoty máme, teď to vlastní třídění.
    if($konfig{trid} =~ m/^chron/i)
    {
        @{$prihlasky} = sort
        {
            my $vysledek = nejdriv_platici($a, $b);
            if(!$vysledek)
            {
                # Ne všichni platící mají uvedeno datum zaplacení a my ho stejně nezobrazujeme, tak podle něj nebudeme třídit.
                #$vysledek = $a->{zaplaceno_dne} <=> $b->{zaplaceno_dne};
                if(!$vysledek)
                {
                    $vysledek = $a->{_tridici_cas} cmp $b->{_tridici_cas};
                }
            }
            return $vysledek;
        }
        (@{$prihlasky});
    }
    else
    {
        @{$prihlasky} = sort
        {
            my $vysledek = nejdriv_platici($a, $b);
            if(!$vysledek)
            {
                # Ne všichni platící mají uvedeno datum zaplacení a my ho stejně nezobrazujeme, tak podle něj nebudeme třídit.
                #$vysledek = $a->{zaplaceno_dne} <=> $b->{zaplaceno_dne};
                if(!$vysledek)
                {
                    $vysledek = $a->{_tridici_jmeno} cmp $b->{_tridici_jmeno};
                }
            }
            return $vysledek;
        }
        (@{$prihlasky});
    }
    # Rozskok: buď seznam přihlášených na konkrétní akci, nebo seznam všech přihlášek.
    my $nazev_akce;
    my $typ_prihlasky;
    if($hra ne "" && $turnaj ne "")
    {
        # Zjistit podrobnosti o akci.
        my $nazev_jazyk = jazyky::zjistit("klic_nazev");
        my $akce = mso::dotazat_se_databaze($databaze, $nazev_jazyk, "prihlasky", "akce WHERE (rok = '$rok') AND (kod_hry = '$hra') AND (kod_turnaje = '$turnaj')")->[0];
        $nazev_akce = $akce->{$nazev_jazyk};
        my $datum_prihlasky;
        if($akce->{"prihlasky"} eq "kvalifikovaní registrace")
        {
            $datum_prihlasky = jazyky::zjistit("datum_registrace");
            $typ_prihlasky = "registrovaných";
        }
        else
        {
            $datum_prihlasky = jazyky::zjistit("datum_prihlasky");
            $typ_prihlasky = "přihlášených";
        }
        # Sestavit HTML se seznamem přihlášených.
        $tabulka .= "<h3><a ".mso::odkaz(\%konfig, "telo=propozice.pl").">Propozice turnaje</a></h3>";
        $tabulka .= "<p>$abc | $chr</p>\n";
#        $tabulka .= jazyky::zjistit("prihlaseni_upozorneni");
        $tabulka .= "<table>\n";
        $tabulka .= "  <tr>\n";
        $tabulka .= "    <th align=\"left\">".jazyky::zjistit("c")."</th>\n";
        $tabulka .= "    <th align=\"left\">".jazyky::zjistit("jmeno")."</th>\n";
        $tabulka .= "    <th colspan=\"2\"> $datum_prihlasky </th>\n";
        if($akce->{prihlasky} =~ m/^volitelny\d+$/)
        {
            $tabulka .= "    <th align=\"left\">".jazyky::zjistit("hlasy")."</th>\n";
        }
        $tabulka .= "  </tr>\n";
        my $poradi;
        my %duplikaty;
        my $n_hlasu = 0;
        foreach my $prihlaska (@{$prihlasky})
        {
            # Pokud se někdo přihlásil opakovaně, může seznam obsahovat duplikáty. Vypsat pouze první přihlášku každého člověka.
            my $klic = $prihlaska->{jmeno}." ".$prihlaska->{prijmeni}." ".$prihlaska->{kod_hry}.$prihlaska->{kod_turnaje};
            $duplikaty{$klic}++;
            next if($duplikaty{$klic}>1);
            $poradi++;
            my $datum = $prihlaska->{datum_prihlasky};
            my $cas;
            if($datum =~ m/^(\d+\.\d+\.\d+)(?:\s+(\d+:\d+:\d+))?$/)
            {
                $datum = $1;
                # Od roku 2011 přestáváme zobrazovat čas přihlášení, aby nebylo tak snadné zkonstruovat existující variabilní symbol.
                # Variabilní symbol se bude používat jako identifikace, která uživateli umožní editovat svou přihlášku.
                ###$cas = $2;
            }
            $tabulka .= "  <tr class=\"".($poradi % 2 == 0 ? 'even' : 'odd')."\">\n";
            $tabulka .= "    <td align=\"right\">$poradi. </td>\n";
            $tabulka .= "    <td>$prihlaska->{jmeno} $prihlaska->{prijmeni}</td>\n";
            $tabulka .= "    <td align=\"right\">$datum </td><td align=\"right\">$cas</td>\n";
            if($akce->{prihlasky} =~ m/^volitelny\d+$/)
            {
                $tabulka .= "    <td align=\"right\">$prihlaska->{volitelny_turnaj}</td>\n";
                $n_hlasu += $prihlaska->{volitelny_turnaj};
            }
            if($prihlaska->{zaplaceno_dne})
            {
                $tabulka .= "    <td>zaplaceno</td>\n";
            }
            $tabulka .= "  </tr>\n";
        }
        # U volitelných turnajů přidat řádek s celkovým počtem hlasů.
        if($akce->{prihlasky} =~ m/^volitelny\d+$/)
        {
            $tabulka .= "  <tr>\n";
            $tabulka .= "    <td></td>\n";
            $tabulka .= "    <td><b>".jazyky::zjistit("hlasu_celkem")."</b></td>\n";
            $tabulka .= "    <td></td><td></td>\n";
            $tabulka .= "    <td align=\"right\"><b>$n_hlasu</b></td>\n";
            $tabulka .= "  </tr>\n";
        }
        $tabulka .= "</table>\n";
    }
    else # seznam přihlášených na všechny akce
    {
        # Připravit si obecný "název akce" do nadpisu.
        $nazev_akce = "Deskohraní $rok";
        $typ_prihlasky = "přihlášených";
        # Zjistit a oindexovat názvy akcí.
        my $nazev_jazyk = jazyky::zjistit("klic_nazev");
        my $akce = mso::dotazat_se_databaze($databaze, "kod_hry", "kod_turnaje", $nazev_jazyk, "akce WHERE (rok = '$rok')");
        my %nazvy_akci;
        foreach my $a (@{$akce})
        {
            $nazvy_akci{$a->{kod_hry}}{$a->{kod_turnaje}} = $a->{$nazev_jazyk};
        }
        # Sestavit HTML se seznamem přihlášených.
#        $tabulka .= jazyky::zjistit("prihlaseni_upozorneni");
        $tabulka .= "<p>$abc | $chr</p>\n";
        $tabulka .= "<table>\n";
        $tabulka .= "  <tr><th align=\"left\">".jazyky::zjistit("c")."</th><th align=\"left\">".jazyky::zjistit("jmeno")."</th><th align=\"left\">".jazyky::zjistit("akce")."</th><th colspan=\"2\">".jazyky::zjistit("datum_prihlasky")."</th></tr>\n";
        my $poradi;
        foreach my $prihlaska (@{$prihlasky})
        {
            # Pokud se někdo přihlásil opakovaně, může seznam obsahovat duplikáty. Vypsat pouze první přihlášku každého člověka.
            my $klic = $prihlaska->{jmeno}." ".$prihlaska->{prijmeni}." ".$prihlaska->{kod_hry}.$prihlaska->{kod_turnaje};
            $duplikaty{$klic}++;
            next if($duplikaty{$klic}>1);
            $poradi++;
            my $datum = $prihlaska->{datum_prihlasky};
            my $cas;
            if($datum =~ m/^(\d+\.\d+\.\d+)(?:\s+(\d+:\d+:\d+))?$/)
            {
                $datum = $1;
                # Od roku 2011 přestáváme zobrazovat čas přihlášení, aby nebylo tak snadné zkonstruovat existující variabilní symbol.
                # Variabilní symbol se bude používat jako identifikace, která uživateli umožní editovat svou přihlášku.
                ###$cas = $2;
            }
            my $nazev = "<a ".mso::odkaz(\%konfig, "telo=prihlaseni.pl", "hra=$prihlaska->{kod_hry}", "turnaj=$prihlaska->{kod_turnaje}").">$nazvy_akci{$prihlaska->{kod_hry}}{$prihlaska->{kod_turnaje}}</a>";
            $tabulka .= "  <tr class=\"".($poradi % 2 == 0 ? 'even' : 'odd')."\"><td align=\"right\">$poradi. </td><td>$prihlaska->{jmeno} $prihlaska->{prijmeni}</td><td>$nazev</td><td align=\"right\">$datum </td><td align=\"right\">$cas</td>";
            if($prihlaska->{zaplaceno_dne})
            {
                $tabulka .= "<td>zaplaceno</td>";
            }
            $tabulka .= "</tr>\n";
        }
        $tabulka .= "</table>\n";
    }
    # Sestavit záznam s HTML kódem a doprovodnými informacemi.
    my %zaznam =
    (
        "nazev_akce" => $nazev_akce,
        "typ_prihlasky" => $typ_prihlasky,
        "html" => $tabulka,
    );
    return \%zaznam;
}



sub ma_zaplaceno
{
    my $zaznam = shift;
    # Nelze se spoléhat na to, že pole zaplaceno_dne obsahuje datum, protože tam z některých tabulek kopírujeme případně jen způsob placení bez data.
    return $zaznam->{zaplaceno_dne} !~ m/^\s*$/;
}



sub nejdriv_platici
{
    my $a = shift;
    my $b = shift;
    if(ma_zaplaceno($a) && !ma_zaplaceno($b))
    {
        return -1;
    }
    elsif(ma_zaplaceno($b) && !ma_zaplaceno($a))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
