Difference between revisions of "Meeskond: Redundant Rappers"

From ICO wiki
(Idee)
(Retsensioonid)
 
(33 intermediate revisions by 3 users not shown)
Line 9: Line 9:
  
 
== Veebiteenuse analüüs ==
 
== Veebiteenuse analüüs ==
 +
 +
===Kirjeldus===
 +
Veebiteenus “REDRAP” hoiab informatsiooni muusikute ja nende loomingu kohta, kusjuures teenuse kasutajatel on võimalik üles laadida oma loomingut promomise eesmärgil ning siis saavad teised kasutajad seda loomingut alla laadida.
 +
Andmebaasis hoiame me olemasolevat, meie poolt lisatud muusikute ja nende loominguga seotud informatsiooni, ent ka kasutajate loominguga seotut, kus kasutajad on andmebaasis eristatud teistest muusikutest.
 +
 +
'''Külastaja'''
 +
 +
Külastajad saavad end veebirakenduse kasutajateks registreerida. Samuti saavad nad vaadata olemasolevaid artiste. Minna artistide “kodulehele” ning seal näha artisti toimetusi(artisti üles laetud looming)
 +
 +
'''Kasutaja'''
 +
 +
Kasutajal on olemas oma koduleht, mida tal on võimalik muuta. Juhul kui kasutaja peaks soovima promoda enda loomingut, siis saab ta üles laadida muusikat. Kasutaja saab koostada playliste.
 +
 +
'''Admin'''
 +
 +
Admin on meie saidi omanik, kellel on õigus määrata moderaatoreid, kustutada kasutajaid. Tema haldab tervet saiti.
 +
 +
'''Moderaator'''
 +
 +
Moderaator saab bannida, keelata kasutajaid, muuta kasutajate kodulehtede sisu vastavalt vajadusele. Moderaatorite ülesandeks on ka kuulata üles laetud helifaile, kas tegemist on ikka muusika või on üles laetud tühja noise’i.
 +
 +
===Must have features===
 +
 +
'''Külastaja'''
 +
*Saab vaadata olemasolevaid artiste ja nende loomingut
 +
*Saab end registreerida kasutajaks
 +
 +
'''Kasutaja'''
 +
*Saab sisse logida
 +
*Saab oma kasutajat kustutada
 +
*Saab vaadata olemasoleviad artiste ja nende loomingut
 +
*Saab koostada playliste
 +
*Saab anda hinnanguid loomingutele
 +
*Saab muuta oma andmeid(metadata?)
 +
*Saab jälgida oma lemmik artisti toiminguid(follow)
 +
*Saab üles laadida muusikafaile
 +
*Saab muuta enda “kodulehte” - üleslaetud lood, tema artistiinfo, tema following, bänner, ikoon
 +
*Edit* Näeb lugude juures olevaid laulusõnu
 +
 +
 +
'''Admin'''
 +
*Saab kustutada kõiki kasutajaid
 +
*Saab sisse logida
 +
*Saab kustutada/peita kasutajate üles laetud muusikafaile (plagiaadi puhul näiteks)
 +
*Saab määrata moderaatoreid
 +
 +
 +
'''Moderaator'''
 +
*Saab hallata kasutajaid
 +
*Saab sisse logida
 +
 +
===Nice to have features===
 +
*Kasutajad saavad lisada sõpru
 +
*Saab kuulata muusikat
 +
*Kasutajate all on ka kui on artist siis featured tab olemas
 +
 +
===ERD===
 +
 +
Selline võiks olla enamvähem veebirakenduse ERD mudel.
 +
 +
[[File:REDRAP_ERD.PNG]]
  
 
== XML / XSD / XSLT==
 
== XML / XSD / XSLT==
Line 761: Line 822:
  
 
</source>
 
</source>
 +
 +
== Lõpptoode ==
 +
 +
Veebiteenus koos klientrakendusega on kättesaadav [http://enos.itcollege.ee/~tkliss/VRII/ siit].
 +
 +
== Retsensioonid ==
 +
 +
=== XML retsensioon meeskonnale [https://wiki.itcollege.ee/index.php/Sense_Of_Direction Sense Of Direction] ===
 +
 +
XML fail valideerub. XML failil on kasutatud vähemalt 4 loogilist dimensiooni, täpselt nagu oli nõutud. XMLis kasutatud kirjutamise stiil on läbiv - läbiv Camel Case. Elemendi <\mark> ja <varustus> andmed võiksid olla samuti CDATA sees. Testandmeid on küll kasutatud, kuid meie nägemist mööda võiksid need olla rohkem varieeruvad - esmapilgul tundusid kõik andmed copy-paste´ga tehtud. XML on hästi struktureeritud - seda on hea lugeda. Tundub, et element <suund> on dubleeriv, seda saab kokku panna <lahteKoht> ja <sihtKoht> elemenditest. Atribuut "bussiLiik" elemendis <buss> jääb arusaamatuks, mida tähendab seal see "tavaline". Elemendis "valjumisPaev" ei tundu olevat põhjendatud atribuut "soidab", ehk võiks lihtsalt ära jätta true ja false väärtused. Tundub, et seda "soidab" atribuudi väärtust true või false on tahetud kasutada lihtsalt transformeerimise ajal kontrolliks. Kui on false ära jätta, siis ole vaja kontrolli teha, et kas sõidab. Samas kui tahta kontrollida, mis päevadel buss ei sõida, siis oleks seda atribuuti tõepoolest vast vaja.<br><br>
 +
 +
XSD on meie meeskonna arvates hästi tehtud ning valideerub. Skeemifail ja XML fail vastavad valideerides teineteisele.<br><br>
 +
 +
XSLT HTML on arusaadav, sest struktuur on hästi läbi mõeldud. Transformatsioon teskti failiks jääb arusaamatuks, miks valiti just see, milleks võib kunagi tekstifaili vaja minna.
 +
 +
=== Veebiteenuse retsensioon meeskonnale [https://wiki.itcollege.ee/index.php/Bob%27s_Burgers Bob's Burgers] ===
 +
 +
Antud projekti ideeks oli teha abivahend turniiride läbiviimiseks, mis tundub igati värske ning ühtlasi ka suure potentsiaaliga idee. Sarnaseid lahendusi on küll olemas, kuid kui seda edasi arendada, siis saaks sellest kindlasti väga konkurentsivõimelise lahenduse. Kindlasti tuleks kasuks ka selle eestikeelne versioon, mis oleks suunatud rohkem ka Eesti kasutajaskonnale.<br><br>
 +
 +
Veebiteenus on jagatud mõistlikult ning loogiliselt eraldi kihtideks, mille jaoks on tehtud 7 eraldi projekti: BL, DAL, Domain, Front, Identity, Interfaces ja WebApi.Server. Antud projektide liigituse puhul on selgelt aru saada, kus asub andmebaasimudel, veebiteenus ning klientrakendus. Kõik projektid on lõpptulemuse toimimiseks vajalikud projektid, see tähendab üleliigset projekti, mida veebiteenus üldse ei kasuta, ei ole. Võib juurde mainida, et Identity on ainuke projekt, mis ei ole oluline osa veebiteenuse funktsioneerimiseks, küll aga kasutatakse seda kasutaja autoriseerimiseks ning autentimiseks ja seetõttu on eraldi projekti loomine selleks mõistlik.<br><br>
 +
 +
Vajalik funktsionaalsus on olemas. Kood on samuti lihtsasti loetav, kuid mõned üksikud välja kommenteeritud koodijupid on alles jäänud ning kood on enamjaolt kommenteerimata ehk dokumenteerimata. Projekt on hästi ja mõistlikult struktureeritud ning on jälgitud tunnis ette näidatud praktikaid. Küll aga on väike ettepanek interface-ide osas: kui on eraldi projekt interface-ide jaoks, siis võiksid pigem service-i interface-id ka seal olla, mitte BL-i projektis. Kindlasti ei mõjuta see veebiteenuse toimimist, pigem on see soovitus, et projekti jaotus oleks veelgi lihtsam. WebApi.Server-i controller-ites on rakendatud kõiki CRUD meetodeid ning kõigi komponentide puhul need ka toimivad - andmebaasis tekivad, muutuvad ja kustuvad kirjed. Projekti domeeni osa on samuti kodeeritud detailselt ehk olemitel on juures annotatsioonid, mis takistavad veebiteenuse sisendis ebakorrektseid sisestusi (liialt pikki väärtusi, tundmatuid sümboleid). Samuti on hästi tehtud domeeni osas veateadete tagastamine.<br><br>
 +
 +
Antud projekti puhul on õnnestunud andmed tabelites omavahel siduda. See joonistub välja nii domeeni osas, kus on klassid sisaldavad teiste klasside ID-sid ning ühtlasi on ka annotatsioonis defineeritud ära  Key-d ja ForeignKey-d. Ühtlasi saab selle õnnestumises kinnitust ka andmebaasi vaadates, kus kirjed tekivad omavahel seotud tabelitesse, mitte ainult põhiandmetabelisse, kuhu andmed reaalselt sisestati.<br><br>
 +
 +
Kokkuvõttes on tegemist eeskujuliku lahendusega ning sellise realisatsiooniga, milles ei ole samas ka mingit liigset keerukust.
 +
 +
=== Klientrakenduse retsensioon meeskonnale [https://wiki.itcollege.ee/index.php/Bob%27s_Burgers Bob's Burgers] ===
 +
 +
Visuaalselt näeb klientrakendus väga kasutajasõbralik ning moodne välja. Rakenduses kuvatud alalehed on liigitatud loogiliselt ning arusaadavalt ehk enne peale vajutamist on juba aimdus, mida seal kuvatakse. Küll aga võiks esilehel olla midagi huvitavat - näiteks info parasjagu käimas olevatest ja peagi algavatest turniiridest või kutse liituda stiilis Come sign up now! Hea alternatiiv avalehe täitmiseks oleks ka klassikaline “Tere tulemast!” tervitus. Avalehele sattudes on selgesti aru saada, kus saab sisse logida ning registreerida. Logimise puhul on õnnestunud kasutaja valideerimine ehk avalehele sattudes ei saa täitmata väljadega sisse logida.<br><br>
 +
 +
Registreerimine - kasutaja saab end registreerida kasutades kasutajanimeks ja parooliks ühte märki. Sünnikuupäeva lisamisel on suureks plussiks kalendri komponent, mida on siin ja ka mitmel pool mujal kasutatud, see teeb kuupäeva valimise kasutajale mugavaks. Küll aga ei ole sünnikuupäevale pandud piirangut ning saab registreerida nii tänase kui ka tulevase kuupäevaga. Kasutajasõbalikkuse mõttes võiks registreerimisel kuidagi ära märkida, millised väljad on kohustuslikud. Kasutajanimeks saavad olla ainult numbrid või kirjavahemärgid - kas see on hea praktika? Turniiride leht - kuupäevad From ja To on otsingu vormil veidras formaadis ning ei ole arusaadav, kuidas oleks õige neid sisestada. Liialt kiirelt tegutsema hakkamisel, pärast rakenduse käivitamist, tekib rakenduses viga, kus nupud "Add new team" ja "Add new tournament" jäävad ilmumata. Season võiks olla ka kuidagi loogiliselt kas lahti seletatud, või kuidagi vormindatud, et võtaks kuupäevast aasta ning siis vastavalt winter 2017 näiteks. Muidu otsingud töötavad väga hästi: kui otsida midagi konkreetset, siis selle ka leiad. Ühtlasi ka järjestamine töötab kõikidel lehtedel - saab järjestada tähestikulises järjekorras ning numbreid kasvavas ja kahanevas järjekorras.<br><br>
 +
 
 +
Klientrakenduses joonistus välja ka asjaolu, et registreeritud kasutajal on rohkem õigusi ning võimalusi kui registreerimata kasutajal. Registreeritud kasutaja saab lisada nii turniire kui ka meeskondi, millest registreerimata kasutaja ei saa teha kumbagi, küll aga saab anonüümne kasutaja kõiki andmeid vaadata ning kõiki otsinguid sooritada. Samuti on selle projekti puhul realiseeritud ka teenuse kasutusstatistika, mis kajastub klientrakenduses kasutajate punktide põhjal, mida nad on mängides saanud.<br><br>
 +
 
 +
Klientrakendus on loodud TypeScript programmeerimiskeeles ning kood on jaotatud loogiliselt ja samas ka sarnaselt sellega, kuidas on reaalselt välja kuvatud. Hetkel on klientrakendus struktureeritud pigem olemite kaupa. Näiteks on hetkel kaust “Team”, mille sees on “TeamController” ja “TeamService”. Pigem oleks oodanud veebiteenusega analoogset struktuuri, kus oleks kaust “Controllers”, mille sees on kõik kontrollerid, kaust “Services”, mille sees on kõik ”Service”-id ning ka eraldi kaust “View”, kus sees oleksid kõik vajaminevad vaated (hetkel on kaustas “Views” ainult menüü). Kui võõras programmeerija leiaks kujunduses mõne lihtsama stiili või trükivea, siis leiab ta suure tõenäosusega selle parandamiseks õige kooditüki kerge vaevaga üles. Ehk klientrakenduse koodi on antud projekti puhul igati kerge hoomata, mis on väga hea pluss.<br><br>
 +
 
 +
Kokkuvõtteks võib väita, et antud klientrakenduses on realiseeritud kõik vajalik ning sellele veel lisakski. Rakendus on ülesehituselt igati arusaadav ning kõigele lisaks ka mugav. Esinesid pigem üksikutel lahtritel (just kuupäevade puhul) mõned valideerimise vead.
  
 
== Log ==
 
== Log ==
Line 766: Line 865:
 
* 15.03.2017 - teine kokkusaamine - igalt meeskonna liikmelt esmane XML fail ning nendest kokkupandud põhiline xml skelett
 
* 15.03.2017 - teine kokkusaamine - igalt meeskonna liikmelt esmane XML fail ning nendest kokkupandud põhiline xml skelett
 
* 19.03.2017 - kolmas kokkusaamine - XML on andmetega täidetud iga meeskonna liikme poolt, stiili ja skeemifaili tegemine. Retsensiooni kirjutamine meeskonnale Sense Of Direction. XSD fail done.
 
* 19.03.2017 - kolmas kokkusaamine - XML on andmetega täidetud iga meeskonna liikme poolt, stiili ja skeemifaili tegemine. Retsensiooni kirjutamine meeskonnale Sense Of Direction. XSD fail done.
 +
* 18.05.2017 - neljas kokkusaamine - solution'i valmis tegemine, task'ide jagamine, mingi baas struktuuri loomine.
 +
* 07.06.2017 - viies kokkusaamine - ülevaade, mis sai tehtud, mida veel teha, mis kaitsmiseks valmis saada - refactoring

Latest revision as of 17:04, 15 June 2017

Meeskond

  • Taavi Kliss
  • Kertu Nurmberg
  • Anneli Asser
  • Mart-Erki Nõumees

Idee

XML ideeks on muusika kataloog. Sellest on ka plaan edasi arendada veebiteenus ning klientrakendus.

Veebiteenuse analüüs

Kirjeldus

Veebiteenus “REDRAP” hoiab informatsiooni muusikute ja nende loomingu kohta, kusjuures teenuse kasutajatel on võimalik üles laadida oma loomingut promomise eesmärgil ning siis saavad teised kasutajad seda loomingut alla laadida. Andmebaasis hoiame me olemasolevat, meie poolt lisatud muusikute ja nende loominguga seotud informatsiooni, ent ka kasutajate loominguga seotut, kus kasutajad on andmebaasis eristatud teistest muusikutest.

Külastaja

Külastajad saavad end veebirakenduse kasutajateks registreerida. Samuti saavad nad vaadata olemasolevaid artiste. Minna artistide “kodulehele” ning seal näha artisti toimetusi(artisti üles laetud looming)

Kasutaja

Kasutajal on olemas oma koduleht, mida tal on võimalik muuta. Juhul kui kasutaja peaks soovima promoda enda loomingut, siis saab ta üles laadida muusikat. Kasutaja saab koostada playliste.

Admin

Admin on meie saidi omanik, kellel on õigus määrata moderaatoreid, kustutada kasutajaid. Tema haldab tervet saiti.

Moderaator

Moderaator saab bannida, keelata kasutajaid, muuta kasutajate kodulehtede sisu vastavalt vajadusele. Moderaatorite ülesandeks on ka kuulata üles laetud helifaile, kas tegemist on ikka muusika või on üles laetud tühja noise’i.

Must have features

Külastaja

  • Saab vaadata olemasolevaid artiste ja nende loomingut
  • Saab end registreerida kasutajaks

Kasutaja

  • Saab sisse logida
  • Saab oma kasutajat kustutada
  • Saab vaadata olemasoleviad artiste ja nende loomingut
  • Saab koostada playliste
  • Saab anda hinnanguid loomingutele
  • Saab muuta oma andmeid(metadata?)
  • Saab jälgida oma lemmik artisti toiminguid(follow)
  • Saab üles laadida muusikafaile
  • Saab muuta enda “kodulehte” - üleslaetud lood, tema artistiinfo, tema following, bänner, ikoon
  • Edit* Näeb lugude juures olevaid laulusõnu


Admin

  • Saab kustutada kõiki kasutajaid
  • Saab sisse logida
  • Saab kustutada/peita kasutajate üles laetud muusikafaile (plagiaadi puhul näiteks)
  • Saab määrata moderaatoreid


Moderaator

  • Saab hallata kasutajaid
  • Saab sisse logida

Nice to have features

  • Kasutajad saavad lisada sõpru
  • Saab kuulata muusikat
  • Kasutajate all on ka kui on artist siis featured tab olemas

ERD

Selline võiks olla enamvähem veebirakenduse ERD mudel.

REDRAP ERD.PNG

XML / XSD / XSLT

XML

  • atribuut date parandatud retsensiooni järgi 24.03.2017
  • genre poolikult parandatud 24.03.2017
<?xml version="1.0" encoding="UTF-8"?>
<music>
  <artists>
    <artist id="1">
      <name><![CDATA[Everfall]]></name>
      <country>Estonia</country>
      <genre id="1" name="Metal"></genre>
      <labels>
        <label id="1">
          <name><![CDATA[Swimming With Sharks Records]]></name>
          <country>United States of America</country>
        </label>
      </labels>
      <members>6</members>
      <startyear>2013</startyear>
      <endyear />
      <description><![CDATA[Estonian core-band called Everfall. It is actually hard to define our genre.
      It is core-ish, but since it is fresh, djenty, bit progressive and very bipolar, we named our genre djent'n'roll.]]></description>
      <records>
        <eps>
          <ep id="1" date="2014-05-05" type="studio">
            <title><![CDATA[Everfall EP]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a4238728268_5.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="1:49" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Intro]]></title>
              </track>
              <track id="2" tracknumber="2" duration="3:33" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Celestial Revenge]]></title>
              </track>
              <track id="3" tracknumber="3" duration="3:01" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Above the World]]></title>
              </track>
              <track id="4" tracknumber="4" duration="3:23" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Where I Come From, Lambs Eat Wolves]]></title>
              </track>
              <track id="5" tracknumber="5" duration="3:43" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Tides]]></title>
              </track>
            </tracklist>
          </ep>
        </eps>
        <singles>
          <single id="1" date="2016-05-27" type="studio">
            <title><![CDATA[Six Feet Under]]></title>
            <coverURI><![CDATA[https://images.cdbaby.name/e/v/everfall.jpg]]></coverURI>
            <tracklist>
              <track id="6" duration="5:05" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Six Feet Under]]></title>
              </track>
            </tracklist>
          </single>
          <single id="2" date="2016-12-30" type="studio">
            <title><![CDATA[Vanquish]]></title>
            <coverURI><![CDATA[https://i.ytimg.com/vi/tn9QtNHL4R4/maxresdefault.jpg]]></coverURI>
            <tracklist>
              <track id="7" duration="3:05" fileformat="WAV" bitrate="128" channels="16">
                <title><![CDATA[Vanquish]]></title>
              </track>
            </tracklist>
          </single>
        </singles>
      </records>
    </artist>
    <artist id="2">
      <name><![CDATA[The Myrrors]]></name>
      <country>USA</country>
      <genre id="1" name="psychedelic rock"></genre>
      <genre id="2" name="alternative rock"></genre>
      <genre id="3" name="folk rock"></genre>
      <labels>
        <label id="1">
          <name><![CDATA[Beyond Beyond is Beyond Records]]></name>
          <country>USA</country>
        </label>
        <label id="2">
          <name><![CDATA[Strange Design Records]]></name>
          <country>USA</country>
        </label>
        <label id="3">
          <name><![CDATA[Fuzz Club Records]]></name>
          <country>USA</country>
        </label>
      </labels>
      <members>5</members>
      <startyear>2008</startyear>
      <endyear />
      <description><![CDATA[The Myrrors are an experimental psychedelic rock band from Arizona, formed in early 2007.
      Originally consisting of Nik Rayne on vocals and guitar, Claira Safi on bass, and Grant Beyschau on drums]]></description>
      <records>
        <albums>
          <album id="1" date="2008-08-01" type="studio">
            <title><![CDATA[Burning Circles in the Sky]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a3815315623_10.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="3:51" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[The Mind's Eye]]></title>
              </track>
              <track id="2" tracknumber="2" duration="3:07" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Plateau Skull]]></title>
              </track>
              <track id="3" tracknumber="3" duration="4:42" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Burning Circles In the Sky]]></title>
              </track>
              <track id="4" tracknumber="4" duration="7:26" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Warpainting]]></title>
              </track>
              <track id="5" tracknumber="5" duration="16:31" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Mother of All Living]]></title>
              </track>
            </tracklist>
          </album>
          <album id="2" date="2015-03-24" type="studio">
            <title><![CDATA[Arena Negra]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1913997164_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="11:55" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Arena Negra]]></title>
              </track>
              <track id="2" tracknumber="2" duration="04:05" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Juanito Laguna Duerme]]></title>
              </track>
              <track id="3" tracknumber="3" duration="4:37" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Dome House Music]]></title>
              </track>
              <track id="4" tracknumber="4" duration="20:41" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[The Forward Path]]></title>
              </track>
            </tracklist>
          </album>
          <album id="3" date="2016-05-27" type="studio">
            <title><![CDATA[Entranced Earth]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a2953659820_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="1:41" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Mountain Mourning]]></title>
              </track>
              <track id="2" tracknumber="2" duration="4:44" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Liberty Is In The Streets]]></title>
              </track>
              <track id="3" tracknumber="3" duration="3:42" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[No Clear Light]]></title>
              </track>
              <track id="4" tracknumber="4" duration="8:51" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Entranced Earth (for Sigmund Kvaløy)]]></title>
              </track>
              <track id="5" tracknumber="5" duration="3:04" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Tallos]]></title>
              </track>
              <track id="6" tracknumber="6" duration="11:58" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Invitation Mantra]]></title>
              </track>
              <track id="7" tracknumber="7" duration="5:40" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Surem Dervish]]></title>
              </track>
            </tracklist>
          </album>
          <album id="4" date="2017-02-01" type="studio">
            <title><![CDATA[Ljudkamrater]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1986610802_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="10:13" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[I E]]></title>
              </track>
              <track id="2" tracknumber="2" duration="4:07" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Yttre Hybriderna]]></title>
              </track>
              <track id="3" tracknumber="3" duration="4:53" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[CVega's Bodega]]></title>
              </track>
              <track id="4" tracknumber="4" duration="6:28" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Khalivera]]></title>
              </track>
              <track id="5" tracknumber="5" duration="13:25" fileformat="mp3" bitrate="320" channels="2">
                <title><![CDATA[Night Flower Codex]]></title>
              </track>
            </tracklist>
          </album>
        </albums>
        <eps>
          <ep id="1" date="2013-08-24" type="studio">
            <title><![CDATA[Solar Collector]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1925968529_10.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="A1" duration="07:00" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Solar Collector]]></title>
              </track>
              <track id="2" tracknumber="A2" duration="7:55" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Ascensión]]></title>
              </track>
              <track id="3" tracknumber="B1" duration="14:39" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Ascensión]]></title>
              </track>
            </tracklist>
          </ep>
          <ep id="2" date="2013-08-24" type="studio">
            <title />
            <coverURI><![CDATA[URI]]></coverURI>
            <tracklist>
              <track id="" tracknumber="" duration="" fileformat="" bitrate="" channels="">
                <title />
              </track>
            </tracklist>
          </ep>
          <ep id="3" date="2015-05-03" type="live">
            <title><![CDATA[Southwest Acoustic Session]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a3696141168_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="4:43" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[A La Cima De La Segunda Montaña]]></title>
              </track>
              <track id="2" tracknumber="2" duration="20:29" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[The Forward Path: Emergence/Distant Travellers/Permanent Revolution/Distant Travellers (Reprise)]]></title>
              </track>
            </tracklist>
          </ep>
        </eps>
        <singles>
          <single id="1" date="2016-04-29" type="studio">
            <title><![CDATA[Semillas Sembradas]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a0593292307_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" duration="5:52" fileformat="mp3" bitrate="128" channels="2">
                <title><![CDATA[Semillas Sembradas Pt 1]]></title>
              </track>
              <track id="2" duration="4:55" fileformat="mp3" bitrate="128" channels="2">
                <title><![CDATA[Semillas Sembradas Pt 2]]></title>
              </track>
            </tracklist>
          </single>
          <single id="2" date="2015-11-01" type="studio">
            <title><![CDATA[Comrades / Storm Mills]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1674406256_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" duration="4:26" fileformat="mp3" bitrate="128" channels="2">
                <title><![CDATA[Comrades]]></title>
              </track>
              <track id="2" duration="3:21" fileformat="mp3" bitrate="128" channels="2">
                <title><![CDATA[Storm Mills]]></title>
              </track>
            </tracklist>
          </single>
          <single id="3" date="2016-04-20" type="studio">
            <title><![CDATA[God Unknown Split]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1291361171_16.jpg]]></coverURI>
            <tracklist>
              <track id="1" duration="6:21" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Wood Smoke Corona]]></title>
              </track>
            </tracklist>
          </single>
          <single id="4" date="2015-07-25" type="studio">
            <title><![CDATA[Funeral Ark]]></title>
            <coverURI><![CDATA[https://f4.bcbits.com/img/a1578490649_10.jpg]]></coverURI>
            <tracklist>
              <track id="1" duration="7:02" fileformat="mp3" bitrate="256" channels="2">
                <title><![CDATA[Funeral Ark]]></title>
              </track>
            </tracklist>
          </single>
        </singles>
      </records>
    </artist>
    <artist id="3">
      <name><![CDATA[DubFX]]></name>
      <country>Australia</country>
      <genres>
        <genre id="101">
          <name><![CDATA[beatboxing]]></name>
        </genre>
        <genre id="102">
          <name><![CDATA[dub]]></name>
        </genre>
        <genre id="103">
          <name><![CDATA[reggae]]></name>
        </genre>
        <genre id="104">
          <name><![CDATA[hip hop music]]></name>
        </genre>
        <genre id="105">
          <name><![CDATA[dubstep]]></name>
        </genre>
        <genre id="106">
          <name><![CDATA[drum and bass]]></name>
        </genre>
      </genres>
      <labels>
        <label id="201">
          <name><![CDATA[Convoyun.ltd]]></name>
          <country />
        </label>
      </labels>
      <members>1</members>
      <startyear>2005</startyear>
      <endyear />
      <description><![CDATA[Dub FX is a worldwide street performer who uses loop &amp; effects pedals to create layers of sounds into music using only his voice.]]></description>
      <records>
        <albums>
          <album id="301" date="2016" type="studio">
            <title><![CDATA[Thinking Clear]]></title>
            <coverURI><![CDATA[https://cdn.shopify.com/s/files/1/0286/6082/products/Front_Cover_Thinking_Clear_1024x1024.jpg?v=1472135940]]></coverURI>
            <tracklist>
              <track id="401" tracknumber="1" duration="5:49" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Birds and the Bees]]></title>
              </track>
              <track id="402" tracknumber="2" duration="4:59" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Road to Babylon]]></title>
              </track>
              <track id="403" tracknumber="3" duration="7:25" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Heat Wave]]></title>
              </track>
              <track id="404" tracknumber="4" duration="5:42" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Where I Belong]]></title>
              </track>
              <track id="405" tracknumber="5" duration="4:53" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Unwind]]></title>
              </track>
              <track id="406" tracknumber="6" duration="4:13" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[So Are You]]></title>
              </track>
              <track id="407" tracknumber="7" duration="9:07" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Beaming Light]]></title>
              </track>
              <track id="408" tracknumber="8" duration="5:11" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Fake Paradise]]></title>
              </track>
              <track id="409" tracknumber="9" duration="4:03" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Searching]]></title>
              </track>
              <track id="410" tracknumber="10" duration="6:56" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[Get Down]]></title>
              </track>
              <track id="411" tracknumber="11" duration="5:06" fileformat="mp3" bitrate="320" channels="">
                <title><![CDATA[That's the Game]]></title>
              </track>
            </tracklist>
          </album>
        </albums>
        <eps>
          <ep id="" date="" type="">
            <title />
            <coverURI><![CDATA[URI]]></coverURI>
            <tracklist>
              <track id="" tracknumber="" duration="" fileformat="" bitrate="" channels="">
                <title />
              </track>
            </tracklist>
          </ep>
        </eps>
        <singles>
          <single id="501" date="2009" type="Self-released">
            <title><![CDATA[Love Someone]]></title>
            <coverURI><![CDATA[https://img.discogs.com/F80ndtYmvILznMeFq2VvI--ESr8=/fit-in/300x300/filters:strip_icc():format(jpeg):mode_rgb():quality(40)/discogs-images/R-6870778-1428405863-4498.jpeg.jpg]]></coverURI>
            <tracklist>
              <track id="511" duration="7:19" fileformat="mp3" bitrate="" channels="">
                <title><![CDATA[Love Someone]]></title>
              </track>
            </tracklist>
          </single>
        </singles>
      </records>
    </artist>
    <artist id="4">
      <name><![CDATA[The Strokes]]></name>
      <country>USA</country>
      <genres>
        <genre id="1">
          <name><![CDATA[Indie rock]]></name>
        </genre>
        <genre id="2">
          <name><![CDATA[Garage rock revival]]></name>
        </genre>
        <genre id="3">
          <name><![CDATA[Post-punk revival]]></name>
        </genre>
      </genres>
      <labels>
        <label id="1">
          <name><![CDATA[Cult]]></name>
          <country>United States</country>
        </label>
        <label id="2">
          <name><![CDATA[RCA]]></name>
          <country>United States</country>
        </label>
        <label id="3">
          <name><![CDATA[Rough Trade]]></name>
          <country>England</country>
        </label>
      </labels>
      <members>5</members>
      <startyear>1998</startyear>
      <endyear />
      <description><![CDATA[The Strokes is an American rock band from New York City]]></description>
      <records>
        <albums>
          <album id="1" date="2013-03-26" type="">
            <title><![CDATA[Comedown Machine]]></title>
            <coverURI><![CDATA[https://upload.wikimedia.org/wikipedia/en/9/91/The_Strokes_-_Comedown_Machine.jpg]]></coverURI>
            <tracklist>
              <track id="1" tracknumber="1" duration="3:42" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Tap Out]]></title>
              </track>
              <track id="2" tracknumber="2" duration="3:01" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[All the Time]]></title>
              </track>
              <track id="3" tracknumber="3" duration="4:02" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[One Way Trigger]]></title>
              </track>
              <track id="4" tracknumber="4" duration="3:50" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Welcome to Japan]]></title>
              </track>
              <track id="5" tracknumber="5" duration="4:58" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[80's Comedown Machine]]></title>
              </track>
              <track id="6" tracknumber="6" duration="2:42" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[50/50]]></title>
              </track>
              <track id="7" tracknumber="7" duration="4:20" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Slow Animals]]></title>
              </track>
              <track id="8" tracknumber="8" duration="3:21" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Partners in Crime]]></title>
              </track>
              <track id="9" tracknumber="9" duration="3:36" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Chances]]></title>
              </track>
              <track id="10" tracknumber="10" duration="2:52" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Happy Ending]]></title>
              </track>
              <track id="11" tracknumber="11" duration="3:24" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Call It Fate, Call It Karma]]></title>
              </track>
            </tracklist>
          </album>
        </albums>
        <singles>
          <single id="1" date="2013-02-19" type="">
            <title><![CDATA[All the Time]]></title>
            <coverURI><![CDATA[https://upload.wikimedia.org/wikipedia/en/8/85/The_Strokes_All_The_Time_Cover.jpg]]></coverURI>
            <tracklist>
              <track id="1" duration="3:01" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[All The Time]]></title>
              </track>
              <track id="2" duration="3:45" fileformat="FLAC" bitrate="16" channels="2">
                <title><![CDATA[Fast Animals]]></title>
              </track>
            </tracklist>
          </single>
        </singles>
      </records>
    </artist>
  </artists>
</music>

XSD

  • (parandatud retsensiooni järgi ja natuke veel 24.03.2017)
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="music">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="artists">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="artist" maxOccurs="unbounded" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="name"/>
                    <xs:element type="xs:string" name="country"/>
                    <xs:element name="genres">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="genre" maxOccurs="unbounded" minOccurs="0">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element type="xs:string" name="name"/>
                              </xs:sequence>
                              <xs:attribute type="xs:int" name="id" use="optional"/>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                    <xs:element name="labels">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="label" maxOccurs="unbounded" minOccurs="0">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element type="xs:string" name="name"/>
                                <xs:element type="xs:string" name="country"/>
                              </xs:sequence>
                              <xs:attribute type="xs:int" name="id" use="optional"/>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                    <xs:element type="xs:byte" name="members"/>
                    <xs:element type="xs:short" name="startyear"/>
                    <xs:element type="xs:short" name="endyear"/>
                    <xs:element type="xs:string" name="description"/>
                    <xs:element name="records">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="albums" minOccurs="0">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="album" maxOccurs="unbounded" minOccurs="0">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element type="xs:string" name="title"/>
                                      <xs:element type="xs:string" name="coverURI"/>
                                      <xs:element name="tracklist">
                                        <xs:complexType>
                                          <xs:sequence>
                                            <xs:element name="track" maxOccurs="unbounded" minOccurs="0">
                                              <xs:complexType>
                                                <xs:sequence>
                                                  <xs:element type="xs:string" name="title"/>
                                                </xs:sequence>
                                                <xs:attribute type="xs:int" name="id" use="optional"/>
                                                <xs:attribute type="xs:short" name="tracknumber" use="optional"/>
                                                <xs:attribute type="xs:string" name="duration" use="optional"/>
                                                <xs:attribute type="xs:string" name="fileformat" use="optional"/>
                                                <xs:attribute type="xs:short" name="bitrate" use="optional"/>
                                                <xs:attribute type="xs:short" name="channels" use="optional"/>
                                              </xs:complexType>
                                            </xs:element>
                                          </xs:sequence>
                                        </xs:complexType>
                                      </xs:element>
                                    </xs:sequence>
                                    <xs:attribute type="xs:int" name="id" use="optional"/>
                                    <xs:attribute type="xs:date" name="date" use="optional"/>
                                    <xs:attribute type="xs:string" name="type" use="optional"/>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                          <xs:element name="eps" minOccurs="0">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="ep" maxOccurs="unbounded" minOccurs="0">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element type="xs:string" name="title"/>
                                      <xs:element type="xs:string" name="coverURI"/>
                                      <xs:element name="tracklist">
                                        <xs:complexType>
                                          <xs:sequence>
                                            <xs:element name="track" maxOccurs="unbounded" minOccurs="0">
                                              <xs:complexType>
                                                <xs:sequence>
                                                  <xs:element type="xs:string" name="title"/>
                                                </xs:sequence>
                                                <xs:attribute type="xs:int" name="id" use="optional"/>
                                                <xs:attribute type="xs:short" name="tracknumber" use="optional"/>
                                                <xs:attribute type="xs:string" name="duration" use="optional"/>
                                                <xs:attribute type="xs:string" name="fileformat" use="optional"/>
                                                <xs:attribute type="xs:short" name="bitrate" use="optional"/>
                                                <xs:attribute type="xs:short" name="channels" use="optional"/>
                                              </xs:complexType>
                                            </xs:element>
                                          </xs:sequence>
                                        </xs:complexType>
                                      </xs:element>
                                    </xs:sequence>
                                    <xs:attribute type="xs:int" name="id" use="optional"/>
                                    <xs:attribute type="xs:date" name="date" use="optional"/>
                                    <xs:attribute type="xs:string" name="type" use="optional"/>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                          <xs:element name="singles">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="single" maxOccurs="unbounded" minOccurs="0">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element type="xs:string" name="title"/>
                                      <xs:element type="xs:string" name="coverURI"/>
                                      <xs:element name="tracklist">
                                        <xs:complexType>
                                          <xs:sequence>
                                            <xs:element name="track" maxOccurs="unbounded" minOccurs="0">
                                              <xs:complexType>
                                                <xs:sequence>
                                                  <xs:element type="xs:string" name="title"/>
                                                </xs:sequence>
                                                <xs:attribute type="xs:int" name="id" use="optional"/>
                                                <xs:attribute type="xs:string" name="duration" use="optional"/>
                                                <xs:attribute type="xs:string" name="fileformat" use="optional"/>
                                                <xs:attribute type="xs:short" name="bitrate" use="optional"/>
                                                <xs:attribute type="xs:short" name="channels" use="optional"/>
                                              </xs:complexType>
                                            </xs:element>
                                          </xs:sequence>
                                        </xs:complexType>
                                      </xs:element>
                                    </xs:sequence>
                                    <xs:attribute type="xs:int" name="id" use="optional"/>
                                    <xs:attribute type="xs:date" name="date" use="optional"/>
                                    <xs:attribute type="xs:string" name="type" use="optional"/>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute type="xs:int" name="id" use="optional"/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT

XSLT (HTML)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="msxsl">
  <xsl:output method="html" indent="yes" />
  <xsl:template name="getYear">
    <xsl:param name="date" />
    <xsl:choose>
      <xsl:when test="contains($date, '/')">
        <xsl:call-template name="getYear">
          <xsl:with-param name="date" select="substring-after($date, '/')" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$date" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template match="/">
    <html>
      <body>
        <h1>Artist's records later than 2015</h1>
        <table border="1">
          <tr bgcolor="#FFFFFF">
            <th>Artist</th>
            <th>Album</th>
          </tr>
          <xsl:for-each select="/music/artists/artist">
            <tr>
              <td>
                <xsl:value-of select="name" />
              </td>
              <td>
                <xsl:for-each select="records/albums/album | records/eps/ep | records/singles/single">
                  <xsl:variable name="recordDate" select="@date" />
                  <xsl:variable name="year">
                    <xsl:call-template name="getYear">
                      <xsl:with-param name="date" select="$recordDate" />
                    </xsl:call-template>
                  </xsl:variable>
                  <xsl:choose>
                    <xsl:when test="$year &gt; 2015">
                      <p style="text-align:center;">
                        <xsl:value-of select="title" disable-output-escaping="yes" />
                        <br />
                        <img style="width:160px;height:120px">
                          <xsl:attribute name="src">
                            <xsl:value-of select="coverURI" disable-output-escaping="yes" />
                          </xsl:attribute>
                        </img>
                        <br />
                        <xsl:value-of select="$year" />
                      </p>
                    </xsl:when>
                    <xsl:otherwise />
                  </xsl:choose>
                </xsl:for-each>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

XSLT (XML)

<?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"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
      <artists>
        <xsl:for-each select="/music/artists/artist">
          <xsl:variable name="artistName" select="name"/>
              <xsl:for-each select="records/albums/album | records/eps/ep | records/singles/single">
                <xsl:variable name="recordcategory" select="name(.)"/>
                <xsl:variable name="recordType" select="@type"/>
                <xsl:choose>
                  <xsl:when test="$recordType = 'live'">
                    <artist name="{$artistName}">
                    <record category="{$recordcategory}">
                      <title>
                        <xsl:value-of select="title" disable-output-escaping="yes"/>
                      </title>
                      <date>
                        <xsl:value-of select="@date" disable-output-escaping="yes"/>
                      </date>
                      <tracks>
                        <xsl:for-each select="tracklist/track">
                          <track>
                            <xsl:value-of select="title" disable-output-escaping="yes"/>
                          </track>
                        </xsl:for-each>
                      </tracks>
                    </record>
                    </artist>
                  </xsl:when>
                  <xsl:otherwise></xsl:otherwise>
                </xsl:choose>
           </xsl:for-each>
        </xsl:for-each>
      </artists>
    </xsl:template>
</xsl:stylesheet>

Lõpptoode

Veebiteenus koos klientrakendusega on kättesaadav siit.

Retsensioonid

XML retsensioon meeskonnale Sense Of Direction

XML fail valideerub. XML failil on kasutatud vähemalt 4 loogilist dimensiooni, täpselt nagu oli nõutud. XMLis kasutatud kirjutamise stiil on läbiv - läbiv Camel Case. Elemendi <\mark> ja <varustus> andmed võiksid olla samuti CDATA sees. Testandmeid on küll kasutatud, kuid meie nägemist mööda võiksid need olla rohkem varieeruvad - esmapilgul tundusid kõik andmed copy-paste´ga tehtud. XML on hästi struktureeritud - seda on hea lugeda. Tundub, et element <suund> on dubleeriv, seda saab kokku panna <lahteKoht> ja <sihtKoht> elemenditest. Atribuut "bussiLiik" elemendis <buss> jääb arusaamatuks, mida tähendab seal see "tavaline". Elemendis "valjumisPaev" ei tundu olevat põhjendatud atribuut "soidab", ehk võiks lihtsalt ära jätta true ja false väärtused. Tundub, et seda "soidab" atribuudi väärtust true või false on tahetud kasutada lihtsalt transformeerimise ajal kontrolliks. Kui on false ära jätta, siis ole vaja kontrolli teha, et kas sõidab. Samas kui tahta kontrollida, mis päevadel buss ei sõida, siis oleks seda atribuuti tõepoolest vast vaja.

XSD on meie meeskonna arvates hästi tehtud ning valideerub. Skeemifail ja XML fail vastavad valideerides teineteisele.

XSLT HTML on arusaadav, sest struktuur on hästi läbi mõeldud. Transformatsioon teskti failiks jääb arusaamatuks, miks valiti just see, milleks võib kunagi tekstifaili vaja minna.

Veebiteenuse retsensioon meeskonnale Bob's Burgers

Antud projekti ideeks oli teha abivahend turniiride läbiviimiseks, mis tundub igati värske ning ühtlasi ka suure potentsiaaliga idee. Sarnaseid lahendusi on küll olemas, kuid kui seda edasi arendada, siis saaks sellest kindlasti väga konkurentsivõimelise lahenduse. Kindlasti tuleks kasuks ka selle eestikeelne versioon, mis oleks suunatud rohkem ka Eesti kasutajaskonnale.

Veebiteenus on jagatud mõistlikult ning loogiliselt eraldi kihtideks, mille jaoks on tehtud 7 eraldi projekti: BL, DAL, Domain, Front, Identity, Interfaces ja WebApi.Server. Antud projektide liigituse puhul on selgelt aru saada, kus asub andmebaasimudel, veebiteenus ning klientrakendus. Kõik projektid on lõpptulemuse toimimiseks vajalikud projektid, see tähendab üleliigset projekti, mida veebiteenus üldse ei kasuta, ei ole. Võib juurde mainida, et Identity on ainuke projekt, mis ei ole oluline osa veebiteenuse funktsioneerimiseks, küll aga kasutatakse seda kasutaja autoriseerimiseks ning autentimiseks ja seetõttu on eraldi projekti loomine selleks mõistlik.

Vajalik funktsionaalsus on olemas. Kood on samuti lihtsasti loetav, kuid mõned üksikud välja kommenteeritud koodijupid on alles jäänud ning kood on enamjaolt kommenteerimata ehk dokumenteerimata. Projekt on hästi ja mõistlikult struktureeritud ning on jälgitud tunnis ette näidatud praktikaid. Küll aga on väike ettepanek interface-ide osas: kui on eraldi projekt interface-ide jaoks, siis võiksid pigem service-i interface-id ka seal olla, mitte BL-i projektis. Kindlasti ei mõjuta see veebiteenuse toimimist, pigem on see soovitus, et projekti jaotus oleks veelgi lihtsam. WebApi.Server-i controller-ites on rakendatud kõiki CRUD meetodeid ning kõigi komponentide puhul need ka toimivad - andmebaasis tekivad, muutuvad ja kustuvad kirjed. Projekti domeeni osa on samuti kodeeritud detailselt ehk olemitel on juures annotatsioonid, mis takistavad veebiteenuse sisendis ebakorrektseid sisestusi (liialt pikki väärtusi, tundmatuid sümboleid). Samuti on hästi tehtud domeeni osas veateadete tagastamine.

Antud projekti puhul on õnnestunud andmed tabelites omavahel siduda. See joonistub välja nii domeeni osas, kus on klassid sisaldavad teiste klasside ID-sid ning ühtlasi on ka annotatsioonis defineeritud ära Key-d ja ForeignKey-d. Ühtlasi saab selle õnnestumises kinnitust ka andmebaasi vaadates, kus kirjed tekivad omavahel seotud tabelitesse, mitte ainult põhiandmetabelisse, kuhu andmed reaalselt sisestati.

Kokkuvõttes on tegemist eeskujuliku lahendusega ning sellise realisatsiooniga, milles ei ole samas ka mingit liigset keerukust.

Klientrakenduse retsensioon meeskonnale Bob's Burgers

Visuaalselt näeb klientrakendus väga kasutajasõbralik ning moodne välja. Rakenduses kuvatud alalehed on liigitatud loogiliselt ning arusaadavalt ehk enne peale vajutamist on juba aimdus, mida seal kuvatakse. Küll aga võiks esilehel olla midagi huvitavat - näiteks info parasjagu käimas olevatest ja peagi algavatest turniiridest või kutse liituda stiilis Come sign up now! Hea alternatiiv avalehe täitmiseks oleks ka klassikaline “Tere tulemast!” tervitus. Avalehele sattudes on selgesti aru saada, kus saab sisse logida ning registreerida. Logimise puhul on õnnestunud kasutaja valideerimine ehk avalehele sattudes ei saa täitmata väljadega sisse logida.

Registreerimine - kasutaja saab end registreerida kasutades kasutajanimeks ja parooliks ühte märki. Sünnikuupäeva lisamisel on suureks plussiks kalendri komponent, mida on siin ja ka mitmel pool mujal kasutatud, see teeb kuupäeva valimise kasutajale mugavaks. Küll aga ei ole sünnikuupäevale pandud piirangut ning saab registreerida nii tänase kui ka tulevase kuupäevaga. Kasutajasõbalikkuse mõttes võiks registreerimisel kuidagi ära märkida, millised väljad on kohustuslikud. Kasutajanimeks saavad olla ainult numbrid või kirjavahemärgid - kas see on hea praktika? Turniiride leht - kuupäevad From ja To on otsingu vormil veidras formaadis ning ei ole arusaadav, kuidas oleks õige neid sisestada. Liialt kiirelt tegutsema hakkamisel, pärast rakenduse käivitamist, tekib rakenduses viga, kus nupud "Add new team" ja "Add new tournament" jäävad ilmumata. Season võiks olla ka kuidagi loogiliselt kas lahti seletatud, või kuidagi vormindatud, et võtaks kuupäevast aasta ning siis vastavalt winter 2017 näiteks. Muidu otsingud töötavad väga hästi: kui otsida midagi konkreetset, siis selle ka leiad. Ühtlasi ka järjestamine töötab kõikidel lehtedel - saab järjestada tähestikulises järjekorras ning numbreid kasvavas ja kahanevas järjekorras.

  Klientrakenduses joonistus välja ka asjaolu, et registreeritud kasutajal on rohkem õigusi ning võimalusi kui registreerimata kasutajal. Registreeritud kasutaja saab lisada nii turniire kui ka meeskondi, millest registreerimata kasutaja ei saa teha kumbagi, küll aga saab anonüümne kasutaja kõiki andmeid vaadata ning kõiki otsinguid sooritada. Samuti on selle projekti puhul realiseeritud ka teenuse kasutusstatistika, mis kajastub klientrakenduses kasutajate punktide põhjal, mida nad on mängides saanud.

  Klientrakendus on loodud TypeScript programmeerimiskeeles ning kood on jaotatud loogiliselt ja samas ka sarnaselt sellega, kuidas on reaalselt välja kuvatud. Hetkel on klientrakendus struktureeritud pigem olemite kaupa. Näiteks on hetkel kaust “Team”, mille sees on “TeamController” ja “TeamService”. Pigem oleks oodanud veebiteenusega analoogset struktuuri, kus oleks kaust “Controllers”, mille sees on kõik kontrollerid, kaust “Services”, mille sees on kõik ”Service”-id ning ka eraldi kaust “View”, kus sees oleksid kõik vajaminevad vaated (hetkel on kaustas “Views” ainult menüü). Kui võõras programmeerija leiaks kujunduses mõne lihtsama stiili või trükivea, siis leiab ta suure tõenäosusega selle parandamiseks õige kooditüki kerge vaevaga üles. Ehk klientrakenduse koodi on antud projekti puhul igati kerge hoomata, mis on väga hea pluss.

  Kokkuvõtteks võib väita, et antud klientrakenduses on realiseeritud kõik vajalik ning sellele veel lisakski. Rakendus on ülesehituselt igati arusaadav ning kõigele lisaks ka mugav. Esinesid pigem üksikutel lahtritel (just kuupäevade puhul) mõned valideerimise vead.

Log

  • 08.03.2017 - esimene kokkusaamine - teema valik, meeskonna nime valik, xml stiili valik...
  • 15.03.2017 - teine kokkusaamine - igalt meeskonna liikmelt esmane XML fail ning nendest kokkupandud põhiline xml skelett
  • 19.03.2017 - kolmas kokkusaamine - XML on andmetega täidetud iga meeskonna liikme poolt, stiili ja skeemifaili tegemine. Retsensiooni kirjutamine meeskonnale Sense Of Direction. XSD fail done.
  • 18.05.2017 - neljas kokkusaamine - solution'i valmis tegemine, task'ide jagamine, mingi baas struktuuri loomine.
  • 07.06.2017 - viies kokkusaamine - ülevaade, mis sai tehtud, mida veel teha, mis kaitsmiseks valmis saada - refactoring