Studio1: näyteportfolio | Johannes Koponen

Alkuruoka eli alkusanat Keitto eli kotitehtävät Viini eli olotapaukset

Pääruoka eli projekti

Jälkiruoka eli loppusanat

Pääruoka eli projekti

Projektin loppuraportti, sen sisältämä projektin JavaDoc-kommentaatio ja sen liitteenä seuraava ohjelmakoodi tarjoavat kattavan näkymän projektin syviin mysteereihin.

Projekti kokemuksena

Tämä ohjelmointiprojekti on ehkä raskain, opettavaisin ja palkitsevin työ mihin olen koskaan ryhtynyt. Vasta projektivaiheessa asiat, jotka luuli osanneensa joutui työstämään sellaisiksi, että ne todella ymmärsi. Raskas projekti oli monestakin syystä, joista ensimmäinen on tietysti sen kohtuuton laajuus. Sataa riviä koodia varten pitää kirjoittaa ainakin kaksisataa, monesti enemmänkin, jos kysymys on vähääkään haastavammasta ongelmasta, joka tulee ensi kertaa vastaan. Toinen syy projektin rankkuuteen oli se, että sitä oli käytännössä pakko työstää loma-ajalla. Palkitsevuudesta kertoo se, että ymmärsin todella tehneeni ensimmäistä kertaa sitten yläasteen teknisen työn tuntien jotain omaa konkreettista [omatekemä tietokoneohjelma voi olla hyvinkin konkreettinen kokemus] omin käsin, taidoin ja tiedoin.


Projektin loppuraportti

1. Ohjelman kuvaus

VirtuaaliEMO on erityisesti yksinasuville korkeakouluopiskelijoille suunnattu käyttöohjelma, jonka tarkoitus on käyttäjänsä palveleminen – kirjaimellisesti. VE pyrkii mittaamaan käyttäjän tarpeiden – kuten nälkäisyyden, yksinäisyyden ja sivistyksen puutteen – tilaa, ja ehdottamaan sopivaa tarpeen täyttävää toimintaa – kuten syömistä, kavereiden tapaamista tai kirjan lukemista. Täten VE on lähes täydellinen holhooja: ottaessaan tarpeiden kehityksen sopivasti huomioon käyttäjän ei enää tarvitse henkilökohtaisesti huolehtia siivoamisen tai kuntoilun muistamisesta, kunhan vain tottelee tietokoneohjelmaa silloin kun se pyytää lenkille lähtemään.

Kirjoitin: ” - - VE on lähes täydellinen holhooja - -”. Lauseessa on sana ”lähes” siksi, että käyttäjän toimien motivoimiseksi VE:lle on luotu mieliala. VE ei siten ole käyttäjän kannalta joka hetki ihanteellisin mahdollinen persoona. Jos käyttäjä yksinkertaisesti kieltäytyy kaikista tarpeellisista arjen askareista VirtuaaliEMOlle tulee paha mieli. Huonolla tuulella VE saattaa nälväistä tai puhua mieluummin siivoamisesta kuin Linnanmäelle menemisestä, tämä kaikki tietysti vain siksi, ettei käyttäjä enää ensi kerralla ajaisi emoaan surulliseen jamaan, eli kyseessä on oikeaa käyttöä motivoiva toiminta. Hetkellisen olon lisäksi emolla on myös onnellisuus, joka vaikuttaa oloon nostavasti tai laskevasti.

1.1 Käyttöliittymän kuvaus

profiili emo

VirtuaaliEMOssa on kaksi tilaa: toisesta valitaan ohjelmaan henkilökohtainen profiili ja toisesta löytyy emo itse eli ohjelman toiminnallinen osio. VE vaihtelee tilan näkyvyyttä CardLayout-asettelijan avulla.

Profiiliasetukset-osiosta valitaan haluttu profiili emoa varten. Profiilin yksilöimistä varten pitää profiilille antaa sekä nimi että tunnus – sana on tarkoituksellisesti jätetty kattavaksi, kyseessä ei niinkään ole salasana vaan nimenomaan tekstijono, jolla tunnistuttaa itsensä. Nimi ja tunnus hyväksytään painamalla vastaavaa nappia, jonka jälkeen käyttäjällä on kaksi vaihtoehtoa: A) käyttää tietoja uuden profiilin luomiseen tai B) käyttää tietoja vanhan profiilin lataamiseen, jos samoilla tiedoilla on aikaisemmin luotu profiili.

Käyttäjän valinnasta riippumatta esiin nostetaan Emopaneeli (Käyttäjän valinta vaikuttaa ainoastaan emon saamiin lähtöarvoihin). Emo on jaettu neljään tärkeään osaan. Alhaalla vasemmalla näkyvät Emon käyttäjälle esittämät kysymykset ja toteamat ja ylhäällä vasemmalla Emon kasvot, joiden ilme vaihtuu Emon mielialan mukaan. Nämä ovat ne ruudut joita käyttäjän tulee lähinnä tarkkailla.

Alhaalla oikealla sijaitsee käyttäjän vuorovaikutuksen mahdollistava alue, jossa on ”kyllä”- ja ”ei”-napit Emon kysymyksiä varten, liukuripalkki josta voidaan nopeuttaa Emon aikakäsitystä (usein hyödyllistä, esimerkiksi tilanteessa jossa emo on ollut aktiivikäytössä ja sähkökatkos on sulkenyt tietokoneen voidaan Emo saattaa nopeasti tilanteen tasalle antamalla ajan kulua nopeasti ja tarpeiden vastaavasti kasvaa hurjasti). Alimpana tässä paneelissa on ”menen nukkumaan” –nappi, joka pysäyttää Emon toiminnot kunnes nappia painetaan uudelleen.

Ylhäällä oikealla sijaitsee Emon käsitykset tärkeimpien tarpeiden tilasta ilmaistuna JProgressbareina. Niiden näyttäminen on tuiki tärkeää siksi, että Emon toimille olisi perusta. Käyttäjä siis voi pienellä vilkaisulla todeta, että nälkä pitäisi tosiaan jo pian olla, eikä Emo tälläkään kertaa puhunut läpiä päähänsä. Myös esimerkiksi siivoamisen tarvetta kuvaava palkki on hyödyllinen: se kertoo likaisuuden tilan kodissa ilman, että tarvitsisi kokeilla pintojen pölyisyyttä.

2. Ohjelman teknisen toteutuksen kuvaus

Pyrkimyksenäni oli kehittää ohjelma, jonka käyttö olisi erittäin selkeää ja luontevaa, joka ei välttämättä vaatisi koko käytössäoloaikanaan käyttäjän täydellistä huomiota vaan olisi pikemminkin aktiivinen vain silloin kuin käyttäjä itse haluaisi. Tämän vuoksi halusin kiinnittää huomiota erityisesti ulkoasuun, mutta myös toimivaan ohjelman sisäiseen rakenteeseen. Lisäksi pyrin tekemään omien ohjelmointitaitojeni tasoista tai hieman kehittyneempää ohjelmaa.

Näillä eväillä, sekä niillä mitä olin aikaisemmin kurssin kuluessa kerännyt, lähdin rakentamaan toimivaa kokonaisuutta. Olio-ohjelmointi oli avainsana, mutta kuten kokemukset projektista -luku osoittaa, en sen noudattamisessa heti aluksi täysin onnistunut. Lopullinen tuotos kuitenkin seuraa näitä periaatteita.

2.1 Toteutusympäristö

Ohjelmoin WinXP-koneella ja xemacs-ohjelmalla, johon olin syvästi kiintynyt jo kurssin aikana. Ohjelman hyvä puoli on sen käsittämätön monipuolisuus (miltä vaivalta säästivätkään käskyt M-x jde-javadoc-autodoc ja M-x jde-javadoc-make!). Myös java-apin aarreaitta aukeni vasta projektivaiheessa, ei tosin vieläkään täysin, luulen, sillä sen käsittämätön laajuus on ja huimaava monipuolisuus lupaa sen, että oikeita asioita ei välttämättä osaa edes kysyä.

Apista löysin kuitenkin yhden tuttavuuden, josta lopulta tuli lähes koko projektin ydin: java.util –pakkauksen luokat Timer ja TimerTask. Kuvittelin pystyväni pitämään näppini erossa säikeistä, mutta Timer-luokan avulla sain pehmeän kosketuksen niihin. Käytin luokkia sekä Tarve-luokan sisällä kertomaan tarpeen ominaisesta vähenemisnopeudesta että Emo-luokan palkkien päivittäjässä. Myös keskustelun aloittamisen tarpeellisuuden kokeilu toimii samalla periaatteella.

Toinen paljon käytetty kirjasto oli tietenkin javax.swing, ja sen siivellä myös javax.swing.event, java.awt ja java.awt.event tulivat tutuiksi. Erityisesti swingin JProgressbar ja JSlider olivat ahkerassa käytössä, kuten myös tavallisimmat nappulat ja asettelut.

2.2 Teknisen toteutuksen pääpiirteet

Luokkakaaviosta voi hahmottaa ohjelman luokkien suhtautumista toisiinsa: VirtuaaliEMO-luokka on se, minkä päälle kaikki kasataan, mutta kaaviokin osoittaa, että Emo-luokan suhteet ovat moninaisimmat. Malli on tietysti pelkistetty, mutta antaa havainnollisen kuvan. Käyttäjä oli ohjelman suunnittelussa keskeisessä asemassa, kuten kuvassakin.

luokkakaavio

2.2.1 Kaikkien luokkien JavaDoc-kommentit metoditarkastelua varten

2.2.2 Merkittäviä tietorakenteita

public void palkkipaivittaja(){
 	timer = new Timer(); 
 	timer.schedule(new Paivitus(), PULSSI); 
     } 
    class Paivitus extends TimerTask { 
 	public void tarkistus(){ 
  	    if(keskustelu.annaJutusteluKaynnissa()){ 
   		kyllanappi.setEnabled(true); 
   		einappi.setEnabled(true); 
  	    } 
  	    else{ 
   		kyllanappi.setEnabled(false); 
   		einappi.setEnabled(false); 
  	    } 
 	} 
 	public void run() { 
  	    tarkistus(); 
  	    kyllaisyysPalkki.setValue(annaKyllaisyys().annaTarpeenMaara()); 
  	    vasymysPalkki.setValue(annaVasymys().annaTarpeenMaara()); 
  	    huviPalkki.setValue(annaHuvi().annaTarpeenMaara()); 
  	    yksinaisyysPalkki.setValue(annaYksinaisyys().annaTarpeenMaara()); 
  	    siivoamisPalkki.setValue(annaSiivoaminen().annaTarpeenMaara()); 
  	    onnellisuusPalkki.setValue(annaOnnellisuus().annaTarpeenMaara()); 
  	    kuntopalkki.setValue(annaKunto().annaTarpeenMaara()); 
  	    sivistyspalkki.setValue(annaSivistys().annaTarpeenMaara()); 
  	    timer.cancel(); 
  	    palkkipaivittaja(); 
 	} 
    } 

Palkkipaivittaja()-metodi on tyypillinen esimerkki projektissani käyttämästä Timer- ja TimerTask-luokkien hyödyntämisestä. Metodin tehtävänä on päivittää Tarpeiden määrät käyttäjän nähtäväksi JProgressbarin kautta.

Sisäluokka Paivituksessa sijaitseva tarkistus() –metodi sen sijaan katsoo, pitääkö käyttäjälle jättää mahdollisuus painaa ”kyllä” ja ”ei” näppäimiä.

Ajastimen schedule(TimerTask t, aika s) kutsuu sisäluokkaa, kun sille annettu aikamäärä mikrosekunteina (PULSSI) on kulunut loppuun. silloin Paivitus-luokka käy läpi kaikki tehtävänsä, ja katkaisee ajastimen (luokka Timer ei ole daemonthread) ja kutsuu uudelleen ajastimen käynnistävää metodia

public void maalaa(JPanel k){ 
 	 	k.setBackground(TAUSTAVARI); 
 	Component[] komponentit = k.getComponents(); 
 	int pituus = komponentit.length; 
 	for(int t = 0; t < pituus; t++){ 
  Component kompo = komponentit[t]; 
  	    if(kompo instanceof JPanel){ 
   		JPanel kompot = (JPanel)kompo; 
   		Component[] kompokomponentit = kompot.getComponents(); 
   		kompot.setBackground(TAUSTAVARI); 
   		if(kompokomponentit.length > 0){ 
    for(int p = 0; p < kompokomponentit.length; p++){ 
     if(kompokomponentit[p] instanceof JPanel){ 
         JPanel kompott = (JPanel)kompokomponentit[p]; 
         maalaa(kompott); 
     } 
     else{ 
      kompokomponentit[p].setBackground(TAUSTAVARI.darker()); 
     } 
    }
   }
  }
  else{ 
   if(!(kompo instanceof JTextField)){ 
    kompo.setBackground(TAUSTAVARI.darker()); 
   } 
  } 
 } 
    } 

Metodi maalaa() profiililuokassa käy läpi kaikki pinnat ja värittää ne pinnan tyypin mukaan.

Metodin idea on yksinkertainen rekursio: jos kappale sisältää vielä muita kappaleita, nekin väritetään ja niiden sisältämät kappaleet tarkistetaan. Paneelit väritetään eri värillä kuin muut pinnat, kuten myös JTextField-komponentti.

Metodi käyttää vain yhtä väriä TAUSTAVARI ja hyödyntää Javan Color-luokan darker()-metodia erottaakseen tietyt komponentit muista

public double laskeOnnellisuus(){ 
 if(olojenLukumaara > 3*muisti){ 
  	    int indeksi = olojenLukumaara; 
  	    indeksi = (indeksi+3)%(3*muisti); 
  	    onnellisuus = (double)((olo - edellisetOlot[indeksi])); 
  	    onnellisuus = onnellisuus / (double)muisti; 
 	} 
	return onnellisuus; 
} 

Pitkäaikaisen onnellisuuden Mieliala-luokassa laskeva metodi laskeOnnellisuus() toimii seuraavasti: se vähentää edellisen vastauksen olotilan määrän kolme kertaa muisti -luvun antaman määrän verran vanhan vastauksen aikaansaamasta olosta, ja jakaa tämän luvun muisti kertaa. Näin saadaan suoran, joka vedetään (muisti, vastaus) -koordinaatiston pisteestä (0, olotila muisti -oloa sitten) pisteeseen (muisti, olo nyt) kulmakerroin kerrottuna kolmella.

Tämä luku kertoo pitkäaikaisen onnellisuuden vaikutuksen hetkelliseen oloon.

2.3 Luokkien kuvaus

VirtuaaliEMO extends Jframe implement ActionListener: VirtuaaliEMOssa on CardLayoutin kortteina ”profiili” ja ”emo”. Luokka sisältää myös main() –metodin, eli on se luokka, josta käsin muitakin luokkia käytetään.

VirtuaaliEmossa sijaitsee ohjelman JMenuBar, jossa on JMenut ”Valikko” ja ”Ohjelmasta”. Valikko-menusta löytyy JMenuItemeinä ”Profiiliasetukset”, ”Tallenna” ja ”Lopeta”. Profiiliasetukset-itemiä painettaessa ohjelma siirtyy profiili-tilaan, eli CardLayout näyttää Profiili-paneelin. Tallenna-itemistä suoritetaan yksinkertainen tallennustoiminto, ja Lopeta-itemistä tallennetaan ja suljetaan ohjelma.

Profiili extends JPanel: Profiili-luokka on profiilin luomista varten – siinä tehty profiili on tallennustiedosto, ja samoilla lähtötiedoilla tehty profiili on mahdollista ladata. Tämän vuoksi metodi lataaTiedosto() on Profiili-luokassa. Profiililuokka luo uuden Emo-olion.

Profiili-paneelissa on kaksi tyhjää tekstikenttää – toinen nimen ja toinen vapaavalintaisen tunnuksen syöttämiselle, neljä nappia, joista yksi hyväksyy syötetyn nimen ja tunnuksen – jos hyväksyy – yksi tyhjentää tekstikenttiin syötetyn tekstin, ja joista kahta viimeistä nappia ei voi painaa ennen kuin nimi ja tunnus on sekä käyttäjän että ohjelman puolesta hyväksytty. Hyväksymishetken jälkeen nimi ja tunnus näytetään paneelin keskelle sijoitetuista JLabeleista, ja kahden alimman napin käyttö mahdollistuu. Toinen nappi luo annetuilla tiedoilla uuden profiilin, toinen lataa vanhan jos tiedot täsmäävät vanhoihin tietoihin.

Emo extends JPanel: Varsinainen Emo-luokka on varsinaisen ohjelman varsinainen ydin. Profiililuokalta saamillaan lähtöarvoilla Emo-olio luo luokkien Tarve, Mieliala ja Keskustelu olioita.

Muita Emo-luokan tärkeitä ominaisuuksia ovat JSlider-palkin käyttäjän antaman arvon päivitys Tarve-olioille, ja Tarve-olioiden kertoman tarvemäärän päivittäminen omille JProgressbareille. Emo myös yrittää tietyin väliajoin aloittaa uutta keskustelua ja hakee kuvapaneelin kuvan mielialaluokalta. Emossa sijaitsee tallennaTiedosto()-metodi, sillä ainoastaan emopaneelin näkyessä tallennus on mielekästä.

Tarve: Tarve-luokan ilmentymät ovat tarpeita, joilla on ominainen syntymisnopeus (ts. kuinka nopeasti nälkä kasvaa) ja ominainen lause, jolla niistä voidaan alkaa puhua. Tarve-luokan tärkein metodi on ajastin(), joka laskee tarpeen syntymistä. Tärkeä on myös muutaTarpeenMaaraa(int muutos), jolla Keskustelu-olio voi vaikuttaa tarpeeseen.

Keskustelu: Keskustelu on isoin luokka, koska se sisältää raa’asti kaikki VirtuaaliEMOn mahdolliset keskustelut. Siinä on myös iso metodi etsiKysymys(), joka valitsee seuraavan keskustelunaiheen emon mielialasta riippuvalla todennäköisyydellä.

Mieliala: Mieliala kertoo ja laskee nimenomaan Emon mielialan, eli sen, kuinka hyvin käyttäjä on toteuttanut Emon käskyt ja pyynnöt.

Luokka sisältää algoritmit sekä pitkä että lyhytaikaisen onnellisuuden laskemiseen.

3. Kokemukset projektista

Tarpeet –luokan tekeminen oli turha, huonosti perusteltu ratkaisu, jonka muuttamiseen Tarve-luokaksi meni runsaasti arvokkaita työtunteja. Koodirivien määrä väheni muutoksen myötä tässä luokassa vajaasta kahdeksastasadasta kuuteenkymmeneen ilman huomattavia muutoksia käyttäjän kannalta.

Bugeja esiintyi, mutta suurin osa niistä – oli niiden aikaansaama lopputulos miten hupaisa tahansa , kuten erään kirjoitusvirheestä (’{’ merkki vahingossa ’;’) johtuneen kääntäjästä läpi menneen bugin seuraus: VirtuaaliEMOn keskustelu muuttui lähes dadaistiseksi – oli yksinkertaisia pieniä ajatus- tai kirjoitusvirheitä.

Kaksi poikkeusta tähän hokemaan löytyi: ensimmäinen bugi ilmeni siten, että emon Jprogressbareista laski kerrallaan vain niin moni, kuin oli viimeksi yhtä aikaa käynnistynyt. Tämä oli erittäin hämmentävää, ja bugin korjaus ratkaisi lopullisesti Tarve-luokan vaatiman luokkarakenneuudistuksen: syy oli luokan sisältämän ajastimen, jota kutsui jokainen tarve erikseen – ei tässä vielä mitään – ja jokainen tarve myös katkaisi ajastimen ennen kuin aloitti itse uuden – mistä seurasi suoraan ainoastaan yhden tai muutaman Jprogressbarin päivittyminen.

Toinen, vielä oikeastaan kummallisempi bugi ei oikeastaan löydyttyään ollut vielä haitaksi: bugi tuplasi kaikki System.out.prinln –komentojen tulosteet, mutta siten, että aina jomman kumman, joko ensimmäisen tai toisen kloonitulostuksen arvot, olivat nullia ja nollaa. Selitys oli yksinkertainen – kuten bugeissa kaiketi lähes aina – sillä taustalla yksinkertaisesti pyöri yksi ylimääräinen emo, jolle ei oltu annettu mitään lähtöarvoja, ja jonka käyttöliittymäikkuna oli suljettu.

Yllämainittujen ongelmien lisäksi suuren debuggausajan vei Keskustelu-luokan Kysy()-metodin kirjoitusvirheiden etsintä – metodissa vertaillaan rutkasti tekstijonojen samankaltaisuutta, joten pienikin virhe keskeytti selkeän ja loogisen kysymysten sarjan äkillisesti. Etukäteen pelkäämäni kuvilla leikkiminen ei sen sijaan noussut kertaakaan ongelmaksi – tämä iloinen yllätys mainittakoon tässä yhteydessä vastapainoksi edellisille.

3.1 Kokemukset omasta työskentelystä

Alunperin tarkoituksenani oli pyrkiä suunnittelemaan mahdollisimman tarkkaan mitä teen – tiesin ohjelmointitaitojeni olevan rajatut mutta riittävät. Hyvin pian huomasin kuitenkin, että suunnittelu järkevästi on äärimmäisen haastava tehtävä, ja että paikkansapitävän suunnitelman teko kuuluu samaan joukkoon lottoamisen ja abstraktin taiteen kanssa. Olen ihminen, joka luottaa suunnitelmiinsa, mutta tällä kertaa minun oli poikkeuksellisesti oikeastaan pakko heittäytyä osviittaisen ja ylimalkaisen luokkarakenteen ja päässäni pyörivän vielä sanan muotoa saamattoman idean siiville.

Tarkkojen suunnitelmien puute – tottakai minä tiesin mitä olen suunnilleen tekemässä – aiheutti lähinnä valtavan keltaisten lappujen invaasion työpöydälle. Viimeisenä viikkona päädyin ratkaisuun, jossa kirjoitin aina sen päivän tavoitteellisen suunnitelman tarkasti listalle sen pohjalta, mitä nyt päällimmäisissä lapuissa tuntui lukevan. Ratkaisu oli hyvä, koska koko ajan pystyi etenemään ja tiesi, että jokainen asia on kuitenkin tehtävä, eikä näiden asioiden tekojärjestyksellä ole suurempaa merkitystä.

Tähdennettäköön tässä vielä, että projektin jälkeen suunnitelmien teko tuntuu lasten leikiltä. En oikeastaan voi käsittää sitä ahdistusta, joka huokuu projektisuunnitelman jälkeisien päivien merkinnöistä, jolloin todella yritin suunnitella projektiini järkevää rakennetta ja ehkä lähes onnistuinkin, pystymättä sitä kuitenkaan paperille pistämään. Selvästikin ohjelmointiharjoitukset eivät tuoneet lainkaan sellaista korkeampaa ohjelmointitaitoa, jota voisi kutsua näkemykseksi. Tämä taito kehittyi vasta projektin edetessä, mikä oli sinänsä sääli, sillä vasta seuraavan suuren ohjelmointityön tekeminen olisi huomattavasti kevyempi urakka: suunnitelma onnistuisi ja pitäisi tarkasti mietityiltä osin.

3.2 Resursseista

Aikaa kului, määrän erittely on mahdotonta ja jokseenkin turhaa. Projekti imi myös henkisiä resursseja, mutta palkitsi lopulta yhtä suurella mitalla. Poikkeaman suunnitelmiin aiheutti paha suunnitelmallinen kömmähdys Tarpeet/Tarve –luokan kohdalla, jonka aiheutti nähtävästi selvä olio-ohjelmoinnin periaatteiden sivuuttaminen ajattelussa. Tietysti kun on kerran suunnitelman tehnyt, sitä ei helposti kovin aikaisessa vaiheessa lähde kritisoimaan tai muuttamaan. Yllättävänkin helppoa ohjelman rakennetta oli muuttaa vasta silloin, kun se oli jo lähes myytävässä kunnossa.

4. Yhteenveto

Olen äärimmäisen tyytyväinen aikaansaannokseeni. Demosessiossa totesin: ”Tiedän, ettei tekeleeni ole maailman paras ohjelma - - mutta minulle se on vähintään toiseksi paras!” Olen tätä mieltä yhä. Miksi? Koska ensi kertaa sitten yläasteen teknisen työn tuntien on saanut tuottaa jotain omaa laudansäleistä, nauloista ja osviittaisista neuvoista, nähnyt ohjelman kehittyvän ja valmistuvan ja ehkä kaikkein tärkeimpänä: olen yllättänyt itseni. Katsoi sitten koko ohjelman kehityskaarta yhtenä suurena yllätyksenä, tai jotain pientä mahdottoman oloista bugia, neulaa heinäsuovassa, jonka sitten löytääkin kun siihen astuu, olen yllättänyt ja ylittänyt omat uskomukseni kyvyistäni, ja se on äärimmäisen palkitseva kokemus.


5. Ohjelmakoodi

Koodi sisältää seuraavat luokat:

5.1 VirtuaaliEMO


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.IOException;

/**
 * VirtuaaliEMO perii JFrame-luokan, ja näyttää itse asiassa kahden
 * CardLayout -lehtisen sisällön.
 *
 * @author Johannes Koponen
 * @version 1.1
 */
public class VirtuaaliEMO extends JFrame implements ActionListener{
    private JPanel cards;
    final static String PROFIILIPANEL = "Profiili";
    final static String EMOPANEL = "Emo";

    private Profiili card1;
    private JPanel card2;

    /**
     *  luoValikkopalkki luo JFramen valikkopalkin.
     *
     * @return JMenuBar
     */
    public JMenuBar luoValikkopalkki(){
	 // Valikko
        JMenuBar valikkopalkki = new JMenuBar();
	JMenu tiedotvalikko = new JMenu("Ohjelmasta");	
        JMenu tiedostovalikko = new JMenu("Valikko");
        tiedostovalikko.getAccessibleContext().setAccessibleDescription(
            "kuvaus");
        valikkopalkki.add(tiedostovalikko);
	valikkopalkki.add(tiedotvalikko);

        JMenuItem valikkorivi = new JMenuItem("Profiiliasetukset");
        valikkorivi.getAccessibleContext().
                    setAccessibleDescription("Luo uusi profiili tai lataa vanha");
	valikkorivi.setActionCommand("profiiliin");
        valikkorivi.addActionListener(this);
	tiedostovalikko.add(valikkorivi);


        valikkorivi = new JMenuItem("Tallenna");
        valikkorivi.getAccessibleContext().setAccessibleDescription("Tallenna");
        valikkorivi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
		if(card2 instanceof Emo){
		    try{
			Emo emo = (Emo)card2;
			emo.tallennaTiedosto(card1.annaProfiilinNimi() + 
                                             card1.annaProfiilinTunnus() + ".tal");
		    }catch(IOException ioe){}
		}
            }
	    });
	
	tiedostovalikko.add(valikkorivi);


        valikkorivi = new JMenuItem("Lopeta");
        valikkorivi.getAccessibleContext().setAccessibleDescription("Lopeta!");
        valikkorivi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    if(card2 instanceof Emo){
			try{
			    Emo emo2 = (Emo)card2;
			    emo2.tallennaTiedosto(card1.annaProfiilinNimi() + 
                                                  card1.annaProfiilinTunnus() + ".tal");
			}catch(IOException ioe){}
		    }
		    System.exit(0);
		}
	    });
        tiedostovalikko.add(valikkorivi);


	valikkorivi = new JMenuItem("Apua!");
	valikkorivi.getAccessibleContext().
                          setAccessibleDescription("Ohjeita ohjelman käyttöön");
	valikkorivi.setActionCommand("apuarivi");
	valikkorivi.addActionListener(this);


	

	tiedotvalikko.add(valikkorivi);
	
	valikkorivi = new JMenuItem("Ohjelmasta");
	valikkorivi.getAccessibleContext().setAccessibleDescription("Tietoa ohjelmasta");
	valikkorivi.setActionCommand("ohjelmastarivi");
	valikkorivi.addActionListener(this);
	tiedotvalikko.add(valikkorivi);

        // Ikkunan kuuntelija
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
		if(card2 instanceof Emo){
		    try{
			Emo emo3 = (Emo)card2;
			emo3.tallennaTiedosto(card1.annaProfiilinNimi() + 
                                              card1.annaProfiilinTunnus() + ".tal");
		    }catch(IOException ioe){}
		}
		System.exit(0);
            }
        });
	return valikkopalkki;
    }


    /**
     * lisaaOsia lisää Säiliöön palasia.
     *
     * @param pane a Container value
     */
    public void lisaaOsia(Container pane) {
        //luodaan kortit (CardLayout voidaan ajatella päällekkäin pinottuina pelikortteina
	//eli vain yksi näkyy kerrallaan - siitä nimi)
        card2 =  new JPanel();
        card1 = new Profiili(this);
	card1.setPreferredSize(new Dimension(470, 350));
	card1.setBackground(Color.PINK);
        //luodaan paneeli, johon kortit sijoitetaan

        cards = new JPanel(new CardLayout());
        cards.add(card1, PROFIILIPANEL);
        cards.add(card2, EMOPANEL);
        pane.add(cards, BorderLayout.CENTER);
    }
    /**
     * actionPerformed toteuttaa ActionListener rajapinnan
     * Metodi pyrkii toteuttamaan käyttäjän tuottamat tapahtumat.
     * tapahtumat eritellään tässä actionCommandeilla, eli tapahtumalle
     * ominaisella tekstipätkällä.
     *
     * @param e ActionEvent 
     */
    public void actionPerformed(ActionEvent e) {
        CardLayout cl = (CardLayout)(cards.getLayout());

	if(e.getActionCommand().equals("apuarivi")){
	    JOptionPane.showMessageDialog(this,
	      "Luotuasi itsellesi henkilökohtaisen profiilin, 
\nEmo kysyy kysymyksiä ja yrittää muodostaa mahdollisimman 
\npitävää kuvaa Sinun tarpeistasi. Vastaa Emon kysymyksiin 
\n \"kyllä\" ja \"ei\" napeilla.", "APUA!", JOptionPane.PLAIN_MESSAGE);
	}
	if(e.getActionCommand().equals("ohjelmastarivi")){
	    JOptionPane.showMessageDialog(this, 
	      "Tämä sovellus on tehty informaatioverkostojen koulutus-
\nohjelman projektityönä, ja sen jalona tavoitteena on 
\nhelpottaa kaikkien yksinasuvien kotoamuuttaneiden elämää.
\n                       Loi: Johannes Koponen 2005", "Ohjelmasta", JOptionPane.PLAIN_MESSAGE);
	}
	if(e.getActionCommand().equals("uusiprofiili")){
	    card2 = null;
	    card2 = new Emo(card1.annaProfiilinNimi(), 0,0,0,0,0,0,0,0,0,0);
	    cards.add(card2, EMOPANEL);
	    cl.show(cards, EMOPANEL);
	}

	if(e.getActionCommand().equals("ladattu")){
	    try{
		card2 = null;
		card2 = card1.lataaTiedosto(card1.annaProfiilinNimi() + 
                                            card1.annaProfiilinTunnus() + ".tal");
	    }catch(IOException ioe){ 
		JOptionPane.showMessageDialog(this, 
                    "Nimi tai tunnus virheellinen!", "Nyt mogasit", JOptionPane.ERROR_MESSAGE);
		return;
	    }
	    cards.add(card2, EMOPANEL);
	    cl.show(cards, EMOPANEL);
	}
	if(e.getActionCommand().equals("profiiliin")){
	    try{
		Emo emo = (Emo)card2;
		emo.tallennaTiedosto(card1.annaProfiilinNimi() + 
                                     card1.annaProfiilinTunnus() + ".tal");
	    }catch(IOException ioe){}
	    cl.show(cards, PROFIILIPANEL);
	}
    }
    private static void teeJaNayta(){
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("VirtuaaliEMO");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        VirtuaaliEMO vE = new VirtuaaliEMO();
        vE.lisaaOsia(frame.getContentPane());
	frame.setJMenuBar(vE.luoValikkopalkki());
	frame.setResizable(false);
	frame.setIconImage(new ImageIcon("kuvat/ikoni.jpg").getImage());

        frame.pack();
        frame.setVisible(true);
    }

    /**
     * main on pääohjelmametodi
     *
     * @param args String[]
     */
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
		public void run() {
		    teeJaNayta();
		}
	    });
    }
}


5.2 Emo


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
import javax.swing.border.EtchedBorder;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.text.*;
import java.awt.*;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.HashSet;


/**
 * Emo.java on sokerina pohjalla
 *
 * Emopaneelin tehtävä on varsinainen ohjelman toiminnan ydin, 
 * eli se koordinoi muiden luokkien toimintaa ja toimii itse, 
 * jotta käyttäjän hoivaaminen olisi tosiaan mahdollisimman
 * mutkatonta.
 *
 * @author Johannes Koponen
 * @version 1.1
 */
public class Emo extends JPanel{

    //Paneeli, jossa on muut hässelit
    private JPanel pohjapaneeli;
    private final static int PULSSI = 500;
    private final static int TIHEYS = 10;
    private final static Color TAUSTAVARI = Color.PINK;
    private static final int MUISTI = 27;

    private JButton kyllanappi;
    private JButton einappi;
    private JSlider aktiivisuusLiukuri;
    private int liukurinArvo;

    private HashSet tarpeetSet;
    private String profiilinNimi;
    private Tarve kyllaisyys;
    private Tarve vasymys;
    private Tarve huvi;
    private Tarve yksinaisyys;
    private Tarve siivoaminen;
    private Tarve onnellisuus;
    private Tarve sivistys;
    private Tarve kunto;
    private Tarve kaupassakaynti;

    private int kyllaisyysint;
    private int vasymysint;
    private int huviint;
    private int yksinaisyysint;
    private int siivoaminenint;
    private int onnellisuusint;
    private int sivistysint;
    private int kuntoint;
    private int kaupassakayntiint;

    private int olo;
    private Timer timer;
    private int nopeus;

    //neljä paneelia pohjapaneelin päälle
    private JPanel kuvapaneeli;
    private JPanel kysypaneeli;
    private JPanel vastaapaneeli;
    private JPanel tietopaneeli;

    private Mieliala mieliala;
    private Keskustelu keskustelu;

    private String nukkuuko;
    private JToggleButton uninappi;
    private JEditorPane editorPane;
    private Timer aktiivisuus;
    private JProgressBar kyllaisyysPalkki;
    private JProgressBar vasymysPalkki;
    private JProgressBar huviPalkki;
    private JProgressBar yksinaisyysPalkki;
    private JProgressBar siivoamisPalkki;
    private JProgressBar onnellisuusPalkki;
    private JProgressBar kuntopalkki;
    private JProgressBar sivistyspalkki;
    private JLabel kuvalabel;

    /**
     * Palauttaa pohjapaneelin.
     * @return pohjapaneeli
     */
    public JPanel annaPohjapaneeli() {
        return pohjapaneeli;
    }
    /**
     * Asettaa pohjapaneelin.
     * @param uusiPohjapaneeli Paneeli, johon käyttöliittymän elementit lisätään.
     */
    public void asetaPohjapaneeli(JPanel uusiPohjapaneeli) {
        pohjapaneeli = uusiPohjapaneeli;
    }

    /**
     * annaKuvapaneeli palauttaa kuvapaneelin.
     *
     * @return  JPanel value
     */
    public JPanel annaKuvapaneeli(){
	return kuvapaneeli;
    }
    /**
     * annaTietopaneeli palauttaa tietopaneelin
     *
     * @return JPanel 
     */
    public JPanel annaTietopaneeli(){
	return tietopaneeli;
    }
    /**
     * annaKysypaneeli palauttaa kysypaneelin
     *
     * @return JPanel 
     */
    public JPanel annaKysypaneeli(){
	return kysypaneeli;
    }
    /**
     * annaVastaapaneeli palauttaa vastaapaneelin
     *
     * @return  JPanel 
     */
    public JPanel annaVastaapaneeli(){
	return vastaapaneeli;
    }
    /**
     *  annaEditorPane palauttaa tekstikentän.
     *
     * @return JEditorPane 
     */
    public JEditorPane annaEditorPane(){
	return editorPane;
    }

    /**
     * Asettaa kuvapaneelin.
     * @param uusiKuvapaneeli JPanel 
     */
    public void asetaKuvapaneeli(JPanel uusiKuvapaneeli) {
        kuvapaneeli = uusiKuvapaneeli;
    }
    /**
     * Asettaa kysypaneelin.
     * @param uusiKysypaneeli  JPanel 
     */
    public void asetaKysypaneeli(JPanel uusiKysypaneeli) {
        kysypaneeli = uusiKysypaneeli;
    }
    /**
     * Asettaa vastaapaneelin.
     * @param uusiVastaapaneeli JPanel
     */
    public void asetaVastaapaneeli(JPanel uusiVastaapaneeli) {
        vastaapaneeli = uusiVastaapaneeli;
    }
    /**
     * Asettaa tietopaneelin.
     * @param uusiTietopaneeli JPanel
     */
    public void asetaTietopaneeli(JPanel uusiTietopaneeli) {
        tietopaneeli = uusiTietopaneeli;
    }

    /**
     * Luo Emon ilmentymän.
     *
     * @param profiilinNimi String käyttäjän antamasta 
     * profiilin nimestä.
     * 
     * @param kyllaisyysint int 
     * @param vasymysint int
     * @param huviint int
     * @param yksinaisyysint int>
     * @param siivoaminenint int>
     * @param onnellisuusint int>
     * @param sivistysint int>
     * @param kuntoint int>
     * @param kaupassakayntiint int>
     * @param olo int
     */
    public Emo(String profiilinNimi, int kyllaisyysint, int vasymysint, 
	       int huviint, int yksinaisyysint, int siivoaminenint, int onnellisuusint,  
	       int sivistysint, int kuntoint, int kaupassakayntiint, int olo){
        super();
	this.profiilinNimi = profiilinNimi;
	this.kyllaisyysint = kyllaisyysint;
	this.vasymysint = vasymysint;
	this.huviint = huviint;
	this.yksinaisyysint = yksinaisyysint;
	this.siivoaminenint = siivoaminenint;
	this. onnellisuusint = onnellisuusint;
	this.sivistysint = sivistysint;
	this.kuntoint = kuntoint;
	this.kaupassakayntiint = kaupassakayntiint;
	this.olo = olo;
	
	tarpeetSet = new HashSet();

	kyllaisyys = new Tarve(this, kyllaisyysint, 1, "Oletko syönyt?");
	tarpeetSet.add(kyllaisyys);

	vasymys = new Tarve(this, vasymysint, 1.2, "Onko nyt niin, että sinua ei väsytä?");
	tarpeetSet.add(vasymys);

	huvi = new Tarve(this, huviint, 1.1, "Onko tylsää?");
	tarpeetSet.add(huvi);

	yksinaisyys = new Tarve(this, yksinaisyysint, 1.4, "Oletko tavannut muita
                                 ihmisiä pitkään aikaan?");
	tarpeetSet.add(yksinaisyys);

	siivoaminen = new Tarve(this, siivoaminenint, 1.3, "Katsopa ympärillesi. 
                                Onko huone siisti?");
	tarpeetSet.add(siivoaminen);

	onnellisuus = new Tarve(this, onnellisuusint, 100, "Oletko viime aikoina 
                                ajatellut usein negatiivisia ajatuksia?");
	tarpeetSet.add(onnellisuus);

	sivistys = new Tarve(this, sivistysint, 1.1, "Oletko lukenut viime
                              aikoina yhtään kirjaa?");
	tarpeetSet.add(sivistys);

	kunto = new Tarve(this, kuntoint, 1.1, "Kai olet harrastanut 
                          lähiaikoina ankarasti liikuntaa?");
	tarpeetSet.add(kunto);

	kaupassakaynti = new Tarve(this, kaupassakayntiint, 1.2, "Oletko käynyt
                                    lähiaikoina ruokaostoksilla?");
	tarpeetSet.add(kaupassakaynti);
				   
	mieliala = new Mieliala(MUISTI, olo);
	keskustelu = new Keskustelu(this, mieliala, profiilinNimi);

	nukkuuko = "Menen nukkumaan";

        asetaPohjapaneeli(new JPanel());
        this.add(annaPohjapaneeli());
	GridLayout asettelu = new GridLayout(0,2);

        annaPohjapaneeli().setLayout(asettelu);
        annaPohjapaneeli().setBorder(BorderFactory.createLineBorder(Color.BLACK));

	asetaKuvapaneeli(new JPanel());
        asetaKysypaneeli(new JPanel());
        asetaVastaapaneeli(new JPanel());
        asetaTietopaneeli(new JPanel());

        Dimension d = new Dimension(230, 170);

        annaKuvapaneeli().setBackground(Color.WHITE);
        annaKuvapaneeli().setMinimumSize(d);
        annaKuvapaneeli().setPreferredSize(d);

	kuvalabel = new JLabel(luoImageIcon("kuvat/" + haeKuva() + ".jpg"), 
				      JLabel.CENTER);
	kuvalabel.setPreferredSize(d);

	BorderLayout kuvaAsettelu = new BorderLayout();
	annaKuvapaneeli().setLayout(kuvaAsettelu);
	annaKuvapaneeli().add(kuvalabel, kuvaAsettelu.CENTER);

        annaTietopaneeli().setBackground(TAUSTAVARI);
        annaTietopaneeli().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        annaTietopaneeli().setMinimumSize(d);
        annaTietopaneeli().setPreferredSize(d);
	
	BorderLayout tietoAsettelu = new BorderLayout(0,1);
	annaTietopaneeli().setLayout(tietoAsettelu);

	huviPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	huviPalkki.setValue(50);
	huviPalkki.setStringPainted(true);
	huviPalkki.setPreferredSize(new Dimension(5, 58));
	huviPalkki.setMaximumSize(new Dimension(5, 300));

	siivoamisPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	siivoamisPalkki.setValue(50);
	siivoamisPalkki.setStringPainted(true);
	siivoamisPalkki.setPreferredSize(new Dimension(5, 58));
	siivoamisPalkki.setMaximumSize(new Dimension(5, 300));

	kyllaisyysPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	kyllaisyysPalkki.setValue(50);
	kyllaisyysPalkki.setStringPainted(true);
	kyllaisyysPalkki.setPreferredSize(new Dimension(5, 58));
	kyllaisyysPalkki.setMaximumSize(new Dimension(5, 300));

	yksinaisyysPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	yksinaisyysPalkki.setValue(50);
	yksinaisyysPalkki.setStringPainted(true);
	yksinaisyysPalkki.setPreferredSize(new Dimension(5, 58));
	yksinaisyysPalkki.setMaximumSize(new Dimension(5, 300));

	vasymysPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	vasymysPalkki.setValue(50);
	vasymysPalkki.setStringPainted(true);
	vasymysPalkki.setPreferredSize(new Dimension(5, 58));
	vasymysPalkki.setMaximumSize(new Dimension(5, 300));

	onnellisuusPalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	onnellisuusPalkki.setValue(70);
	onnellisuusPalkki.setStringPainted(true);
	onnellisuusPalkki.setPreferredSize(new Dimension(5, 58));
	onnellisuusPalkki.setMaximumSize(new Dimension(5, 300));

	kuntopalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	kuntopalkki.setValue(70);
	kuntopalkki.setStringPainted(true);
	kuntopalkki.setPreferredSize(new Dimension(5, 58));
	kuntopalkki.setMaximumSize(new Dimension(5, 300));

	sivistyspalkki = new JProgressBar(JProgressBar.HORIZONTAL);
	sivistyspalkki.setValue(70);
	sivistyspalkki.setStringPainted(true);
	sivistyspalkki.setPreferredSize(new Dimension(5, 58));
	sivistyspalkki.setMaximumSize(new Dimension(5, 300));

	GridLayout tyhjatAdjektiivitAsettelu = new GridLayout(0,1);
	JPanel tyhjatAdjektiivit = new JPanel(tyhjatAdjektiivitAsettelu);
	tyhjatAdjektiivit.setBackground(TAUSTAVARI);
	tyhjatAdjektiivit.add(new JLabel(" nälkäinen "));
	tyhjatAdjektiivit.add(new JLabel(" tylsistynyt "));
	tyhjatAdjektiivit.add(new JLabel(" likainen "));
	tyhjatAdjektiivit.add(new JLabel(" yksinäinen "));
	tyhjatAdjektiivit.add(new JLabel(" väsynyt "));
	tyhjatAdjektiivit.add(new JLabel(" tukeva "));
	tyhjatAdjektiivit.add(new JLabel(" taantunut "));
	tyhjatAdjektiivit.add(new JLabel(" surullinen "));

	GridLayout palkkienAsettelu = new GridLayout(0,1);
	JPanel palkkiPanel = new JPanel(palkkienAsettelu);
	palkkiPanel.add(kyllaisyysPalkki);
	palkkiPanel.add(huviPalkki);
	palkkiPanel.add(siivoamisPalkki);
	palkkiPanel.add(yksinaisyysPalkki);
	palkkiPanel.add(vasymysPalkki);
	palkkiPanel.add(kuntopalkki);
	palkkiPanel.add(sivistyspalkki);
	palkkiPanel.add(onnellisuusPalkki);

	GridLayout taydetAdjektiivitAsettelu = new GridLayout(0,1);
	JPanel taydetAdjektiivit = new JPanel(taydetAdjektiivitAsettelu);
	taydetAdjektiivit.setBackground(TAUSTAVARI);
	taydetAdjektiivit.add(new JLabel(" kylläinen "));
	taydetAdjektiivit.add(new JLabel(" vireä "));
	taydetAdjektiivit.add(new JLabel(" siisti "));
	taydetAdjektiivit.add(new JLabel(" sosiaalinen "));
	taydetAdjektiivit.add(new JLabel(" virkeä "));
	taydetAdjektiivit.add(new JLabel(" trimmissä "));
	taydetAdjektiivit.add(new JLabel(" terävä "));
	taydetAdjektiivit.add(new JLabel(" onnellinen "));

	annaTietopaneeli().add(new JLabel(" Emon käsitys Sinun voinnistasi "), 
                               tietoAsettelu.NORTH);

	annaTietopaneeli().add(tyhjatAdjektiivit, tietoAsettelu.WEST);
	annaTietopaneeli().add(palkkiPanel, tietoAsettelu.CENTER);
	annaTietopaneeli().add(taydetAdjektiivit, tietoAsettelu.EAST);

        annaKysypaneeli().setBackground(Color.WHITE);
        annaKysypaneeli().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        annaKysypaneeli().setMinimumSize(d);
        annaKysypaneeli().setPreferredSize(d);

	editorPane = new JEditorPane();
	editorPane.setEditable(false);
	editorPane.setContentType("text/html");
	editorPane.setPreferredSize(d);
	editorPane.setMinimumSize(new Dimension(20, 20));
	editorPane.setBackground(Color.WHITE);
	editorPane.setText("Emosi keskustelee kanssasi tämän ruudun avulla");
    
	annaKysypaneeli().add(editorPane);


	kyllanappi = new JButton("kyllä");
	kyllanappi.setBackground(TAUSTAVARI);
	kyllanappi.setPreferredSize(new Dimension(35, 35));
	kyllanappi.setBorder(BorderFactory.createRaisedBevelBorder());
        kyllanappi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    if(keskustelu != null){
			if(keskustelu.annaJutusteluKaynnissa()){
			    annaEditorPane().setText(keskustelu.vastaa(true));
			    mieliala.laskeOlo(true);
			    kuvalabel.setIcon(luoImageIcon("kuvat/" + 
							   haeKuva() + ".jpg"));
			}else{
			    annaEditorPane().setText(keskustelu.etsiKysymys());
			}
		    }
		}
	    });

	einappi = new JButton("ei");
	einappi.setBackground(TAUSTAVARI);
	einappi.setPreferredSize(new Dimension(35, 35));
	einappi.setBorder(BorderFactory.createRaisedBevelBorder());
	einappi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    if(keskustelu != null){
			if(keskustelu.annaJutusteluKaynnissa()){
			    annaEditorPane().setText(keskustelu.vastaa(false));
			    mieliala.laskeOlo(false);
			    kuvalabel.setIcon(luoImageIcon("kuvat/" + 
							   haeKuva() + ".jpg"));
			}else{
			    annaEditorPane().setText(keskustelu.etsiKysymys());
			}
		    }
		}
	    });
	uninappi = new JToggleButton(nukkuuko);
	uninappi.setBackground(TAUSTAVARI);
	uninappi.setBorder(BorderFactory.createRaisedBevelBorder());
	uninappi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    unitilanVaihto();
		}
	    });

        annaVastaapaneeli().setBackground(TAUSTAVARI.darker());
        annaVastaapaneeli().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        annaVastaapaneeli().setMinimumSize(d);
        annaVastaapaneeli().setPreferredSize(d);

	aktiivisuusLiukuri = new JSlider(JSlider.HORIZONTAL, 0, 100, 6);
	aktiivisuusLiukuri.setBackground(TAUSTAVARI);
	aktiivisuusLiukuri.addChangeListener(new ChangeListener(){
		public void stateChanged(ChangeEvent e) {
		    JSlider source = (JSlider)e.getSource();
		    if (!source.getValueIsAdjusting()) {
			nopeus = (int)source.getValue();
		    }
		}
	    });

	aktiivisuusLiukuri.setPreferredSize(new Dimension(100, 15));
        aktiivisuusLiukuri.setMajorTickSpacing(25);
        aktiivisuusLiukuri.setMinorTickSpacing(5);
        aktiivisuusLiukuri.setPaintTicks(true);
        aktiivisuusLiukuri.setPaintLabels(true);
        aktiivisuusLiukuri.setBorder(
                BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));

	JLabel aktiivisuusmittarinTekstiLabel = new 
                                        JLabel(" Emon ajantaju (% reaaliajasta).");

	BorderLayout vastaaAsettelu = new BorderLayout();
	GridLayout vastaaNappiAsettelu = new GridLayout(1,0);
	BorderLayout vastaaOsanAsettelu = new BorderLayout();
	JPanel vastaaNappiPanel = new JPanel(vastaaNappiAsettelu);

	BorderLayout liukuriAsettelu = new BorderLayout();
	JPanel liukuriPanel = new JPanel(liukuriAsettelu);
	liukuriPanel.setBackground(TAUSTAVARI.darker());
	liukuriPanel.add(aktiivisuusmittarinTekstiLabel, liukuriAsettelu.NORTH);
	liukuriPanel.add(aktiivisuusLiukuri, liukuriAsettelu.CENTER);

	vastaaNappiPanel.add(kyllanappi);
	vastaaNappiPanel.add(einappi);

	annaVastaapaneeli().setLayout(vastaaAsettelu);
	JPanel vastaaOsa = new JPanel(vastaaOsanAsettelu);
	vastaaOsa.setBackground(TAUSTAVARI.darker());
	vastaaOsa.add(new JLabel(" Vastaan Emon kysymykseen "), 
                                 vastaaOsanAsettelu.NORTH);
	vastaaOsa.add(vastaaNappiPanel, vastaaOsanAsettelu.CENTER);

	annaVastaapaneeli().add(vastaaOsa, vastaaAsettelu.NORTH);
	annaVastaapaneeli().add(liukuriPanel, vastaaAsettelu.CENTER);
	annaVastaapaneeli().add(uninappi, vastaaAsettelu.SOUTH);
	

        annaPohjapaneeli().add(annaKuvapaneeli());
        annaPohjapaneeli().add(annaTietopaneeli());
        annaPohjapaneeli().add(annaKysypaneeli());
        annaPohjapaneeli().add(annaVastaapaneeli());
	
	emonKyselynAktiivisuus(TIHEYS);
	palkkipaivittaja();

    }
    /**
     * annaNopeus ompi julkinen nopeuden toteutus
     *
     * @return int
     */
    public int annaNopeus(){
	return nopeus + 1;
    }
    /**
     * annaTarpeetSet antaa HashSetin tarpeetSet;
     *
     * @return HashSet 
     */
    public HashSet annaTarpeetSet(){
	return tarpeetSet;
    }
    /**
     *  annaKyllaisyys palauttaa kyllaisyyden
     *
     * @return Tarve  
     */
    public Tarve annaKyllaisyys(){
	return kyllaisyys;
    }
    /**
     *  annaVasymys palauttaa vasymyksen
     *
     * @return Tarve  
     */
    public Tarve annaVasymys(){
	return vasymys;
    }
    /**
     *  annaHuvi palauttaa huvin
     *
     * @return Tarve  
     */
    public Tarve annaHuvi(){
	return huvi;
    }
    /**
     *  annaYksinaisyys palauttaa tarpeen "yksinaisyys".
     *
     * @return Tarve  
     */
    public Tarve annaYksinaisyys(){
	return yksinaisyys;
    }
    /**
     *  annaSiivoaminen palauttaa tarpeen "siivoaminen".
     *
     * @return Tarve  
     */
    public Tarve annaSiivoaminen(){
	return siivoaminen;
    }
    /**
     *  annaOnnellisuus palauttaa tarpeen "onnellisuus".
     *
     * @return Tarve  
     */
    public Tarve annaOnnellisuus(){
	return onnellisuus;
    }
    /**
     *  annaSivistys palauttaa tarpeen "sivistys".
     *
     * @return Tarve  
     */
    public Tarve annaSivistys(){
	return sivistys;
    }
    /**
     *  annaKunto palauttaa tarpeen "kunto".
     *
     * @return Tarve  
     */
    public Tarve annaKunto(){
	return kunto;
    }
    /**
     *  annaKaupassakaynti palauttaa tarpeen "kaupassakaynti".
     *
     * @return Tarve  
     */
    public Tarve annaKaupassakaynti(){
	return kaupassakaynti;
    }

    /**
     * palkkipaiavittaja() päivittää tarvepalkkeja
     */

    public void palkkipaivittaja(){
	timer = new Timer();
	timer.schedule(new Paivitus(), PULSSI);

    }
    class Paivitus extends TimerTask {
	public void tarkistus(){
	    if(keskustelu.annaJutusteluKaynnissa()){
		kyllanappi.setEnabled(true);
		einappi.setEnabled(true);
	    }
	    else{
		kyllanappi.setEnabled(false);
		einappi.setEnabled(false);
	    }
	}
	public void run() {
	    tarkistus();
	    
	    kyllaisyysPalkki.setValue(annaKyllaisyys().annaTarpeenMaara());
	    vasymysPalkki.setValue(annaVasymys().annaTarpeenMaara());
	    huviPalkki.setValue(annaHuvi().annaTarpeenMaara());
	    yksinaisyysPalkki.setValue(annaYksinaisyys().annaTarpeenMaara());
	    siivoamisPalkki.setValue(annaSiivoaminen().annaTarpeenMaara());
	    onnellisuusPalkki.setValue(annaOnnellisuus().annaTarpeenMaara());
	    kuntopalkki.setValue(annaKunto().annaTarpeenMaara());
	    sivistyspalkki.setValue(annaSivistys().annaTarpeenMaara());

	    timer.cancel();
	    palkkipaivittaja();
	}
    }


    /**
     * yritaAloittaaKeskustelu luo uuden keskustelun, jos sellaista ei 
     * aiemmin ollut, ja kutsuu keskustelu -luokan etsiKysymys() metodia tietyin 
     * väliajoin.
     *
     */
    public void yritaAloittaaKeskustelu(){
	if(keskustelu == null){
	    keskustelu = new Keskustelu(this, mieliala, profiilinNimi);
	}
	if(!keskustelu.annaJutusteluKaynnissa()){
	    editorPane.setText(keskustelu.etsiKysymys());
	}
    }
    /**
     * emonKyselynAktiivisuus käynnistää Tehtävä-säikeen
     * tiheys tulee vetopalkista, jolla vaihdetaan emon aktiivisuutta
     * @param tiheys int>
     */
    public void emonKyselynAktiivisuus(int tiheys){
	if(aktiivisuus != null){
	    aktiivisuus.cancel();
	    aktiivisuus = null;
	}
	aktiivisuus = new Timer();
	Tehtava tehtava = new Tehtava();
	tehtava.aktiivisuusSekunnit = tiheys;
	aktiivisuus.schedule(tehtava, tehtava.aktiivisuusSekunnit*1000);
    }
    /**
     * Tehtava -luokka kutsuu aika ajoin yritaAloittaaKeskustelu() 
     * -metodia.
     *
     */
    public class Tehtava extends TimerTask {
	/**
	 * muuttujaaktiivisuusSekunnit on käyttäjän säätämä tiheys
         * yritaAloittaaKeskustelu() metodikutsulle.
	 *
	 */
	public int aktiivisuusSekunnit;
	/**
	 * run On säie, joka toimii kun tietty aika on kulunut.
	 *
	 */
	public void run(){
	    yritaAloittaaKeskustelu();
	    aktiivisuus.cancel();
	    emonKyselynAktiivisuus(aktiivisuusSekunnit);
	}
    }	    
    //kuvan haku on sijoitettu mieliala-luokkaan, koska kuva riippuu 
    //mieliala.annaOlo()sta.
    /**
     * luoImageIcon piirtää kuvan.
     *
     * @param polku String on paikka mistä kuva löytyy
     * @return ImageIcon
     */
    protected static ImageIcon luoImageIcon(String polku) {
        java.net.URL kuvaOsoite = Emo.class.getResource(polku);
        if (kuvaOsoite != null) {
            return new ImageIcon(kuvaOsoite);
        } else {
            System.err.println("Ei löydy: " + polku);
            return null;
        }
    }

    /**
     * haeKuva kysyy mielialaluokalta sopivaa kuvaa
     *
     * @return String, joka on oikeastaan kuvan sijainti
     * (kuvat -nimisessä hakemistossa).
     */
    public String haeKuva(){
	if(mieliala == null){
	    return "neutral";
	}
	else{
	    return mieliala.annaKuva();
	}
    }
    /**
     * tallennaTiedosto luo käyttäjälle profiloidun 
     * tiedoston, jonka käyttäjä voi halutessaan
     * ensi kerralla ohjelmaa käyttäessään avata samalla nimellä ja tunnuksella.
     *
     * @param tiedostonNimi String on tässä 
     * tapauksessa aina profiilin nimi ja profiilin tunnus.
     * @exception IOException jos tiedostontallennuksessa esiintyy ongelmia.
     */
    public void tallennaTiedosto(String tiedostonNimi) throws IOException {
        PrintWriter kirjoittaja = new PrintWriter(new BufferedWriter(
					     new FileWriter(tiedostonNimi)));
	kyllaisyysint = annaKyllaisyys().annaTarpeenMaara();
	vasymysint = annaVasymys().annaTarpeenMaara();
	huviint = annaHuvi().annaTarpeenMaara();
	yksinaisyysint = annaYksinaisyys().annaTarpeenMaara();
	siivoaminenint = annaSiivoaminen().annaTarpeenMaara();
	onnellisuusint = annaOnnellisuus().annaTarpeenMaara();
	sivistysint = annaSivistys().annaTarpeenMaara();
	kuntoint = annaKunto().annaTarpeenMaara();
	kaupassakayntiint = annaKaupassakaynti().annaTarpeenMaara();
	olo = (int)mieliala.annaOlo();

	kirjoittaja.println(profiilinNimi + "&" + kyllaisyysint + "&" + vasymysint +
			    "&" + huviint + "&" + yksinaisyysint + "&" + siivoaminenint + 
			    "&" + onnellisuusint + "&" + sivistysint + "&" + kuntoint +
			    "&" + kaupassakayntiint + "&" + olo + "&");
	kirjoittaja.close();
    }    

    /**
     * unitilanVaihto vaihtaa pelin tilaa:
     * unitila on ikään kuin "pause"-nappi.
     * tila palautetaan vastaavaksi kun nappia painetaan toistamiseen.
     *
     */
    public void unitilanVaihto(){
	if(nukkuuko.equals("Menen nukkumaan")){
	    nukkuuko = "Heräsin";

	    timer.cancel();

	    kyllanappi.setEnabled(false);
	    einappi.setEnabled(false);
	    liukurinArvo = aktiivisuusLiukuri.getValue();
	    aktiivisuusLiukuri.setValue(100);
	    aktiivisuusLiukuri.setEnabled(false);
	    
	    kyllaisyysint = annaKyllaisyys().annaTarpeenMaara();
	    vasymysint = annaVasymys().annaTarpeenMaara();
	    huviint = annaHuvi().annaTarpeenMaara();
	    yksinaisyysint = annaYksinaisyys().annaTarpeenMaara();
	    siivoaminenint = annaSiivoaminen().annaTarpeenMaara();
	    onnellisuusint = annaOnnellisuus().annaTarpeenMaara();

	    annaKyllaisyys().tarpeenMaaranMuutos(-kyllaisyysint);
	    annaSiivoaminen().tarpeenMaaranMuutos(-siivoaminenint);
	    annaVasymys().tarpeenMaaranMuutos(-vasymysint);
	    annaYksinaisyys().tarpeenMaaranMuutos(-yksinaisyysint);
	    annaHuvi().tarpeenMaaranMuutos(-huviint);
	    annaOnnellisuus().tarpeenMaaranMuutos(-onnellisuusint);

	    uninappi.setBorder(BorderFactory.createLoweredBevelBorder());
	}else{
	    nukkuuko = "Menen nukkumaan";
	    if(keskustelu.annaJutusteluKaynnissa()){
		kyllanappi.setEnabled(true);
		einappi.setEnabled(true);
	    }
	    aktiivisuusLiukuri.setValue(liukurinArvo);
	    aktiivisuusLiukuri.setEnabled(true);

	    annaKyllaisyys().tarpeenMaaranMuutos(kyllaisyysint);
	    annaSiivoaminen().tarpeenMaaranMuutos(siivoaminenint);
	    annaVasymys().tarpeenMaaranMuutos(vasymysint);
	    annaYksinaisyys().tarpeenMaaranMuutos(yksinaisyysint);
	    annaHuvi().tarpeenMaaranMuutos(huviint);
	    annaOnnellisuus().tarpeenMaaranMuutos(onnellisuusint);

	    palkkipaivittaja();
	    uninappi.setBorder(BorderFactory.createRaisedBevelBorder());
	}
	uninappi.setText(nukkuuko);
    }
    /**
     * annaKyllanappi palauttaa sen
     * käyttöliittymän napin, jossa lukee "kyllä"
     *
     * @return JButton
     */
    public JButton annaKyllanappi(){
	return kyllanappi;
    }
    /**
     * annaEinappi palauttaa sen
     * käyttöliittymän napin, jossa lukee "ei"
     *
     * @return JButton 
     */
    public JButton annaEinappi(){
	return einappi;
    }
}

5.3 Profiili


import javax.swing.border.EtchedBorder;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;

/**
 * Profiili luokan ilmentymästä valitaan oma profiili. 
 *
 * @author Johannes Koponen
 * @version 1.0
 */
public class Profiili extends JPanel implements ActionListener{
    
    private static final Color TAUSTAVARI = Color.PINK;

    private JFrame ikkuna;
    private String profiilinNimi;
    private String profiilinTunnus;
    private int kyllaisyys;
    private int vasymys;
    private int huvi;
    private int yksinaisyys;
    private int siivoaminen;
    private int onnellisuus;
    private int sivistys;
    private int kunto;
    private int kaupassakaynti;
    private int olo;
    private JLabel toimintaLabel;
    private JLabel tunnusToimintaLabel;
    private JTextField nimiKentta;
    private JTextField tunnusKentta;
    private JButton uusiProfiiliNappi;
    private JButton latausnappi;

    /**
     * Profiilin uuden ilmentymän luonti
     *
     * @param ikkuna JFrame
     */
    public Profiili(JFrame ikkuna){
	super();
	this.ikkuna = ikkuna;
	BorderLayout profiiliPohjaLayout = new BorderLayout();
	JPanel profiiliPohjaPanel = new JPanel(profiiliPohjaLayout);

	JLabel profiiliAsetukset = new JLabel("PROFIILIASETUKSET");
	profiiliAsetukset.setHorizontalAlignment(JLabel.CENTER) ;

	GridLayout syottoLayout = new GridLayout(0,2);
	JPanel syottoPanel = new JPanel(syottoLayout);
	JLabel nimiSyotto = new JLabel("Kirjoita nimesi ");	
	JLabel tunnusSyotto = new JLabel("Kirjoita vapaavalintainen tunnuksesi ");

	GridLayout ylaPalkkiAsettelu = new GridLayout(0,1);
	JPanel ylaPalkki = new JPanel(ylaPalkkiAsettelu);

	ylaPalkki.add(profiiliAsetukset);

	nimiKentta = new JTextField(10);
        nimiKentta.setActionCommand("nimen anto");
        nimiKentta.addActionListener(this);

	tunnusKentta = new JTextField(10);
	tunnusKentta.setActionCommand("tunnuksen anto");
	tunnusKentta.addActionListener(this);

	BorderLayout nappiLayout = new BorderLayout();
	JPanel nappiPanel = new JPanel(nappiLayout);
	uusiProfiiliNappi = new JButton("A) uuden profiilin luomiseen");
	uusiProfiiliNappi.setBorder(BorderFactory.createRaisedBevelBorder());
	uusiProfiiliNappi.setActionCommand("uusiprofiili");
	uusiProfiiliNappi.addActionListener((ActionListener)ikkuna);
	uusiProfiiliNappi.setEnabled(false);
	latausnappi = new JButton("B) vanhan profiilin lataamiseen");
	latausnappi.setBorder(BorderFactory.createRaisedBevelBorder());
	latausnappi.setActionCommand("ladattu");
	latausnappi.addActionListener((ActionListener)ikkuna);
	latausnappi.setEnabled(false);

	JButton tarkistaNappi = new JButton("Hyväksy nimi ja tunnus");
	tarkistaNappi.setBorder(BorderFactory.createRaisedBevelBorder());
	tarkistaNappi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e){
		    boolean nimiOK = false;
		    boolean tunnusOK = false;
		    if(nimiKentta.getText() != null){
			toimintaLabel.setText(nimiKentta.getText());
			profiilinNimi = toimintaLabel.getText();
			if(!(profiilinNimi.equals(""))){
			     nimiOK = true;
			}
		    }
		    if(tunnusKentta.getText() != null){
			tunnusToimintaLabel.setText(tunnusKentta.getText());
			profiilinTunnus = tunnusToimintaLabel.getText();
			if(!(profiilinTunnus.equals(""))){
			    tunnusOK = true;
			}
		    }
		    if(nimiOK && tunnusOK){
			uusiProfiiliNappi.setEnabled(true);
			latausnappi.setEnabled(true);
		    }
		}
	    });

	JButton tyhjennaNappi = new JButton("Tyhjennä tekstikentät");
	tyhjennaNappi.setBorder(BorderFactory.createRaisedBevelBorder());
	tyhjennaNappi.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e){
		    if(nimiKentta.getText() != null){
			nimiKentta.setText("");
			toimintaLabel.setText("");
			profiilinNimi = null;
			uusiProfiiliNappi.setEnabled(false);
			latausnappi.setEnabled(false);
		    }
		    if(tunnusKentta.getText() != null){
			tunnusKentta.setText(null);
			tunnusToimintaLabel.setText(null);
			profiilinTunnus = null;
			uusiProfiiliNappi.setEnabled(false);
			latausnappi.setEnabled(false);
		    }
		}
	    });
	JPanel nappulaPanel = new JPanel();
	nappulaPanel.add(tarkistaNappi);
	nappulaPanel.add(tyhjennaNappi);

	syottoPanel.add(nimiSyotto);
	syottoPanel.add(tunnusSyotto);
	syottoPanel.add(nimiKentta);
	syottoPanel.add(tunnusKentta);

	ylaPalkki.add(syottoPanel);

	profiiliPohjaPanel.add(ylaPalkki, profiiliPohjaLayout.NORTH);

	JPanel nimiPanel = new JPanel();
	JLabel nimi = new JLabel("Nimesi: ");
	nimi.setHorizontalAlignment(JLabel.LEFT) ;

	JPanel tunnusPanel = new JPanel();
	JLabel tunnus = new JLabel("Tunnuksesi: ");
	tunnus.setHorizontalAlignment(JLabel.LEFT) ;
	toimintaLabel = new JLabel("kirjoita nimesi sille varattuun ruutuun");
	tunnusToimintaLabel = new JLabel("kirjoita tunnuksesi sille varattuun ruutuun");
	
	nimiPanel.add(nimi);
	nimiPanel.add(toimintaLabel);
	nimiPanel.setBorder(
                BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
	tunnusPanel.add(tunnus);
	tunnusPanel.add(tunnusToimintaLabel);
	tunnusPanel.setBorder(
                BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
	GridLayout tekstiPaneeliAsettelu = new GridLayout(0,1);
	JPanel tekstiPaneelit = new JPanel(tekstiPaneeliAsettelu);
	tekstiPaneelit.add(nimiPanel);
	tekstiPaneelit.add(tunnusPanel);

	BorderLayout keskiLayout = new BorderLayout();
	JPanel keskiPanel = new JPanel(keskiLayout);
	keskiPanel.add(nappulaPanel, keskiLayout.NORTH);
	keskiPanel.add(tekstiPaneelit, keskiLayout.CENTER);

	profiiliPohjaPanel.add(keskiPanel, profiiliPohjaLayout.CENTER);

	JPanel miksiPanel = new JPanel();
	JLabel miksiTeksti = new JLabel("Käytä näitä tietoja");
	miksiTeksti.setHorizontalAlignment(JLabel.CENTER) ;

	miksiPanel.add(miksiTeksti);

	nappiPanel.add(miksiPanel, nappiLayout.NORTH);
	JPanel sisaNappiPanel = new JPanel();
	sisaNappiPanel.add(uusiProfiiliNappi);
	sisaNappiPanel.add(latausnappi);
	nappiPanel.add(sisaNappiPanel, nappiLayout.CENTER);

	profiiliPohjaPanel.add(nappiPanel, profiiliPohjaLayout.SOUTH);
	
	maalaa(profiiliPohjaPanel);
	this.add(profiiliPohjaPanel);
    }
    /**
     * maalaa värittää profiilin paneeleita sopivasti
     *
     * @param k JPanel se JPanel, jonka osat halutaan
     * maalata.
     */
    public void maalaa(JPanel k){
	k.setBackground(TAUSTAVARI);
	Component[] komponentit = k.getComponents();
	int pituus = komponentit.length;
	for(int t = 0; t < pituus; t++){
	    Component kompo = komponentit[t];
	    if(kompo instanceof JPanel){
		JPanel kompot = (JPanel)kompo;
		Component[] kompokomponentit = kompot.getComponents();
		kompot.setBackground(TAUSTAVARI);
		if(kompokomponentit.length > 0){
		    for(int p = 0; p < kompokomponentit.length; p++){
			if(kompokomponentit[p] instanceof JPanel){
			    JPanel kompott = (JPanel)kompokomponentit[p];
			    maalaa(kompott);
			}
			else{
			    kompokomponentit[p].setBackground(TAUSTAVARI.darker());
			}
		    }
		}
	    }
	    else{
		if(!(kompo instanceof JTextField)){
		    kompo.setBackground(TAUSTAVARI.darker());
		}
	    }
	}
    }

    /**
     * annaProfiilinNimi palauttaa muuten yksityisen profiiilin
     * nimen sitä kutsuville.
     *
     * @return String
     */
    public String annaProfiilinNimi(){
	return profiilinNimi;
    }
    /**
     * annaProfiilinTunnus palauttaa profiilin tunnuksen
     *
     * @return String 
     */
    public String annaProfiilinTunnus(){
	return profiilinTunnus;
    }
			     
    /**
     * actionPerformed toteuttaa ActionListener rajapinnan
     * ja antaa toteutuksen erilaisille käyttäjän tuottamille tapahtumille
     *
     * @param e ActionEvent
     */
    public void actionPerformed(ActionEvent e) {

	if (e.getActionCommand().equals("nimen anto")) {
	    JTextField source = (JTextField)e.getSource();
	    toimintaLabel.setText(source.getText());
	    profiilinNimi = toimintaLabel.getText();
	}
	if(e.getActionCommand().equals("tunnuksen anto")){
	    JTextField source = (JTextField)e.getSource();
	    tunnusToimintaLabel.setText(source.getText());
	    profiilinTunnus = tunnusToimintaLabel.getText();
	}
    }
    /**
     * lataaTiedosto hakee profiilin nimen ja tunnuksen perusteella
     * tiedostoa, jossa on käyttäjän edellisen käyttökerran tiedot.
     *
     * @param tiedostonNimi String
     * @return Emon 
     * @exception IOException heitetään jos tiedostoa ei löydy tai on muuta filunkia.
     */
    public Emo lataaTiedosto(String tiedostonNimi) throws IOException{
        BufferedReader lukija = new BufferedReader(
						   new FileReader(tiedostonNimi));
        String line;
        if ((line = lukija.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(line, "&");
	    profiilinNimi = st.nextToken();
	    kyllaisyys = Integer.parseInt(st.nextToken());
	    vasymys = Integer.parseInt(st.nextToken());
	    huvi = Integer.parseInt(st.nextToken());
	    yksinaisyys = Integer.parseInt(st.nextToken());
	    siivoaminen = Integer.parseInt(st.nextToken());
	    onnellisuus = Integer.parseInt(st.nextToken());
	    sivistys =  Integer.parseInt(st.nextToken());
	    kunto = Integer.parseInt(st.nextToken()); 
	    kaupassakaynti = Integer.parseInt(st.nextToken());
	    olo = Integer.parseInt(st.nextToken());
        }
        lukija.close();
	return new Emo(profiilinNimi, kyllaisyys, vasymys, huvi, 
                       yksinaisyys, siivoaminen, onnellisuus, 
                       sivistys, kunto, kaupassakaynti, olo);
	
    }
}
    

5.4 Keskustelu


import java.util.HashSet;
import java.util.Random;
import java.util.Iterator;

/**
 * Keskustelu pitää sisällään monenmoisia loogisia kysymysketjuja, 
 * joihin voi vastata kyllä tai ei. Se sisältää myös keinon löytää tärkein 
 * keskustelunaihe Tarve-luokkien avulla.
 *
 * @author Johannes Koponen
 * @version 1.1
 */
public class Keskustelu{

    private String edellinenKeskustelu;
    private String profiilinNimi;
    private String edellinenKysymys;
    private boolean jutusteluKaynnissa;
    private String kysymys;
    private Mieliala mieliala;
    private Random rand = new Random();
    private Emo emo;

    /**
     * Luopi upouuden Keskustelun
     *
     * @param emo  Emo 
     * @param mieliala Mieliala 
     * @param profiilinNimi String
     */
    public Keskustelu(Emo emo, Mieliala mieliala, String profiilinNimi){
	this.emo = emo;
	this.mieliala = mieliala;
	this.profiilinNimi = profiilinNimi;
	jutusteluKaynnissa = false;
    }

    /**
     * annaJutusteluKaynnissa on 
     * julkinen toteutus yksityiselle totuusarvolle
     * Kertoo, josko keskustelua on syytä vielä käydä kyseisestä aiheesta.
     * @return boolean.
     */
    public boolean annaJutusteluKaynnissa(){
	return jutusteluKaynnissa;
    }
    
    /**
     * vastaa antaa emolle loogisen seuraavan kysymyksen.
     *
     * @param vastaus on boolean.
     * @return  String.
     */
    public String vastaa(boolean vastaus){
	edellinenKysymys = kysy(vastaus);
	return edellinenKysymys;
    }

    /**
     * etsiKysymys antaa keskustelunaiheeksi sen kysymyksen, 
     * joka on ohjelman mukaan tällä hetkellä kriittinen. Mieliala vaikuttaa
     * kysymyksen valintaan, koska se painottaa todennäköisyyttä keskustella
     * tietyistä aiheista. Vihainen emo patistaa mieluummin siivoamaan ja 
     * iloinen syömään ja huvittelemaan.
     *
     * @return String. Palauttaa ensimmäisen 
     * kysymyksen (eli aina uuden keskustelunavauksen).
     */
    public String etsiKysymys(){
	double d = 0;
	Iterator tarveiteraattori = emo.annaTarpeetSet().iterator();
	HashSet aiheet = new HashSet();
	if(tarveiteraattori.hasNext()){
	    jutusteluKaynnissa = true;
	    while(tarveiteraattori.hasNext()){
		Tarve tarve = (Tarve)tarveiteraattori.next();
		String lause = tarve.annaTarvelause();
		if(!lause.equals(edellinenKeskustelu)){
		    aiheet.add(lause);
		}
	    }
	    //edellinenKysymys on viimeinen käyttäjälle edennyt viesti.
	    //edellinenKeskustelu on viimeisen keskustelun aloittanu viesti.
	  
	    if(mieliala.annaOlo() < -22){
		do{
		    d = rand.nextDouble();
		    
		    if(d < 0.05 && aiheet.contains(emo.annaKyllaisyys().
                                 annaTarvelause())){
			kysymys = emo.annaKyllaisyys().annaTarvelause();
		    }
		    if((d >= 0.05 && d < 0.15) && aiheet.contains(
                                     emo.annaVasymys().annaTarvelause())){
			kysymys = emo.annaVasymys().annaTarvelause();
		    }
		    if((d >= 0.15 && d < 0.24) && aiheet.contains(
                                     emo.annaYksinaisyys().annaTarvelause())){
			kysymys = emo.annaYksinaisyys().annaTarvelause();
		    }
		    if((d >= 0.24 && d < 0.29) && aiheet.contains(
                                     emo.annaHuvi().annaTarvelause())){
			kysymys = emo.annaHuvi().annaTarvelause();
		    }
		    if((d >= 0.29 && d < 0.36) && aiheet.contains(
                                     emo.annaOnnellisuus().annaTarvelause())){
			kysymys = emo.annaOnnellisuus().annaTarvelause();
		    }
		    if((d >= 0.36 && d < 0.48) && (aiheet.contains(
                                     emo.annaSivistys().annaTarvelause()))){
			kysymys = emo.annaSivistys().annaTarvelause();
		    }
		    if((d >= 0.48 && d < 0.70) && (aiheet.contains(
                                     emo.annaSiivoaminen().annaTarvelause()))){
			kysymys = emo.annaSiivoaminen().annaTarvelause();
		    }
		    if((d >= 0.70 && d < 0.85) && (aiheet.contains(
                                     emo.annaKunto().annaTarvelause()))){
			kysymys = emo.annaKunto().annaTarvelause();
		    }
		    if(d >= 0.85 && aiheet.contains(
                                    emo.annaKaupassakaynti().annaTarvelause())){
			kysymys = emo.annaKaupassakaynti().annaTarvelause();
		    }
		}while(kysymys.equals(edellinenKysymys));
	    }
	    if(mieliala.annaOlo() >= -22 && mieliala.annaOlo() < -7){
		do{
		    d = rand.nextDouble();
		    
		    if(d < 0.07 && aiheet.contains(
                                  emo.annaKyllaisyys().annaTarvelause())){
			kysymys = emo.annaKyllaisyys().annaTarvelause();
		    }
		    if((d >= 0.07 && d < 0.18) && aiheet.contains(
                                     emo.annaVasymys().annaTarvelause())){
			kysymys = emo.annaVasymys().annaTarvelause();
		    }
		    if((d >= 0.18 && d < 0.29) && aiheet.contains(
                                     emo.annaYksinaisyys().annaTarvelause())){
			kysymys = emo.annaYksinaisyys().annaTarvelause();
		    }
		    if((d >= 0.29 && d < 0.34) && aiheet.contains(
                                     emo.annaHuvi().annaTarvelause())){
			kysymys = emo.annaHuvi().annaTarvelause();
		    }
		    if((d >= 0.34 && d < 0.44) && aiheet.contains(
                                     emo.annaOnnellisuus().annaTarvelause())){
			kysymys = emo.annaOnnellisuus().annaTarvelause();
		    }
		    if((d >= 0.44 && d < 0.58) && (aiheet.contains(
                                     emo.annaSivistys().annaTarvelause()))){
			kysymys = emo.annaSivistys().annaTarvelause();
		    }
		    if((d >= 0.58 && d < 0.7) && (aiheet.contains(
                                     emo.annaSiivoaminen().annaTarvelause()))){
			kysymys = emo.annaSiivoaminen().annaTarvelause();
		    }
		    if((d >= 0.7 && d < 0.88) && (aiheet.contains(
                                    emo.annaKunto().annaTarvelause()))){
			kysymys = emo.annaKunto().annaTarvelause();
		    }
		    if(d >= 0.88 && aiheet.contains(
                                    emo.annaKaupassakaynti().annaTarvelause())){
			kysymys = emo.annaKaupassakaynti().annaTarvelause();
		    }
		}while(kysymys.equals(edellinenKysymys));
	    }
	    if((mieliala.annaOlo() >= -7) && (mieliala.annaOlo() < 9)){
		do{
		    d = rand.nextDouble();

		    if(d < 0.12 && aiheet.contains(
                                     emo.annaKyllaisyys().annaTarvelause())){
			kysymys = emo.annaKyllaisyys().annaTarvelause();
		    }
		    if((d >= 0.12 && d < 0.24) && aiheet.contains(
                                     emo.annaVasymys().annaTarvelause())){
			kysymys = emo.annaVasymys().annaTarvelause();
		    }
		    if((d >= 0.24 && d < 0.38) && aiheet.contains(
                                     emo.annaYksinaisyys().annaTarvelause())){
			kysymys = emo.annaYksinaisyys().annaTarvelause();
		    }
		    if((d >= 0.38 && d < 0.47) && aiheet.contains(
                                     emo.annaHuvi().annaTarvelause())){
			kysymys = emo.annaHuvi().annaTarvelause();
		    }
		    if((d >= 0.47 && d < 0.6) && aiheet.contains(
                                     emo.annaOnnellisuus().annaTarvelause())){
			kysymys = emo.annaOnnellisuus().annaTarvelause();
		    }
		    if((d >= 0.6 && d < 0.7) && (aiheet.contains(
                                    emo.annaSivistys().annaTarvelause()))){
			kysymys = emo.annaSivistys().annaTarvelause();
		    }
		    if((d >= 0.7 && d < 0.8) && (aiheet.contains(
                                    emo.annaSiivoaminen().annaTarvelause()))){
			kysymys = emo.annaSiivoaminen().annaTarvelause();
		    }
		    if((d >= 0.8 && d < 0.9) && (aiheet.contains(
                                    emo.annaKunto().annaTarvelause()))){
			kysymys = emo.annaKunto().annaTarvelause();
		    }
		    if(d >= 0.9 && aiheet.contains(
                                    emo.annaKaupassakaynti().annaTarvelause())){
			kysymys = emo.annaKaupassakaynti().annaTarvelause();
		    }
		}while(kysymys == null || kysymys.equals(edellinenKysymys));
	    }
	    if(mieliala.annaOlo() >= 9 && mieliala.annaOlo() < 29){
		do{
		    d = rand.nextDouble();

		    if(d < 0.2 && aiheet.contains(
                                    emo.annaKyllaisyys().annaTarvelause())){
			kysymys = emo.annaKyllaisyys().annaTarvelause();
		    }
		    if((d >= 0.2 && d < 0.3) && aiheet.contains(
                                    emo.annaVasymys().annaTarvelause())){
			kysymys = emo.annaVasymys().annaTarvelause();
		    }
		    if((d >= 0.3 && d < 0.35) && aiheet.contains(
                                    emo.annaYksinaisyys().annaTarvelause())){
			kysymys = emo.annaYksinaisyys().annaTarvelause();
		    }
		    if((d >= 0.35 && d < 0.5) && aiheet.contains(
                                     emo.annaHuvi().annaTarvelause())){
			kysymys = emo.annaHuvi().annaTarvelause();
		    }
		    if((d >= 0.5 && d < 0.65) && aiheet.contains(
                                    emo.annaOnnellisuus().annaTarvelause())){
			kysymys = emo.annaOnnellisuus().annaTarvelause();
		    }
		    if((d >= 0.65 && d < 0.75) && (aiheet.contains(
                                     emo.annaSivistys().annaTarvelause()))){
			kysymys = emo.annaSivistys().annaTarvelause();
		    }
		    if((d >= 0.75 && d < 0.8) && (aiheet.contains(
                                     emo.annaSiivoaminen().annaTarvelause()))){
			kysymys = emo.annaSiivoaminen().annaTarvelause();
		    }
		    if((d >= 0.8 && d < 0.9) && (aiheet.contains(
                                    emo.annaKunto().annaTarvelause()))){
			kysymys = emo.annaKunto().annaTarvelause();
		    }
		    if(d >= 0.9 && aiheet.contains(
                                    emo.annaKaupassakaynti().annaTarvelause())){
			kysymys = emo.annaKaupassakaynti().annaTarvelause();
		    }
		}while(kysymys.equals(edellinenKysymys));
	    }
	    if(mieliala.annaOlo() >= 29){
		
		do{
		    d = rand.nextDouble();
		    
		    if(d < 0.22 && aiheet.contains(
                                     emo.annaKyllaisyys().annaTarvelause())){
			kysymys = emo.annaKyllaisyys().annaTarvelause();
		    }
		    if((d >= 0.22 && d < 0.32) && aiheet.contains(
                                     emo.annaVasymys().annaTarvelause())){
			kysymys = emo.annaVasymys().annaTarvelause();
		    }
		    if((d >= 0.32 && d < 0.43) && aiheet.contains(
                                     emo.annaYksinaisyys().annaTarvelause())){
			kysymys = emo.annaYksinaisyys().annaTarvelause();
		    }
		    if((d >= 0.43 && d < 0.6) && aiheet.contains(
                                     emo.annaHuvi().annaTarvelause())){
			kysymys = emo.annaHuvi().annaTarvelause();
		    }
		    if((d >= 0.6 && d < 0.75) && aiheet.contains(
                                    emo.annaOnnellisuus().annaTarvelause())){
			kysymys = emo.annaOnnellisuus().annaTarvelause();
		    }
		    if((d >= 0.75 && d < 0.85) && (aiheet.contains(
                                     emo.annaSivistys().annaTarvelause()))){
			kysymys = emo.annaSivistys().annaTarvelause();
		    }
		    if((d >= 0.85 && d < 0.9) && (aiheet.contains(
                                     emo.annaSiivoaminen().annaTarvelause()))){
			kysymys = emo.annaSiivoaminen().annaTarvelause();
		    }
		    if((d >= 0.9 && d < 0.97) && (aiheet.contains(
                                    emo.annaKunto().annaTarvelause()))){
			kysymys = emo.annaKunto().annaTarvelause();
		    }
		    if(d >= 0.97 && aiheet.contains(
                                  emo.annaKaupassakaynti().annaTarvelause())){
			kysymys = emo.annaKaupassakaynti().annaTarvelause();
		    }
		}while(kysymys.equals(edellinenKysymys));
	    }	
	}
	else{
	    kysymys = muutPuuhat();
	    jutusteluKaynnissa = false;
	}
	edellinenKeskustelu = kysymys;
	return kysymys;
    }

    /**
     * muutPuuhat palauttaa kysyttäessä arvotun yhdentekevän tekstipätkän
     *
     * @return String 
     */
    public String muutPuuhat(){
	String lause = null;
	double e = rand.nextDouble();
	if(e > 0.2){
	    lause = "Tiedätkös, " + profiilinNimi + ", Emolla on joskus muutakin
                     puuhaa. Aina sinua ei ehdi paapoa";
	}
	if(e >= 0.2 && e < 0.4){
	    lause = "Emo järjestelee kaappeja"; 
	}
	if(e >= 0.4 && e < 0.6){
	    lause = "Emo katselee saippuasarjaa televisiosta"; 
	}
	if(e >= 0.6 && e < 0.8){
	    lause = "Emo kuorsaa sikeästi olohuoneen sohvalla"; 
	}
    	else{
	    lause = "Emolla on muita hommia.";
	}
	edellinenKysymys = lause;
	return lause;
    }

   /**
     *  kysy-metodi pitää yllä keskustelua käyttäjän kanssa 
     *
     * @param vastaus on boolean, ja kertoo vastasiko käyttäjä edelliseen
     * kysymykseen kyllä vai ei.
     * @return  String. Palauttaa seuraavan kysymyksen.
     */
    public String kysy(boolean vastaus){
	edellinenKysymys = kysymys;

	if(jutusteluKaynnissa){
	    if(kysymys == null){
		//tapahtuu, jos ohjelmaan laajennettaessa luodaan tarpeita, 
                //joille ei anneta tekstimuotoista asua.
		System.err.println("KYSYMYS ON NULL");
		kysymys = "Kuules nyt, " + profiilinNimi + ", 
                           Emolla on joskus muutakin puuhaa"; 
		jutusteluKaynnissa = false;
	    }
	    if(kysymys.equals(emo.annaSivistys().annaTarvelause())){
		if(vastaus){
		    emo.annaSivistys().tarpeenMaaranMuutos(40);
		    kysymys = "Hienoa!. Entäs oletko päntännyt niitä
 opiskeluun liittyen?"; 
		}
		else{
		    kysymys = "Et edes yhtään opusta opiskeluun liittyen?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals(emo.annaKunto().annaTarvelause())){
		if(vastaus){
		    emo.annaKunto().tarpeenMaaranMuutos(60);
		    kysymys = kehaise() + "Mites tuntuuko ettei urheilu
 väsytä sinua enää huomenna?"; 
		}
		else{
		    kysymys = "Eikös sitten päivän pelastaisi reipas urheilu?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Mites tuntuuko ettei
 urheilu väsytä sinua enää huomenna?")){ 
		if(vastaus){
		    kysymys = "No, ehkä kannattaisi kuitenkin levätä nyt. 
Jos kaivaisit jonkun levyn hyllystä, pistäisit sen soimaan ja venyttelisit kunnolla?";
		}
		else{
		    kysymys = "Oletko viime aikoina ajatellut usein negatiivisia
 ajatuksia?";
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("venyttelisit kunnolla?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(10);
		    kysymys = "Älä sitten venyttele liian pitkään. 
Ja muista levätä myös henkisesti - mitä se sitten tarkoittaakin";
		    jutusteluKaynnissa = false;
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "No ei sitten. Mutta hirveästi ei kannattaisi hösätä.";
		}
		return kysymys;
	    }
	    if(kysymys.equals(emo.annaKaupassakaynti().annaTarvelause())){
		if(vastaus){
		    jutusteluKaynnissa = false;
		    emo.annaKaupassakaynti().tarpeenMaaranMuutos(100);
		    kysymys = "Oivallisesti tehty. " + kehaise();
		}
		else{
		    kysymys =  "Pistäytyisitkö sitten pikavisiitillä kaupassa?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("opiskeluun liittyen?")){
		if(vastaus){
		    emo.annaSivistys().tarpeenMaaranMuutos(20);
		    kysymys = "Tämä on lähestulkoon liian hyvää ollakseen totta " +
			kehaise() + "Tuollainen täydellisyyden ilmentymä
 on varmaan myös tiskannut astiat?"; 
		}
		else{
		    emo.annaSivistys().tarpeenMaaranMuutos(-25);
		    kysymys = tuhahda() + "Mitä jos lukisit nyt jotain
 korkealentoista ja sivistävää?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("tiskannut astiat?")){
		if(vastaus){
		    kysymys = kehaise();
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "No en ihmettele. Ei sitä kukaan kaikkea ehdi.";
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("korkealentoista ja sivistävää?")){
		if(vastaus){
		    emo.annaSivistys().tarpeenMaaranMuutos(30);
		    kysymys = kehaise() +"Mites kai olet muistanut lenkkeillä 
ja urheilla? Ihan hyvää tekisi sellainen tunnin - parin urheilu?"; 
		}
		else{
		    kysymys = "No hyvä elokuva sitten? Käy lainaamassa vuokraamosta,
 kirjastosta tai kaverilta ja pidä mukava elokuvailta."; 
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("No hyvä elokuva sitten?")){
		if(vastaus){
		    emo.annaSivistys().tarpeenMaaranMuutos(20);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(5);
		    kysymys = kehaise() + "Saisitko ketään katsomaan sitä kanssasi?";
		}
		else{
		    kysymys = "Katsoisit edes TV-uutisia?";
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Saisitko ketään katsomaan sitä kanssasi?")){
		if(vastaus){
		    emo.annaYksinaisyys().tarpeenMaaranMuutos(30);
		    kysymys = "Hauskaa!";
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "No mutta yksin siitä nauttii enemmän!";
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.equals("Katsoisit edes TV-uutisia?")){
		if(vastaus){
		    emo.annaSivistys().tarpeenMaaranMuutos(10);
		    kysymys = kehaise();
		    jutusteluKaynnissa = false;
		}
		else{
		    emo.annaSivistys().tarpeenMaaranMuutos(-10);
		    kysymys = tuhahda();
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
		
	    if(kysymys.equals("Katsopa ympärillesi. Onko huone siisti?")){
		if(vastaus){
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(50);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-20);
		    int arvaus = rand.nextInt(3);
		    String lopetus;
		    if(arvaus <= 1){
			lopetus = "Entä oletko viimeisen puolentoista viikon
 aikana kuurannut vessan?"; 
		    }
		    if(arvaus == 2){
			lopetus = "Oletko muuten muistanut kastella kukat?"; 
		    }
		    else{
			lopetus = "Keittiö on toivottavasti siisti myös?"; 
		    }
		    
		    kysymys = kehaise() + " " + lopetus; 
		}else{
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(-40);
		    kysymys = "Siivoatko sen nyt?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("kuurannut vessan?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-25);
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(80);
		    kysymys = kehaise();
		    jutusteluKaynnissa = false;
		}
		else{
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(-25);
		    kysymys = "Pitäisiköhän sinun sitä sitten?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Pitäisiköhän sinun sitä sitten?")){
		if(vastaus){
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(90);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-30);
		    if(mieliala.annaOlo() > 2){
			kysymys = kehaise();
			jutusteluKaynnissa = false;
		    }
		    else{
			kysymys = tuhahda(); 
			jutusteluKaynnissa = false;
		    }
		}
		else{
		    if(mieliala.annaOlo() < 6){
			kysymys = "Myönnä pois, olet laiska. 
Oletko muuten muistanut kastella kukat?"; 
		    }
		    else{
			kysymys = "No joo, okei. Ei se varmaan ole edes likainen - -"; 
			jutusteluKaynnissa = false;
		    }
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Oletko muuten muistanut kastella kukat?")){
		if(vastaus){
		    if(mieliala.annaOlo() > -7){
			kysymys = "Et kai sinä vaan ole rakastunut?"; 
		    }
		    else{
			kysymys = "Hymf. Sitä ollaan niin aina niin 
valmiita, että! Onko sinulla edes omia kukkia?"; 
		    }
		}
		else{
		    if(mieliala.annaOlo() > 3){
			kysymys = "Kastelelisitko heti?"; 
		    }
		    else{
			kysymys = "Kastele heti!"; 
			emo.annaOnnellisuus().tarpeenMaaranMuutos(-10);
		    }
		}
		return kysymys;
	    }	   
	    if(kysymys.endsWith("sinulla edes omia kukkia?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(20);
		    kysymys = "Ne kyllä lisäävät viihtyisyyttä!"; 
		    jutusteluKaynnissa = false;
		}
		else {
		    kysymys = "Ja silti väität, että olet kastellut ne? 
Taisit puhua itsesi hieman pussiin? Valehtelu on typerää!"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Valehtelu on typerää!")){
		kysymys = "Nyt heräsikin epäilys, että kuinka paljon olet
 minulle valehdellut? Mitä jos istutkin kaikki päivät tietokoneen edessä
 sipsejä syöden ja väität sinisin silmin siivoavasi samalla kun juokset 
lenkkiä? Epäilys jäytää!"; 
		mieliala.asetaOlo(-50);
		jutusteluKaynnissa = false;
		return kysymys;
	    }
	    
	    if(kysymys.startsWith("Kastele")){
		if(vastaus){
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(5);
		    kysymys = "Hyvin tehty! Kukkia pitää vaalia!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "Kukat kuolevat jos niille ei anna vettä."; 
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("rakastunut?")){
		if(vastaus){
		    emo.annaHuvi().tarpeenMaaranMuutos(20);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(20);
		    emo.annaYksinaisyys().tarpeenMaaranMuutos(70);
		    if(mieliala.annaOlo() > 2){
			kysymys = "Voi miten ihanaa! Sinä säteilet valoa ympäristöösi,
 myönnetään! Tästä tulikin mieleeni: mitä jos kävisit hankkimassa vaikka jonkun kivan
 vaatteen itsellesi?"; 
		    }
		    else{
			emo.annaOnnellisuus().tarpeenMaaranMuutos(15);
			kysymys = "Jaahas. Mihinkään riiaamaan on turha pyrkiä ennen
 kuin koti on kunnossa. Mitä sekin riekkonen ajattelisi kun tänne tulisi! Kävisitkö - 
ihan vaan muonavarojen täydentämisen vuoksi - kaupassa? Osta vaikka munia."; 
		    }
		}
		else{
		    if(mieliala.annaOlo() < -30){
			emo.annaOnnellisuus().tarpeenMaaranMuutos(-40);
			kysymys = "Taidat olla niin ilkeä ettet ilkeä edes rakastua?"; 
		    }
		    if(mieliala.annaOlo() >= -30 && mieliala.annaOlo() < 10){
			kysymys = "Oletko sinä juonut jotain alkoholia? 
Kun hekumoit tuolla tavalla?"; 
		    }
		    else{
			kysymys = "Ottaisitko suklaata? Se ajaa saman asian"; 
		    }
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("kivan vaatteen itsellesi?")){
		if(vastaus){
		    kysymys = "Onko nyt mielestäsi hyvä aika lähteä vaatekauppaan 
ja viitsitkö sinne lähteä?";
		}
		else{
		    kysymys = "No ei sitten. Mutta muista nyt ainakin välillä 
pestä niitä vanhoja vaatteitasi!";
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("viitsitkö sinne lähteä?")){
		if(vastaus){
		    kysymys = "No hauskaa shoppailua! Älä käytä liikaa rahaa!";
		}
		else{
		    kysymys = "Hanki niitä vaatteita sitten joskus myöhemmin!";
		}
		jutusteluKaynnissa = false;
		return kysymys;
	    }
	    if(kysymys.equals("Taidat olla niin ilkeä ettet ilkeä edes rakastua?")){
		jutusteluKaynnissa = false;
		if(vastaus){
		    kysymys = "Nirppis!"; 
		}
		else{
		    kysymys = "No sitähän minäkin"; 
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("Oletko sinä juonut jotain alkoholia?")){
		if(vastaus){
		    emo.annaVasymys().tarpeenMaaranMuutos(-20);
		    emo.annaHuvi().tarpeenMaaranMuutos(25);
		    kysymys = "Herranenaika! Noin röyhkeä!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "No minä jo säikähdin"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Ottaisitko suklaata? Se ajaa saman asian")){
		if(vastaus){
		    emo.annaKyllaisyys().tarpeenMaaranMuutos(22);
		    kysymys = "Se tekee sinulle vain hyvää!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    if(mieliala.annaOlo() < 10){
			kysymys = "Totta. Ehkä sinun kannattaisi suklaan sijasta
 käydä lenkillä?"; 
		    }
		    else{
			kysymys = "Ehkä ensi kerralla."; 
			jutusteluKaynnissa = false;
		    }
		}
		return kysymys;
	    }
			
	    if(kysymys.endsWith("Osta vaikka munia.")){
		if(vastaus){
		    kysymys = "Muista ottaa omat muovipussit mukaan niin
 et pilaa luontoa!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "Onhan jääkaapissa varmasti riittävästi ruokaa"; 
		}
	    }
	    if(kysymys.endsWith("Keittiö on toivottavasti siisti myös?")){
	       if(vastaus){
		   if(mieliala.annaOlo() > 2){
		       emo.annaSiivoaminen().tarpeenMaaranMuutos(0);
		       kysymys = "Niinpä tietysti, turhaan utelin."; 
		   }
		   else{
		       kysymys = "yllättävää."; 
		   }
		   jutusteluKaynnissa = false;
	       }
	       else{
		    if(mieliala.annaOlo() > 2){
			kysymys = "No kuules. Pitäisiköhän sinun tehdä ihan
 kunnon vanhanaikanen suursiivous?"; 
		   }
		   else{
		       kysymys = "Ei hämmästytä yhtään. Tuollainen laiskimus. 
Kuules: miten olisi oikein kunnon suursiivous?"; 
		   }
	       }
	       return kysymys;
	    }
	    if(kysymys.endsWith("suursiivous?")){
		if(vastaus){
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(100);
		    kysymys = "Veisitkö roskat ulos sitten kun olet siivonnut. 
Hässäkän jälkeen voit onnitella itseäsi!"; 
		}
		else{
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(-10);
		    kysymys = "Veisitkö roskat ulos? Kyllä sinunkin täytyy
 jotain tehdä!"; 
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("Veisitkö roskat ulos")){
		if(vastaus){
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(30);
		    kysymys = "Hapen haukkaaminen tekee hyvää koko ruumiille ihan
 muutenkin"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "Mahdoton. Pian ryvet kuin sika lätissä."; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Siivoatko sen nyt?")){
	       if(vastaus){
		   emo.annaSiivoaminen().tarpeenMaaranMuutos(90);
		   if(mieliala.annaOlo() < 0){
		       kysymys = "Tekee sinulle vain hyvää"; 
		       jutusteluKaynnissa = false;
		   }
		   else{
		       kysymys = kehaise() + "Muista että se on vain hyväksi"; 
		       jutusteluKaynnissa = false;
		   }
	       }
	       else{
		   if(mieliala.annaOlo() < 9){
		       kysymys = "Otapa itseäsi niskasta kiinni! Tuollainen peli
 ei vetele! Älä sitten siivoa nyt, mutta myöhemmin joudut sen tekemään
 joka tapauksessa!"; 
		       jutusteluKaynnissa = false;
		   }
		   else{
		       kysymys = "No ei sitten. Ei se huone  niin  likainen ole."; 
		       jutusteluKaynnissa = false;
		   }
	       }
	       return kysymys;
	    }
	    if(kysymys.equals("Oletko viime aikoina ajatellut usein 
                               negatiivisia ajatuksia?")){
		if(vastaus){
		    emo.annaHuvi().tarpeenMaaranMuutos(-70);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-70);
		    if(mieliala.annaOlo() < -4){
			kysymys = "No sen siitä saa. Tottelisit minua niin asiat
 olisivat paremmin. Vai?"; 
		    }
		    if(mieliala.annaOlo() < 4 && mieliala.annaOlo() >= -4){
			kysymys = "No voi sentään. Mitä jos söisit hieman suklaata
 ja vaikka vuokraisit elokuvan?"; 
		    }
		    else{
			kysymys = "Mikä nallekarhuni ja oman pikku natuseni on noin
 maihin ajanut? Mitä jos lähtisit Linnanmäelle?"; 
		    }
		}else{
		    kysymys = "Entä tunnetko pitäväsi elämänlankojasi omissa käsissäsi?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("No sen siitä saa. Tottelisit minua niin asiat olisivat
 paremmin. Vai?")){
		if(vastaus){
		    jutusteluKaynnissa = false;
		    kysymys = "No just niin. Ei mitään hätää, kaikki järjestyy."; 
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "Pöyhkeä elvis! Ihme " + profiilinNimi 
+ "! " + tuhahda(); 
		    
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Mitä jos lähtisit Linnanmäelle?")){
		if(vastaus){
		    emo.annaHuvi().tarpeenMaaranMuutos(0);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(40);
		    kysymys = "Pyytäisitkö ystäviä mukaan?"; 
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "Niin. Liekö edes auki tähän aikaan.";
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-3);
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("vuokraisit elokuvan?")){
		if(vastaus){
		    emo.annaHuvi().tarpeenMaaranMuutos(20);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(15);
		    jutusteluKaynnissa = false;
		    int i = rand.nextInt(2);
		    if(i <= 1){kysymys = "Nauti. Ja muista etteivät elokuva ja
 suklaa ole vaihtoehtoisia.";} 
		    else{kysymys = "Suklaata syödessäsi muista syödä paras 
ensiksi: siten sinulla on aina paras myös jäljellä!"; 
		    }
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "Askeettisuudesta ei elämässä saa lisäpisteitä"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Entä tunnetko pitäväsi elämänlankojasi omissa 
käsissäsi?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(5);
		    if(mieliala.annaOlo() < 9){
			kysymys = "Hehehee. Niin valheellista, niin valheellista
 on tämä elämä. Tunnetko olosi euforiseksi?"; 
		    }
		    else{
			kysymys = "Tunnetko olosi euforiseksi?"; 
		    }
		    
		}else{
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-5);
		    emo.annaHuvi().tarpeenMaaranMuutos(-40);
		    kysymys = "Heh. No sitähän minäkin."; 
		    jutusteluKaynnissa = false;
		    
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Tunnetko olosi euforiseksi?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(80);
		    emo.annaHuvi().tarpeenMaaranMuutos(20);
		    if(mieliala.annaOlo() < 5){
			kysymys = "Oletko sinä juonut jotain alkoholia? Et kai
 vaan käytä huumeita?";
		    }
		    else{
			kysymys = "No mutta tämähän on mahtavaa!"; 
			jutusteluKaynnissa = false;
		    }
		}
		else{
		    jutusteluKaynnissa = false;
		    kysymys = "Aina ei tarvitse."; 
		}
		return kysymys;
	    }
	    
			
	    if(kysymys.equals("Onko tylsää?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-10);
		    kysymys = "Haluaisitko äksöniä?"; 
		}else{
		    int arpa = rand.nextInt(4);
		    String loppu;
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(20);
		    emo.annaHuvi().tarpeenMaaranMuutos(50);
		    jutusteluKaynnissa = false;
		    if(arpa < 2){kysymys = "No kiva kuulla.";} 
		    if(arpa == 3){kysymys = "Ai. Mukavaa";} 
		    else{
			jutusteluKaynnissa = true;
			if(emo.annaYksinaisyys().annaTarpeenMaara() < 40){
			    loppu = "Oletko muuten tavannut muita ihmisiä 
pitkään aikaan?";
			}
			else{
			    loppu = "Tämän takia uskallankin kysyä: joisitko
 lasin porkkanamehua, jo pelkästään vitamiinien vuoksi.";
			}
			kysymys = "Hyvä. Elämässäsi on ilmeisesti riittävästi 
huvitusta tällä hetkellä." + loppu; 
		    }
		}
		return kysymys;
	    }
	    if(kysymys.equals("Haluaisitko äksöniä?")){
		if(vastaus){
		    if(emo.annaYksinaisyys().annaTarpeenMaara() < 30){
			kysymys = "Jaksaisitko pyytää paria ystävää pelaamaan
 biljardia?"; 
		    }
		    else{
			kysymys = "Mitä jos menisit katsomaan huonoa elokuvaa?"; 
		    }
		}else{
		    kysymys = "Soisitko itsellesi hetken aikaa television katseluun?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Jaksaisitko pyytää paria ystävää pelaamaan biljardia?")){
		if(vastaus){
		    kysymys = "Onko luontevan matkan päässä tähän tarkoitukseen
 oivallisesti soveltuvaa tilaa?";
		}else{
		    emo.annaYksinaisyys().tarpeenMaaranMuutos(-5);
		    kysymys = "Entä jos ottaisitkin itseäsi niskasta kiinni ja menisit
 katsomaan huonoa elokuvaa?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("menisit katsomaan huonoa elokuvaa?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(5);
		    emo.annaHuvi().tarpeenMaaranMuutos(60);
		    emo.annaVasymys().tarpeenMaaranMuutos(-5);
		    jutusteluKaynnissa = false;
		    kysymys = "Hauskaa leffaa!"; 
		}else{
		    kysymys = "Mites jos ottaisit kaapista naposteltavaa ja käyttäisit 
aikaa television katseluun?"; 
		}
		return kysymys;
	    }
	      if(kysymys.endsWith("television katseluun")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(5);
		    jutusteluKaynnissa = false;
		    emo.annaHuvi().tarpeenMaaranMuutos(30);
		    emo.annaKyllaisyys().tarpeenMaaranMuutos(10);
		    kysymys = "Ei kuitenkaan kannata katsoa amerikkalaisten tekemiä 
huonoja ohjelmien irvikuvia!"; 
		}else{
		    kysymys = "Haluaisitko nähdä muita ihmisiä, vaikka jotain vanhoja tuttuja?"; 
		}
		return kysymys;
	    }
	      if(kysymys.equals("Onko luontevan matkan päässä tähän tarkoitukseen oivallisesti soveltuvaa tilaa?")){
		  if(vastaus){
		      emo.annaOnnellisuus().tarpeenMaaranMuutos(15);
		      emo.annaHuvi().tarpeenMaaranMuutos(0);
		      emo.annaKunto().tarpeenMaaranMuutos(5);
		      emo.annaYksinaisyys().tarpeenMaaranMuutos(35);
		      jutusteluKaynnissa = false;
		      kysymys = "Häkellyttävän ihanaa! Eikun sinne vaan ja pallot pussiin!"; 
		  }else{
		      kysymys = "Entä keilahallia? Löytyykö lähistöltä tai liikenneyhteyksien 
varrelta keilailuun soveltuvaa tilaa?";
		  }
		  return kysymys;
	      }	    
	      if(kysymys.startsWith("Entä keila")){
		  if(vastaus){
		      emo.annaOnnellisuus().tarpeenMaaranMuutos(15);
		      emo.annaKunto().tarpeenMaaranMuutos(10);
		      emo.annaHuvi().tarpeenMaaranMuutos(0);
		      emo.annaYksinaisyys().tarpeenMaaranMuutos(25);
		      jutusteluKaynnissa = false;
		      kysymys = "Todella mukavaa. Sinne vaan sitten, tötsiä kaatamaan!"; 
		  }else{
		      kysymys = "Entäpä jos menisit katsomaan huonoa elokuvaa?"; 
		  }
		  return kysymys;
	      }
	    if(kysymys.startsWith("Haluaisitko nähdä muita")){
		if(vastaus){
		    if(emo.annaHuvi().annaTarpeenMaara() < 20){
			kysymys = "Pyytäisitkö ystäviä lähtemään johonkin kahville,
 baariin tai vaikka elokuviin?"; 
		    }
		    int arpa = rand.nextInt(3);
		    if(arpa < 1){
			kysymys = "Pyytäisitkö ystäviä kotiisi pelaamaan 
jotain lautapelejä?"; 
		    }
		    if(arpa == 2){
			kysymys = "Soitapa muutamaa ystävääsi pelaamaan kanssasi
 jalkapalloa! Tai oikeastaan: kävisikö mikä tahansa urheilu?"; 
		    }else{
			kysymys = "Mitä jos lähtisit yllätysvisiitille jonkun
 ystävän luo?"; 
		    }
		}else{
		    String loppuhuomautus;
		    if(mieliala.annaOlo() < -3.4){
			loppuhuomautus = " Ihme tuolisieni - -"; 
			emo.annaOnnellisuus().tarpeenMaaranMuutos(-30);
		    }
		    if(mieliala.annaOlo() > 3.4){
			loppuhuomautus = " Emon oma kotihiirulainen"; 
		    }
		    else{
			loppuhuomautus = " Mutta pahaa ei tekisi"; 
		    }
		    jutusteluKaynnissa = false;
		    kysymys = "No ei väkisin, ei väkisin." + loppuhuomautus; 

		}
		return kysymys;
	    }
	    		    
	    if(kysymys.startsWith("Mitä jos lähtisit yllätysvisiitille")){
		if(vastaus){
		    kysymys = "Lähdetkö samantien?"; 
		}else{
		    kysymys = "Väsyttääkö?"; 
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-20);
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("Pyytäisitkö ystäviä")){
		if(vastaus){
		    kysymys = "Soitatko heti?"; 
		}else{
		    kysymys = "Väsyttääkö?"; 
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-20);
		}
		return kysymys;
	    }
	    if(kysymys.equals("Lähdetkö samantien?")){
		if(vastaus){
		    kysymys = "No terve menoa! Pitäkää hauskaa!";
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "Väsyttääkö?"; 
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-20);
		}
		return kysymys;
	    }    
	    if(kysymys.endsWith("Soitatko heti?")){
	       if(vastaus){
		   kysymys = "Vastasiko?"; 
	       }
	       else{
		   kysymys = "Mitä jos vain menisit käymään?"; 
	       }
	       return kysymys;
	    }
	    if(kysymys.equals("Mitä jos vain menisit käymään?")){
	       if(vastaus){
		   kysymys = "No hei! Loistavaa!"; 
		   emo.annaYksinaisyys().tarpeenMaaranMuutos(0);
		   jutusteluKaynnissa = false;
	       }
	       else{
		   kysymys = "Väsyttääkö?"; 
	       }
	       return kysymys;
	    }
	    if(kysymys.equals("Vastasiko?")){
	       if(vastaus){
		   kysymys = "Sovitteko tekevänne jotain?";
	       }
	       else{
		   kysymys = "Soita toiselle. Soitatko heti?"; 
	       }
	       return kysymys;
	    }
	    if(kysymys.equals("Sovitteko tekevänne jotain?")){
		if(vastaus){
		    kysymys = "Loistavaa! Mukava kuulla!"; 
		    emo.annaYksinaisyys().tarpeenMaaranMuutos(0);
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "Soita jollekin muulle. Soitatko heti?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("tavannut muita ihmisiä pitkään aikaan?")){
		if(vastaus){
		    emo.annaYksinaisyys().tarpeenMaaranMuutos(60);
		    kysymys = "Kuulostaisiko hyvältä idealta: jos pyhittäisit 
seuraavat tunnit ihan vain pelkästään itsellesi?"; 
		}else{
		    if(mieliala.annaOlo() < -2){
			kysymys = "Haluaisitko nähdä muitakin kuin omaa pärstääsi?"; 
		    }else{
			kysymys = "Haluaisitko nähdä muita ihmisiä?"; 
		    }
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("jos pyhittäisit seuraavat tunnit ihan vain
 pelkästään itsellesi?")){
		if(vastaus){
		    kysymys = "Mitä jos tekisit sen käymällä pienellä juoksulenkillä?"; 
		}
		else{
		    kysymys = "Mitä jos lähtisit Linnanmäelle?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals(emo.annaVasymys().annaTarvelause())){
		if(vastaus){
		    emo.annaVasymys().tarpeenMaaranMuutos(100);
		    kysymys = "Oletko nukkunut sikeästi?"; 
		}else{
		    kysymys = "Pitäisiköhän sinun nukkua?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Väsyttääkö?")){
		if(!vastaus){
		    emo.annaVasymys().tarpeenMaaranMuutos(100);
		    kysymys = "Oletko nukkunut sikeästi?"; 
		}else{
		    kysymys = "Pitäisiköhän sinun nukkua?"; 
		}
		return kysymys;
	    }	   
	    if(kysymys.equals("Oletko nukkunut sikeästi?")){
		if(vastaus){
		    kysymys = "No onpas mukava kuulla"; 
		    jutusteluKaynnissa = false;
		}else{
		    emo.annaVasymys().tarpeenMaaranMuutos(-40);
		    kysymys = "Voi sentään. Näitkö pahoja unia?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("pahoja unia?")){
		if(vastaus){
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-90);
		    emo.annaVasymys().tarpeenMaaranMuutos(-40);
		    kysymys = "Jos menisit makuulle, sulkisit silmäsi ja
 yrittäisit silti nukkua?"; 
		}else{
		    kysymys = "Tuliko ulkoa turhaa melua tai valoa?"; 
		}
		return kysymys;
	    }	    
	    if(kysymys.equals("Tuliko ulkoa turhaa melua tai valoa?")){
		if(vastaus){
		    kysymys = "Käypä sulkemassa ikkuna ja verhot. Paraniko
 tilanne?"; 
		}else{
		    kysymys = "Sinun pitäisi nukkua enemmän. Mitä jos kävisit
 lyhyellä lenkillä?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("nukkua?")){
		if(vastaus){
		    kysymys = "Ovatko lakanat puhtaat?"; 
		}else{
		    kysymys = "Selvä. Mutta kohtuuton valvominen ei tee sinulle hyvää."; 
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Paraniko tilanne?")){
		if(vastaus){
		    kysymys = kehaise(); 
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "No voi harmin paikka. Täytynee vain odottaa hetken
 niin kyllä se siitä."; 
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.equals("Ovatko lakanat puhtaat?")){
		if(vastaus){
		    kysymys = "No eikun pehkuihin!"; 
		    jutusteluKaynnissa = false;
		}else{
		    emo.annaSiivoaminen().tarpeenMaaranMuutos(-40);
		    kysymys = "Ottaisitko siitä huolimatta nokoset?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Oletko syönyt?")){
		if(vastaus){
		    emo.annaKyllaisyys().tarpeenMaaranMuutos(20);
		    double r = rand.nextDouble();
		    if(r < 0.33){
			kysymys = "Oliko hyvää?"; 
		    }
		    if(r >= 0.33 && r < 0.67){
			kysymys = "Maistuiko?";
		    }
		    else{
			kysymys = "Muistitko juoda tarpeeksi?";
		    }
		}else{
		    kysymys = "Söisitkö nyt?"; 
		}
		return kysymys;
	    }
		if(kysymys.equals("Muistitko juoda tarpeeksi?")){
		    if(vastaus){
			emo.annaKyllaisyys().tarpeenMaaranMuutos(50);
			kysymys = "Söitkö riittävästi?";
		    }
		    else{
			kysymys = "No juopa iso lasi nestettä. Muuten tulee munuaistauti.";
			jutusteluKaynnissa = false;
		    }
		    return kysymys;
		}
	    
	    if(kysymys.equals("Oliko hyvää?") || kysymys.equals ("Maistuiko?")){
		emo.annaKyllaisyys().tarpeenMaaranMuutos(100);
		if(vastaus){
		    kysymys = "Oliko ruoassa riittävästi hivenaineita?"; 
		}else{
		    kysymys = "Söitkö riittävästi?"; 
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("Söisitkö nyt")){
		if(vastaus){
		    kysymys = "Onhan jääkaapissa riittäväsi aineksia tai eineksiä?"; 
		}else{
		    kysymys = "Jotta ruoka maistuisi kannattaisi ehkä käväistä
 pikku lenkillä?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Oliko ruoassa riittävästi hivenaineita?")){
		if(vastaus){
		    kysymys = kehaise();
		    emo.annaKunto().tarpeenMaaranMuutos(15);
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "Jaksaisitko napata muutaman vihanneksen vielä, ihan
 vaan vitamiinien vuoksi."; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Söitkö riittävästi?")){
		if(vastaus){
		    kysymys = "Ottaisitko ruoan päälle terveelliset kymmenen minuutin 
nokoset?"; 
		}else{
		    emo.annaKyllaisyys().tarpeenMaaranMuutos(-60);
		    kysymys = "Söisitkö nyt vielä sitten hieman lisää? Jotain
 vihreää tai värikästä?"; 
		}
		return kysymys;
	    }
	    if(kysymys.startsWith("Onhan jääkaapissa")){
		if(vastaus){
		    emo.annaKyllaisyys().tarpeenMaaranMuutos(50);
		    kysymys = "No sepä mukavaa. Popsasepa sitten palanen"; 
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "Viitsitkö käväistä kaupassa?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("kaupassa?")){
		if(vastaus){
		    kysymys = "Onko sinulla rahaa ruokaan?"; 
		}else{
		    kysymys = "Minun mielestäni sinun kyllä pitäisi!";
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	    if(kysymys.equals("Onko sinulla rahaa ruokaan?")){
		if(vastaus){
		    emo.annaKaupassakaynti().tarpeenMaaranMuutos(100);
		    kysymys = "Hyvää kauppareissua. Kannattaa tehdä lista!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "Sitä pitää hankkia. Muuten pitää varastaa, eikä se
 ole yhtä viisasta kuin lainan otto mikä ei välttämättä ole sekään viisasta.
 Ymmärrätkö mitä vihjaan?"; 
		}
		return kysymys;
	    }
	    if(kysymys.equals("Ymmärrätkö mitä vihjaan?")){
		if(vastaus){
		    kysymys = kehaise(); 
		}
		else{
		    kysymys = "Hmm. Jos vain hankkisit sitä valuuttaa jostain, ok?"; 
		}
		jutusteluKaynnissa = false;
		return kysymys;
	    }
	    if(kysymys.endsWith("vitamiinien vuoksi.")){
		if(vastaus){
		    kysymys = "Onhan jääkaapissa porkkanoita tai muita vastaavia?"; 
		    emo.annaHuvi().tarpeenMaaranMuutos(-15);
		    emo.annaKunto().tarpeenMaaranMuutos(20);
		    emo.annaOnnellisuus().tarpeenMaaranMuutos(-15);
		}else{
		    kysymys = "No ei väkisin. En halua tuputtaa"; 
		    jutusteluKaynnissa = false;
		}
		return kysymys;
	    }
	       
	    if(kysymys.endsWith("urheilu?")){
		if(vastaus){
		    kysymys = "Miten olisi ulkoliikunta?";
		}else{
		    kysymys = "Onko nuutunut olo?";
		}
		return kysymys;
	    }
	    if(kysymys.equals("Onko nuutunut olo?")){
		if(vastaus){
		    emo.annaVasymys().tarpeenMaaranMuutos(-50);
		    kysymys = "Pitäisiköhän sinun ottaa lyhyet nokoset?";
		}
		else{
		    kysymys = "Tiedätkö mikä tekisi tosi hyvää sinulle: lähtisit punttisalille?";
		}
		return kysymys;
	    }
	    if(kysymys.equals("Miten olisi ulkoliikunta?")){
		if(vastaus){
		    emo.annaKunto().tarpeenMaaranMuutos(90);
		    emo.annaVasymys().tarpeenMaaranMuutos(-25);
		    kysymys = "No eikun ulos vaan ja liikkumaan!"; 
		    jutusteluKaynnissa = false;
		}
		else{
		    kysymys = "Sisäliikunta?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("Sisäliikunta?")){
		if(vastaus){

		    kysymys = "Ellet ole erityisen luova, sinun pitää varata vuoro
 tai keksiä jotain. Hei! Nyt tuli mieleeni hyvä aatos!  Menisitkö punttisalille?";
		}
		else{
		    kysymys = "Lahjattomat harjoittelee! Tee sitten täsmälleen 
päinvastainen ratkaisu: ottaisit nokoset?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("punttisalille?")){
		if(vastaus){
		    emo.annaKunto().tarpeenMaaranMuutos(80);
		    emo.annaHuvi().tarpeenMaaranMuutos(30);
		    emo.annaVasymys().tarpeenMaaranMuutos(-30);
		    jutusteluKaynnissa = false;
		    kysymys = "Se tekeekin hyvää! Voimaile nyt sitten oikein olan takaa!"; 
		}
		else{
		    kysymys = "Harrasta sitten jotain muuta sisäliikuntaa, 
kyllä sinä keksit, minä tiedän"; 
		    jutusteluKaynnissa = false;
		}
	    }
	    if(kysymys.endsWith("lenkillä?")){
		if(vastaus){
		    emo.annaKunto().tarpeenMaaranMuutos(50);
		    kysymys = "Eiku kamat niskaan ja matkaan!"; 
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "Oletko syönyt terveellisesti? Jos et, en ihmettele
 ettet jaksa lenkkeillä!"; 
		}
		return kysymys;
	    }	
	    if(kysymys.startsWith("Oletko syönyt terveellisesti?")){
		if(vastaus){
		    kysymys = "No kävisikö sitten joku reipas kuntoilu. Sisäliikunta?";
		}
		else{
		    kysymys = "Onhan jääkaapissa porkkanoita tai muita vastaavia?"; 
		}
		return kysymys;
	    }
	    if(kysymys.endsWith("nokoset?")){
		if(vastaus){
		    emo.annaVasymys().tarpeenMaaranMuutos(40);
		    kysymys = "Muista herätä ajoissa: 10 - 15 minuuttia 
on hyvä pituus. Ja hyviä torkkuja!"; 
		    jutusteluKaynnissa = false;
		}else{
		    kysymys = "Pirteä olo? Jospa kävisit lenkillä?"; 
		}
		return kysymys;
	    }
	    else{
		jutusteluKaynnissa = false;
		double t = rand.nextDouble();
		if(t < 0.25){
		    kysymys = "Emo ei nyt ehdi vastaamaan, koska naapurin ukko
 tuli lainaamaan sokeria";
		}
		if(t >= 0.25 && t < 0.5){
		    kysymys = "Emo lepuuttaa parhaillaan äänekkäästi jalkojaan
 kylvyssä, eikä täten kuule vastaustasi.";
		}
		if(t >= 0.5 && t < 0.75){
		    kysymys = "Emo naureskelee itsekseen television saippuasarjoille 
kuulematta mitä sanoit";
		}
		else{
		    kysymys = "Emo pälättää puhelimeen eikä tainnut kuulla mitä sanoit";
		}

		return kysymys;
	    }

	}
	else{
	    jutusteluKaynnissa = false;
	    if(kysymys.equals("Emolla on muuta puuhaa.")){
		int luku = rand.nextInt(5);
		if(luku == 1){
		    kysymys = "Emo järjestelee kaappeja"; 
		}
		if(luku == 2){
		    kysymys = "Emo katselee saippuasarjaa televisiosta"; 
		}
		else{
		    kysymys = "Emo kuorsaa sikeästi olohuoneen sohvalla"; 
		}
	    }
	}	    
	return kysymys;
    }
    /**
     *  tuhahda  nälväisee
     * @return String 
     */
	    public String tuhahda(){
	int luku = rand.nextInt(5);
	if(mieliala.annaOlo() > 7){
	    if(luku > 2){
		return "Hmmm. ";
	    }else{
		return "Jasso. ";
	    }
	}
	else{
	    if(luku <= 1){return "Turisija! ";}
	    if(luku == 2){return "Laiska kutale. ";}
	    if(luku == 3){return "Ihme turnipsi ";}
	    if(luku == 4){return "Mahonkiperse. Opettelisit tekemään työtä. ";}
	    if(luku >= 5){return "Miten sinustakin on tuollainen kasvanut? ";}
	}
	return "Jahas, jahas";
    }
    /**
     * kehaise hekumoi
     * @return String 
     */
    public String kehaise(){
	int luku = rand.nextInt(8);
	if(mieliala.annaOlo() > -7){
	    if(luku <= 1){return "Hyvä! ";}
	    if(luku == 2){return "Loistavaa. Olet ahkera, myönnettäköön. ";}
	    if(luku == 3){return "Hyvin tehty. ";}
	    if(luku == 4){return "Onpas mukavaa kun jaksat! ";}
	    if(luku == 5){return "Oletpa reipas! ";}
	    if(luku == 6){return "Loistavaa! Olen ylpeä sinusta! ";}
	    if(luku == 7){return "Hienoa! ";}
	    if(luku >= 8){return "Oivallista! ";}
	}
	else{
	    if(luku < 4){
		return "Kelvannee.";
	    }else{
		return "Pitäisi kai kehua.";
	    }
	}
	return "Joopa joo, joopa joo";
    }
    /**
     *  annaKysymys on julkinen keino saada näppinsä kysymys-stringiin
     *
     * @return String 
     */
    public String annaKysymys(){
	return kysymys;
    }
}

5.5 Mieliala


/**
 * Mieliala säätelee emon käyttäytymistä
 * mielialalla on sekä lyhyt- että pitkäkestoinen ominaisuus
 *
 * @author Johannes Koponen
 * @version 1.0
 */
public class Mieliala{

    private int olo;
    private double onnellisuus;
    private int olojenLukumaara;
    private int edellisetOlot[];
    private int muisti;

    /**
     * Mieliala -luokan uusi ilmentymä.
     *
     * @param muisti int
     * @param olo int 
     */
    public Mieliala(int muisti, int olo){
	this.muisti = muisti;//muistitason säätö on toteutettavissa
	edellisetOlot = new int[3*muisti + 1];
	this.olo = olo;
	onnellisuus = 0;
    }
    /**
     * laskeOlo:lasketaan olo edellisen vastauksen ja 
     * pitkäaikaisen mielialan 
     * (onnellisuuden) perusteella
     *
     * @param vastaus boolean on käyttäjän emon kysymykseen antama vastaus
     * @return double 
     */
    public double laskeOlo(boolean vastaus){
	olojenLukumaara++;
	if(vastaus){
	    olo++;
	    if(olo > 50){olo = 50;}
	}
	else{
	    olo--;
	    if(olo < -50){olo = -50;}
	}
	edellisetOlot[olojenLukumaara%(3*muisti)] = olo;
	return (double)olo + laskeOnnellisuus();
    }
    /**
     * asetaOlo muuttaa olo-luvun arvoa
     *
     * @param muutos int 
     */
    public void asetaOlo(int muutos){
	olo = olo + muutos;
    }
    /**
     * annaOlo palauttaa tämänhetkisen olon ja
     * tämänhetkisen onnellisuuden summan
     *
     * @return a double value
     */
    public double annaOlo(){
	return olo + onnellisuus;
    }
    /**
     *  laskeOnnellisuus laskee onnellisuuden. 
     * Onnellisuus on emo pitkäaikainen mieliala.
     *
     * @return double
     */

    // laskeOnnellisuus()toimii seuraavasti: se 
    //vähentää edellisen vastauksen olotilan määrän kolme
    // kertaa muisti -luvun antaman määrän 
    //verran vanhan vastauksen aikaansaamasta olosta, ja 
    // jakaa tämän luvun muisti kertaa. Näin
    // saadaan suoran, joka vedetään (muisti, vastaus) 
    // -koordinaatiston pisteestä (0, olotila muisti
    // -oloa sitten) pisteeseen (muisti, olo nyt)
    // kulmakerroin kerrottuna kolmella. 
    //
    // Tämä luku kertoo pitkäaikaisen onnellisuuden vaikutuksen hetkelliseen oloon.
    public double laskeOnnellisuus(){
	if(olojenLukumaara > 3*muisti){
	    int indeksi = olojenLukumaara;
	    indeksi = (indeksi+3)%(3*muisti);
	    onnellisuus = (double)((olo - edellisetOlot[indeksi]));
	    onnellisuus = onnellisuus / (double)muisti;
	}
	return onnellisuus;
    }
    /**
     * annaKuva valitsee kuvat -kansion jpg-kuvista parhaiten olotilaan
     * sopivan ja polun siihen.
     *
     * @return String on kuvan sijainti.
     */
    public String annaKuva(){
	//palauttaa sopivan kasvokuvan emosta. Kasvokuva riippuu mielialasta.
	String kuvaString = "neutral";
	if(olo < -22){
	    kuvaString = "isosuru";
	}
	if(olo >= -22 && olo < -7){
	    kuvaString = "suru";
	}
	if(olo >= -7 && olo < 9){
	    kuvaString = "neutral";
	}
	if(olo >= 9 && olo < 29){
	    kuvaString = "ilo";
	}
	if(olo >= 29){
	    kuvaString = "isoilo";
	}
	return kuvaString;
    }
}

5.6 Tarve


import java.util.Timer;
import java.util.TimerTask;


/**
 * Tarve luokka kuvaa tarpeen täyttymistä ja sen
 * hiljaista syntymistä jokaisessa meistä.
 *
 * @author Johannes Koponen - aina paikalla jos syntyy Tarve
 * @version 2.0
 */
public class Tarve{
    private String tarvelause;
    private int tarpeenMaara;
    private Timer ajastin;
    private Emo emo;
    private double tarvekerroin;

    private static final int VAHENNYS = 2;

    /**
     * Tarve tekee uuden tarveilmentymän.
     *
     * @param emo Emo 
     * @param tarpeenMaara int
     * @param tarvekerroin double
     * @param tarvelause String
     */
    public Tarve(Emo emo, int tarpeenMaara, double tarvekerroin, String tarvelause){
	this.emo = emo;
	this.tarpeenMaara = tarpeenMaara;
	this.tarvekerroin = tarvekerroin;
	this.tarvelause = tarvelause;
	tarpeenMaaranMuutos(0);
    }
    /**
     * annaTarvelause palauttaa tarpeelle ominaisen lauseen.
     *
     * @return String
     */
    public String annaTarvelause(){
	return tarvelause;
    }
    /**
     * ajastin hoitelee tarpeiden syntymisen kuvausta.
     * Metodi käynnistää ajastimen, joka ajan 'sekuntia' loputtua
     * vähentää tarpeenMaaraa.
     *
     * @param sekuntia int 
     */
    public void ajastin(int sekuntia){
        ajastin = new Timer();
	ajastin.schedule(new Ajastintehtava(), sekuntia*1000);
    }
    private class Ajastintehtava extends TimerTask{
	public void run(){
	    tarpeenMaara = tarpeenMaara - VAHENNYS;
	    ajastin.cancel();
	    tarpeenTila();
	}
    }
    /**
     * tarpeenMaaranMuutos muuttaa tarpeen määrää.
     *
     * @param muutos int 
     */
    public void tarpeenMaaranMuutos(int muutos){
	tarpeenMaara = tarpeenMaara + muutos;
	if(tarpeenMaara > 100){tarpeenMaara = 100;}
	if(tarpeenMaara < 0){tarpeenMaara = 0;}
	tarpeenTila();
    }
    /**
     * annaTarpeenMaara palauttaa tarpeen määrän.
     *
     * @return int 
     */
    public int annaTarpeenMaara(){
	return tarpeenMaara;
    }
    /**
     * tarpeenTila tarkistaa, josko tarve olisi
     * sellainen että se pitäisi ottaa huomioon. Eli syntyykö
     * esim. nälkä.
     *
     */
    public void tarpeenTila(){
	if(tarpeenMaara > 10){
	    if(emo.annaTarpeetSet().contains(this)){
		emo.annaTarpeetSet().remove(this);
	    }
	    ajastin((int)tarvekerroin*haeNopeus());
	}else if(!emo.annaTarpeetSet().contains(this)){
		emo.annaTarpeetSet().add(this);
	}
    }
    /**
     * haeNopeus noutaa nöyrästi emo-luokalta
     * käyttäjän asettaman nopeuden
     *
     * @return int 
     */
    public int haeNopeus(){
	return emo.annaNopeus();
    }
}