\documentclass[a4paper,10pt]{article}
\usepackage{amsmath}                    % Lisäyksiä LaTeXin matematiikkatukeen
%\usepackage{SIunits}                   % Tuki SI-yksiköille (esim. \meter\per\second)
\usepackage[latin1]{inputenc}           % Ääkköstuki
%\usepackage{color}                     % Tuki väritetylle tekstille
\usepackage{array}
% \usepackage{multirow}                   % Tuki useita rivejä kattaville taulukkoelementeille
\usepackage[T1]{fontenc}
\usepackage[finnish]{babel}             % Suomenkielinen lokalisaatio
\usepackage{graphicx}                   % Tuki EPS-kuville

% ---
% Tästä voit muokata sivun marginaaleja.
% ---
\addtolength{\evensidemargin}{-1cm}
\addtolength{\oddsidemargin}{-1cm}
\addtolength{\textwidth}{2cm}
\addtolength{\topmargin}{-0.5in}
\addtolength{\textheight}{0.5in}
\setlength{\parindent}{0in}             % Kappaleiden sisennys pois päältä
\setlength{\parskip}{4pt plus 4pt minus 2pt}               % Tyhjää tilaa kappaleiden välillä

% ---
% Ohjeita LaTeXin käyttöön esimerkiksi täältä: http://www.andy-roberts.net/misc/latex/
% LaTeX-editoreja: http://en.wikipedia.org/wiki/LaTeX#Editors_and_IDEs
% ---

\begin{document}
\emergencystretch=16pt
% \hyphenation{}
% \overfullrule=5pt

% ---
% Otsikkosivu. Tämä olisi kiva toteuttaa käyttäen hyväksi LaTeXin ohjelmoitavuutta.
% ---

\begin{center}
Tampereen teknillinen yliopisto

Ohjelmistotekniikan laitos
\vspace{4cm}

\rule{4.5in}{0.4mm}

\begin{Huge}
OHJ-1151

Ohjelmointi IIe
\end{Huge}

\vspace{0.4cm}
\begin{Large}
Harjoitustyö

\vspace{-2mm}
Pirates of Kaukajärvi\\ -\\ Väitelleen miehen kirstu

\vspace{-1mm}
Välipalautus %Poista tarpeeton
\end{Large}
\rule{4.5in}{0.4mm}

\vspace{4cm}
Jyri Vuorinen

10.4.2008 14:20 TB208
\end{center}

\vfill
Petteri Aimonen (205441)

\vspace{-2mm}
aimonen

\vspace{-2mm}
petteri.aimonen@tut.fi
\newpage

\tableofcontents

\newpage

% -----------------------
% Kappaleet alkavat tästä
% -----------------------

% ---
% Esimerkki EPS-muotoon tallennetun UML-kaavion liittämisestä dokumenttiin.
% Huomaa, että EPS-kuvia käytettäessä suora käännös PDF-muotoon 'pdflatex':lla
% ei onnistu (ainakaan ilman kikkailua). Käännös tulee suorittaa ensin DVI-muotoon,
% mistä edelleen PDF:ksi. Muita kuvamuotoja käytettäessä tilanne on ymmärtääkseni
% päinvastainen, eli ainoastaan 'pdflatex' toimii.
% ---
%\section*{UML-kaavio}
%\begin{center}
%\includegraphics[scale=0.6, trim = 0 0 0 0, clip]{classes2}
%\end{center}

\section{Ohjelman rakenne}

\subsection{Ohjelman tietorakenteet}
Pelitilanne sisältyy HakkeriPeli-olioon, josta tarkempi selostus alempana. Luokassa
on tallennettuna vektoriin Hakkeri-oliot. Pelissä käytetään hakkerien tunnisteina
niiden indeksiä tässä vektorissa.

Vuoroihin liittyvä rakenne HakkeriRyhma:ssa, Hakkerin reitityskohteet yms. on
toteutettu pakkana (deque). Tällöin on mahdollista siirtää ensimmäinen alkio
viimeiseksi. Vuoron hallinta on siten helppoa, kun aina käytetään vuorona
ensimmäistä alkiota. Tilanteen tulostusta varten lajitellaan pakan kopion alkiot
tunnistenumeron perusteella, jolloin saadaan alkuperäinen asetustiedostojen järjestys.

Hakkeriryhmien tiedot on tallennettu structeina pakkaan. Tehtävänannon pelissä
hakkeriryhmiä on aina kaksi, mutta toteutuksen kannalta ei ole tarpeellista rajoittaa
määrää tähän. Tietueita luotaessa on pidettävä huolta, että kukin hakkeri kuuluu
vain yhteen hakkeriryhmään.

\begin{verbatim}
struct HakkeriRyhma {
    int tunniste; // Alkuperäinen ryhmän paikka, 1 tai 2.
    std::string nimi; // Hakkeriryhmän nimi (voi sisältää välilyöntejä yms.)
    std::deque<int> hakkerit; // Ryhmän hakkerien tunnisteet. Pakkaa
        // pyöritetään siten, että seuraavana/tällä hetkellä vuorossa oleva
        // hakkeri on aina listan ensimmäisenä. Tosin vuoron vaihtuessa on
        // tehtävä tarkistus siltä varalta, että ensimmäinen hakkeri onkin
        // nyt OFFLINE-tilassa.
};
\end{verbatim}

Pelin siirrot tallennetaan structiin, jossa on siirron tyyppi enumina ja siirtoon
liittyvien hakkerien tunnisteet. Structin kenttien käyttö riippuu siirtotyypistä.
Tämä struct voidaan välittää parametrina mm. siirron oikeellisuuden tarkistusta varten.
\begin{verbatim}
enum SiirtoTyyppi {KOODAA, PUSKUROI, REITITA, RESETOI, HYOKKAA, TANKKAA,
                   ODOTA};

struct Siirto {
    SiirtoTyyppi tyyppi; // Siirron tyyppi - määrää muiden kenttien käytön
    int tekija; // Siirron suorittavan hakkerin tunniste.
    
    int maara; // KOODAA: maara on koodattavan viruksen taso.
               // PUSKUROI: maara on puskuroitavien virusten määrä.
               // REITITA: maara on reititettävien virusten määrä,
               //          ei välttämättä sama kuin reitityskohteiden määrä.
               // RESETOI: kenttä ei ole käytössä.
               // HYOKKAA: kenttä ei ole käytössä.
               // TANKKAA: tankattavan kolan määrä.
               // ODOTA: kenttä ei ole käytössä.
    
    int kohde; // Vain HYOKKAA-komennossa, jossa hyökkäyksen kohteena olevan
               // hakkerin tunniste.
    
    std::deque<int> reitityskohteet; // Vain REITITA-komennossa, jossa
                                     // pakka annetuista reitityskohteista.
};
\end{verbatim}

\subsection{Ohjelman suoritus}
\includegraphics[scale=0.7]{kaavio.eps}

\section{Moduulit}

\subsection{Pääohjelma}
\subsubsection{Apufunktio: tulkitseParametrit}
Tulkitsee parametrit ja toteuttaa ne.

{\em Esittely:}\\
{\tt bool tulkitseParametrit(int argc, char *argv[], HakkeriPeli \&hakkeripeli,\\
int \&lopetusarvo);}

{\em Parametrit:}\\
Parametrit {\bf argc} ja {\bf argv} ovat main-funktiolta saadut komentoriviparametrit C-taulukkona.\\
Parametri {\bf hakkeripeli} on viite HakkeriPeli-olioon, johon parametreista tulkitut asetustiedostot ladataan.\\
Parametri {\bf lopetusarvo} on viite, jonka kautta ohjelman lopetusarvo tallennetaan. Ei käytetä jos palautetaan true.

{\em Paluuarvo:}\\
True, jos peli käynnistyy normaalisti. Virheiden tapauksessa ne tulostetaan
hakkeripelin virhevirtaan ja palautetaan false, sekä asetetaan lopetusarvoksi EXIT\_FAILURE.
Ohjetekstin tapauksessa tulostetaan se, asetetaan lopetusarvoksi EXIT\_SUCCESS ja palautetaan false.

{\em Toiminta:}\\
Käydään parametrit järjestyksessä läpi. Jos parametri on -a, -1 tai -2, seuraava
on sille annettu tiedostonimi. Tiedostonimet tallennetaan väliaikaismuuttujiin.

Jos parametri on -h tai --help, tulostetaan ohjeteksti, asetetaan lopetusarvo ja palautetaan false.

Ellei parametria tunnisteta, tulostetaan ``Virhe: Virheelliset komentoriviparametrit.'',
asetetaan lopetusarvo ja palautetaan false. Jos jotain tiedostonimeä ei ole annettu, toimitaan vastaavasti.

Lopuksi yritetään avata parametreina saadut tiedostot ja lukea ne HakkeriPeli-olion
jäsenfunktioiden kautta.
Mahdollisia ovat virheet ``Virhe: Asetustiedoston {\em tiedoston nimi} avaaminen ei onnistunut.'' ja
``Virhe: Virheellinen asetustiedosto: {\em tiedoston nimi}.'' Näissä toimitaan vastaavasti kuin ylläolevassa
virhetilanteessa.

{\em Käyttö:}\\
Pääohjelma kutsuu tätä funktiota.

\subsubsection{Funktio: main}
{\em Toiminta:}\\
Luodaan uusi HakkeriPeli-olio. Kutsutaan tulkitseParametrit-apufunktiota.
Jos se palauttaa falsen, lopetetaan ohjelma funktiolta saadulla paluuarvolla.

Muutoin siirrytään pääsilmukkaan. Tulostetaan HakkeriPeliltä saatu vuorossa
olevan hakkerin nimi kehotteeksi ja luetaan {\tt std::getline}:lla yksi rivi.
Mikäli rivi alkaa risuaidalla, luetaan uusi rivi.
Välitetään luettu rivi komentotulkin toteutaRivi-funktiolle. Silmukka päättyy
kun toteutaRivi palauttaa falsen tai rivin lukeminen epäonnistuu.

Jos komennon jälkeen HakkeriPelin {\tt peliLoppu}-jäsenfunktio palauttaa
{\bf true}:n, tulostetaan voittaja ja tilanne.

Lopetetaan paluuarvolla EXIT\_SUCCESS.

\subsection{Moduuli: Komentotulkki}
Komentotulkki hoitaa komentojen tulkitsemisen ja osittain suorittamisen.

Tässä moduulissa on määritelty tietotyypit ja olemassaolevat komennot:
\begin{verbatim}
enum Toiminto {VIRHE, SIIRTO, TILANNE, TIEDOT, OHJE, LOPETUS};

struct Komento {
    std::string komento;
    Toiminto toiminto;
    SiirtoTyyppi siirtotyyppi; // Vain jos toiminto == SIIRTO
    int parametreja_enintaan; // Jos == -1, tarkistus ei käytössä
    int parametreja_vahintaan; // Jos == -1, tarkistus ei käytössä
};

const Komento KOMENNOT[] = {{"LOPETA", LOPETUS, 0, 0, 0}, ...};
\end{verbatim}

\subsubsection{Funktio: toteutaRivi}
Toteuttaa rivin tai tulostaa virheen. Palauttaa false, jos käyttäjä haluaa
lopettaa.

{\em Esittely:}\\
{\tt bool toteutaRivi(std::string rivi, HakkeriPeli \&hakkeripeli);}

{\em Parametrit:}\\
Parametri {\bf rivi} on käyttäjältä luettu kokonainen rivi.\\
Parametri {\bf hakkeripeli} on viite HakkeriPeli-olioon, johon komento toteutetaan.

{\em Paluuarvo:}\\
False jos komento oli lopetuskomento.

{\em Toiminta:}\\
Rivistä luodaan {\tt std::istringstream}, josta luetaan rivin ensimmäinen
sana eli komento. Jos komento on tyhjä (tarkoittaa että rivillä on vain tyhjää
tilaa) palautetaan {\bf true} tulostamatta mitään. Muutoin komento välitetään tulkitseKomento-funktiolle.

Jos tämä palauttaa komennon tyyppinä VIRHE, tulostetaan ``Virhe: Tuntematon komento.''
hakkeripelin virhevirran kautta ja palautetaan {\bf true}, sillä peli jatkuu
virheellisestä komennosta huolimatta.

Parametrit luetaan yksi kerrallaan virrasta vektoriin. Niiden määrää verrataan
komennon {\tt parametreja\_enintaan}- ja {\tt parametreja\_vahintaan}-kenttiin. Virheistä
tulostetaan joko ``Virhe: Liikaa parametreja.'' tai ``Virhe: Liian vähän parametreja.'' ja
palautetaan {\bf true}.

Jos komennon tyyppi on LOPETUS tai OHJE, nämä toteutetaan suoraan tässä funktiossa.
Komento LOPETUS aiheuttaa {\bf false}:n palauttamisen.
Muutoin välitetään komento, parametrivektori ja viite HakkeriPeli-olioon
toteutaKomento-funktiolle. Palautetaan {\bf true}, vaikka komennon toteutuksessa
olisi virhe.

{\em Käyttö:}\\
Pääohjelma kutsuu tätä luettuaan käyttäjältä rivin.

\subsubsection{Funktio: toteutaKomento}
Toteuttaa tulkitun komennon HakkeriPeli-olioon. Tulostaa virheen jos parametrina
on olematon hakkeri tai siirrossa on virhe.

{\em Esittely:}\\
{\tt bool toteutaKomento(const Komento \&komento,\\
const std::vector<std::string> \&parametrit, HakkeriPeli \&hakkeripeli);}

{\em Parametrit:}\\
Parametri {\bf komento} on tulkittu Komento-tietorakenne.\\
Parametri {\bf parametrit} on vektori komennolle annetuista parametreista.\\
Parametri {\bf hakkeripeli} on viite HakkeriPeli-olioon, johon komento toteutetaan.

{\em Paluuarvo:}\\
True, jos komennossa ei ollut virheitä.

{\em Toiminta:}\\
Jos komennon tyyppi on TILANNE tai TIEDOT, kutsutaan hakkeripelin vastaavaa
jäsenfunktiota. TIEDOT-komentoa varten tulkitaan ensimmäinen parametri
hakkerin nimeksi tai tulostetaan virhe jos hakkeria ei löydy.

Muutoin komennon tyypin pitäisi olla SIIRTO. Siirtotyypin perusteella
tulkitaan parametrit Siirto-tietorakenteeseen ja kutsutaan HakkeriPelin
tarkistaSiirto-jäsenfunktiota. Jos se palauttaa {\bf false}:n, tieto virheestä
on jo tulostettu, eli palautetaan vain {\bf false}.

Muutoin suoritetaan siirto HakkeriPelin suoritaSiirto-jäsenfunktiolla ja
palautetaan {\bf true}.

{\em Käyttö:}\\
Funktio toteutaRivi käyttää tätä funktiota.

\subsubsection{Funktio: tulkitseKomento}
Etsii annettua komentoa vastaavan toiminnon. Osittaiset komennot käyvät,
kunhan vastaavuuksia ei ole useita.

{\em Esittely:}\\
{\tt Komento tulkitseKomento(const std::string \&annettu);}

{\em Parametrit:}\\
Parametri {\bf annettu} on käyttäjän antama komento.

{\em Paluuarvo:}\\
Komento-tietorakenne. Jos vastaavuuksia ei ollut tai niitä oli useita,
komennon tyyppi on VIRHE.

{\em Toiminta:}\\
Käydään KOMENNOT-vakiotaulukko järjestyksessä läpi. Komentoja verrataan
funktiolla vertaaKomento ja lasketaan vastaavuudet.
Jos vastaavuuksia on tasan yksi, palautetaan se. Muutoin palautetaan rakenne,
jossa on komennontyyppinä VIRHE.

{\em Käyttö:}\\
Funktio toteutaRivi tulkitsee tämän funktion avulla käyttäjän antaman komennon.

\subsubsection{Funktio: vertaaKomento}
Vertaa annettua komentoa kokonaiseen komentoon. Ei välitä kirjainkoosta.

{\em Esittely:}\\
{\tt bool vertaaKomento(const std::string \&annettu, const std::string \&kokonainen);}

{\em Parametrit:}\\
Parametri {\bf annettu} on käyttäjän antama komento.\\
Parametri {\bf kokonainen} on taulukosta otettu kokonainen komento.

{\em Paluuarvo:}\\
True, jos annettu komento on kirjainkokoriippumattomasti kokonaisen komennon
alkuosa.

{\em Toiminta:}\\
Aluksi verrataan komentojen pituuksia. Jos annettu komento on kokonaista pidempi,
palautetaan suoraan {\bf false}.

Seuraavaksi verrataan merkkijonoja kirjainkokoriippumattomasti merkki kerrallaan,
kunnes annettu merkkijono loppuu. Eroavaisuuden löytyessä palautetaan heti {\bf false}.
Muutoin palautetaan {\bf true}.

{\em Käyttö:}\\
Funktio tulkitseKomento käyttää tätä vastaavuuksien etsinnässä.

\subsection{Luokka: HakkeriPeli}
HakkeriPeli-luokka sisältää pelitilanteen, mukaanlukien pelissä olevat
hakkerit ja hakkeriryhmät. Lisäksi muut moduulit tulostavat ilmoituksensa
tämän luokan kautta, jolloin tulostus- ja virhevirrat voidaan tarvittaessa
vaihtaa.

\subsubsection{Jäsenmuuttujat}
\begin{verbatim}
// Tulostus- ja virhevirta
std::ostream &tulostusvirta_;
std::ostream &virhevirta_;

// Pelissä olevat hakkerit. Sijaintia vektorissa käytetään hakkerin
// tunnisteena.
std::vector<Hakkeri> hakkerit_;

// Pelissä olevat hakkeriryhmät. Nyt vuorossa oleva on pakassa ensimmäisenä.
std::deque<HakkeriRyhma> hakkeriryhmat_;

// Toimintojen kulutustiedot jotka on luettu yleisasetustiedostosta.
int koodauskulutus_;
int reitityskulutus_;
int puskurointikulutus_;
int tankkauskulutus_;

// Kullekin hakkeriryhmälle jaettavaksi jäävä kola/hermovarasto. Luetaan
// yleisasetustiedostosta.
int ryhmanvarastot_;

// Kolavaraston uusiutumisnopeus prosentteina, yleisasetustiedostosta.
int kolauusiutuminen_;
\end{verbatim}

\subsubsection{Yksinkertaiset jäsenfunktiot}
Tässä pelkkä lista jäsenfunktioista, joiden toteutuksessa ei ole mitään ihmeellistä:
\begin{verbatim}
// Tulostus- tai virhevirran hakeminen, pelin muut osat käyttävät tätä
// tulostuksissaan.
std::ostream &haeTulostusVirta() const;
std::ostream &haeVirheVirta() const;

// Yleisasetustiedoston tietojen hakeminen
int haeKoodausKulutus() const;
int haeReititysKulutus() const;
int haePuskurointiKulutus() const;
int haeTankkausKulutus() const;
int haeKolaUusiutuminen() const;

// Palauttaa vuorossa olevan hakkerin tunnisteen, eli hakkeriryhmat_-pakassa
// ensimmäisen hakkeriryhmän hakkerit-pakan ensimmäisen alkion.
int haeVuoro() const;

// Palauttaa tunnisteen määräämän hakkerin nimen
const std::string &haeHakkerinNimi(int tunniste) const;

// Kutsuu kyseisen hakkerin tulostaTiedot-jäsenfunktiota
void tulostaHakkerinTiedot(int tunniste) const;

// Kutsuu tekijänä olevan hakkerin tarkistaSiirto-jäsenfunktiota
bool tarkistaSiirto(const Siirto &siirto) const;
\end{verbatim}

\subsubsection{Rakentaja}
Rakentaja alustaa jäsenmuuttujat oletusarvoihin. Todelliset arvot luetaan
myöhemmin asetustiedostoista.

{\em Esittely:}\\
{\tt HakkeriPeli();}

{\em Jäsenmuuttujien alustus:}\\
Rakentajan alustuslista:
\begin{verbatim}
tulostusvirta_(std::cout),
virhevirta_(std::cerr),
hakkerit_(),
hakkeriryhmat_(),
koodauskulutus_(1), // Yksinkertaiset oletusarvot testausta varten
reitityskulutus_(1),
puskurointikulutus_(1),
tankkauskulutus_(1),
ryhmanvarastot_(1000),
kolauusiutuminen_(10)
\end{verbatim}

\subsubsection{Julkinen jäsenfunktio: etsiHakkeri}
Etsii hakkerin tunnistenumeron sen nimen perusteella.

{\em Esittely:}\\
{\tt int etsiHakkeri(const std::string \&nimi) const;}

{\em Parametrit:}\\
Parametri {\bf nimi} on etsittävän hakkerin nimi.

{\em Paluuarvo:}\\
Etsityn hakkerin tunnistenumero, tai {\bf -1} jos määrätyn nimistä hakkeria
ei löytynyt.

{\em Toiminta:}\\
Käydään hakkerit järjestyksessä läpi ja verrataan nimiä kirjainkoosta välittämättä.

{\em Käyttö:}\\
Käytetään komentojen parametreina annettujen hakkerinimien tulkintaan, sekä
sen tarkistamiseen, onko kyseinen nimi jo käytössä.

\subsubsection{Julkinen jäsenfunktio: lahetaVirus}
Lähettää viruksen jollekin hakkerille.

{\em Esittely:}\\
{\tt void lahetaVirus(int kohde, int taso);}

{\em Parametrit:}\\
Parametri {\bf kohde} on kohteena olevan hakkerin tunniste.\\
Parametri {\bf taso} on lähetettävän viruksen taso.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Kutsutaan kohteena olevan hakkerin otaVirus-jäsenfunktiota.

{\em Käyttö:}\\
Hakkerit kutsuvat tätä virusten lähettämiseksi toisilleen.

\subsubsection{Julkinen jäsenfunktio: lueYleisasetukset}
Lukee parametrina annetusta virrasta yleisasetukset olion jäsenmuuttujiin.

{\em Esittely:}\\
{\tt bool lueYleisasetukset(std::istream \&virta);}

{\em Parametrit:}\\
Parametri {\bf virta} on viite virtaan, josta asetukset luetaan.

{\em Paluuarvo:}\\
True, jos lukeminen onnistui. False, jos asetustiedostossa oli virhe.
Virheen jälkeen osa asetuksista voi olla uusia ja osa vanhoja.

{\em Toiminta:}\\
Luetaan virran {\tt $>>$}-operaattorilla seuraavien jäsenmuuttujien sisältö:
{\tt koodauskulutus\_}, {\tt reitityskulutus\_}, {\tt puskurointikulutus\_},
{\tt tankkauskulutus\_}, {\tt ryhmanvarastot\_},\\{\tt kolauusiutuminen\_}.

Lopuksi tarkistetaan virran {\tt good}-jäsenfunktiolla, onnistuivatko edelliset
lukemiset. Elleivät, palautetaan {\bf false}. Muutoin tarkistetaan vielä,
että kaikki luetut arvot ovat nollaa suurempia.

{\em Käyttö:}\\
Pääohjelma kutsuu tätä funktiota komentoriviparametrin perusteella.

\subsubsection{Julkinen jäsenfunktio: lueHakkeriryhma}
Lukee yhden hakkeriryhmän asetustiedoston. Luettu hakkeriryhmä lisätään
pakan viimeiseksi.

{\em Esittely:}\\
{\tt bool lueHakkeriryhma(std::istream \&virta);}

{\em Parametrit:}\\
Parametri {\bf virta} on viite virtaan, josta hakkeriryhmän asetustiedosto luetaan.

{\em Paluuarvo:}\\
True, jos lukeminen onnistui. False, jos tiedostossa oli virhe. Virheen
tapahtuessa oliota ei pitäisi enää käyttää, sillä
{\tt hakkerit\_}-jäsenmuuttujaan jää hakkereita jotka eivät kuulu mihinkään
ryhmään.

{\em Toiminta:}\\
Luodaan paikalliseksi muuttujaksi uusi HakkeriRyhma-tietorakenne. Luetaan
virrasta funktiolla {\tt std::getline} ensimmäinen rivi hakkeriryhmän nimeksi.
Osuuksien tarkkailua varten luodaan laskurimuuttuja, joka alustetaan nollaksi.

Luetaan sitten rivi kerrallaan tiedostoa silmukassa, joka päättyy lukemisen
epäonnistuessa. Luetusta rivistä luodaan {\tt std::istringstream}, josta ensin
luetaan hakkerin nimi. Jos nimi on tyhjä, tarkoittaa se ettei rivillä ole muita
merkkejä kuin tyhjää tilaa, joten rivi jätetään välistä. Muutoin tarkistetaan
{\tt etsiHakkeri}-jäsenfunktion kautta, onko nimi jo käytössä. Jos on, palautetaan
{\bf false}.

Seuraavaksi luetaan rivistä luodusta virrasta hakkerin varasto-osuus, hermosuhde
ja kolasuhde. Tarkistetaan että nämä ovat suurempia kuin nolla, muutoin palautetaan
heti {\bf false}. Varasto-osuus lisätään laskurimuuttujaan. Lasketaan näistä
hakkerin hermo- ja kolavarastojen koko seuraavasti:
\begin{verbatim}
// Samat kuin tehtävänannossa, mutta ensin suoritettavalla kertolaskulla
// vältetään liukulukujen käyttö.
kolavarastot = (ryhmanvarastot_ * varastoosuus * kolasuhde)
                / (100 * (hermosuhde + kolasuhde));
hermovarastot = (ryhmanvarastot_ * varastoosuus * hermosuhde)
                / (100 * (hermosuhde + kolasuhde));
\end{verbatim}

Jäsenmuuttujaan {\tt hakkerit\_} lisätään uusi Hakkeri-olio, jonka rakentajalle
välitetään osoitin tähän HakkeriPeli-olioon, ryhmän nimi, hakkerin nimi sekä
lasketut varastojen koot. Uuden hakkerin tunniste saadaan {\tt hakkerit\_}-vektorin
koosta, ja lisätään HakkeriRyhman {\tt hakkerit}-pakan loppuun.

Silmukan jälkeen tarkistetaan, ettei laskurimuuttujan arvo ylitä 100:aa.
Lisätään hakkeriryhmä {\tt hakkeriryhmat\_}-pakkaan ja palautetaan {\bf true}.

{\em Käyttö:}\\
Pääohjelma tätä kummallekin komentorivillä annetulle
ryhmätiedostolle.

\subsubsection{Julkinen jäsenfunktio: peliLoppu}
Palauttaa tiedon siitä, onko peli loppunut. Funktion toteutus on tarkoitettu
kahden pelaajan peliin.

{\em Esittely:}\\
{\tt bool peliLoppu() const;}\\
{\tt bool peliLoppu(std::string \&voittaja);}

{\em Parametrit:}\\
Valinnainen parametri {\bf voittaja} on viite, jonka kautta voittaneen
hakkeriryhmän nimi tallennetaan.

{\em Paluuarvo:}\\
True, jos peli on loppu ja false muutoin.

{\em Toiminta:}\\
Käydään hakkeriryhmät järjestyksessä läpi, ja varmistetaan että jokaisessa
ryhmässä on ainakin yksi hakkeri, jonka online() palauttaa {\bf true}:n. Jos
löytyy ryhmä, jossa näin ei ole, palautetaan {\bf true}. Jos viite on annettu,
tallennetaan ensin voittaneen ryhmän nimi.

Muutoin palautetaan {\bf false}.

{\em Käyttö:}\\
Jäsenfunktio suoritaSiirto kutsuu tätä siirron jälkeen. Pääohjelma
tarkistaa tällä pelin loppumisen.

\subsubsection{Julkinen jäsenfunktio: suoritaSiirto}
Suorittaa siirron ja tulostaa siirtoon liittyvät ilmoitukset. Vaihtaa
vuoron tarvittaessa.

{\em Esittely:}\\
{\tt bool suoritaSiirto(const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf siirto} on suoritettava siirto.

{\em Paluuarvo:}\\
False, jos peli loppuu. Muutoin true.

{\em Toiminta:}\\
Siirto oletetaan kelvolliseksi. Tekijänä olevan hakkerin vastaavaa jäsenfunktiota
kutsutaan.

Tarkistetaan jäsenfunktiolla peliLoppu onko peli loppunut, ja palautetaan {\bf false}
jos näin on.

Jos hakkerin suoritaSiirto palautti falsen eli vuoron pitäisi vaihtua,
siirretään aluksi {\tt hakkeriryhmat\_}-pakan ensimmäisen alkion {\tt hakkerit}-kentän
ensimmäinen alkio viimeiseksi, eli vaihdetaan ryhmän sisällä seuraavaksi vuoroon tulevaa.

Sitten siirretään jäsenmuuttujan {\tt hakkeriryhmat\_} ensimmäinen alkio viimeiseksi,
eli vaihdetaan vuorossa olevaa hakkeriryhmää. Jos uuden ryhmän ensimmäinen hakkeri on
menettänyt hermonsa, pyöritetään pakkaa kunnes löytyy hakkeri, joka ei ole menettänyt
hermojaan. Tällainen hakkeri pitäisi löytyä, sillä aiemmin on tarkistettu ettei peli ole loppunut.

Lopuksi kutsutaan uuden ensimmäisenä olevan ryhmän ensimmäisen hakkerin aloitaVuoro-jäsenfunktiota.
Palautetaan {\bf true}.

{\em Käyttö:}\\
Komentotulkki kutsuu tätä käyttäjän syöttäessä siirtoa tarkoittavan komennon.

\subsubsection{Julkinen jäsenfunktio: tulostaTilanne}

{\em Esittely:}\\
{\tt void tulostaTilanne();}

{\em Parametrit:}\\
Ei parametreja.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Jäsenmuuttujan {\tt hakkeriryhmat\_} pakasta otetaan kopio, joka lajitellaan
HakkeriRyhma-rakenteiden {\tt tunniste}-kentän perusteella, jolloin saadaan
alkuperäinen järjestys.

Kopio käydään järjestyksessä läpi, ja jokaisen ryhmän sisältämä
{\tt hakkerit}-pakka lajitellaan. Tämä pakka sisältää hakkerien tunnisteita,
joten lajittelun jälkeen ne ovat samassa järjestyksessä kuin ne on tiedostosta
luettu.

Ryhmän nimi tulostetaan, ja sen jälkeen kutsutaan järjestyksessä kaikkien
ryhmän hakkerien tulostaTilanne-jäsenfunktioita. Kunkin ryhmän jälkeen
tulostetaan tyhjä rivi.

{\em Käyttö:}\\
Komentotulkki kutsuu tätä TILANNE-komennon yhteydessä.

\subsection{Luokka: Hakkeri}
Yksittäinen hakkeri. Pitää kirjaa hakkerin hermoista ja kolavarannosta. Sisältää
viitteen HakkeriPeli-olioon, johon kuuluu. Tulostaa tarpeelliset ilmoitukset
HakkeriPeli-olion kautta.

Sisältää HakkeriTila-tyypin:
\begin{verbatim}
enum HakkeriTila {PERUS, HYOKKAYS, REITITYS, PUSKUROINTI, OFFLINE};
\end{verbatim}

\subsubsection{Jäsenmuuttujat}
\begin{verbatim}
// Osoitin HakkeriPeli-olioon, johon tämä hakkeri kuuluu. Käytetään virusten
// lähettämiseen takaisin ja asetusten hakemiseen.
// Tämä on osoitin viitteen sijasta jotta olion sijoitusfunktio toimii. Tämä
// puolestaan on tarpeen, jotta HakkeriPeli voi pitää hakkerit vektorissa.
const HakkeriPeli *hakkeripeli_;

// Hakkeriryhmän nimi ilmoitusten tulostamista varten.
std::string ryhmannimi_;

std::string nimi_; // Hakkerin nimi.
HakkeriTila tila_; // Hakkerin tila.

// Hakkerin hallussa olevan viruksen taso. Arvoltaan 0 jos hakkerilla ei ole
// virusta.
int virustaso_; 

// Hakkerit, joille viruksia reititetään. Pyöritetään siten, että seuraava
// reitityskohde on aina ensimmäisenä. Vain REITITYS-tilassa.
std::deque<int> reitityskohteet_; 

// Jäljellä olevien toimintokertojen määrä. Vain REITITYS- ja
// PUSKUROINTI-tiloissa.
int maara_;

int kola_; // Pitää kirjaa hakkerin kolavarannoista.
int hermot_; // Pitää kirjaa hakkerin hermoista.
int maxkola_; // Hakkerin kolavarastojen maksimikoko (alkukoko).
int maxhermot_; // Vastaavasti hermojen maksimiarvo.
\end{verbatim}

\subsubsection{Yksinkertaiset jäsenfunktiot}
Tässä pelkkä lista jäsenfunktioista, joiden toteutuksessa ei ole mitään ihmeellistä:
\begin{verbatim}
const std::string &haeNimi() const; // Palauttaa hakkerin nimen
bool online() const; // Onko hakkerin tila jokin muu kuin OFFLINE?

// Lisäksi automaattisesti tuotetut kopiorakentaja ja sijoitusoperaattori.
\end{verbatim}

\subsubsection{Rakentaja, parametrina asetustiedostosta lasketut tiedot}
{\em Esittely:}\\
{\tt Hakkeri(const HakkeriPeli *hakkeripeli, const std::string \&ryhmannimi,
const std::string \&nimi, int maxkola, int maxhermot);}

{\em Parametrit:}\\
Parametri {\bf hakkeripeli} on osoitin siihen HakkeriPeli-olioon, johon tämä hakkeri kuuluu.\\
Parametri {\bf ryhmannimi} on hakkeriryhmän nimi.\\
Parametri {\bf nimi} on hakkerin nimi.\\
Parametri {\bf maxkola} on hakkerin kolavarastojen suurin koko ja samalla alkukoko.\\
Parametri {\bf maxhermot} on vastaavasti hakkerin hermojen määrä.

{\em Jäsenmuuttujien alustus:}\\
Rakentajan alustuslista:
\begin{verbatim}
hakkeripeli_(hakkeripeli),
ryhmannimi_(ryhmannimi),
nimi_(nimi),
tila_(PERUS),
virustaso_(0),
reitityskohteet_(),
maara_(0),
kola_(maxkola),
hermot_(maxhermot),
maxkola_(maxkola),
maxhermot_(maxhermot)
\end{verbatim}

\subsubsection{Julkinen jäsenfunktio: aloitaVuoro}
Suorittaa vuoron alussa tehtävän kolavaraston täydentämisen ja vuoron
tulostuksen

{\em Esittely:}\\
{\tt void aloitaVuoro();}

{\em Parametrit:}\\
Ei parametreja.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Lasketaan lisättävän kolan määrä HakkeriPeli-oliolta saatavan
asetuksen ja Hakkerin maksimikolavarastojen perusteella. Suoritetaan lisäys
ja varmistetaan ettei tulos ylitä maksimivarastoja.

Tulostetaan ilmoitus ``Vuorossa: {\em hakkeriryhmän nimi}  - {\em hakkerin nimi} ''.

\subsubsection{Julkinen jäsenfunktio: suoritaSiirto}
Suorittaa siirron, muuttaen hakkerin tilaa ja tarvittaessa lähettää viruksen
HakkeriPelin lahetaVirus-jäsenfunktion kautta.

{\em Esittely:}\\
{\tt bool suoritaSiirto(const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf siirto} on suoritettava siirto, joka on jo tarkistettu lailliseksi.

{\em Paluuarvo:}\\
False, jos hakkerin tila vaihtui, eli vuoron pitäisi päättyä. True muutoin.

{\em Toiminta:}\\
Siirron tyypin perusteella tehdään jotain seuraavista:

{\bf KOODAA:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  koodaa tason {\em x}  viruksen.''
Vaihdetaan tilaksi HYOKKAYS vaihdaTila-jäsenfunktiolla, joka nollaa tilaan liittyvät
jäsenmuuttujat. Asetetaan sitten jäsenmuuttujaan {\tt virustaso\_} koodatun viruksen taso.

Lasketaan kuluva kolan määrä HakkeriPelin haeKoodausKulutus() tuloksen perusteella,
ja kulutetaan se kulutaKolaa-jäsenfunktiolla, joka saattaa vaihtaa tilaksi OFFLINE.
Palautetaan {\bf false}, sillä koodaus lopettaa aina vuoron.

{\bf PUSKUROI:} Tulostetaan ilmoitus
``{\em hakkerin nimi}  valmistautuu puskuroimaan sisääntulevia viruksia.''
Vaihdetaan jäsenfunktion kautta tilaksi PUSKUROI ja asetetaan jäsenmuuttujaan
{\tt maara\_} siirron yhteydessä annettu puskurointien määrä. Kulutetaan
kolaa HakkeriPeliltä saadun asetustiedon perusteella ja palautetaan {\bf false}.

{\bf REITITA:} Tulostetaan ilmoitus
``{\em hakkerin nimi}  valmistautuu reitittämään sisääntulevia viruksia.''
Vaihdetaan jäsenfunktion kautta tilaksi REITITA, ja asetetaan jäsenmuuttujiin
annettu reititysten määrä ja reitityskohteet. Kulutetaan kolaa ja palautetaan
{\bf false}.

{\bf RESETOI:} Tulostetaan ilmoitus
``{\em hakkerin nimi}  buuttaa koneensa.'' Asetetaan jäsenfunktion kautta tilaksi PERUS.
Palautetaan {\bf false}.

{\bf HYOKKAA:} Tulostetaan ilmoitus
``{\em hyökkääjän nimi}  hyökkää kohteenaan {\em kohteen nimi} !'' (kohteen nimi täytyy
hakea HakkeriPeli:n kautta). Lähetetään hakkerin hallussa oleva virus HakkeriPeli-olion
lahetaVirus-jäsenfunktion kautta. Asetetaan tilaksi jäsenfunktion kautta PERUS, joka
samalla nollaa {\tt virustaso\_}:n. Palautetaan {\bf false}.

{\bf TANKKAA:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  ottaa rennosti ja tankkaa kolaa.''
Kulutetaan kolaa asetusten perusteella laskettu määrä ja kasvatetaan {\tt hermot\_}-jäsenmuuttujaa
vastaavasti. Palautetaan {\bf true}, sillä tila ei vaihtunut ja vuoro jatkuu.

{\bf ODOTA:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  odottaa oikeaa hetkeä idlaten irkissä.'' ja
palautetaan {\bf false} vuoron lopettamiseksi.

{\em Käyttö:}\\
HakkeriPeli-olio kutsuu tietyn hakkerin tätä jäsenfunktiota suorittaakseen komentotulkilta
saadun siirron.

\subsubsection{Julkinen jäsenfunktio: tarkistaSiirto}
Tarkistaa siirron kelvollisuuden nykyisessä tilanteessa ja tulostaa mahdolliset
virheilmoitukset.

{\em Esittely:}\\
{\tt bool tarkistaSiirto(const Siirto \&siirto);}

{\em Parametrit:}\\
Parametri {\bf siirto} on tarkistettava siirto.

{\em Paluuarvo:}\\
True, jos siirto oli kelvollinen. Ellei siirto ole kelvollinen, tulostetaan
virheilmoitus ja palautetaan false.

{\em Toiminta:}\\
Tarkistetaan seuraavat virhetilanteet:
\begin{itemize}
\item Siirron tyyppi on HYOKKAA mutta {\tt virustaso\_} on 0. Tulostetaan
``Virhe: {\em hakkerin nimi}  ei omista virusta.'' ja palautetaan {\bf false}.

\item Siirron tyyppi on TANKKAA mutta {\tt kola\_} on pienempi kuin annettu
{\tt maara}. Tulostetaan ``Virhe: Liian vähän kolaa :'(.'' ja palautetaan {\bf false}.

\item Siirron tyyppi on TANKKAA mutta {\tt tila\_} ei ole PERUS. Tulostetaan
``Virhe: Tämän komennon voi suorittaa vain perusmoodissa.'' ja palautetaan {\bf false}.
\end{itemize}

Muutoin palautetaan {\bf true} eikä tulosteta mitään.

{\em Käyttö:}\\
HakkeriPeli-olio kutsuu tietyn Hakkerin tätä jäsenfunktiota komentotulkilta
saadun siirron tarkistamiseksi. Komentotulkki suorittaa jo siirtoa tulkitessaan
osan tarkastuksista, kuten etsii hakkerit nimien perusteella.

\subsubsection{Julkinen jäsenfunktio: otaVirus}
Kutsutaan, kun tälle hakkerille on lähetetty virus. Suorittaa toimenpiteitä
hakkerin tilan perusteella.

{\em Esittely:}\\
{\tt void otaVirus(int taso);}

{\em Parametrit:}\\
Parametri {\bf taso} on lähetetyn viruksen taso.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
{\bf Aina:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  saa tason {\em viruksen taso}  viruksen koneelleen!''

{\bf PERUS- tai HYOKKAYS-tilassa:} Kutsutaan {\tt kulutaHermoja}-jäsenfunktiota viruksen tasolla.
Tämä funktio tulostaa tarvittavat ilmoitukset ja vaihtaa hermojen loppuessa hakkerin tilan.

{\bf PUSKUROINTI-tilassa:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  puskuroi viruksen!''
Lisätään taso jäsenmuuttujaan {\tt virustaso\_}. Pienennetään {\tt maara\_}-jäsenmuuttujaa.
Jos uusi {\tt maara\_} on 0, vaihdetaan {\tt tila\_}:ksi HYOKKAYS ja tulostetaan ilmoitus
``{\em hakkerin nimi}  on täyttänyt puskurinsa viruksilla.''

{\bf REITITYS-tilassa:} Haetaan seuraava kohde {\tt reitityskohteet\_}-pakan ensimmäisestä
alkiosta ja siirretään se viimeiseksi. Tulostetaan ilmoitus
``{\em hakkerin nimi}  reitittää viruksen kohti hakkerin {\em kohteen nimi}  konetta!''

Pienennetään {\tt maara\_}-jäsenmuuttujaa. Jos uusi {\tt maara\_} on 0, siirrytään
tilaan PERUS ja tulostetaan ilmoitus ``{\em hakkerin nimi}  purkaa reitityksensä!''.

Kutsutaan HakkeriPeli-olion lahetaVirus-funktiota kohteella ja annetulla tasolla.

{\bf OFFLINE-tilassa:} Tulostetaan ilmoitus ``{\em hakkerin nimi}  on terassilla. Häntä ei kiinnosta.''

{\em Käyttö:}\\
HakkeriPeli-olio kutsuu tätä, kun joku toinen hakkeri on lähettänyt viruksen sen
lahetaVirus-funktion kautta.


\subsubsection{Julkinen jäsenfunktio: tulostaTiedot}
Tulostaa hakkerin tiedot TIEDOT-komentoa varten.

{\em Esittely:}\\
{\tt void tulostaTiedot() const;}

{\em Parametrit:}\\
Ei parametreja.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Tulostetaan tiedot seuraavassa muodossa:
\begin{verbatim}
<hakkerin nimi>
Moodi:     <moodin kuvaus>
[Taso:     <reititysten/puskurointien määrä>] // Vain jos tila_ on REITITYS
                                              // tai PUSKUROINTI
[Hermot:   <hermot>/<maksimihermot>] // Ei offline-tilassa
[Kola:     <kola>/maksimikola>] // Ei offline-tilassa

[Virus:    tason <viruksen taso> virus] // Vain jos virustaso_ != 0
[Kohteet:  <kohde 1>, <kohde 2>, ... <kohde n>] // Vain jos tila_ on REITITYS
\end{verbatim}

{\em Käyttö:}\\
Komentotulkki kertoo parametrin välityksellä HakkeriPeli-olion
tulostaTiedot-jäsenfunktiolle minkä hakkerin tiedot tulostetaan.
HakkeriPeli-olio kutsuu kyseisen hakkerin tätä jäsenfunktiota.

\subsubsection{Julkinen jäsenfunktio: tulostaTilanne}
Tulostaa tilannelistausta varten sopiva tietorivi.

{\em Esittely:}\\
{\tt void tulostaTilanne();}

{\em Parametrit:}\\
Ei parametreja.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Jos {\tt tila\_} on OFFLINE, tulostetaan ``{\em hakkerin nimi} Terassilla''.

Muutoin tulostetaan
``{\em hakkerin nimi} {\em hermot}/{\em maxhermot} {\em kola}/{\em maxkola} {\em moodi}''.
Moodi on Irkkaa, Koodaa, Reitittää tai Puskuroi.

{\em Käyttö:}\\
HakkeriPeli kutsuu tilannetta tulostaessaan vuorollaan kaikkien hakkerien tätä
jäsenfunktiota.

\subsubsection{Yksityinen jäsenfunktio: kulutaHermoja}
Vähentää hakkerin hermoja ja tulostaa siihen liittyvän ilmoituksen. Hermojen
loppuessa tulostaa ilmoituksen ja vaihtaa hakkerin tilan. Palauttaa tiedon
hermojen riittämisestä.

{\em Esittely:}\\
{\tt bool kulutaHermoja(int maara);}

{\em Parametrit:}\\
Parametri {\bf maara} on hermoista vähennettävä määrä.

{\em Paluuarvo:}\\
True, jos hermot riittivät ja false muutoin.

{\em Toiminta:}\\
Tulostetaan ilmoitus ``{\em hakkerin nimi}  menettää hermojaan {\em x}  pisteen verran!''.
Pienennetään jäsenmuuttujaa {\tt hermot\_} tämän verran.

Jos tulos on negatiivinen tai 0, tulostetaan ilmoitus
``{\em hakkerin nimi}  menettää hermonsa ja lähtee terassille.'' ja palautetaan {\bf false}.
Muutoin palautetaan {\bf true}.

{\em Käyttö:}\\
Jäsenfunktio otaVirus kutsuu tätä viruksen kuluttaessa hakkerin hermoja.
Jäsenfunktio kulutaKolaa kutsuu tätä ellei kolamäärä riitä.

\subsubsection{Yksityinen jäsenfunktio: kulutaKolaa}
Ottaa tarvittavan määrän kolaa hakkerin kolavarastoista. Ellei kola riitä,
määrä otetaan hermoista. Tankkauksen yhteydessä puuttuvaa määrää ei pidä ottaa
hermoista, mutta kolan riittäminen tankkaukseen tarkistetaan ennen siirron
toteutusta.

Palauttaa totuusarvon joka kertoo kolan/hermojen riittämisestä. False tarkoittaa
hermojen menneen, eli hakkerin siirtyneen terassille.

{\em Esittely:}\\
{\tt bool kulutaKolaa(int maara);}

{\em Parametrit:}\\
Parametri {\bf maara} on tarvitun kolan määrä.

{\em Paluuarvo:}\\
True, jos kolaa tai hermoja riitti. False jos hakkeri menetti hermonsa.

{\em Toiminta:}\\
Tarkistetaan riittääkö kolan määrä. Jos riittää, vähennetään se suoraan
jäsenmuuttujasta {\tt kola\_} ja palautetaan {\bf true}.

Muutoin lasketaan kolavarastojen ja tarvitun määrän erotus, asetetaan
jäsenmuuttujaan {\tt kola\_} arvo 0 ja kutsutaan jäsenfunktiota {\tt kulutaHermoja}
erotuksella. Palautetaan saatu arvo.

{\em Käyttö:}\\
Jäsenfunktio suoritaSiirto käyttää tätä siirron tarvitseman kolan kuluttamiseen.

\subsubsection{Yksityinen jäsenfunktio: vaihdaTila}
Vaihtaa hakkerin tilaa nollaten samalla tilaan liittyvät jäsenmuuttujat.

{\em Esittely:}\\
{\tt void vaihdaTila(HakkeriTila uusitila);}

{\em Parametrit:}\\
Parametri {\bf uusitila} on hakkerin seuraava tila.

{\em Paluuarvo:}\\
Ei paluuarvoa.

{\em Toiminta:}\\
Asetetaan uusi tila jäsenmuuttujaan {\tt tila\_}. Nollataan {\tt virustaso\_}
ja {\tt maara\_}. Tyhjennetään {\tt reitityskohteet\_}.

{\em Käyttö:}\\
Jäsenfunktio suoritaSiirto käyttää tätä hakkerin tilan vaihtamiseen. Tilaan
liittyvät arvot asetetaan tämän funktion kutsumisen jälkeen.

% \newpage
% \section{Loppudokumentaatio}
% Tämä luku vain harjoitustyön loppudokumentaatiossa. Välipalautusta
% tehdessäsi voit poistaa tämän luvun.
% 
% \subsection{Muutokset alkuperäiseen suunnitelmaan}
% 
% Tässä kohdassa kuvataan muutokset joita jouduttiin tekemään alkuperäiseen
% välipalautuksessa esitettyyn suunnitelmaan. (Tässä dokumentissa siis
% esitetään ohjelman nykytila)
% 
% \subsection{Kuvaus harjoitustyön tekemisestä}
% 
% Lyhyt kuvaus siitä miten harjoitustyön tekeminen sujui, mihin ongelmiin
% toteutettaessa törmättiin ja miten ne ratkaistiin.
% 
% Arvio harjoitustyöhön käytetystä ajasta. 
% 
% Oma arvio harjoitustyön onnistumisesta.
% 
% \subsection{Palautetta}
% 
% Kaikkea mahdollista palautetta erityisesti kurssin harjoitustöistä,
% muitakin kurssiin liittyviä asioita saa kommentoida. Kuten esimerkiksi:
% \begin{itemize}
% \item harjoitustyö
% \item harjoitustyön tehtävänanto ja aihe
% \item harjoitustyön käytännön järjestelyt
% \item dokumenttipohjan käyttökelpoisuus
% \item olisitko tehnyt välipalautusdokumentin mieluummin ilman dokumenttipohjaa
% \item luennot
% \item harjoitukset
% \item loputon palautteen kerääminen :-)
% \item jne.
% \end{itemize}

\end{document} 
