Viikon 5 paikanpäällä tehtävien tehtävien mallivastaukset - HY-TKTL/otm2014s GitHub Wiki

Tehtävä 1

public class OstoskoriTest {

    Ostoskori kori;
    Tuote karjala;
    Tuote koff;

    @Before
    public void setUp() {
        kori = new Ostoskori();
        karjala = new Tuote("Karjala", 3);
        koff = new Tuote("Koff", 2);
    }

    @Test
    public void luodunOstoskorinHintaJaTuotteidenMaaraNolla() {
        assertEquals(0, kori.hinta());
        assertEquals(0, kori.tuotteitaKorissa());
    }

    @Test
    public void yhdenTuotteenLisaamisenJalkeenKorissaYksiTuote() {
        kori.lisaaTuote(karjala);

        assertEquals(1, kori.tuotteitaKorissa());
    }

    @Test
    public void yhdenTuotteenLisaamisenJalkeenostoskorinHintaSamaKuinTuotteenHinta() {
        kori.lisaaTuote(karjala);

        assertEquals(karjala.getHinta(), kori.hinta());
    }

    @Test
    public void kahdenTuotteenLisaamisenJalkeenKorissaKaksiTuotetta() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(koff);

        assertEquals(2, kori.tuotteitaKorissa());
    }

    @Test
    public void kahdenTuotteenLisaamisenJalkeenostoskorinHintaSamaKuinTuotteidenHintojenSumma() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(koff);

        assertEquals(karjala.getHinta() + koff.getHinta(), kori.hinta());
    }

    @Test
    public void yhdenTuotteenLisaamisenJalkeenostoskoriSisaltaaYhdenOstoksen() {
        kori.lisaaTuote(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();

        assertEquals(1, ostokset.size());
    }

    @Test
    public void yhdenTuotteenLisaamisenJalkeenostoskoriSisaltaaOstoksenJonaSamaNimiKuinTuotteellaJaLukumaara1() {
        kori.lisaaTuote(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();
        Ostos lisatty = ostokset.get(0);

        assertEquals(karjala.getNimi(), lisatty.tuotteenNimi());
        assertEquals(1, lisatty.lukumaara());
    }

    @Test
    public void kahdenEriTuotteenLisaamisenJalkeenostoskoriSisaltaaKaksiOstosta() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(koff);

        ArrayList<Ostos> ostokset = kori.ostokset();

        assertEquals(2, ostokset.size());
    }

    @Test
    public void kahdenSamanTuotteenLisaamisenJalkeenostoskoriSisaltaaYhdenOstoksen() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();

        assertEquals(1, ostokset.size());
    }

    @Test
    public void kahdenSamanTuotteenLisaamisenJalkeenostoskoriSisaltaaOstoksenJonaSamaNimiKuinTuotteellaJaLukumaaraw() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();
        Ostos lisatty = ostokset.get(0);

        assertEquals(karjala.getNimi(), lisatty.tuotteenNimi());
        assertEquals(2, lisatty.lukumaara());
    }

    @Test
    public void josKoriinOnLisattyTuoteJaSamaTuotePoistetaanOnKoriTamanJälkeenTyhja() {
        kori.lisaaTuote(karjala);
        kori.poista(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();

        assertEquals(0, ostokset.size());
        assertEquals(0, kori.hinta());
        assertEquals(0, kori.tuotteitaKorissa());
    }

    @Test
    public void josKoriinOnLisattyKaksiSamaaTuotettaJaToinenNaistaPoistetaanJaaKoriinOstosJossaOnTuotetta1() {
        kori.lisaaTuote(karjala);
        kori.lisaaTuote(karjala);
        kori.poista(karjala);

        ArrayList<Ostos> ostokset = kori.ostokset();

        assertEquals(1, ostokset.size());
        Ostos lisatty = ostokset.get(0);

        assertEquals(karjala.getNimi(), lisatty.tuotteenNimi());
        assertEquals(1, lisatty.lukumaara());
    }
}

Ostokset ArrayListiin tallettava ostoskori:

import java.util.ArrayList;

public class Ostoskori {

    private ArrayList<Ostos> ostokset;

    public Ostoskori() {
        ostokset = new ArrayList<Ostos>();
    }

    public int tuotteitaKorissa() {
        int tuotteita = 0;
        for (Ostos ostos : ostokset) {
            tuotteita += ostos.lukumaara();
        }

        return tuotteita;
    }

    public int hinta() {
        int hinta = 0;

        for (Ostos ostos : ostokset) {
            hinta += ostos.hinta();
        }

        return hinta;
    }

    public void lisaaTuote(Tuote lisattava) {
        Ostos ostos = haeOstos(lisattava);
        if (ostos != null) {
            ostos.muutaLukumaaraa(1);
        } else {
            ostokset.add(new Ostos(lisattava));
        }
    }

    public void poista(Tuote poistettava) {
        Ostos ostos = haeOstos(poistettava);
        ostos.muutaLukumaaraa(-1);
        if (ostos.lukumaara() == 0) {
            ostokset.remove(ostos);
        }
    }

    public ArrayList<Ostos> ostokset() {
        return ostokset;
    }

    public void tyhjenna() {
        ostokset.clear();
    }

    private Ostos haeOstos(Tuote lisattava) {
        for (Ostos ostos : ostokset) {
            if (ostos.tuotteenNimi().equals(lisattava.getNimi())) {
                return ostos;
            }
        }

        return null;
    }
}

Tallettamalla ostokset HashMap:iin (avaimena ostoksen nimi) olisi päästy helpommalla ja ratkaisu olisi muutenkin ollut tyylikkäämpi.

tehtävä 2

Tallettamalla hinnat ja myytyjen lounaiden määrä Mapiin saadaan koodia muutettua huomattavasti joustavampaan suuntaan. Mapin avaimena on käytetty enumeja, ks. ohjelmoinnin jatkokurssin materiaalista lisää enumeista

public enum Lounas {
    EDULLINEN, MAUKAS;
}

public class Kassapaate {

    private int kassassaRahaa;
    private HashMap<Lounas, Integer> hinta;
    private HashMap<Lounas, Integer> myytyja;

    public Kassapaate() {
        this.kassassaRahaa = 100000;
        hinta = new HashMap<Lounas, Integer>();
        hinta.put(Lounas.EDULLINEN, 240);
        hinta.put(Lounas.MAUKAS, 400);
        myytyja = new HashMap<Lounas, Integer>();
        myytyja.put(Lounas.EDULLINEN, 0);
        myytyja.put(Lounas.MAUKAS, 0);
    }

    public int syoEdullisesti(int maksu) {
        return syoKateisella(Lounas.EDULLINEN, maksu);
    }

    public int syoMaukkaasti(int maksu) {
        return syoKateisella(Lounas.MAUKAS, maksu);
    }

    public boolean syoEdullisesti(LyyraKortti kortti) {
        return syoKortilla(Lounas.EDULLINEN, kortti);
    }

    public boolean syoMaukkaasti(LyyraKortti kortti) {
        return syoKortilla(Lounas.MAUKAS, kortti);
    }

    public void lataaRahaaKortille(LyyraKortti kortti, int summa) {
        if (summa < 0) {
            return;
        }

        kortti.lataaRahaa(summa);
        this.kassassaRahaa += summa;

    }

    public int kassassaRahaa() {
        return kassassaRahaa;
    }

    public int maukkaitaLounaitaMyyty() {
        return myytyja.get(Lounas.MAUKAS);
    }

    public int edullisiaLounaitaMyyty() {
        return myytyja.get(Lounas.EDULLINEN);
    }

    private int syoKateisella(Lounas lounasTyyppi, int maksu) {
        int lounaanHinta = hinta.get(lounasTyyppi);

        if (maksu < lounaanHinta) {
            return maksu;
        }

        kassassaRahaa += lounaanHinta;
        kasvataMyytyjenMaaraa(lounasTyyppi);

        return maksu - lounaanHinta;
    }

    private void kasvataMyytyjenMaaraa(Lounas lounasTyyppi) {
        myytyja.put(lounasTyyppi, myytyja.get(lounasTyyppi) + 1);
    }

    private boolean syoKortilla(Lounas lounasTyyppi, LyyraKortti kortti) {
        int lounaanHinta = hinta.get(lounasTyyppi);
        if (lounaanHinta > kortti.saldo()) {
            return false;
        }

        kortti.otaRahaa(lounaanHinta);
        kasvataMyytyjenMaaraa(lounasTyyppi);

        return true;
    }
}

Ratkaisu ei ole vieläkään paras mahdillinen. Vika on oikeastaan Kassapääte-luokan metodeissa. Jos halutaan uusia myytäviä tuotteita, on kassapäätteelle luotava metodi jokaista tuotetta varten. Tästä ongelmasta päästäisiin eroon muuttamalla kassapäätteen rajapinta sellaiseksi, että ostettavan lounaan/tuotteen tyyppi annetaan parametrina.

⚠️ **GitHub.com Fallback** ⚠️