(P) Sairaala¶
Tavoite: Opettelen modulaarisuutta olio-ohjelmoinnissa sekä sitä, miten luokat (oliot) voivat olla yhteydessä toisiinsa. Harjoittelen valmiin koodin lukemista sekä osoittimien käyttämistä ja dynaamista muistinhallintaa. Samalla kertaan STL:n säiliöitä. Myös ohjelman jakamista osiin funktioita ja luokkia käyttäen on syytä pohtia.
Ohjeita:
Hae ohjelmakoodipohja: templates/11/hospital/
->
student/11/hospital/
.
Koodipohjassa on aika monta tiedostoa ja luokkaa, mutta ne ovat hyvin
yksinkertaisia ja helposti ymmärrettäviä.
Pohjakoodissa on joitakin komentoja toteutettu valmiiksi. Voit aloittaa kokeilemalla, miten ne toimivat.
Tärkeää
Ennen kuin aloitat, lue huolellisesti koko tehtävänanto. Huomaa erityisesti kohdat Ohjelman toteuttaminen osissa (vaaditut commitit) sekä Erityisvaatimukset.
Huomautus
Tämä projekti tehdään itsenäisenä työskentelynä. Parityöskentely ei ole sallittua, vaan sitä pidetään plagiointina.
Toteuta valmiiksi ohjelma, joka käynnistyessään lukee käyttäjän antamia komentoja. Komennosta riippuen ohjelma joko tallentaa tietoja sopivaan tietorakenteeseen, poistaa niitä, tai tekee hakuja kyseiseen tietorakenteeseen.
Alkukommentti ja palautteen kieli¶
Samoin kuin ensimmäisessä projektissa, tässäkin projektissa vaaditaan alkukommentti. Tällä kertaa alkukommenttia ei anneta valmiina, vaan sinun pitää kirjoittaa se itse. Mallia voit katsoa ensimmäisen projektin tehtävänannosta (4.6 (P) Muistipeli).
Palautteen kieli valitaan palautuslaatikossa (tämän sivun lopussa). Palautteen kielenä on oletuksena suomi, mutta voit vaihtaa sen, jos haluat assistenttien antaman palautteen englanniksi. Kielivalinta määräytyy sen perusteella, minkä kielivalinnan olet tehnyt viimeisimmän palautuksen palautuslaatikossa.
Ohjelman toiminnan kuvaus¶
Ohjelmassa on luokat Hospital
, CarePeriod
, Person
, Date
ja Cli
sekä moduuli Utils
.
Luokan Person
oliot (ilmentymät) voivat olla joko potilaita tai sairaalan
henkilökuntaa (mutta eivät molempia).
Henkilökuntaa ei ole eroteltu sen tarkemmin, esimerkiksi jaoteltu
lääkäreihin ja hoitajiin.
Henkilöiden tunnistamiseen voi käyttää nimeä (kuten on tehty esimerkkiajoissa
alempana) tai mitä tahansa merkkijonoa.
Sairaalan henkilökunta on pysyvää. Rekrytoinnin jälkeen jäsenet säilyvät henkilökunnassa ohjelman loppuun asti. (Ohjelmassa on rekrytointikomento mutta ei komentoa henkilökunnan poistamiseen.) Potilaita voidaan sekä lisätä että poistaa. Potilasta lisättäessä luodaan myös uusi hoitojakso, ja kaikki luodut hoitojaksot säilyvät ohjelman loppuun asti. Samalla potilaalla voi olla useita hoitojaksoja ohjelman aikana. Toisin sanoen sama potilas voi tulla sairaalaan ja päästä sairaalasta useita kertoja ohjelman aikana.
Luokka CarePeriod
kuvaa yhden potilaan yhden hoitojakson,
mutta kuten edellä mainittiin, samalla potilaalla voi olla useita hoitojaksoja.
Hoitojaksolla on ainakin alkamispäivämäärä, ja päättyneillä hoitojaksoilla
on myös päättymispäivämäärä.
Potilaan lisäksi hoitojaksolla on henkilökunnan jäseniä 0-n
kappaletta.
Sama henkilö voi olla työntekijänä usealla (saman potilaan tai eri
potilaiden) hoitojaksolla.
Potilaalla voi myös olla lääkkeitä.
Lääke on kuvattu ohjelmassa tietueena (struct
) eikä luokkana,
koska lääkkeellä ei ole mitään operaatioita.
Kyseinen tietue löytyy luokasta Person
.
Lääkkeet ovat potilaskohtaisia, ja ne säilyvät hoitojaksosta toiseen.
Kun (ja vain kun) potilas on hoitojaksolla sairaalassa, hänelle voidaan
lisätä lääkkeitä tai poistaa niitä, mutta hoitojakson päättyessä potilaalla
säilyy ne lääkkeet, jotka hänelle on määrätty ja joita ei ole poistettu.
Sen sijaan potilasta hoitaneet henkilökunnan jäsenet ovat
hoitojaksokohtaisia, ja eri hoitojaksoilla
potilasta voivat hoitaa eri henkilöt (tai samat).
Luokka Cli
(command line interpreter) kuvaa komentotulkin,
eli se hallinnoi ohjelmassa käytettyjä komentoja.
Moduuli Utils
tarjoaa muutaman yleiskäyttöisen funktion.
Kumpaankaan näistä (Cli
tai Utils
) ei tarvitse tehdä mitään muutoksia.
Näissä moduuleissa tarkistetaan esimerkiksi, antaako käyttäjä komennolle
oikean määrän oikean tyyppisiä parametreja.
Tarkistukset on toteutettu valmiiksi, joten niistä ei tarvitse huolehtia.
Luokka Hospital
hallinnoi koko ohjelmaa, ja siitä luodaan vain yksi olio.
Sairaalassa on potilaita, henkilökuntaa sekä hoitojaksoja.
Luokkien väliset suhteet näkyvät alla olevassa kuvassa.
Luokasta A luokkaan B on piirretty nuoli, jos luokka A tuntee luokan B.
Tällöin luokan A attribuuttina on luokan B ilmentymä
(tai osoitin siihen).
Luokka Cli
ja moduuli Utils
on jätetty kuvasta pois,
koska ne ovat apumoduuleja, eivätkä varsinaisesti kuulu sairaalajärjestelmään.
Nuolten päälle on tarvittaessa kirjoitettu selvennys, joka voi
auttaa ymmärtämään, miksi yhteys tarvitaan.
Kuvassa syntymäpäivänuoli on katkoviivalla, koska tällainen yhteys voisi hyvin luontevasti olla olemassa, mutta ohjelmassa tätä ei oikeasti käytetä.
Kuten edellä kerrottiin, sama henkilö voi esiintyä useassa eri paikassa. Esimerkiksi sama potilas voi olla potilaana usealla hoitojaksolla, ja sama henkilö voi työskennellä usealla hoitojaksolla. Tästä syystä tarvitset osoittimia. Kukin henkilö luodaan vain kerran, ja jos/kun henkilöä tarvitaan eri paikoissa, käytetään osoitinta kyseiseen henkilöön.
Yleistä asiaa komennoista¶
Ohjelmassa on aika monta komentoa, mutta sinun tehtävänäsi on toteuttaa vain noin puolet niistä.
Ohjelmalle ei anneta syötetiedostoa, joten alussa sairaala on tyhjä,
eli siellä ei ole henkilökuntaa eikä potilaita.
Lisäykset (samoin kuin poistot) tehdään komennoilla.
Komentojen joukossa on kuitenkin READ_FROM
, joka lukee
komennot annetusta tiedostosta (ks. komento 3 valmiiksi toteutetuista
komennoista).
Ohjelman käynnistyessä sekä aina kun käyttäjältä odotetaan syötettä, tulostetaan rivin alkuun:
Hosp>
Tähän kehotteeseen ohjelman käyttäjä voi syöttää komentoja
(tai vain painaa Enter-näppäintä).
Komennot voidaan kirjoittaa isoilla tai pienillä kirjaimilla tai
käyttää sekaisin isoja ja pieniä kirjaimia.
Näin ollen lopetuskomennon sallittuja muotoja ovat esimerkiksi QUIT
,
quit
ja Quit
.
Komennoilla on myös muutaman kirjaimen pituiset lyhenteet,
jotka on kerrottu HELP
-komennon yhteydessä.
Esimerkiksi lopetuskomennon lyhenne on Q
(tai pienellä
kirjoitettuna q
).
Kullakin komennolla on määrätty määrä parametreja. Parametrit näkyvät kunkin komennon kuvauksessa kulmasulkujen sisällä. Jos parametri koostuu useammasta sanasta, se pitää kirjoittaa lainausmerkkien sisään. Jos parametreja on liikaa tai liian vähän, tulostetaan virheilmoitus:
Error: Wrong amount of parameters.
Parametrien määrän tarkastaminen on toteutettu pohjakoodiin, joten siitä ei tarvitse huolehtia.
Jos käyttäjä antaa jonkin muun komennon kuin ohjelman tunteman, tulostetaan virheilmoitus:
Hosp> jotakin
Error: Unknown commands given.
Hosp>
Hosp>
Kun käyttäjän syöttämä komento on suoritettu, ohjelma tulostaa
kehotteen uudelleen.
Tätä jatketaan kunnes käyttäjä syöttää komennon QUIT
.
Jos käyttäjä pelkästään painaa Enter-näppäintä antamatta mitään komentoa, kehote tulostuu uudelleen, kuten näkyy viimeisimmässä esimerkissä. Tässä mielessä ohjelma toimii kuten Linux-etätyöpöydän komentorivi.
Seuraavissa kahdessa osiossa on ensin kuvattu toteutetut komennot ja sen jälkeen toteutettavat kommennot. Luonnollisesti ensimmäistä näistä osioista ei tarvitse lukea kovin tarkkaan, koska riittää osata käyttää komentoja. Jälkimmäinen osio taas tulee lukea tarkasti, koska tehtäväsi on toteuttaa nämä komennot.
Toteutetut komennot virheilmoituksineen¶
QUIT
- Ohjelman suoritus päätty paluuarvoonEXIT_SUCCESS
ilman, että ohjelma tulostaa mitään. Komennolla ei ole parametreja, mutta jos käyttäjä antaa parametreja, niitä ei huomioida.HELP
- Komento tulostaa kaikki käytössä olevat ole komennot lyhenteineen. Kullakin rivillä näkyy ensin komennon kuvaus ja kaksoispisteen jälkeen komento ja sen lyhenne:Hosp> HELP Recruit staff : RECRUIT R Take patient to hospital : ENTER E Take patient from hospital : LEAVE L Assign staff for a patient : ASSIGN_STAFF AS Add medicine for a patient : ADD_MEDICINE AM Remove medicine from a patient : REMOVE_MEDICINE RM Print patient's info : PRINT_PATIENT_INFO PPI Print care periods per staff : PRINT_CARE_PERIODS PCPS Print all used medicines : PRINT_ALL_MEDICINES PAM Print all staff : PRINT_ALL_STAFF PAS Print all patients : PRINT_ALL_PATIENTS PAP Print current patients : PRINT_CURRENT_PATIENTS PCP Set date : SET_DATE SD Advance date : ADVANCE_DATE AD Read : READ_FROM RF Help : HELP H Quit : QUIT Q Hosp>
READ_FROM <tiedosto>
- Komennolla voidaan lukea annetusta tiedostosta komennot parametreineen, mikä voi helpottaa ohjelman testaamista. Pohjakoodien mukana saat tiedostonassignment.input
, joka sisältää esimerkkiajoissa esiintyneitä komentoja. Tiedostossa on käytetty komentojen lyhenteitä. Tiedoston sisältö on seuraava:e Pekka r Jussi ah Jussi Pekka ad 2 l Pekka e Pekka am Burana 200 2 Pekka q
Kyseinen tiedosto voidaan antaa lukukomennolle parametrina seuraavasti:
Hosp> READ_FROM assignment.input Input read from file: assignment.input Hosp>
Tällä tavalla saat suoritettua kaikki tiedoston sisältämät onnistuneet komennot nopeammin, kuin jos kirjoittaisit ne yksitellen kehotteen jälkeen.
Huomaa, että tiedosto
assignment.input
sisältää myös sellaisia komentoja, joita ei ole toteutettu pohjakoodissa.Jos tiedostossa oleva komento on virheellinen, esimerkiksi parametreja on väärä määrä, mitään virheilmoitusta ei tulostu, kuten komentoriviltä tulostuisi. Lisäksi tiedostossa täytyy olla viimeisenä komentona
QUIT
(tai sen lyhenne), sillä muuten tiedoston lukeminen ei lopu koskaan. Noudata siis edellä kerrottuja ohjeita, jos käytät itse kirjoittamaasi syötetiedostoa testatessasi ohjelmaa. Ohjelman testaaminen (tavalla tai toisella) on erittäin suositeltavaa.Jos komennon parametriksi annetaan tuntematon tiedosto, tulostetaan virheilmoitus:
Hosp> READ_FROM ei_loydy.txt Error: Can't read given file.
Tämän jälkeen ohjelman toiminta päättyy paluuarvoon
EXIT_SUCCESS
.SET_DATE <pp> <kk> <vvvv>
- Komennolla voidaan asettaa uudeksi päivämääräksi päivämääräpp.kk.vvvv
. (Nykyiseksi päivämääräksi on asetettu 24.2.2021 tiedostossautils.hh
, ja halutessasi voit muuttaa sitä myös koodiin, mutta tämä komento hoitaa saman asian.) Komennolla on kolme kokonaislukuparametria. Jos päivä (tai kuukausi) on numeroltaan 1, se voidaan antaa joko muodossa1
tai01
, ja sama pätee muihin 1-numeroisiin lukuihin. Esimerkiksi:Hosp> SET_DATE 1 04 2021 Date has been set to 1.4.2021 Hosp>
Jos parametriksi annetaan liian suuri luku, joka ei sovi päiväksi tai kuukaudeksi, kyseiseksi luvuksi asetetaan 1. Esimerkiksi:
Hosp> SET_DATE 32 13 2021 Date has been set to 1.1.2021 Hosp>
Jos jokin parametreista on jotakin muuta kuin positiivinen kokonaisluku, ohjelma tulostaa virheilmoituksen:
Hosp> SET_DATE 1 3 w Error: Wrong type of parameters.
ADVANCE_DATE <ei-negatiivinen kokonaisluku>
- Komennolla voidaan siirtää nykyistä päivämäärä parametrina annetun ei-negatiivisen kokonaisluvun verran päiviä eteenpäin. Esimerkiksi:Hosp> ADVANCE_DATE 7 New date is 3.3.2021 Hosp>
Jos komennolle antaa parametriksi nollan, saa selville nykyisen päivämäärän. Esimerkiksi:
Hosp> ADVANCE_DATE 0 New date is 24.2.2021 Hosp>
Jos parametriksi annetaan jotakin muuta kuin ei-negatiivinen kokonaisluku, tulostetaan virheilmoitus:
Hosp> ADVANCE_DATE -1 Error: Wrong type of parameters. Hosp>
RECRUIT <id>
- Komennolla voi lisätä sairaalan henkilökuntaan uuden jäsenen. Parametrina annetaan tunniste, esimerkiksi nimi. (Annettua tunnistetta voidaan käyttää parametrina muissa komennoissa.) Esimerkki henkilökunnan lisäämisestä:Hosp> RECRUIT Jussi A new staff member has been recruited. Hosp>
Jos samanniminen henkilö on henkilökunnassa jo ennestään, tulostetaan virheilmoitus:
Hosp> RECRUIT Jussi Error: A new staff member has been recruited. Hosp> RECRUIT Jussi Error: Already exists: Jussi Hosp>
PRINT_ALL_STAFF
- Komento tulostaa sairaalaan rekrytoidun henkilökunnan. Jäsenet tulostetaan allekkain aakkosjärjestyksessä. Jos henkilökuntaa ei ole yhtään, tulostetaanNone
. Esimerkiksi:Hos> PRINT_ALL_STAFF None Hosp> RECRUIT Jussi A new staff member has been recruited. Hosp> PRINT_ALL_STAFF Jussi Hosp> RECRUIT Jukka A new staff member has been recruited. Hosp> PRINT_ALL_STAFF Jukka Jussi
ADD_MEDICINE <lääkkeen nimi> <vahvuus> <annostus> <potilaan id>
- Komennolla potilaalle voidaan lisätä lääke, jonka vahvuus (milligrammoina) ja annostus annetaan kokonaislukuina.Lääkkkeitä voidaan määrätä vain sellaisille potilaille, jotka ovat tällä hetkellä sairaalassa. Seuraavissa esimerkeissä oletetaan, että
Pekka
on potilaana sairaalassa:Hosp> ADD_MEDICINE Burana 200 2 Pekka Medicine added for: Pekka Hosp>
Jos potilaalle on jo ennestään määrätty kyseinen lääke, komennolla voidaan muuttaa lääkemääräystä (vahvuutta ja/tai annostusta). Jos koko lääkemääräys (nimi, vahvuus, annostus) on sama kuin potilaalla on ollut ennestään, ei tapahdu mitään, eikä mitään virheilmoitusta anneta. Esimerkiksi:
Hosp> ADD_MEDICINE Burana 400 2 Pekka Medicine added for: Pekka Hosp> ADD_MEDICINE Burana 400 2 Pekka Medicine added for: Pekka Hosp>
Jos vahvuudeksi tai annostukseksi annetaan jotakin muuta kuin kokonaislukuja, tulostetaan virheilmoitus:
Hosp> ADD_MEDICINE Voltaren xx yy Pekka Error: Wrong type of parameters. Hosp>
Jos parametrina annettua potilasta ei löydy (hän ei ole sillä hetkellä sairaalassa), tulostetaan virheilmoitus:
Hosp> ADD_MEDICINE Voltaren 100 1 joku Error: Can't find anything matching: joku Hosp>
REMOVE_MEDICINE <lääkkeen nimi> <potilaan id>
- Komennolla potilaalta voidaan poistaa lääke. Lääkkeitä voi poistaa vain sairaalassa tällä hetkellä olevilta potilailta. Alla olevissa esimerkeissä oletaan, ettäPekka
on potilaana sairaalassa:Hosp> REMOVE_MEDICINE Burana Pekka Medicine removed from: Pekka Hosp>
Jos kyseistä lääkettä ei ole määrätty potilaalle, ei tapahdu mitään, eikä mitään virheilmoitusta anneta. Esimerkiksi:
Hosp> REMOVE_MEDICINE Burana Pekka Medicine removed from: Pekka Hosp> REMOVE_MEDICINE Burana Pekka Medicine removed from: Pekka Hosp>
Jos parametrina annettua potilasta ei löydy (hän ei ole sillä hetkellä sairaalassa), tulostetaan virheilmoitus:
Hosp> REMOVE_MEDICINE Burana joku Error: Can't find anything matching: joku Hosp>
Toteutettavat komennot virheilmoituksineen¶
ENTER <id>
- Komennolla voi lisätä uuden potilaan sairaalaan. Parametrina annetaan tunniste, esimerkiksi potilaan nimi. (Annettua tunnistetta voidaan käyttää parametrina muissa komennoissa.) Esimerkki potilaan lisäämisestä:Hosp> ENTER Pekka A new patient has entered. Hosp>
Potilaan saapuessa sairaalaan luodaan myös uusi hoitojakso, jonka alkupäivämääräksi laitetaan
Utils
-moduulintoday
-muuttujan sen hetkinen arvo.Jos samanniminen potilas on jo ennestään, tulostetaan virheilmoitus:
Hosp> ENTER Pekka A new patient has entered. Hosp> ENTER Pekka Error: Already exists: Pekka Hosp>
Kuitenkin jos potilas välillä lähtee sairaalasta (komennolla
LEAVE
), hänet voi lisätä uudelleen (uudelle hoitojaksolle). Tällaisessa tapauksessa ei luoda uutta potilasta, vaan ohjelman pitää säilyttää tiedot kaikista sairaalassa joskus olleista potilaista. Riittää kuitenkin säilyttää vain saman ajon aikana syntyneet tiedot. Jos ohjelma käynnistetään uudelleen, sairaalassa ei aluksi ole henkilökuntaa eikä potilaita.Uusi hoitojakso luodaan joka tapauksessa riippumatta siitä, onko potilas ollut ennestään sairaalassa vai ei.
LEAVE <id>
- Komennolla voi poistaa potilaan sairaalasta, mutta tiedot hänen hoitojaksostaan säilytetään (hoitojakson päivämäärät sekä henkilökunta). Esimerkiksi:Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp>
Kun potilas poistuu sairaalasta, hänen nykyinen hoitojaksonsa päättyy, jolloin hoitojaksolle voidaan asettaa päättymispäiväksi nykyinen päivämäärä.
Jos poistettavaa potilasta ei löydy (hän ei ole tällä hetkellä sairaalassa), tulostetaan virheilmoitus:
Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp> LEAVE Pekka Error: Can't find anything matching: Pekka Hosp>
Seuraavassa esimerkissä näkyy, miten potilas voi ensin tulla sairaalaan ja sitten lähteä ja tulla taas takaisin:
Hosp> ENTER Pekka A new patient has entered. Hosp> ENTER Pekka Error: Already exists: Pekka Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp> ENTER Pekka A new patient has entered. Hosp>
ASSIGN_STAFF <henkilökunnan jäsenen id> <potilaan id>
- Komennolla voidaan sijoittaa annettu henkilökunnan jäsen työskentelemään annetun potilaan nykyisellä hoitojaksolla. Esimerkiksi:Hosp> ENTER Pekka A new patient has entered. Hosp> RECRUIT Jussi A new staff member has been recruited. Hosp> ASSIGN_STAFF Jussi Pekka Staff assigned for: Pekka Hosp>
Jos sama henkilökunnan jäsen yritetään sijoittaa samalle potilaalle uudelleen, ei tapahdu mitään, eikä mitään virheilmoitusta anneta:
Hosp> ASSIGN_STAFF Jussi Pekka Staff assigned for: Pekka Hosp> ASSIGN_STAFF Jussi Pekka Staff assigned for: Pekka
Seuraavassa esimerkissä oletetaan, että yllä olevat komennot on suoritettu ensin. Jos henkilökunnan jäsentä tai potilasta ei löydy, ohjelma tulostaa alla näkyvän virheilmoituksen:
Hosp> ASSIGN_STAFF Jukka Pekka Error: Can't find anything matching: Jukka Hosp> Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp> ASSIGN_STAFF Jussi Pekka Error: Can't find anything matching: Pekka Hosp> Hosp> ASSIGN_STAFF Jukka Pekka Error: Can't find anything matching: Jukka Hosp>
Yleisemmin sanottuna, jos ensimmäistä tunnistetta (id) ei löydy, ilmoitetaan siitä. Jos ensimmäinen löytyy mutta toinen ei, ilmoitetaan toisesta. Jos kumpaakaan ei löydy, ilmoitetaan vain ensimmäisen puuttumisesta.
PRINT_PATIENT_INFO <potilaan id>
- Komento tulostaa tiedot potilaan kaikista hoitojaksoista sekä potilaan lääkityksen. Hoitojaksoista tulostetaan henkilökunta sekä alkupäivämäärä, päättyneistä hoitojaksoista tulostetaan lisäksi myös päättymispäivämäärä. Hoitojaksot tulostetaan aikajärjestyksessä (aikaisempi ensin). Henkilökunta ja lääkkeet tulostetaan aakkosjärjestyksessä. Jos henkilökuntaa tai lääkkeitä ei ole, niiden kohdalle tulostetaanNone
. Esimerkiksi:Hosp> ENTER Pekka A new patient has entered. Hosp> PRINT_PATIENT_INFO Pekka * Care period: 24.2.2021 - - Staff: None * Medicines: None Hosp> Hosp> ADD_MEDICINE Burana 200 2 Pekka Medicine added for: Pekka Hosp> ADD_MEDICINE Panadol 500 1 Pekka Medicine added for: Pekka Hosp> Hosp> RECRUIT Jussi A new staff member has been recruited. Hosp> RECRUIT Jukka A new staff member has been recruited. Hosp> Hosp> ASSIGN_STAFF Jussi Pekka Staff assigned for: Pekka Hosp> ASSIGN_STAFF Jukka Pekka Staff assigned for: Pekka Hosp> Hosp> PRINT_PATIENT_INFO Pekka * Care period: 24.2.2021 - - Staff: Jukka Jussi * Medicines: - Burana 200 mg x 2 - Panadol 500 mg x 1 Hosp> Hosp> ADVANCE_DATE 2 New date is 26.2.2021 Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp> ADVANCE_DATE 3 New date is 1.3.2021 Hosp> Hosp> ENTER Pekka A new patient has entered. Hosp> PRINT_PATIENT_INFO Pekka * Care period: 24.2.2021 - 26.2.2021 - Staff: Jukka Jussi * Care period: 1.3.2021 - - Staff: None * Medicines: - Burana 200 mg x 2 - Panadol 500 mg x 1 Hosp>
Jos annettua potilasta ei löydy, ohjelma tulostaa virheilmoituksen:
Hosp> PRINT_PATIENT_INFO joku Error: Can't find anything matching: joku Hosp>
Komento toimii kaikilla sairaalassa joskus olleilla potilailla. Toisin sanoen potilas jää löytymättä vain, jos hän ei ole koskaan ollut sairaalassa.
Kuten ohjelman toiminnan kuvauksessa kerrottiin, lääkitys on potilaskohtaista, eli se ei riipu hoitojaksoista. Potilaalle sijoitetut henkilökunnan jäsenet taas ovat hoitojaksokohtaisia.
PRINT_CARE_PERIODS <henkilökunnan jäsenen id>
- Komento tulostaa hoitojaksot, joilla annettu henkilökunnan jäsen on työskennellyt tai työskentelee. Hoitojaksoista tulostetaan potilas sekä alkupäivämäärä, päättyneistä hoitojaksoista tulostetaan lisäksi myös päättymispäivämäärä. Hoitojaksot tulostetaan aikajärjestyksessä (aikaisempi ensin). Jos annettu henkilökunnan jäsen on rekrytoitu, mutta häntä ei ole sijoitettu työskentelemään kenenkään potilaan hoitojaksolle (komennollaASSIGN_STAFF
), ohjelma tulostaaNone
. Esimerkiksi:Hosp> RECRUIT Jussi A new staff member has been recruited. Hosp> PRINT_CARE_PERIODS Jussi None Hosp> ENTER Pekka A new patient has entered. Hosp> ENTER Matti A new patient has entered. Hosp> ASSIGN_STAFF Jussi Pekka Staff assigned for: Pekka Hosp> ASSIGN_STAFF Jussi Matti Staff assigned for: Matti Hosp> ADVANCE_DATE 2 New date is 26.2.2021 Hosp> LEAVE Matti Patient left hospital, care period closed. Hosp> Hosp> PRINT_CARE_PERIODS Jussi 24.2.2021 - * Patient: Pekka 24.2.2021 - 26.2.2021 * Patient: Matti Hosp>
Jos annettua henkilökunnan jäsentä ei löydy, ohjelma tulostaa virheilmoituksen:
Hosp> PRINT_CARE_PERIODS joku Error: Can't find anything matching: joku Hosp>
PRINT_ALL_MEDICINES
- Komento tulostaa kaikkien sairaalassa joskus olleiden (myös nykyisten) potilaiden tällä hetkellä käytössä olevat lääkkeet. Lääkkeet tulostetaan aakkosjärjestyksessä, ja kustakin lääkkeestä kerrotaan, kenelle sitä on määrätty. Potilaat, joilla on käytössä sama lääke, tulostetaan aakkosjärjestyksessä. Lääkkeet ovat samoja, jos niillä on sama nimi, vahvuuksista tai annostuksista ei välitetä. Jos yhtään lääkettä ei ole käytössä, tulostetaanNone
. Esimerkiksi:Hosp> PRINT_ALL_MEDICINES None Hosp> ENTER Pekka Hosp> ADD_MEDICINE Burana 200 2 Pekka Medicine added for: Pekka Hosp> ADD_MEDICINE Panadol 500 1 Pekka Medicine added for: Pekka Hosp> Hosp> ENTER Matti Hosp> ADD_MEDICINE Burana 400 2 Matti Medicine added for: Matti Hosp> Hosp> PRINT_ALL_MEDICINES Burana prescribed for * Matti * Pekka Panadol prescribed for * Pekka Hosp> Hosp> REMOVE_MEDICINE Burana Pekka Medicine removed from: Pekka Hosp> PRINT_ALL_MEDICINES Burana prescribed for * Matti Panadol prescribed for * Pekka Hosp> Hosp> LEAVE Pekka Patient left hospital, care period closed. Hosp> PRINT_ALL_MEDICINES Burana prescribed for * Matti Panadol prescribed for * Pekka Hosp>
PRINT_ALL_PATIENTS
- Komento tulostaa tiedot kaikista sairaalassa joskus olleista potilaista, myös nykyisistä. Potilaiden tiedot tulostetaan potilaan tunnisteen (id) mukaisessa aakkosjärjestyksessä. Jos sairaalassa ei ole yhtään potilasta, tulostetaanNone
.Komento antaa saman tulostuksen kuin komento
PRINT_PATIENT_INFO
, mutta ikään kuin kyseinen komento suoritettaisiin niin monta kertaa, kuin sairaalassa on ollut potilaita. Ennen kunkin potilaan tietojen tulostamista, tulostetaan kyseisen potilaan tunniste (id).Jos oletaan, että edellisen komennon (
PRINT_ALL_MEDICINES
) esimerkkiajon mukaiset toiminnot on suoritettu, ohjelma tulostaa:Hosp> PRINT_ALL_PATIENTS Matti * Care period: 24.02.2021 - - Staff: None * Medicines: - Burana 400 mg x 2 Pekka * Care period: 24.02.2021 - 24.02.2021 - Staff: None * Medicines: - Panadol 500 mg x 1 Hosp>
Jos sairaalassa ei olisi koskaan ollut yhtään potilasta, komennon tulostus näyttäisi tältä:
Hosp> PRINT_ALL_PATIENTS None Hosp>
PRINT_CURRENT_PATIENTS
- Komento tulostaa tiedot kaikista sairaalan nykyisistä potilaista. Potilaiden tiedot tulostetaan potilaan nimen mukaisessa aakkosjärjestyksessä.Komento antaa saman tulostuksen kuin komento
PRINT_PATIENT_INFO
, mutta ikään kuin kyseinen komento suoritettaisiin niin monta kertaa, kuin sairaalassa on tällä hetkellä potilaita. Ennen kunkin potilaan tietojen tulostamista, tulostetaan kyseisen potilaan nimi.Jos oletaan, että aikaisemman komennon (
PRINT_ALL_MEDICINES
) esimerkkiajon mukaiset toiminnot on suoritettu, ohjelma tulostaa:Hosp> PRINT_CURRENT_PATIENTS Matti * Care period: 24.02.2021 - - Staff: None * Medicines: - Burana 400 mg x 2 Hosp>
Jos sairaalassa ei olisi tällä hetkellä yhtään potilasta, komennon tulostus näyttäisi tältä:
Hosp> PRINT_CURRENT_PATIENTS None Hosp>
Kun ohjelma toiminta lopetaan, se tulostaa vielä henkilöt, joille varattu tila vapautetaan. Tämä voi olla hyödyllistä, kun testaat ohjelmaa omilla testeilläsi. Jos ohjelmassa on käytetty edellisissä esimerkeissä esiintyneitä henkilöitä, tulostetaan:
Hosp> QUIT
Person Jukka destructed.
Person Jussi destructed.
Person Matti destructed.
Person Pekka destructed.
Press <RETURN> to close this window...
Automaattitesteissä oletetaan kuitenkin, että tällaisia tulostuksia
ei ole, joten ennen Plussa-palautusta poista luokan Person
purkajasta
sen ainoa koodirivi.
Ohjelman moduulit¶
Koodipohja koostuu pääohjelmamoduulista sekä kuudesta muusta moduulista.
Pääohjelmamoduuli on hyvin yksinkertainen.
Se vain käynnistää komentotulkin (command line interpreter, CLI), joka
pyörii niin kauan kuin käyttäjä antaa komennon QUIT
.
Pääohjelmaa ei ole tarpeen muuttaa.
Ohjelmaan kuuluu moduuli Utils
, joka ei ole luokka vaan nimiavaruus.
Se tarjoaa tutun apufunktion split
, funktion is_numeric
sekä
päivämäärän today
.
Päivämäärän arvoa voit halutessasi päivittää tiedostosta utils.hh
.
Tällä hetkellä päivämääränä on 24.2.2021.
Muilta osin tätä moduulia ei ole tarpeen muuttaa.
Päivämäärää voi muuttaa myös komennolla SET_DATE
.
Komentotulkki eli luokka Cli
on määritelty ja toteutettu
tiedostoissa cli.hh
ja cli.cpp
.
Luokka on annettu koodipohjassa valmiina, eikä siihen
tarvitse tehdä muutoksia.
Luokan tehtävänä on tunnistaa komennot käyttäjän syötteistä.
Kaikki komennot toteutetaan luokassa Hospital
.
Komentotulkin otsikkotiedostossa on komentovektori, joka sisältää
funktio-osoittimia.
Sen perusteella näet
missä Hospital
-luokan jäsenfunktiossa mikäkin komento on toteutettu.
Muilta osin komentotulkin toimintaa ei ole välttämätöntä ymmärtää.
Erityisesti funktio-osoittimien osaamista/ymmärtämistä ei vaadita.
Luokka Date
kuvaa päivämääriä.
Kukin päivämäärän osa (päivä, kuukausi, vuosi) on esitetty kokonaislukuna.
Päivämäärää voidaan siirtää parametrina saadun
päivälukumäärän verran eteenpäin metodilla advance
.
Metodi is_default
kertoo, onko päivämäärä oletuspäivämäärä
eli päivämäärä, jossa päivän, kuukauden ja vuoden arvot ovat nollia.
Jos hoitojakso ei ole vielä päättynyt, sen loppupäivämäärä on
oletuspäivämäärä.
Metodia is_default
voi siis käyttää selvittämään, onko hoitojakso
päättynyt.
Lisäksi Date
-luokassa on metodit päivämäärän asettamiseen ja tulostamiseen.
Päivämäärien yhtäsuuruutta voidaan vertailla.
Luokalla on myös operaattori <
:
päivämäärä a
on pienempi kuin päivämäärä b
, jos
a
edeltää päivämäärää b
.
(Vertailuoperaattorifunktioille ei nykyisessä koodissa ole käyttöä.)
Luokkaan Date
ei tarvitse tehdä muutoksia.
Luokka Person
kuvaa henkilöitä: potilaita ja sairaalan henkilökuntaa.
Henkilöt tunnistetaan attribuutin id_
avulla.
Edellä olevissa esimerkeissä tunnisteina käytettiin nimiä.
Tällöin henkilöillä pitää olla yksikäsitteiset nimet.
Periaatteessa potilas ja henkilökunnan jäsen voisivat olla samannimisiä, mutta
silloin heidät tulkittaisiin eri henkilöiksi (eri olioiksi).
Luokalla Person
on myös attribuutti date_of_birth_
, mutta sitä
ei välttämättä tarvittaisi.
Luokan attribuutti medicines_
on map
, joka sisältää henkilölle
(potilaalle) määrätyt lääkkeet.
Henkilökunnalle ei pystytä lisäämään lääkkeitä, koska lääkkeitä voi määrätä
vain sairaalassa sillä hetkellä oleville potilaille.
Luokkaa Person
ei tarvitse muuttaa, ellet sitten halua lisätä sinne
metodeita, joita kutsut muihin luokkiin toteuttamistasi metodeista.
(Muista kuitenkin poistaa luokan purkajasta tulostusrivi, kuten neuvottiin
edellisen osion lopussa.)
Ohjelmassa on myös luokka CarePeriod
, joka kuvaa hoitojaksoja.
Luokan toteuttaminen on jätetty sinun tehtäväksesi.
Luokka Hospital
kuvaa sairaalaa (joita yleisesti voisi olla useitakin
mutta joita tässä ohjelmassa on vain yksi).
Luokassa on tiedot kaikista sairaalan hoitojaksoista sekä henkilöistä,
jotka voivat olla potilaita tai henkilökuntaa.
Näitä tietoja varten luokassa on säiliöt,
joihin tallennetaan uusia alkioita käyttäjän komentojen perusteella.
Kaikki sairaalaan kohdistuvat komennot toteutetaan tässä luokassa.
Huomaa, että samalla potilaalla voi olla useita hoitojaksoja, ja sama
henkilö voi työskennellä usealla hoitojaksolla.
Tällaisissa tapauksissa luodaan vain yksi Person
-olio,
johon on osoittimet useasta eri paikasta (tietorakenteesta).
Tällaisessa tilanteessa osoittimet ovat välttämättömiä.
Moduulien (luokkien) väliset suhteet tulevat ilmi tehtävänannon alussa esitetystä kuvasta.
Tarkempi tehtävänanto¶
Tehtävänäsi on täydentää luokat Hospital
ja CarePeriod
niin, että komennot toimivat edellä kuvatulla tavalla.
Muitakin luokkia saat muuttaa tarpeen mukaan.
Voit ehkä kokea tarpeelliseksi lisätä johonkin luokkaan uusia metodeja.
Useimmat tietorakenteet on annettu valmiina.
Luokka CarePeriod
on melkein kokonaan tyhjä, ja sen saat suunnitella
ja toteuttaa kokonaan itse.
Luokasta Hospital
puuttuu toteutukset metodeille:
enter
leave
assign_staff
print_patient_info
print_care_periods
print_all_medicines
print_all_patients
print_current_patients
.
Kunkin näistä on tarkoitus toteuttaa samanniminen puuttuva komento.
Myös muita apufunktioita saa toteuttaa ja lisätä attribuutteja.
Koodi (esimerkiksi tulostuskoodi) kannattaa sijoittaa siihen luokkaan, jonka tietoja käsitellään (tulostetaan). Esimerkiksi tulostusketju voi lähteä jostakin “isommasta” luokasta, joka ehkä itse tulostaa jotakin ja pyytää sitten osiaan tulostamaan osuutensa. Tässä isommalla luokalla tarkoitetaan luokkaa, jolla on osinaan (attribuutteinaan) toisten luokkien ilmentymiä.
Tehtävää tehdessäsi kannattaa juurikin kiinnittää huomiota siihen, miten toisen luokan ilmentymät (oliot tai osoittimet niihin) voivat olla toisen luokan attribuutteina.
Ohjelmassa on monenlaisia henkilöitä: henkilökuntaa, sairaalassa tällä
hetkellä olevia potilaita ja siellä joskus olleita potilaita.
Kaikki nämä ovat kuitenkin luokan Person
ilmentymiä.
Eri henkilöitä voi erotella lisäämällä Person
-luokkaan sopivia
totuusarvoisia (bool
) tai luettelotyyppisiä (enum
) attribuutteja.
Tai voit koota erilaiset henkilöt eri säiliöihin (mikä on ehkä parempi
ratkaisu).
Luokassa Hospital
on esimerkiksi attribuutti current_patients_
,
joka sisältää sairaalassa tällä hetkellä olevat potilaat.
Monien komentofunktioiden (komennon toteuttava metodi) parametrina
on params
, jonka tyyppinä on Params
.
Kyseessä on vektori, jonka määrittely on tiedostossa hospital.hh
.
Parametrien määrät tarkistetaan Cli
-luokan exec
-metodissa,
joten kaikissa toteutettavissa funktioissa voit olettaa, että
params
-vektorissa on juuri sen verran alkioita, kuin kyseinen komento
vaatii.
Joillakin komennoilla ei ole lainkaan parametreja, jolloin vastaavat
komentofunktiot eivät käytä saamaansa params
-parametria.
Silloin tämän parametrin nimi on jätetty pois.
Tyyppiä ei kuitenkaan voi jättää pois, sillä funktiota on kutsuttu
funktio-osoittimen kautta.
Kaikilla samantyyppisen funktio-osoittimen kautta kutsutuilla funktioilla
täytyy olla sama määrä samantyyppisiä parametreja.
Kaikki tämä on kuitenkin toteutettu pohjakoodiin, joten asiasta ei
tarvitse huolehtia.
Tehtävän tekeminen ei siis vaadi funktio-osoittimien osaamista.
Vihjeitä¶
- Aloita tutustumalla valmiiseen koodiin.
Annettua koodia ei kuitenkaan tarvitse ymmärtää perin pohjin.
Ei haittaa, vaikka et ymmärtäisi luokan
Cli
koodia. Muista luokista kannattaa tutkia, mitä metodeja ne tarjoavat (julkiset metodit) ja mitä attribuutteja niillä on. Tutustu metodien toteutusten yksityiskohtiin vasta, jos/kun huomaat tarvitsevasi kyseisten yksityiskohtien tuntemusta. Useimmissa tapauksissa riittää, että päättelet metodin tekemän toiminnon sen nimestä. - Ennen ohjelman toteuttamista, mieti huolellisesti, miten rakennat ohjelman niin, että pystyt vastaamaan annettuihin vaatimuksiin.
- Tässä projektissa pääpaino on modulaarisuudella sekä osoittimilla.
Joudut kuitenkin lisäämään pari STL-säiliötä, mutta niiden valinnan
ei pitäisi tuottaa hankaluuksia enää tässä vaiheessa.
- Mikä olisi sopiva säiliö sairaalan hoitojaksoille, kun hoitojaksot halutaan käydä läpi lisäysjärjestyksessä?
- Mikä olisi sopiva säiliö hoitojakson henkilökunnalle, kun henkilökunnan jäsenet halutaan tulostaa aakkosjärjestyksessä?
- Huomaa, että luokan sisäiset
const
-funktiot eivät voi kutsua funktioita, joista puuttuu määreconst
. Sananconst
puuttuminen aiheuttaa kääntäjässä[-fpermissive]
-virheen. Eli funktio, jota on kielletty muuttamasta olion tilaa, ei saa kutsua funktioita, jotka voivat muokata olion tilaa. - Muista, että oletuksena ohjelma käännetään build-hakemistoon. Testaamista varten kannattaa siirtää mahdolliset syötetiedostot tähän samaan hakemistoon.
Ohjelman toteuttaminen osissa¶
Tässä vaiheessa kurssia pitäisi jo olla muodostunut riittävän hyvä käsitys siitä, millaisissa osissa ohjelmia kannattaa toteuttaa ja millaisia committeja kannattaa tehdä.
Erityisvaatimukset¶
Seuraavia vaatimuksia on noudatettava, mikäli haluaa työstä hyväksytyn arvosanan:
- Ohjelmassa pitää käyttää dynaamista muistinhallintaa, mutta siinä ei saa olla muistinhallintaan liittyviä virheitä. Kannattaa siis suorittaa valgrind. Osoittimina voit käyttää joko tavallisia osoittimia tai älykkäitä osoittimia tai molempia.
- Vain STL-kirjaston säiliöt sallitaan, ei esim. Boost-kirjaston.
Arviointi¶
Jotta työ päätyisi assistenttien arvioitavaksi, sen pitää ensin läpäistä automaattitestit. Jos saat automaattitesteistä 0 pistettä, myös lopullinen pistemääräsi on 0, eikä työ mene assistenttien arvioitavaksi.
Assistentti arvioi ja pisteyttää automaattitestit läpäisseistä (= 1 p) sekä tehtävänannon erikoisvaatimukset täyttävistä töistä viimeisen määräajan puitteissa tehdyn commitin seuraavien arviointikriteerien mukaan:
- Ratkaisun yleisperiaate: 0-40 pistettä:
- Tehtävän osaamistavoitteet on saavutettu.
- Ohjelmakoodi on jaettu funktioita, luokkia ja/tai metodeita käyttäen loogisiksi kokonaisuuksiksi, jotka ovat sopivan pituisia.
- Jos luokkia ja olioita on käytetty, ne on toteutettu olio-ohjelmoinnin periaatteita noudattaen (ks. 4-kierroksen Tyyliseikoista kohta Olio-ohjelmointi).
- Tietorakenne ei sisällä toisteista eikä turhaa tietoa. Valittuja tietorakenteita on käytetty järkevästi.
- Ohjelmakoodi ei sisällä turhaa toisteisuutta eikä muutakaan turhaa.
- Ohjelmakoodi ei sisällä tarpeettomia rajoitteita tai oletuksia tai muita väkinäisiä ratkaisuita.
- Ohjelmarakenteet on toteutettu helposti ymmärrettäviksi.
- Ohjelmakoodissa ei ole käytetty globaaleja muuttujia (globaalit
const
-vakiot ovat OK). - Ohjelman toimintaa ei lopeteta
exit
-funktiota käyttäen. - Ohjelmassa ei ole muistinhallintaan liittyviä virheitä (suorita valgrind, ja huomaa, että kohtaa 10.1 on päivitetty).
- Ohjelmointityyli: -20-0 pistettä:
- Muuttujat ja funktiot nimetty selkeästi ja kuvaavasti.
- Ohjelmassa on käytetty nimettyjä vakioita taikanumeroiden sijasta.
- Ohjelmakoodi on asemoitu siististi.
- Koodirivien pituus on enintään 80 merkkiä.
- Jokaisen itse kirjoittamasi/editoimasi tiedoston alussa on kommentti, josta käy ilmi tiedoston tarkoitus, nimesi, opiskelijanumerosi ja muut tarvittavat tiedot. (Tarvittaessa katso mallia ensimmäisen projektin tehtävänannosta.)
- Jokaisen funktion/metodin alussa (otsikkotiedostossa jos mahdollista) on kommentti, joka kuvaa sen toiminnan, paluuarvon ja parametrit.
- Kommentteja on muutenkin tarpeellisissa kohdissa.
- Kaikki muuttujat on alustettu.
- Kääntäjä ei anna koodia käännettäessä varoituksia.
- Versionhallinnan käyttö: 0-10 pistettä:
- Committeja on riittävä määrä.
- Commit-viestien sisältö on selkeä ja kuvaava.
Huomaa yllä olevasta listasta, että tässä vaiheessa tyyliseikkojen oletetaan olevan opiskelijoilla hallussa. Enää et siis saa pisteitä tyylisääntöjen noudattamisesta, vaan niiden käyttämättä jättämisestä sakotetaan. Kannattaa siis tarkistaa, mitä tyyliasioista on kerrottu materiaalin kierroksilla 4 ja 11.
Huomautus
Viimeisen palautuksen tehtyäsi tarkasta TTY:n GitLabin web-käyttöliittymän kautta, että muutokset ovat menneet perille keskustietovarastoosi. Assistentti arvioi sen version ohjelmastasi, joka keskustietovarastosta löytyy viimeisestä eräpäivään mennessä tehdystä commitista.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.