Tenta i TDP007 onsdag 18 augusti 2010 kl 14-18
----------------------------------------------

Uppgift 1: Grundläggande Ruby (6p)
----------------------------------

a) Vad är skillnaden på @var och @@var? (1p)

b) Ge exempel på minst tre olika sätt att utöka en array i Ruby! (1p)

c) I följande körexempel ser vi hur en hash-tabell används:

     >> h
     => {"apa"=>14, "banan"=>27}
     >> h["apelsin"]
     => "Finns i sjön!"

   Förklara hur det kan komma sig att nyckeln "apelsin" ger värdet 
   "Finns i sjön!", utan att detta par finns i hash-tabellen. Visa vilken 
   kod som bör ha körts innan dessa rader. (2p)

d) I filen myclass.rb finns defintionen av en klass. Experimentera
   med klassen och försök förstå vad den gör. Förklara vad man skulle
   kunna ha klassen till och föreslå bättre namn på själva klassen och
   det attribut a som klassen innehåller. (2p)

Uppgift 2: Reguljära uttryck (3p)
---------------------------------

a) (2p) Ett svensk registreringsnummer består av tre bokstäver följt av
   tre siffror. De tre bokstäverna kommer från intervallet A-Z men
   kan inte vara I, Q eller V eftersom dessa är lätta att förväxla
   med andra bokstäver på håll.

   Din uppgift är att konstruera ett reguljärt uttryck som kan användas
   för att matcha svenska registreringsnummer. Du ska också baka in
   detta i en funktion som tar en sträng och returnerar true eller
   false om strängen är ett korrekt registreringsnummer eller inte.
   Strängen ska kunna innehålla inledande och avslutande blanktecken
   som ska tas ignoreras. Exempel:

     >> regnr "XGT794"
     => true
     >> regnr "XQT794"
     => false
     >> regnr "  XGT794 "
     => true
     >> regnr "xgt794"
     => false

b) (1p) Konstruera ett reguljärt uttryck som kan matcha olika stavningar
   av följande efternamn: Pettersson, Petterson, Petersson, Peterson,
   Petterzon, Peterzon.

Uppgift 3: Enhetstestning samt bearbetning av textfiler (7p)
------------------------------------------------------------

a) (4p) I filen temp.txt finns en tabell med genomsnittliga dygnsmedel-
   temperaturerna under årets tolv månader för några olika flygplatser.
   Din uppgift är att skriva ett program som läser in tabellen till
   ett lämpligt format och därefter beräknar för varje månad vilken
   flygplats som har den varmaste medeltemperaturen (så att man vet
   vart man borde åka på semester varje månad hela året). Programmet
   ska funka ungefär så här:

     >> my_program("temp.txt")
     1: SYD (22.1)
     2: SYD (22.0)
     3: SYD (20.9)
     4: SYD (18.3)
     5: FCO (17.8)
     6: FCO (21.7)
     7: FCO (24.4)
     8: FCO (24.1)
     9: LAX (21.0)
     10: LAX (19.3)
     11: SYD (19.4)
     12: SYD (21.2)

   Det exakta utdataformatet är inte så intressant, så länge korrekt
   information finns med. Programmet ska utformas så generellt att det
   inte är beroende av att det är exakt fem flygplatser, eller just dessa.

b) (3p) Utforma ett antal lämpliga enhetstester för inläsningsdelen
   av ditt program för uppgift a). Kolla t.ex. att du fått med alla
   flygplatserna och att temperaturerna för några olika månader är okej.

Uppgift 4: XML-parsning (5p)
----------------------------

Sture driver en liten kiosk som heter "Stures kiosk" kort och gott.
Stures revisor har flera gånger påpekat att Sture borde göra en
uppskattning av hur mycket allt godis i kiosken är värt, åtminstone
en gång i veckan. Det skulle vara bra, både för Stures bokföring och
för Stures försäkringsbolag. Eftersom det inte riktigt håller att
räkna alla grejer vill Sture hitta på ett annat sätt. Han har ett
datoriserat kassasystem som kan mata ut en XML-fil med information om 
hur mycket kassasystemet tror att det finns i kiosken. Det kan duga 
som underlag. Dock behöver varorna i XML-filen summeras så att man 
vet vad allt är värt tillsammans. Det är här som du kommer in i bilden.

Din uppgift är att skriva ett Ruby-program som kan läsa igenom
XML-filen med uppgift om godiset i Stures kiosk och tala om vad allt
är värt. Sture är lite petig, så han vill gärna ha en SAX-lösning.
Det finns som tur är ett exempel på en sådan parser i filen
sax_example.rb, så du har något att utgå från. Tanken är att när
allt är klart så ska Sture kunna skriva så här vid Ruby-prompten:

 >> value("lager.xml")
 => 2665.0

Svaret innebär alltså att det totala värdet av allt godis som finns
i kiosken är 2665 kr.

Uppgift 5: Domänspecifika språk (5p)
------------------------------------

Stina och hennes företag Bookshop Solutions Ltd utvecklar programvara
som tar hand om all information som en bokhandel behöver hantera:
lager, fakturor, beställningar, kassakvitton, etc. Deras programvara
är utvecklad i Ruby och för varje installation finns en konfigurationsfil
som talar om grundläggande information om det aktuella företaget i form 
av ett antal strängar. Följande exempel finns även i filen config.rb:

  store_name "Berras bokhandel"
  company_name "Bertilssons Bokhandel AB"
  first_name "Bertil"
  last_name "Bertilsson"
  name first_name+" "+last_name
  receipt_header store_name
  receipt_footer "Välkommen åter önskar #{first_name}!"
  invoice_header "Faktura från #{company_name}"

Stina vill att du ska betrakta konfigurationsfilen som ett litet
domänspecifikt språk och skriva en mycket enkel parser för att 
läsa in denna information till ett Ruby-objekt, enligt de tekniker
vi har gått igenom i kursen. Hon vill alltså att man ska kunna
skriva t.ex. så här:

  >> c=Configuration.load("config.rb")
  => ...
  >> c.receipt_footer
  => "Välkommen åter önskar Bertil!"

Implementera klassen Configuration.

Uppgift 6: Parsning (6p)
------------------------

Cascading Style Sheets (CSS) är en teknik för att specificera hur en
webbsida ska se ut. Tanken är att dokumentets struktur och innehåll
ska ligga i en HTML-fil och att utseendet bestäms av en CSS-fil. På så sätt
kan man separera innehåll och utseende, vilket ger många fördelar.

Lite förenklat kan man säga att en CSS-fil specificerar för varje
HTML-tagg hur den ska presenteras på skärmen. Följande korta exempel
finns i filen example.css:

  h1 {
    font-weight: bold;
    font-size: 12px 
  }
  p  { font-size: 12px }    /* px */
  em { color: red } 

Detta säger att all text som taggas med <h1>...</h1> ska presenteras
som fetstil i 12 punkters storlek, etc. 

CSS-filer kan se lite mer komplicerade ut, men för den här uppgiften
utgår vi från att den består av en uppsättning regler som börjar
med namnet på en tagg och fortsätter med en egenskapslista, inramad
av { ... }. Egenskapslistan består av ett antal egenskaper där namnet
skiljs från värdet med ett kolon. Om listan består av flera egenskaper
ska det vara ett semikolon mellan egenskaperna, dock inte sist.
Förutom detta kan det finnas kommentarer som inramas av /* ... */.

Din uppgift är att utgå från den parser som finns i rdparse.rb och bygga
en enkel parser som kan läsa in och tolka CSS-filer. Resultatet av
parsningen ska vara någon form av datastruktur som innehåller de
stilmallar som finns i filen, t.ex. i form av en hashtabell. Du behöver
inte hantera mer komplicerade CSS-filer än filen example.css. Följande
körexempel visar hur det skulle kunna se ut:

  irb(main):180:0> cp=CSSParser.new
  #<CSSParser:0x2ed820 (-klipp-) >
  irb(main):181:0> cp.load "example.css"
  (-klipp-)
  {"p"=>{"font-size"=>"12px"}, "em"=>{"color"=>"red"}, 
   "h1"=>{"font-weight"=>"bold", "font-size"=>"12px"}}