• Nebyly nalezeny žádné výsledky

Okno vlastn´ıch parti´ı dan´ eho z´ apasu druˇ zstev

4.3. Implementace p´arov´an´ı kol

4.3 Implementace p´ arov´ an´ı kol

V t´eto ˇc´asti pop´ıˇsi implementaci p´arov´an´ı kol. Pop´ıˇsi pouze turnaj jednotlivc˚u, protoˇze pro turnaj druˇzstev, je implementace obdobn´a. Implementaci jsem provedl pˇresnˇe podle navrˇzen´e architektury aplikace. Poˇzadavek na p´arov´an´ı je zachycen instanc´ı tˇr´ıdy PlayerRoundView. Ta bez jak´ehokoli zpracov´an´ı pˇred´a tento poˇzadavek sv´emu prezenterovi. Jedn´a se o instanci tˇr´ıdy PlayerRoun-dPresenter. Ta poˇz´ad´a o p´arov´an´ı rozhran´ı PlayerRound, kter´e jiˇz patˇr´ı do business vrstvy. T´ım se poˇzadavek pˇresunul z prezentaˇcn´ı vrstvy do business vrstvy. Prezenter pak oˇcek´av´a vr´acen´ı seznamu s p´arov´an´ım. Je ovˇsem tak´e pˇripraven na vyhozen´ı v´yjimky ApplicationLogicException, kter´e by v tomto pˇr´ıpadˇe znamenalo neoˇcek´avanou intern´ı chybu aplikace. Pokud vˇsak prezen-ter ´uspˇeˇsnˇe obdrˇz´ı p´arov´an´ı, pˇriprav´ı z´ıskan´a data pro sv˚uj pohled a pˇrik´aˇze mu ho zobrazit. T´ım je role prezenteru ukonˇcena a pohled je nyn´ı zodpovˇedn´y za dan´e zobrazen´ı. Pot´e jiˇz uˇzivatel aplikace vid´ı proveden´e p´arov´an´ı v GUI.

Nyn´ı pop´ıˇsi co se odehr´av´a v business vrstvˇe. Jak jiˇz bylo zm´ınˇeno, prezentaˇcn´ı vrstva vol´a metodu deklarovanou v rozhran´ı PlayerRound. Pod t´ımto rozhran´ı se mohou nach´azet r˚uzn´e implementace. V souˇcasn´e dobˇe je pouze jedin´a implementace tohoto rozhran´ı, jelikoˇz plnˇe dostaˇcuje. V bu-doucnu se vˇsak m˚uˇze uvaˇzovat o zmˇenˇe t´eto implementace. Dan´e rozhran´ı je implementov´ano tˇr´ıdou StdPlayerRound. Jej´ı instance obdrˇz´ı poˇzadavek na p´arov´an´ı pomoc´ı vol´an´ı metody doPairing. Provede nezbytn´e kontroly tohoto poˇzadavku a poˇz´ad´a p´arovac´ı engine o proveden´ı p´arov´an´ı. Pokud p´arov´an´ı probˇehne bez probl´emu, zaktualizuje sv˚uj stav a poˇz´ad´a instanci tˇr´ıdy StdPla-yerTournament o uloˇzen´ı sv´eho stavu do perzistentn´ıho prostˇred´ı. Jelikoˇz je jej´ı souˇc´ast´ı, mus´ı instance tˇr´ıdy StdPlayerTournament tak´e aktualizovat sv˚uj stav. N´aslednˇe poˇz´ad´a rozhran´ı TournamentManager o perzistentn´ı uloˇzen´ı.

Rozhran´ı TournamentManager je implementov´ano tˇr´ıdou StdTournamentMa-nager a pˇredstavuje jedin´aˇcka. Je to z toho d˚uvodu, ˇze je potˇreba pouze jedin´a instance t´eto tˇr´ıdy. Tato tˇr´ıda poˇz´ad´a rozhran´ı EntityDao o perzistetn´ı uloˇzen´ı.

Toto rozhran´ı patˇr´ı do datov´e vrstvy. Implementace tohoto rozhran´ı StdEnti-tyDao pak pomoc´ı tˇr´ıdy EntityManager uloˇz´ı entitu PlayerTournamentEntity do datab´aze.

Nyn´ı se vr´at´ım k p´arovac´ım enginu. Ten obdrˇz´ı poˇzadavek na p´arov´an´ı a provede ho podle zvolen´eho turnajov´eho syst´emu. Algoritmus se liˇs´ı podle zvolen´eho turnajov´eho typu, syst´emu a enginu. Pop´ıˇsi nyn´ı algoritmus pro jednotliv´e syst´emy, kter´e aplikace podporuje. Opˇet zanedb´am turnajov´y typ a pop´ıˇsi jen turnaj jednotlivc˚u, jelikoˇz pro turnaj druˇzstev je to obdobn´e.

4.3.1 Holandsk´a varianta ˇsv´ycarsk´eho syst´emu

Tento syst´em je implementov´an extern´ım enginem JaVaFo. Vlastn´ı algorit-mus je tedy skryt. M´ym ´ukolem bylo pouze pˇripravit vstupy a zpracovat jeho v´ystupy. Tento engine podporuje v´ıce vstup˚u. Byl vybr´an TRF form´at.

4. Implementace

4.3.2 Baku akcelerace holandsk´e varianty ˇsv´ycarsk´eho syst´em Tento syst´em je opˇet implementov´an pomoc´ı enginu JaVaFo. Plat´ı vˇse, co bylo zm´ınˇeno v pˇredchoz´ı ˇc´asti. Rozd´ıl byl pouze v zavol´an´ı jin´eho k´odu v dan´e metodˇe. Pomoc´ı tohoto k´odu totiˇz rozliˇs´ı o jakou variantu syst´emu se jedn´a.

Pro klasickou holandskou variantu je definovan´ym k´odem 1000, zat´ımco pro jej´ı Baku akceleraci je definovan´ym k´odem 1001.

4.3.3 Jednokolov´y syst´em kaˇzd´y s kaˇzd´ym

Tento syst´em je implementov´an vlastn´ım enginem aplikace. Jako algoritmus byly zvoleny Bergerovy tabulky, kter´e byly pops´any v kapitole 1. Pokud je lich´y poˇcet hr´aˇc˚u, je pˇrid´an pro p´arovac´ı ´uˇcely hr´aˇc, kter´y pˇredstavuje bye. Na n´asleduj´ıc´ı uk´azce k´odu m˚uˇzeme vidˇet metodu gerRoundRobinMatches, zod-povˇednou za p´arov´an´ı. Tato metoda oˇcek´av´a seznam hr´aˇc˚u se sud´ym poˇctem, ˇcehoˇz se doc´ıl´ı jiˇz zm´ınˇen´ym postupem. D´ale pak oˇcek´av´a skuteˇcn´y poˇcet hr´aˇc˚u, ˇc´ıslo kola a parametr, kter´y je pro jednokolovou verzi kaˇzd´y s kaˇzd´ym vˇzdy false. V metodˇe se vol´a metoda roundRobinAddition, kter´a je zodpovˇedn´a za vypoˇcten´ı indexu hr´aˇce v dan´em seznamu hr´aˇc˚u.

Metoda pro generov´an´ı p´arov´an´ı v syst´emu kaˇzd´y s kaˇzd´ym /**

* Generates a pairing

* Berger tables method is used.

* @param players all players in the tournament, must be even

* @param playersCount actual players count

* @param roundNum number of the round

* @param secondHalfDoubleRoundRobin if pairing is for second half, for single round robin it is always false

* @return list of matches (ie. the pairing)

*/

private List<MatchEntity> getRoundRobinMatches(List<PlayerEntity>

players, int playersCount, int roundNum, boolean secondHalfDoubleRoundRobin) {

4.3. Implementace p´arov´an´ı kol players.size() - i - 1, roundNum));

}

MatchEntity match = new MatchEntity(whitePlayer, blackPlayer);

if (secondHalfDoubleRoundRobin && i != 0) { PlayerEntity temp = match.getWhite();

Tento syst´em je opˇet implementov´an vlastn´ım enginem aplikace. Algoritmus je v podstatˇe stejn´y jako pro jednokolovou verzi. Dokonce je vyuˇzita stejn´a metoda. Hlavn´ı rozd´ıl je pouze v tom, ˇze pˇri jej´ım vol´an´ı z´aleˇz´ı na tom, zda je turnaj v prvn´ı nebo druh´e polovinˇe. Pokud v prvn´ı, tak vol´an´ı je totoˇzn´e jako pro jednokolovou verzi a parametr secondHalfDoubleRoundRobin je false.

Naopak v druh´e polovinˇe turnaje je true. Co se t´yˇce samotn´eho algoritmu, tak se liˇs´ı pouze t´ım, ˇze pokud je turnaj v druh´e polovinˇe, tak se prohod´ı barvy hr´aˇc˚u kaˇzd´e partie. Neboli hr´aˇc, kter´y by mˇel v prvn´ı polovinˇe turnaje v dan´e partii b´ıl´e figury, bude m´ıt ˇcern´e a naopak.

4.3.5 Vyˇrazovac´ı syst´em

Tento syst´em je tak´e implementov´an vlastn´ım enginem aplikace. Pˇri jeho im-plementaci jsem neuvaˇzoval, kdo s k´ym m´a b´yt p´arov´an. Dan´e p´arov´an´ı je pseudon´ahodn´e. Na n´asleduj´ıc´ı uk´azce k´odu m˚uˇzeme vidˇet metodu doElimi-nationPairing, kter´a je zodpovˇedn´a za vlastn´ı p´arov´an´ı. Metoda je relativnˇe jednoduch´a. Vytvoˇr´ı mˇelkou kopii seznamu hr´aˇc˚u, kter´y obdrˇz´ı jako parametr.

Pot´e zkontroluje, zda nen´ı v dan´e kopii seznamu lich´y poˇcet hr´aˇc˚u. Pokud ano, pak do n´ı jednoduˇse pˇrid´a dalˇs´ı poloˇzku. Pˇresnˇeji ˇreˇceno hodnotu null.

Hodnota null totiˇz pˇredstavuje bye. D´ale pak v cyklu pseudon´ahodnˇe vyb´ır´a dva hr´aˇce a odstran´ı je z kopie seznamu a vytvoˇr´ı jejich z´apas. Tento z´apas jednoduˇse pˇrid´a do seznamu z´apas˚u. Po skonˇcen´ı cyklu jsou jiˇz vˇsichni hr´aˇci

4. Implementace

sp´arov´ani a metoda vrac´ı seznam z´apas˚u. Opˇet zde seznam z´apas˚u pˇredstavuje p´arov´an´ı dan´eho kola.

Metoda pro generov´an´ı p´arov´an´ı ve vyˇrazovac´ım syst´emu /**

* Generates a pairing

* @param tour player tournament

* @param playerList list of players to pairing

* @return list of matches (ie. the pairing)

*/

final int iterations = players.size() / 2;

for (int i = 0; i < iterations; i++) {

MatchEntity match = new MatchEntity(white, black);

matches.add(match);

}

return matches;

}

4.4 Implementace pomocn´ ych hodnocen´ı

Pomocn´e hodnocen´ı jsou potomky abstraktn´ı tˇr´ıdy RankingSystem. Tato tˇr´ıda deklaruje dvˇe abstraktn´ı metody, kter´e kaˇzd´e pomocn´e hodnocen´ı mus´ı im-plementovat. Jedn´a se v´ypoˇcet hodnoty pomocn´eho hodnocen´ı pro hr´aˇce ˇci druˇzstva dan´eho turnaje. Pomoc´ı tˇechto dvou metod pak definuje porovn´an´ı dvou hr´aˇc˚u nebo druˇzstev dan´eho turnaje. Implementace jednotliv´ych po-mocn´ych hodnocen´ı bylo provedeno pomoc´ı informac´ı z´ıskan´ych z kapitoly 1.

Pro jejich implementaci jsem nepouˇzil ˇz´adn´y engine, vˇse jsem

implemento-4.5. Logov´an´ı val s´am. Na n´asleduj´ıc´ı uk´azce k´odu, m˚uˇzeme vidˇet pˇr´ıklad naimplemento-van´eho pomocn´eho hodnocen´ı pro turnaj jednotlivc˚u. Jedn´a se o Buchholz˚uv syst´em. Nejprve z´ısk´a od turnaje body vˇsech hr´aˇc˚u a seznam soupeˇr˚u hr´aˇce, pro kter´eho se hodnota tohoto pomocn´eho hodnocen´ı vypoˇc´ıt´av´a. Pot´e jed-noduˇse seˇcte body vˇsech jeho soupeˇr˚u a tento souˇcet vr´at´ı.

Metoda pro v´ypoˇcet hodnoty pomocn´eho hodnocen´ı Buchholz

@Override

public int getValue(PlayerTournament tour, PlayerEntity player) throws ApplicationLogicException {

Map<Integer, Integer> playersPoints = tour.getPlayersPoints();

List<PlayerEntity> opponents = tour.getOpponents(player);

int opponentPoints = 0;

for (PlayerEntity i : opponents) {

opponentPoints += playersPoints.get(i.getId());

}

return opponentPoints;

}

4.5 Logov´ an´ı

Logov´an´ı bylo implementov´ano v datov´e vrstvˇe pomoc´ı tˇr´ıdy Logger. Tˇr´ıda obsahuje pouze jednu statickou metodu writeToLog. Tato metoda pˇrij´ım´a dva parametry. Prvn´ı je v´yjimka a druh´y je zpr´ava, kter´a m´a b´yt uloˇzena do logo-vac´ıho souboru. V´yjimka slouˇz´ı pro uloˇzen´ı z´aznamu z´asobn´ıku k dan´e zpr´avˇe.

Hodnota null je pro oba parametry povolena. Byly tak´e naimplementov´any v´yjimky, po jejichˇz vytvoˇren´ı dojde automaticky k z´apisu do logovac´ıho sou-boru. Dˇeje se tak pr´avˇe prostˇrednictv´ım tˇr´ıdy Logger. Jedn´a se o v´yjimky BaseException a UnexpectedException. BaseException je abstraktn´ı tˇr´ıda a jej´ı potomci pˇredstavuj´ı vlastn´ı v´yjimky. Jedn´a se o ApplicationLogicEx-ception, FileExApplicationLogicEx-ception, InvalidDataException a NoEntityFoundException. Je-likoˇz v´yjimka BaseException dˇed´ı od tˇr´ıdy Exception, mus´ı se ona i vˇsechny jej´ı potomci v aplikaci zachyt´avat a oˇsetˇrit. Naproti tomu v´yjimka Unexpecte-dException je potomkem tˇr´ıdy RuntimeException a tedy se zachyt´avat nutnˇe nemus´ı.

4.6 Instalace aplikace

Instalace je velmi jednoduch´a. Aplikace je pˇredstavov´ana pouze jedn´ım koˇrenov´ym adres´aˇrem, kter´y obsahuje spouˇstˇec´ı soubor ChessTournamentMa-nager.jar a pomocn´e adres´aˇre db, logs, uploads a temp. Aplikace se m˚uˇze dis-tribuovat napˇr´ıklad zabalena do libovoln´eho archivu. Na c´ılov´ym poˇc´ıtaˇci je

4. Implementace

pak potˇreba pouze extrahovat koˇrenov´y adres´aˇr aplikace na libovoln´e m´ısto.

Je vˇsak nutn´e, aby vˇsechny ˇc´asti aplikace mˇely pr´ava ˇc´ıst a zapisovat.

Nyn´ı pop´ıˇsi jednotliv´e podadres´aˇre. Podadres´aˇr db je vyuˇz´ıv´an pro uloˇzen´ı datab´azov´eho souboru database.mv.db. Pokud tento soubor neexistuje, je po spuˇstˇen´ı aplikace automaticky vytvoˇren. Tento soubor pˇredstavuje celou da-tab´azi a tedy vˇsechna data aplikace. M˚uˇze se jednoduˇse z´alohovat pouh´ym pˇrekop´ırov´an´ım. Pokud uˇzivatel napˇr´ıklad smaˇze omylem turnaj, m˚uˇze pak pˇrekop´ırovat z´alohu do adres´aˇre db. Mus´ı se vˇsak jmenovat stejnˇe. Pro logo-vac´ı ´uˇcely m˚uˇze aplikace vygenerovat do toho adres´aˇre logovac´ı soubor data-base.mv.db. Dalˇs´ım podadres´aˇrem je logs, kter´y obsahuje soubor log.txt. Do nˇej aplikace ukl´ad´a kromˇe intern´ıch chyb tak´e r˚uzn´a upozornˇen´ı, kter´e pak mohou pomoci napˇr´ıklad pˇri zjiˇst’ov´an´ı, proˇc se dan´a operace nezdaˇrila. Po-kud neexistuje, bude aplikac´ı v pˇr´ıpadˇe potˇreby automaticky vytvoˇren. Dalˇs´ım podadres´aˇrem je uploads. Zde aplikace ukl´ad´a vˇsechny soubory, kter´e byly pˇripojeny k urˇcit´emu kolu. Pokud tedy uˇzivatel smaˇze nˇekter´y soubor, jiˇz ho nebude moci z aplikace st´ahnout. Tak´e zde plat´ı, ˇze lze tyto soubory z´alohovat a tak´e, ˇze pˇri vracen´ı z´alohy se mus´ı soubory jmenovat stejnˇe jako pˇredt´ım.

Posledn´ım podadres´aˇrem je temp. Slouˇz´ı pro ukl´ad´an´ı doˇcasn´ych soubor˚u.

Pokud aplikace nen´ı spuˇstˇena mohou se tyto soubory kdykoli smazat.

4.7 Dokumentace aplikace a zveˇ rejnˇ en´ı otevˇ ren´ eho odu

Pro zdokumentov´an´ı zdrojov´ych k´od˚u aplikace jsem vyuˇzil Javadoc. Po zdo-kumentov´an´ı nejd˚uleˇzitˇejˇs´ıch metod a atribut˚u, jsem pak vygeneroval do-kumentaci. Tu m˚uˇzeme nal´ezt v pˇriloˇzen´em DVD v adres´aˇri doc. Jelikoˇz m´a b´yt aplikace open-source, vytvoˇril jsem na port´alu github.com repozit´aˇr pro zdrojov´e k´ody. Repozit´aˇr jsem vˇsak zat´ım ponechal soukrom´y, abych pˇredeˇsel pot´ıˇz´ım. Napˇr´ıklad by nˇekdo mohl m˚uj k´od pouˇz´ıt a j´a bych pak musel vysvˇetlovat, proˇc pouˇz´ıv´am stejn´y k´od jako dan´a osoba. Repozit´aˇr je plnˇe pˇripraven a po obhajovˇe t´eto pr´ace ho nastav´ım jako veˇrejn´y. Jeho url je https://github.com/pahorjir/Chess Tournament Manager. Tato url je bez pˇrihl´aˇsen´ı do m´eho ´uˇctu na port´alu github.com z v´yˇse zm´ınˇen´ych d˚uvod˚u zat´ım nedostupn´a.

4.8 Porovn´ an´ı implementovan´ eho ˇ reˇ sen´ı s existuj´ıc´ımi metodami

Aplikaci jsem naimplementoval tak, aby byla intuitivn´ı a snadno pouˇziteln´a.

Neobsahuje tedy tolik funkcionalit jako napˇr´ıklad aplikace Swiss-Manager nebo SwissSys. Naproti tomu m´a vˇsak oproti nim pouˇzitou modern´ı tech-nologii pro grafick´e uˇzivatelsk´e rozhran´ı. Poˇctem funkcionalit je srovnateln´a

4.8. Porovn´an´ı implementovan´eho ˇreˇsen´ı s existuj´ıc´ımi metodami s open-source aplikac´ı JavaPairing. Na rozd´ıl od n´ı m´a vˇsak l´epe navrˇzenou architekuru a je dle m´eho n´azoru obecnˇe l´epe naimplementovan´a. D´ıky zvo-len´e architektuˇre lze snadno vymˇenit uˇzivatelsk´e rozhran´ı, datab´azi, pˇridat p´arovac´ı enginy, pomocn´a hodnocen´ı atd., coˇz nemus´ı b´yt pro JavaPairing jednoduch´e. Oproti aplikaci stChess m´a mnohem v´ıce funkcionalit a neobsa-huje reklamu a oproti aplikaci Vega je kompletnˇe zdarma a open-source.

Kapitola 5

Testov´ an´ı

V t´eto kapitole budu popisovat, jak jsem otestoval naimplementovanou apli-kaci. Jednalo se o manu´aln´ı testov´an´ı GUI a pouˇz´ıv´an´ı jednotkov´ych test˚u.

Oba zp˚usoby jsem vˇsak pouˇz´ıval jiˇz pˇri v´yvoji.

5.1 Manu´ aln´ı testov´ an´ı GUI

Manu´aln´ı testov´an´ı jsem pouˇz´ıval pˇredevˇs´ım na ovˇeˇren´ı, zda jednotliv´e GUI elementy spr´avnˇe funguj´ı. Napˇr´ıklad jestli stisknut´ı tlaˇc´ıtka vykon´a danou akci. Tak´e jsem to pouˇz´ıval pro testov´an´ı, zda se s aplikac´ı pracuje pohodlnˇe.

Manu´aln´ım testov´an´ım vˇetˇsinou neˇslo o testov´an´ı spr´avn´eho fungov´an´ı logiky aplikace.

Chybu jsem bˇehem implementace vˇetˇsinou rozpoznal tak, ˇze jsem vidˇel, ˇ

ze aplikace neprovedla danou akci nebo j´ı provedla ˇspatnˇe. Pom´ahali tak´e chybov´e hl´aˇsky a upozornˇen´ı ve v´yvojov´em prostˇred´ı. Pozdˇeji pom´ahaly tak´e naimplementovan´e chybov´e dialogy a logov´an´ı. Na obr´azku 5.1 m˚uˇzeme vidˇet chybov´y dialog, kter´y ozn´amil chybu pˇri vykon´av´an´ı dan´e akce. Konkr´etnˇe se zde jednalo o chybu pˇri p´arov´an´ı hr´aˇc˚u v syst´emu kaˇzd´y s kaˇzd´ym v tur-naji jednotlivc˚u. Kdykoli po upozornˇen´ı jsem se mohl pod´ıvat do logovac´ıho souboru, co danou chybu zp˚usobilo.

5.2 Jednotkov´ e testy

Pomoc´ı jednotkov´ych test˚u jsem testoval, zda logika aplikace funguje spr´avnˇe.

Jednotkov´e testy byly tak´e velmi uˇziteˇcn´e, kdyˇz jsem provedl zmˇeny v k´odu.

Po jejich spuˇstˇen´ı jsem zjistil, zda jsem nerozbil nˇejakou funkˇcnost aplikace.

D´ıky zvolen´e architektuˇre lze kromˇe business a datov´e vrstvy tak´e testovat pre-zentery z prezentaˇcn´ı vrstvy. To je zp˚usobeno t´ım, ˇze prezentery nepouˇz´ıvaj´ı grafick´e elementy. Ty jsou pouˇz´ıv´any pouze pohledy. Nejprve uk´aˇzi uk´azku jednotkov´eho testu pro tˇr´ıdu StandardPlayerTournament. Pomoc´ı nich jsem

5. Testov´an´ı