\chapter{Implementácia}

\label{kap:implementacia}

Systém je implementovaný ako súbor programov bežiacich v kontaineroch. Každý program má svoju úlohu.
\begin{enumerate}
    \item Open Street Maps tile server
    \item Webový server pre frontend
    \item Webový server pre backed
    \item Konzolová aplikácia Seed
    \item Background service IpInfoMap
    \item Background service CountryPingInfo
\end{enumerate}

\section{Nástroje používané na implementáciu}

Na písanie kódu sa dajú používať rôzne nástroje v závislosti od jazyka, v ktorom chceme kód písať. Na písanie backendového kódu v C\# 
sa najčastejšie používajú nástroje Visual Studio alebo Rider. Vzhľadom na osobnú preferenciu sme sa rozhodli použiť nástroj Visual Studio 2022, 
ktorého Community verzia je zadarmo na stiahnutie.

Na písanie frontendového kódu v TypeScript, HTML a CSS sa najčastejšie používajú nástroje Visual Studio Code, WebStorm alebo aj rôzne iné. 
Vzhľadom na osobnú preferenciu sme sa rozhodoli použiť WebStorm, na ktorý máme udelenú študentskú licenciu.

\section{Štruktúra backendového riešenia}

V jazyku C\# je možnosť zoskupovať viacero aplikácií do jedného riešenia. V praxi to vyzerá tak, že riešenie je znázornené ako súbor .sln a každá 
aplikácia alebo knižnica je znázornená ako súbor .csproj. Aplikáciám a knižniciam sa vnútorne hovorí projekty. V našom riešení sa nachádzajú nasledovné 
projekty:

\begin{itemize}
    \item IpInfoViewer.Web
    - projekt, v ktorom je obsiahnuté riešenie frontendovej časti aplikácie
    \item IpInfoViewer.Api
    - projekt slúžiaci ako API pre komunikáciu medzi backendom a frontendom
    \item IpInfoViewer.IpInfoService
    - projekt, ktorý slúži ako služba bežiaca na pozadí ktorá vytvorí v lokálnom dátovom sklade zoznam všetkých ip adries s ich lokalitami a krajinami
    \item IpInfoViewer.CountryPingInfoService
    - projekt, ktorý slúži ako služba bežiaca na pozadí spracovávajúca údaje v týždenných intervaloch o dobe odozvy pre danú krajinu
    \item IpInfoViewer.MapPointsService
    - projekt, ktorý slúži ako služba bežiaci na pozadí spracovávajúca údaje v týždenných intervaloch o dobe odozvy pre dané geografické 
    okolie (zemepisnú šírku a dĺžku)
    \item IpInfoViewer.Libs
    - knižnica obsahujúca väčšinu aplikačnej logiky, tak aby bola zahrnuteľná zo všetkých ostatných projektov
\end{itemize}

\subsection{IpInfoViewer.Api}
Tento projekt je ASP.NET Core 6.0 aplikácia bežiaca na webovom serveri Kestrel. Obsahuje nasledujúce triedy: 
\begin{itemize}
    \item Program
    - Základná trieda každého spustiteľného programu. Jej metóda Main je vstupným bodom každého C\# programu, teda po spustení programu sa automaticky 
    začne vykonávať. Registrujú sa v nej triedy do DI kontainera (Dependency Injection), z ktorého sa potom vyberajú z iných tried vrámci behu programu. 
    Tiež tu prebieha inicializácia potrebných nastavení programu. Od verzie .NET 6.0 je podporovaná upravená syntax tejto triedy na tzv. \uv{top-level statements}. 
    To znamená, že v súbore Program.cs je vynechaná inicializácia triedy Program a metódy Main, nakoľko bola v každom 
    programe rovnaká. Vnútorne sú však tieto triedy stále používané, ide len o syntaktickú skratku. Používanie top-level statements 
    je dobrovoľné, vrámci čistoty kódu ich ale využívame.
    \begin{lstlisting}[language={[Sharp]C},caption={Ukážka kódu triedy Program bez použitia \uv{top-level statements}},label=alg:Program_Old]
        class Program 
        {
            public static void Main(string[] args) 
            {
                System.Console.WriteLine("Hello World");
            }
        }
    \end{lstlisting}
    \begin{lstlisting}[language={[Sharp]C},caption={Ukážka kódu triedy Program s použitím \uv{top-level statements}},label=alg:Program_New]
        System.Console.WriteLine("Hello World");
    \end{lstlisting}
    \item MapPointsController
    - Trieda slúži ako súbor metód, ktoré sa dajú volať cez protokol HTTP z frontendovej časti aplikácie. Obsahuje metódy pre získavanie 
    dát zoskupených podľa zemepisnej dĺžky a šírky.
    \item CountryPingInfoController
    - Súbor metód volateľných cez HTTP. Obsahuje metódy pre dáta zoskupené podľa krajiny.
\end{itemize}
\subsection{IpInfoViewer.IpInfoService}
Projekt je konzolová aplikácia bežiaca ako služba na pozadí. Obsahuje nasledovné triedy:
\begin{itemize}
    \item Program
    \item IpInfoServiceWorker
    - Treida reprezentujúca samotnú službu. Trieda je zadefinovaná v triede Program ako \uv{Hosted Service}, teda pri spustení sa vykoná jej metóda ExecuteAsync. 
    Načíta súbor s priradením medzi IP adresou a geografickými dátami a paralelne pošle každý jeho riadok na spracovanie.
\end{itemize}
\subsection{IpInfoViewer.CountryPingInfoService}
Projekt je rovnako konzolová aplikácia bežiaca ako služba na pozadí. Obsahuje nasledovné triedy:
\begin{itemize}
    \item Program
    \item CountryPingInfoServiceWorker
    - \uv{Hosted Service} tejto služby.
    Načita všetky známe IP adresy spracované službou IpInfoService. Následne ich zoskupí podľa krajín prislúchajúcich daným adresám. 
    Nakoniec ešte zistí, kedy boli dáta naposledy spracovávané a pošle na spracovanie dáta paralelne pre každý týždeň od posledného spracovania 
    až po súčasnosť.
\end{itemize}
\subsection{IpInfoViewer.MapPointsService}
Taktiež služba na pozadí. Obsahuje nasledovné triedy:
\begin{itemize}
    \item Program
    \item MapPointsServiceWorker
    - \uv{Hosted Service} tejto služby.
    Funguje rovnako ako CountryPingInfoServiceWorker, ale adresy zoskupuje podľa geografických súradníc. Adresy sú rozdelené do stabilných sektorov 
    na mape. Mapa je rozdelená do 23x60 sektorov rovnomerne podľa geografickej šírky a dĺžky. 
\end{itemize}
\subsection{IpInfoViewer.Libs}
Knižnica zoskupujúca logiku všetkých C\# programov. Ostatné programy ju využívajú ako referenciu. Je tomu tak preto, lebo programy navzájom zdieľajú 
časť logiky a bolo by nesprávne túto logiku písať do každého programu zvlášť. Tiež sme sa chceli vyhnúť referencovaniu ostatných spustiteľných programov navzájom 
priamo, pretože sa to ukázalo ako nepraktické. Dôvodov je niekoľko, najvážnejší s ktorým sme sa stretli je konflikt mien konfiguračných súborov. Pri C\# 
projektoch je zaužívané používať konfiguračné súbory s menami appsettings.json a appsettings.{environmentName}.json. Tiež je pravidlo, že keď referencujeme 
iný projekt, do priečinka s výstupom kompilácie idú všetky súbory rovnako, ako keď kompilujeme projekt samotný. Keďže aj pôvodný projekt aj referencovaný projekt 
obshujú súbory appsettings.json, nastane konflikt a do výstupného priečinka sa nakopíruje len jeden z nich, a podľa skúseností to bol vždy ten z referencovaného projektu, 
čo je ten nesprávny. Tomuto sa dá vyhnúť tým, že spustiteľné projekty sa navzájom nereferencujú a namiesto toho všetky referencujú jednu knižnicu. Knižnica nemá takéto 
konfiguračné súbory, preto ku konfliktu nedochádza. Knižnica IpInfoViewer.Libs obsahuje nasledovné triedy: 
\begin{itemize}
    \item BaseModel
    - Abstraktná trieda z ktorej dedia všetky modely, teda triedy predstavujúce dáta. Obsahuje všetky parametre ktoré by mali zdieľať všetky modely v riešení. V súčasnosti 
    je jediným takýmto parametrom Id, teda primárny kľúč v databázovej tabuľke, v našom riešení znázornené ako 64-bitové celé číslo.
    \item BaseWeeklyProcessedModel
    - Abstraktná trieda, ktorá je rozšírením triedy BaseModel o vlastnosť Week reprezentovanú reťazcom. Táto vlastnosť 
    sa opakovala vo všetkých časovo spracovávaných triedach.
    \item BaseMapModel 
    - Abstraktná trieda ktorá je rozšírením BaseMapModel o vlastnosti IpAddressesCount, AveragePingRtT, MinimumPingRtT, MaximumPingRtT. 
    Ide o pre nás zaujímavé vlastnosti ktoré sa vyskytovali vo 
    viacerých modeloch. Prvá znázorňuje počet IP adries ktoré daný záznam znázorňuje, zvyšné ich priemernú, minimálnu a maximálnu dobu odozvy v milisekundách.
    \item CountryPingInfo
    - Model predstavujúci dáta pre konkétnu krajinu v konkrétny týždeň. Rozširuje BaseMapModel o vlastnosť CountryCode, ktorá predstavuje ISO skratku konkrétnej
    krajiny.
    \item IpAddressInfo
    - Model predstavujúci jednu IP adresu s geografickými informáciami ako mesto, krajina a geografické súradnice.
    \item MapPointsController
    - Model predstavujúci dáta pre konkrétny geografický sektor v konkrétnom čase. Rozširuje BaseMapModel o geografickú šírku a dĺžku.
    \item String response
    - Model prestavujúci HTTP odpoveď pozostávajúcu z jediného reťazca. Takýto model je potrebný, pretože po správnosti by sa nemal vracať 
    samotný reťazec ako telo odpovede, ale mal by byť zabalený do rodičovského objektu, pretože niektoré knižnice takéto odpovede nepodporujú.
    \item Week
    - Keďže dáta spracovávame po týždňoch, potrebovali sme si vedieť takýto týždeň znázorniť. Ako jeden týždeň sme si určili obdobie začínajúce v pondelok o polnoci a končiace 
    v nedeľu toho istého týždňa tesne pred polnocou ako je definované v štandarde ISO 8601. Tento štandard určuje spôsob, ako vyjadriť konkrétny týždeň ako textový reťazec, 
    a to vo formáte YYYY-'W'WW, teda napríklad deviaty týždeň roku 2023 by bol vyjadrený ako 2023-W09. Tento formát zápisu týždňa je podporovaný ako formát výstupu pre 
    HTML input typu \uv{week}, preto je pre našu aplikáciu veľmi užitočný. V jazyku C\# však neexistuje žiadna vstavaná trieda reprezentujúca takýto týždeň, jednu sme preto napísali 
    podľa našich potrieb. Trieda podporuje dva rôzne konštruktory, teda dva rôzne spôsoby ako definovať týždeň. Prvý spôsob je podľa už zmieneného ISO 8601 formátu. Druhý spôsob 
    si vezme na vstup ľubovoľný čas reprezentovaný štandardnou triedou DateTime a určí týždeň, do ktorého daný čas patrí. Na základe definície ISO 8601 každý čas patrí do práve jedného 
    dňa a každý deň patrí do práve jedného týždňa. 
    \item DateTimeUtilities
    - Trieda zoskupujúca pomocné metódy na prácu s časom. Momentálne má len jednu metódu GetWeeksFromTo, ktorá prijme dva dátumy a vráti zoznam týždňov 
    medzi nimi.
    \item GeographicUtilities
    - Trieda zoskupujúca pomocné metódy na prácu s geografickými dátami. Momentálne obsahuje jeden konštantný slovník CountryCodeToNameDictionary, ktorý slúži 
    na prevod ISO 3166-1 Alpha 2 kódu na ISO názov krajiny.
    \item Host
    - Model predstavujúci jednu IP adresu v zdrojovej databáze.
    \item Ping
    - Model predstavujúci jedno volanie príkazu ping na konkrétnu IP adresu v zdrojovej databáze.
    \item IIpInfoViewerDbRepository
    - Rozhranie definujúce metódy, ktorými sa dajú vyťahovať dáta z lokálneho dátového skladu. 
    \item IpInfoViewerDbRepository
    - Trieda slúžiaca na vyťahovanie dát z lokálneho dátového skladu. Implementuje rozhranie IIpInfoViewerDbRepository.
    \item IMFileDbRepository
    - Rozhranie definujúce metódy určené na vyťahovanie dát zo zdrojovej databázy.
    \item MFileDbRepository
    - Trieda slúžiaca na výber dát zo zdrojovej databázy. Implementuje rozhranie IMFileDbRepository.
    \item ICountryPingInfoFacade
    - Rozhranie definujúce metódy obsahujúce logické manipulácie s dátami ohľadom IP adries zoskupených podľa krajín.
    \item CountryPingInfoFacade
    - Trieda obshujúca logickú manipuláciu s dátami ohľadom IP adries zoskupených podľa krajín. Implementuje rozhranie ICountryPingInfoFacade.
    \item IIpAddressInfoFacade
    - Rozhranie definujúce metódy využívané pri priraďovaní geografických informácií k databázam.
    \item IpAddressInfoFacade
    - Implementácia priraďovania IP adries ku geografickým dátam ako krajiny a súradnice. Implementuje rozhranie IIpAddressInfoFacade.
    \item IMapPointsFacade
    - Rozhranie definujúce metódy obsahujúce logické manipulácie s dátami ohľadom IP adries zoskupených podľa geografických súradníc.
    \item MapPointsFacade
    - Implementácia manipulácie s dátami zoskupenými podľa geografických súradníc. Implementuje rozhranie IMapFacade.
\end{itemize}

\section{Štruktúra frontendovej časti aplikácie}
Frontendová časť aplikácie spočíva z jedinej aplikácie písanej pomocou frameworku Angular 15. Projekt bol vytvorený pomocou templatu vo Visual Studio 2022, vďaka čomu bolo možné ho 
spúšťať s Visual Studia a bol zahrnutý do jedného .sln súboru, čo nám zjednodušilo manipuláciu. Z používateľského hľadiska aj z hľadiska písania kódu je to ale ekvivalentné 
vygenerovaniu projektu pomocou príkazu \lstinline{ng new}.

Jednou z hlavných výhod využitia frameworku ako napríklad Angular je, že aplikáciu je možné deliť na komponenty. Jeden komponent je možné si predstaviť ako istú podčasť zobrazenej stránky. 
Každý komponent sa môže skladať z viacerých iných komponentov. Naša aplikácia obsahuje nasledovné komponenty:
\begin{itemize}
    \item app.component
    - Základný komponent pre každú aplikáciu. Všetky ostatné komponenty sú jeho podkomponenty. Reprezentuje celé okno aplikácie. Framework Angular je defaultne nastavený aby vždy 
    zobrazoval práve tento komponent. 
    \item nav-menu.component
    - Komponent reprezentujúci vrchný panel s menu aplikácie.
    \item ip-address-map.component
    - Komponent reprezentujúci mapu s vyznačenými ip adresami zoskupenými podľa geografických súradníc.
    \item country-ping-map.component 
    - Komponent reprezentujúci mapu krajín zafarbených podľa pingu.
\end{itemize}

\section{Dôležité algoritmy a postupy riešenia}
\label{postupy}

Pri implementácií aplikácie sme využívali niekoľko špecifických postupov a algoritmov, ktoré považujeme za vhodné vysvetliť a zdôvodniť. 

\subsection{CORS}
\uv{Cross-Origin Resource Sharing} je mechanizmus na zdieľanie obsahu stránok z rôznych domén pracujúci na základe HTTP hlavičiek. Tento mechanizmus je nutné použiť na zdieľanie dát medzi
frontendovou a backendovou časťou aplikácie. V systéme ASP.NET Core 6.0 je možnosť zadefinovať \uv{CORS} hlavičky pre všetky endpointy naraz v triede Program. Náš systém dovoľuje všetky 
zdroje, hlavičky aj metódy.

\subsection{Zoskupovanie IP adries na domovskej stránke}
Na domovskej stránke sa nachádza mapa sveta a na nej sú vyznačené body znázorňujúce skupiny IP adries zoskupené podľa geografickej blízkosti. 
Adresy boli zoskupené podľa geografických súradníc takým spôsobom, aby skupín vzniklo co najviac, ale zároveň stránka zostala funkčná a responzívna. 
Jedna skupina je ekvivalentná jednému sektoru na mape.
Stránka sa stane neresponzívnou v prípade, ak je zobrazených príliš veľa skupín. Vtedy knižnica Leaflet nestíha skupiny dostatočne rýchlo prekresľovať pri 
pohybe alebo zväčšovaní mapy. Dôležité bolo preto odhadnúť čo najväčši počet skupín tak, aby ich stránka bola stále schopná zobrazovať. Tento počet bol 
systémom pokus-omyl odhadnutý na  . Na testovanie bola použitý kód v ukážke \ref{alg:Markers_Seed}. Najskôr sme skúsili vygenerovať jeden kruh na každú rovnobežku 
a na každý poludník, čo znamená 64800 kruhov. To sa ukázalo ako priveľa a tak sme skúsili vygenerovať kruh len na každú desiatu rovnobežku a každý desiaty poludník, 
čiže dokopy 648 kruhov, čo aplikácia v prehliadači zvládala. Skúsili sme preto každú piatku rovnobežku a každý piaty poludník, čiže 2592 kruhov. Aplikácia sa
v prehliadači stále zvládala zobrazovať. Následne sme postupným pridávaním získali hodnotu približne 6000 kruhov, teda 6000 sektorov na mape. Toto číslo sme 
následne vynásobili tromi, pretože približne dve tretiny zemského povrchu tvorí voda, v ktorej neočakávame takmer žiadne odpovedajúce IP adresy. Teda z 18000 
sektorov bude približne 12000 prázdnych a teda sa zmestíme do 6000 vykreslených kruhov. 

\begin{lstlisting}[language={TypeScript},caption={Ukážka kódu použitého na testovanie počtu možných skupín},label=alg:Markers_Seed]
    getMarkers(mapPoints: MapIpAddressRepresentation[], zoom: number): Leaflet.CircleMarker[] {
        let markers: Leaflet.CircleMarker[] = [];
        for(let lat= -90; lat<=90; lat++){
            for(let lon = -180; lon <=180; lon++){
                markers.push(new Leaflet.CircleMarker(new Leaflet.LatLng(lat, lon)))
            }
        }
    }
\end{lstlisting}

Máme teda niekoľko možností ako rozdeliť mapu na 18000 sektorov, my sme sa rozhodli pre zaokrúhlenie zemepisnej šírky a dĺžky na najbližšiu menšiu rovnobežku 
deliteľnú tromi a na najbližší menší poludník deliteľný šiestimi. Aby body na mape vyzerali prirodzene, za ich stred sme určili aritmetický priemer všetkých 
bodov v danej skupine namiesto príslušnej zaokrúhlenej hodnoty.

Veľkosť daného kruhu znázorňuje počet IP adries patriacich do daného sektoru. Rozhodli sme sa, že závislosť medzi počtom adries a polomerom kruhu bude 
logaritmická, pretože v rôznych sektoroch boli rozdiely medzi počtami niekedy rádovo aj desaťtisícnásobné, čo má za následok že menšie sektory by boli prakticky 
neviditeľné. Vzorec na výpočet tiež obsahuje aj úroveň priblíženia, pretože pri nízkych úrovňach priblíženia sa kruhy príliš prelínali. Preto kruhy začínajú 
menšie a rastú s úrovňou priblíženia. Konkrétny vzorec bol upravený tak, aby kruhy na mape vyzerali prirodzene. Vzorec je uvedený v 
ukážke \ref{alg:Count_To_Size}.

\begin{lstlisting}[language={TypeScript},caption={Ukážka kódu na výpočet veľkosti kruhu z počtu IP adries v sektore},label=alg:Count_To_Size]
    ipCountToCircleRadius(ipCount: number, zoom: number): number{
        return 0.5 * Math.log(ipCount) * zoom;
    }
\end{lstlisting}

Farba kruhu je zase určená priemernou dobou odozvy v danom sektore pre daný týždeň. Rozhodli sme sa, že chceme nízke hodnoty doby odozvy reprezentovať 
zelenou farbou a vysoké hodnoty doby odozvy červenou farbou. Všetko medzi má byť adekvátne na škále medzi týmito dvoma farbami. Ako vhodné sa preto ukázalo 
určovať farbu pomocou RGB notácie (jazyk CSS podporuje aj HSL notáciu). Hodnotu B sme určili konštantne na 0. Cieľom je teda rovnomerne sa presunúť medzi 
RGB hodnotami v HTML notácií \lstinline{#00FF00} do \lstinline{#FF0000} s rastúcou dobou odozvy. Ako hornú hranicu pre úplne červenú farbu sme zvolili 500 ms. 
Túto hranicu sme zvolili preto, že odchýlky k najvyššej dobe odozvy pri niektorých týždňoch boli priveľké. Ako spodnú hranicuu pre absolútnu zelenú sme zvolili 
hodnotu 5 ms, pretože menšie hodnoty považujeme za zanedbateľné z hľadiska odchýlky merania. Presný algoritmus je uvedený v ukážke \ref{alg:Ping_to_color}.

\begin{lstlisting}[language={TypeScript},caption={Ukážka kódu na výpočet veľkosti kruhu z počtu IP adries v sektore},label=alg:Ping_to_color]
    pingToColor(ping: number) {
        const upperBound = 500;
        const lowerBound = 5;
        let pingInBounds = ping;
        if(pingInBounds < lowerBound)
        pingInBounds = lowerBound;
        if(pingInBounds > upperBound)
        pingInBounds = upperBound;
        let percent = (pingInBounds - lowerBound)/(upperBound - lowerBound);
        let r = Math.round(255*percent), g = Math.round((1-percent)*255), b = 0;
        let h = r * 0x10000 + g * 0x100;
        return '#' + ('000000' + h.toString(16)).slice(-6);
    }
\end{lstlisting}

\subsection{Mapa krajín sveta zafarbených podľa priemernej doby odozvy}
Keďže knižnica Leaflet nepodporuje jednoduchý spôsob zafarbovania celých krajín, namiesto toho sme sa rozhodli použiť iný postup. Pomocou vyhľadávača sme
našli vzor mapy sveta vo fromáte SVG. Na prácu s dokumentmi SVG existuje v jazyku C\# niekoľko knižníc, my sme sa rozhodli pre knižnicu GrapeCity. 
Formát SVG má tú výhodu, že ak vieme priradiť ku konkrétnej krajine daný objekt jej tvaru na obrázku, vieme v programe 
jednoducho tento objekt uchopiť a prefarbiť. SVG vzor, ktorý sme použili \cite{svg_mapa} mal predpoklady na takéto priradenie, pre optimálne použitie ich 
však bolo treba upraviť. Hlavný problém nezmeneného templatu bolo nekonzistenté pomenovávanie prvkov \lstinline{path}, kde boli náhodne pre rôzne prvky 
pomenované ISO 3166-1 Alpha 2 kôdom v atribúte id, menom krajiny v atribúte name alebo menom krajiny v atribúte class či ľubovoľnou kombináciouv daných atribútov. 
Pre nás bolo najvhodnejšie tento systém zjednotiť pre všetky prvky rovnako. Z toho dôvodu sme vylúčili možnosť ISO 3166-1 Alpha 2 kódu v atribúte id, pretože rôzne krajiny 
sa môžu skladať z viacerých prvkov \lstinline{path} (napríklad rôzne ostrovy), no id musí byť jedinečné pre konkrétny SVG dokument. Atribút name je netypický 
pre SVG dokumenty a použitá knižnica v C\# s ním nevie pracovať, preto sme si zvolili identifikáciu podľa atribútu class. Ďaľší problém je, že niektoré krajiny 
majú viacero dlhých názvov, no my potrebujeme jeden jednoznačný reťazec na identifikáciu. Preto sme sa rozhodli, že prvky \lstinline{path} budeme identifikovať 
podľa ISO 3166-1 Alpha 2 kódu v atribúte class. Preto pri spracovávaní dát pre tento graf ukladáme ISO 3166-1 Alpha 2 kód krajiny. Súbor sme programom 
upravili tak, aby všetky prvky \lstinline{path} mali v atribúte class aj hodnotu adekvátneho ISO 3166-1 kôdu. Pôvodné triedy sme ponechali tiež, pretože jeden 
prvok môže patriť do viacerých tried, stačí ich oddeliť medzerou. 


\begin{figure}
    \centerline{\includegraphics[width=0.8\textwidth]{images/world}}
    %popis obrazku
    \caption[Neupravený svg vzor]{Pôvodný vzor so SVG mapou sveta, ktorý sme upravili pre lepšie použitie. }
    %id obrazku, pomocou ktoreho sa budeme na obrazok odvolavat
    \label{obr:world}
\end{figure}

\begin{lstlisting}[language={XML},caption={Ukážka kódu neupravenej SVG mapy.},label=alg:map_orig]
    ...
    <path class="Canada" d="M 665.9 203.6 669.3 204.5 674 204.3 670.7 206.9 668.7 207.3 663.2 204.6 662.6 202.5 665.1 200.6 665.9 203.6 Z">
    </path>
    ...
    <path d="M1633.1 472.8l2.2-2.4 4.6-3.6-0.1 3.2-0.1 4.1-2.7-0.2-1.1 2.2-2.8-3.3z" id="BN" name="Brunei Darussalam">
    </path>
    ...
    <path class="Azerbaijan" d="M 1229 253.2 1225.2 252.3 1222 249.4 1220.8 246.9 1221.8 246.8 1223.7 248.5 1226 248.5 1226.2 249.5 1229 253.2 Z">
    </path>
    ...
\end{lstlisting}

\begin{lstlisting}[language={XML},caption={Ukážka kódu upravenej SVG mapy.},label=alg:map_edited]
    ...
    <path class="Canada CA " d="M665.9,203.6 669.3,204.5 674,204.3 670.7,206.9 668.7,207.3 663.2,204.6 662.6,202.5 665.1,200.6 665.9,203.6Z"/>
    ...
    <path id="BN" class=" BN" d="M1633.1,472.8l2.2,-2.4 4.6,-3.6 -.1,3.2 -.1,4.1 -2.7,-.2 -1.1,2.2 -2.8,-3.3z" name="Brunei Darussalam"/>
    ...
    <path class="Azerbaijan AZ " d="M1229,253.2 1225.2,252.3 1222,249.4 1220.8,246.9 1221.8,246.8 1223.7,248.5H1226L1226.2,249.5 1229,253.2Z"/>
    ...
\end{lstlisting}


Na základe upravených tried sme boli schopní identifikovať krajiny aj pri pridávaní prvkov \lstinline{title}. Tento prvok má za následok to, že pri podržaní 
kurzora myši nad danou krajinou sa zobrazí vyskakovacie okno s informáciou o názve krajiny a konkrétnou hodnotou doby odozvy. Na prevod medzi ISO 3166-1 Alpha 2 kódom, 
ktorý je v atribúte class a názvom krajiny používame slovník, ktorý sme zostavili ako konštantu v triede GeographicUtilities. Ako zdroj pre tento tento zoznam 
sme použili voľný súbor vo formáte JSON \cite{country_codes}. Pre úpravu do formátu, v akom sa v jazyku C\# definujú slovníky, sme použili nástroj pre nájdenie 
a nahradenie v programe Visual Studio, ktorým sme reťazce \lstinline{"Name": } a \lstinline{"Code": } nahradili prázdnym reťazcom. 

\begin{lstlisting}[language={[Sharp]C},caption={Ukážka kódu CountryCodeToNameDictionary},label=alg:country_code_to_country_dict]
    public static Dictionary<string, string> CountryCodeToNameDictionary = new Dictionary<string, string>()
    {
        { "AF", "Afghanistan" },
        { "AX", "\u00c5land Islands" },
        { "AL", "Albania" },
        { "DZ", "Algeria" },
    ...
    };
\end{lstlisting}

\subsection{Priebeh priebežného spracovávania dát}
Súčasťou nášho systému sú aj dve služby, ktoré majú za úlohu na pozadí priebežne spracovávať dáta pribúdajúce do tabuľky. Tieto služby sa spustia raz za týždeň 
pomocou zabudovaného Linuxového nástroja cron, ktorý slúži ako plánovač úloh. Pre spustenie služby stačí spustiť kontainer príslušnej služby, služba sa spustí 
spolu s ním. Po dokončení spracovávania sa služba sama ukončí. 

Dáta sa pri každom novom spustení len doplnia, spracovanie sa nerobí odznova. Programy dopĺňajú dáta nasledovným spôsobom:
\begin{itemize}
    \item Program skontroluje, či existujú všetky potrebné tabuľky v databáze, ak nie tak ich vytvorí.
    \item Program získa dátum posledných spracovaných dát. Ak tabuľka neobsahuje žiadne dáta, za posledný dátum sa určí 19.4.2008, čo je týždeň pred začatím
    meraní, aby sa dáta začali spracovávať od prvého týždňa.
    \item Z databázy sa vytiahne zoznam všetkých platných IP adries, pre ktoré máme geografické dáta.
    \item Tieto adresy sa následne zoskupia podľa určených parametrov pre daný program pomocou metódy \lstinline{GroupBy} zo vstavanej C\# knižnice LinQ. To znamená,
    že služba CountryPingInfoService zoskupí IP adresy podľa ISO 3166-1 Alpha 2 kódu príslušnej krajiny, kým služba MapPointsService zoskupí adresy podľa 
    dvojice najbližšieho vyhovujúceho poludníka a najbližšej vyhovujúcej rovnobežky.
    \item Zavolá sa funkcia enumerujúca týždne od posledného spracovania po súčasnosť.
    \item Následne sa cez tieto týždne paralelne iteruje pomocou vstavanej metódy \lstinline{Paralel.ForEachAsync}, ktorá podporuje iteráciu na viacerych 
    vláknach naraz, čo má z následok výrazne skrátenú dobu spracovávania, pretože dáta pre jednotlivé týždne nie sú od seba závislé.
    \item Vrámci jednotlivej iterácie sa pre konkrétny týždeň vyberie zoznam všetkých meraní doby odozvy pomocou príkazu ping ktoré prebehli v daný týždeň. 
    \item Následne sa vykoná projekcia pre všetky skupiny, pri ktorej sa na každú skupinu premietne jej výpočet priemernej doby odozvy v daný týždeň.
    \item Výpočet pre jednotlivú skupinu prebieha tak, že sa pre každú IP adresu v skupine nájde jej príslušná doba odozvy pre daný týždeň zo zoznamu 
    všetkých meraní.
    \item Parametre danej skupiny a vypočítané hodnoty sa následne použijú na zostavenie výsledného objektu, teda CountryPingInfo alebo MapPoint.
    \item Výsledné objekty sa nakoniec vrámci jednej transakcie zapíšu do databázy. To má za následok, že pre daný týždeň sa dáta buď uložia všetky alebo 
    v prípade chyby neuložia žiadne. Vďaka tomu sa vyhneme nekonzistencii dáta pre daný týždeň.
    \item Po dokončení behu sa aplikácia sama ukončí volaním príkazu \lstinline{Environment.Exit(0)}. Služby v C\# sa totiž bez zavolania tohto príkazu same 
    neukončia.
\end{itemize}