diff --git a/III/Balciunas/Makefile b/III/Balciunas/Makefile new file mode 100644 index 0000000..a78d7f1 --- /dev/null +++ b/III/Balciunas/Makefile @@ -0,0 +1,4 @@ +all: egzaminas-2021-01-25.pdf + +%.pdf: %.tex + latexmk -shell-escape -g -pdf $< diff --git a/III/Balciunas/egzaminas-2021-01-25.tex b/III/Balciunas/egzaminas-2021-01-25.tex new file mode 100644 index 0000000..fb6f981 --- /dev/null +++ b/III/Balciunas/egzaminas-2021-01-25.tex @@ -0,0 +1,169 @@ +\documentclass{article} + +\usepackage[L7x,T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage[lithuanian]{babel} +\usepackage{hyperref} +\usepackage{minted} +\usepackage{tikz} +\usetikzlibrary{positioning} + +\title{Žemėlapių naršyklės ir elektroninės paslaugos\\ \vspace{4mm} +Galutinis semestro egzaminas} + +\author{Motiejus Jakštys} + +\date{\today} + +\begin{document} +\maketitle + +\section{Įžanga} + +Kaip pasufleruota užduotyje, pagrindinė problema yra bandymas atvaizduoti per +daug duomenų vienu metu. Problemos sprendimas dvilypis: vartotojo sąsajoje ir +"serverinėje" implementacijoje. + +Kaip pasufleruota užduotyje, sprendimas dvilypis: vartotojo sąsaja ir serverinis komponentas. + +\section{Sprendimas} + +Kadangi problema labai opi smulkiuose masteliuose, pirmiausia nuspręskime, kaip +žemėlapį vaizduoti smulkiame mastelyje. Tai atsispindės ir GUI/UX, ir +serveriniame sprendime. + +\subsection{Funkcionalumo keitimas, GUI/UX keitimas} +\label{sec:ux} + +Jei vienoje vietoje (pvz., per 5\% ekrano ploto) yra daugiau, nei du objektai, +juos agreguoti ir vietoj pačių objektų rodyti skaičių, kiek tame plote yra +objektų. Tada priartinus tuos objektus jie natūraliai atsiskirs. + +Tai implementuojant reikia apgalvoti šiokias tokias išimtis: pvz., jei ekrane +rodoma iš viso mažiau, nei X objektų (tarkime, 42), tuomet agregacijos daryti +nereikia, ir rodyti viską taip, kaip buvo "senuoju būdu". Taip užtikriname, kad +objektus, kad ir kaip arti vienas kito esančius, visada galėsime pamatyti +pakankamai priartinę. Algoritmą, kaip tai padaryti, aprašome +skyriuje~\ref{sec:backend}. + +\subsection{Žemėlapio vizualizacijos modifikavimo/optimizavimo priemonės} +\label{sec:api} + +Šioje sekcijoje aprašome API dalį: į ką pakeisti milžinišką GeoJSON objektą, +kad galėtume jį atvaizduoti? + +Pirmiausia, vartotojas į serverį turi siųsti savo matomo žemėlapio koordinates +({\em extent}). Tada pagal tai serveris nusprendžia, kuriuos duomenis grąžinti +tiesiogiai, kuriuos -- agreguotus. Taip kai kurie taškai lieka originalūs, o +kai kurie dingsta, ir vietoje jų atsiranda "agreguoti". + +Agreguoti taškai -- GeoJSON objektai, tačiau su papildomu atributu, kad tai yra +"virtualūs" taškai, ir nurodantys, kiek objektų savyje "slepia". Pvz. + +\begin{minted}{json} +{ + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [24.3 55.68] + }, + "properties": { + "aggregated": true, + "aggregate_count": 10 + } +} +\end{minted} + +Paspaudus ant agreguoto komponento būtų patogu, jei atsirastų kitas langas su +visais "slepiamais" komponentais, arba žemėlapis taip prisiartintų, kad +pasirodytų visi to agreguoto vidiniai slepiami objektai. + +Grąžinus tik matomą dalį duomenų, serveris visada atsiųs pakankamai mažą kiekį +GeoJSON objektų, kurie tikrai neapkraus naršyklės; taip vartotojo sąsaja bus +sėkmingai naudotina ir smulkiuose, ir stambiuose masteliuose. + +\subsection{Esamų servisų modifikavimo ir/ar naujų kūrimo priemonės, įvardinant +konkrečius servisus tipus/sprendimus ir juos trumpai pagrindžiant} + +Dėstytojo nurodymu, ArcGIS Online pakeičiame PostGIS duombaze ir serveriniu +({\em back-end}) komponentu; žr. architektūros diagramą~\ref{fig:arch}. + +\begin{figure}[H] + \centering + \begin{tikzpicture}[thick] + \node at (0,4)[rectangle,draw=black,fill=yellow!20] (browser) {Naršyklė}; + \node at (0,2)[rectangle,draw=black,fill=blue!20] (backend) {Serverinis komponentas}; + \node at (0,0)[rectangle,draw=black,fill=blue!20] (gis) {PostGIS}; + \draw [->] (browser) to (backend); + \draw [->] (backend) to (gis); + \end{tikzpicture} + \caption{Architektūros diagrama} + \label{fig:arch} +\end{figure} + +Pakeitę ArcGIS į PostGIS, atsikratome dirbtinio 2000 objektų ribojimo ir +aplikacijoje galime pasiimti tiek duomenų, kiek reikia. Šioje užduotyje taip +pat tariame, kad visi, kas įrašinėja objektus, juos rašo į duombazę naudojant +GIS įrangą, ir įrašymu mums rūpintis nereikia. + +Liko neišspręsta viena problema: kaip, turint tūkstančius objektų ir vartotojo +"langą" (extent) grąžinti tinkamus PostGIS objektus? Logiką galima dėti į dvi +vietas: arba duomenų bazę, arba pačią programą. + +\subsubsection{Duomenų bazė} +\label{sec:db} + +Programuoti skirstymo duomenų bazėje yra paprasčiau, nei serveriniame +komponente. Pavyzdinis, gana naivus, algoritmas, kurį galima parašyti naudojant +plpgsql: + +\begin{itemize} + \item parinkti objektus, esančius rėme ({\em extent}). + \item padalinti rėmą į reikiamą skaičių dalių (aprašyta~\ref{sec:ux}). Rėmą + populiaru dalinti į šešiakampius arba kvadratus. + + \item kiekvienai daliai grąžinti tikrus arba virtualius objektus + (aprašyta~\ref{sec:api}). + + \item sukonstruoti GeoJSON objektą ir grąžinti vartotojui. +\end{itemize} + +Nors išspręsti problemą duomenų bazėje yra paprasčiau kodo prasme, tačiau +duomenų bazės apkrovimas bus didesnis ir kils su naršančiųjų kiekiu. Todėl +ateityje, jei duomenų arba vartotojų bus dar daugiau, gali būti sunkiau +optimizuoti algoritmus; naudojant tikrą programavimo kalbą (tarkime, C++ arba +Go) daug paprasčiau optimizuoti ir užtikrinti norimą servisą augant vartotojų +skaičiui. + +\subsubsection{Serverinis komponentas} +\label{sec:backend} + +Algoritmas gali būti panašus į aprašytą~\ref{sec:db}. Tačiau kaip gauti +duomenis? + +Kadangi objektų kiekis -- tik dešimtys tūkstančių, visus duomenis lengvai +galima laikyti atmintyje ir serveriniame komponente analizę leisti su kiekviena +užklausa iš naujo. Duomenis atsisiųsti iš duomenų bazės galima reguliariai, +tarkime, kas kelias sekundes ar minutę: taip duomenų bazės apkrovimas bus +minimalus, ir nekils didėjant skaitytojų kiekiui (didės rašančiųjų kiekiui, bet +tokių paprastai būna daug mažiau). + +Kaip minėta anksčiau, serveriniame komponente lengviau užtikrinti, kad servisas +veiks gerai ir su dideliais apkrovimais, ir nereikės didinti duomenų bazių +galingumo, kas paprastai yra brangiau ir/arba sudėtingiau, nei aplikacijos. + +Jei apkrovimai smarkiai didėja, reikia analizuoti ir tobulinti algoritmą. +Kelios idėjos optimizacijai: + +\begin{itemize} + + \item apskaičiuoti generalizacijas iš anksto kiekvienam įmanomam masteliui + ir atėjus užklausai, tiesiog pasiimti jas iš atminties. + + \item išankstinės optimizacijos, jei skaičiuojamos ne kiekvienos užklausos + metu, gali būti leidžiamos ir į duomenų bazę: taip DB apkrovimas + nesikeičia su naršančių vartotojų kiekiu. + +\end{itemize} + +\end{document}