BurgerAce

From EIK wiki

Kodutöö aines "Võrgurakendused II: hajussüsteemide ehitamine"

Meeskond

  • Silver Ohlo
  • Martin Luik
  • Ahto Elken
  • Arvo Bendi

Idee

Meie idee oli luua veebirakendus BurgerAce, mis võimaldaks klientidel ette tellida burgereid. Mõte on selles, et meie klientidel on võimalik burgereid ette tellida. Seetõttu kiire elutempoga kliendil pole vaja oodata toidu valmistamist. Klientidel on võimalik koostada etteantud komponentidest omale meelepärane või valida eelnevalt valmis tehtud burger. Meie teenus vahendab kiirtoidukohate ja nende klientide vahelist suhtlust. Burgeri ostmine pole varem nii kiire ja mugav olnud! :)

Analüüs

Veebirakendus on oma olemuselt vahendusteenus, mis ühendab näljased kliendid ja hõrgutavad burgerid. Tänapäeva kiire elutempo juures ei ole klientidel aega oodata toote valmistamist, seega aitab meie teenus inimestel kiiremini ja mugavamalt soovitud tooteid kätte saada, tellides ette neid meie veebirakenduse kaudu. Seega on vaja kliendil kõigest minna söögikohta, võtta oma tellimus ja nautida toitu. Selline ettetellimise võimalus hoiab kokku kliendi aega ja raha. Kõikide soovide rahuldamiseks on võimalik ise komplekteerida algkoostisosadest burger. Klient saab näha meie teenuse kodulehelüljel, milliste hindadega ja milliseid tooteid erinevad burgerimüüjad pakuvad ning teha selle info põhjal talle sobivama otsuse. Kui klient soovib osta erinevate burgerimüüjate tooteid, registreerib ta ennast kõigepealt süsteemi kasutajaks ning seejärel on tal võimalik juba valida talle sobiv burgerimüüja ning valida asukoht kuhu tellimusele järele soovitakse minna. Järgneb tellimuse kokkupanemine võttes arvesse valitud koha laoseisu. Kliendile näidatakse minimaalset valmimisaega kui tegu on lähiajalise tellimusega, ost tuleb seejärel kliendil kinnitada ja tasuda. Selle tulemusena genereeritakse tšekk kliendile. Kui müüja soovib ennast registreerida meie veebiteenuse kasutajaks, sisestab ta rakendusse vajaliku info nii oma firma kui ka toodete detailide kohta. Teenusepakkujale tehakse pärast registreerimist süsteemi kasutajakonto, mille kaudu saab ta teostada erinevaid toiminguid, sealhulgas muuta oma andmeid, lisada/redigeerida tooteid, määrata hindasid, lisada menüüsid jt.

Must have

  • Kontode loomine ja kustutamine
  • Teenusesse sisse logimine kasutajanime/e-maili ja parooli põhjal
  • Kasutaja andmete muutmine
  • Võimalik komponentidest kokku panna burgeri ja salvestada
  • Ise kokkupandud burgeri hind sõltub komponentide hulgast ja kallidusest
  • Tooteid saab lisada ostukorvi
  • Kasutajal on võimalik ostukorvi muuta enne tellimist
  • Kasutajal on võimalik valida enne tellimuse kinnitamist asukoht ja valmimisaeg
  • Tasumine:
    • Tellimisel tuleb maksta oma burgeri eest
    • Ostude ajalugu (tšekid, mingi meili peale saatmine? Mingi xmliga?)
  • Minimaalne valmimisaja arvutamine komponentide olemusest ja tellimustearvust
  • Kuavatakse valitud restorani hetketellimuste arvu, keskmist valmimisaega ning olemasolevad tooteid
  • Piirangud burgeri kokkupanemisel.

Nice to have

  • Lemmikute jagamine, mis on hästi välja ja piltide
  • Kõikide tellimuste peale nimekiri populaarsematest ise kokkupandud burgeritest mida tellitakse
  • Enne kinnitamist saab veel ostukorvi vaates vahetada asukohta, kuhu minna tellimusele järele ning valikute filtreerimine vastavalt toote varule
  • Tagasiside andmine
  • Nimekiri sooduskampaania tootehindadest
  • Personaalne koostisosade arvestamine/statistika

XML/XSD/XSLT

Jookide pildid leiab siit. Antud juhul pilte otsitakse asukohast "C:\Resources\Images".

XML

<?xml version="1.0" encoding="utf-8" ?>
<Menu Currency="€">
  <Info>
    <Name>BurgerAce teenus</Name>
    <Description>
      <![CDATA[Eesti parim (ja ainukene) burgeri ostu teenuse vahendaja]]>
    </Description>
    <Contacts>
      <Contact Type="Aadress">Raja 4C, Tallinn</Contact>
      <Contact Type="E-mail">kontakt@burgerAce.ee</Contact>
      <Contact Type="Telefon">+372123456789</Contact>
    </Contacts>
  </Info>

  <FoodTypes>
    <Food>
      <Burgers>
        <Burger Name="Queen of Hearts">
          <PriceTable>
            <S>2.40</S>
            <M>3.40</M>
            <L>4.10</L>
          </PriceTable>
          <Description><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.]]></Description>
          <Image>https://s-media-cache-ak0.pinimg.com/originals/e7/56/0c/e7560c91aeb45294dcb4adff7ebeb70c.gif</Image>
          <Ingredients Gluten="false" Allergens="Egg, soy, wheat">
            <Ingredient>Beef</Ingredient>
            <Ingredient>Ketchup</Ingredient>
            <Ingredient>Tomatoes</Ingredient>
            <Ingredient>Mayonnasise</Ingredient>
            <Ingredient>Lettuce</Ingredient>
            <Ingredient>Cheese</Ingredient>
          </Ingredients>
        </Burger>

        <Burger Name="BIG Joker">
          <PriceTable>
            <S>2.90</S>
            <M>3.60</M>
          </PriceTable>
          <Description><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.]]></Description>
          <Image>http://www.zauberfranz.at/pics/kvbigjo.gif</Image>
          <Ingredients Gluten="true" Allergens="Egg, soy, wheat">
            <Ingredient>Beef</Ingredient>
            <Ingredient>Onions</Ingredient>
            <Ingredient>Hot sauce</Ingredient>
            <Ingredient>Tomatoes</Ingredient>
            <Ingredient>Mayonnasise</Ingredient>
            <Ingredient>Pickles</Ingredient>
            <Ingredient>Sesame seed bun</Ingredient>
            <Ingredient>Lettuce</Ingredient>
            <Ingredient>Cheese</Ingredient>
          </Ingredients>
        </Burger>
      </Burgers>
      <!-- Premade standard burgers that you can order without any modifications-->
    </Food>
    <Drinks S="220" M="330" L="500">

      <Type Name="Sodas">
        <Drink Name="Pepsi">
          <PriceTable>
            <S>1.60</S>
            <M>2.99</M>
            <L>3.45</L>
          </PriceTable>
        </Drink>

        <Drink Name="7up">
          <PriceTable>
            <S Size="300">2.30</S>
            <M>5</M>
            <L Size="1000">5.5</L>
          </PriceTable>
        </Drink>

        <Drink Name="Cola">
          <PriceTable>
            <S>2</S>
            <M>3</M>
            <L>4</L>
          </PriceTable>
        </Drink>
      </Type>

      <Type Name="Smoothies">
        <Drink Name="Strawberry-Sundae">
          <PriceTable>
            <S>2</S>
            <M>3</M>
            <L>4</L>
          </PriceTable>
        </Drink>
      </Type>

      <Type Name="Juices">
        <Drink Name="Orange juice">
          <PriceTable>
            <S>2</S>
            <M>3</M>
            <L>4</L>
          </PriceTable>
        </Drink>

      </Type>

    </Drinks>
    <!-- Drinks that can be ordered besides burgers-->
  </FoodTypes>

  <Ingredients>
    <Ingredient Type="Meat">Beef</Ingredient>
    <Ingredient Type="Vegetable">Onions</Ingredient>
    <Ingredient Type="Sauce">Hot sauce</Ingredient>
    <Ingredient Type="Vegetable">Tomatoes</Ingredient>
    <Ingredient Type="Sauce">Mayonnasise</Ingredient>
    <Ingredient Type="Vegetable">Pickles</Ingredient>
    <Ingredient Type="Wheat">Sesame seed bun</Ingredient>
    <Ingredient Type="Vegetable">Lettuce</Ingredient>
    <Ingredient Type="Sauce">Ketchup</Ingredient>
    <Ingredient Type="Dairy">Cheese</Ingredient>
  </Ingredients>
  <!-- Ingredients that can be used to make a custom burger-->

</Menu>

XSD

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Menu">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Info">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Name" type="xs:string" />
              <xs:element name="Description" type="xs:string" />
              <xs:element name="Contacts">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="Contact">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:string">
                            <xs:attribute name="Type" type="xs:string" use="required" />
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="FoodTypes">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Food">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Burgers">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element maxOccurs="unbounded" name="Burger">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="PriceTable">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element name="S" type="xs:decimal" />
                                      <xs:element name="M" type="xs:decimal" />
                                      <xs:element minOccurs="0" name="L" type="xs:decimal" />
                                    </xs:sequence>
                                  </xs:complexType>
                                </xs:element>
                                <xs:element name="Description" type="xs:string" />
                                <xs:element name="Image" type="xs:string" />
                                <xs:element name="Ingredients">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element maxOccurs="unbounded" name="Ingredient" type="xs:string" />
                                    </xs:sequence>
                                    <xs:attribute name="Gluten" type="xs:boolean" use="required" />
                                    <xs:attribute name="Allergens" type="xs:string" use="required" />
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                              <xs:attribute name="Name" type="xs:string" use="required" />
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="Drinks">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="Type">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element maxOccurs="unbounded" name="Drink">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="PriceTable">
                                  <xs:complexType>
                                    <xs:sequence>
                                      <xs:element name="S">
                                        <xs:complexType>
                                          <xs:simpleContent>
                                            <xs:extension base="xs:decimal">
                                              <xs:attribute name="Size" type="xs:unsignedShort" use="optional" />
                                            </xs:extension>
                                          </xs:simpleContent>
                                        </xs:complexType>
                                      </xs:element>
                                      <xs:element name="M" type="xs:decimal" />
                                      <xs:element name="L">
                                        <xs:complexType>
                                          <xs:simpleContent>
                                            <xs:extension base="xs:decimal">
                                              <xs:attribute name="Size" type="xs:unsignedShort" use="optional" />
                                            </xs:extension>
                                          </xs:simpleContent>
                                        </xs:complexType>
                                      </xs:element>
                                    </xs:sequence>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                              <xs:attribute name="Name" type="xs:string" use="required" />
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                        <xs:attribute name="Name" type="xs:string" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="S" type="xs:unsignedByte" use="required" />
                  <xs:attribute name="M" type="xs:unsignedShort" use="required" />
                  <xs:attribute name="L" type="xs:unsignedShort" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="Ingredients">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="Ingredient">
                <xs:complexType>
                  <xs:simpleContent>
                    <xs:extension base="xs:string">
                      <xs:attribute name="Type" type="xs:string" use="required" />
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="Currency" type="xs:string" use="required" />
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT

<?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="html" indent="yes"/>
  <xsl:template match="/">
    <xsl:variable name="currency" select="/Menu/@Currency"/>
    <html>
      <head>
        <title>BurgerACE</title>
      </head>
      <body>
        <xsl:apply-templates select="Menu/FoodTypes"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="FoodTypes">
    <xsl:for-each select="./*">
      <h1>
        <xsl:value-of select="name(.)"/>
      </h1>
      <xsl:apply-templates select="."/>

    </xsl:for-each>
  </xsl:template>

  <xsl:template match="Food">
    <xsl:apply-templates select="Burgers"/>
  </xsl:template>

  <xsl:template match="Ingredients">
    <p>
      <xsl:apply-templates select="Ingredient"/>
      <xsl:if test="@Gluten = 'true' or @Allergens">
        <br/>
        Contains
        <ul>
          <xsl:if test="@Gluten = 'true'">
            <li>
              Gluten
            </li>
          </xsl:if>
          <xsl:if test="@Allergens">
            <li>
              <xsl:value-of select="@Allergens"/>
            </li>
          </xsl:if>
        </ul>
      </xsl:if>
    </p>
  </xsl:template>

  <xsl:template match="Description">
    <h4>
      <xsl:value-of select="."/>
    </h4>
  </xsl:template>

  <xsl:template match="Ingredient">
    <xsl:call-template name="PrintLowerCaseWords"/>
    <xsl:if test="position() != last()">, </xsl:if>
  </xsl:template>


  <xsl:template match="Burgers">
    <xsl:call-template name="PrintHeaderName"/>
    <xsl:apply-templates select="Burger"/>
  </xsl:template>


  <xsl:template match="Burger">
    <xsl:call-template name="PrintHeaderName"/>
    <xsl:apply-templates select="Description"/>
    <xsl:apply-templates select="Ingredients"/>
    <xsl:apply-templates select="PriceTable"/>
  </xsl:template>

  <xsl:template match="Drinks">
    <xsl:for-each select="@*">
      <xsl:value-of select="concat(name(), ' - ',.,' ml')"/>
      <br/>
    </xsl:for-each>
    <xsl:apply-templates select ="Type"/>
  </xsl:template>

  <xsl:template match="Type">
    <xsl:call-template name="PrintHeaderName"/>
    <xsl:apply-templates select="Drink"/>
  </xsl:template>

  <xsl:template match="Drink">
    <xsl:call-template name="PrintHeaderName"/>
    <xsl:apply-templates select="PriceTable"/>
  </xsl:template>

  <xsl:template match="PriceTable">
    <table border="1" style="width:35%">
      <tr>
        <th>Size</th>
        <th>Price</th>
      </tr>
      <xsl:for-each select="./*">
        <tr>
          <td>
            <xsl:choose>
              <xsl:when test="@Size">
                <xsl:value-of select="concat(name(.), ' (', @Size, ' ml)')"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="name(.)"/>
              </xsl:otherwise>
            </xsl:choose>
          </td>
          <td>
            <xsl:value-of select="concat(.,' ','€')"/>
          </td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

  <xsl:template name="PrintHeaderName">
    <xsl:variable name="level" select="count(ancestor::node()) - 2 "/>
    <!--Count depth from element 'FoodTypes'-->
    <xsl:element name="h{$level}">
      <xsl:choose>
        <xsl:when test="@Name">
          <xsl:value-of select="@Name"/>
          <xsl:if test="not(../Type)">
            <xsl:element name="IMG">
              <xsl:attribute name="src">
                <xsl:choose>
                  <xsl:when test="./Image">
                    <xsl:value-of select="./Image"/>
                  </xsl:when>
                  <xsl:otherwise>
                    file:///C:\Resources\Images\<xsl:value-of select="concat(@Name,'.jpg')"/>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:attribute>
              <xsl:attribute name="width">150</xsl:attribute>
              <xsl:attribute name="Style">Margin-left: 20px</xsl:attribute>
            </xsl:element>
          </xsl:if>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="name(.)"/>
        </xsl:otherwise>
      </xsl:choose>

    </xsl:element>
  </xsl:template>

  <xsl:template name="PrintLowerCaseWords">
    <xsl:choose>
      <xsl:when test="position() != 1">
        <xsl:value-of select="concat(translate(substring(., 1, 1), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), substring(., 2))"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Andmebaasi skeem

BurgerAceDbV3.png

Logi

  • 14.03 - Idee valikute debatt ja valitu väljatöötamine ning läbimõtlemine, XMLiga alustamine
  • 15.03 - XML, XSD ja XSLT valmimine.
  • 20.03 - Esimese etapi esitamine wikis.
  • 27.03 - Retsensioonide valmimine meeskondadele "Netgroup" ja "Ordering".
  • 17.04 - Analüüsi valmimine.
  • 21.04 - Andmebaasi skeemi valmimine.
  • 01.05 - Projekt TFSi.
  • 06.06 - Retsensioonid meeskonna SHOP veebiteenusele ja meeskonna VVA klientrakendusele.