Meeskond "Harold": Difference between revisions

From ICO wiki
Jump to navigationJump to search
No edit summary
 
(48 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Võrgurakendused II: hajussüsteemide ehitamine]]
[[Category:Võrgurakendused II: hajussüsteemide ehitamine]]
{| style="width:100%;height: 40px; background-color:#f2dede;border: 1px solid #EED3D7;color:#B94A48;padding:10px;font-size:16px;font-weight:bold-webkit-border-radius: 8px;-moz-border-radius: 8px;border-radius: 8px;"
{| style="width:100%;height: 40px; background-color:#dff0d8;border: 1px solid ##468847;color:#468847;padding:10px;font-size:16px;font-weight:bold-webkit-border-radius: 8px;-moz-border-radius: 8px;border-radius: 8px;"
|- style="text-align: center"
|- style="text-align: center"
| Paistab, et tegu on üheliikmelise meeskonnaga.
| Ära kaitsesime. Maksimumpunktidele. Aitähh!!
|-
|-
|}
|}


Tegemist on IT Kolledži aine raames eksamieeldust taotleva projektimeeskonna töö dokumentatsiooniga.


{| class="infobox" style="width: 30em; padding-left: 2em; float: right; font-size: 95%;"
{| class="infobox" style="width: 30em; padding-left: 2em; float: right; font-size: 95%;"
|-
|-
|colspan="2" style="background: #D1D695; text-align:center;" | '''Meeskond ''"Harold"'''''
|colspan="2" style="background: #1A151A;color:#D5E8BD; text-align:center;" | '''Meeskond ''"Harold"'''''
|-
|-
|- style="vertical-align: top;"
|- style="vertical-align: top;"
Line 23: Line 24:
|- style="vertical-align: top;"
|- style="vertical-align: top;"
| '''Liikmed:'''
| '''Liikmed:'''
| [[User:Anroots]]
| [[User:Anroots]]<br />[[User:Mparast]]
|- style="vertical-align: top;"
|- style="vertical-align: top;"
| '''Juhendajad:'''
| '''Juhendajad:'''
Line 31: Line 32:
| 2011/2012 kevad
| 2011/2012 kevad
|-
|-
|colspan="2" style="background: #D1D695; text-align:center;" | '''Kood (GitHub)'''
|colspan="2" style="background:#1A151A;color:#D5E8BD; text-align:center;" | '''Lingid'''
|-
|-
|- style="vertical-align: top;"
| '''Valify:'''
| https://github.com/anroots/Valify
|-style="vertical-align:top;"
|-style="vertical-align:top;"
| '''Challengo:'''
|https://github.com/anroots/Challengo
|-
|colspan="2" style="background: #D1D695; text-align:center;" | '''Live demo'''
|-
|-
|- style="vertical-align: top;"
|API Demo
| '''Valify:'''
|[http://api.sqroot.eu http://api.sqroot.eu] ''(offline)''
| http://v.sqroot.eu
|}
|}


= Projekt =
= Projekt =


Projekti esimene ja viimane osa käsitlevad sama teemat, veebiteenuse ülesande raames realiseeritakse eraldiseisev lahendus.
Projekti esimesed kaks osa keskenduvad veebiteenuse "Challengo" taasloomisele. Projekti esimene osa valmistab ette peamis(t)e päringu(te) XML vastuse struktuuri, projekti teine osa (veebiteenuse loomine) ehitab vastava API.


== Korraldus ==
== Korraldus ==
Line 57: Line 50:
Koodi haldab GitHub repositoorium, juurdepääsu saamiseks tuleb projektijuhile saata oma GitHub kasutajanimi (või ''pull request''). Tegemist vajavaid töid näeb GitHub lehel ''Issues'' vahekaardilt ning asjakohane dokumentatsioon (API) on GitHub wiki alamjaotises.
Koodi haldab GitHub repositoorium, juurdepääsu saamiseks tuleb projektijuhile saata oma GitHub kasutajanimi (või ''pull request''). Tegemist vajavaid töid näeb GitHub lehel ''Issues'' vahekaardilt ning asjakohane dokumentatsioon (API) on GitHub wiki alamjaotises.


Lähtekood on põhjalikult kommenteeritud, muud, eraldiseisvat dokumentatsiooni koodi kohta pole.
Lähtekood on põhjalikult kommenteeritud, muud, eraldiseisvat dokumentatsiooni koodi kohta on minimaalselt.


== XML Andmefailid ==
== XML Andmefailid ==
Line 63: Line 56:
''Tähtaeg 3. märts 2012''
''Tähtaeg 3. märts 2012''


XML andmefail kirjeldab veebiteenuse "[http://garage48.org/blogger/projects-on-garage48-tallinn-2011 Challengo]" andmeid. Andmed asuvad MYSQL andmebaasis, mille struktuur on kirjeldatud ERD mudeliga [[File:Harold_Challengo_MYSQL_ERD.png|200px|thumb|MYSQL ERD mudel]]. XML formaadis andmeid väljastab serveris asuv PHP API.
XML andmefail kirjeldab veebiteenuse "[http://garage48.org/blogger/projects-on-garage48-tallinn-2011 Challengo]" andmeid. Andmed asuvad MYSQL andmebaasis, mille struktuur on kirjeldatud ERD mudeliga [[File:Harold_Challengo_MYSQL_ERD.png|200px|thumb|MYSQL ERD mudel]]. XML formaadis andmeid väljastab serveris asuv PHP API. Järgnevalt toodud XML näited ei pruugi projekti esimese osa nõudmiste tõttu olla vastavuses teise osana valmiva veebiteenuse tegeliku väljundiga.


=== Päringud (''aka Feature set'') ===
Faile saab vaadata ka võrgust: http://enos.itcollege.ee/~anroots/challengo/xml/. Soovitatav on seda teha just XSLT stiilifaili jaoks (http://enos.itcollege.ee/~anroots/challengo/xml/Response.xml).


Nimekiri erinevatest päringutüüpidest, mis tagastavad omapärase struktuuriga XML-i.
=== XML [[http://enos.itcollege.ee/~anroots/challengo/xml/Response.xml link]]===


* Väljakutsete nimekirja küsimine
Järgnevalt on toodud lõik kasutaja praeguste väljakutsete päringust. Kasutajal on parajasti kaks aktiivset väljakutset, igal väljakutsel on veidi meta-infot, mingi hulk ülesandeid (tasks) ning igal ülesandel on üks või mitu autasu (rewards).
** Kasutaja aktiivsed väljakutsed
** Kasutaja lõpetatud väljakutsed
** Alustamata väljakutsed
** Kõik väljakutsed
* Alamülesannete nimekirja küsimine (''mingi väljakutse kohta'')
** Lõpetatud alamülesannete nimekiri
** Lõpetamata alamülesannete nimekiri
** Kõik alamülesanded
* Kasutajate nimekirja küsimine
* Märkide nimekirja küsimine


==== Väljakutsete info päring ====
<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Response.xsl"?>
<!-- List of user's current challenges -->
<challenges>
  <!-- First challenge, started by the user -->
  <challenge id="4" tasks="6" progress="17%">
    <title>The Improgrupp Jaa!</title>
    <description>Inspired by a true story, the Improgrupp Jaa! contains tasks that challenge ones spontaniety and social courage.</description>
    <duration>1209600</duration>
    <points_required>18</points_required>
    <badge_id>2</badge_id>
   
    <!-- Each challenge has a number of tasks that have to be completed.-->
    <!-- No challenge can be completed before earned points from tasks (rewards) exceed the points_required field -->
    <tasks max_points="26">
      <task id="19">
        <title>Make a present to a homeless person</title>
        <description>If you can read this, you're probably among the luckier ones. Do something for the ones who can't.</description>
        <badge_id>2</badge_id>
       
        <!-- Each task yields rewards on completion. Rewards are "power" points of different categories.-->
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">2</reward>
        </rewards>
      </task>
      <task id="20" completed="true">
        <title>Compliment a stranger</title>
        <description>Make a sincere compliment to someone you don't know. We could do with more praise where it's due.</description>
        <badge_id>1</badge_id>
        <rewards>
          <reward power_id="2">4</reward>
        </rewards>
      </task>
      <task id="21">
        <title>Do volunteer work</title>
        <description>Offer yourself as a volunteer to an event or a cause.</description>
        <badge_id>4</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">4</reward>
          <reward power_id="3">1</reward>
        </rewards>
      </task>
      <task id="22">
        <title>Perform to a security camera</title>
        <description>Do a little dance to a security camera. It shouldn't be illegal...probably. Don't get in trouble!</description>
        <badge_id>2</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
        </rewards>
      </task>
      <task id="23">
        <title>Compliment someone for a job well done</title>
        <description>When was the last time you thanked the janitor?</description>
        <badge_id>1</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="3">1</reward>
        </rewards>
      </task>
      <task id="24">
        <title>Take a day off</title>
        <description>This is mostly for work-a-holics: rest for a while.</description>
        <badge_id>4</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">4</reward>
        </rewards>
      </task>
    </tasks>
  </challenge>
</challenges>
</source>


Väljakutsete kohta saab XML formaadis infot, tehes GET päringu '''BASE'''/api/v1/challenge/get[/'''ID'''] URI pihta. Kui ID on tühi, tagastatakse kõik read.
=== XSLT (stiilifail) [[http://enos.itcollege.ee/~anroots/challengo/xml/Response.xsl link]] ===


Näidis: Päring väljakutse #4 info saamiseks:
Toodud stiilifail muudab ülaltoodud XML vastuse inimesele kergemini loetavaks.


'''Request:'''
<pre>
GET http://challengo.me/api/v1/challenge/get/4 HTTP/1.1
</pre>
'''Response:'''
<source lang="xml">
<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<challenges>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <challenge id="4" tasks="6" max_points="18" progress="0%">
  <xsl:template match="/">
         <id>4</id>
    <html class="no-js" lang="en">
         <title>The Improgrupp Jaa!</title>
      <head>
         <description>Inspired by a true story, the Improgrupp Jaa! contains tasks that challenge ones spontaniety and social courage.</description>
        <meta charset="utf-8"/>
         <duration>1209600</duration>
         <meta name="author" content="Ando Roots" />
        <points_required>11</points_required>
         <title>Challengo Response</title>
        <badge_id>2</badge_id>
         <link rel="stylesheet" href="http://i.jaa.ee/assets/bootstrap-2.0/css/bootstrap.min.css" />
        <tasks>
        <link rel="stylesheet" href="http://i.jaa.ee/assets/bootstrap-2.0/css/bootstrap.min.responsive.css" />
            <task id="19">
      </head>
                 <id>19</id>
      <body>
                <title>Make a present to a homeless person</title>
 
                <description>If you can read this, you're probably among the luckier ones. Do something for the ones who can't.</description>
         <div class="container">
                 <power_id>1</power_id>
          <h1>Challengo API response</h1>
                 <badge_id>2</badge_id>
          <p class="help-block">
                <points>3</points>
            The following is a list of challenges reported by the XML API.
             </task>
          </p>
             <task id="20">
         
                 <id>20</id>
         
                <title>Compliment a stranger</title>
          <!-- Go over each challenge -->
                <description>Make a sincere compliment to someone you don't know. We could do with more praise where it's due.</description>
          <xsl:for-each select="challenges/challenge">
                 <power_id>3</power_id>
            <h2>
                <badge_id>1</badge_id>
             
                 <points>2</points>
              <!-- Challenge badge image and title -->
             </task>
              <img alt="Challenge badge" height="48" width="48">
             <task id="21">
                 <xsl:attribute name="src">
                <id>21</id>
                  http://enos.itcollege.ee/~anroots/challengo/badges/<xsl:value-of select="badge_id"/>.png</xsl:attribute>
                 <title>Do volunteer work</title>
              </img>
                <description>Offer yourself as a volunteer to an event or a cause.</description>
              <xsl:value-of select="title"/>
                <power_id>2</power_id>
 
                <badge_id>4</badge_id>
              <!-- Challenge progress, if applicable -->
                 <points>5</points>
              <xsl:if test="@progress">
            </task>
                 (<span>
            <task id="22">
                  <xsl:value-of select="@progress"/>
                <id>22</id>
                 </span>)
                <title>Perform to a security camera</title>
              </xsl:if>
                <description>Do a little dance to a security camera. It shouldn't be illegal...probably. Don't get in trouble!</description>
            </h2>
                <power_id>2</power_id>
           
                <badge_id>2</badge_id>
           
                <points>3</points>
            <p class="well">
            </task>
              <xsl:value-of select="description"/>
            <task id="23">
             </p>
                <id>23</id>
 
                <title>Compliment someone for a job well done</title>
            <!-- Table for some challenge meta-info -->
                <description>When was the last time you thanked the janitor?</description>
             <table class="table table-bordered span4">
                <power_id>2</power_id>
              <tbody>
                <badge_id>1</badge_id>
                 <tr>
                <points>4</points>
                  <th>
            </task>
                    Points required to complete:
            <task id="24">
                  </th>
                <id>24</id>
                  <td>
                <title>Take a day off</title>
                    <xsl:value-of select="points_required"/>
                <description>This is mostly for work-a-holics: rest for a while.</description>
                  </td>
                 <power_id>1</power_id>
                </tr>
                <badge_id>4</badge_id>
                 <tr>
                <points>1</points>
                  <th>
            </task>
                    Time left (hours):
        </tasks>
                  </th>
    </challenge>
                  <td>
                    <xsl:value-of select="round(duration div 1800)"/>
                  </td>
                 </tr>
              </tbody>
             </table>
             <div class="clearfix"></div>           
           
            <!-- List all challenge tasks -->
            <h3 style="margin-top:140px">Tasks (<xsl:value-of select="@tasks"/>)</h3>
            <table class="table table-bordered table-striped table-condensed">
              <thead>
                 <tr>
                  <th>ID</th>
                  <th>Title</th>
                  <th>Badge</th>
                  <th>Rewards</th>
                 </tr>
              </thead>
              <tbody>
                <xsl:for-each select="tasks/task">
                  <tr>
                    <!-- Color the row gray if task is completed -->
                    <xsl:if test="@completed">
                      <xsl:attribute name="class">
                        help-block
                      </xsl:attribute>
                    </xsl:if>
                   
                    <td>
                      <xsl:value-of select="@id"/>
                    </td>
                    <td>
                      <xsl:value-of select="title"/>
                      <p class="help-block">
                        <xsl:value-of select="description"/>
                      </p>
                    </td>
                    <td>
                      <img alt="Challenge badge" height="48" width="48">
                        <xsl:attribute name="src">http://enos.itcollege.ee/~anroots/challengo/badges/<xsl:value-of select="badge_id"/>.png</xsl:attribute>
                      </img>
                    </td>
                    <td>
                      <ul>
                        <xsl:for-each select="rewards/reward">
                          <li>
                            <xsl:if test="(@power_id)=1">
                              Compassion
                            </xsl:if>
                            <xsl:if test="(@power_id)=2">
                              Strength
                            </xsl:if>
                            <xsl:if test="(@power_id)=3">
                              Intelligence
                            </xsl:if>
                            <span>
                              <xsl:value-of select="."/>
                            </span>
                          </li>
                        </xsl:for-each>
                      </ul>
                    </td>
                  </tr>
                 </xsl:for-each>
              </tbody>
            </table>
            <!-- End of challenge task table -->
           
          </xsl:for-each>
          <!-- End of challenge -->
         
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
</source>
</source>


=== XSD skeemifail ===
=== XSD (skeemifail) [[http://enos.itcollege.ee/~anroots/challengo/xml/Response.xsd link]] ===
 
Skeemifail kirjeldab päringu vastuse XML struktuuri.


<source lang="xml">
<source lang="xml">
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="challenges">
   <xs:element name="challenges">
     <xs:complexType>
     <xs:complexType>
       <xs:sequence>
       <xs:sequence>
         <xs:element name="challenge">
         <xs:element maxOccurs="unbounded" name="challenge">
           <xs:complexType>
           <xs:complexType>
             <xs:sequence>
             <xs:sequence>
              <xs:element name="id" type="xs:unsignedByte" />
               <xs:element name="title" type="xs:string" />
               <xs:element name="title" type="xs:string" />
               <xs:element name="description" type="xs:string" />
               <xs:element name="description" type="xs:string" />
Line 178: Line 307:
                       <xs:complexType>
                       <xs:complexType>
                         <xs:sequence>
                         <xs:sequence>
                          <xs:element name="id" type="xs:unsignedByte" />
                           <xs:element name="title" type="xs:string" />
                           <xs:element name="title" type="xs:string" />
                           <xs:element name="description" type="xs:string" />
                           <xs:element name="description" type="xs:string" />
                          <xs:element name="power_id" type="xs:unsignedByte" />
                           <xs:element name="badge_id" type="xs:unsignedByte" />
                           <xs:element name="badge_id" type="xs:unsignedByte" />
                           <xs:element name="points" type="xs:unsignedByte" />
                           <xs:element name="rewards">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element maxOccurs="unbounded" name="reward">
                                  <xs:complexType>
                                    <xs:simpleContent>
                                      <xs:extension base="xs:unsignedByte">
                                        <xs:attribute name="power_id" type="xs:unsignedByte" use="required" />
                                      </xs:extension>
                                    </xs:simpleContent>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                         </xs:sequence>
                         </xs:sequence>
                         <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                         <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                         <xs:attribute name="completed" type="xs:boolean" use="required" />
                         <xs:attribute name="completed" type="xs:boolean" use="optional" />
                       </xs:complexType>
                       </xs:complexType>
                     </xs:element>
                     </xs:element>
                   </xs:sequence>
                   </xs:sequence>
                  <xs:attribute name="max_points" type="xs:unsignedByte" use="required" />
                 </xs:complexType>
                 </xs:complexType>
               </xs:element>
               </xs:element>
Line 195: Line 337:
             <xs:attribute name="id" type="xs:unsignedByte" use="required" />
             <xs:attribute name="id" type="xs:unsignedByte" use="required" />
             <xs:attribute name="tasks" type="xs:unsignedByte" use="required" />
             <xs:attribute name="tasks" type="xs:unsignedByte" use="required" />
            <xs:attribute name="max_points" type="xs:unsignedByte" use="required" />
             <xs:attribute name="progress" type="xs:string" use="optional" />
            <xs:attribute name="can_complete" type="xs:boolean" use="required" />
             <xs:attribute name="progress" type="xs:string" use="required" />
           </xs:complexType>
           </xs:complexType>
         </xs:element>
         </xs:element>
Line 206: Line 346:
</source>
</source>


== Veebiteenus "''Valify''" ==
== Veebiteenus ==
''Tähtaeg 14. aprill 2012''
''Tähtaeg 30. mai 2012''
 
[[File:challengo_req2.png|300px|thumb|Näidis HTTP API päringust]]
 
Veebiteenusena realiseeriti API, mis võimaldab klientide registreerimist, haldamist ning Challengo teenuse põhifunktsionaalsuse pakkumist HTTP päringute kaudu. API loomisel kasutati RESTful arhitektuuri. Täpsem dokumentatsioon asub API lehel: [http://api.sqroot.eu "API dokumentatsioon"] (tegemist on ajutise aadressiga, mis võetakse maha aine lõppemisel).
 
=== Kriteeriumid ===
 
Kõik õppejõu poolt esitatud kriteeriumid on täidetud. Erikokkuleppe alusel on projekti keeleks PHP.


N.B! Praegune Git repo (ja live demo) on kirjutatud PHP-s ning sisaldab minimaalset funktsionaalsust andmete kogumiseks. PHP rakendus kirjutati selleks, et võimalikult vara kümne lehekülje kohta statistikat koguma hakata, hiljem saab PHP poolt loodud andmebaasi importida.
Kriteeriumid:


=== Idee ===
* Teenuse pakkumist - API suudab vastata talle esitatud, valideeruvatele (vt. API dokumentatsiooni) päringutele
* Teenuse kasutajate tuvastamist ning haldamist - Kasutajatuvastus toimub nime/parooli alusel HTTP Basic Authentication protokollil, ideaalis üle HTTPS-i. Süsteemi sisemiselt on kasutajatel rollid, mida saab kasutada halduseks, näiteks LOGIN rolli eemaldamisel ei saa kasutaja enam sisse logida.
* Teenuse kasutajate ja kasutusstatistika üle arve pidamist kasutajate lõikes - Kõik API päringud käivad API tokeni alusel. Tokeni kasutaja päringud logitakse nii logifaili kui andmebaasi, neid on sealt võimalik pärida. Lisaks on igal tokenil päringulimiit (tunnis), selle ületamisel päringuid eiratakse. Tokeneid saab tühistada, mis tähendab, et klientrakenduse päringuid ei töödelda mingil juhul.


Tegemist on veebiteenusega, mis kogub ja väljastab infot veebilehtede lähtekoodi ajaloolise valideerimise kohta [http://www.w3.org/Consortium/mission W3C standardite] järgi. Teenusel on sisemine nimekiri (mida saab täiendada) veebilehtedest ning andmebaas, mida teatud ajavahemiku tagant automaatselt uuendatakse. Andmebaas sisaldab iga veebisaidi kohta ajaloolist infot. Infot annab [http://validator.w3.org/ W3C Validator] tööriist ning selleks on vastava veebilehe lähtekoodi vea (''error'') ja hoiatus (''warning'') numbrid.
=== Testimine ===


Teenusel on graafiline veebiliides ning kasutajapõhine API. Mõlemad liidesed võimaldavad sooritada samu toiminguid: infot pärida ning kontrollnimekirja hallata. Veebiliides suudab kuvada ka etteantud päringutingimustele vastavat graafikut. Näiteks saab küsida http://delfi.ee koodi valideerimisandmed ühe kuu kohta, et näha, kui usinad sealsed veebimeistrid vigade parandamises olid.
Veebiteenusel ei ole eraldi kasutajaliidest. Testimiseks on kaks varianti:


[[File:Harold Valify Screenshot v01.png|300px|thumb|Ekraanipilt rakendusest, ''proof-of-concept'' versioon]]
# Luua ise vastav kasutajaliides ehk klientrakendus
# Kasutada mõnd abitööriista HTTP päringute koostamiseks. Soovitus: [https://chrome.google.com/webstore/detail/aejoelaoggembcahagimdiliamlcdmfm "Chrome plugin"]


=== Toimimine ===
Autentimisandmed rakendusele saab luua dokumentatsiooni lehel oleva vormi kaudu (andmed saadetakse e-mailile). Kasutajakonto saab luua juba API päringute abil.


* Salvestatakse lehekülje URL
N.B. Juhul, kui uute API tokenite loomine ebaõnnestub (serveri mailiserver on veidi ebastabiilne), võib kasutada ka järgnevaid andmeid:
* Rakendus (serveris) küsib W3C validaator API-lt selle aadressi error ja warning numbrid
* Rakendus salvestab tulemused ajatempliga ning küsib perioodiliselt (1p) andmeid uuesti
* Rakendus näitab veebilehel graafikut vigade arvu trendiga
* Rakendusel on kasutajapõhine API domeenide lisamiseks ning andmete pärimiseks.


=== Feature set ===
Secret: fowhosurtothab
Token: fleraffahskuff


Tegevused, mida API ja/või veebiliidese kaudu teha peaks saama.
=== Kood ===


* Kasutaja autentimine
Lähtekoodi saab [http://api.sqroot.eu/anroots-challengo-a6da30942c8c.tar.gz siit] ''(removed)''. Kohtmasinasse paigaldamiseks tuleb alla laadida [http://kohanaframework.org Kohana] framework ning paigaldada application/bootstrap.php failis märgitud moodulid. Andmebaasi schema on database kaustas. Kood on testitud ainult Linux platvormil LAMP stack-iga.
** Kasutaja lisamine
** Login, sessiooniga, API token
** Kasutaja blokeerimine
* Kontrollnimekirja haldus
** Veebilehe lisamine kontrollnimekirja
** Veebilehe eemaldamine kontrollnimekirjast
** Veebilehe URL muutmine peale lisamist
**  Kontrollide ajutine peatamine (''suspend checking'')
* Automaatne kontroll fikseeritud ajavahemiku tagant
** Kontrollib veebilehte W3C validaator API kaudu
** Tulemused salvestatakse ajatempliga
* Kontrollide tulemuste kuvamine
** Graafikuna (Google Charts API, andmed JSON vastusena API-lt)
** Kontrolli tulemuste kuvamine tabelina mingi veebilehe kohta
** Tabeli filtreerimine
* API dokumentatsioon


== Klientrakendus ==
== Klientrakendus ==
Line 253: Line 385:
''Tähtaeg 5. mai 2012''
''Tähtaeg 5. mai 2012''


Klientrakendus on Windows Phone 7 klient Challengo teenusele, mis kasutab projekti esimeses osas koostatud XML andmestruktuuri.
[[File:5554-IceCream 024.png|300px|thumb|Ekraanipilt tulevaste etenduste nimekirjast]]
[[File:5554-IceCream 025.png|300px|thumb|Ekraanipilt etenduse detailvaatest]]
 
Klientrakendus on Android rakendus, mis kuvab teater NO99 etendusi ning võimaldab punktide alusel pileteid osta. Tegu on jQuery Mobile pordiga Android platvormile.
 
Rakendus suhtleb Play! raamistikus kirjutatud API-ga, mis asub kahjuks meeskonna localhostis, sest selle võrku panemiseks oli vaja VPS serverit. Seega ei suuda rakendus Teie arvutites sisselogimist teostada.
 
Rakendusel on neli peamist vaadet: sisselogimine, etenduste nimekiri, etenduse detailvaade ning konto info. Pileteid saab osta punktide alusel (punktid peavad eelneva mehanismiga juba kontol olema, konto on punkt.no99.ee-ga ühine). Kui pilet on ostetud, märgib rakendus vastava etenduse taustavärviga, teiskordselt piletit osta ei saa, kuid seda pole raske realiseerida.
 
Peale sisselogimist tõmmatakse serverist alla nimekiri etendustest ning hakatakse siis ükshaaval sellele nimekirjale pisipilte laadima. Allalaaditud pisipildid salvestatakse Android poolt antud vahemälukausta, neid teiskordselt ei laadita.
 
Kõik suhtlused serveris on asünkroonsed, seda kahel põhjusel: esiteks tapab Android rakenduse ära (ja kasutajal on ebamugav), kui päringu vastust kasutajaliidese ''thread''-ist oodata. Teiseks saab asünkroonset päringut mugavalt taustalt teha ning kasutaja saab oma asjadega edasi tegeleda.
 
Rakenduse kood asub [https://bitbucket.org/anroots/punkt99-android/src/f87687bbe41d BitBucketis] (develop branch).
 
'''Retsensendile'''


XML-i väljastab Challengo API, mis vajab veel kirjutamist. Challengo on realiseeritud PHP-s.
Kuna rakendust iseseisvalt testida ei saa, olen soovi korral valmis seda uuesti oma arvutist demoma.


=== Feature set ===
=== Feature list ===  


* Autentimine
* Autentimine
** Login
* Tulevaste etenduste nimekirja vaatamine
** Logout
* Etenduse detailide vaatamine (sh pilt)
* Nimekiri aktiivsetest väljakutsetest ja nende staatustest
* Allalaaditud piltide '''cache'''-mine
** Nimekiri väljakutse alamülesannetest ja nende staatustest
* Pileti ostmine etendusele punktide alusel
* Väljakutse märkimine lõpetatuks
* Konto info vaatamine
** Alamülesande märkimine lõpetatuks
* Uue väljakutse valimine nimekirjast
** Väljakutse detailide ja alamülesannete vaatamine
* Väljakutse "hülgamine" (''abandon'')
* Kasutaja statistika näitamine
** Praegune punktiseis
** Lõpetatud väljakutsed
*** Lõpetatud alamülesanded
** Teenitud märgid


= Meeskonna Liikmed =
= Meeskonna Liikmed =


* Ando Roots ''anroots@itcollege.ee''
* Ando Roots ''anroots@itcollege.ee''
* Mikk Pärast ''mparast@itcollege.ee''


== Liitumine ==
== Liitumine ==
Line 292: Line 431:


= Lisad =
= Lisad =
[http://jaa.ee Kes on Harold?]


== Challengo ==
== Challengo ==
Line 302: Line 443:
</pre>
</pre>


<youtube v="pPfHJD5F7sc" />
<youtube>pPfHJD5F7sc</youtube>
[http://www.youtube.com/watch?v=pPfHJD5F7sc Jelena tutvustab Challengo teenust]
[http://www.youtube.com/watch?v=pPfHJD5F7sc Jelena tutvustab Challengo teenust]
== Punkt99 ==
[http://garage48.org/blogger/projects-launched-at-garage48-tallinn-music-2012 Punkt99] valmis Garage48-l 2012 kevadel paljude hakkajate inimeste koostööl. Tegu on piletimüügirakendusega teater NO99-le.

Latest revision as of 14:04, 24 July 2015

Ära kaitsesime. Maksimumpunktidele. Aitähh!!

Tegemist on IT Kolledži aine raames eksamieeldust taotleva projektimeeskonna töö dokumentatsiooniga.

Meeskond "Harold"
Aine: Category:Võrgurakendused II: hajussüsteemide ehitamine
Juhend: Juhend
Tüüp: Projekt
Liikmed: User:Anroots
User:Mparast
Juhendajad: User:Mposka
User:Kraspel
Semester: 2011/2012 kevad
Lingid
API Demo http://api.sqroot.eu (offline)

Projekt

Projekti esimesed kaks osa keskenduvad veebiteenuse "Challengo" taasloomisele. Projekti esimene osa valmistab ette peamis(t)e päringu(te) XML vastuse struktuuri, projekti teine osa (veebiteenuse loomine) ehitab vastava API.

Korraldus

Projektiga seonduv dokumentatsioon (erandiks on käesolev wiki leht), kasutajale nähtavad tekstid ning lähtekood on kirjutatud inglise keeles. Võimalusel on kood kirjutatud hilisema I18n toe võimaldamiseks.

Koodi haldab GitHub repositoorium, juurdepääsu saamiseks tuleb projektijuhile saata oma GitHub kasutajanimi (või pull request). Tegemist vajavaid töid näeb GitHub lehel Issues vahekaardilt ning asjakohane dokumentatsioon (API) on GitHub wiki alamjaotises.

Lähtekood on põhjalikult kommenteeritud, muud, eraldiseisvat dokumentatsiooni koodi kohta on minimaalselt.

XML Andmefailid

Tähtaeg 3. märts 2012

XML andmefail kirjeldab veebiteenuse "Challengo" andmeid. Andmed asuvad MYSQL andmebaasis, mille struktuur on kirjeldatud ERD mudeliga

MYSQL ERD mudel

. XML formaadis andmeid väljastab serveris asuv PHP API. Järgnevalt toodud XML näited ei pruugi projekti esimese osa nõudmiste tõttu olla vastavuses teise osana valmiva veebiteenuse tegeliku väljundiga.

Faile saab vaadata ka võrgust: http://enos.itcollege.ee/~anroots/challengo/xml/. Soovitatav on seda teha just XSLT stiilifaili jaoks (http://enos.itcollege.ee/~anroots/challengo/xml/Response.xml).

XML [link]

Järgnevalt on toodud lõik kasutaja praeguste väljakutsete päringust. Kasutajal on parajasti kaks aktiivset väljakutset, igal väljakutsel on veidi meta-infot, mingi hulk ülesandeid (tasks) ning igal ülesandel on üks või mitu autasu (rewards).

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Response.xsl"?>
<!-- List of user's current challenges -->
<challenges>
  <!-- First challenge, started by the user -->
  <challenge id="4" tasks="6" progress="17%">
    <title>The Improgrupp Jaa!</title>
    <description>Inspired by a true story, the Improgrupp Jaa! contains tasks that challenge ones spontaniety and social courage.</description>
    <duration>1209600</duration>
    <points_required>18</points_required>
    <badge_id>2</badge_id>
    
    <!-- Each challenge has a number of tasks that have to be completed.-->
    <!-- No challenge can be completed before earned points from tasks (rewards) exceed the points_required field -->
    <tasks max_points="26">
      <task id="19">
        <title>Make a present to a homeless person</title>
        <description>If you can read this, you're probably among the luckier ones. Do something for the ones who can't.</description>
        <badge_id>2</badge_id>
        
        <!-- Each task yields rewards on completion. Rewards are "power" points of different categories.-->
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">2</reward>
        </rewards>
      </task>
      <task id="20" completed="true">
        <title>Compliment a stranger</title>
        <description>Make a sincere compliment to someone you don't know. We could do with more praise where it's due.</description>
        <badge_id>1</badge_id>
        <rewards>
          <reward power_id="2">4</reward>
        </rewards>
      </task>
      <task id="21">
        <title>Do volunteer work</title>
        <description>Offer yourself as a volunteer to an event or a cause.</description>
        <badge_id>4</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">4</reward>
          <reward power_id="3">1</reward>
        </rewards>
      </task>
      <task id="22">
        <title>Perform to a security camera</title>
        <description>Do a little dance to a security camera. It shouldn't be illegal...probably. Don't get in trouble!</description>
        <badge_id>2</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
        </rewards>
      </task>
      <task id="23">
        <title>Compliment someone for a job well done</title>
        <description>When was the last time you thanked the janitor?</description>
        <badge_id>1</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="3">1</reward>
        </rewards>
      </task>
      <task id="24">
        <title>Take a day off</title>
        <description>This is mostly for work-a-holics: rest for a while.</description>
        <badge_id>4</badge_id>
        <rewards>
          <reward power_id="1">2</reward>
          <reward power_id="2">4</reward>
        </rewards>
      </task>
    </tasks>
  </challenge>
</challenges>

XSLT (stiilifail) [link]

Toodud stiilifail muudab ülaltoodud XML vastuse inimesele kergemini loetavaks.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html class="no-js" lang="en">
      <head>
        <meta charset="utf-8"/>
        <meta name="author" content="Ando Roots" />
        <title>Challengo Response</title>
        <link rel="stylesheet" href="http://i.jaa.ee/assets/bootstrap-2.0/css/bootstrap.min.css" />
        <link rel="stylesheet" href="http://i.jaa.ee/assets/bootstrap-2.0/css/bootstrap.min.responsive.css" />
      </head>
      <body>

        <div class="container">
          <h1>Challengo API response</h1>
          <p class="help-block">
            The following is a list of challenges reported by the XML API.
          </p>
          
          
          <!-- Go over each challenge -->
          <xsl:for-each select="challenges/challenge">
            <h2>
              
              <!-- Challenge badge image and title -->
              <img alt="Challenge badge" height="48" width="48">
                <xsl:attribute name="src">
                  http://enos.itcollege.ee/~anroots/challengo/badges/<xsl:value-of select="badge_id"/>.png</xsl:attribute>
              </img>
              <xsl:value-of select="title"/>

              <!-- Challenge progress, if applicable -->
              <xsl:if test="@progress">
                (<span>
                  <xsl:value-of select="@progress"/>
                </span>)
              </xsl:if>
            </h2>
            
            
            <p class="well">
              <xsl:value-of select="description"/>
            </p>

            <!-- Table for some challenge meta-info -->
            <table class="table table-bordered span4">
              <tbody>
                <tr>
                  <th>
                    Points required to complete:
                  </th>
                  <td>
                    <xsl:value-of select="points_required"/>
                  </td>
                </tr>
                <tr>
                  <th>
                    Time left (hours):
                  </th>
                  <td>
                    <xsl:value-of select="round(duration div 1800)"/>
                  </td>
                </tr>
              </tbody>
            </table>
            <div class="clearfix"></div>            
            
            <!-- List all challenge tasks -->
            <h3 style="margin-top:140px">Tasks (<xsl:value-of select="@tasks"/>)</h3>
            <table class="table table-bordered table-striped table-condensed">
              <thead>
                <tr>
                  <th>ID</th>
                  <th>Title</th>
                  <th>Badge</th>
                  <th>Rewards</th>
                </tr>
              </thead>
              <tbody>
                <xsl:for-each select="tasks/task">
                  <tr>
                    <!-- Color the row gray if task is completed -->
                    <xsl:if test="@completed">
                      <xsl:attribute name="class">
                        help-block
                      </xsl:attribute>
                    </xsl:if>
                    
                    <td>
                      <xsl:value-of select="@id"/>
                    </td>
                    <td>
                      <xsl:value-of select="title"/>
                      <p class="help-block">
                        <xsl:value-of select="description"/>
                      </p>
                    </td>
                    <td>
                      <img alt="Challenge badge" height="48" width="48">
                        <xsl:attribute name="src">http://enos.itcollege.ee/~anroots/challengo/badges/<xsl:value-of select="badge_id"/>.png</xsl:attribute>
                      </img>
                    </td>
                    <td>
                      <ul>
                        <xsl:for-each select="rewards/reward">
                          <li>
                            <xsl:if test="(@power_id)=1">
                              Compassion
                            </xsl:if>
                            <xsl:if test="(@power_id)=2">
                              Strength
                            </xsl:if>
                            <xsl:if test="(@power_id)=3">
                              Intelligence
                            </xsl:if>
                            <span>
                              <xsl:value-of select="."/>
                            </span>
                          </li>
                        </xsl:for-each>
                      </ul>
                    </td>
                  </tr>
                </xsl:for-each>
              </tbody>
            </table>
            <!-- End of challenge task table -->
            
          </xsl:for-each>
          <!-- End of challenge -->
          
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

XSD (skeemifail) [link]

Skeemifail kirjeldab päringu vastuse XML struktuuri.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="challenges">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="challenge">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="title" type="xs:string" />
              <xs:element name="description" type="xs:string" />
              <xs:element name="duration" type="xs:unsignedInt" />
              <xs:element name="points_required" type="xs:unsignedByte" />
              <xs:element name="badge_id" type="xs:unsignedByte" />
              <xs:element name="tasks">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="task">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="title" type="xs:string" />
                          <xs:element name="description" type="xs:string" />
                          <xs:element name="badge_id" type="xs:unsignedByte" />
                          <xs:element name="rewards">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element maxOccurs="unbounded" name="reward">
                                  <xs:complexType>
                                    <xs:simpleContent>
                                      <xs:extension base="xs:unsignedByte">
                                        <xs:attribute name="power_id" type="xs:unsignedByte" use="required" />
                                      </xs:extension>
                                    </xs:simpleContent>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                        <xs:attribute name="id" type="xs:unsignedByte" use="required" />
                        <xs:attribute name="completed" type="xs:boolean" use="optional" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="max_points" type="xs:unsignedByte" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="id" type="xs:unsignedByte" use="required" />
            <xs:attribute name="tasks" type="xs:unsignedByte" use="required" />
            <xs:attribute name="progress" type="xs:string" use="optional" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Veebiteenus

Tähtaeg 30. mai 2012

Näidis HTTP API päringust

Veebiteenusena realiseeriti API, mis võimaldab klientide registreerimist, haldamist ning Challengo teenuse põhifunktsionaalsuse pakkumist HTTP päringute kaudu. API loomisel kasutati RESTful arhitektuuri. Täpsem dokumentatsioon asub API lehel: "API dokumentatsioon" (tegemist on ajutise aadressiga, mis võetakse maha aine lõppemisel).

Kriteeriumid

Kõik õppejõu poolt esitatud kriteeriumid on täidetud. Erikokkuleppe alusel on projekti keeleks PHP.

Kriteeriumid:

  • Teenuse pakkumist - API suudab vastata talle esitatud, valideeruvatele (vt. API dokumentatsiooni) päringutele
  • Teenuse kasutajate tuvastamist ning haldamist - Kasutajatuvastus toimub nime/parooli alusel HTTP Basic Authentication protokollil, ideaalis üle HTTPS-i. Süsteemi sisemiselt on kasutajatel rollid, mida saab kasutada halduseks, näiteks LOGIN rolli eemaldamisel ei saa kasutaja enam sisse logida.
  • Teenuse kasutajate ja kasutusstatistika üle arve pidamist kasutajate lõikes - Kõik API päringud käivad API tokeni alusel. Tokeni kasutaja päringud logitakse nii logifaili kui andmebaasi, neid on sealt võimalik pärida. Lisaks on igal tokenil päringulimiit (tunnis), selle ületamisel päringuid eiratakse. Tokeneid saab tühistada, mis tähendab, et klientrakenduse päringuid ei töödelda mingil juhul.

Testimine

Veebiteenusel ei ole eraldi kasutajaliidest. Testimiseks on kaks varianti:

  1. Luua ise vastav kasutajaliides ehk klientrakendus
  2. Kasutada mõnd abitööriista HTTP päringute koostamiseks. Soovitus: "Chrome plugin"

Autentimisandmed rakendusele saab luua dokumentatsiooni lehel oleva vormi kaudu (andmed saadetakse e-mailile). Kasutajakonto saab luua juba API päringute abil.

N.B. Juhul, kui uute API tokenite loomine ebaõnnestub (serveri mailiserver on veidi ebastabiilne), võib kasutada ka järgnevaid andmeid:

Secret: fowhosurtothab Token: fleraffahskuff

Kood

Lähtekoodi saab siit (removed). Kohtmasinasse paigaldamiseks tuleb alla laadida Kohana framework ning paigaldada application/bootstrap.php failis märgitud moodulid. Andmebaasi schema on database kaustas. Kood on testitud ainult Linux platvormil LAMP stack-iga.

Klientrakendus

Tähtaeg 5. mai 2012

Ekraanipilt tulevaste etenduste nimekirjast
Ekraanipilt etenduse detailvaatest

Klientrakendus on Android rakendus, mis kuvab teater NO99 etendusi ning võimaldab punktide alusel pileteid osta. Tegu on jQuery Mobile pordiga Android platvormile.

Rakendus suhtleb Play! raamistikus kirjutatud API-ga, mis asub kahjuks meeskonna localhostis, sest selle võrku panemiseks oli vaja VPS serverit. Seega ei suuda rakendus Teie arvutites sisselogimist teostada.

Rakendusel on neli peamist vaadet: sisselogimine, etenduste nimekiri, etenduse detailvaade ning konto info. Pileteid saab osta punktide alusel (punktid peavad eelneva mehanismiga juba kontol olema, konto on punkt.no99.ee-ga ühine). Kui pilet on ostetud, märgib rakendus vastava etenduse taustavärviga, teiskordselt piletit osta ei saa, kuid seda pole raske realiseerida.

Peale sisselogimist tõmmatakse serverist alla nimekiri etendustest ning hakatakse siis ükshaaval sellele nimekirjale pisipilte laadima. Allalaaditud pisipildid salvestatakse Android poolt antud vahemälukausta, neid teiskordselt ei laadita.

Kõik suhtlused serveris on asünkroonsed, seda kahel põhjusel: esiteks tapab Android rakenduse ära (ja kasutajal on ebamugav), kui päringu vastust kasutajaliidese thread-ist oodata. Teiseks saab asünkroonset päringut mugavalt taustalt teha ning kasutaja saab oma asjadega edasi tegeleda.

Rakenduse kood asub BitBucketis (develop branch).

Retsensendile

Kuna rakendust iseseisvalt testida ei saa, olen soovi korral valmis seda uuesti oma arvutist demoma.

Feature list

  • Autentimine
  • Tulevaste etenduste nimekirja vaatamine
  • Etenduse detailide vaatamine (sh pilt)
  • Allalaaditud piltide cache-mine
  • Pileti ostmine etendusele punktide alusel
  • Konto info vaatamine

Meeskonna Liikmed

  • Ando Roots anroots@itcollege.ee
  • Mikk Pärast mparast@itcollege.ee

Liitumine

for t in tudengid:
  if !t.laisk && t.oskab_progreda:
    kutsu_meeskonda(t)
$ mail -s "Harold" anroots@itcollege.ee

Eeldan varasemaid teadmisi ning usaldusväärsust. Soovin, et asi ei lõppeks jälle nii, et projektijuht on kaitsmiseelsel õhtul üleval ja lõpetab üksinda projekti. Ole nii kena ja anna huvist märku enne 26. veebruari.

Lisad

Kes on Harold?

Challengo

Challengo.me on Garage48 Tallinn 2011 raames alustatud veebiteenus.

A social network of themed challenges, comes with a Karma profile and level-system.
Revenues from ads on the mobile version.
Team members: Ando Roots, Kristo Vaher, Valeria Gasik, Jelena Savinen

Jelena tutvustab Challengo teenust

Punkt99

Punkt99 valmis Garage48-l 2012 kevadel paljude hakkajate inimeste koostööl. Tegu on piletimüügirakendusega teater NO99-le.