README.md 9.68 KB
Newer Older
M1888's avatar
M1888 committed
1 2
# Lottokone - TTOS0300 kurssin harjoitustyö

M1888's avatar
M1888 committed
3
Joeli Hokkanen *<M1888@student.jamk.fi>*
M1888's avatar
M1888 committed
4

M1888's avatar
M1888 committed
5
Speksiin **[TÄSTÄ](doc/spec.md)**.
M1888's avatar
M1888 committed
6

M1888's avatar
M1888 committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
![logo](Lottokone/Resources/lotto.png)

## Sisältö

1. [Asennus](#asennus)
2. [Tietoa ohjelmasta](#tietoa-ohjelmasta)
3. [Kuvankaappaukset + ohjeet](#kuvankaappaukset-ohjeet)
4. [Ohjelman mukana tulevat tiedostot](#ohjelman-mukana-tulevat-tiedostot)
5. [Opittua ja suurimmat haasteet](#opittua-ja-suurimmat-haasteet)
6. [Työmäärä](#tyomaara)
7. [Ehdotus arvosanaksi](#ehdotus-arvosanaksi)

## Asennus

[Release.zip](Release.zip) tiedostosta löytyy purkamisen jälkeen kaikki tarvittava. Käynnistä vain lottokone.exe.

M1888's avatar
M1888 committed
23
.NET Frameworkin ulkopuoliset käytetyt kirjastot:
M1888's avatar
M1888 committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

- [System.Data.SQLite](https://www.nuget.org/packages/System.Data.SQLite) (+ [EntityFramework](https://www.nuget.org/packages/EntityFramework/)): SQLite-tietokantaa varten
- [MedallionRandom](https://www.nuget.org/packages/MedallionRandom/): Thread-safe staattinen satunnaislukugeneraattori

## Tietoa ohjelmasta

Kyseessä on lottosimulaattori. Tarkoituksenasi on voittaa päävoitto lotossa. Ohjelma simuloi loton toimintaa melko pitkälle:

- Simuloituja pelaajia, jotka tekevät lottorivejä
- Joka kierrokselle arvotaan uusi lottorivi ja kaikki rivit tarkistetaan sitä vasten
- Kelvollinen suorituskyky jopa sadoilla tuhansilla lottoriveillä
- Joka kierroksen voitot jaetaan kierroksen potista. Päävoitto kasvaa, kunnes joku voittaa sen.

Lista speksissä olleista suunnitelluista toiminnoista, ja tila:

- [x] Yleinen käyttöliittymä
- [x] Rahan/pisteiden tarkastelu
- [x] Lottosimulaatiosta tulostetta ja statistiikkaa, jota näkee pelin aikana
- [x] Vakiorivejen syöttö
- [x] Arparivien määrittely
- [x] Lottosimulaation asetusten säätö
- [x] Scoreboard
- [ ] Pelitilanteen tallennus
- [ ] Aiemman tallennuksen lataaminen

Toiminnot, jotka toteutettiin, vaikka ne ei olleet speksissä:

- [x] Muuttuvat grafiikat isojen voittojen sattuessa
- [x] Simulaation rikkaimpien pelaajien listaus

## Kuvankaappaukset + ohjeet

Ohjelman käynnistyttyä näet pääikkunan:

![pääikkuna](lottokone.png)

Vasemmassa laidassa on napit, joilla ohjataan konetta. Voit edistää aikaa eteenpäin viikon kerrallaan, tai sitten käynnistä-napilla antaa viikkojen rullata itsestään.

Seuraavassa sarakkeessa näet yleisiä tietoja simulaatiosta: kuinka mones vuosi ja viikko on menossa, montako lottoriviä kierroksella on mukana, paljonko on päävoitosta jaossa ja viime kierroksen voittorivin.

Tämän vieressä on listaikkuna, johon tulee simulaation edetessä tietoa kierrosten kestosta ja kierroksella jaetuista voitoista.

Oikeassa laidassa on pelaajan tiedot. Tilin saldo näyttää tilisi saldon: joka rivi maksaa jotain, ja voitoista sinne kertyy rahaa. Jos haluat kuitenkin muistaa uhkapelatessasi vain hyvät hetket, näet myös pelkät voittosi tämän alapuoleta.

Asetukset-ikkunassa pääsee säätämään simulaation asetuksia tarkemmin.

![asetukset](asetukset.png)

Rikkaimmat-napin takaa löytyy sekä sillä hetkellä käynnissä olevan simulaation rikkaimpien pelaajien listaus, sekä SQLite-tietokannasta haettavat high scoret. Mikäli voitat päävoiton, tallentuu nimesi tälle listalle.

## Ohjelman mukana tulevat tiedostot

M1888's avatar
M1888 committed
76
### Resources/lotto.sqlite
M1888's avatar
M1888 committed
77

M1888's avatar
M1888 committed
78
SQLite-tietokanta, joka sisältää pelaajan tallentamat vakiorivit, sekä high scoret. Tarvittaessa tietokannan voi luoda uudelleen SQLitellä luontiskriptin [create-lotto.sql](Lottokone/Resources/create-lotto.sql) avulla.
M1888's avatar
M1888 committed
79

M1888's avatar
M1888 committed
80 81
![ER-kaavio](lotto-er.png)  
Tietokannan ER-kaavio
M1888's avatar
M1888 committed
82

M1888's avatar
M1888 committed
83
### Resources/etunimet.csv, Resources/sukunimet.csv
M1888's avatar
M1888 committed
84

M1888's avatar
M1888 committed
85 86 87 88 89
CSV-formaatissa olevat listat etunimistä ja sukunimistä. Näitä käytetään simuloitujen pelaajien nimien arpomisessa. Lähde: [avoindata.fi](https://www.avoindata.fi/data/fi/dataset/none)

### \*.dll

Ohjelman tarvitsemia kirjastoja.
M1888's avatar
M1888 committed
90 91 92

## Tiedossa olevat bugit ja jatkokehitysideat

M1888's avatar
M1888 committed
93
Yritin ison osan bugeista eliminoida ennen julkaisua. Kuitenkin joitain huomioita:
M1888's avatar
M1888 committed
94 95 96

- Kerran sain ohjelman jumiin kokonaan, eikä se enää suostunut käynnistymäänkään, kun vaihtelin tarpeeksi isolla skaalalla edestakaisin asetuksia (esim. pelaajia 1000 -> 10 miljoonaa, samalla kertaa arparivejä 3 -> 10 000). Piti poistaa koko release-kansio, ei riittänyt config-tiedoston tyhjennys.

M1888's avatar
M1888 committed
97
- Muutenkin ohjelma käy aika hitaaksi, jos simuloitujen pelaajien ja arparivien ylärajoja alkaa kokeilla. Jätin asetukset-ikkunaan reilusti varaa rukata asetuksia ylöspäin, mikäli uskallusta ja tehoa koneesta löytyy. **Realistisesti kuitenkin sain omalla vuoden 2012 Macbookillani virtuaali-Windows 10:ssä simulaation rullaamaan siedettävästi** (2-3s/kierros) yhteensä **n. 1.5 miljoonalla rivillä** joka kierroksella. 6-ytiminen AMD **Ryzen 5 2600x** jaksoi pyörittää samalla nopeudella **n. 2.8 miljoonaa riviä** joka arvonnassa.
M1888's avatar
M1888 committed
98 99 100

- Jos simulaatiolle asettaa hyvin vähän simuloituja pelaajia ja rivejä, sekä todella paljon omia arparivejä, voi kierrokset rullata niin nopeasti että oman pelaajan voitot listaava ikkuna jää kierroksissa "jälkeen". Tämä kuitenkin korjautuu, kun simulaation pysäyttää ja odottaa että voittolistaus ehtii takaisin ajan tasalle.

M1888's avatar
M1888 committed
101
### Jatkokehitysideoita
M1888's avatar
M1888 committed
102 103 104 105 106 107

- Käyttöliittymää voisi viilata enemmän käyttäjäystävälliseksi. Olen kuitenkin insinööri, enkä käyttöliittymäsuunnittelija. Koen teknisen osaamiseni vahvaksi, ja voin toteuttaa monenlaisia asioita, mutta mieluusti jätän käyttöliittymän suunnittelun muille. Halusin sen tässä projektissa kuitenkin tehdä itse, että edes jotain pohjaa olisi.

- Musiikki. Lottokoneen rullatessa haluaisin [tämän biisin](https://www.youtube.com/watch?v=7wTMd_fPWA4) soivan. Pitänee ottaa säveltäjään yhteyttä, ja kysyä sopiiko biisiä käyttää. En kuitenkaan sitä ehtinyt vielä tehdä.

- Tallennuksen voisi vielä kanssa toteuttaa: tallennetaan satunnaislukugeneraattorin seed-arvo lottokoneen ominaisuudeksi, ja serialisoidaan koko lottokone-objekti binary blobina tietokantaan josta sen voisi sitten ladata ja alustaa tasan samaan tilaan. Ajan puutteesta johtuen en ehtinyt tähänkään vielä koskea.
M1888's avatar
M1888 committed
108

M1888's avatar
M1888 committed
109 110
- Koodin uudelleenjärjestely pois [MainWindow.xaml.cs](Lottokone/MainWindow.xaml.cs):stä. Itse [Lotto](Lottokone/Model/Lotto.cs)-perusluokka ja kaikki siihen liittyvä (Rivit yms.) on mielestäni siististi toteutettu. Kiitos tästä kuulunee hyvälle [suunnitelmalle](doc/spec.md#luokkakaavio), jota lopullinen lottokone vastaa melko tarkasti lukuunottamatta tiettyjen tietorakenteiden muutoksia ja Lotto-luokan luonnollista kasvua ominaisuuksien niitä vaatiessa. Jälkiviisaaana samoissa jalanjäljissä olisi kannattanut jatkaa myös käyttäjän oman Pelaaja-olion hallinnassa: luoda vielä yksi "yliluokka", joka sisältäisi Lottokoneen sekä käyttäjän Pelaaja-olion ja sen käsittelyyn tarvittavat toimenpiteet. Tämän olion voisi sitten helposti sitoa pääikkunaan, ja toteuttaa toiminnallisuuden ilman että koodissa pääikkunan takana olisi liikaa tuota logiikkaa. Nykyiseen ratkaisuun en täysin tyytyväinen ole, vaikka se toimiikin.

M1888's avatar
M1888 committed
111 112
## Opittua ja suurimmat haasteet

M1888's avatar
M1888 committed
113
Iso haaste projektia toteuttamaan lähtiessä oli suuri prosessointimäärä, joka joka kierroksella joudutaan tekemään. Parallelismi tuli tähän avuksi, samalla kuitenkin ongelmaksi. Tämä oli ensimmäinen monisäikeinen tekemäni ohjelma, ja sitä kautta tulikin opittua paljon uutta. Kun UI ja pelilogiikka pyörivät eri threadeissa, oli niiden välisen viestinnän tekeminen haastavaa. Myös käytetyt tietorakenteet joutui miettimään uudelleen suunnitelluista, jotta niitä pystyi käyttämään monesta threadista yhtäaikaa.
M1888's avatar
M1888 committed
114

M1888's avatar
M1888 committed
115 116 117 118
Monisäikeisyys aiheutti ongelmia myös satunnaislukujen luonnissa. Yhtä .NETin omaa Random-objektia ei voi käyttää kuin yhdestä threadista kerrallaan, tai se antaa pelkkiä nollia. Joka threadille, taikka arvottavalle lottoriville, oman Randomin tekeminen oli myös haastavaa, koska Random-luokka käyttää oletuksena seed-lukuna tietokoneen kelloa, mutta ei kauhean suurella tarkkuudella. Niinpä n. 15ms sisään luodut Random-oliot tuottavat identtisiä satunnaislukuja keskenään.

Päädyin ratkaisemaan asian käyttämällä erillistä [MedallionRandom](https://www.nuget.org/packages/MedallionRandom/) pakettia, joka toteuttaa monisäikeisen staattisen Rand-luokan (eli Rand-oliota ei tarvitse alustaa, vaan lukuja voi luoda suoraan tyhjästä). Toinen vaihtoehto olisi ollut luoda Lotto-oliolle yksi satunnaislukugeneraattori, joka tekee ison liudan lukuja valmiiksi ja antaa niitä sitten tarpeen mukaan jo valmiiksi generoituna lottoriveille ja muualle, missä satunnaisuutta tarvitaan. Koin ensimmäisen lähestymistavan kuitenkin helpommaksi toteuttaa.

M1888's avatar
M1888 committed
119
Yksi iso haaste oli myös tuo vakiorivien toteuttaminen. .NET antaa tallentaa Properiesiin haluttuja asetuksia, mutta sieltä ei löytynyt haluamiani tietotyyppejä. Olisin tarvinnut vähintäänkin taulukon, tai mielummin dynaamisen listan näitä taulukoita. Toteutin vakiorivit lopulta SQLiten avulla, mutta se teki tiedonsidonnasta haastavampaa ja päädyinkin koodaamaan paljon logiikasta [Lottorivit.xaml.cs](Lottokone/Lottorivit.xaml.cs):ään käsin.
M1888's avatar
M1888 committed
120 121 122

## Työmäärä

M1888's avatar
M1888 committed
123
Aikaseurantani mukaan toteuttamiseen kului aikaa noin 36 tuntia (issue #1). Tästä n. 4 tuntia oli alun suunnittelua, kunnes toteutus alkoi. Itse lottokoneen logiikan toimimaan saamisessa kului n. 15 h, vakiorivien tallennukseen n. 5h ja loput 12 tuntia kului käyttöliittymän muiden osien toteuttamiseen sekä viilailuun.
M1888's avatar
M1888 committed
124 125 126

## Ehdotus arvosanaksi

M1888's avatar
M1888 committed
127
Ehdotan arvosanaksi 5. Työ on kuitenkin melkoisen laaja, ja täyttää yksikkötestausta lukuunottamatta mielestäni kaikki harjoitustyön vaatimukset. Vaikka se ei käyttöliittymän ulkoasussa välttämättä näy, niin koodi pellin alla on vaatinut aika paljon ajattelua ja lottokoneen perusarkkitehtuuri on mielstäni hyvä.