viikon 5 ohjelmointitehtävien esimerkkiratkaisut - mluukkai/OTM2012 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äätteen 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** ⚠️