Toteutusdokumentti Sahara-ryhmä Helsinki 31.8.2005 Ohjelmistotuotantoprojekti HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos
Kurssi 581260 Ohjelmistotuotantoprojekti (6 ov) Projektiryhmä Sanna Keskioja Sampo Lehtinen Hanna Liedenpohja Seppo Syrjänen Asiakas Joni Salmi Johtoryhmä Juha Taina Kimmo Simola Kotisivu http://www.cs.helsinki.fi/group/sahara Versiohistoria Versio Päiväys Tehdyt muutokset 0.1 17.8.2005 Ensimmäinen versio. Tietokanta-asioita mukaan./ss 0.2 23.8.2005 Tiedostojen kuvaus./ss 0.3 24.8.2005 Sovelluksen runko. Asetustiedostojen ja muuttujien kuvaus./ss 0.4 24.8.2005 Sovelluksen sisältöä./hl 0.5 25.8.2005 Luvut csvtuonti.php, aikataulu.php, apu.php./ss 0.6 30.8.2005 Ydinosat valmiita. 0.7 31.8.2005 Kuvat kohdalleen./ss
Sisältö i 1 Johdanto 1 1.1 Toteutustekniikan valinnasta........................ 1 1.2 Dokumentin rakenne (ohjeita lukijalle)................... 1 1.3 Termit.................................... 2 2 Arkkitehtuuri 4 2.1 Ohjelmistoympäristö............................ 4 2.2 Valmiit komponentit............................ 4 3 Tiedostojen sijainti 5 4 Alustustiedostot 7 5 Sovelluksen rakenne 9 5.1 index.php.................................. 12 5.2 perustiedot.php............................... 13 5.3 osallistujat.php............................... 13 5.3.1 csvtuonti.php............................ 13 5.4 aikataulu.php................................ 14 5.4.1 Aikataulun muokkaus....................... 14 5.5 Apumoduulit................................ 15 5.5.1 yhteiset.php............................ 15 5.5.2 apu.php............................... 17 5.5.3 lukujarjestys.php.......................... 19 5.5.4 munkres-kuhn.php......................... 21 5.5.5 sahkoposti.php........................... 21 5.5.6 sessiot.php............................. 21 5.5.7 ylavalikko.php........................... 22 5.5.8 valilehdet.php............................ 22 6 Algoritmit 23 6.1 Yksilötapaamiset.............................. 23 6.2 Ryhmätapaamiset.............................. 23
ii 7 Tietokannan toteutus 25 7.1 Tietokannan abstrahointi.......................... 25 7.2 Taulut.................................... 25 7.3 Indeksit................................... 27 7.4 Eheystarkistukset.............................. 27 7.5 Proseduurit ja triggerit........................... 27
1 Johdanto 1 Tanja-järjestelmän toteutusdokumentti kuvaa yksityiskohtaisesti miten järjestelmä on toteutettu. 1.1 Toteutustekniikan valinnasta Toteutettu järjestelmä poikkeaa useassa kohdassa merkittävästi suunnitteludokumentissa esitetystä. 1.8.2005 pidettyssä kokouksessa projektiryhmä päätti, että projektin käytössä olevat resurssit ja aika eivät riitä sovelma/web Start -tyyppisen kokonaan graafisen sovelluksen tuottamiseen Javalla. Tanja-järjestelmä päätettiin toteuttaa tekniikoilla, joilla käytössä olevan ajan puitteissa on mahdollista tehdä tärkeimmät vaatimukset toteuttava sovellus ja joista projektiryhmällä oli riittävää osaamista. Asiakkaan kanssa sovittiin 4.8.2005 vaatimusten uudelleenpriorisoinnista sekä toteutettavan sovelluksen ominaisuuksien supistamisesta. Tanja-järjestelmää lähdettiin toteuttamaan web-käyttöliittymällä PHP-kielellä heti 2.8.2005. Käyttöliittymän ulkoasu ja muu perustoiminta voitiin pitää vaatimusdokumentin mukaisena, vain erilaiset hiirellä maalaamiset jouduttiin korvaamaan alkeellisemmilla käyttötavoilla web-käyttöliittymän (HTML, JavaScript) rajoituksellisuuden vuoksi. Sovelluksen perusrakenteen suunnitteli Hanna vaatimusdokumentin käyttöliittymäsuunnitelmien mukaan. Tietokannan abstrahoitiin otettiin käyttöön Sepon tuntema PHP-luokkakirjasto. Yksilötapaamisaikataulun muodostusalgorimi portattiin suoraan Javalla tehdystä referenssitoteutuksesta. 1.2 Dokumentin rakenne (ohjeita lukijalle) Dokumentissa kuvataan ensin toteutetun sovelluksen rakenne (laitetaanko tähän automaattinen viite jotenkin???) eli ohjelmistoympäristö ja käytetyt valmiit komponentit. Kolmannessa luvussa (laitetaanko tähän automaattinen viite jotenkin???) kerrotaan lyhyesti sovelluksen jokaisen tiedoston tarkoitus. Neljäs luku tarkentaa tätä asetustiedostojen osalta. Kyseisessä luvussa dokumentoidaan jokainen yksittäinen asetus sekä kerrotaan, missä tiedostossa se on. Vaikka joitain asioita on mahdollista säätää muualta, niiden liittäminen asetustiedostoihin ei ole ollut vaatimuksena. Tästä hyvänä esimerkkinä käy moduulit/lukujarjestys.php, josta on säädettävissä ensimmäisen ja viimeisen tarjotun ajan alkuhetki. Viides luku kuvaa yleisellä tasolla, miten parametrit välitetään sekä tarkemmin jokaisen yksittäisen sovelluksen ohjelmatiedoston tarkoituksen. Kuvatut tiedostot on eroteltu sen mukaan, ovatko ne suoraan käyttäjälle näkyviä vai toteuttavatko aputoimintoja. Yleiskuvan antamisen jälkeen viidennessä luvussa kuvataan jokaisen yksittäisen tiedoston tarkoitus ja tarjoamat toiminnot yksityiskohtaisesti.
Kuudes luku kuvaa aikataulun laskemiseen käytetyt algoritmit. Seitsemäs luku kuvaa tietokannan toteutuksen, abstrahoinnin sekä yksittäiset taulut ja niiden atribuutit, indexit, eheyden tarkistukset, talletetut proseduurit ja triggerit. 2 1.3 Termit Toteutusdokumentissa käytetyt termit. CSV, Comma Separated Values, pilkkuerotetut arvot Tiedonsiirtomuoto, jota käytetään osallistujen tietojen tuontiin leikepöydän kautta esim. Kurki-järjestelmästä. Ehdotettu aikataulu Järjestelmän muodostama aikataulu, joka perustuu kutsujan kutsujan määrittelemiin aikataulun ominaisuuksiin ja osallistujien antamiin sopivuustietoihin. Järjestelmä Tanjan ohjelmiston (asiakas ja sovelluspalvelin) sekä tietokannan muodostama toiminnallinen kokonaisuus. Kurki-järjestelmä Laitoksen kurssikirjanpitojärjestelmä. Kutsuja Henkilö, joka haluaa tavata muita henkilöitä eli osallistujia itselleen sopivina ajankohtina. Käyttäjä Kutsuja tai osallistuja, joka käyttää järjestelmää jollain käyttöliittymällä. Lopullinen aikataulu Kutsujan hyväksymä aikataulu, joko järjestelmän alun perin ehdottama aikataulu tai kutsujan itse muokkaama aikataulu. Muokattu aikataulu Ehdotettu aikataulu, johon kutsuja on tehnyt haluamiaan muutoksia. Ohjelmisto Tanja-järjestelmän sovellukset: asiakas ja sovelluspalvelin. Osallistuja Henkilö, jonka kutsuja haluaa tavata. Osallistujan sopivuudet kutsujan määritteleminä aikoina syötetään järjestelmään. Ryhmä Kutsujan määrittelemä kokonaisuus, joka sisältää osallistujat sekä yhden tai useampia aikatauluja. Ryhmätapaaminen Ryhmän yhteinen tapaaminen, johon mahdollisimman moni ryhmän osallistujista osallistuu. Sopivuus Osallistujan tapaamisajoille annettu sopivuusarvo, "prioriteetti". Arvot ovat "Sopii hyvin", "Sopii kohtalaisesti"ja "Ei sovi". Järjestelmä käyttää myös arvoa "Ei tietoa"kuvaamaan sitä, että tietyltä osallistujalta ei ole tiedossa sopivuutta kyseiselle ajankohdalle. Sovellus Tanja-järjestelmän ohjelma.
3 Tapaaminen Osallistujalle tai ryhmätapaamiselle valittu aika. Tapaamisen kesto Kutsujan valitsema yhden tapaamisen kesto. Vaihtoehdot ovat 10, 20, 15, 30, 45, 60 tai 120 minuuttia. Tapaamisen tyyppi Yhteen aikatauluun kuuluvien tapaamisten tyyppi. Aikataulu voi olla tyypiltään ryhmätapaaminen tai yksilötapaaminen. Tarjottu aika Kutsujan määrittelemä yksittäinen ajankohta (aloitus- ja lopetusaika), jolloin hän haluaa tavata ryhmänsä osallistujia. Tarjottu aika sijoittuu tiettyihin viikonpäiviin tiettynä aikataulun määrittelemänä viikkojaksona. Vanhentunut aikataulu Aikataulu, jonka viikkojakso on jo päättynyt, mutta jota ei vielä ole poistettu järjestelmästä. Viikkojakso Kutsujan kalenterista valitsemat viikot, joiden aikana ryhmän tietty aikataulu on voimassa. Yksilötapaaminen Tapaaminen, jossa kutsuja tapaa henkilökohtaisesti yhden osallistujan.
2 Arkkitehtuuri 4 Tanja on yksinkertainen web-sovellus, jossa WWW-selain keskustelee PHP-sovelluksen kanssa. Sovellus tallettaa tarvittavat tiedot SQL-tietokantaan. Osa Tanjan käyttöliittymästä on toteuttettu yksinkertaisilla JavaScript-tekniikoilla. 2.1 Ohjelmistoympäristö Tanja on rakennettu seuraavien alustakomponenttien avulla: Ohjelmisto Versio Kuvaus Apache Apache/1.3.33 WWW-palvelin PHP 4.3.11 WWW-sovelluskieli PostgreSQL 7.4.7 Tietokantapalvelin Tanjaa on testattu seuraavien WWW-selaimien kanssa: Selain Versio Mozilla 1.6 Mozilla Firefox 1.0.4 Internet Explorer 6 2.2 Valmiit komponentit Tanja-järjestelmä käyttää seuraavia OpenSource-komponentteja. Komponentti Versio URL Munkres-Kuhnalgoritmi 0.11 http://www.spatial.maine.edu/~kostas/ dev/soft/munkres.htm Tietokantataulujen abstrahointi 1.0 http://baglan.web.tr/personal/articles/ dbhanfler.html Työkaluopasteet (tooltip) 3.33 http://www.walterzorn.com/scripts/wz_ tooltip.zip
3 Tiedostojen sijainti 5 Ohjelmiston käyttämät tiedostot:
6 Tiedosto Tarkoitus.htaccess PHP-ohjelmien käyttöönotto WWW-palvelimessa sekä index.php-sivun asettaminen hakemiston oletussivuksi aikataulu.php Aikataulujen hallinta asetukset/ Ohjelman asetustiedostot (PHP-muodossa) asetukset/.htaccess Kielletään Apachea antamasta asetustiedostoja ulkopuolisille. asetukset/aikataulut.php Aikataulujen oletusasetukset asetukset/csv.php CSV-tuonnin oletusasetukset asetukset/rekisteroitumisviesti.txt Rekisteröitymisen yhteydessä sähköpostiosoitteen toimivuuden varmistamiseen käytetty sähköpostiviesti asetukset/sahkopostimuutettuviesti.txt Muutetun sähköpostiosoitteen toimivuuden varmistamiseen käytetty sähköpostiviesti asetukset/salasanaviesti.txt Unohtuneen salasanan lähettämiseen käytetty sähköpostiviesti asetukset/tietokantayhteys.php Tietokantayhteyden asetukset asetukset/yleiset.php Mm. kutsujan sähköpostiosoitteen oletusasetukset csvtuonti.php CSV-muotoisen tiedon tuonti demo.html Tanjan käyttöohje index.html Oletussivu, joka ohjaa index.php:hen index.php Sisäänkirjautumissivu kuvat/ Ohjelmiston käyttämät kuvat ja ikonit moduulit/ Apumoduulit. moduulit/apu.js JavaScript-kirjastofunktiot moduulit/apu.php PHP-kirjastofunktiot moduulit/lukujarjestys.php Tarjottujen aikojen ja sopivuuksien syötön kirjastofunktiot moduulit/munkres-kuhn.php Munkres-Kuhn-algoritmin PHP-toteutus moduulit/sahkoposti.php Sähköpostiviestien lähettämiseen käytetty koodi sekä sähköpostiviestien otsakkeiden asetukset. moduulit/sessiot.php PHP-istuntojen apufunktiot. moduulit/valilehdet.php Käyttöliittymän välilehtien toteutus moduulit/wz_tooltip.js Käyttöliittymän työkaluavusteiden (tooltip) JavaScripttoteutus moduulit/yhteiset.php Käyttöliittymän kirjastofunktiot moduulit/ylavalikko.php Käyttöliittymän ryhmä- ja aikatauluvalikkojen toteutus osallistujat.php Osallistujien hallinta perustiedot.php Aikataulun perustietojen hallinta rekisteroidy.php Rekisteröinti järjestelmään saved_sessions/ PHP-istuntojen talletushakemisto saved_sessions/.htaccess Kielletään Apachea antamasta sessiotietoja ulkopuolisille tietokanta/ Tietokannan komponentit tietokanta/db.abstraction.php Käytettävän SQL-tietokannan abstrahointi tietokanta/db.handle.php Tietokantataulujen PHP-luokkien toteutus tietokanta/db.settings.php Alustaa tietokannan salasanat jne. tiedostosta asetukset/tietokantayhteys.php tietokanta/tietokanta.php Tanja-sovelluksen käyttämien taululuokkien toteutus tyylit/ Ulkoasun CSS-tyylitiedostot
4 Alustustiedostot 7 Tanjan oletusarvoja muutetaan seuraavilla muuttujilla seuraavissa tiedostoissa hakemistossa asetukset. Päätteeltään.php olevat asetustiedostot ovat suoraan sovellukseen mukaanotettavaa (include) PHP-koodia, joten niiden muokkaamisessa on oltava huolellinen. Sähköpostiviestipohjat ovat tavallisia tekstitiedostoja, joista korvataan määrätyt sanat vastaanottajakohtaisesti.
Tiedosto Muuttuja Tarkoitus aikataulut.php $TAPAAMISPITUUDET Aikataulujen tapaamispituuksien vaihtoehdot aikataulut.php $SOPIVUUSPAINOT Aikataulujen laskennassa käytettävät eri sopivuusarvojen painoarvot. Sopivuudet talletetaan arvoilla 0=ei tietoa, 1=ei sovi, 2=sopii kohtalaisesti, 3=sopii hyvin. Sopivuusarvoja painotetaan laskenta-algoritmeissa, jotta sovellus muodostaa mielekkäitä aikatauluja. csv.php $CSVEROTIN CSV-tuonnin erotinmerkin oletusarvo csv.php $CSVKENTAT CSV-tuonnissa käytettävien kenttänumeroiden oletusarvot. Oletuksena käytetään Kurki-järjestelmän kenttäjärjestystä. rekisteroitumisviesti.txt Käyttäjän rekisteröityessä lähetettävän sähköpostiviestin pohja. $linkki korvataan automaattisesti varsinaisella rekisteröitymislinkillä. #- merkillä alkavat rivit tulkitaan kommenteiksi. Ensimmäinen kommentoimaton rivi käytetään viestin otsikkona. sahkopostimuutettuviesti.txt Käyttäjän vaihtaessa sähköpostiaan lähetettävän sähköpostiviestin pohja. $linkki korvataan automaattisesti varsinaisella muutoksen vahvistavalla linkillä. #-merkillä alkavat rivit tulkitaan kommenteiksi. Ensimmäinen kommentoimaton rivi käytetään viestin otsikkona. salasanaviesti.txt Unohtuneen salasanan lähettämiseen käytetyn sähköpostiviestin pohja. $salasana korvataan automaattisesti käyttäjän varsinaisella salasanalla. #-merkillä alkavat rivit tulkitaan kommenteiksi. Ensimmäinen kommentoimaton rivi tietokantayhteys.php$conn_string käytetään viestin otsikkona. Tietokantayhteyden asetukset: tietokantakone (host), tietokannan nimi (dbname), TCPporttinumero (port), tietokantakäyttäjä (user) sekä tietokannan salasana (password). Asennettaessa Tanja uuteen ympäristöön on nämä käytävä muuttamassa tietokannan mukaiseksi. yleiset.php $tanja_debug Tulostetaanko debug tulosteet. Ohjaa tulosta- Debug() ja onkodebug() funktioiden toimintaa. yleiset.php $salasana Salasanan kelvollisuustarkistuksessa käytettävä säännöllinen lauseke (Perl). yleiset.php $kutsujansahkopostiosoite Kutsujan sähköpostiosoitteen tunnistamiessa käytettävä säännöllinen lauseke (Perl). Oletuksena sähköpostiosoitteen pitää olla muodollisesti validi ja päättyä helsinki.fi. yleiset.php $kutsuttavansahkopostiosoite Kutsuttavan sähköpostiosoitteen tunnistamiessa käytettävä säännöllinen lauseke (Perl). Oletuksena vaaditaan sähköpostiosoitteen olevan muodollisesti validi tai tyhjä. yleiset.php $salasana Salasanan kelvollisuustarkistuksessa käytettävä säännöllinen lauseke (Perl). yleiset.php $salaisuuttarekisteroinninhaasteeseen Rekisteröinnissä ja muutetun sähköpostin aktivoinnissa käytettävä MD5-algoritmin alustusbittijono. 8
5 Sovelluksen rakenne 9 Tanja-sovellus koostuu viidestä php-sivuista, joiden välillä käyttäjä voi navigoida. Aloitussivulla (index.php) käyttäjä voi kirjautua sisään. Kirjautuneena käyttäjä voi liikkua välilehdillä Perustiedot (perustiedot.php), Osallistujat (osallistujat.php) ja Aikataulu (aikataulu.php). Osallistujat-sivulta pääsee lisäksi käyttämään CSV-tuonti-sivua (csv-tuonti), joka aukeaa ponnahdusikkunaan. Kun käyttäjä kirjautuu ulos, hänet siirretään takaisin aloitussivulle. Aloitussivulla käyttäjä pääsee kirjautumisen lisäksi myös rekisteröitymään, tilaamaan unohtuneen salasanansa sekä siirtymään demosivuille (demo.html). Rekisteröityminen täytyy kuitata sähköpostiin lähetetyn linkin kautta rekisteröintisivulla (rekisteroidy.php). Sovelluksen käyttäjälle näkyvät sivut: Sivu index.php perustiedot.php osallistujat.php aikataulu.php csvtuonti.php rekisteroidy.php demo.html index.html Sovelluksen perusrakenne on kuvattu oheisessa kaaviossa. Kuvaus Aloitussivu: rekisteröityminen, sisäänkirjautuminen, salasanan tilaus Perustietojen ja tarjottujen aikojen syöttölomake Osallistujien ja sopivuuksien syöttölomake Aikataulun muokkauslomake CSV-muotoisten osallistujatietojen syöttölomake Rekisteröitymisen ja muutetun sähköpostin aktivoinnit käsittelevä sivu Tanja-demo/käyttöohje HTML meta refresh -ohjaus index.php-sivulle Tanja perustiedot.php index.php osallistujat.php csvtuonti.php aikataulu.php Kuva 1: Navigointi sovelluksessa
Moduulit Usean sivun tarvitsemat osiot ja toiminnot on pyritty erottelemaan omiksi moduuleikseen, jotka on sitten liitetty varsinaiselle sivulle. Osa moduuleista on melko isoja ja ne olisi voinut halutessaan jaotella pienemmiksikin osiksi, mutta päätimme jättää ne nyt näin. Pääosin moduulitiedostot sisältävät funktioita, joita kutsutaan siinä kohdassa, missä niitä tarvitaan. Sivujen yhteiset toiminto- ja ulkoasumoduulit: Tiedoston nimi Kuvaus yhteiset.php Suurin osa sivujen toimintalogiikasta ja välilehtisivujen yhteisten ylä- ja alaosien HTML-koodit. ylavalikko.php Yläosan ryhmä- ja aikatauluvalikoiden HTML-koodi. valilehdet.php Välilehtipalkin ja Kirjaudu ulos-painikkeen HTML-koodi. lukujarjestys.php Tarjotut ajat- tai Sopivuudet-viikkonäkymän tulostava koodi. apu.php Sekalaisia apufunktioita esim. arvojen tarkistukseen. munkres-kuhn.php Aikataulun sopivuuksien perusteella laskeva algoritmi. sahkoposti.php Sähköpostiviestipohjat käsittelevä, sähköpostiviestien otsakkeet sisältävä ja sähköpostin lähettämiseen käytetty apufunktio. sessiot.php Järjestelmän käyttämien php-sessioiden asetusten asettaminen sekä sessioiden debug tulostuksen tekevä tulostasessio- Debug() -funktio wz_tooltip.js Aikataulun muokkauksessa käytetyt tooltipit. apu.js Sekalaisia javascript-apufunktioita. Tilojen hallinta 10 Sivujen tilanhallinta on toteutettu php:n SESSION- ja POST-parametrejä käyttämällä. GET-parametreja käytetään ainoastaan rekisteröinnin ja sähköpostin muuttamisen vahvistavat linkit käsittelevän rekisteroidy.php -sivun kohdalla. SESSION-parametrit:
Parametrin nimi $_SESSION[kid] $_SESSION[rid] $_SESSION[aid] 11 Kuvaus Kirjautuneen kutsujan id Käsiteltävän ryhmän id, oletuksena viimeksi lisätty Käsiteltävän aikataulun id, oletuksena viimeksi lisätyn ryhmän uusin aikataulu $_SESSION[etunimi] Kirjautuneen kutsujan etunimi (käytetään Kutsujan tiedot - lomakkeessa) $_SESSION[sukunimi] Kirjautuneen kutsujan etunimi (käytetään Kutsujan tiedot - lomakkeessa) $_SESSION[sposoite] $_SESSION[salasana] $_SESSION[ toiminnon nimi _virhe] $_SESSION[ toiminnon nimi _ok] POST-parametrit Parametrin nimi $_POST[ kentän nimi ] $_POST[toiminto] $_POST[seuraavatoiminto] $_POST[valilehti] Toiminnallisuus Kirjautuneen kutsujan sähköpostiosoite (käytetään Kutsujan tiedot -lomakkeessa) Kirjautuneen kutsujan salasana (käytetään Kutsujan tiedot -lomakkeessa) Tulostettava virheilmoitusteksti Tieto onnistuneesta toiminnon onnistuneesta suorittamisesta (käytössä index.php:ssä) Kuvaus kentän nimi = lähetetyn lomakkeen tallennettava tieto ohjaustieto: seuraavaksi kutsuttava toiminto (kyseisen välilehden lomakkeen tallennus) ohjaustieto: toiminto, johon siirrytään välilehden lomakkeen (katso $_POST[toiminto]) tallentamisen jälkeen ohjaustieto: valilehti, johon siirrytään edellisen välilehden lomakkeen (katso $_POST[toiminto]) Sovelluksen käyttöliittymä oli aiottua Java-toteutusta varten suunniteltu sellaiseksi, että käyttäjä pystyisi samalla näytöllä pystyisi tekemään useita toimintoja ja että tallennus sujuisi mahdollisimman automaattisesti. HTML-käyttöliittymästä pyrittiin tekemään toiminnaltaan mahdollisimman samanlainen ja tässä onnistuttiinkin melko hyvin. Tallennusta varten on välilehtisivuilla (perustiedot.php, osallistujat.php ja aikataulu.php) kaikki lomake-elementit sijoitettu samaan HTML:n <FORM>-elementtiin. Sovellus on toteutettu niin, että mikä tahansa toiminto sekä tallentaa välilehden lomakkeen tiedot että tekee jonkin muun toiminnon. Samalla lomakkeen lähetyksellä tehdään siis kaksi eri tallennusta ja niiden jälkeen vasta näytetään päivitetty sivu. Esimerkiksi ryhmän vaihtaminen ylävalikosta käynnistää toimintosarjan, jossa ensin tallennetaan välilehden lomake ja sitten vaihdetaan ryhmä. Tallennus on toteutettu käyttämällä POST-parametrejä toiminto ja seuraavatoiminto. Suoritettava toiminto-parametri tutkitaan yhteiset.php:n valitsetoiminto()-funktiossa, joka ohjaa suorituksen toimintoa vastaavaan funktioon. Toimintofunktiot on esitelty luvussa 5.5.1 yhteiset.php.
12 Tilanne: Perustiedot-lomakkeen tietoja on muokattu ja käyttäjä vaihtaa ryhmän ylävalikosta, mikä käynnistää lomakkeen lähetyksen Ohjaustiedot: post(toiminto)=tallenna_perustiedot post(seuraavatoiminto)=vaihda_ryhma yhteiset.php function valitsetoiminto() { switch(toiminto) case tallenna_perustiedot call tallennaperustiedot() } perustiedot.php call valitsetoiminto() function tallennaperustiedot() { //tallennetaan Perustiedot-lomakkeen //kentät post(toiminto)=post(seuraavatoiminto) call valitsetoiminto() } function valitsetoiminto() { switch(toiminto) case vaihda_ryhma call vaihdaryhma() } function vaihdaryhma() { //vaihdetaan sessioon rid call tulostapaasivu() } function tulostasisalto() { // tulostetaan perustiedot- // lomakkeen sisältö } function tulostapaasivu() { call tulostaylaosa() call tulostasisalto() call tulostaalaosa() } Kuva 2: Kontrollin kulku tallennuksessa 5.1 index.php Tanja-sovelluksen etusivu: sisäänkirjautuminen, rekisteröityminen sekä unohtuneen salasanan tilaus. Tiedoston alussa testataan $_POST[toiminto]-parametrin arvo. Sen mukaan ohjataan suoritus oikeaan aliohjelmaan. Jos parametriä ei ole (eli sivulle ei tulla lomakkeen lähetyksen kautta), tulostetaan aloitussivu.
Toiminto Käsittelevä Kuvaus funktio kirjaudu_sisaan kirjaudusisaan() Tarkistetaan, että sähköpostiosoite-salasana-parilla löytyy käyttäjä. Asetetaan sessioon tietoja ja siirretään käyttäjä sisään Tanja-järjestelmään. Jos käyttäjää ei löydy, tulostetaan aloitussivu uudestaan ja näytetään virheilmoitus. tilaa_salasana tilaasalasana() Haetaan salasana sähköpostiosoitteen perusteella ja lähetetään käyttäjälle sähköpostiviesti. Tulostetaan uudestaan aloitussivu, jossa ilmoitus toiminnon onnistumisesta. rekisteroidy rekisteroidy() Tarkistetaan annetut syötteet. Jos syötteet kelpaavat, lähetetään käyttäjälle viesti, jossa vahvistuslinkki. Tulostetaan uudestaan aloitussivu, jossa ilmoitus toiminnon onnistumisesta. (ei toimintoa) tulostasisalto() Tulostetaan aloitussivun sisältö. 13 5.2 perustiedot.php Tiedoston tulostasisalto()-funktio tulostaa käsiteltävän ryhmän ja aikataulun perustietojen muokkauslomakkeen. Lomakkeen kentät ovat ryhmän nimi, aikataulun nimi, tapaamisen tyyppi, tapaamisen kesto, aikataulun viikkojakson alku- ja loppupäivä sekä tarjottujen aikojen syöttö viikkokalenterinäkymän valintaruutujen avulla. Viikkonäkymän tulostukseen käytetään lukujarjestys.php-moduulia. Lomakkeen tiedot tallennetaan yhteiset.php:n funktiossa tallennaperustiedot(). 5.3 osallistujat.php Tiedoston tulostasisalto()-funktio tulostaa lisäys- ja muokkauslomakkeen, jolla ryhmään voi lisätä osallistujia ja syöttää heille sopivuuksia tietyssä aikataulussa. Osallistujia voidaan lisätä joko antamalla heidän tietonsa suoraan osallistujalistan loppuun tai tuomalla tiedot CSV-muodossa (csvtuonti.php) esim. leikepöydän avulla Kurki-järjestelmästä. Lomakkeen kentät ovat valitun osallistujan etunimi, sukunimi ja sähköpostiosoite sekä osallistujakohdaisten sopivuuksien syöttö viikkokalenterinäkymän valintaruutujen avulla. Viikkonäkymän tulostukseen käytetään lukujarjestys.php-moduulia. Lomakkeen tiedot tallennetaan yhteiset.php:n funktiossa tallennaosallistujantiedot(). 5.3.1 csvtuonti.php Osallistujatietojen tuonti CSV-muodossa leikepöydän kautta esim. Kurki-järjestelmästä tapahtuu vaiheittain. Aluksi CSV-muotoinen tieto liitetään suureen tekstikenttään, valitaan käytettävät erotinmerkit sekä mistä kohtaa CSV-tietuetta tulkitaan etunimi, sukunimi sekä sähköpostiosoite.
Tämän lomakkeen tekee funktio aloitus(). Toisessa vaiheessa funktio siirralomakkeelle() tarkistaa, että on annettu jotain tietoja, valitsee käytettävät erotinmerkit ja kentät ja tulkitsee tiedon osallistujalistaksi lomakkeelle. Rivit, joilta saadaan tunnistettua halutusta sarakkeesta sähköpostiosoite, valitaan jatkokäsittelyyn laittamalla valintarasti sarakkeelle Valitse. Muut rivit jätetään rastitta. Etu- ja sukunimitietoja ei validoida eikä myöskään estetä saman sarakenumeron antamista jokaiseen kenttään. Tässä vaiheessa tietoihin voi vielä tehdä muokkauksia, joiden jälkeen siirrytään kolmanteen vaiheeseen. Jos annettu sähköpostiosoite on jo järjestelmässä, annetaan siitä ilmoitus. Jos annettu sähköpostiosoite on jo osallistujana ryhmässä, annetaan siitä ilmoitus. Muuten lisätään osallistuja ryhmään. Jos valitaan jo olemassaolevan sähköpostiosoitteen talletus, päivitetään nimitiedot annettujen tietojen mukaan. Funktio tallennavalitut() tallettaa tietokantaan edellisellä lomakkeella annetut käyttäjät. Jos sähköpostiosoite on virheellinen, tarjotaan mahdollisuus palata takaisin edelliseen vaiheeseen tekemään korjaukset. Muuten ilmoitetaan mitä tietokantaan talletettiin. 14 5.4 aikataulu.php Aikataulujen laskenta-algoritmit on kuvattu luvussa 6. Aikataulujen käsittelyä ohjaa funktio tulostasisalto(), joka Näyttää aikataulun tapaamisaikojen mukaan järjestettynä taulukkona, jossa annetut tapaamisajat on merkattu mustilla kehyksillä kunkin osallistujan ja ajan kohdalle. Muokattavien valintaruutujen kohdalle asetetaan tooltip-opasteet. Laskee sen uudestaan, jos käyttäjä pyytää tai jos aikataulua ei vielä ole laskettu. Antaa käyttäjän jakaa aikataulun aikoja manuaalisesti uudelleen vaihtamalla aikoja keskenään tai antamalla suoraan tietty aika tietylle osallistujalle (jos aikoja on eri määrä kuin osallistujia). Osallistujalistan muokattu järjestys muistetaan niin pitkään, kuin ollaan aikataulusivulla, muuten osallistujat ja ajat järjestetään aikajärjestykseen. Järjestyksen muistaminen tehdään tallettamalla osallistujien tunnisteet ($kid) sessiomuuttujaan (talukko) $kidit, joka siis tyhjennetään jos vaihdetaan näkymää tai painetaan Järjestä tapaamisajan mukaan -painiketta. 5.4.1 Aikataulun muokkaus Aikataulun muokkaus tapahtuu siten, että annetut tapaamisajat, yli jääneet tapaamisajat, sekä ilman aikaa jääneet osallistujat merkataan valintaruudulla. Valitsemalla kaksi annettua tapaamisaikaa vaihdetaan ne keskenään: käyttäjät saavat siis toistensa ajat, jotka eivät
välttämättä ole enää kummallekin sopivia. Epäsopivuustilanteessa on jatkettava vaihtamista. Valitsemalla vapaa aika tai ilman aikaa valittu käyttäjä, annetaan valittu aika valitulle käyttäjälle. Vapautunut aika tulee valittavaksi (ylimääräisiä aikoja) tai ajan aikaisemmin saanut käyttäjä jää ilman aikaa (aikoja liian vähän). Tämä aikojenmuokkauslogiikka toteutetaan siten, että lomakkeelta saadaan yksi tai kaksi aika/osallistujaparia, joiden arvoista päätellään mitä muokkaustoimi halutaan tehdä. Muokkauksen toteuttamisessa käytetään JavaScript-funktioita, jotka lähettävät taulukon tiedot lomakkeena, kun haluttu määrä valintaruuduja on valittuna. Valintaruuduille on määritelty JavaScript-koodilla leijuopasteet (tooltip; ilmestyvät esille, kun hiiri tuodaan valintaruudun päälle), jotka kertovat mitä kyseisen ruudun valinnalla tapahtuu. Funktio muodostaaikataulu($aid) muodostaa halutun aikataulun ja tallettaa sen kantaan. Se huolehtii sopivuusarvojen skaalaamisesta sekä sopivuusmatriisin kääntämisestä Munkres- Kuhn-algoritmille sopiviksi sekä saatujen tulosten muuntamisesta sovelluksen käyttöön. Saadut tapaamisajat talletetaan tietokantaan (yksilötapaamiset annettujen aikojen tauluun funktoilla varaaaika($aid,$aika,$kid), ryhmätapaaminen aikataulutauluun). 15 5.5 Apumoduulit 5.5.1 yhteiset.php Sovelluksen toimintalogiikan ydin. Alussa on toiminnon tulkitseva dispatcher valitsetoiminto(), jota muut sivut kutsuvat. Moduulissa seuraavat toiminnon toteuttavat funktiot. Tiedoston alussa ovat myös koko sovellukselle yhteisien vakioiden määrittelyt. toiminto-parametrin tutkiminen valitsetoiminto()-funktiossa:
Toiminto Käsittelevä funktio Kuvaus kirjaudu_ulos kirjauduulos() Tyhjentää session ja ohjaa käyttäjän takaisin aloitussivulle. vaihda_ryhma vaihdaryhma() Vaihtaa rid:lle uuden arvon. vaihda_aikataulu vaihdaaikataulu() Vaihtaa aid:lle uuden arvon. uusi_ryhma uusiryhma() Luo uuden ryhmän ja päivittää sen arvon rid:hen. uusi_aikataulu uusiaikataulu() Luo uuden aikataulun ja päivittää sen arvon aid:hen. poista_ryhma poistaryhma() Poistaa käsiteltävänä olevan ryhmän. poista_aikataulu poistaaikataulu() Poistaa käsiteltävänä olevan aikataulun. tallenna_perustiedot tallennaperustiedot() Tallentaa Perustiedotvälilehden lomakkeen (perustiedot ja tarjotut ajat). tallenna_osallistujan_tiedot tallennaosallistujantiedot() Tallentaa Osallistujatvälilehden lomakkeen (osallistujan tiedot ja sopivuudet). poista_osallistuja poistaosallistuja() Poistaa käsiteltävänä olevan osallistujan. tallenna_kutsujan_tiedot tallennakutsujantiedot() Tallentaa muokatut kutsujan tiedot (lomake sivun yläosassa). aikataulu - HUOM! Aikataulu on poikkeus välilehtien tallennuksessa, sivua ei tallenneta vaan suoritus ohjataan suoraan seuraavatoiminto-parametrin toimintoon. Lisäksi yhteiset.php sisältää seuraavat funktiot: toiminto-parametrin tutkiminen valitsetoiminto()-funktiossa: 16
17 Funktio luooletukset() tulostapaasivu() tulostaylaosa() tulostaalaosa() Kuvaus Jos käyttäjällä ei ole ryhmiä eikä aikatauluja (uusi käyttäjä tai viimeinen ryhmä/aikataulu poistettu), luodaan oletusryhmät kantaan ja päivitetään niiden id:t sessioon. Kutsuu funktioita tulostaylaosa(), tulostasisalto() ja tulostaalaosa(). tulostasisalto() on kaikilla kolmella välilehtisivuilla erilainen, joten se löytyy välilehden kokoavalta phpsivulta (katso esim. perustiedot.php). Tulostaa välilehtisivujen yhteisen yläosan HTML-koodin. Ryhmä- ja aikatauluvalikon tulostus on erotettu tiedostoon ylavalikko.php ja välilehdet tiedostoon valilehdet.php. Tulostaa välilehtisivujen yhteisen alaosan HTML-koodin. 5.5.2 apu.php Tiedostossa moduulit/apu.php on kokoelma kirjastometodeita.
Funktio tulostadebug($string) onkodebug() rekisteroitymisenmd5haaste( $tiedot) 18 Kuvaus Tulostaa annetun merkkijonon debug-ulkoasulla. Palauttaa true, jos debuggaus on päällä. Palauttaa MD5-suodatteen annettujen tietojen ja Tanjan suodate-evästeen (tiedostosta asetukset/yleiset.php) yhdistelmästä. Tiedot tulee katenoida yhdeksi merkkijonoksi ennen funktiolle lähettämistä. osoitteenalku() Palauttaa sovelluksen aktiivisena olevan WWW-sivun hakemiston. Esimerkiksi sivulla http://www.kone.com/polku/tiedosto.php funktio palauttaa http://www.kone.com/polku. Funktio toimii vain http:-protokollalla palveltujen sivujen kanssa. aika2d($s) Aika (sekunteina maanantaista klo 00) viikonpäivän nimeksi (ma -> su). aika2hm($s) Aika (sekunteina maanantaista klo 00) tunneiksi ja minuuteiksi muodossa H:M. pvm($date) Englantilainen päivämäärä $s (m/d/y) suomalaiseksi kello($date) nyt($aika=0) (d.m.y). Kellonaika $s muodossa H:M. Täydellinen aikaleima muodossa Y-M-D HH:MM:SS annetulle ajalle $aika tai nykyhetkelle (jos aikaa ei anneta kutsussa). htmlspecialchars_array($arr = array()) dmy2ymd($aika) Vaihtaa päiväyksen $aika muodosta d.m.y muotoon y.m.d. aikaleima($date) Palauttaa Unix-epookkiajan annetulle ajanhetkelle $date. sposoiteok($email) Palauttaa true, jos annettu sähköpostiosoite $email on muodollisesti validi (ks. asetukset/yhteiset.php). kutsujanspostiok($email) Palauttaa true, jos annettu sähköpostiosoite $email kelpaa kutsujan sähköpostiosoitteeksi (ks. asetukset/yhteiset.php). sposoitekaytossa($sposoite) Palauttaa true, jos annettu sähköpostiosoite $sposoite on jo käyttäjätaulussa. salasanaok($tarksalasana) Palauttaa true, jos annettu salasana $tarksalasana on muodollisesti validi (ks. asetukset/yhteiset.php). sopivuuksiaaikataulussa($aid) Palauttaa true, jos taulussa $aid on sopivuuksia määriteltynä. Tätä käytetään tapaamisen keston lukitsemiseen. Palauttaa taulukon, jossa annetun taulukon $arr arvokenttien HTML-erikoismerkit on suojattu/merkattu tavallisiksi merkeiksi eli < muutetaan muotoon < jne. Tätä käytetään kantaan talletettavien tietojen suojaamiseen HTMLväärinkäytöksiä vastaan.
19 5.5.3 lukujarjestys.php $tapaami- tulostatarjotut( sen_kesto ) Ulkopuolelta kutsuttavaksi tarkoitetut funktiot: tulostasopivuudet( $tapaamisen_kesto, $kid ) tietyssä aikataulussa voidaan syöttää. Palvelu on tarkoitet- Tulostaa taulukon, jolla yksittäisen osallistujan sopivuudet tu osallistujat.php -sivun eli osallistujat-välilehden käytettäväksi. Aikataulun, jolle sopivuudet tulostetaan, tunniste välittyy funktiolle sessioparametrina. Tämä tulisi muuttaa eksplisiittisesti välitettäväksi, jotta sivu ei hajoa kun sessioparametreihin joskus mahdollisesti tehdään muutoksia. Tulostaa taulukon, jolla tietyn aikataulun puitteissa valittavaksi tarjotut ajat syötetään. Implisiittiset parametrit kts. tulostasopivuudet() Lukujärjestys-taulukon tulostamiseen käytetyt apufunktiot. Nämä funktiot on tarkoitettu käytettäväksi vain lukujarjestys.php-tiedostosta käsin. Niiden käyttöä muualta ei ole kuitenkaan estetty.
tulostaotsikkorivi() Tulostaa otsikot klo, ma, ti... tulostarivi($t) Tulostaa kelloajan ja kutsuu tulostasolu() funktiota jokaiselle tulostettavalle solulle Parametri $t on aikaileima, joka vain välitetään tulostasolu() funktiolle. tulostasolu( $t ) Tulostaa lukujärjestysnäkymän yksittäiset solut. Näkymänä on joko tarjotut tai sopivuudet. Tulostettaessa sopivuuden syöttämiseen tarkoitettuja soluja, tarkistetaan kannasta onko kyseisellä aikataululla tarjottuna kyseistä aikaa. Mikäli aika on tarjottu, haetaan kannasta käyttäjän mahdollisesti aiemmin tallettama sopivuus, laitetaan taustaväri ja radiobuttonin valinta sen mukaiseksi. Parametrit: Eksplisiittiset: $t unix-aikaleima kertoo tapaamisen alkuajan Implisiittiset $sopivuudet globaali kertoo tulostetaanko sopivuudet vai tarjotut $aid sessiossa välitettävä kertoo mistä aikataulusta kyse $lukujarjestyskid globaali kertoo kenen käyttäjän sopivuuksista kyse Muuta huomattavaa helposti muutettavasti, mutta kovakoodatusti, asetetut soluille sopivuuden tai tarjolla olon mukaan asetettu tyyli sekä tyylin muuttamisen koukuttava javascript funktion kutsu. onkotarjottu( $t ) Palauttaa totuusarvon onko ajanhetken $t aika tarjottu implisiittisenä parametrina välitetyssä aikataulussa. asetakesto( $tapaamisen_kesto ) kutsumien apufunktioiden käyttämään globaaliin muuttu- Asettaa tulostasopivuudet() tai tulostatarjotut() funktioiden jaan tapaamisen keston. Tapaamisen kesto ilmaistan sekuntteina unixtimestampin tapaan. tulostasopivuudet( $tapaamisen_kesto, $kid ) tukset apufunktioiden käytettäväksi, hakee tarjotut, asettaa osallistujat.php kutsuu tätä funktiota. Funktio asettaa ase- tapaamisen keston ja kutsuu tulostataulukko funktion teke- $tapaami- tulostatarjotut( sen_kesto ) tulostataulukko() 20 mään varsinaiset työt. perustiedot.php kutsuu tätä funktiota. Funktio asettaa asetukset, hakee tarjotut, asettaa tapaamisen keston ja kutsuu tulostataulukko funktion tekemään varsinaiset työt. Funktio tulostaa html-taulukon alun ja otsikkorivin. Kutsuu tulostarivi() funktiota lukujärjestysnäkymän jokaiselle riville ja tulostaa loppuun html-taulukon päättävän tagin.
21 5.5.4 munkres-kuhn.php Laskee kaksijakoisen graafin maksimisovituksen. Ks. luku 6 Algoritmit. 5.5.5 sahkoposti.php sahkoposti.php sisältää sähköpostiviestit käsittelevän funktion sekä lähetettävissä sähköposteissa käytettävien otsaketietojen asetukset. Näitä ei ole eriytetty asetuksiin, sillä niiden muuttaminen on harvoin tarpeellista. Funktio on yleisempi kuin sitä Tanjan puitteissa käytetään. Parametreina sille välitetään vastaanottaja tai vastaanottajat PHP:n mail() funktion ymmärtämässä muodossa, viestin pohjatiedoston nimi ja tarvittaessa polku sekä taulukko assosiatiivinen taulukko korvaajista ja korvattavista. Pohjatiedoston rivit, jotka alkavat #-merkillä katsotaan kommenteiksi. Tällä funktiolla ei siis ole mahdollista lähettää rivejä, jotka alkavat #-merkillä. Ensimmäiseltä kommentoimattomalta riviltä poistetaan lopusta rivinvaihto ja erilaiset välilyöntimerkit (whitespace) käyttäen PHP:n rtrim()-funktiota. Näin saatu merkkijono käytetään viestin otsikkona. Pohjatiedoston seuraavilta kommentoimattomilta riveiltä korvataan korvattavaksi merkityt asiat. Tanjan rekisteröinnin ja sähköpostinvaihtamisen varmistusviesteissä tämän avulla viesteihin laitetaan käyttäjille yksilöllinen linkki sekä unohtuneita salasanoja lähetettäessä salasana. Tämän toiminnallisuuden avulla on mahdollista laittaa useita korvattavia tekstinpätkiä viestipohjaan. Olisi täysin mahdollista personoida Tanjan lähettämiä viestejä esimerkiksi etunimeä ja sukunimeä käyttämällä. On kuitenkin huomioitava, että korvaus tehdään järjestyksessä eikä kerralla. Jälkinmäiset korvattavat korvaavat siis aiemmissa korvauksissa syntynyttä tietoa, mutta ominaisuus on tarvittaessa helposti korjattavissa. 5.5.6 sessiot.php Asettaa PHP-istuntotiedostojen (sessio) paikan WWW-palvelimella Tanjan asennuskohtaiseksi hakemistoksi, sessioiden tunnistamiseen käytetyn selaimelle välitettävän keksin polun sekä PHP:n session nimen (käytetään myös selaimelle välitetyn keksin nimenä). Tällä tavalla Tanjaa voidaan ajaa palvelimella usean käyttäjätunnuksen alaisuudessa samalla palvelimella ilman, että sessiot menisivät sekaisin tai sessiotietojen tallettamiseen käytetyt tiedostot törmäisivät. Sessiopolun asettamisella pyritään estämään muita samalla palvelimella mahdollisesti käytössä olevia sovelluksia ryöstämästä Tanjan sessiotietoja. Laitoksen tietokantapalvelimen PHP on konfiguroitu siten, että oletuksena istuntotiedostot talletetaan palvelimen /tmp-hakemistoon. Tästä seuraa, että eri tunnuksilla ajetut sovellukset yrittävät käyttää samaa istuntotiedostoa, mikä kilpistyy luku- tai kirjoitusoikeuksien puuttumiseen ja aiheuttaa ikävät virheilmoitukset. Virheilmoituksien tulostumisen voi estää, mutta PHP-session aloittava funktio ( session_start() ) palauttaa aina true riippumatta siitä, onnistuiko session alustus vai ei. tulostasessiodebug() funktio on tehty sessiolle annettujen arvojen tulostamiseen. Funk-
tiota käytettiin tutkittaessa, miksi sessiot eivät tuntuneet laitoksen ympäristössä toimivan. Keksittyämme syyt ja mukautettuamme asetuksemme niihin, funktio jäi jokseenkin tarpeettomaksi. Tämä voi olla tarpeen kuitenkin asennettaessa Tanjaa laitosta normaalimpiin PHP-ympäristöihin. 22 5.5.7 ylavalikko.php Ryhmä- ja aikatauluvalikon tulostava HTML-koodi. Toiminnot (ryhmän/aikataulun lisäys, vaihto ja poisto) käsittelevät funktiot löytyvät yhteiset.php:stä. 5.5.8 valilehdet.php Tulostaa sovelluksen välilehdet (Perustiedot, Osallistujat, Aikataulut) ja Kirjaudu ulos - painikkeen. Välilehden vaihtaminen vaihtaa $_POST[valilehti]-parametrin, joka tutkitaan tallennuksen yhteydessä. Uloskirjautuminen käsitellään yhteiset.php:n funktiossa kirjauduulos().
6 Algoritmit 23 Sovelluksen mielenkiintoisimmat algorimit liittyvät aikataulujen reiluun muodostamiseen osallistujen antamien sopivuuksien perusteella. 6.1 Yksilötapaamiset Yksilötapaamista varten etsitään kullekin osallistujalle mahdollisimman toivottu tapaamisaika. Yleisessä tapauksessa ongelma palautuu klassiseen kaksijakoisen graafin maksimisovitukseen (luokkaa O(n!)), joka ratkaistaan perinteisesti Munkres-Kuhn-algoritmilla (ns. Unkarilainen algoritmi) ajassa O(n 3 ). Sovelluksessa käytetään Konstantinos A. Nedas:n [VIITE] Java-toteutuksesta http:// www.spatial.maine.edu/~kostas/dev/soft/munkres.htm tehtyä suoraa PHP-käännöstä. PHP-modulin munkres-kuhn.php yksikkötestaus tehtiin vertaamalla kymmenen testimatriisin sovitusta referenssinä pidetyn Java-version tuottamaan sovitukseen. Munkres-Kuhn-algoritmi käsittelee matriiseita [0..n][0..m], joten sovelluksen matriisi [tarjotut ajat][osallistujat] piti muuntaa algoritmin haluamaan muotoon. Tämä tehdään funktiossa muodostaaikataulu($aid,$tyyppi), joka muodostaa aikataulun ja tallettaa sen tietokantaan. Koska Munkres-Kuhn-algoritmi yksinkertaisesti maksimoi [tarjottu aika][osallistuja] - matriisin sopivuuksien kokonaissumman, pitää sovelluksen antamia sopivuusarvoja painottaa vastaamaan paremmin haluttua tulosta: ei sovi -arvoille annetaan painoarvo -100, jotta niitä ei varmasti anneta kenellekään. Ei tietoa -arvoilla annetaan painoarvo 10, jotta niitä voidaan käyttää jos muita sopivuuksia ei ole tiedossa. Sopii kohtalaisesti ja sopii hyvin -arvoille annetaan painoarvot 100 ja 150. Osallistujille, joille ei ole tiedossa sopivuustietoja annetaan painoarvoksi -10, jolloin heille jaetaan ne ajat, jotka muille eivät kelpaa. Lisäksi jokaisen tarjotun ajan painoarvosta vähennetään pieni korjauskerroin log(aika)*0.01, jotta algoritmi suosii tasatilanteessa aikaisempia tapaamisaikoja. Koska aikaa käsitellään sekunteina maanantain keskiyöstä, logaritmi sijoittuu välille n. [10,13] ja korjauskerroin siten välille n. [0.10,0.13]. Korjauskertoimen laskenta valittiin näin, jottei se valitulla arvovälillä vääristä muiden painokertoimien merkitystä (logaritmifunktio muuttuu tasaisesti havaitulla arvovälillä). Painoarvoja voi muuttaa järjestelmän konfiguraatiotiedostossa asetukset/aikataulu.php. 6.2 Ryhmätapaamiset Sopivimman ajan löytämisen ryhmätapaamiseen on triviaali ongelma, jossa riitää valita halutaanko aika, joka sopii mahdollisimman monelle edes jotenkin vaiko aika, jota mahdollisimman harva on ilmoittanut ei-sopivaksi. Ero näiden välillä tulee siitä miten tulkitaan aikoja, joista ei ole tarjolla sopivuustietoa: voidaan saada useammalle sopiva aika, jos voidaan tulkita ei tietoa -sopivuus jonkinlai-
seksi sopivuudeksi sen sijaan, että löydetään aika joka sopii varmasti mahdollisimman monelle. Valinta näiden laskentatapojen välillä tehdään valitsemalla konfiguraatiotiedostoon asetukset/aikataulu.php ei tietoa -sopivuudelle nollaa suurempi painokerroin (minimoidaan ei sovi -sopivuuksien määrä) tai painokerroin nolla (maksimoidaan vain aidot tiedetyt sopivuudet). 24
7 Tietokannan toteutus 25 Tietokannan luovat SQL-komennot ovat Tanjan asennuspaketissa tiedostossa asetukset/tanja-init.sql. 7.1 Tietokannan abstrahointi Tietokantataulujen operaatiot on abstrahoitu Baglan Dosmagambetovin sivulla http:// baglan.web.tr/personal/articles/dbhanfler.html esittelemällä tekniikalla. Tauluja käsitellään PHP:n luokkamuuttujien ilmentyminä, jolloin rutiiniioperaatioiden tekemiseen ei tarvita sovellukseen kirjoitettavaa SQL-koodia. Tauluoliot ovat itse tietoisia taulun sarakkeiden nimistä, joten metodeille voidaan välittää suoraan $_POSTtaulukko, jossa kenttänimet vastaavat taulun sarakenimniä. Alkuperäinen db.abstraction.php oli toteuttu MySQL-ohjelmistolle, mutta siitä saatiin käyttöön Sepon aikaisemmin PostgreSQL:lle porttaama versio. Myös pääluokkaa db.handle.php oli kehitetty huomattavasti yo. sivun esittämästä versiosta (mm. avainkentän nimien korvaaminen perittävissä luokissa, useampien avainkenttien käyttö). Tietokantaluokkien PHP-tiedostot ovat hakemistossa tietokanta. Koska tietokantaluokat otettiin projektin käyttöön ulkopuolisena valmiina komponenttina, niitä ei ole projektin puitteissa erikseen testattu. 7.2 Taulut Taulut on nimetty yksikkömuotoon (KAYTTAJA, RYHMA). Merkintä =tbl:f tarkoittaa eheystarkistusta taulun tbl kentän f kanssa eli että tämä kenttä voi saada vain arvoja, jotka esiintyvät taulun tbl kentässä f. Nämä toteutetaan PostgreSQL:n CONSTRAINT-asetuksilla. Tietokannan tietojen vanhenemiseen käytettävien aikaleimojen Date-tyyppi toteutetaan PostgreSQL:n timestamp with time zone -tyypillä. Varattavat aikojen alkupisteet lasketaan sekunteina maanantaista klo 00 lähtien.
Taulu KAYTTAJA Käyttäjien tiedot kid serial not Tietokannan generoima juokseva yksikäsitteinen tunniste. null etunimi varchar sukunimi varchar sposoite varchar Sähköpostiosoite. salasana varchar uusisalasana varchar Asetettu, jos salasanaa ollaan vaihtamassa. uusisposoite varchar Asetettu, jos käyttäjä on rekisteröitymässä. viimkaytto date Viimeisin käyttöaika. Päivittyy triggereillä, kun käyttäjä loggaa sisälle (Tanja-sovellukseen), käyttäjän tiedot, ryhmäjäsenyydet, sopivuudet tai annetut ajat muuttuvat. Taulu RYHMA Ryhmien tiedot rid serial Juokseva tunniste. rnimi varchar Ryhmän nimi. kid =kayttaja:kid Ryhmän kutsuja. viimkaytto date Viimeisin käyttöaika. Päivittyy triggerillä, kun ryhmän aikatauluja päivitetään. Taulu OSALLISTUMINEN Ryhmiin osallistuminen kid =kayttaja:kid Käyttäjä kid osallistuu ryhmään rid. rid =ryhma:rid Taulu AIKATAULU Aikataulujen tiedot aid serial Juokseva tunniste. rid =ryhma:rid Ryhmä, johon aikataulu liittyy. animi varchar Aikataulun nimi. alkupvm date Viikkojakson alku. loppupvm date Viikkojakson loppu. tap_kesto integer Minuutteja. tap_tyyppi integer 1=Yksilötapaaminen, 2=Ryhmätapaaminen. tila integer Aikataulun tila: 0=laskematta, 1=laskettu. ryhmatap_aika integer Ryhmätapaamiselle laskettu aika. viimlaskettu date Viimeinen laskuaika. viimkaytto date Viimeinen käyttöaika. Päivittyy triggerillä, kun aikataulun tietoja, tarjottuja aikoja tai sopivuuksia muutetaan. Taulu TARJOTTU Tarjotut ajat aid =aikataulu:aid Aikataulu, johon tarjotut ajat kuuluvat. alkuaika integer Tarjotun ajan alku sekunteina maanantaista klo 0. 26
Taulu SOPIVUUS Sopivuudet aid =aikataulu:aid Aikataulu, jonka sopivuuksia käyttäjälle kid kerrotaan. kid =kayttaja:kid sopivuus int Sopivuusarvo 0-3. 0=ei tietoa, 1=ei sovi, 2=sopii kohtalaisesti, 3=sopii hyvin. alkuaika date Sopivuus alkaa tähän aikaan. Taulu ANNETTU Osallistujille annetut ajat aid =aikataulu:aid Aikataulu, johon annettu aika kuuluu. alkuaika integer Annetun ajan alku sekunteina maanantaista klo 0. kid integer Aika on varattu ko. käyttäjälle. Saa olla myös 0 tai NULL, joten tätä ei varmisteta eheystarkistuksella. 27 7.3 Indeksit SERIAL-tyyppisille avainkentille syntyvät indeksit automaattisesti. Lisäksi on luotu seuraavat indeksit: Indeksi Taulu Kentät kayttaja_sposoite kayttaja sposoite osallistuminen_rid_kid osallistuminen rid, kid sopivuus_aid_kid sopivuus aid, kid tarjottu_aid tarjottu aid annettu_aid annettu aid 7.4 Eheystarkistukset Tietokannan eheyttä valvovat seuraavat constraint-määrittelyt: Tarkistus Taulu.kenttä Taulu(kenttä) ryhma_kid_check ryhma.rid kayttaja(kid) aikataulu_ryhma_rid_check aikataulu.rid ryhma(rid) osallistuminen_kayttaja_kid_check osallistuminen.kid kayttaja(kid) osallistuminen_ryhma_rid_check osallistuminen.rid ryhma(rid) sopivuus_aikataulu_aid_check sopivuus.aid aikataulu(aid) tarjottu_aikataulu_aid_check tarjottu.aid aikataulu(aid) sopivuus_kayttaja_kid_check sopivuus.kid kayttaja(kid) 7.5 Proseduurit ja triggerit Tietokantaan on määritelty seuraavat PLPSQL-proseduurit.
28 Nimi touch() touchuser() Lähdetaulut Kohdetaulut Tarkoitus kayttaja, kayttaja, ryhma, ryhma, aikataulu aikataulu annettu, sopivuus kayttaja Virkistää kohdetaulun viimkaytto-kenttää, kun lähdetaulun ko. rivin tietoja päivitetään. Virkistää käyttäjän viimkaytto-kenttää kun hänelle annetaan tapaamisaika tai hänelle määritellään sopivuuksia.