Luku 4.2: Tehtävä: Reading a chunked file
Pistearvo: 200p
Bonus: +5 % omista pisteistä aikaisesta palautuksesta.
Teema
Tehtävissä 4.2 ja 4.3 luetaan eri formaatein tallennettua dataa. Molemmissa luettava data kuvaa shakkipelin tilanteita. Shakkipeliä kuvaavat luokat ja tiedoston tulkintaa varten olevan luokan pohja annetaan valmiina.
Tavoitteet
- Harjoitellaan lukemista tietovirrasta.
- Tutustutaan mahdolliseen tapaan säilyttää tietoa tiedostossa.
- Kirjoitetaan isomman ohjelman keskeinen osa. Lähes jokaisessa projektiaiheessa ohjelman tulee pystyä lukemaan ja tallentamaan tiedostoja. Monessa työssä formaatti voi olla yksinkertaisempi.
Intro : Tiedostoformaateista
Yksi keskeinen ominaisuus lähes joka ohjelmassa on mahdollisuus tallentaa ohjelman toimintaan liittyvää tietoa tiedostoihin sekä ladata ohjelman käyttöön. Tallennettavalla tiedolla on lähes aina jokin selkeä rakenne. Tiedon esitystapaa tiedostoissa kutsutaan tiedostoformaatiksi.
Formaattien suunnitteluun tai olemassa olevan formaatin valintaan johonkin tehtävään vaikuttaa joukko erilaisia tavoitteita kuten
Luettavuus
- Editoitavuus (käsin tai apuohjelmilla)
- Kirjoittaminen alusta myös käsin
- Mahdollisuus lisätä väliin
- Virheherkkyys
- Yhtälailla formaatin kuin parserin (tiedoston tulkitsijan) tehtävä
Tilankäyttö
Formaatin laajennettavuus
Nopeus
Tunnetut formaatit (esim CSV) joita käyttämällä ohjelman tallentama data on muilla ohjelmilla käsiteltävissä.
Lohkopohjainen formaatti
Tässä tehtävässä kirjoitetaan ohjelma, joka lukee lohkopohjaista formaattia. Mm. monet kuva- ja ääniformaatit ovat tällaisia. Niitä on helppo lukea ja kirjoittaa ohjelmilla. Nämä formaatit ovat helposti laajennettavissa: Niihin voidaan lisätä tietoa, jota kaikkien niitä lukevien ohjelmien ei tarvitse ymmärtää, mutta kaikki ohjelmat pystyvät silti käsittelemään olennaiset perustiedot. Mm. kameroiden tuottama lisäinformaatio kuvasta on voitu liittää olemassaoleviin kuvatyyppeihin muuttamatta tiedostojen alkuperäistä formaattia.
Esimerkkejä muista formaateista
Luvussa 4.3 käsitellään ihmiselle helpommin käsiteltävää formaattia.
Tehtäväpohja : tehtävässä käytettävä formaatti
Tehtävän formaatti on kehitetty shakkipelin tilanteen tallennukseen. Tässä on pelkkä lopputilanne, ei siirtoja. Alla on esitetty esimerkkitallennus ja sen jälkeen seuraa formaalimpi esitys siitä millainen tehtävän käyttämä rakenne on.
Esitetyn formaatin suunnitteluperiaatteina on sen luettavuus helposti ohjelman toimesta, mahdollisuus lisätä uusia lohkoja säilyttäen silti mahdollisuus lukea tietoa vanhoilla ohjelmilla sekä hyvä tilankäyttö. Tiedostossa on myös versionumero ja tunniste, joiden avulla voidaan estää tilanteet, joissa yritetään lukea vääräntyyppistä dataa.
Esimerkki
Tiedostossa ei ole rivinvaihtoja eikä kaksoispisteitä! Kuvassa teksti on vain jaettu lyhyempiin pätkiin esittämisen helpottamiseksi.
Yllä oleva tekstinä
SHAKKI1205072001CMT54Laurin revanssipeli, hyvin huonosti on taas menossa...PLR17M5MarkoKa4Ta6b3c3PLR13V5LAURIKd3Rf1END00
Tiedoston rakenne
Katsele tätä osiota lukiessasi samalla yllä olevaa kuvaa.
Tiedosto koostuu otsikosta ja joukosta lohkoja. Tarkemmin ilmaistuna sen rakenne on seuraava:
Header : 8 merkkiä teksti "SHAKKI" : 6 merkkiä versionumero : 2 merkkiä Päiväys : 8 merkkiä DDMMYYYY : 8 merkkiä (DD on päivä väliltä 01-31, MM on kuukausi väliltä 01-12, YYYY on vuosi) (1 - N) mitä tahansa lohkotyyppiä, kuitenkin niin että: * viimeinen on END-lohko * PLR lohkoja on tasan 2 kappaletta ja niillä on eri värit
Lohkot
Lohkojen rakenne on seuraava:
Tunniste : 3 merkkiä (esim CMT, PLR, END) datan pituus : 2 merkkiä (sisältää numeron) data : (datan pituus) merkkiä
Datan pituus kertoo lohkoon kuuluvien merkkien määrän poislukien tunnisteen ja datan-pituus-merkinnän itsensä viemät merkit. Toisin sanoen, numeron luettuaan voi huoletta lukea numeron kertoman määrän merkkejä.
Lohkojen kuvaukset
Kommenttilohko (tunniste CMT)
Kommenttilohko. Koko lohkon sisältö on merkkijono, joka kuvaa tallennettua tilannetta.
Pelaajalohko (tunniste PLR)
Pelaajalohko. Ehjässä tiedostossa näitä on aina kaksi kappaletta eri väreillä.
Pelaajan väri : 1 merkki (M tai V) Nimen pituus : 1 merkki (väliltä 1-9) Nimi : (nimen pituus) merkkiä Pelaajan nappulat shakkinotaatiolla : lohkon loppuun asti
Huom: Tiedoston avulla voidaan esittää myös shakkitehtäviä, joissa nappuloita voi olla mikä tahansa määrä mitä tahansa nappulatyyppiä. Sinun ei siis tarvitse pohtia shakin nappuloiden määriä tai voiko johonkin tilanteeseen päästä.
Shakkinotaatio:
Shakkilaudan koko on 8x8. Laudalla on 8 riviä jotka on numeroitu 1-8, sekä 8 saraketta jotka on merkitty pienin kirjaimin a-h. Laudan nurkat ovat siis paikoissa a1, a8, h1 ja h8.
Shakissa on 6 erilaista nappulaa (suluissa tehtävässä käytetty suomalainen lyhenne, jota käytämme tallennuksessa):
- Kuningas/King (K)
- Kuningatar/Queen (D)
- Torni/Rook (T)
- Lähetti/Bishop (L)
- Ratsu/Knight (R)
- Sotilas/Pawn ().
Jos halutaan merkitä, että kuningas on ruudussa a3, kirjoitetaan "Ka3". Torni ruudussa h8 merkittäisiin "Th8". Sotilaalla ei ole notaatiossa merkkiä, joten sotilas ruudussa b7 merkittäisiin "b7".
Nappuloiden paikat on tiedostossa lueteltu peräkkäin ilman erotinmerkkejä. Jos ensimmäinen merkki on välillä a-h, niin kuvattu merkki on sotilas, muuten merkki kertoo nappulan tyypin.
Lopetuslohko (tunniste END)
Lopetuslohko. End-lohkon koko on aina 00, ja se lopettaa tiedoston, joten end-lohkon luettuaan tiedoston voi sulkea.
Muut lohkot (tuntematon tunniste *** sisältäen mitkä tahansa kolme merkkiä)
Tuntemattomat lohkot ovat todennäköisesti formaattiin uudemmissa versioissa lisättyjä ominaisuuksia. Näistä luetaan vain lohkon koko ja ohitetaan merkit skip-komennolla.
Tehtävänanto
Toteuta objektiin game.ChunkIO
pyydetty metodi
def load_game(self, input)
Luo uuden Game-olion, jonka se metodin päätteeksi palauttaa. Metodi lukee pelin pelaajat ja nappuloiden sijainnin käyttäen apuna muita tiedostossa määriteltyjä metodeja. Lopetuslohkon luettuaan palauttaa peliolion, jossa on tiedostossa annetut pelaajat ja lauta asetettuna. Kommenttilohko ja mahdolliset tuntemattomat lohkot metodin tulee ohittaa. Kun toivottavasti tesataat ohjelmaasi, luo ja sulje tietovirta testiluokassasi, ei tässä metodissa.
Jos luettavassa tiedostossa on jotain pielessä, metodin tulee heittää poikkeus
CorruptedChessFileException
. Annettu tehtäväpohja heittää jo tällaisen poikkeuksen tilanteessa, jossa tietovirran luvussa on jokin ongelma. Sinun pitäisi heittää sellainen, jos luetun tiedon rakenteessa on jokin ongelma. Tällaisia ovat esim. puuttuva lopetuslohko, poikkeava määrä pelaajalohkoja, pelilaudalla päällekkäin olevat nappulat jne...
Valmiiksi annettu koodi
- board.py. (Ei palauteta)
- Hyvin yksinkertainen luokka joka kuvaa pelilautaa. Mahdollistaa nappuloiden sijoittamisen laudalle ja laudan ruutujen tarkastelun. Sisältää apumetodin sarakekirjainten muuntamiseen ruudukon indekseiksi.
- player.py. (Ei palauteta)
- Hyvin yksinkertainen luokka joka kuvaa pelaajaa. Mahdollistaa nimen ja pelaajan värin asettamisen ja näiden attribuuttien lukemisen.
- game.py. (Ei palauteta)
- Hyvin yksinkertainen luokka joka koostaa pelissä tarvitut luokat yhteen. Mahdollistaa pelaajien ja pelilaudan asettamisen ja hakemisen.
- piece.py. (Ei palauteta)
- Hyvin yksinkertainen luokka joka kuva shakkinappulaa. Shakkinappulalla on omistaja (pelaaja) sekä tyyppi (Kuningas, Ratsu, jne...)
- corrupted_chess_file_error.py. (Ei palauteta)
- Poikkeusluokka tiedostonluvussa esiintyvien ongelmien esittämiseen.
- broken_reader.py. (Ei palauteta)
- Apuluokka virhetilanteiden testaamiseen.
- chunkIO.py. Palautetaan
- Apuluokka jonka avulla voidaan ladata ja tallentaa(ei tässä harjoituksessa) pelitilanne tiedostosta. Toteuta luokkaan vaadittujen metodien lisäksi halutessasi myös apumetodeja. Esimerkiksi eri tyyppisten lohkojen lukemiseen voi olla kätevää tehdä omat metodit. test.py Palautetaan
- test.py. Palautetaan
- Testitiedoston pohja. Testiluokan nimen tulee olla Test jotta A+ tunnistaa sen. Eli Test tiedostossa test.py.
Testien kuvaukset
Tässä on kuvattu tehtävässä käytetty testidata. Voitte muokata tämän perusteella itsellenne testit, jotta pääsette debuggaamaan.
Given Example
SHAKKI1205072001CMT54Laurin revanssipeli, hyvin huonosti on taas menossa...PLR17M5MarkoKa4b3Ta6c3PLR13V5LauriKd3Rf1END00
Another Test
Pelaajien nimet ja kommenttilohkon sisältö ovat kummallisia, mutta herrojen PLR ja CMTEND pelissä ei ole mitään muuta kummallista.
SHAKKI1225072008CMT12PLRENDENDCMTPLR15M3PLRRh4e3Lb6c3PLR11V6CMTENDKa1END00
Unknown Chunks
Tehtävänannon mukaisesti tiedostossa saa olla tuntemattomia lohkoja kuten 'BAT101234567890' ja 'HUH00'. Nämä täytyy vain ohittaa ottamatta niihin kantaa.
SHAKKI1205072001BAT101234567890CMT54Laurin revanssipeli, hyvin huonosti on taas menossa...PLR17M5MarkoKa4b3Ta6c3HUH00PLR13V5LauriKd3Rf1END00
Broken file
Suurin osa testeistä menee läpi itsestään, vain nappuloiden nimet ja sijainti voivat olla väärin tai toisen pelaajan nappulat puuttua.
- Testataan rikkinäinen tiedostoheader (menee läpi jo valmiilla tehtäväpohjalla)
- Testataan tiedoston äkillinen päättyminen (Ei tarvitse tarkastella - menee läpi kunhan et kaappaa IO-poikkeuksia, vaan annat sen muuttua päämetodissa CorruptedChessFileExceptioniksi)
- Testataan kuvitteelinen nappi 'Ha1'
- Testataan kuvitteellinen sijainti 'x1'
- Testataan toisen PLR-lohkon puuttuminen kokonaan
- Testataan END:in puuttuminen (menee läpi tekemättä muutoksia kuten äkillinen päättyminen). Seuraavaa lohkoa luettaessa syntyy IOException -> CorruptedChessFileException.
- Testataan lopuksi vielä että ehjä tiedosto menee myös läpi
Tyypillisimmät koodausvirheet
- On oletettu jokin järjestys lohkoille (musta tai valkoinen ensin, CMT-lohko alussa tai lopussa jne.) Huomaa, että ainoastaan END-lohkon sijainti on speksattu.
- Käytetään luettuja merkkejä suoraan indekseinä (ei muunneta kirjaimia '5', 'a' numeroiksi). Kts. Board-luokan apumetodit, getChunkSize
- Unohdetaan lukea seuraava chunkHeader
- Unohdetaan ohittaa tuntemattomat lohkot (luetaan vain header)
- Unohdetaan luoda pelilauta tai asettaa se peliin.
- Luodaan yksi pelaaja laudalle ja toinen samanniminen joka merkitään nappuloihin
Ohjeita
Lue molemmat PyUnit-ohjeet, mikäli et vielä ole lukenut niitä. Halutessasi tee Eclipseen projekti jossa PyUnit:ia on helppo suorittaa.
Tehtävänanto löytyy A+:sta.