Preskočiť na obsah

Generovanie dozorov

Generovanie dozorov je jadrová časť aplikácie Pozor Dozor. Zabezpečuje ho trieda DutyGenerator, ktorá vytvára mesačný rozpis na základe zoznamu učiteľov, ich dostupnosti a nastavenia kalendára.

Dôležitou vlastnosťou návrhu je, že samotné generovanie ešte nemení štatistiky učiteľov. Najprv sa vytvorí iba návrh rozpisu, ktorý sa zobrazí používateľovi ako náhľad. Štatistiky učiteľov sa upravia až po potvrdení rozpisu.


Základný princíp generovania

Generátor vytvorí rozpis pre konkrétny mesiac. Pre každý deň, ktorý je v kalendári označený ako zahrnutý, sa pokúsi vybrať dvojicu učiteľov.

Základná úloha generátora

Generátor prejde dni mesiaca, vynechá dni nezahrnuté v kalendári a pre každý aktívny deň vyberie dvoch učiteľov, ktorí môžu mať v daný deň dozor.

Výsledkom generovania je zoznam objektov DutyEntry. Každý záznam obsahuje dátum a dvojicu učiteľov priradených na dozor.

Výsledok generovania

Jeden záznam rozpisu predstavuje objekt DutyEntry. Obsahuje dátum dozoru, prvého učiteľa a druhého učiteľa.


Vstupné údaje generátora

Generátor pracuje s viacerými údajmi, ktoré načíta z dátových súborov aplikácie.

Vstup Zdroj Význam
Zoznam učiteľov teachers.csv učitelia, dostupnosť a štatistiky
Kalendár mesiaca calendar.csv dni zahrnuté do generovania
Počty dozorov teachers.csv historický počet započítaných dozorov
Posledný týždeň dozoru teachers.csv pomocné kritérium pri férovom výbere

Načítanie vstupov

Trieda DutyGenerator používa TeacherRepository na načítanie učiteľov a MonthSettingsRepository na prípravu nastavení dní v mesiaci.

Nesprávne vstupné údaje ovplyvnia výsledok

Ak majú učitelia nesprávne nastavenú dostupnosť alebo ak sú v kalendári nesprávne označené dni, generátor bude pracovať s týmito údajmi. Preto je potrebné pred generovaním skontrolovať učiteľov aj kalendár.


Príprava mesiaca

Pred samotným generovaním sa pripraví kalendár daného mesiaca. Túto časť zabezpečuje MonthSettingsRepository.

Ak mesiac ešte v súbore calendar.csv neexistuje, aplikácia doplní všetky jeho dni. Pracovné dni sa predvolene nastavia ako zahrnuté a víkendy ako nezahrnuté.

Príprava kalendára

Pri príprave mesiaca sa zabezpečí, že aplikácia pozná každý deň daného mesiaca. Zároveň sa vykoná normalizácia víkendov, ktoré sa do generovania nezahŕňajú.

Víkendy sa negenerujú

Sobota a nedeľa sa pri príprave mesiaca nastavujú ako nezahrnuté dni. Aj keby boli v súbore calendar.csv ručne nastavené na true, aplikácia ich pri príprave mesiaca opraví na false.


Filtrovanie dní

Generátor prechádza nastavenia dní v mesiaci. Každý deň má príznak included, ktorý určuje, či sa má použiť pri generovaní.

Ak je deň označený ako nezahrnutý, generátor ho preskočí. Ak je deň zahrnutý, generátor preň hľadá dvojicu učiteľov.

Princíp filtrovania dní

Ak je v kalendári deň nastavený ako included = false, generátor ho vynechá. Takýto deň sa vo výslednom rozpise nezobrazí a nebude mať pridelených učiteľov.

Využitie filtrovania

Filtrovanie dní sa používa najmä na vynechanie sviatkov, prázdnin, riaditeľského voľna alebo iných dní bez vyučovania.


Výber dostupných učiteľov

Pre každý zahrnutý deň generátor vytvorí zoznam kandidátov. Kandidátom môže byť iba učiteľ, ktorý má povolenú dostupnosť pre konkrétny deň týždňa.

Ak sa generuje napríklad utorok, do kandidátov sa dostanú iba učitelia, ktorí majú povolenú dostupnosť v utorok.

Deň v týždni Použitá dostupnosť učiteľa
Pondelok canMonday
Utorok canTuesday
Streda canWednesday
Štvrtok canThursday
Piatok canFriday

Dostupnosť podľa dňa

Dostupnosť učiteľa je uložená priamo pri učiteľovi. Generátor podľa dňa v týždni rozhodne, či sa učiteľ môže zaradiť medzi kandidátov.

Na jeden deň sú potrební dvaja učitelia

Pre každý zahrnutý deň musia byť dostupní aspoň dvaja učitelia. Ak generátor nájde menej než dvoch kandidátov, generovanie sa zastaví chybou.


Férové triedenie kandidátov

Kandidáti sa pred výberom zoradia podľa viacerých kritérií. Cieľom je, aby sa dozory rozdeľovali čo najrovnomernejšie a aby sa rovnakí učitelia neopakovali zbytočne často.

Generátor pri triedení zohľadňuje historické údaje z teachers.csv aj údaje vzniknuté počas práve prebiehajúceho generovania.

Poradie kritérií

Kandidáti sa triedia podľa celkového počtu dozorov, rozloženia v aktuálnom generovaní, posledného týždňa dozoru a nakoniec podľa mena. Skôr sa vyberú učitelia, ktorí majú podľa týchto kritérií vyššiu prioritu.


Kritérium 1: počet dozorov

Prvým a najdôležitejším kritériom je počet dozorov. Generátor zohľadňuje historický počet dozorov učiteľa a zároveň počet dozorov, ktoré už učiteľ dostal v aktuálne generovanom mesiaci.

Používa sa teda súčet:

dutyCount + počet pridelený v aktuálnom generovaní

Učiteľ s nižšou hodnotou má prednosť.

Prečo sa počíta aj aktuálne generovanie

Ak by sa bral do úvahy iba historický dutyCount, mohol by ten istý učiteľ dostať v jednom mesiaci príliš veľa služieb. Preto generátor priebežne počíta aj dozory pridelené počas aktuálneho generovania.


Kritérium 2: rozostup v aktuálnom mesiaci

Druhým kritériom je rozostup medzi dozorami v rámci práve generovaného mesiaca.

Generátor si pamätá posledný dátum, kedy bol učiteľ v aktuálnom generovaní použitý. Prednosť má učiteľ, ktorý ešte použitý nebol. Ak už boli použití obaja porovnávaní učitelia, prednosť má ten, ktorý mal v aktuálnom generovaní dozor dávnejšie.

Úloha rozostupu

Toto kritérium pomáha tomu, aby učiteľ nedostával dozory príliš blízko pri sebe, ak existujú vhodní iní kandidáti.


Kritérium 3: posledný týždeň dozoru

Tretím kritériom je hodnota lastDutyWeek. Ide o číslo týždňa, v ktorom mal učiteľ naposledy potvrdený dozor.

Nižšia hodnota znamená, že učiteľ mal podľa tejto evidencie dozor dávnejšie.

Pomocné historické kritérium

Hodnota lastDutyWeek slúži ako jednoduché historické kritérium. Pomáha pri rozhodovaní vtedy, keď majú učitelia podobný počet dozorov a podobné rozloženie v aktuálnom generovaní.


Kritérium 4: abecedné zoradenie

Ak sú predchádzajúce kritériá rovnaké, generátor použije abecedné zoradenie podľa priezviska a mena.

Toto kritérium neslúži na férovosť v hlavnom zmysle, ale na stabilné rozhodovanie v prípade rovnosti.

Stabilné rozhodovanie

Abecedné zoradenie zabezpečí, že generátor má jednoznačný spôsob rozhodnutia aj vtedy, keď sú predchádzajúce kritériá rovnaké.


Výber dvojice učiteľov

Po zoradení kandidátov generátor vyberie prvých dvoch učiteľov zo zoznamu. Tí sa stanú dvojicou pre daný dátum.

Následne sa vytvorí nový záznam DutyEntry, ktorý obsahuje dátum a oboch vybraných učiteľov.

Vytvorenie záznamu dozoru

Pre každý zahrnutý deň vznikne jeden objekt DutyEntry. Tento objekt predstavuje jeden riadok výsledného rozpisu.

Po vytvorení záznamu generátor aktualizuje pomocné počítadlá aktuálneho generovania. Zvýši počet pridelení pre oboch učiteľov a uloží dátum ich posledného použitia v aktuálnom mesiaci.


Pomocné údaje počas generovania

Počas jedného generovania si aplikácia vedie vlastné dočasné údaje. Tieto údaje sa nepíšu hneď do súboru teachers.csv.

Pomocný údaj Význam
generatedCount počet dozorov pridelených učiteľovi v aktuálnom generovaní
lastGeneratedDate posledný dátum, kedy bol učiteľ použitý v aktuálnom generovaní

Dočasné údaje

Pomocné údaje existujú iba počas generovania. Slúžia na férovejšie rozloženie dozorov v rámci jedného mesiaca.

Generovanie ešte nemení teachers.csv

Počas generovania sa nemení súbor teachers.csv. Historické štatistiky učiteľov sa aktualizujú až po potvrdení rozpisu.


Výsledok generovania

Výsledkom generovania je zoznam záznamov DutyEntry. Tento zoznam sa v aplikácii uloží ako rozpracovaný rozpis.

V hlavnej triede aplikácie sa takýto rozpis uchováva ako pendingDuties. Spolu s ním sa uloží aj mesiac, podpis kalendára a podpis učiteľov.

Rozpracovaný rozpis

Rozpracovaný rozpis je návrh, ktorý ešte nebol potvrdený. Slúži na vytvorenie PDF náhľadu a na neskoršie potvrdenie, ak používateľ rozpis schváli.


Oddelenie náhľadu a potvrdenia

Aplikácia zámerne oddeľuje vygenerovanie náhľadu od potvrdenia rozpisu.

Tlačidlo Generuj vytvorí návrh a zobrazí ho. Tlačidlo Potvrdiť zapíše dozory učiteľom do evidencie.

Výhoda oddelenia

Používateľ si môže rozpis najprv skontrolovať. Až keď je spokojný s náhľadom, môže rozpis potvrdiť a započítať učiteľom.

Potvrdenie je zápis do evidencie

Potvrdenie rozpisu nie je iba potvrdenie zobrazenia. Pri potvrdení sa učiteľom zvýši počet dozorov a aktualizuje sa informácia o poslednom týždni dozoru.


Kontrola platnosti pred potvrdením

Pri vygenerovaní náhľadu si aplikácia uloží podpis aktuálneho kalendára a podpis aktuálneho zoznamu učiteľov.

Pred potvrdením aplikácia znovu vypočíta aktuálne podpisy a porovná ich s podpismi uloženými pri generovaní.

Ak sa podpisy líšia, znamená to, že sa po vygenerovaní zmenil kalendár alebo zoznam učiteľov. Takýto rozpis sa nesmie potvrdiť bez nového generovania.

Čo sa kontroluje pred potvrdením

Pred potvrdením sa kontroluje existencia rozpracovaného rozpisu, zhoda podpisu kalendára, zhoda podpisu učiteľov a to, či už daný mesiac nebol potvrdený.

Neaktuálny náhľad sa nesmie potvrdiť

Ak sa po vygenerovaní zmení zoznam učiteľov alebo kalendár, pôvodný náhľad už nemusí zodpovedať aktuálnym údajom. Aplikácia preto vyžaduje nové generovanie.


Ochrana pred dvojitým potvrdením

Aplikácia si v konfigurácii ukladá posledný potvrdený mesiac. Pred potvrdením kontroluje, či aktuálny mesiac už nebol potvrdený.

Táto kontrola chráni aplikáciu pred tým, aby sa tie isté dozory započítali učiteľom opakovane.

Rovnaký mesiac sa nemá započítať dvakrát

Ak by sa rovnaký rozpis potvrdil viackrát, učiteľom by sa umelo zvýšil počet dozorov. Preto aplikácia bráni opakovanému potvrdeniu rovnakého mesiaca.


Zápis štatistík po potvrdení

Až po potvrdení sa zavolá metóda, ktorá aplikuje vygenerované dozory na aktuálny zoznam učiteľov.

Pri tomto kroku sa znovu načíta aktuálny zoznam učiteľov zo súboru. Potom sa podľa ID učiteľov vyhľadajú osoby z rozpisu a aktualizujú sa ich štatistiky.

Aktualizované hodnoty

Pri potvrdení sa každému učiteľovi z rozpisu zvýši dutyCount a nastaví sa lastDutyWeek podľa týždňa konkrétneho dátumu dozoru.

Učiteľ musí stále existovať

Ak bol učiteľ po vygenerovaní rozpisu odstránený zo zoznamu, aplikácia nemôže bezpečne zapísať štatistiky. Preto sa pred potvrdením kontrolujú zmeny v zozname učiteľov.


Výpočet týždňa dozoru

Pri potvrdení sa pre každý dátum dozoru vypočíta číslo týždňa. Toto číslo sa uloží do hodnoty lastDutyWeek príslušného učiteľa.

Používa sa týždeň podľa nastavenia lokálneho prostredia systému.

Úloha lastDutyWeek

Hodnota lastDutyWeek slúži ako pomocná historická informácia pri ďalšom generovaní. Umožňuje generátoru zohľadniť, v ktorom týždni mal učiteľ naposledy dozor.


Chybové situácie pri generovaní

Najčastejšou chybou pri generovaní je nedostatok dostupných učiteľov pre niektorý deň.

V takom prípade generátor vyhodí chybu a rozpis sa nevytvorí.

Riešenie chyby

Ak generovanie zlyhá pre konkrétny deň, je potrebné skontrolovať dostupnosť učiteľov v daný deň týždňa alebo vypnúť daný dátum v kalendári, ak sa v ten deň dozor nemá vykonávať.

Menej než dvaja kandidáti

Generátor potrebuje pre každý zahrnutý deň dvoch učiteľov. Ak je dostupný iba jeden alebo žiadny učiteľ, rozpis nie je možné bezpečne vytvoriť.


Zjednodušený algoritmus

Zjednodušený postup generovania možno opísať takto:

načítaj učiteľov
priprav kalendár mesiaca
vytvor prázdny zoznam dozorov
pre každý deň v mesiaci:
    ak deň nie je zahrnutý:
        preskoč deň
    vyber učiteľov dostupných v daný deň
    ak sú dostupní menej než dvaja:
        skonči chybou
    zoraď kandidátov podľa férovosti
    vyber prvých dvoch učiteľov
    vytvor DutyEntry
    aktualizuj dočasné počítadlá generovania
vráť zoznam DutyEntry

Hlavná vlastnosť algoritmu

Algoritmus je jednoduchý, deterministický a kontrolovateľný. Nepoužíva náhodný výber, ale zoradenie podľa jasne určených kritérií.


Silné stránky riešenia

Použitý spôsob generovania je vhodný pre menšiu školskú aplikáciu, kde je dôležitá jednoduchosť, čitateľnosť a predvídateľné správanie.

Výhody návrhu

Generátor zohľadňuje dostupnosť učiteľov, priebežné rozloženie dozorov v aktuálnom mesiaci a historické štatistiky. Vďaka oddeleniu náhľadu a potvrdenia zároveň chráni dáta pred nechceným zápisom.


Obmedzenia riešenia

Generátor nie je optimalizačný systém v matematickom zmysle. Neprepočítava všetky možné kombinácie a nehľadá globálne najlepšie riešenie. Pracuje postupne po dňoch a v každom kroku vyberá najvhodnejšiu dvojicu podľa zoradenia kandidátov.

Nejde o úplnú optimalizáciu

Algoritmus je praktický a jednoduchý, ale nemusí nájsť najlepšie možné rozdelenie zo všetkých kombinácií. Pre potreby bežného mesačného rozpisu je však výhodou jeho predvídateľnosť a jednoduchosť.