KKMK: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Mmaeste (talk | contribs)
No edit summary
Ktarma (talk | contribs)
 
(56 intermediate revisions by 4 users not shown)
Line 1: Line 1:
===Meeskond===
==Meeskond==
* Kaido Tarma (D23)
* Kaido Tarma (D23)
* Katre Paabo (D22)
* Katre Paabo (D22)
Line 5: Line 5:
* Kaisa Taelma (D23)
* Kaisa Taelma (D23)


==XML'i kodutöö==
===XML'i genereerimiseks loodud programm===
===XML'i genereerimiseks loodud programm===
<source lang="csharp">
<source lang="csharp">
Line 894: Line 895:
</xs:schema>
</xs:schema>
</source>
</source>
===Retsensioonid===
==XML Retsensioonid==
==Retsensioon meeskonna BitByBit XML faili ülesande kohta==
 
===Retsensioon meeskonna "BitByBit" XML ülesande kohta===
Meeskond BitbyBit on valinud oma teemaks muusika ning sellega seotud elementide kategoriseerimise ja kirjeldamise. XML fail juurelemendiks on üldiselt muusika (music), järjestuse järgmiseks etapiks on esitaja (artist), kellel võib olla mitu albumit. Igal albumil on järjestatud lood (song), milledel on eraldi kommentaarid, ja albumi kommentaar. <br/>
Meeskond BitbyBit on valinud oma teemaks muusika ning sellega seotud elementide kategoriseerimise ja kirjeldamise. XML fail juurelemendiks on üldiselt muusika (music), järjestuse järgmiseks etapiks on esitaja (artist), kellel võib olla mitu albumit. Igal albumil on järjestatud lood (song), milledel on eraldi kommentaarid, ja albumi kommentaar. <br/>
XML on süntaktilise ehituse poolest korrektne. Otsingute tegemiseks on selline XML küllaltki hea. Sellegi poolest jääb arusaamatuks, miks on igal lool eraldi žanr, kui iga albumi juures on kirjeldatud selle muusikavool. See oleks mõistetav, kui tegemist on n-ö kogutud teoste või aastahittidega, millel iga laul võib olla eri žanrist. Sellisel juhul peaks iga laulu juures olema ka eraldi esitaja, mis enamus juhtudel tekitaks info liiasust. Samuti näib eraldi albumi kommentaar (album comments) liiasena, sest iga muusikapala juures on eraldi kommentaar.<br/>
XML on süntaktilise ehituse poolest korrektne. Otsingute tegemiseks on selline XML küllaltki hea. Sellegi poolest jääb arusaamatuks, miks on igal lool eraldi žanr, kui iga albumi juures on kirjeldatud selle muusikavool. See oleks mõistetav, kui tegemist on n-ö kogutud teoste või aastahittidega, millel iga laul võib olla eri žanrist. Sellisel juhul peaks iga laulu juures olema ka eraldi esitaja, mis enamus juhtudel tekitaks info liiasust. Samuti näib eraldi albumi kommentaar (album comments) liiasena, sest iga muusikapala juures on eraldi kommentaar.<br/>
Line 904: Line 906:
Töö täitis ülesande tingimusi. Vaatamata on lühidusele, täitab see oma ülesannet. Hea loetavuse tõttu ei näe põhjust eraldi dokumentatsiooniks ega kommentaarideks. Iga päringu juures oli välja trükitud, mida konkreetne väärtus tähendab.
Töö täitis ülesande tingimusi. Vaatamata on lühidusele, täitab see oma ülesannet. Hea loetavuse tõttu ei näe põhjust eraldi dokumentatsiooniks ega kommentaarideks. Iga päringu juures oli välja trükitud, mida konkreetne väärtus tähendab.


===Retsensioon meeskonna "Trenniinfo" XML ülesande kohta===
XML fail on suhteliselt lühike. Aadressi asemel oleks võinud kasutada linna, sest aadress märgib pigem täpsemat asukohta. Kalev Spa spordialade juures on mõlemal treeningajaks argipäevad. Ühes on see ka eraldi välja toodud, teises on ainult päevadena kirja pandud. See oleks võinud olla ühtemoodi tehtud.<br/>
Sama kehtib ka Saku spordikompleksi kohta. Treeningpäevad võiks olla ühtemoodi märgitud. Kui trenni saab teha igapäevaselt, siis võiks see igal pool ka samamoodi märgitud olla. Samuti hakkab siin silma ka spordialade juures ära märgitud tasuta võimaluse koht, kuigi allpool maksumuse juures on selleks täiesti hea koht olemas. Pole vajadust sama infot allpool uuesti korrata.<br/>
Esimese XML transformatsioonifaili puhul  väljastatakse kõik spordikohad koos infoga. Paremini loetavuse koha pealt võiks peale treeningu kohta ja ennem spordiala olla ka üks tühi rida, sest vastasel juhul tekib mulje, et see kehtibki vaid esimese spordiala kohta, kui tegelikult näitab see infot ka järgmiste kohta.<br/>
Teise XML transformatsiooni faili puhul on sama asi. Ei ole väga hästi aru saada, kas andmed kehtivad vaid teatud informatsiooni kohta või laienevad ka allpool olevatele. Tulemus on praktiliselt sama, mis esimese puhul. Muutunud on ainult see, et maksumuse koha peal öeldakse, et see on tasuta.<br/>
Kolmanda XML transformatsiooni faili juures võib märgata praktiliselt sama tulemust, mis eelmiste puhul. Seekord on aga paremini aru saada, mille kohta info käib. Siin tulevad välja ka erinevused treeningpäevade suhtes. Kui ühel on ETKNRLP kirjeldatud päevadena, siis teisel on märgitud, et toimub igapäevaselt, kuigi need tähendavad ühte ja sama asja.<br/>
Kõiki kolme transformatsiooni puhul oleks võinud olla erinevad väljastused. Hetkel väljastavad kõik kolm praktiliselt ühte ja sama väärtust. Aga oleks võinud olla väljastused näiteks kõikidele sisehallidele või kõikidele jõutreeningutele.
==Teenuse Kirjeldus==
<p>Teenus on mõeldud foorumitega seonduva loomiseks, haldamiseks ja muutmiseks.<br/>
Iga foorumi juures on kategooriad, mis liigitavad konkreetse foorumi suundi.<br/>
Kategooria jaguneb omakorda teemadeks, mida võib ühe kategooria raames olla mitmeid.<br/>
Teemal on kasutajate poolt postitatud teated ehk postitused. </p>
===Foorumi päringud===
Foorumi päringud implementeerivad foorumi interfacei.
<li><b>getApplicationIdByForumName</b> - Võimaldab pärida aplikatsiooni ID-d foorumi nime järgi.
<li><b>getAll</b> – Võimaldab pärida kõik foorumid, arvestades suletud foorumeid.
<li><b>getById</b> – Foorumi päring ID järgi.
<li><b>create</b> – Foorumi loomine, mille käigus määratakse foorumile nimi, loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
<li><b>update</b> – Foorumi uuendamine. Sellega saab muuta foorumi nime.
<li><b>delete</b> – Foorumi sulgemine- sulgemise ja muutmise ajaks määratakse meetodi rakendamise aeg.
<li><b>getAllCategoriesInForum</b> – Konkreetse foorumi kõigi kategooriate päring.
<li><b>getAllUsersInForum</b> - Konkreetse foorumi kõigi seal registreerunud kasutajate päring.
===Kategooria päringud===
Kategooria päringud implementeerivad kategooria interfacei, mis omakorda baas interfacei (ITemplate).
<li><b>getAll</b> – Võimaldab pärida kõik kategooriad.
<li><b>getById</b> –Kategooria päring ID järgi.
<li><b>create</b> – Kategooria loomine, mille käigus määratakse kategooria nimi,kirjeldus, loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
<li><b>update</b> – Kategooria uuendamine. Sellega saab muuta kategooria nime ja kirjeldust.
<li><b>delete</b> – Kategooria sulgemine- sulgemise ja muutmise ajaks määratakse meetodi rakendamise aeg.
<li><b>getAllTopicsInCategory</b> – Konkreetse kategooria kõigi teemade päring.
===Teema päringud===
Teema päringud implementeerivad teema interfacei, mis omakorda baas interfacei (ITemplate).
<li><b>getAll</b> – Võimaldab pärida kõik teemad.
<li><b>getById</b> –Teema päring ID järgi.
<li><b>create</b> – Teema loomine, mille käigus määratakse teema nimi, teema looja kasutaja ID, kategooria ID, kuhu see teema kuulub ja loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
<li><b>update</b> – Teema uuendamine. Võimalik muuta kategooriat, kuhu vastav teema kuulub, ja teema nime.
<li><b>delete</b> – Teema kustutamine- sulgemise ajaks määratakse meetodi rakendamise aeg.
<li><b>getByCategoryId</b> –Teemade otsing, mis pole kustutatud, kategooria ID järgi.
<li><b>getByUserId</b> – Konkreetse kasutaja kõigi lisatud teemade otsing.
===Postituse päringud===
Postituse päringud implementeerivad postituse interfacei, mis omakorda baas interfacei (ITemplate).
<li><b>getAll</b> – Võimaldab pärida kõik postitused.
<li><b>getById</b> –Postituse päring ID järgi.
<li><b>create</b> – Postituse loomine, mille käigus määratakse postituse nimi ja tekst, postituse looja kasutaja ID, teema ID, mille all postitus tehti, ning uuenduse ja loomise väärtuseks määratakse loomise hetk.
<li><b>update</b> – Postituse uuendamine. Võimalik muuta teemat, kuhu vastav postitus kuulub, ja postituse nime ning teksti.
<li><b>delete</b> – Postituse kustutamine- sulgemise ajaks määratakse meetodi rakendamise aeg.
<li><b>getByUserId</b> – Konkreetse kasutaja kõigi lisatud postituste otsing.
<li><b>getByTopicId</b> – Postituste otsing, mis pole kustutatud, teema ID järgi.
<li><b>getAnswers</b> – Postituse vastuse otsing vastava postituse ID järgi.
===Kasutaja päringud===
Kasutaja päringud implementeerivad kasutaja interfacei.
<li><b>getAll</b> – Võimaldab pärida kõik kasutajaid, arvestades suletud kasutajaid.
<li><b>getById</b> –Kasutaja päring ID järgi.
<li><b>create</b> – Kasutaja loomine, mille käigus määratakse kasutajanimi, kasutaja ees-ja perekonnanimi, parool, e-maili aadress ja salasõna. Samuti lisatakse kasutaja tabelisse Membership, user ja UserProperties.
<li><b>update</b> – Kasutaja uuendamine. Kasutaja saab muuta salasõna, emaili ja kommentaari.
<li><b>updateUserProperties</b> –Kasutaja propertite uuendamine.
<li><b>delete</b> – Kasutaja kustutamine ID järgi.
<li><b>undelete </b>– Kasutaja kustutamise annulleerimine.
<li><b>visit</b> – Viimase külastuse väärtuse uuendamine.
<li><b>getAllPostsByUser</b> – Kasutaja kõigi postituste otsing.
<li><b>getByUsername </b>– Kasutaja otsing kasutajanime järgi.
<li><b>getByEmail</b> – Kasutaja otsing emaili järgi.
<li><b>validateUser</b> – Kasutaja valideerimine ehk kindlaks tegemine, kas vastav forum, kasutajanimi ja salasõna ühtivad.
<li><b>isForumUser</b> - Kasutaja kindlakstegemine, kas tegemist on vastava foorumi kasutajaga.
<li><b>getProperties </b>– Kasutaja propertite saamine.
<li><b>getUserRoles</b> – Kasutaja rolli päring kasutaja ID järgi.
<li><b>updateUserRoles</b> – Kasutaja rolli muutmine. Ühel kasutajal võib olla mitu rolli.
===Rolli päringud===
Rolli päringud implementeerivad rolli interfacei.
<li><b>getAll</b> – Võimaldab pärida kõik rollid.
<li><b>getById</b> –Rolli päring ID järgi.
<li><b>create</b> – Rolli loomine. Lisaks tagastatakse selle ID.
<li><b>update</b> – Rolli uuendamine ID järgi.
<li><b>delete</b> - Rolli kustutamine ID järgi.
<li><b>changeUserRole</b> - Kasutaja rolli muutmine.
===FirstQueries===
<li><b>setup</b> - Foorumi tegemiseks vajalik meetod; luuakse administraator.
===Membership päringud===
Membership päringud implementeerivad Membership interfacei.
<li><b>getById </b>– Membership info otsing kasutaja ID järgi.
<li><b>All</b>- Kõigi Membershipide otsing.
==Klientrakenduse Kirjeldus==
<p>Rakendusel on kahte tüüpi kasutajaid-tavakasutajad ja administraator.<br/>
Selleks, et foorumeid, kategooriaid ja teemasid vaadata on vaja sisse logida.<br/>
Kui kasutajal veel kontot pole, saab ta selle teha registreerimise lehel.<br/>
Kasutaja saab vajadusel muuta enda andmeid ja profiilipilti.<br/>
Kasutaja saab lisada, muuta ja kommenteerida vaid postitusi.<br/>
Foorumeid, kategooriaid ja topicuid saab lisada vaid administraator.<br/>
Administraator saab foorumeid aktiivseks ja mitteaktiivseks teha. Lisaks saab administraator muuta ning vaadata kasutajate andmeid ja vajadusel kasutajaid kustutada.<br/>
<br/>
Selliseid rakendusi on maailmas palju, ning nagu näha, siis pole olemas seda kõige paremat - täiuslikku foorumit.<br/>
Ka meie rakendust(ja selle kõrvalt teenust) saaks veel suurel määral täiendada. Hetkel peame suurimaks puuduseks ebaturvalisust ja seda, et kliendile pole lisatud töötavat custom membershipi.<br/>
Kasutasime <b>ASP.NET MVC4</b> tehnoloogiat.</p>
<li><b>Pealeht</b> - [http://enos.itcollege.ee/~ktarma/up/VR/pealeht.jpg]
<li><b>Sisselogimine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/sisselogimine.jpg]
<li><b>Registreerimine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/registreerimine.jpg]
<li><b>Kasutaja profiili muutmine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/edit_user.jpg]
<li><b>Kategooria ja teema vaade</b> - [http://enos.itcollege.ee/~ktarma/up/VR/category_ja_topic_valik.jpg]
<li><b>Kategooria muutmine ja lisamine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/category_muutmine_lisamine.jpg]
<li><b>Teema lisamine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/admin_topicu_lisamine.jpg]
<li><b>Postituse lisamine</b> - [http://enos.itcollege.ee/~ktarma/up/VR/vaata_voi_lisa_postitusi.jpg]
<li><b>Postituse vaade</b> - [http://enos.itcollege.ee/~ktarma/up/VR/postituse_vaade.jpg]
<li><b>Foorumi ülevaade</b> - [http://enos.itcollege.ee/~ktarma/up/VR/admin_foorumi_%C3%BClevaade.jpg]
<li><b>Kasutajate vaade</b> - [http://enos.itcollege.ee/~ktarma/up/VR/admin_kasutajate_vaade.jpg]
===Rakenduse käivitamine===
1) Esmalt tuleb alla laadida [http://enos.itcollege.ee/~ktarma/up/VR/ForumWithMembershipProvider.zip pakk siit] või kasutada selleks [https://hajussysteemid.visualstudio.com/DefaultCollection/ForumWithMembershipProvider/ TFSi].
2) Siis tuleb ära muuta WcfForumService Web.config'u serviceCertificate thumbprint (WcfForumService->Web.config->Advanced->Service Behaviors->serviceBehavior->serviceCredentials->serviceCertificate). (enne seda peab teil olema vajalik sertifikaat, mille loomist kirjeldatakse [https://wiki.itcollege.ee/index.php/Praktikum:_Windows_Communication_Foundation_teenuse_turvamine,_VR2.9#Sertifikaatide_loomine siin])
3) Tõenäoliselt peate ka rebuildima library, clienti ja service.
4) Nüüd tuleb luua andmebaasi(.\sqlexpress) vajalikud tabelid. Selleks on vastavad SQL skriptid ForumServiceLibrary/Scripts kaustas.
5) Nüüd tuleb ka ASP.NET Membershipi jaoks vajalikud tabelid luua, seda on kirjeldatud [https://wiki.itcollege.ee/index.php/Praktikum:_Windows_Communication_Foundation_teenuse_turvamine,_VR2.9#ASP.NET_Membership_database_loomine_ja_WCF.27ile_selle_kasutamiseks_.C3.B5iguste_andmine siin].<br/>
5.1) See võib visata errorit, et NETWORK SERVICE on juba olemas, siis tuleb see käsitsi ära kustutada ja ikkagi 5) uuesti teha.
6) Siis võite käivitada rakenduse.
7) Teile näidatakse tühja lehte, kus veel ühtegi foorumit ei ole, kuna andmebaas on tühi. Esimene setup toimub aadressil: http://localhost:64621/Home/Setup
8) Peale seda peaks teil olema administraatori õigusega kasutaja ning esimene foorum loodud.<br/>
8.1) Kui esineb probleeme sellise "külma stardiga", siis võite andmebaasist vanad kirjed ära kustutada skriptiga (ForumServiceLibrary/Scripts/SQLdelete.sql) ning uuesti proovida.
==Teenuste Retsensioonid==
===Retsensioon meeskonna "[[X-Ladu]]" Teenuse ülesande kohta===
====Teenus====
Tegemist on Windows Communication Foundation tehnoloogial realiseeritud  teenusega. Teenuse funksionaalsus on defineeritud projektis X-LaduLibrary. Seega teenus ja kasutatav äriloogika on eraldatud, ning seega on võimalik olemasoleva loogika lihtsam muutmine ning taaskasutus teistes projektides. Teenus vastab üldjoontes aines toodud ülesandepüstitusele:
*Teenus võimaldab pidada logi kasutajate tegevuste kohta ja kasutajate haldamist. Logi on baasis toodud eraldi tabelina, kuid logi täiendamine ei toimu teenuses automaatselt vaid see funktsionaalsus peab olema realiseeritud kliendi poolel. Teenus kujutab endast suuresti lihtsalt liidest klientrakenduse ja baasi vahel.
*Kasutajate tuvastamine teenuse poolel piirdub parooli ja kasutajanime põhjal kasutaja baasist leidmisega. Nagu ka autorid ise on öelnud, siis teenuse turvamine on hetkel veel realiseerimata. Kasutusel on basicHttpBinding.


===Log===
Teenus on loodud ühe konkreetse ettevõtte tarbeks ja üldiselt teistele teenuse pakkumist ei võimalda, kuna kliendi tuvastamine puudub ja uute klientide lisamine eeldab ka olemasoleva klientrakenduse muutmist (ülesande püstituse kohalt pole see küll puudus, kuna teenus võibki olla loodud vaid ühe “juriidilise” kliendi tarbeks). Teisalt, skaleeruvust arvestades on tegemist siiski miinusega, kuna edaspidine muutmine on selle võrra keerulisem.
 
Meeskonna lehel on kergesti leitav nii ammendav teenuse kirjeldus kui ka kasutajajuhend, mille abil on võimalik teenus ka reaalselt käivitada.
 
====Kood====
 
Teenuses on kood loogiliselt liigendatud: eraldi kaustades on mudelid ja “data access” kiht, milles on baasi vastu käivad päringud. Päringud on eristatud kasutaja õiguste põhjal (tavakasutaja ja administraatori päringud), mitte olemite kaupa (nt tootegrupi pärningud jne).  Taoline lähenemine ilmselt kergendab kliendis loogika kirjeldamist. Lisaks on eraldi välja toodud nn automaatsed päringud kasutaja autoriseerimiseks ning logi lisamiseks.
 
Projektle on lisatud ka vajalik sql skript, mis võimaldab projekti tööle saada ka retsenseerijatel.
 
Andmebaasis on toodud tabelid “Kasutaja”, “KasutajaLogi”, “Kommentar”, “Toode”, ja “Tootegrupp”. Kuigi ka nende tabelite abil saab luua töötava rakenduse, siis andmebaasi disain jääb kohati siiski küsitavaks. Näiteks on olemis “Kasutaja” sõnena kirjas kommentaar, kuid samas on loodud ka Kommentaari tabel, millesse kasutaja saab lisada kommentaare toote kohta. Üldisem lahendus oleks kasutada Kommentaaride tabelit ja kahte vahetabelit kasutajate ja toodete kommentaaride hoidmiseks. Sellisel juhul ei tekiks ka segadust nimetustega, kuna mõiste “Kommentaar” tähendaks ühte ja sama nii toote kui ka kasutaja puhul.
 
Andmebaasi disaini juures tasuks märkida ka seda, et sõltuvalt toote kategooriast võidakse baasis hoida suurel hulgal liigseid andmeid: näiteks toote “tomatimahl” korral on tabelis “Toode” ikkagi olemas väljad pikkuse, laiuse, rõiva suuruse ja muude parameetrite kirjeldamiseks. Üheks lahenduseks oleks lisada tabelid erinevate parameetrite grupeerimiseks toote iseloomu järgi. Ka ühikud võiksid olla eraldi tabelis.
 
Võimalik, et taoline lähenemine muudaks projekti mõnevõrra keerukamaks, kuid taas: edaspidi oleks lihtsam teenust muuta (näiteks lisada ühikute teisendamise loogika teenusesse). Lisaks paraneks kasutusmugavus, kuna kasutaja ei pea leidma suure hulga info hulgast tarvilikke parameetreid.
 
Kommentaare pole mõistetavatel põhjustel paljudele meetoditele lisatud. Nimelt on meetodite ja argumentide nimetused valdavalt ennast seletavad (näiteks meetod annaToodeKoguseJargi(double kogus)) ja seega kommentaaride vähesus üldjuhul ei häiri. Küll aga võiks ära mainida, et kui jätta kommentaarid lisamata, siis pole mõtet jätta koodi ka tühjasid dokumentatsiooni väljasid, mis häirivad rohkem kui puuduvad märked. Tõenäoliselt on tegu ajapuuduse tagajärjega, kuid olulisem osa (teenuse poolt pakutavad meetodid) on ka dokumenteeritud.
 
Mis on mõnevõrra harjumatu on valitud keel: koodis on igal võimalikul juhul kasutusel eesti keel ja näiteks andmebaasi juures tähendab see võrdlemisi kummalisi tabelite nimetusi (näiteks “Toodes”). Teisalt on valitud stiili läbivalt järgitud, kui välja arvata vahemuutuja “query”. Üldiselt on eestikeelne kood küll harjumatu, kuid arvatavasti pole see mitte otseselt puudus, kuna tegemist on koolitöö raames valminud projektiga. Probleemiks osutuks see tõenäoliselt alles reaalse kasutamise korral.
 
====Kokkuvõte====
 
Üldjoontes on teenus realiseeritud korrektselt: kogu olemasolev funktsionaalsus töötab ja kood on lihtsalt loetav. Miinustena võib välja tuua teenuse turvalisuse puudumist ja võibolla ka mudelite disaini, mis piirab liigselt pakutavaid võimalusi ja vähendab kasutusmugavust.
 
Teenus on piisaval määral dokumenteeritud.
 
===Retsensioon meeskonna "[[AFFA II]]" Teenuse ülesande kohta===
 
====Teenus====
 
Tegemist on Windows Communication Foundation tehnoloogial realiseeritud  teenusega. Teenuse funksionaalsus on defineeritud projektis AFFA2WcfServiceLibrary. Seega teenus ja kasutatav äriloogika on eraldatud, ning seega on võimalik olemasoleva loogika lihtsam muutmine ning taaskasutus teistes projektides. Teenus vastab aines toodud ülesandepüstitusele:
 
*Teenus võimaldab pidada logi kasutajate tegevuste kohta ja kasutajate haldamist. Logi peetakse kõigi meetodite väljakutsete kohta kasutajate kaupa. Lisaks peab  Membership provider eraldi arvet kasutajate selliste tegevuste kohta nagu sisselogimine, lukustamine jne.
 
*Kasutajate tuvastamine toimub Membership provider-i Validate() meetodi abil ja infot sisse loginud kasutajate kohta hoitakse staatilises listis. Seejuures genereeritakse iga sisselogimise korral (Guid) SessionId.  Välja logimisel eemaldatakse kasutaja info staatilisest listist.
 
Teenuse eesmärk on finantsandmete pakkumine kasutajatele.Seejuures kasutatakse eelnevalt baasi sisestatud andmeid. Lahtiseks jääb küsimus, mil viisil andmeid uuendatakse. Hetkel teenuse koodis see ilmutatud kujul realiseeritud ei ole. Samas ei raskenda olemasolev kood selle funktsiooni lisamist.
 
Dokumentatsioon on antud projektil suhteliselt korralik: koostatud on teenuse kirjeldus,
 
kirjeldatud on meeskonnaliikmete tööjaotus ja lisatud on ka kasutusjuhend. Viimase kohta võib küll öelda, et testija geeniga retsenseerijal ainult seda juhendit järgides teenust käivitada ei õnnestunud.
 
====Kood====
 
Eelpool mainitud kasutaja tegevuste logimisel loetletakse kasutaja poolt välja kutsutud meetodite arvu. Seejuures iga meetodi väljakutsel lisatakse andmebaasi vastavasse tabelisse rida kasutaja ja kasutatud meetodi kohta. Mis jääb koodi põhjal mõistmatuks on asjaolu, et leidub meetodeid, mille kasutamist teenuse poolel kasutaja rolli põhjal ei piirata (näiteks GetIncomeStatementWithDates), seega väljakutse võib teha ka free-user. Samas tulemust talle küll ei tagastata, küll aga logitakse meetodi väljakutse. Enamgi veel: kuigi väidetavalt on tasuta kasutaja päringud piiratud, siis päringute arvu kontrollitakse vaid kolme päringu korral ja limiidi ületamisel tõstetakse ülesse exception teatega päringute mahu ületamise kohta.
 
Kui rääkida sellest, et administraatori õigustega saab teha kõiki päringuid, siis näiteks meetodi GetCashFlowStatementWithDates korral tagastatakse andmed vaid tasuta kasutajale. Selle probleemi lahendamiseks piisaks annotatsioonide kasutamisest meetoditel. Viimane lähenemine eeldab ka olemasoleva rollide halduse reaalset kasutamist. Hetkel on küll olemas Role Provider kuid kasutatakse enda kirjutatud  loendi väärtusi. Millest selline lähenemine tingitud on jääb mingis mõttes arusaamatuks. Kokkuvõttes võiks öelda, et päringute piiramine kasutaja tüübi põhjal on realiseeritud pisut kaootiliselt.
 
Huvitaval kombel ei ole hetkel implementeeritud uue kasutaja registreerimiseks vajalikku funktsionaalsust. Rakenduse kasutatavuse seisukohalt on see üsna tõsine puudus.
 
Kasutajate tuvastamisel luuakse staatiline list ja selle andmed sisaldavad iga kasutaja kohta “käsitsi” genereeritud sessiooni id-d. Viimane variant töötab projekti näitel hästi, kuid WCF vaikeväärtused peaksid seda funktsionaalsust ka ise toetama. Nimelt peaks WCF teenuse vaikimisi “InstanceContextMode” olema wsHttpBinding korral “Per Session” ja sessiooni id saaks küsida teenuselt. Teine küsitavus on listi kasutamine andmete hoidmisel. Kuna sisse logitud kasutajaid otsitakse sellest üsna sageli võiks kaaluda näiteks HashMap või mõne muu struktuuri kasutamist ja tõsta võtme (sessiooni id) järgi otsimise kiirust.
 
Koodis on kirjeldatud mõningad kasutatud mudelid, mis on eraldatud eraldi kausta ja seega kergesti leitavad. Mõnevõrra segadusttekitav on asjaolu, et juhul, kui tegemist on andmebaasi kandele vastava olemiga, siis klassi nimi baasis sisalduva tabeli nimega ei kattu. Veelgi enam, juhul, kui kasutatakse nimetusi nagu “FinDataEntity” võiks lisada ka väikse kirjelduse selle sisu ja kasutamise kohta. Lõppkokkuvõttes annab küll kõik ka koodi ja google abil selgeks saada, aga ajakulu on üsna suur.
 
Kui rääkida “data access” kihist, siis see puudub. Kogu suhtlus andmebaasiga on kirjutatud teenuse poolt pakutavatesse meetoditesse. Viimane lähenemine raskendab oluliselt koodi lugemist ja ka muutmist, kui see peaks mingil hetkel vajalikuks osutuma.
 
Seejuures on eksitud ka selle vastu, et üks meetod teeb parajasti ühte asja. Kui vaadata näiteks meetodeid Login ja CheckUser, siis oleks võinud suure osa sisust refaktoreerida eraldi meetoditeks ja koodi taaskasutada. Hetkel on kaks korda järjest suurel hulgal sama koodi kirjutatud.
 
Ääremärkusena võiks lisada veel selle, et üldiselt inglise keelse sisu korral võiks ka kommentaarid olla inglise keelsed.
 
====Kokkuvõte====
 
Koodi kvaliteet ja arhitektuur on kohati korralikult läbimõtlemata. Teisalt on rakendus üsna korralikult dokumenteeritud ja idee poolest ka majanduslikult mõistlik. Ka rakenduse turvamine on korralikult realiseeritud.
 
==Rakenduste Retsensioonid==
 
===Retsensioon meeskonna "[[X-Ladu]]" Klientrakenduse ülesande kohta===
 
====Rakendus====
 
Tegemist on WPF klientrakendusega, mis kasutab suurt osa teenuse pakutavatest meetoditest. Tavakasutaja vaates saab toodet lisada ning otsida, samuti saab muuta kasutaja andmeid. Administraatori vaates saab lisaks luua tootegruppe, hallata teisi kasutajaid ning jälgida logi (inimeste tegevust).
 
Esialgne käivitamine oli mõnevõrra probleemne, sest arendajate WIKI lehel oli kirjeldatud administraatori loomist puudulikult. Põhjuseks oli kasutaja parooli lisamine - see pidi tegelikult olema “krüpteeritud” kujul. Esimese administraatori oleks tegelikult võinud luua väga lihtsa SQL käsuga, mitte poleks pidanud kasutajat SQL Server Management’i käsitsi andmebaasi kallale suunama.
 
====Kood====
 
Rakenduses kasutati vaatemudeleid, seal oli kaks kausta: Mudelid ja Vaatemudelid, kusjuures niiöelda Vaatemudelite sees oli realiseeritud palju funktsionaalsust.
 
Kasutajate parool tekitati/tuvastati leides MD5 räsi, muud turvalisuse haldust (sessioon, membership) rakenduses polnud.
 
Kasutajate logi pidamine oli üks väga häid ideid ning see oli ka koodi mõttes normaalselt realiseeritud. Miinuseks oli see, et iga LogiVM klassi meetodi alguses kutsuti uuesti lae() meetod, mis lõi logide nimekirja iga kord uuesti.
 
Erinevate nimekirjade tulpade järgi sorteerimise funktsionaalsus oli hea featuur.
 
Koodistiil, nagu ka teenuses, ei olnud parim. Kasutati eestikeelseid nimesid nii meetodite kui muutujate jaoks - üldiselt ei ole see põhjendatud, kuid kooliprojekti jaoks piisavalt hea lahendus - võibolla aitas see meeskonda ühtviisi mõtlemisel. Kood oli dokumenteeritud piisavas koguses, enamus meetodite ja muutujate nimesid seletasid enda eesmärki üheselt.
 
====Kahtlased koodiosad====
 
*Staatiliste meetodite seas klass “Krüpteerimine” - eestikeelsed täpitähed võivad suuri probleeme tekitada.
 
*Staatiliste meetodite klassi sees “AndmetegaSeotudMeetodid” pandi kasutaja.BlokeeritudKuni = DateTime.Now.AddYears(-99); - järelikult muutuv kuupäev erinevate kasutajate jaoks; hiljem võrdlemise lihtsustamiseks oleks pidanud kasutama ühte väärtust, näiteks DateTime minimaalset väärtust.
 
====Puudused rakenduse kasutaja vaatevinklist====
 
Üldised värvid rakendusel polnud head - oleks võinud kasutada lihtsaid värvipalette. Lisaks näiteks nupu rollover olek tegi nupu tausta helesiniseks, samal ajal kui selle tekst oli valge.
 
Paremal all olev “Sulge rakendus” nupp oleks võinud olla kõikidel vaadetel konstantne (praegu polnud seda kasutaja ja administraatori avavaadetes). Teine võimalus oleks olnud see nupp üldse ära jätta.
 
Erinevates lahtrites olid lubatud enamus sümboleid, tegelikult peaks ka seda kontrollima (näiteks numbriväljadele ainult numbreid lubada).
 
====Puuduste nimekiri vaadete järgi====
 
*AdminGruppidelisamine
 
Viimati vajutatud nupp jäi fookusesse ning võttis vastu Enter nupu vajutusi, kas see oli bug või hoopis feature?
 
Kirjaviga: “Kustuta valtud grupp” > “Kustuta valitud grupp”.
 
*AdminKasutajahaldus
 
Nimekirjas oleks võinud olla näha ka kasutaja blokeeritust, sest selline funktsionaalsus oli selles vaates olemas.
 
*AdminGruppidelisamine
 
Gruppe sai küll lisada, kuid hiljem muuta ei saanud. Kui peaks tekkima vajadus tootegruppi muuta, siis peaks terve tootegrupi koos selles grupis olevate toodetega kustutama ning kõik uuesti tekitama. Selle oleks võinud realiseerida kasvõi nii, et nimekirjast mingi tootegrupi valikul kuvatakse paremal selle tootegrupi infot ning seda saaks siis üle-salvestada.
 
*AvaekraanUser
 
Nupud ja sisutekst oleksid võinud olla ühtlaste suur-väiketähtedega.
 
*Parooli muutmine
 
Nupud oleksid võinud olla alati samas järjekorras, näiteks Salvesta nupp oleks võinud olla  konstantselt paremal, või konstantselt vasakul, mitte nagu [http://enos.itcollege.ee/~ktarma/up/VR/rets1.PNG siin].
 
Registreerides oli minimaalne parooli pikkus 8 tähemärki, parooli muutes seda ei kontrollitud - võis mõlemad lahtrid isegi tühjaks jätta.
 
*TooteLisamine
 
Ilma tootegrupita ei tohiks sellesse vaatesse üldse ligi pääseda, sest lisamisel on tootegrupp nõutud.
 
Tundub, et lisainfo väli oleks pidanud olema muutuv olenevalt antud tootegrupist. Tõenäoliselt seda arendajad soovisid, kuid realiseerida ei jõudnud.
 
Kogus ja Hind väljadel olid lubatud tähed (oleks võinud väljadel vaid numbrisisestust lubada), kontroll tehti alles peale “Salvesta” nupu vajutamist ja ka siis ei antud konkreetset vihjet, mis valesti läks.
 
Toote muutmisel “Parim enne” lahtris kuupäeva ei näidatud.
 
====Kokkuvõte====
 
Peab mainima, et rakendus oli täiesti kasutatav ning kokku ei jooksnud kordagi. Ärilistel eesmärkidel kasutamiseks peaks pöörama rohkem tähelepanu turvalisusele, tegelema puuduste nimekirjaga ning rakenduse koodi suurel määral optimeerima.
 
===Retsensioon meeskonna "[[AFFA II]]" Klientrakenduse ülesande kohta===
 
====Kood====
 
Rakenduses kasutati vaatemudeleid, seal oli kaks kausta: Mudelid ja Vaatemudelid, kusjuures mõlema sees oli realiseeritud palju funktsionaalsust.
 
Turvalisuse tagamiseks kasutati paroolide jaoks RSA krüpteerimist.
 
Koodistiil ei olnud parim, meetodite ja muutujate nimed ei olnud kohati mõistetavad. Inglisekeelse koodi kõrval kasutati eestikeelseid kommentaare. Enamus koodist oli dokumenteeritud.
 
====Rakendus kasutaja vaatevinklist====
 
Grupp AFFA II on teinud rakenduse, mis näitab erinevate ettevõtete finantsandmeid. Rakenduse kasutamiseks on vaja sisse logida. On olemas kolme tüüpi kasutajaid. Esimene kasutajagrupp on admin kasutajad, ehk siis kasutaja, kes haldab lehte, saab lisada kasutajaid, saab pärida kõiki andmeid ning samas ka kirjutada andmeid juurde. Teine kasutajagrupp, ehk Pro kasutaja saab pärida piiramatus mahus kõiki andmeid. Kolmas kasutajagrupp ehk Free kasutaja saab pärida ka andmeid, kuid tal on andmete hulk ja päringute arv piiratud. Kui kasutaja on sisse loginud, siis saab ta alustada andmete otsimisega. Otsinguid saab teostada kahte moodi- ettevõtte nime järgi ning aktsiasümboli järgi. Selle osa juures on selgelt näha, mille poolest erinevad kasutajagrupid ja nende õigused. Kui Free kasutajal on otsimine ja parameetrid piiratud, siis Pro kasutaja saab valida lisaks ka selle, mis perioodi andmeid kuvatakse. Esialgu tundus rakenduse kasutamine raske, kuid abiks oli grupi koostatud kasutusjuhend. Kui klient on leidnud endale sobiva ettevõtte või aktsiasümboli, siis saab ta andmed alla laadida vajutades "Load data" nuppu. Kui andmed on AFFA klienti laetud, peab kasutaja WCF akna sulgema ja seejärel kasutama klientrakendust ettevõtte väärtuse hinnangute arvutamise kohta. Edasiseks tegevuseks on vaja sisendiks anda finantsandmed, mis laetakse kas siis kasutaja poolt või otse internetist. Selle koha peal oleks võinud kasutada teistsugust lahendust, sest andmed peavad olema XML formaadis. Rakenduses oleks võinud kasutada sisendiks näiteks tabelkujul andmeid. Siinkohal on hea, et grupp on enda töös välja toonud ka soovituse selleks, et tulemused oleksid täpsemad. Üheks sisendi võimaluseks on laadida andmed otse veebilehelt Ycharts.com, kus saab tarkvara andmeid Exceli formaadis, mis töödeldakse XML formaati ja seejärel loetakse tarkvara poolt sisse. Ycharts.com miinuseks on see, et lehe kasutamine eeldab tasulise konto olemasolu. Edasi teostab tarkvara 4 tüüpi arvutusi. Kuna arvutuste põhjal saab näha ka tuleviku finantsprognoose ning leitakse ettevõtte väärtuse hinnang ja võrreldakse seda hetkelise turuhinnaga, siis on kasutajatel väga hea ülevaade firmade hetkeseisust ja ettekujutus nende tulevikunäitajatest. Kuna rakenduse abil antakse kliendile ka investeerimissoovitus siis on kasutajal hea võrrelda erinevaid investeerimisvõimalusi. Seega rakenduse kasutajatel, kes saavad kasulikku infot firma finantsseisu kohta, on väiksem võimalus teha valesid otsuseid.
 
Rakenduses saab kasutaja andmete vaatamiseks valida menüüst Input data, Quaterly data, Forecast ja Charts vahel. Input data juures saab kasutaja näha andmeid, mille põhjal tehakse tuleviku tarbeks prognoos. Valides Quaterly data, kuvatakse kasutajale andmed kvartalite kaupa ning arvutatakse välja ka muutused. Nende admete põhjal saab kasutaja ülevaate firma näitajatest kvartalites. Edasi on võimalik kasutajal näha tuleviku prognoosi, kus on siis välja toodud 5 aasta tulevikuprognoos. Kuna paljude investorite jaoks on väga oluline, et investeering saaks õigesse kohta tehtud,siis on rakendus firma seisu pildi saamiseks väga hea. Loomulikult ei saa rakendusest terviklikku pilti. Seega ei pruugi prognoos olla alati õige ja investeering võib minna siiski valesse kohta.  Rakenduse juures on väga suur pluss see, et kasutaja saab andmeid näha ka graafilisel kujul. Graafikud on kasutaja eelistustest lähtuvalt kohandatavad. See annab kasutajale parema ülevaate mingi teatud andmevoo kohta.
 
====Kokkuvõte====
 
Grupp oli oma töös ära kirjeldanud rakenduse funktsioonid ja töötamispõhimõtted ning õpetus oli kergesti arusaadav, rakenduse kasutamine ei olnud väga raske. Rakenduse ülesehitus on korralik. Ilme on rakendusel lihtne ning kergesti arusaadav. Kõik funktsioonid on välja toodud ja kergesti leitavad. Üheks suureks miinuseks rakenduse juures on aga see, et andmete laadimine käib XML faili näol või läbi tasulise internetisaidi.
 
Nagu ka AFFA II aruandes selgus, siis tegemist on varemvalminud rakenduse täiendusega. Mahult on antud projekt (eriti koodi mõttes) suur.
 
==Log==
07.03.2013 - sai valmis esimene osa kodusest tööst (XML)
07.03.2013 - sai valmis esimene osa kodusest tööst (XML)


09.03.2013 - kandsime esimese osa (XML) WIKI keskkonda
09.03.2013 - kandsime esimese osa (XML) WIKI keskkonda
29.03.2013 - kandsime XML retsensioonid WIKI keskkonda
25.05.2013 - kandsime teenuse kirjelduse WIKI keskkonda
26.05.2013 - kandsime rakenduse kirjelduse WIKI keskkonda
04.06.2013 - kandsime teenuste ja klientrakenduste retsensioonid WIKI keskkonda (X-Ladu ja AFFA II)

Latest revision as of 17:19, 4 June 2013

Meeskond

  • Kaido Tarma (D23)
  • Katre Paabo (D22)
  • Mark-Hendrik Mäeste (D21)
  • Kaisa Taelma (D23)

XML'i kodutöö

XML'i genereerimiseks loodud programm

using System;
using System.Text;
using System.Xml;

namespace Praktikum4
{
    class Program
    {
        static void Main(string[] args)
        {
            Random r = new Random();
            int i, j, k;

            int minTeemad = 1;
            int maxTeemad = 5;
            int minVastused = 1;
            int maxVastused = 9;

            string[] ained = new string[] { "Algebra ja graafiteooria", "Arvutigraafika", "Microsofti mobiilirakenduste arendamine", "Mobiilirakenduste arendamine Androidile", "Sidevõrgud", "Sissejuhatus Apple-i mob.", "Tarkvara testimise alused", "Veebirakenduste loomine ASP .NET abil", "Võrgurakendused II" };
            string[] inimesed = new string[] { "Mati", "Kati", "Jüri", "Teet", "Linda", "Vilma", "Olga", "Vallo", "Kaupo", "Peeter" };
            string[] teemanimed = new string[] { "Eksami eeldus", "Lisatunnid", "Esimene kontrolltöö", "Teine kontrolltöö", "Enesetestid", "Abimaterjalid", "Mingi teema", "Kehva teema", "Spikrid" };

            string[] tekstid = new string[] {
                "Tere, ma ei saa teemast üldse aru.",
                "Miks me ometi sellist asja tegema peame?",
                "Homses töös tuleb maha kirjutada.",
                "Soovin rentida pastakat..",
                "Please RTFM!",
                "Pliiats on kõver!!",
                "Tunnis saab ju niisama istuda, kodus on aega õppida.",
                "Kui õppejõule silma ei jää, siis häid hindeid ei saa!",
                "Mis te tulite siia nalja tegema vää?",
                "Kolmekesi üheskoos!",
                "Tahvel jäi mustaks..",
                "Kolmanda vastus oli 332232323*C-124321543512343564123",
                "Raske töö oli jah..",
                "Astrofüüsik!",
                "Kes viisi tahab saada??"
            };


            int teemaID = 1;
            int postitusID = 1;
            int vastusID = 1;

            int postitajaID = 1;

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = "\t";
            XmlWriter xmlWriter = XmlWriter.Create("test.xml", settings);

            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("KOOLIFOORUM");

            for (i = 0; i < ained.Length; i++)
            {
                xmlWriter.WriteStartElement("AINE");
                xmlWriter.WriteAttributeString("ID", i.ToString());
                xmlWriter.WriteAttributeString("NIMI", ained[i]);
                xmlWriter.WriteAttributeString("KOOD", ained[i].Substring(0, 4).ToUpper());

                for (j = 0; j < r.Next(minTeemad, maxTeemad); j++)
                {
                    xmlWriter.WriteStartElement("TEEMA");
                    xmlWriter.WriteAttributeString("ID", teemaID.ToString());
                    teemaID++;
                    xmlWriter.WriteAttributeString("NIMI", teemanimed[r.Next(0, teemanimed.Length - 1)]);

                    xmlWriter.WriteStartElement("POSTITUS");
                    xmlWriter.WriteAttributeString("ID", postitusID.ToString());
                    postitusID++;

                    xmlWriter.WriteStartElement("AEG");
                    DateTime aeg = new DateTime(r.Next(2000, 2010), r.Next(1, 12), r.Next(1, 28), r.Next(0, 23), r.Next(0, 59), r.Next(0, 59));
                    xmlWriter.WriteValue(aeg);
                    xmlWriter.WriteEndElement(); //AEG

                    xmlWriter.WriteStartElement("POSTITAJA");
                    postitajaID = r.Next(1, inimesed.Length - 1);
                    xmlWriter.WriteAttributeString("ID", postitajaID.ToString());
                    xmlWriter.WriteString(inimesed[postitajaID]);
                    xmlWriter.WriteEndElement(); //POSTITAJA

                    xmlWriter.WriteStartElement("TEKST");
                    xmlWriter.WriteString(tekstid[r.Next(0, tekstid.Length - 1)]);
                    xmlWriter.WriteEndElement(); //TEKST

                    xmlWriter.WriteEndElement(); //POSTITUS

                    for (k = 0; k < r.Next(minVastused, maxVastused); k++)
                    {
                        xmlWriter.WriteStartElement("VASTUS");
                        xmlWriter.WriteAttributeString("ID", vastusID.ToString());
                        vastusID++;

                        xmlWriter.WriteStartElement("AEG");
                        aeg = aeg.AddHours(r.Next(1, 2000));
                        aeg = aeg.AddSeconds(r.Next(1, 2000));
                        xmlWriter.WriteValue(aeg);
                        xmlWriter.WriteEndElement(); //AEG

                        xmlWriter.WriteStartElement("POSTITAJA");
                        postitajaID = r.Next(1, inimesed.Length - 1);
                        xmlWriter.WriteAttributeString("ID", postitajaID.ToString());
                        xmlWriter.WriteString(inimesed[postitajaID]);
                        xmlWriter.WriteEndElement(); //POSTITAJA

                        xmlWriter.WriteStartElement("TEKST");
                        xmlWriter.WriteString(tekstid[r.Next(0, tekstid.Length - 1)]);
                        xmlWriter.WriteEndElement(); //TEKST

                        xmlWriter.WriteEndElement(); //VASTUS
                    }

                    xmlWriter.WriteEndElement(); //TEEMA
                }

                xmlWriter.WriteEndElement(); //AINE
            }

            xmlWriter.WriteEndDocument(); //KOOLIFOORUM
            xmlWriter.Close();
        }
    }
}

Genereeritud XML

<?xml version="1.0" encoding="UTF-8"?>
<KOOLIFOORUM>
	<AINE ID="1" NIMI="Algebra ja graafiteooria" KOOD="ALGE">
		<TEEMA ID="1" NIMI="Mingi teema">
			<POSTITUS ID="1">
				<AEG>2004-09-24T18:18:12</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</POSTITUS>
			<VASTUS ID="1">
				<AEG>2004-10-19T20:42:22</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="2" NIMI="Arvutigraafika" KOOD="ARVU">
		<TEEMA ID="2" NIMI="Mingi teema">
			<POSTITUS ID="2">
				<AEG>2007-05-06T22:04:43</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Pliiats on kõver!!</TEKST>
			</POSTITUS>
			<VASTUS ID="2">
				<AEG>2007-05-29T14:21:05</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="3">
				<AEG>2007-06-25T06:46:48</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="4">
				<AEG>2007-09-01T13:53:27</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</VASTUS>
			<VASTUS ID="5">
				<AEG>2007-09-30T21:00:27</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="3" NIMI="Lisatunnid">
			<POSTITUS ID="3">
				<AEG>2008-08-05T20:19:01</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Pliiats on kõver!!</TEKST>
			</POSTITUS>
			<VASTUS ID="6">
				<AEG>2008-09-29T09:33:07</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="3" NIMI="Microsofti mobiilirakenduste arendamine" KOOD="MICR">
		<TEEMA ID="4" NIMI="Mingi teema">
			<POSTITUS ID="4">
				<AEG>2004-03-25T06:20:58</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</POSTITUS>
			<VASTUS ID="7">
				<AEG>2004-04-23T03:42:33</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="8">
				<AEG>2004-05-19T23:52:09</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
			<VASTUS ID="9">
				<AEG>2004-07-15T02:12:34</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="5" NIMI="Mingi teema">
			<POSTITUS ID="5">
				<AEG>2001-09-24T06:46:57</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</POSTITUS>
			<VASTUS ID="10">
				<AEG>2001-11-30T11:18:05</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Tunnis saab ju niisama istuda, kodus on aega õppida.</TEKST>
			</VASTUS>
			<VASTUS ID="11">
				<AEG>2002-01-11T03:23:25</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="6" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="6">
				<AEG>2002-02-25T19:21:26</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</POSTITUS>
			<VASTUS ID="12">
				<AEG>2002-04-09T00:47:33</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</VASTUS>
			<VASTUS ID="13">
				<AEG>2002-06-21T22:16:18</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="14">
				<AEG>2002-07-22T13:37:51</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="4" NIMI="Mobiilirakenduste arendamine Androidile" KOOD="MOBI">
		<TEEMA ID="7" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="7">
				<AEG>2001-05-22T01:56:53</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</POSTITUS>
			<VASTUS ID="15">
				<AEG>2001-08-11T09:10:32</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="16">
				<AEG>2001-10-30T22:10:54</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="8" NIMI="Mingi teema">
			<POSTITUS ID="8">
				<AEG>2006-04-09T02:28:08</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Please RTFM!</TEKST>
			</POSTITUS>
			<VASTUS ID="17">
				<AEG>2006-05-24T09:50:41</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</VASTUS>
			<VASTUS ID="18">
				<AEG>2006-07-24T01:11:00</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="19">
				<AEG>2006-07-31T01:42:12</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</VASTUS>
			<VASTUS ID="20">
				<AEG>2006-08-10T17:47:32</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
			<VASTUS ID="21">
				<AEG>2006-08-28T18:54:19</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Please RTFM!</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="9" NIMI="Lisatunnid">
			<POSTITUS ID="9">
				<AEG>2005-11-13T17:50:34</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Tunnis saab ju niisama istuda, kodus on aega õppida.</TEKST>
			</POSTITUS>
			<VASTUS ID="22">
				<AEG>2005-12-06T18:01:49</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Soovin rentida pastakat..</TEKST>
			</VASTUS>
			<VASTUS ID="23">
				<AEG>2006-02-17T05:12:51</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="24">
				<AEG>2006-03-22T17:26:33</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="5" NIMI="Sidevõrgud" KOOD="SIDE">
		<TEEMA ID="10" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="10">
				<AEG>2003-04-14T18:43:18</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</POSTITUS>
			<VASTUS ID="25">
				<AEG>2003-05-13T01:50:09</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Pliiats on kõver!!</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="11" NIMI="Abimaterjalid">
			<POSTITUS ID="11">
				<AEG>2008-10-09T10:32:20</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</POSTITUS>
			<VASTUS ID="26">
				<AEG>2008-11-24T19:37:37</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
			<VASTUS ID="27">
				<AEG>2008-12-07T18:55:04</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</VASTUS>
			<VASTUS ID="28">
				<AEG>2008-12-15T12:02:16</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="12" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="12">
				<AEG>2003-11-24T13:31:16</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</POSTITUS>
			<VASTUS ID="29">
				<AEG>2004-01-05T10:01:45</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="6" NIMI="Sissejuhatus Apple-i mob." KOOD="SISS">
		<TEEMA ID="13" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="13">
				<AEG>2001-02-23T09:30:10</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Please RTFM!</TEKST>
			</POSTITUS>
			<VASTUS ID="30">
				<AEG>2001-03-28T13:42:14</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Pliiats on kõver!!</TEKST>
			</VASTUS>
			<VASTUS ID="31">
				<AEG>2001-03-31T17:08:02</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
			<VASTUS ID="32">
				<AEG>2001-04-20T23:39:09</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</VASTUS>
			<VASTUS ID="33">
				<AEG>2001-06-08T02:06:32</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="14" NIMI="Abimaterjalid">
			<POSTITUS ID="14">
				<AEG>2006-09-05T09:08:49</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</POSTITUS>
			<VASTUS ID="34">
				<AEG>2006-09-19T20:18:16</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</VASTUS>
			<VASTUS ID="35">
				<AEG>2006-11-06T18:42:59</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</VASTUS>
			<VASTUS ID="36">
				<AEG>2006-12-25T01:45:19</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="7" NIMI="Tarkvara testimise alused" KOOD="TARK">
		<TEEMA ID="15" NIMI="Eksami eeldus">
			<POSTITUS ID="15">
				<AEG>2008-08-15T01:52:45</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</POSTITUS>
			<VASTUS ID="37">
				<AEG>2008-09-04T20:19:06</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
			<VASTUS ID="38">
				<AEG>2008-09-10T17:21:33</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
			<VASTUS ID="39">
				<AEG>2008-12-02T09:28:00</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="16" NIMI="Abimaterjalid">
			<POSTITUS ID="16">
				<AEG>2008-07-02T14:46:16</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</POSTITUS>
			<VASTUS ID="40">
				<AEG>2008-07-18T11:55:29</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Pliiats on kõver!!</TEKST>
			</VASTUS>
			<VASTUS ID="41">
				<AEG>2008-08-03T01:24:04</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Tunnis saab ju niisama istuda, kodus on aega õppida.</TEKST>
			</VASTUS>
			<VASTUS ID="42">
				<AEG>2008-10-23T10:50:39</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
			<VASTUS ID="43">
				<AEG>2008-11-01T08:14:37</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Soovin rentida pastakat..</TEKST>
			</VASTUS>
			<VASTUS ID="44">
				<AEG>2009-01-11T11:35:00</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Please RTFM!</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="17" NIMI="Eksami eeldus">
			<POSTITUS ID="17">
				<AEG>2006-02-13T11:02:08</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Raske töö oli jah..</TEKST>
			</POSTITUS>
			<VASTUS ID="45">
				<AEG>2006-05-05T05:10:52</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="46">
				<AEG>2006-05-17T19:30:27</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</VASTUS>
			<VASTUS ID="47">
				<AEG>2006-07-07T04:51:29</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="18" NIMI="Enesetestid">
			<POSTITUS ID="18">
				<AEG>2009-02-16T02:44:09</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</POSTITUS>
			<VASTUS ID="48">
				<AEG>2009-04-19T08:45:00</AEG>
				<POSTITAJA ID="9">Kaupo</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
			<VASTUS ID="49">
				<AEG>2009-06-26T19:48:59</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
			<VASTUS ID="50">
				<AEG>2009-08-05T10:04:47</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Kolmekesi üheskoos!</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="8" NIMI="Veebirakenduste loomine ASP .NET abil" KOOD="VEEB">
		<TEEMA ID="19" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="19">
				<AEG>2003-05-05T13:23:44</AEG>
				<POSTITAJA ID="5">Linda</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</POSTITUS>
			<VASTUS ID="51">
				<AEG>2003-05-30T15:46:30</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
			<VASTUS ID="52">
				<AEG>2003-07-26T20:52:26</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="53">
				<AEG>2003-10-02T15:59:39</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="54">
				<AEG>2003-11-03T03:19:50</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="20" NIMI="Enesetestid">
			<POSTITUS ID="20">
				<AEG>2008-02-23T06:40:58</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</POSTITUS>
			<VASTUS ID="55">
				<AEG>2008-04-04T01:56:57</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="21" NIMI="Esimene kontrolltöö">
			<POSTITUS ID="21">
				<AEG>2000-09-09T06:27:22</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</POSTITUS>
			<VASTUS ID="56">
				<AEG>2000-11-25T05:39:35</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Kolmanda vastus oli 332232323*C-124321543512343564123</TEKST>
			</VASTUS>
			<VASTUS ID="57">
				<AEG>2000-12-23T15:04:12</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</VASTUS>
			<VASTUS ID="58">
				<AEG>2000-12-26T22:13:02</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Tere, ma ei saa teemast üldse aru.</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
	<AINE ID="9" NIMI="Võrgurakendused II" KOOD="VÕRG">
		<TEEMA ID="22" NIMI="Abimaterjalid">
			<POSTITUS ID="22">
				<AEG>2003-09-05T15:45:26</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Homses töös tuleb maha kirjutada.</TEKST>
			</POSTITUS>
			<VASTUS ID="59">
				<AEG>2003-09-14T22:50:35</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Tunnis saab ju niisama istuda, kodus on aega õppida.</TEKST>
			</VASTUS>
			<VASTUS ID="60">
				<AEG>2003-11-12T12:13:42</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</VASTUS>
			<VASTUS ID="61">
				<AEG>2004-01-19T21:39:24</AEG>
				<POSTITAJA ID="2">Kati</POSTITAJA>
				<TEKST>Tahvel jäi mustaks..</TEKST>
			</VASTUS>
			<VASTUS ID="62">
				<AEG>2004-01-25T22:45:18</AEG>
				<POSTITAJA ID="8">Vallo</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
			<VASTUS ID="63">
				<AEG>2004-03-31T05:49:55</AEG>
				<POSTITAJA ID="1">Mati</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="64">
				<AEG>2004-05-07T17:02:52</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Soovin rentida pastakat..</TEKST>
			</VASTUS>
		</TEEMA>
		<TEEMA ID="23" NIMI="Enesetestid">
			<POSTITUS ID="23">
				<AEG>2002-01-17T14:38:24</AEG>
				<POSTITAJA ID="6">Vilma</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</POSTITUS>
			<VASTUS ID="65">
				<AEG>2002-02-06T23:57:36</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Miks me ometi sellist asja tegema peame?</TEKST>
			</VASTUS>
			<VASTUS ID="66">
				<AEG>2002-02-21T15:30:47</AEG>
				<POSTITAJA ID="4">Teet</POSTITAJA>
				<TEKST>Mis te tulite siia nalja tegema vää?</TEKST>
			</VASTUS>
			<VASTUS ID="67">
				<AEG>2002-04-09T14:35:29</AEG>
				<POSTITAJA ID="3">Jüri</POSTITAJA>
				<TEKST>Kui õppejõule silma ei jää, siis häid hindeid ei saa!</TEKST>
			</VASTUS>
			<VASTUS ID="68">
				<AEG>2002-04-18T00:54:36</AEG>
				<POSTITAJA ID="7">Olga</POSTITAJA>
				<TEKST>Astrofüüsik!</TEKST>
			</VASTUS>
		</TEEMA>
	</AINE>
</KOOLIFOORUM>

Stiilifail 1

See stiilifail väljastab html lehel kõik postitused ning nende vastused.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <!--See stiilifail väljastab html lehel kõik postitused ning nende vastused-->
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <body style="background-color:#294052;font-family:Arial;font-size:12pt">
        <span style="font-size:25pt;font-weight:bold;color:white">
          KOOLIFOORUM
        </span>
        <xsl:for-each select="KOOLIFOORUM/AINE" >
          <div style="background-color:#8FBCDB;font-size:20pt;font-weight:bold;padding:5px">
            <xsl:value-of select="@NIMI"/>
          </div>
          <xsl:for-each select="TEEMA" >
            <div style="background-color:#F4D6BC;padding:5px">
              <span style="font-size:16pt;font-weight:bold">
                <xsl:value-of select="@NIMI"/>
              </span>
            </div>
            <div style="background-color:#F8E4CC;padding:10px">
              <b>Postitus </b> @
              <xsl:value-of select="POSTITUS/AEG"/><br></br>
              <xsl:value-of select="POSTITUS/POSTITAJA"/>:
              <xsl:value-of select="POSTITUS/TEKST"/><br></br>
              <xsl:for-each select="VASTUS">
                <b>Vastus </b> @
                <xsl:value-of select="AEG"/> <br></br>
                <xsl:value-of select="POSTITAJA"/>:
                <xsl:value-of select="TEKST"/> <br></br>
              </xsl:for-each>
            </div>
          </xsl:for-each>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Stiilitud HTML

Stiilifail 1'ga stiilitud XML, väljastus HTML kujul: http://enos.itcollege.ee/~ktarma/Vorgurakendused/XML/test_Stiil1.xml

Stiilifail 2

Antud stiilifail kuvab kõik foorumi kasutajad ja iga kasutaja puhul kasutaja algatatud teemad ühes postitamise ajaga.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:fn="http://www.w3.org/2005/xpath-functions">
  <!--Antud stiilifail kuvab kõik foorumi kasutajad ja iga kasutaja puhul kasutaja algatatud teemad ühes postitamise ajaga-->
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <KASUTAJAD>
      <xsl:for-each select="//POSTITAJA[not(. = preceding::POSTITAJA)]" >
        <KASUTAJANIMI>
          <xsl:value-of select="."/>
        </KASUTAJANIMI>
        <xsl:variable name="tmp" select="@ID" />
        <POSTITUSED>
          <xsl:for-each select="//POSTITUS[POSTITAJA/@ID = $tmp]" >
            <POSTITUS>
              <AEG>
                <xsl:value-of select="AEG"/>
              </AEG>
              <TEXT>
                <xsl:value-of select="TEKST"/>
              </TEXT>
            </POSTITUS>
          </xsl:for-each>
        </POSTITUSED>
      </xsl:for-each>
    </KASUTAJAD>
  </xsl:template>
</xsl:stylesheet>

Stiilifail 3

See stiilifail väljastab XML kujul kõikide postituste teema ning aine, kus see asub.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!--See stiilifail väljastab XML kujul kõikide postituste teema ning aine, kus see asub-->
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="/">
    <POSTITUSED>
      <xsl:for-each select="KOOLIFOORUM/AINE/TEEMA/POSTITUS">
        <POSTITUS>
          <xsl:attribute name="ID">
            <xsl:value-of select="@ID"/>
          </xsl:attribute>
          <TEEMA>
            <xsl:attribute name="NIMI">
              <xsl:value-of select="../@NIMI"/>
            </xsl:attribute>
          </TEEMA>
          <AINE>
            <xsl:attribute name="NIMI">
              <xsl:value-of select="../../@NIMI"/>
            </xsl:attribute>
            <xsl:attribute name="KOOD">
              <xsl:value-of select="../../@KOOD"/>
            </xsl:attribute>
          </AINE>
        </POSTITUS>
      </xsl:for-each>
    </POSTITUSED>
  </xsl:template>
</xsl:stylesheet>

Manuaalselt genereeritud skeemifail

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
  <xs:element name="KOOLIFOORUM" type="foorumType" />
  
  <xs:complexType name="foorumType">
    <xs:sequence minOccurs="1" maxOccurs="unbounded">
      <xs:element name="AINE" type="aineType" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="aineType">
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element name="TEEMA" type="teemaType" />
    </xs:sequence>
    <xs:attribute name="ID" type="xs:positiveInteger" use="required" />
    <xs:attribute name="NIMI" type="xs:string" use="required" />
    <xs:attribute name="KOOD" type="xs:string" use="required" />
  </xs:complexType>

  <xs:complexType name="teemaType">
    <xs:sequence minOccurs="1" maxOccurs="unbounded">
      <xs:element name="POSTITUS" type="postitusType" />
      <xs:element name="VASTUS" type="postitusType" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="ID" type="xs:positiveInteger" use="required" />
    <xs:attribute name="NIMI" type="xs:string" use="required" />
  </xs:complexType>

  <xs:complexType name="postitusType">
    <xs:all>
      <xs:element name="AEG" type="xs:dateTime"  />
      <xs:element name="POSTITAJA" type="postitajaType" />
      <xs:element name="TEKST" type="xs:string" />
    </xs:all>
    <xs:attribute name="ID" type="xs:positiveInteger" use="required" />
  </xs:complexType>

  <xs:complexType name="postitajaType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="ID" type="xs:positiveInteger" use="required" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  
</xs:schema>

Automaatselt genereeritud skeemifail

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="KOOLIFOORUM">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="AINE">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="TEEMA">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="POSTITUS">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="AEG" type="xs:dateTime" />
                          <xs:element name="POSTITAJA">
                            <xs:complexType>
                              <xs:simpleContent>
                                <xs:extension base="xs:string">
                                  <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
                                </xs:extension>
                              </xs:simpleContent>
                            </xs:complexType>
                          </xs:element>
                          <xs:element name="TEKST" type="xs:string" />
                        </xs:sequence>
                        <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
                      </xs:complexType>
                    </xs:element>
                    <xs:element maxOccurs="unbounded" name="VASTUS">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="AEG" type="xs:dateTime" />
                          <xs:element name="POSTITAJA">
                            <xs:complexType>
                              <xs:simpleContent>
                                <xs:extension base="xs:string">
                                  <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
                                </xs:extension>
                              </xs:simpleContent>
                            </xs:complexType>
                          </xs:element>
                          <xs:element name="TEKST" type="xs:string" />
                        </xs:sequence>
                        <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
                  <xs:attribute name="NIMI" type="xs:string" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
            <xs:attribute name="NIMI" type="xs:string" use="required" />
            <xs:attribute name="KOOD" type="xs:string" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XML Retsensioonid

Retsensioon meeskonna "BitByBit" XML ülesande kohta

Meeskond BitbyBit on valinud oma teemaks muusika ning sellega seotud elementide kategoriseerimise ja kirjeldamise. XML fail juurelemendiks on üldiselt muusika (music), järjestuse järgmiseks etapiks on esitaja (artist), kellel võib olla mitu albumit. Igal albumil on järjestatud lood (song), milledel on eraldi kommentaarid, ja albumi kommentaar.
XML on süntaktilise ehituse poolest korrektne. Otsingute tegemiseks on selline XML küllaltki hea. Sellegi poolest jääb arusaamatuks, miks on igal lool eraldi žanr, kui iga albumi juures on kirjeldatud selle muusikavool. See oleks mõistetav, kui tegemist on n-ö kogutud teoste või aastahittidega, millel iga laul võib olla eri žanrist. Sellisel juhul peaks iga laulu juures olema ka eraldi esitaja, mis enamus juhtudel tekitaks info liiasust. Samuti näib eraldi albumi kommentaar (album comments) liiasena, sest iga muusikapala juures on eraldi kommentaar.
XML-i skeemifail (XSD) on vastavuses XML-is esinevate elementide, atribuutide ja atribuudi nimede ning tüüpidega.
Esimese päringu puhul on tegemist kõiki „metal“ žanri sisaldavate lugude väljaeraldamisega. Selline otsing on vajalik juhul, kui tegemist on albumiga, millel on paljude esinejate palad. Praegusel juhul piisaks otsingust üle albumi žanrite.
Teine päring käib üle kõik albumid ning kuvab nende andmed üksteise järel. Tulemuseks on loetavavad eraldused, millest on väga hea lugeda iga albumi kohta. Kolmas päring on samuti head ülevaadet andev tabel lauljate ning kõigi nende albumite kohta. Selline päring on paslik näiteks muusikapoes, kus tihti on vaja ülevaadet konkreetse artisti kõikidest albumitest.
Töö täitis ülesande tingimusi. Vaatamata on lühidusele, täitab see oma ülesannet. Hea loetavuse tõttu ei näe põhjust eraldi dokumentatsiooniks ega kommentaarideks. Iga päringu juures oli välja trükitud, mida konkreetne väärtus tähendab.

Retsensioon meeskonna "Trenniinfo" XML ülesande kohta

XML fail on suhteliselt lühike. Aadressi asemel oleks võinud kasutada linna, sest aadress märgib pigem täpsemat asukohta. Kalev Spa spordialade juures on mõlemal treeningajaks argipäevad. Ühes on see ka eraldi välja toodud, teises on ainult päevadena kirja pandud. See oleks võinud olla ühtemoodi tehtud.
Sama kehtib ka Saku spordikompleksi kohta. Treeningpäevad võiks olla ühtemoodi märgitud. Kui trenni saab teha igapäevaselt, siis võiks see igal pool ka samamoodi märgitud olla. Samuti hakkab siin silma ka spordialade juures ära märgitud tasuta võimaluse koht, kuigi allpool maksumuse juures on selleks täiesti hea koht olemas. Pole vajadust sama infot allpool uuesti korrata.
Esimese XML transformatsioonifaili puhul väljastatakse kõik spordikohad koos infoga. Paremini loetavuse koha pealt võiks peale treeningu kohta ja ennem spordiala olla ka üks tühi rida, sest vastasel juhul tekib mulje, et see kehtibki vaid esimese spordiala kohta, kui tegelikult näitab see infot ka järgmiste kohta.
Teise XML transformatsiooni faili puhul on sama asi. Ei ole väga hästi aru saada, kas andmed kehtivad vaid teatud informatsiooni kohta või laienevad ka allpool olevatele. Tulemus on praktiliselt sama, mis esimese puhul. Muutunud on ainult see, et maksumuse koha peal öeldakse, et see on tasuta.
Kolmanda XML transformatsiooni faili juures võib märgata praktiliselt sama tulemust, mis eelmiste puhul. Seekord on aga paremini aru saada, mille kohta info käib. Siin tulevad välja ka erinevused treeningpäevade suhtes. Kui ühel on ETKNRLP kirjeldatud päevadena, siis teisel on märgitud, et toimub igapäevaselt, kuigi need tähendavad ühte ja sama asja.
Kõiki kolme transformatsiooni puhul oleks võinud olla erinevad väljastused. Hetkel väljastavad kõik kolm praktiliselt ühte ja sama väärtust. Aga oleks võinud olla väljastused näiteks kõikidele sisehallidele või kõikidele jõutreeningutele.

Teenuse Kirjeldus

Teenus on mõeldud foorumitega seonduva loomiseks, haldamiseks ja muutmiseks.
Iga foorumi juures on kategooriad, mis liigitavad konkreetse foorumi suundi.
Kategooria jaguneb omakorda teemadeks, mida võib ühe kategooria raames olla mitmeid.
Teemal on kasutajate poolt postitatud teated ehk postitused.

Foorumi päringud

Foorumi päringud implementeerivad foorumi interfacei.

  • getApplicationIdByForumName - Võimaldab pärida aplikatsiooni ID-d foorumi nime järgi.
  • getAll – Võimaldab pärida kõik foorumid, arvestades suletud foorumeid.
  • getById – Foorumi päring ID järgi.
  • create – Foorumi loomine, mille käigus määratakse foorumile nimi, loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
  • update – Foorumi uuendamine. Sellega saab muuta foorumi nime.
  • delete – Foorumi sulgemine- sulgemise ja muutmise ajaks määratakse meetodi rakendamise aeg.
  • getAllCategoriesInForum – Konkreetse foorumi kõigi kategooriate päring.
  • getAllUsersInForum - Konkreetse foorumi kõigi seal registreerunud kasutajate päring.

    Kategooria päringud

    Kategooria päringud implementeerivad kategooria interfacei, mis omakorda baas interfacei (ITemplate).

  • getAll – Võimaldab pärida kõik kategooriad.
  • getById –Kategooria päring ID järgi.
  • create – Kategooria loomine, mille käigus määratakse kategooria nimi,kirjeldus, loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
  • update – Kategooria uuendamine. Sellega saab muuta kategooria nime ja kirjeldust.
  • delete – Kategooria sulgemine- sulgemise ja muutmise ajaks määratakse meetodi rakendamise aeg.
  • getAllTopicsInCategory – Konkreetse kategooria kõigi teemade päring.

    Teema päringud

    Teema päringud implementeerivad teema interfacei, mis omakorda baas interfacei (ITemplate).

  • getAll – Võimaldab pärida kõik teemad.
  • getById –Teema päring ID järgi.
  • create – Teema loomine, mille käigus määratakse teema nimi, teema looja kasutaja ID, kategooria ID, kuhu see teema kuulub ja loomise kuupäev ning uuenduse väärtuseks määratakse loomise hetk.
  • update – Teema uuendamine. Võimalik muuta kategooriat, kuhu vastav teema kuulub, ja teema nime.
  • delete – Teema kustutamine- sulgemise ajaks määratakse meetodi rakendamise aeg.
  • getByCategoryId –Teemade otsing, mis pole kustutatud, kategooria ID järgi.
  • getByUserId – Konkreetse kasutaja kõigi lisatud teemade otsing.

    Postituse päringud

    Postituse päringud implementeerivad postituse interfacei, mis omakorda baas interfacei (ITemplate).

  • getAll – Võimaldab pärida kõik postitused.
  • getById –Postituse päring ID järgi.
  • create – Postituse loomine, mille käigus määratakse postituse nimi ja tekst, postituse looja kasutaja ID, teema ID, mille all postitus tehti, ning uuenduse ja loomise väärtuseks määratakse loomise hetk.
  • update – Postituse uuendamine. Võimalik muuta teemat, kuhu vastav postitus kuulub, ja postituse nime ning teksti.
  • delete – Postituse kustutamine- sulgemise ajaks määratakse meetodi rakendamise aeg.
  • getByUserId – Konkreetse kasutaja kõigi lisatud postituste otsing.
  • getByTopicId – Postituste otsing, mis pole kustutatud, teema ID järgi.
  • getAnswers – Postituse vastuse otsing vastava postituse ID järgi.

    Kasutaja päringud

    Kasutaja päringud implementeerivad kasutaja interfacei.

  • getAll – Võimaldab pärida kõik kasutajaid, arvestades suletud kasutajaid.
  • getById –Kasutaja päring ID järgi.
  • create – Kasutaja loomine, mille käigus määratakse kasutajanimi, kasutaja ees-ja perekonnanimi, parool, e-maili aadress ja salasõna. Samuti lisatakse kasutaja tabelisse Membership, user ja UserProperties.
  • update – Kasutaja uuendamine. Kasutaja saab muuta salasõna, emaili ja kommentaari.
  • updateUserProperties –Kasutaja propertite uuendamine.
  • delete – Kasutaja kustutamine ID järgi.
  • undelete – Kasutaja kustutamise annulleerimine.
  • visit – Viimase külastuse väärtuse uuendamine.
  • getAllPostsByUser – Kasutaja kõigi postituste otsing.
  • getByUsername – Kasutaja otsing kasutajanime järgi.
  • getByEmail – Kasutaja otsing emaili järgi.
  • validateUser – Kasutaja valideerimine ehk kindlaks tegemine, kas vastav forum, kasutajanimi ja salasõna ühtivad.
  • isForumUser - Kasutaja kindlakstegemine, kas tegemist on vastava foorumi kasutajaga.
  • getProperties – Kasutaja propertite saamine.
  • getUserRoles – Kasutaja rolli päring kasutaja ID järgi.
  • updateUserRoles – Kasutaja rolli muutmine. Ühel kasutajal võib olla mitu rolli.

    Rolli päringud

    Rolli päringud implementeerivad rolli interfacei.

  • getAll – Võimaldab pärida kõik rollid.
  • getById –Rolli päring ID järgi.
  • create – Rolli loomine. Lisaks tagastatakse selle ID.
  • update – Rolli uuendamine ID järgi.
  • delete - Rolli kustutamine ID järgi.
  • changeUserRole - Kasutaja rolli muutmine.

    FirstQueries

  • setup - Foorumi tegemiseks vajalik meetod; luuakse administraator.

    Membership päringud

    Membership päringud implementeerivad Membership interfacei.

  • getById – Membership info otsing kasutaja ID järgi.
  • All- Kõigi Membershipide otsing.

    Klientrakenduse Kirjeldus

    Rakendusel on kahte tüüpi kasutajaid-tavakasutajad ja administraator.
    Selleks, et foorumeid, kategooriaid ja teemasid vaadata on vaja sisse logida.
    Kui kasutajal veel kontot pole, saab ta selle teha registreerimise lehel.
    Kasutaja saab vajadusel muuta enda andmeid ja profiilipilti.
    Kasutaja saab lisada, muuta ja kommenteerida vaid postitusi.
    Foorumeid, kategooriaid ja topicuid saab lisada vaid administraator.
    Administraator saab foorumeid aktiivseks ja mitteaktiivseks teha. Lisaks saab administraator muuta ning vaadata kasutajate andmeid ja vajadusel kasutajaid kustutada.

    Selliseid rakendusi on maailmas palju, ning nagu näha, siis pole olemas seda kõige paremat - täiuslikku foorumit.
    Ka meie rakendust(ja selle kõrvalt teenust) saaks veel suurel määral täiendada. Hetkel peame suurimaks puuduseks ebaturvalisust ja seda, et kliendile pole lisatud töötavat custom membershipi.
    Kasutasime ASP.NET MVC4 tehnoloogiat.

  • Pealeht - [1]
  • Sisselogimine - [2]
  • Registreerimine - [3]
  • Kasutaja profiili muutmine - [4]
  • Kategooria ja teema vaade - [5]
  • Kategooria muutmine ja lisamine - [6]
  • Teema lisamine - [7]
  • Postituse lisamine - [8]
  • Postituse vaade - [9]
  • Foorumi ülevaade - [10]
  • Kasutajate vaade - [11]

    Rakenduse käivitamine

    1) Esmalt tuleb alla laadida pakk siit või kasutada selleks TFSi.

    2) Siis tuleb ära muuta WcfForumService Web.config'u serviceCertificate thumbprint (WcfForumService->Web.config->Advanced->Service Behaviors->serviceBehavior->serviceCredentials->serviceCertificate). (enne seda peab teil olema vajalik sertifikaat, mille loomist kirjeldatakse siin)

    3) Tõenäoliselt peate ka rebuildima library, clienti ja service.

    4) Nüüd tuleb luua andmebaasi(.\sqlexpress) vajalikud tabelid. Selleks on vastavad SQL skriptid ForumServiceLibrary/Scripts kaustas.

    5) Nüüd tuleb ka ASP.NET Membershipi jaoks vajalikud tabelid luua, seda on kirjeldatud siin.
    5.1) See võib visata errorit, et NETWORK SERVICE on juba olemas, siis tuleb see käsitsi ära kustutada ja ikkagi 5) uuesti teha.

    6) Siis võite käivitada rakenduse.

    7) Teile näidatakse tühja lehte, kus veel ühtegi foorumit ei ole, kuna andmebaas on tühi. Esimene setup toimub aadressil: http://localhost:64621/Home/Setup

    8) Peale seda peaks teil olema administraatori õigusega kasutaja ning esimene foorum loodud.
    8.1) Kui esineb probleeme sellise "külma stardiga", siis võite andmebaasist vanad kirjed ära kustutada skriptiga (ForumServiceLibrary/Scripts/SQLdelete.sql) ning uuesti proovida.

    Teenuste Retsensioonid

    Retsensioon meeskonna "X-Ladu" Teenuse ülesande kohta

    Teenus

    Tegemist on Windows Communication Foundation tehnoloogial realiseeritud teenusega. Teenuse funksionaalsus on defineeritud projektis X-LaduLibrary. Seega teenus ja kasutatav äriloogika on eraldatud, ning seega on võimalik olemasoleva loogika lihtsam muutmine ning taaskasutus teistes projektides. Teenus vastab üldjoontes aines toodud ülesandepüstitusele:

    • Teenus võimaldab pidada logi kasutajate tegevuste kohta ja kasutajate haldamist. Logi on baasis toodud eraldi tabelina, kuid logi täiendamine ei toimu teenuses automaatselt vaid see funktsionaalsus peab olema realiseeritud kliendi poolel. Teenus kujutab endast suuresti lihtsalt liidest klientrakenduse ja baasi vahel.
    • Kasutajate tuvastamine teenuse poolel piirdub parooli ja kasutajanime põhjal kasutaja baasist leidmisega. Nagu ka autorid ise on öelnud, siis teenuse turvamine on hetkel veel realiseerimata. Kasutusel on basicHttpBinding.

    Teenus on loodud ühe konkreetse ettevõtte tarbeks ja üldiselt teistele teenuse pakkumist ei võimalda, kuna kliendi tuvastamine puudub ja uute klientide lisamine eeldab ka olemasoleva klientrakenduse muutmist (ülesande püstituse kohalt pole see küll puudus, kuna teenus võibki olla loodud vaid ühe “juriidilise” kliendi tarbeks). Teisalt, skaleeruvust arvestades on tegemist siiski miinusega, kuna edaspidine muutmine on selle võrra keerulisem.

    Meeskonna lehel on kergesti leitav nii ammendav teenuse kirjeldus kui ka kasutajajuhend, mille abil on võimalik teenus ka reaalselt käivitada.

    Kood

    Teenuses on kood loogiliselt liigendatud: eraldi kaustades on mudelid ja “data access” kiht, milles on baasi vastu käivad päringud. Päringud on eristatud kasutaja õiguste põhjal (tavakasutaja ja administraatori päringud), mitte olemite kaupa (nt tootegrupi pärningud jne). Taoline lähenemine ilmselt kergendab kliendis loogika kirjeldamist. Lisaks on eraldi välja toodud nn automaatsed päringud kasutaja autoriseerimiseks ning logi lisamiseks.

    Projektle on lisatud ka vajalik sql skript, mis võimaldab projekti tööle saada ka retsenseerijatel.

    Andmebaasis on toodud tabelid “Kasutaja”, “KasutajaLogi”, “Kommentar”, “Toode”, ja “Tootegrupp”. Kuigi ka nende tabelite abil saab luua töötava rakenduse, siis andmebaasi disain jääb kohati siiski küsitavaks. Näiteks on olemis “Kasutaja” sõnena kirjas kommentaar, kuid samas on loodud ka Kommentaari tabel, millesse kasutaja saab lisada kommentaare toote kohta. Üldisem lahendus oleks kasutada Kommentaaride tabelit ja kahte vahetabelit kasutajate ja toodete kommentaaride hoidmiseks. Sellisel juhul ei tekiks ka segadust nimetustega, kuna mõiste “Kommentaar” tähendaks ühte ja sama nii toote kui ka kasutaja puhul.

    Andmebaasi disaini juures tasuks märkida ka seda, et sõltuvalt toote kategooriast võidakse baasis hoida suurel hulgal liigseid andmeid: näiteks toote “tomatimahl” korral on tabelis “Toode” ikkagi olemas väljad pikkuse, laiuse, rõiva suuruse ja muude parameetrite kirjeldamiseks. Üheks lahenduseks oleks lisada tabelid erinevate parameetrite grupeerimiseks toote iseloomu järgi. Ka ühikud võiksid olla eraldi tabelis.

    Võimalik, et taoline lähenemine muudaks projekti mõnevõrra keerukamaks, kuid taas: edaspidi oleks lihtsam teenust muuta (näiteks lisada ühikute teisendamise loogika teenusesse). Lisaks paraneks kasutusmugavus, kuna kasutaja ei pea leidma suure hulga info hulgast tarvilikke parameetreid.

    Kommentaare pole mõistetavatel põhjustel paljudele meetoditele lisatud. Nimelt on meetodite ja argumentide nimetused valdavalt ennast seletavad (näiteks meetod annaToodeKoguseJargi(double kogus)) ja seega kommentaaride vähesus üldjuhul ei häiri. Küll aga võiks ära mainida, et kui jätta kommentaarid lisamata, siis pole mõtet jätta koodi ka tühjasid dokumentatsiooni väljasid, mis häirivad rohkem kui puuduvad märked. Tõenäoliselt on tegu ajapuuduse tagajärjega, kuid olulisem osa (teenuse poolt pakutavad meetodid) on ka dokumenteeritud.

    Mis on mõnevõrra harjumatu on valitud keel: koodis on igal võimalikul juhul kasutusel eesti keel ja näiteks andmebaasi juures tähendab see võrdlemisi kummalisi tabelite nimetusi (näiteks “Toodes”). Teisalt on valitud stiili läbivalt järgitud, kui välja arvata vahemuutuja “query”. Üldiselt on eestikeelne kood küll harjumatu, kuid arvatavasti pole see mitte otseselt puudus, kuna tegemist on koolitöö raames valminud projektiga. Probleemiks osutuks see tõenäoliselt alles reaalse kasutamise korral.

    Kokkuvõte

    Üldjoontes on teenus realiseeritud korrektselt: kogu olemasolev funktsionaalsus töötab ja kood on lihtsalt loetav. Miinustena võib välja tuua teenuse turvalisuse puudumist ja võibolla ka mudelite disaini, mis piirab liigselt pakutavaid võimalusi ja vähendab kasutusmugavust.

    Teenus on piisaval määral dokumenteeritud.

    Retsensioon meeskonna "AFFA II" Teenuse ülesande kohta

    Teenus

    Tegemist on Windows Communication Foundation tehnoloogial realiseeritud teenusega. Teenuse funksionaalsus on defineeritud projektis AFFA2WcfServiceLibrary. Seega teenus ja kasutatav äriloogika on eraldatud, ning seega on võimalik olemasoleva loogika lihtsam muutmine ning taaskasutus teistes projektides. Teenus vastab aines toodud ülesandepüstitusele:

    • Teenus võimaldab pidada logi kasutajate tegevuste kohta ja kasutajate haldamist. Logi peetakse kõigi meetodite väljakutsete kohta kasutajate kaupa. Lisaks peab Membership provider eraldi arvet kasutajate selliste tegevuste kohta nagu sisselogimine, lukustamine jne.
    • Kasutajate tuvastamine toimub Membership provider-i Validate() meetodi abil ja infot sisse loginud kasutajate kohta hoitakse staatilises listis. Seejuures genereeritakse iga sisselogimise korral (Guid) SessionId. Välja logimisel eemaldatakse kasutaja info staatilisest listist.

    Teenuse eesmärk on finantsandmete pakkumine kasutajatele.Seejuures kasutatakse eelnevalt baasi sisestatud andmeid. Lahtiseks jääb küsimus, mil viisil andmeid uuendatakse. Hetkel teenuse koodis see ilmutatud kujul realiseeritud ei ole. Samas ei raskenda olemasolev kood selle funktsiooni lisamist.

    Dokumentatsioon on antud projektil suhteliselt korralik: koostatud on teenuse kirjeldus,

    kirjeldatud on meeskonnaliikmete tööjaotus ja lisatud on ka kasutusjuhend. Viimase kohta võib küll öelda, et testija geeniga retsenseerijal ainult seda juhendit järgides teenust käivitada ei õnnestunud.

    Kood

    Eelpool mainitud kasutaja tegevuste logimisel loetletakse kasutaja poolt välja kutsutud meetodite arvu. Seejuures iga meetodi väljakutsel lisatakse andmebaasi vastavasse tabelisse rida kasutaja ja kasutatud meetodi kohta. Mis jääb koodi põhjal mõistmatuks on asjaolu, et leidub meetodeid, mille kasutamist teenuse poolel kasutaja rolli põhjal ei piirata (näiteks GetIncomeStatementWithDates), seega väljakutse võib teha ka free-user. Samas tulemust talle küll ei tagastata, küll aga logitakse meetodi väljakutse. Enamgi veel: kuigi väidetavalt on tasuta kasutaja päringud piiratud, siis päringute arvu kontrollitakse vaid kolme päringu korral ja limiidi ületamisel tõstetakse ülesse exception teatega päringute mahu ületamise kohta.

    Kui rääkida sellest, et administraatori õigustega saab teha kõiki päringuid, siis näiteks meetodi GetCashFlowStatementWithDates korral tagastatakse andmed vaid tasuta kasutajale. Selle probleemi lahendamiseks piisaks annotatsioonide kasutamisest meetoditel. Viimane lähenemine eeldab ka olemasoleva rollide halduse reaalset kasutamist. Hetkel on küll olemas Role Provider kuid kasutatakse enda kirjutatud loendi väärtusi. Millest selline lähenemine tingitud on jääb mingis mõttes arusaamatuks. Kokkuvõttes võiks öelda, et päringute piiramine kasutaja tüübi põhjal on realiseeritud pisut kaootiliselt.

    Huvitaval kombel ei ole hetkel implementeeritud uue kasutaja registreerimiseks vajalikku funktsionaalsust. Rakenduse kasutatavuse seisukohalt on see üsna tõsine puudus.

    Kasutajate tuvastamisel luuakse staatiline list ja selle andmed sisaldavad iga kasutaja kohta “käsitsi” genereeritud sessiooni id-d. Viimane variant töötab projekti näitel hästi, kuid WCF vaikeväärtused peaksid seda funktsionaalsust ka ise toetama. Nimelt peaks WCF teenuse vaikimisi “InstanceContextMode” olema wsHttpBinding korral “Per Session” ja sessiooni id saaks küsida teenuselt. Teine küsitavus on listi kasutamine andmete hoidmisel. Kuna sisse logitud kasutajaid otsitakse sellest üsna sageli võiks kaaluda näiteks HashMap või mõne muu struktuuri kasutamist ja tõsta võtme (sessiooni id) järgi otsimise kiirust.

    Koodis on kirjeldatud mõningad kasutatud mudelid, mis on eraldatud eraldi kausta ja seega kergesti leitavad. Mõnevõrra segadusttekitav on asjaolu, et juhul, kui tegemist on andmebaasi kandele vastava olemiga, siis klassi nimi baasis sisalduva tabeli nimega ei kattu. Veelgi enam, juhul, kui kasutatakse nimetusi nagu “FinDataEntity” võiks lisada ka väikse kirjelduse selle sisu ja kasutamise kohta. Lõppkokkuvõttes annab küll kõik ka koodi ja google abil selgeks saada, aga ajakulu on üsna suur.

    Kui rääkida “data access” kihist, siis see puudub. Kogu suhtlus andmebaasiga on kirjutatud teenuse poolt pakutavatesse meetoditesse. Viimane lähenemine raskendab oluliselt koodi lugemist ja ka muutmist, kui see peaks mingil hetkel vajalikuks osutuma.

    Seejuures on eksitud ka selle vastu, et üks meetod teeb parajasti ühte asja. Kui vaadata näiteks meetodeid Login ja CheckUser, siis oleks võinud suure osa sisust refaktoreerida eraldi meetoditeks ja koodi taaskasutada. Hetkel on kaks korda järjest suurel hulgal sama koodi kirjutatud.

    Ääremärkusena võiks lisada veel selle, et üldiselt inglise keelse sisu korral võiks ka kommentaarid olla inglise keelsed.

    Kokkuvõte

    Koodi kvaliteet ja arhitektuur on kohati korralikult läbimõtlemata. Teisalt on rakendus üsna korralikult dokumenteeritud ja idee poolest ka majanduslikult mõistlik. Ka rakenduse turvamine on korralikult realiseeritud.

    Rakenduste Retsensioonid

    Retsensioon meeskonna "X-Ladu" Klientrakenduse ülesande kohta

    Rakendus

    Tegemist on WPF klientrakendusega, mis kasutab suurt osa teenuse pakutavatest meetoditest. Tavakasutaja vaates saab toodet lisada ning otsida, samuti saab muuta kasutaja andmeid. Administraatori vaates saab lisaks luua tootegruppe, hallata teisi kasutajaid ning jälgida logi (inimeste tegevust).

    Esialgne käivitamine oli mõnevõrra probleemne, sest arendajate WIKI lehel oli kirjeldatud administraatori loomist puudulikult. Põhjuseks oli kasutaja parooli lisamine - see pidi tegelikult olema “krüpteeritud” kujul. Esimese administraatori oleks tegelikult võinud luua väga lihtsa SQL käsuga, mitte poleks pidanud kasutajat SQL Server Management’i käsitsi andmebaasi kallale suunama.

    Kood

    Rakenduses kasutati vaatemudeleid, seal oli kaks kausta: Mudelid ja Vaatemudelid, kusjuures niiöelda Vaatemudelite sees oli realiseeritud palju funktsionaalsust.

    Kasutajate parool tekitati/tuvastati leides MD5 räsi, muud turvalisuse haldust (sessioon, membership) rakenduses polnud.

    Kasutajate logi pidamine oli üks väga häid ideid ning see oli ka koodi mõttes normaalselt realiseeritud. Miinuseks oli see, et iga LogiVM klassi meetodi alguses kutsuti uuesti lae() meetod, mis lõi logide nimekirja iga kord uuesti.

    Erinevate nimekirjade tulpade järgi sorteerimise funktsionaalsus oli hea featuur.

    Koodistiil, nagu ka teenuses, ei olnud parim. Kasutati eestikeelseid nimesid nii meetodite kui muutujate jaoks - üldiselt ei ole see põhjendatud, kuid kooliprojekti jaoks piisavalt hea lahendus - võibolla aitas see meeskonda ühtviisi mõtlemisel. Kood oli dokumenteeritud piisavas koguses, enamus meetodite ja muutujate nimesid seletasid enda eesmärki üheselt.

    Kahtlased koodiosad

    • Staatiliste meetodite seas klass “Krüpteerimine” - eestikeelsed täpitähed võivad suuri probleeme tekitada.
    • Staatiliste meetodite klassi sees “AndmetegaSeotudMeetodid” pandi kasutaja.BlokeeritudKuni = DateTime.Now.AddYears(-99); - järelikult muutuv kuupäev erinevate kasutajate jaoks; hiljem võrdlemise lihtsustamiseks oleks pidanud kasutama ühte väärtust, näiteks DateTime minimaalset väärtust.

    Puudused rakenduse kasutaja vaatevinklist

    Üldised värvid rakendusel polnud head - oleks võinud kasutada lihtsaid värvipalette. Lisaks näiteks nupu rollover olek tegi nupu tausta helesiniseks, samal ajal kui selle tekst oli valge.

    Paremal all olev “Sulge rakendus” nupp oleks võinud olla kõikidel vaadetel konstantne (praegu polnud seda kasutaja ja administraatori avavaadetes). Teine võimalus oleks olnud see nupp üldse ära jätta.

    Erinevates lahtrites olid lubatud enamus sümboleid, tegelikult peaks ka seda kontrollima (näiteks numbriväljadele ainult numbreid lubada).

    Puuduste nimekiri vaadete järgi

    • AdminGruppidelisamine

    Viimati vajutatud nupp jäi fookusesse ning võttis vastu Enter nupu vajutusi, kas see oli bug või hoopis feature?

    Kirjaviga: “Kustuta valtud grupp” > “Kustuta valitud grupp”.

    • AdminKasutajahaldus

    Nimekirjas oleks võinud olla näha ka kasutaja blokeeritust, sest selline funktsionaalsus oli selles vaates olemas.

    • AdminGruppidelisamine

    Gruppe sai küll lisada, kuid hiljem muuta ei saanud. Kui peaks tekkima vajadus tootegruppi muuta, siis peaks terve tootegrupi koos selles grupis olevate toodetega kustutama ning kõik uuesti tekitama. Selle oleks võinud realiseerida kasvõi nii, et nimekirjast mingi tootegrupi valikul kuvatakse paremal selle tootegrupi infot ning seda saaks siis üle-salvestada.

    • AvaekraanUser

    Nupud ja sisutekst oleksid võinud olla ühtlaste suur-väiketähtedega.

    • Parooli muutmine

    Nupud oleksid võinud olla alati samas järjekorras, näiteks Salvesta nupp oleks võinud olla konstantselt paremal, või konstantselt vasakul, mitte nagu siin.

    Registreerides oli minimaalne parooli pikkus 8 tähemärki, parooli muutes seda ei kontrollitud - võis mõlemad lahtrid isegi tühjaks jätta.

    • TooteLisamine

    Ilma tootegrupita ei tohiks sellesse vaatesse üldse ligi pääseda, sest lisamisel on tootegrupp nõutud.

    Tundub, et lisainfo väli oleks pidanud olema muutuv olenevalt antud tootegrupist. Tõenäoliselt seda arendajad soovisid, kuid realiseerida ei jõudnud.

    Kogus ja Hind väljadel olid lubatud tähed (oleks võinud väljadel vaid numbrisisestust lubada), kontroll tehti alles peale “Salvesta” nupu vajutamist ja ka siis ei antud konkreetset vihjet, mis valesti läks.

    Toote muutmisel “Parim enne” lahtris kuupäeva ei näidatud.

    Kokkuvõte

    Peab mainima, et rakendus oli täiesti kasutatav ning kokku ei jooksnud kordagi. Ärilistel eesmärkidel kasutamiseks peaks pöörama rohkem tähelepanu turvalisusele, tegelema puuduste nimekirjaga ning rakenduse koodi suurel määral optimeerima.

    Retsensioon meeskonna "AFFA II" Klientrakenduse ülesande kohta

    Kood

    Rakenduses kasutati vaatemudeleid, seal oli kaks kausta: Mudelid ja Vaatemudelid, kusjuures mõlema sees oli realiseeritud palju funktsionaalsust.

    Turvalisuse tagamiseks kasutati paroolide jaoks RSA krüpteerimist.

    Koodistiil ei olnud parim, meetodite ja muutujate nimed ei olnud kohati mõistetavad. Inglisekeelse koodi kõrval kasutati eestikeelseid kommentaare. Enamus koodist oli dokumenteeritud.

    Rakendus kasutaja vaatevinklist

    Grupp AFFA II on teinud rakenduse, mis näitab erinevate ettevõtete finantsandmeid. Rakenduse kasutamiseks on vaja sisse logida. On olemas kolme tüüpi kasutajaid. Esimene kasutajagrupp on admin kasutajad, ehk siis kasutaja, kes haldab lehte, saab lisada kasutajaid, saab pärida kõiki andmeid ning samas ka kirjutada andmeid juurde. Teine kasutajagrupp, ehk Pro kasutaja saab pärida piiramatus mahus kõiki andmeid. Kolmas kasutajagrupp ehk Free kasutaja saab pärida ka andmeid, kuid tal on andmete hulk ja päringute arv piiratud. Kui kasutaja on sisse loginud, siis saab ta alustada andmete otsimisega. Otsinguid saab teostada kahte moodi- ettevõtte nime järgi ning aktsiasümboli järgi. Selle osa juures on selgelt näha, mille poolest erinevad kasutajagrupid ja nende õigused. Kui Free kasutajal on otsimine ja parameetrid piiratud, siis Pro kasutaja saab valida lisaks ka selle, mis perioodi andmeid kuvatakse. Esialgu tundus rakenduse kasutamine raske, kuid abiks oli grupi koostatud kasutusjuhend. Kui klient on leidnud endale sobiva ettevõtte või aktsiasümboli, siis saab ta andmed alla laadida vajutades "Load data" nuppu. Kui andmed on AFFA klienti laetud, peab kasutaja WCF akna sulgema ja seejärel kasutama klientrakendust ettevõtte väärtuse hinnangute arvutamise kohta. Edasiseks tegevuseks on vaja sisendiks anda finantsandmed, mis laetakse kas siis kasutaja poolt või otse internetist. Selle koha peal oleks võinud kasutada teistsugust lahendust, sest andmed peavad olema XML formaadis. Rakenduses oleks võinud kasutada sisendiks näiteks tabelkujul andmeid. Siinkohal on hea, et grupp on enda töös välja toonud ka soovituse selleks, et tulemused oleksid täpsemad. Üheks sisendi võimaluseks on laadida andmed otse veebilehelt Ycharts.com, kus saab tarkvara andmeid Exceli formaadis, mis töödeldakse XML formaati ja seejärel loetakse tarkvara poolt sisse. Ycharts.com miinuseks on see, et lehe kasutamine eeldab tasulise konto olemasolu. Edasi teostab tarkvara 4 tüüpi arvutusi. Kuna arvutuste põhjal saab näha ka tuleviku finantsprognoose ning leitakse ettevõtte väärtuse hinnang ja võrreldakse seda hetkelise turuhinnaga, siis on kasutajatel väga hea ülevaade firmade hetkeseisust ja ettekujutus nende tulevikunäitajatest. Kuna rakenduse abil antakse kliendile ka investeerimissoovitus siis on kasutajal hea võrrelda erinevaid investeerimisvõimalusi. Seega rakenduse kasutajatel, kes saavad kasulikku infot firma finantsseisu kohta, on väiksem võimalus teha valesid otsuseid.

    Rakenduses saab kasutaja andmete vaatamiseks valida menüüst Input data, Quaterly data, Forecast ja Charts vahel. Input data juures saab kasutaja näha andmeid, mille põhjal tehakse tuleviku tarbeks prognoos. Valides Quaterly data, kuvatakse kasutajale andmed kvartalite kaupa ning arvutatakse välja ka muutused. Nende admete põhjal saab kasutaja ülevaate firma näitajatest kvartalites. Edasi on võimalik kasutajal näha tuleviku prognoosi, kus on siis välja toodud 5 aasta tulevikuprognoos. Kuna paljude investorite jaoks on väga oluline, et investeering saaks õigesse kohta tehtud,siis on rakendus firma seisu pildi saamiseks väga hea. Loomulikult ei saa rakendusest terviklikku pilti. Seega ei pruugi prognoos olla alati õige ja investeering võib minna siiski valesse kohta. Rakenduse juures on väga suur pluss see, et kasutaja saab andmeid näha ka graafilisel kujul. Graafikud on kasutaja eelistustest lähtuvalt kohandatavad. See annab kasutajale parema ülevaate mingi teatud andmevoo kohta.

    Kokkuvõte

    Grupp oli oma töös ära kirjeldanud rakenduse funktsioonid ja töötamispõhimõtted ning õpetus oli kergesti arusaadav, rakenduse kasutamine ei olnud väga raske. Rakenduse ülesehitus on korralik. Ilme on rakendusel lihtne ning kergesti arusaadav. Kõik funktsioonid on välja toodud ja kergesti leitavad. Üheks suureks miinuseks rakenduse juures on aga see, et andmete laadimine käib XML faili näol või läbi tasulise internetisaidi.

    Nagu ka AFFA II aruandes selgus, siis tegemist on varemvalminud rakenduse täiendusega. Mahult on antud projekt (eriti koodi mõttes) suur.

    Log

    07.03.2013 - sai valmis esimene osa kodusest tööst (XML)

    09.03.2013 - kandsime esimese osa (XML) WIKI keskkonda

    29.03.2013 - kandsime XML retsensioonid WIKI keskkonda

    25.05.2013 - kandsime teenuse kirjelduse WIKI keskkonda

    26.05.2013 - kandsime rakenduse kirjelduse WIKI keskkonda

    04.06.2013 - kandsime teenuste ja klientrakenduste retsensioonid WIKI keskkonda (X-Ladu ja AFFA II)