Ohjelmointi 2 / 2011

Välikoe / 25.3

Vastaa neljään (4) tehtävään ja halutessa bonustehtäviin B1 ja/tai B2, (tuovat lisäpisteitä). Bonustehtävät saa tehdä vaikkei olisi tehnyt siihen tehtävään liittyvää tehtävää. Aikaa 4 tuntia. Jokainen vastaus omalle paperilleen, bonustehtävät voi kirjoittaa samalle. Tehtävistä 1-5 SAA vastata vain 4:ään. Jos vastaa useampaan, niin 4 HUONOINTA arvostellaan.
1.
Tutki alla olevaa koodia ja tee valmiiksi annettua pohjaa käyttäen pöytätesti ohjelmalle. Merkinnät tulee tehdä vain jos muuttujan arvo muuttuu. Väritä harmaaksi myös ne kohdat, joissa muuttujaa ei ole olemassa. Pöytätestin pohjalomakkeella on annettu muutama merkintä jo valmiiksi. (6p)
- Aikasi säästämiseksi sinun ei tarvitse kirjoittaa ohjelman koko
  riviä, vaan pelkkä rivinumero riittää
- Huomaa merkitä myös aliohjelmien/metodien lokaalien 
  muuttujien muutokset.
Käytä merkinnöissä seuraavia merkkejä:
& = viittaus (esim. &N1 viittaa N1-olioon keossa, N1 = 1. new)
Merkitse * jokaisen muuttujan päälle joka on viitemuuttuja.
ROSKA = olio muuttuu roskaksi

/*1*/ public class YdinVoimala {
/*2*/           private Reaktori paaReaktori;
/*3*/           private Reaktori varaReaktori;
/*4*/           private String tila = "NORMAALI";
/*5*/   
/*6*/           public YdinVoimala(Reaktori varaReaktori) {
/*7*/                   this.paaReaktori = new Reaktori();
/*8*/                   this.varaReaktori = varaReaktori;
/*9*/           }
/*10*/  
/*11*/          public void maaJarisee(int sateilynMaara) {
/*12*/                  sateilynMaara += 3;
/*13*/          
/*14*/                  if (paaReaktori != null && varaReaktori != null) {
/*15*/                          this.paaReaktori.riko();
/*16*/                          this.varaReaktori.riko();                       
/*17*/                          this.paaReaktori = null;
/*18*/                          this.varaReaktori = null;
/*19*/                  }
/*20*/                  tila = "KATASTROFI";
/*21*/          }
/*22*/  
/*23*/          public void arvioi() {
/*23*/                  System.out.println(tila);
/*25*/          }
/*26*/  
/*27*/          public static void main(String args[]) {
/*28*/                  Reaktori varaReaktori = new Reaktori();
/*29*/                  YdinVoimala fukushima = 
                                     new YdinVoimala(varaReaktori);
/*30*/                  int sateilynMaara = 0;
/*31*/                  fukushima.maaJarisee(sateilynMaara);
/*32*/                  fukushima.arvioi();
/*33*/                  fukushima.maaJarisee(sateilynMaara=3);
/*34*/                  System.out.println(sateilynMaara);
/*35*/          }
/*36*/ }
/*37*
/*38*/ class Reaktori {
/*39*/          boolean rikki = false;
/*40*/ 
/*41*/          public void riko() {
/*42*/                  this.rikki = true;
/*43*/          }
/*44*/ }

2.
Tehtävä 3. Testaaminen. Alla olevassa listauksessa on kolme aliohjelmaa: vaihda, käännä ja lajittele. Testien luonnissa saat käyttää ComTestia tai JUnitia. ComTestin === vastaa JUnitin assertEqualsia niin, että 1 === 2 ja assertEquals(1,2) on samanarvoisia. Pyri b- ja c-kohdin testeissä mahdollisimman täydelliseen testaamiseen. Testaa olennaisesti taulukon jokaista alkiota, eli pelkästään kahden alkion vertaaminen ei riitä.
2a)
Testivetoinen kehitys. Toteuta vaihda-aliohjelman runko sen testien perusteella. (2p)
2b)
Luo kaanna-aliohjelmalle testi. (2p)
2c)
Luo lajittele-aliohjelmalle testi. (2p)
  /**
   * Vaihtaa taulukon alkioiden a ja b arvojen paikkaa.
   * 
   * @param taulukko Muutettava taulukko.
   * @param a Vaihdettavista alkioista ensimmäisen indeksi.
   * @param b Vaihdettavista alkioista toisen indeksi.
   * <pre name="test">
   *    int[] taulukko = {1, 2, 3, 4};
   *    vaihda(taulukko, 1, 3);
   *    Arrays.toString(taulukko) === "[1, 4, 3, 2]";
   * </pre>
   */
  public static void vaihda(int[] taulukko, int a, int b) {
    // TODO: Toteuta.
  }

  /**
   * Kääntää taulukon ympäri vaihda-aliohjelmaa käyttäen.
   * @param taulukko Käännettävä taulukko
   * @return Käännetty taulukko
   */
  public static int[] kaanna(int[] taulukko) {
     // Pidä alkuperäinen taulukko ennallaan
     int[] kaannetty = Arrays.copyOf(taulukko, taulukko.length);
     int alku = 0, loppu = kaannetty.length - 1;
     while (alku < loppu) {
        vaihda(kaannetty, alku++, loppu--);
     }
     return kaannetty;
  }
  

  /**
   * Lajittelee taulukon O(n²) ajassa. Lisäyslajittelu.
   * 
   * @param alkup Lähtötaulukko
   * @return lajiteltu Lajiteltu taulukko
   */
  public static int[] lajittele(int[] alkup) {
    int[] lajiteltava = Arrays.copyOf(alkup, alkup.length);
    int j, lukumaara = lajiteltava.length;

    for (int i = 1; i < lukumaara; i++) {
      j = i;
      // Lajittele alkiot j:stä vasemalle.
      while (j > 0 && lajiteltava[j] < lajiteltava[j - 1]) {
        vaihda(lajiteltava, j, j - 1);
        j--;
      }
    }

    return lajiteltava;
  }
3.
M3U on tiedostoformaatti soittolistojen tallentamiseen. M3U-tiedostot ovat tekstimuotoisia tiedostoja sisältäen soittolistan toistettavien kohteiden sijainnit. Tehtävä käsittelee Extended M3U -tiedostoja, jotka voivat sisältää myös kommentteja. Näissä tiedostoissa kommentti-rivit alkavat aina #-merkillä.
Tiedostomuoto:
#EXTM3U

#EXTINF:150, ArtistiX - KappaleX
C:\musiikki\raita1.mp3

C:\musiikki\raita2.mp3

#EXTINF:-1, Nettiradio
http://www.example.org/foo.ogg

#EXTINF:-1, Ohjelmoinnin luento
http://kurssit.it.jyu.fi/TIEP111/2011/luento/ohj2_luento02a.mp4

Yllä on esimerkki extended M3U -tiedostosta. Ensimmäinen rivi on tiedoston otsake ja aina samanlainen kuin yllä (#EXTM3U). Tämän jälkeen luetellaan soittolistan tiedostot allekkain. Jokainen tiedosto voidaan varustaa ylimääräisellä informaatiolla merkitsemällä se #EXTINF-merkinnän jälkeen. Merkinnän jälkeen tulee kappaleen pituus sekunteina, jonka jälkeen kappaleen tiedot (pilkulla erotettuna). Virtautetuissa medioissa käytetään yleensä negatiivista pituutta (-1), jolloin soitto-ohjelma jättää pituuden huomiotta.
Yllä olevaa esimerkkitiedostoa apunasi käyttäen, tee ohjelma, joka
3a)
lukee m3u-tiedoston ja tarkistaa tiedoston oikeellisuuden, ts. että tiedostosta löytyy vähintään otsake. Jos tiedosto sisältää osoitteita medioihin, täytyy niihin mahdollisesti liittyvä EXTINF-määrittely löytyä osoiterivin yläpuolelta. EXTINF-määrittelyjä sallitaan vain yksi per osoite. Mahdollisia virhetilanteita ovat ainakin otsakkeen puuttuminen ja osoitteen puuttuminen. (3p)
Esim. tiedosto vika.m3u, jonka sisältö on
#EXTINF:0,Radio
aiheuttaisi ohjelmassa vaikkapa seuravanlaisen tulosteen:
Tiedosto huonolista.m3u on viallinen:
- Otsake puuttuu (#EXTM3U)
- Kohteen 'Radio' osoite puuttuu
3b)
tulostaa tiedostossa olevien soittolistan kohteiden osoitteet. (3p)
Esimerkkitiedostoa käyttämällä pitäisi tulostuksen olla seuraavan kaltainen:
C:\musiikki\raita1.mp3
C:\musiikki\raita2.mp3
http://www.example.org/foo.ogg
http://kurssit.it.jyu.fi/TIEP111/2011/luento/ohj2_luento02a.mp4
Ota huomioon tilanteet, joissa tiedosto ei aukeakaan. Tiedoston nimi on soittolista.m3u.
4.
Tässä on osa yrityksen mahdollista postipakettien hallintajärjestelmää. Täydennä kaikki tehtävän kohdat (a-f) ohjeiden mukaan. Huomioithan, että luokka ei ole vielä valmis, joten id-arvoa ja osoitetta ei vielä käytetä missään, vaikka niitä valmiissa versiossa käytetään. Tässä tehtävässä tähän ei tarvitse reagoida. (6p)
/**
 * Postipaketti
 *
 * Tallentaa sisälleen tavaroita taulukkoon.
 * @author Taistelujarmo
 * @version 0.1
 */
public class Postipaketti {
   private Tavara[] sisalto;
   private int lkm;
   private int id;
   private String osoite;

// Tehtävä a):
// Täydennä konstruktori ja sen kommentit, huomioi mahdolliset
// virhetilaneet. Konstruktorissa pitää luoda sisalto-muuttujan
// taulukko, johonka mahtuu koko-parametrin verran tavaroita.

   /**
* TÄYDENNÄ
    * @param koko Paljonko mahtuu tavaraa sisään maksimissaan
    */
   public Postipaketti(int maxKoko) {
       TÄYDENNÄ
   }

 // Tehtävä b):
 // Tutki miten aliohjelma toimii, ja täydennä kommentit

   /**
    * TÄYDENNÄ
    */
   public void lisaa(Tavara tavara) {
       if ( lkm >= sisalto.length ) return;
       sisalto[lkm] = tavara;
       lkm++;
   }


   // Tehtävä c):
   // Täydennä ohjelma kommentin määrittelemällä tavalla

   /**
    * Palauttaa indeksiä vastaavan tavaran.
    * Jos menee ohi taulukosta, tai kohdalla on null, palautuu null
    * @param i haettava indeksi
    * @return indeksin kohdalla oleva tavara tai null
    */
   public Tavara getTavara(int i) {
       TÄYDENNÄ
   }

   // Tehtävä d):
   // Täydennä silmukan sisältö, jotta ohjelma toimii kommenttien
   // määrittelemällä tavalla

   /**
    * Hakee vaarallisimman ehdokkaan
    * Jos samaa vaarallisuutta on, haetaan ensimmäinen vastaava
    * @return Vaarallisin ehdokas
    */
   public Tavara haeVaarallisin() {
       TÄYDENNÄ TESTI SIITÄ, ETTÄ JOS MITÄÄN ALKIOTA EI OLE 
       Tavara ehdokas = sisalto[0];
       for (TÄYDENNÄ) {
           TÄYDENNÄ
       }
       return ehdokas;
   }
}

/**
 * Tavara-luokka
 * Tietää tavaran nimen ja vaarallisuuden
 * @author Taistelujarmo
 * @version 0.01
 */
public class Tavara {
   private String nimi;
   private int vaarallisuus;

   /**
    * Alustaa tavaran
    */
   public Tavara() {
       nimi = "Default";
   }

   /**
    * Palauttaa tavaran nimen
    * @return Tavaran nimi
    */
   public String getNimi() {
       return nimi;
   }


   // Tehtävä e):
   // Tee metodi public void setNimi(String nimi) {..} ja  kommentit
   // Huomioi, että Tavaran nimi ei saa olla null!

   TÄYDENNÄ
   public void setNimi(String nimi) {
       TÄYDENNÄ
   }

   // Tehtävä f):
   // Tee metodi public void setVaarallisuus(int vaarallisuus) {..}
   // ja tee kommentit. Vaarallisuus on oltava välillä 0-5

   TÄYDENNÄ
   public void setVaarallisuus(int vaarallisuus) {
       TÄYDENNÄ
   }

   /**
    * Palauttaa paketin vaarallisuuden
    * @return Vaarallisuusarvo
    */
   public int getVaarallisuus() {
       return vaarallisuus;
   }
}
5.
Edellinen koodi oli osa yrityksen paketinhallintajärjestelmää. Piirrä kuva tietorakenteesta edellisen tehtävän koodien perusteella. Piirrä kuvaan myös postipakettien säilöminen itse tehtyyn dynaamiseen taulukkoon, joka sisältää alkio-taulukon ja siitä käytössä olevan lkm. Tyhjään järjestelmään lisätään alla olevat 4 lähetettyä pakettia. Kuva tilanteesta missä nämä 4 pakettia on lisätty. Muista olla tarkkana osoittimien suunnasta (nuolet merkittävä). Kuva on siis OLIO-kuva tietorakenteesta, ei UML-kuva. (6p)
paketin id
maxKoko
osoite
sisältö (vaarallisuus)
1
1
Taitoniekantie 9
100kg perunoita(0)
2
3
Perhonkatu 2
Moottorisaha(3), jätesäkkejä(0)
4
1
Vanhaistentie 1
Uudet sterkat(0)
5
2
Rajatie 32
Tappajajänis(5)