Implementácia systému eXam

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání


Kapitola obsahuje riešenie implementácie systému, jeho štruktúry a vysvetlenie ako sa daný systém implementoval. Zahrnuté sú tu zaujímavosti s ktorými sa bolo možné stretnúť počas programovania. Navrhovaný systém kontroly správnosti zdrojových kódov sme nazvali eXam.

Dátový model

Pri tvorbe dátového modelu sa vychádzalo z konkrétnej predstavy fungovania systému kontroly zdrojových kódov. Podobné systémy sú bežne používané pre vyhodnocovanie správnosti algoritmov v programátorských súťažiach ako napr. OpenChallenge (http://www.openchallenge.org), The ICFP Programming Contest
(http://www.icfpconference.org/contest.html) a iné. Špecifikom nášho návrhu je fakt, že systém bude prispôsobený ako podporný nástroj pre výuku programovania. Nakoľko myšlienka predstavy fungovania systému bola od začiatku jasná, po identifikovaní jednotlivých entít sme pristúpili k návrhu fyzického modelu. Dátový model bol tvorený tak, aby vyhovoval 3. normálovej forme [7]. V dátovom modeli boli identifikované nasledujúce entity:

  • users - používatelia,
  • courses - predmety,
  • user_groups - študijné krúžky,
  • assignments - zadania úloh,
  • solutions - riešenia používateľa,
  • system_settings - nastavenia systému,
  • allowed_entities - povolené entity na prístup do systému.

Pri návrhu dátového modelu sme vychádzali so zaužívanej praxe pomenovania entít, resp. databázových tabuliek. Pre názvy entít sme zvolili anglické podstatné mená v množnom čísle.

Princíp fungovania dátového modelu

Systém eXam slúži na kontrolu správnosti zdrojových kódov pre registrovaných používateľov. Registrovaný používateľ môže byť študent alebo učiteľ. Využitie systému nie je obmedzené na konkrétny programovací jazyk alebo predmet, ale je možné vytvoriť viacero nezávislých predmetov ktoré môžu obsahovať svoje vlastné zadania, resp. programátorské úlohy ktoré majú študenti riešiť. Pre ľahšiu správu a vyhodnotenie výsledkov sú používatelia rozdelení do skupín. Tieto skupiny môžu byť totožné so študijnými krúžkami.

Entita users

Tabuľka 3.1: Atribúty entity users
Atribút Popis
id Identifikačné číslo, unikátna hodnota
login Prihlasovacie meno
passwd Heslo (hashovaná hodnota)
firstname Krstné meno
lastname Priezvisko
is_admin hodnota statusu používateľa voči systému

Entita users obsahuje základné údaje pre identifikáciu používateľa systému. Z hľadiska možností ovládania systému bol do users pridaný atribút is_admin ktorý má hodnotu reprezentujúcu rolu prihláseného používateľa. V systéme boli identifikované 3 role: administrátor, učiteľ a študent. Používateľ typu študent má právo len na prístup do používateľskej časti systému, kde má základné oprávnenia. Učiteľ môže pristupovať do administrátorského modulu kde spravuje svoj predmet, ale má obmedzenejšie práva než administrátor. Administrátor má plné práva na celý systém.


Vzťahy entity users

users - courses
V systéme sú definované jednotlivé predmety, do ktorých sú priradení študenti a učitelia. Ak je študent priradený do predmetu, budú mu zobrazené zadania, resp. programátorské úlohy zadefinované v tomto predmete. Používateľ môže mať v systéme zapísaných viacero predmetov a takisto aj predmet môže obsahovať viacero používateľov. Tento vzťah je definovaný kardinalitou M:N. Predmet nemusí obsahovať žiadnych používateľov a ani používateľ nemusí mať zapísaný predmet preto je členstvo z obidvoch strán nepovinné.

Tento vzťah bol realizovaný pridaním ďalšej entity many_courses, ktorá obsahuje povinné cudzie kľúče z oboch tabuliek a svoj vlastný primárny kľúč. Keďže používateľ môže byť buď študentom alebo vyučujúcim v predmete, tabuľka obsahuje ešte navyše atribút user_role ktorý môže obsahovať len hodnoty ’TEACHER’, alebo ’STUDENT’.

Tabuľka 3.2: Atribúty many_courses
Atribút Popis
id Identifikačné číslo
user_role Štatút používateľa v predmete
users_id Cudzí kľúč z entity users
courses_id Cudzí kľúč z entity courses
[many_courses-entity]
users - user_groups
Cieľom práce bolo aby systém odrážal skutočný proces výučby na škole, kde je každý predmet rozdelený na krúžky ktoré sa líšia časom výuky a vyučujúcim. Táto skutočnosť bola zohľadnená pri tvorbe vzťahu entít.

Vzťah má kardinalitu M:N. Používateľ nemusí byť priradený do krúžku a krúžok nemusí obsahovať používateľov. Táto situácia je riešená vytvorením novej entity many_groups, ktorá obsahuje cudzie kľúče z oboch tabuliek ako svoje primárne kľúče, je teda priamo závislá na oboch entitách users a user_groups.

Tabuľka 3.3: Atribúty entity many_groups
Atribút Popis
users_id Primárny, cudzí kľúč z entity users
courses_id Primárny, cudzí kľúč z entity courses
users - users_log
Z dôvodu rozhodnutia sa o zaznamenávaní každej dôležitej akcie používateľa v systéme bolo za potreby vytvoriť novú entitu users_log ktorá obsahuje niektoré identifikačné údaje ako čas záznamu a meno, poprípade hodnotu ovplyvnenej entity akcie.

Používateľ môže spraviť viacero záznamov, no záznam môže patriť len jednému používateľovi. Jedná sa teda o vzťah typu 1:N. Keďže používateľ nemusí mať žiadny záznam ale entita users_log musí mať používateľa, je tento vzťah riešený priradením cudzieho kľúča z entity users do entity users_log. Cudzí kľúč je definovaný ako primárny kľúč entity, pretože je priamo závislá na entite users.

Tabuľka 3.4: Atribúty entity users_log
Atribút Popis
id Identifikačné číslo entity
users_id Primárny, cudzí kľúč z entity users
activity Meno vykonanej akcie
time_made Čas vykonania akcie
entity Ovplyvnená entita
entity_value Hodnota ovplyvnenej entity
entity2 Druhá ovplyvnená entita (za prípadu potreby)
entity2_value Hodnota druhej ovplyvnenej entity
ip Adresa IP za času vykonania akcie
[users_log-entity]

Entita courses

Tabuľka 3.5: Atribúty entity courses
Atribút Popis
id Identifikačné číslo, unikátna hodnota
course_name Meno predmetu
semester Semester v ktorom prebieha výuka
active_year Rok kedy bol predmet naposledy aktívny
active Číselná hodnota (0,1), viditeľnosť predmetu

Pri tvorbe entity courses bol braný ohľad na model predmetu v škole. Keďže každý predmet je vyučovaný v určitom semestri školského roka, bol pridaný do entity atribút semester ktorý môže obsahovať hodnoty ’LS’ v prípade letného semestra a ’ZS’ v prípade zimného semestra. Bolo vhodné aby bola aj možnosť predmet nezaradiť do konkrétneho semestra. Z tohto dôvodu bola pridaná aj možnosť ’GENERAL’, teda všeobecný. Predmet má možnosť učiteľ alebo admin deaktivovať aby nebolo možné prehliadať a vypracovávať v používateľskej časti zadania daného predmetu.

Vzťahy entity courses

courses-assignments
Keďže v praxi má každý predmet na škole svoje špecifiká a bolo vhodné aby učitelia svojich predmetov mali zadefinované svoje zadania pre svoj predmet, bolo rozhodnuté aby boli zadania priradené predmetom. Predmet môže obsahovať viacero programátorských zadaní ale nemusí obsahovať žiadne. Zadanie môže patriť viacerým predmetom ale nemusí patriť žiadnemu. V takomto prípade je zadanie neviditeľné pre obyčajného používateľa.

Tento vzťah je riešený vytvorením novej entity course_assignments ktorá obsahuje cudzie kľúče z oboch entít a má navyše atribút assignment_name ktorý obsahuje unikátne meno zadania v predmete. Atribút je pridaný z dôvodu možnosti priradenia zadania do viacerých predmetov.

Tabuľka 3.6: Atribúty entity course_assignments
Atribút Popis
id Identifikačné číslo entity
assignments_id Cudzí kľúč z entity assignments
courses_id Cudzí kľúč z entity courses
assignment_name Meno zadania v predmete
[course_assignments-entity]
courses-user_groups
Na škole je priradený každý krúžok predmetu. Túto skutočnosť definuje aj vzťah entít v databáze. Predmet môže obsahovať viacero krúžkov no nemusí obsahovať žiadne. Krúžok musí patriť len jednému predmetu. Jedná sa teda o vzťah typu 1:N.

Vzťah je riešený priradeným cudzieho kľúča z entity courses do entity user_groups. Keďže je zároveň alternatívnym primárnym kľúčom entity, entita user_groups je priamo závislá od entity courses.

Tabuľka 3.7: Atribúty entity user_groups
Atribút Popis
id Identifikačné číslo entity
courses_id Primárny, cudzí kľúč z entity courses
group_name Meno skupiny
detail Krátky popis skupiny

Entita assignments

Tabuľka 3.8: Atribúty entity assignments
Atribút Popis
id Identifikačné číslo, unikátna hodnota
title Nadpis zadania
assignment_text Text zadania
is_active Hodnota určujúca, či je zadanie aktívne
assignment_mode Režím zadania (Skúška, Semester, Špeciál)

Entita obsahuje atribút pre zaradenie do režimu systému. Zadanie môže byť v rámci výučby na škole semestrálne, skúškové a špeciálne. Tento fakt je zakomponovaný do atribútu assignment_mode. V systéme je možné takisto aj meniť viditeľnosť zadania. Obrázky k zadaniu sa v systéme ukladajú priamo ako súčasť textu do atribútu entity assignments a to assignment_text.

Vzťahy entity assignments

assignments - assignment_tests
Aby bola funkčná kontrola riešení v systéme je nutné aby zadania obsahovali tzv. vzorové testy zadania v ktorých sú definované vstupy a správne výstupy programu. Pri definícii systému bolo rozhodnuté že na kontrolu logiky by mali postačiť 4 takéto testy. Zadania môžu obsahovať len jedny testy zadania a tie musia byť priradené jednému zadaniu. Jedná sa teda o vzťah typu 1:1.

Pri návrhu databázy bol braný ohľad na dodržiavanie 4. normálovej formy, pri ktorej by mala entita obsahovať len jeden fakt alebo súvislosť. Z toho dôvodu je tento vzťah riešený pridaním cudzieho kľúča z entity assignment do entity assignment_tests, kde je zároveň aj primárnym kľúčom a entita je priamo závislá na entite assignments.

Tabuľka 3.9: Atribúty entity assignment_tests
Atribút Popis
assignments_id Primárny, cudzí kľúč z entity assignments
t1_input Vstupná hodnota testu č.1
t1_output Hodnota správneho výstupu testu č.1
t2_input Vstupná hodnota testu č.2
t2_output Hodnota správneho výstupu testu č.2
t3_input Vstupná hodnota testu č.3
t3_output Hodnota správneho výstupu testu č.3
t4_input Vstupná hodnota testu č.4
t4_output Hodnota správneho výstupu testu č.4
[assignment_tests-entity]
assignments - attachments
Učiteľ by mal mať možnosť pridávať do zadania aj prílohy rôzneho typu, preto je vytvorená entita attachments. Je to však nepovinná časť zadania a zadanie sa dá vytvoriť plnohodnotne aj bez príloh. Zaujímavosťou je že príloha sa ukladá aj do databázy aj do priečinku aplikácie kvôli rýchlejšiemu výberu dát.

Zadanie môže mať viac príloh, avšak príloha musí patriť jednému zadaniu. Tento vzťah má teda kardinalitu 1:N a je riešený pridaním cudzieho kľúča z entity assignments do entity attachments.

Tabuľka 3.10: Atribúty entity attachments
Atribút Popis
id Identifikačné číslo, unikátna hodnota
filename Meno súboru
file Súbor
assignments_id Cudzí kľúč z entity assignments

Entita solutions

Systém uchováva odoslané riešenia používateľa z dôvodu možnosti prezerania. Používateľ môže mať viacero riešení, no riešenie musí mať jedného používateľa, tento istý vzťah je aj pri entite assignments a jedná sa o kardinalitu 1:N. Entita solutions je priamo závislá na oboch entitách a preto má členstvo vo vzťahu povinné a obsahuje cudzie kľúče z oboch entít ako svoje primárne alternatívne kľúče.

Tabuľka 3.11: Atribúty entity solutions
Atribút Popis
id Identifikačné číslo, unikátna hodnota
solution_text Kód odoslaného riešenia
correct Správnosť zadania (0,1)
users_id Cudzí, alternatívny primárny kľúč z entity users
assignments_id Cudzí, alternatívny primárny kľúč z entity assignments
solutions - solution_infos
Entita solutions by mala obsahovať niektoré doplnkové informácie ktoré kvôli svojej odlišnosti bolo vhodné priradiť do novej entity solution_infos. Medzi tieto údaje patrí napríklad meno kompilátora, čas odoslania a spracovania riešenia a identifikačné údaje.

Riešenia môžu mať len jednu informáciu o riešení a informácia o riešení musí mať priradené riešenie preto má tento vzťah kardinalitu 1:1. Aby sa dodržala 4. normálová forma, entita solution_infos ostáva samostatná a má priradený cudzí kľúč z entity solutions.

Tabuľka 3.12: Atribúty entity solution_infos
Atribút Popis
id Identifikačné číslo, unikátna hodnota
compilator Meno použitého kompilátora
time_made Čas odoslania zadania
time_duration Čas spracovania riešenia (ms)
ip_address Adresa IP klienta
solutions_id Cudzí, alternatívny primárny kľúč z entity solutions
solutions - solution_tests
Podobne ako programátorské zadania aj riešenie by malo obsahovať testy, nakoľko tieto obsahujú výstupy od používateľovej aplikácie. Ak sa odoslaný kód nepodarí skompilovať, aplikácia uloží hlášku z kompilátora do databázy aby používateľ vedel kde nastala chyba. Sú však špeciálne prípady kedy aplikácia zapisuje do tohto atribútu vlastný text ktorý bol definovaný na základe výnimky, ďalej sú tieto prípady popísané v ďalšej sekcii. Výstupy v takomto prípade budú obsahovať prázdnu hodnotu. Riešenie môže obsahovať testy riešenia jeden krát a testy riešenia musia patriť jednému riešeniu. Jedná sa teda o kardinalitu 1:1.


Tabuľka 3.13: Atribúty entity solutions_tests
Atribút Popis
solutions_id Primárny, cudzí kľúč z entity solutions
t1_output Výstup z testu č.1
t1_correct Správnosť testu č.1
t2_output Výstup z testu č.2
t2_correct Správnosť testu č.2
t3_output Výstup z testu č.3
t3_correct Správnosť testu č.3
t4_output Výstup z testu č.4
t4_correct Správnosť testu č.4
compiler_output Výstup z kompilátora

Keďže entita solutions_tests je závislá od entity solutions, tento vzťah je riešený pridaním cudzieho kľúča z entity solutions do entity solution_tests ako primárny cudzí kľúč.

Špeciálne entity

Systém obsahuje aj entity, ktoré nie sú nijako prepojené s hlavnými entitami systému a fungujú samy o sebe ako celok. Týmito entitami sú allowed_entities a system_settings. Tieto entity uchovávajú statické informácie ktorými sa systém riadi.

Entita system_settings

Táto entita uchováva rôzne nastavenia systému ako sú napríklad režím systému alebo povolenie registrácie. Každé nastavenie má svoj kľúč, na základe ktorého sa dá identifikovať a hodnotu. Táto hodnota sa pri každej zmene nastavenia administrátorom prepíše. Nastavenie má teda len jeden záznam ktorý sa pri zmene upravuje. Ak systém začína s prázdnou databázou, aplikácia má preddefinované hodnoty nastavení a pri ich zmene administrátorom aplikácia najprv skontroluje či sa kľúč nastavenia nachádza v databáze, ak nie tak vloží nový záznam a v prípade že sa nastavenie v databáze nachádza upraví jeho hodnotu.

Tabuľka 3.14: Atribúty entity system_settings
Atribút Popis
id Identifikačné číslo, unikátna hodnota
setting_key Kľúč nastavenia
setting_value Hodnota nastavenia

Entita allowed_entities

Táto entita bola vytvorená aby v systéme bezpečne fungoval režim skúška a bolo možné obmedziť prístup zariadení do systému. Keďže škola má vyhradené počítače pre miestnosti, bola táto skutočnosť odzrkadlená pri vytváraní entity. Administrátor má možnosť definovať meno povolenej hodnoty a nastaviť jej aktivitu voči systému.

Tabuľka 3.15: Atribúty entity allowed_entities
Atribút Popis
id Identifikačné číslo, unikátna hodnota
name Meno entity
active Aktivita entity voči systému

Keďže entita allowed_entites môže obsahovať aj položky, bola vytvorená entita entity_item. Každá inštancia entity obsahuje práve jeden záznam adresy IP. Jedná sa o vzťah typu 1:N a entite entity_item je priradený cudzí kľúč z entity allowed_entities.

Tabuľka 3.16: Atribúty entity entity_item
Atribút Popis
id Identifikačné číslo, unikátna hodnota
allowed_entities_id Cudzí kľúč z entity allowed_entities
allowed_ip Adresa IP
Výsledný ER diagram systému
Obr. 3.1: Výsledný ER diagram systému

Návrh web aplikácie

Aplikácia je navrhovaná tak aby mohla byť používaná opakovane viacero rokov. Pri implementácii bol braný ohľad na požiadavky učiteľov a študentov, nakoľko aplikácia bola súčasne aj testovaná.

Štruktúra aplikácie

Aby aplikácia fungovala podľa požiadaviek a vyhovovala bezpečnosti a právam používateľom, je rozdelená na špecifickú štruktúru. Ako základ je použitá základná štruktúra Nette projektu ktorá je následovne rozdelená na moduly.

Základná štruktúra aplikácie
Obr. 3.2: Základná štruktúra aplikácie

[fig:app_structure]


Základný strom aplikácie obsahujú štyri časti časti :

  • Admin modul (AdminModule),
  • Konfigurácia (config),
  • Model,
  • Používateľský modul (UserModule).

Moduly - sú to časti aplikácie špecifické pre typ používateľa. Každý modul obsahuje svoje komponenty a šablóny. Modul User ponúka iné možnosti na prácu so systémom ako modul Admin. V aplikácii môže Admin modul používať aj komponenty z User modulu lebo je mu nadradený a obohacuje ho. Konfigurácia - v aplikácii obsahuje 2 súbory pre nastavenie globálnych a lokálnych parametrov aplikácie. V globálnej konfigurácii sú priradené funkcie z Modelu ako typ služby kvôli ich využitiu v aplikácii, ak je potrebné. Konfigurácia obsahuje aj triedu router ktorá slúži na presmerovanie. V lokálnej konfigurácii sú uložené údaje na prihlásenie do databázy. Model - obsahuje triedy na prácu so systémom ktoré sú v konfigurácii priradené ako služby, aby boli kedykoľvek dostupné. Aktuálne systém obsahuje 4 služby :

  • Authenticator (Autentifikátor),
  • Identity (Identita),
  • SystemManager (Manažér systému),
  • UserManager (Manažér používateľov).

Authenticator - používa dve závislosti a to servis SystemManager a databázu. Obsahuje funkciu authenticate na prihlásenie používateľa do systému. Funkcia najprv vytiahne záznam z databázy podľa vyplneného loginu. Ak nenájde záznam vyhodí chybu že používateľ nebol nájdený, v opačnom prípade pokračuje na overenie zadaného hesla s heslom záznamu. Na overenie sa používa funkcia Nette frameworku ktorá zadané heslo konvertuje na bcrypt hash a porovná so záznamom z databázy. Ak všetko prebehne v poriadku, zaznamená sa akcia prihlásenia pomocou manažéra systému a používateľovi je pridelená rola a identita na prácu s aplikáciou.

Identity - trieda obsahuje funkcie na získanie adresy IP a mac klienta web aplikácie. Tieto sa používajú vždy pri zápise akcie, keď používateľ niečo v rámci systému vykoná.

SystemManager - obsahuje všetky funkcie na spracovanie dát do databázy a spracovanie požiadaviek systému. Obsahuje aj algoritmus na kontrolu odovzdaného zadania. V konštruktéri triedy si služba pýta pomocou Dependency Injection závislosti na službu, ktorá pracuje s databázou, ďalej službu na caching pomocou ktorej je možné zapisovať na server niektoré dočasné údaje ktoré budú neskôr, keď im vyprší platnosť zmazané.
UserManager - služba obsahuje funkcie týkajúce sa používateľa. Má službu database kvôli zápisu akcii (logov) používateľa a registrácii. Pri zápise akcie služba používa triedu Identity na získanie aktuálnych údajov používateľa.

Používateľský modul

Modul je prístupný širokej verejnosti a obsahuje aj prihlasovací a registrovací formulár, teda jeho časť je prístupná každému. Po prihlásení používateľa do systému ho systém presmeruje podľa jeho role do správneho modulu.
Štruktúra modelu pozostáva z viacerých presenterov, ktoré sú však odvodené z abstraktného presentera BaseUserPresenter, v ktorom sú obsiahnuté náležitosti ktoré by mal obsahovať každý presenter v tejto časti. Výnimkou je však LoginPresenter pretože v systéme má svoje špecifické vlastnosti a je odlišný od presenterov v časti po prihlásení. Všetky presentery navyše používajú spoločnú globálnu šablónu @layout.latte v ktorej sú zahrnuté všetky potrebné knižnice a štruktúra zobrazenia pohľadu (view). Globálna šablóna obsahuje navyše aj komponent menuControl v ktorom sú zahrnuté lišty aplikácie (menu). Táto komponenta sa však aktivuje len ak je používateľ prihlásený.
V abstraktnej triede BaseUserPresenter sú funkcie ako napríklad kontrola či je používateľ prihlásený. Trieda obsahuje aj spoločné premenné, ktoré by mali obsahovať všetky odvodené triedy. Pomocou dependency injection si odvodené triedy pýtajú služby ktoré následné vkladajú do konštruktéra triedy BaseUserPresenter ktorá ich priradí do týchto premien. Trieda zahŕňa aj spoločné komponenty presenterov, napríklad lištu hlavného menu a zapisuje základné premenné do šablónovacieho systému latte presenterov. Medzi tieto premenné môže patriť status používateľa alebo režim systému.

Diagram tried presenterov v používateľskej časti
Obr. 3.3: Diagram tried presenterov v používateľskej časti

LoginPresenter

Trieda LoginPresenter si všetky závislosti na služby rieši pomocou dependency injection. Pri prístupe na prihlasovaciu stránku (trieda LoginPresenter) sa cez systémovú službu User overí či existuje prihlásený používateľ. Ak existuje, presenter automaticky presmeruje stránku na DashboardPresenter, čo je úvodná stránka pre prihlásených používateľov. Na základe role používateľa je vybraný presenter v module User (prístup pre študenta) alebo v module Admin (prístup pre učiteľa).
Presenter obsahuje dve šablóny:

  • default,
  • signForm.

Tieto šablóny využívajú metódy render presentera. Šablóna default je preddefinovaná. Pokiaľ používateľ vstúpi do presentera bez špecifikácie miesta v URL, aplikácia ho automaticky presmeruje do tejto časti. Obidve šablóny presentera používajú komponent LoginDialogControl ktorý v sebe obsahuje formuláre na prihlásenie a registráciu.

Prihlasovací formulár systému
Obr. 3.4: Prihlasovací formulár systému

[fig:login_dialog]


Registrácia má za úlohu zistiť či je používateľ študentom alebo zamestnancom školy MTF STU. Na toto je využitá funkcionalita vyhľadávania osôb v AIS. Po zadaní svojho mena a priezviska - [fig:signup_dialogs] a) systém danú osobu vyhľadá a v prípade kladného výsledku zobrazí druhú časť registračného formulára - [fig:signup_dialogs] b). Pri implementácii overovania používateľov je využitý proxy server, nakoľko systém eXam posiela požiadavky na server is.stuba.sk; teda na inú doménu - jedná sa o požiadavky typu CORS. Takéto požiadavky sú blokované. Pre úspešné volanie takýchto požiadaviek bol vytvorený spomínaný proxy server ktorý rieši úlohu prekladu požiadaviek na vzdialený server. V množine vyhľadávania sa nachádzajú študenti a zamestnanci školy STU .
Pri dokončení registrácie má používateľ možnosť zvoliť si predmet a krúžok do ktorého bude zaradený.

Prihlasovací formulár systému
Obr. 3.5a: Prihlasovací formulár systému
Prihlasovací formulár systému
Obr. 3.5b: Prihlasovací formulár systému

[fig:signup_dialogs]

DasboardPresenter

DashBoardPresenter obsahuje úvodnú stránku user modulu. V stránke sú vypísané všetky registrované predmety používateľa. Okno s predmetom obsahuje informácie o danom predmete. V rámci systému má používateľ možnosť zvoliť si predmet v ktorom sa chce v aplikácii pohybovať. Jednou z úloh daného presentera je aj možnosť meniť používateľské nastavenia (login, heslo). Táto úloha je zabezpečená komponentom UserSettingsControl, nakoľko je komponent v aplikácii použitý aj v admin časti. V úvodnej stránke sa neskôr plánujú zakomponovať štatistiky o používaní systému.

Úvodná stránka user modulu
Obr. 3.6: Úvodná stránka user modulu

[fig:dashboard_user]


Všetky presentery odvodené od BaseUserPresenter obsahujú komponentu MenuControl - [fig:dashboard_user] (horná a ľavá lišta). Komponenta MenuControl rieši navigáciu v systéme formou odkazov na stránky a informáciu o aktuálnom režime systému - [fig:dashboard_user] (ľavá lišta). Odkazy sú odlišné na základe modulu v ktorom je komponenta. Jednou z úloh komponenty je aj presmerovanie na osobné nastavenia a odhlásenie používateľa - [fig:dashboard_user] (horná lišta). V prípade, že má objekt User vo vlastnosti admin hodnotu vyššiu ako 0 (admin, učiteľ) komponent obsahuje tlačítko na prepínanie medzi modulmi.

AssignmentsPresenter

V rámci systému by si mal byť študent schopný prezerať úlohy formou zadania. Túto funkcionalitu rieši AssignmentsPresenter formou okienok s krátkym popisom zadania. Pokiaľ je v systéme nastavený režim skúška presenter tento krátky popis rozmaže aby si študent nevyberal zadanie, ktoré sa mu hodí.

Odkazy na zadania v AssignmentsPresenter
Obr. 3.7: Odkazy na zadania v AssignmentsPresenter


Okná v 1.2 slúžia ako odkaz na asynchrónnu akciu presentera handleDisplayAssignment, ktorá berie okrem informácii o zadaní aj parameter isFinal, kde je definované či je zadanie zvolené v režime skúška. V takomto prípade ostane zadanie zobrazené až do jeho odovzdania. Funkcia zavolá akciu komponentu AssignmentInfoControl showInfo. Táto akcia vykreslí detailné informácie zvoleného zadania a zakryje zobrazenie ostatných zadaní.

<?php
 public function handleDisplayAssigment($assigmentId, $courseId, $isFinal = false){
        if ($isFinal == true) {
            $this->userManager->logAction('chose exam', $this->user->getId(),'assigments_id', $assigmentId, 'course_id',$courseId);
            $this->getComponent('assignmentInfoControl')->showInfo($assigmentId, $assigmentName);
            $this->redrawControl('assigmentsSnippet');
        } else {
            $this->userManager->logAction('view assigment', $this->user->getId(), 'assigments_id', $assigmentId, 'course_id', $courseId);
            $this->getComponent('assignmentInfoControl')->showInfo($assigmentId, $assigmentName);
            $this->state = "showAssigment";
            $this->redrawControl('assigmentsSnippet');
        }
    }
?>
Kód 3.1: Handler pre zobrazenie detailu zadania

Takéto funkcie sa nazývajú handlery a slúžia na asynchrónne spracovanie požiadavok. Vo funkcii [code:assignmentHandler] je možné vidieť, že po spracovaní takéhoto požiadavku je nutné prekresliť dotknutú časť stránky ktorá je označená ako tzv. snippet aby sa zmeny na stránke prejavili.

Detail zadania
Obr. 3.8: Detail zadania


V detaile zadania 1.3 je vypísaný jeden vzorový test. Tento test slúži ako skúška pre študenta pred odoslaním kódu ako overenie správnosti. Detail môže obsahovať aj okno s prílohami, pokiaľ sú v zadaní definované.

TestPresenter

Po oboznámení sa so zadaním a jeho naprogramovaní by mal byť systém schopný používateľovi zadanie skontrolovať a uložiť. Na túto funkciu slúži TestPresenter. Presenter obsahuje formulár na vloženie zdrojového kódu. V režime semester si používateľ môže zvoliť vypracované zadanie na kontrolu priamo vo formulári. V režime skúška je vybrané zadanie z časti AssignmentsPresenter automaticky priradené až do jeho vypracovania. Aby bola možnosť zadanie vypracovať v rôznych programovacích jazykoch, formulár obsahuje okno na zvolenie kompilátora. Tento si používateľ zvolí na základe jazyku, v ktorom kód písal. Aby mal používateľ možnosť odoslať zadanie učiteľovi bez kontroly správnosti, je vo formulári navyše aj možnosť nekontrolovať správnosť.

Formulár na kontrolu zadania
Obr. 3.9: Formulár na kontrolu zadania


Po odoslaní riešenia aplikácia spracuje požiadavok z formulára 1.4 asynchrónne cez handler formulára. Handler využíva službu SystemManager v ktorej je algoritmus na kontrolu kódu k zadaniu. Ak sa požiadavok spracuje úspešne a zadanie sa vyhodnotí, aplikácia pridá do šablóny objekt solutionId kde je uložené identifikačné číslo riešenia. TestsPresenter v sebe obsahuje komponent SolutionDetail, ktorý ak dostane objekt solutionId automaticky pošle asynchrónny požiadavok na zobrazenie riešenia. Toto riešenie sa zobrazí ako okno v aplikácii a používateľ má možnosť ho zavrieť.

Detail riešenia
Obr. 3.10: Detail riešenia


Detail riešenia 1.5 je riešený ako znovu-použiteľný komponent, kvôli jeho využitiu vo viacerých častiach aplikácie. Šablóna detailu má zafarbenie vrchnej lišty podľa správnosti zadania. V tele je zdrojový kód s textom ktorý študent odovzdal. Dodatočné informácie o riešení sú v spodnej lište kde môže používateľ vidieť aj koľko času systému trvalo kód skontrolovať (údaj v ms).

SolutionsPresenter

V definovaných požiadavkoch aplikácie bolo uznané za vhodné aby si študent mohol prezerať svoje predošlé výsledky. Zobrazenie výsledkov v User časti rieši SolutionsPresenter. Kvôli prehľadnejšiemu pozeraniu riešení študenta v AdminModule presenter zobrazuje tieto riešenia pomocou komponentu SolutionsControl. Komponent berie v konštruktéri triedy parameter userId ako identifikátor entity Users, ktorej riešenia má vykresliť.

Náhľad na zoznam riešení komponenty SolutionsControl
Obr. 3.11: Náhľad na zoznam riešení komponenty SolutionsControl


Výsledky sú na stránke zobrazené do troch stĺpcov podľa režimu systému ako odkazové položky. Odkazy sú asynchrónne a majú svoj handler. Handleru sa po kliknutí odošle odkaz s údajmi o zvolenom riešení a riešenie sa zobrazí pomocou okna. V okne je šablóna, v ktorej je použitý už spomínaný komponent 1.5 (SolutionsDetail). Položky riešení sú vyfarbené buď na zeleno (v prípade správneho riešenia), v opačnom prípade majú červený motív. Každá položka riešenia obsahuje meno zadania (písmená abecedy), nadpis a štyri ikony ktoré reprezentujú správnosť testov. Na základe ikoniek je používateľ schopný vidieť ktoré testy neprešli už v tomto zozname.

Admin modul

Každý informačný systém by mal obsahovať sekciu na správu systému. V aplikácii eXam je táto úloha riešená v module AdminModule. Na obrázku 1.7 je class diagram pre tento modul. Do tohto modulu je povolený prístup len pre učiteľov a systémového administrátora.
Štruktúra modulu je rozdelená na dve hlavné časti, podobne ako v User module :

  • znovu-použiteľné komponenty (components) a ich šablóny (templates)
  • presentery (presenters) a ich šablóny

Všetky presentery sú v tomto module odvodené od abstraktnej triedy BaseAdminPresenter. Tá má v sebe pomocou dependency injection zakomponované všetky potrebné služby pre presentery v tejto časti. V triede BaseAdminPresenter je pri štarte životného cyklu presentera implementovaná kontrola oprávnenia prístupu objektu User. Pokiaľ je User v roli admin alebo teacher, má do tohto modulu prístup. V opačnom prípade je premiestnený používateľ do DashboardPresenter User modulu aplikácie. Prístup je v takomto prípade zaznamenaný ako neoprávnený do logu spoločne s identitou používateľa. BaseAdminPresenter zapisuje do šablóny objekty, ktoré sú pre všetky presentery spoločné. Obsahuje komponentu MenuControl [fig:dashboard_user].


Diagram tried presenterov v admin časti
Obr. 3.12: Diagram tried presenterov v admin časti

Všetka interakcia používateľa v rámci presenterov v časti AdminModule je riešená asynchrónne bez nutnosti obnovenia stránky. Každá akcia v rámci presentera má svoj handler, ktorému môže posielať dodatočné potrebné parametre. Handler prevezme parametre z odkazu na akciu a požiadavok spracuje. Po úspešnom spracovaní požiadavku handler prekreslí dotknutú časť stránky, aby sa prejavili zmeny.

DashboardPresenter

Dobrým zvykom v aplikačných riešeniach je aby mal každý oddelený celok aplikácie svoju úvodnú stránku. V časti AdminModule je touto úvodnou stránkou DashboardPresenter. Presenter ponúka učiteľovi a administrátorovi prehľad o dianí v systéme. Úvodná stránka obsahuje v aktuálnom stave štyri odkazy na prehľad diania v systéme:

  • Posledné prístupy,
  • Zobrazené zadania,
  • Kontrola riešení,
  • Živý monitor.

Presenter obsahuje handler handleDashboardStat do ktorého sa posielajú parametre o kliknutom odkaze. Na základe parametru následne presenter filtruje záznamy z databázy ktoré vykreslí na stránku. V prvých troch odkazoch systém vypíše posledných sto záznamov. Vo všetkých záznamoch sú vypísané časy a adresa IP objektu User ktorý akciu vykonal.
Špeciálnou funkciou v DashboardPresenter je živý monitor. Stránka v tomto prípade zobrazí zvlášť záznamy v podobe karty pre každý objekt User. V karte sú vypísané všetky akcie objektu za posledné tri hodiny. Ak objekt za posledné tri hodiny nič nevykonal, na stránke nie je zobrazený.

Obr. 3.13a: DashboardPresenter v AdminModule: Posledné úpravy
Obr. 3.13b: DashboardPresenter v AdminModule: Živý monitor


UsersPresenter

Systém eXam umožňuje administrátorovi spravovať používateľov systému. Funkcie na správu používateľov sú implementované v presentery UsersPresenter. Východzia stránka presentera obsahuje zoznam entít Users, ktoré majú priradený ľubovolný predmet.

Úvodná stránka UsersPresenter
Obr. 3.14: Úvodná stránka UsersPresenter


Úvodná stránka presentera 1.8 obsahuje odkaz na filter entity Users. Po kliknutí na odkaz Zobraziť nepriradených sa zobrazia entity Users ktoré nemajú priradený žiadny predmet. Zoznam sa vy-filtruje a text odkazu sa zmení na Zobraziť priradených.
V zozname entít Users obsahuje každá entita odkazy na nastavenia vo forme tlačidiel. Nastavenia sa delia na :

  • Nastavenia predmetov,
  • Správa používateľa.

V časti 1.8 Nastavenia predmetov sú následovné tri nastavenia v poradí zľava doprava :

  • pridať používateľa do predmetu,
  • pridať používateľa do skupiny,
  • odstrániť používateľa z predmetu.
Formulár pre pridanie používateľa do predmetu
Obr. 3.15: Formulár pre pridanie používateľa do predmetu

Všetky Nastavenia predmetov sú riešené pomocou modálnych okien, ktoré obsahujú formulár na nastavenie, podobne ako v obrázku 1.9. Časť 1.8 Správa používateľa obsahuje dve nastavenia :

  • zmeniť osobné nastavenia používateľa,
  • zobraziť riešenia používateľa.

Na zmenu osobných nastavení používateľa využíva presenter komponent UserSettingsControl, ktorému posiela cez odkaz identifikačný parameter dotknutej entity Users. Komponent UserSettingsControl vykreslí formulár z preddefinovanou hodnotou loginu zvolenej entity a s možnosťou zmeny hesla.

Formulár komponenty UserSettingsControl
Obr. 3.16: Formulár komponenty UserSettingsControl


Pre zobrazenie riešení entity Users sa používa komponent SolutionsControl 1.6. Keďže komponent očakáva v konštruktéri triedy identifikačný parameter userId zobrazovanej entity Users, je tento požiadavok riešený v handleri handleShowUserSolutions. Konštruktér triedy SolutionsControl potrebuje mať stály prístup k parametru userId. Riešením tohto problému je tento parameter uložiť v dočasnom úložisku aplikácie, ktoré zabezpečuje nette framework pomocou objektu triedy Nette/Caching/Cache cache. O toto uloženie sa postará handler handleShowUserSolutions.

<?php
 public function handleShowUserSolutions($userId)
    {
        $this->state = "showUserSolutions";
        $this->cache->save('selectedUser', $userId, [
            Cache::EXPIRATION => '20 minutes',
        ]);
        $this->redrawControl('usersSnippet');
    }
?>
Kód 3.2: Handler akcie zobrazenia riešenia používateľa


Handler [code:handleShowUserSolutions] nastaví v objekte state hodnotu, aby sa vykreslil komponent SolutionsControl. Vo funkcii presentera na vytvorenia komponentu sa mu v konštruktéri odovzdáva parameter z dočasného úložiska. Komponent má teda vždy pri prekreslení prístup k tomuto údaju a môže fungovať správne.
Presenter UsersPresenter obsahuje v hornej lište 1.8 aj filter na rozdelenie entít Users podľa aktívnych predmetov systému.

CoursesPresenter

Keďže je systém eXam implementovaný na základe modelu reálneho procesu fungovania výuky na fakulte MTF STU, ponúka aj možnosť spravovania predmetov v rámci systému. Funkcionalita je implementovaná v presenteri CoursesPresenter. Presenter na úvodnej stránke obsahuje zoznam entít Courses v ktorom je možné entity upravovať.

Úvodná stránka presentera CoursesPresenter
Obr. 3.17: Úvodná stránka presentera CoursesPresenter


Každý záznam entity Courses obsahuje odkazy na informácie o krúžkoch predmetu, časť Operácie a časť Zmazať. V časti operácie sú tri odkazy na operácie zľava doprava :

  • aktivita predmetu ,
  • upravenie predmetu,
  • správa krúžkov predmetu.

Na všetky odkazy presenter obsahuje handlery. Pri zmene aktivity predmetu na neaktívny predmet stratí zelené podfarbenie a je v rámci systému neviditeľný. Na upravenie predmetu sa používa formulár komponentu CourseControl s preddefinovanými údajmi zvolenej entity. Pre správu krúžkov predmetu je použitá funkcia showGroups z komponenty CourseControl. Táto zabezpečí vykreslenie zoznamu krúžkov v predmete. Zoznam krúžkov predmetu taktiež obsahuje funkcie na pridanie, úpravu a mazanie krúžkov.
Časť Zmazať obsahuje odkazy zľava doprava na :

  • zmazanie zadaní v predmete,
  • zmazanie predmetu.

Pri každom zmazaní musí byť akcia opätovne potvrdená v okne na potvrdenie aby nedošlo k omylnému zmazaniu.
Na úvodnej stránke (obrázok 1.11) je v hornej lište možnosť pridať nový predmet. Po kliknutí presenter spracuje odkaz pomocou handleru handleAddCourse. Keďže presenter na pridanie predmetu obsahuje komponentu CourseControl, handler jej len povie aby zobrazila formulár na pridanie predmetu.

Formulár komponentu CourseControl
Obr. 3.18: Formulár komponentu CourseControl

AssignmentsPresenter

V presenteri je implementovaná požiadavka systému eXam na správu zadaní. Úvodná stránka obsahuje zoznam všetkých zadaní bez ohľadu na predmet. Zadania sú rozdelené do troch kariet na základe režimu ktorému sú priradené. Pozícia týchto kariet sa mení na základe režimu systému.

Horné menu presentera AssignmentsPresenter
Obr. 3.19: Horné menu presentera AssignmentsPresenter


Menu 1.13 obsahuje odkazy na filter zadaní podľa predmetu vo forme tlačidiel. V menu je vykreslené tlačidlo pre každý aktívny predmet v semestri. Je tu aj odkaz na pridanie nového zadania. Presenter po kliknutí na odkaz Pridať zadanie požiadavok spracuje pomocou handlera handleAddAssignment. Po spracovaní stránku prekreslí a zobrazí formulár na pridanie zadania.

Formulár na pridanie zadania (presenter AssignmentsPresenter)
Obr. 3.20: Formulár na pridanie zadania (presenter AssignmentsPresenter)


Formulár 1.14 neobsahuje možnosť zvolenia predmetu, pretože je spracovaný cez odkaz v časti všetky zadania. V prípade použitia odkazu pri zvolenom predmete by formulár obsahoval možnosť zvolenia predmetu s preddefinovanou hodnotou predmetu z ktorého bol spracovaný.

Karty so zoznamom zadaní majú iné možnosti v závislosti či sú zobrazované v predmete alebo v sekcii Všetky zadania.

Karta zoznamu špeciálnych zadaní v predmete (presenter AssignmentsPresenter)
Obr. 3.21: Karta zoznamu špeciálnych zadaní v predmete (presenter AssignmentsPresenter)


Každý objekt v zozname 1.15 obsahuje tri stĺpce na správu zadania. V stĺpci Viditeľnosť je odkaz na zmenu viditeľnosti zvolenej entity Assignments v rámci systému. Vidieľné entity majú zelené podfarbenie.
Stĺpec Náhľad obsahuje odkaz na handler presentera handleShowAssignment ktorý berie v konštruktéri identifikačný parameter zvolenej entity Assignments. Handler následne odovzdá parameter komponentu SolutionDetailControl, ktorý náhľad na zadanie vykreslí v modálovom okne.
Úprava a mazanie entity z predmetu Assignments je riešená v stĺpci Operácie. Odkaz na úpravu zadania rieši handler handleEditAssignment, ktorý berie ako parameter identifikátor zvolenej entity a po spracovaní vykreslí formulár 1.14 s preddefinovanými hodnotami zadania a možnosťou uložiť. Mazanie entity z predmetu spravuje handler handleDeleteAssignmentCourse. V prípade že je entita Assignments zmazaná zo všetkých predmetov, bude zobrazená v sekcii Všetky zadania kde následne bude možné entitu Assignments natrvalo odstrániť.

SolutionsPresenter

Jednou z funkčných požiadaviek systému bolo, aby učiteľ mohol kontrolovať odovzdané riešenia študentov. Tento požiadavok rieši SolutionsPresenter. Presenter obsahuje zoznamy výsledkov študentov vo forme kariet rozdelené podľa režimu zadaní. Usporiadanie kariet je rozličné a závisí od aktuálneho nastavenia režimu systému.

Menu úvodnej stránky SolutionsPresenter
Obr. 3.22: Menu úvodnej stránky SolutionsPresenter


Menu 1.16 obsahuje odkazy vo forme tlačidiel. Každý objekt typu Courses má vlastný kontajner v ktorom je pre každú entitu user_groups entity Courses vykreslený odkaz. Odkazy spracová handler handleShowGroupSolutions ktorý v konštruktéri berie identifikačný parameter entity user_groups. Po spracovaní požiadavku sa na stránke vykreslí filtrovaný zoznam používateľov.

Karta zoznamu riešení pre režim Špeciál
Obr. 3.23: Karta zoznamu riešení pre režim Špeciál


V karte 1.17 sú pre používateľa rozdelené stĺpce podľa názvov zadaní v režime karty. Pre názov stĺpca zadania sú použité iniciály začiatočných písmen názvu zadania. Názvy obsahujú titulok s celým menom zadania ktorý sa zobrazí po prejedení myšou.
Hodnoty stĺpcov sú odkazy. Ak daný študent zadanie neodovzdal v odkaze je ikonka otáznika. V opačnom prípade odkaz spracováva metóda presentera renderSolutionDetail ktorá používa komponent SolutionDetailControl a odovzdáva mu identifikačný parameter entity solutions. Detail riešenia sa zobrazí formou modálneho okna 1.5. Správnosť riešenia sa však dá vyčítať už z odkazu na detail riešenia. V prípade že je riešenie správne je použitá zelená ikona, v opačnom prípade červená.

SettingsPresenter

SettingsPresenter rieši požiadavok systému na správu systému eXam. V presenteri sú implementované funckie na zmenu režimu systému, správu povolených entít a používateľov z časti 1.8.

Úvodná stránka SettingsPresenter
Obr. 3.24: Úvodná stránka SettingsPresenter


Úvodná stránka presenteru 1.18 obsahuje nastavenia na správu systému. Nastavenie režimu systému je riešené pomocou troch odkazových tlačidiel s názvom režimu. Tieto odkazy spracováva handler presentera handleSetSystemMode ktorý berie ako parameter názov režimu. Aktuálne nastavenie režimu je zvýraznené zeleným podfarbením tlačidla. V časti 1.18 je možné zakázať vstup do registračnej časti aplikácie kvôli zneužívaniu registrácie. Po úspešnom nastavení systém notifikuje používateľa formou notifikácie v hornej časti aplikácie.
V obrázku 1.19 povolené entity presentera je zoznam povolených entít v systéme. Administrátor má možnosť pridať nové povolené entity. Dobrým zvykom je voliť za meno entity názov učebne v ktorej je definovaná.

Správa povolených entít systému
Obr. 3.25: Správa povolených entít systému


Záznam aktívnej entity z časti 1.19 má zelené podfarbenie. Každý záznam entity allowed_entities v zázname obsahuje odkazy na zmenu aktivity, úpravu entity a zmazanie entity. Pre všetky odkazy sú využívané handlery presentera.

Formulár na pridanie povolenej entity systému
Obr. 3.26: Formulár na pridanie povolenej entity systému


Pri pridávaní povolenej entity sa píšu adresy IP jedna za riadok. Po odoslaní formulára aplikácia asynchrónne spracuje požiadavok a skontroluje vyplnené adresy IP.

<?php
    $ipAdresses = $values['ipAdresses'];
    $ipAdresses = mb_split('\r\n', $ipAdresses);
    // v prípade, že používateľ nechal posledný riadok prázdny
    if (end($ipAdresses) == '') {
        array_pop($ipAdresses);
    }
    foreach ($ipAdresses as $ipAdress) {
        if (filter_var($ipAdress, FILTER_VALIDATE_IP)) {
            $this->systemManager->insertBy('entity_item', ['allowed_entities_id' => $entityId, 'allowed_ip' => $ipAdress]);
        } else {
            $hasError = true;
            break;
        }
    }
?>
 Kód 3.3: Filtrovanie zadaných adries IP

Ako je možné vidieť v kóde [code:ipFilter], aplikácia je ošetrená voči nesprávnemu vyplneniu adries IP. Na filtráciu adries IP sa používa metóda jazyka PHP filter_var(). Metóda berie ako parameter adresu IP a konštantu ktorá definuje na základe čoho má filtrovať. Ak je v systéme aktívna povolená entita systém blokuje prístup zariadení s inou adresou IP aká je definovaná v aktivovanej povolenej entite. V prípade prepnutia do režimu skúška sú tieto entity automaticky aktivované a administrátor môže zmeniť ich aktivitu.

Kontrola zdrojových kódov

Systém eXam používa na kontrolu zdrojových kódov funkcie zo služby SystemManager. Po odoslaní požiadavku v časti 1.4 sa odovzdajú funkcii processSolution nasledovné parametre:

  • code - text odoslaného zdrojového kódu,
  • compilator - meno kompilátora v ktorom je riešenie poslané,
  • verify - hodnota špecifikujúca, či sa má riešenie kontrolovať,
  • assignmentId - identifikátor entity Assignments, ku ktorej je riešenie, posielané
  • userId - identifikátor entity User, ktorý riešenie posiela.
<?php
public function processSolution($code, $compilator, $verify, $assigmentId, $userId)
    {
        //v prípade úspešného uloženia do DB daľšia manipulácia
        if ($solution) {
            $start = microtime(true);
            // kontrola, či skript obsahuje kľúčové slová
            if (strpos($code, "system") === false && strpos($code, "getch") === false && strpos($code, "pause") === false) {
                $filePath = $path . '/' . $solution->id . '.c';
                if (!file_exists($filePath)) {
                    $file = fopen($filePath, 'w');
                    fwrite($file, $code);
                    fclose($file);
                }
                $executablePath = $path . '/' . $solution->id;
                if ($compilator == 'C') {
                    // ...ďalší kód
                }
            }
        }else{
            $time_elapsed = microtime(true) - $start;
            $compilerOutputText = $this->printCompilerOutput($compilerOutput);
            $solution_tests = $this->database->table('solution_tests')->insert(['solutions_id' => $solution->id, 'compiler_output' => $compilerOutputText]);
        }
    }
?>
Kód 3.3: Filtrovanie zadaných adries IP


Skript [code:processSolution] prvotne vytvorí záznam riešenia, teda riadok entity Solutions v databáze. Entite za behu spracovania pridá neskôr potrebné informácie. V prípade že databáza úspešne uloží tento záznam systém spustí časomieru. V ďalšom kroku aplikácia skontroluje, či sa náhodou v kontrolovanom kóde nenachádzajú zakázané funkcie. Ak sa nájdu v kóde škodlivé funkcie aplikácia kontrolu preruší a uloží informáciu o tom, že používateľ použil škodlivý kód. Po kontrole zakázaných funkcii sa kód odoslaného riešenia zapíše do textového súboru, ktorý bude použitý ako vstup pre kompilátor na vygenerovanie spustiteľnej aplikácie. Správny kompilátor sa vyberie na základe zvoleného kompilátora (obrázok 1.4).

<?php
if ($compilator == 'C') {
    exec('gcc '.$filePath.' -o '.$exePath.' 2>&1', $compilerOutput, $status);
    if (0 === $status) {
        $assigmentTests = $this->getById('assigment_tests', $assigmentId);
        $test1 = $this->testVariables($exePath, $assigmentTests->t1_input, $assigmentTests->t1_output);
        // testy 1-4 ...
        $time_elapsed = microtime(true) - $start;
        $compilerOutputText = $this->printCompilerOutput($compilerOutput);
        /* Vloženie záznamu z kontroly do db ...  */
        unlink($exePath);
    } else {
        $time_elapsed = microtime(true) - $start;
        $compilerOutputText = $this->printCompilerOutput($compilerOutput);
         /* Vloženie záznamu z kompilátora do db ...    */
    }
}
?>
Kód 3.4: Ukážka časti kódu na spracovanie odoslaného riešenia


V kóde [code:processSolutionByCompilator] je možné vidieť, že na generovanie spustiteľnej aplikácie zo zdrojového kódu riešenia je použitá funckia php exec(). Funckia exec berie tri parametre. Prvým parametrom je príkaz na spustenie. V aplikácii je v tomto parametri ako prvé uvedené meno funkcie kompilátora nasledované cestou k súboru so zdrojovým kódom a cestou výstupu spustiteľnej aplikácie po skompilovaní. Druhý parameter funkcie je premenná na uloženie textu výstupu z kompilátora a do tretieho parametru sa uloží číselná hodnota výsledku spracovania. Ak je výsledok spracovania úspešný vytiahnu sa z databázy hodnoty správnych vstup a výstupov. Tieto sa následne testujú vo funkcii testVariables.

Funckia testVariables berie ako parametre cestu k vygenerovanej spustiteľnej aplikácii a vzorový vstup, ktorý posiela vygenerovanej aplikácii. Výstup z aplikácie následne porovná s tretím parametrom tj. vzorovým výstupom.

<?php
 public function testVariables($executablePath, $input, $output)
    {
        try {
            exec('echo "' . $input . '" | timeout 0.5  ' . $executablePath . ' 2>&1', $codeOutput, $status);
            if ($status === 0) {
                for ($i = 0; $i < $outputSize; $i++) {
                    if (isset($codeOutput[$i])) {
                        if ($outputArray[$i] == $codeOutput[$i]) {
                            $correct = 1;
                        } else {
                            $correct = 0;
                            break;
                        }
                    }
                }
            } 
        } catch (Exception $ex) {
            $codeOutput = '';
            $correct = -1;
        }
        $codeOutput = preg_replace('/[\\\\x|\\\\]*/u','$2',$codeOutput);
        $result = ['codeOutput' => $codeOutput, 'correct' => $correct];
        return $result;
    }
?>
Kód 3.5: Kontrola kódu podľa kompilátora (C)


Nutnosť ochrany systému pred preťažením je riešená vo funkcii [code:testVariables] testVariables. Aktuálne je v systéme na pevno nastavený čas 0,5 sekundy po ktorom skript zlyhá a vyhodnotí sa ako nesprávny. Funckia testVariables vracia v premennej result správnosť výsledku porovnania. Keďže výstup z vygenerovanej aplikácie môže obsahovať aj znaky ktoré nepodporuje systém na správu databázy, sú tieto znaky nahradené vo funkcii php preg_replace. Aplikácia vykoná funkciu testVariables štyri krát a pokiaľ sú všetky výstupy označené ako správne označí celé riešenia za správne. V oboch prípadoch sa zastaví spustená časomiera a čas behu kontroly sa zapíše ako záznam do databázy. Používateľovi je následne zobrazený výsledok cez komponentu SolutionDetailControl (obrázok 1.5).