Simulacija epidemije

Predstavljajmo si, da nekje na svetu izbruhne neka bolezen, recimo kak virus, in se razširi v pandemijo. Sestavili bomo simulator širjenja.

Oddajte le eno datoteko z vsem, kar ste izdelali in ne ločenih programov za vsako oceno. Potrebovali boste novejšo različico modula risar. Modula risar ni potrebno oddajati, ga imamo, hvala.

Testov tokrat ni, ker je tole težko avtomatsko testirati. Namesto njih pa dobite program, ki kliče vaše funkcije. Za simulacijo uporabljajte točno ta program. Tega programa ne spreminjajte, niti ne pišite svojih delov simulacije. Pišite le razrede in metode, kot jih zahteva naloga.

Ocena 6

Sestavi razred Oseba. Oseba hodi po svetu. Predstavljena je s krogcem bele barve (vsaj v začetku).

Razred Oseba naj ima

  • konstruktor, ki pripravi vse potrebno;
  • metodo premik(self), ki osebo premakne. Oseba ima določeno hitrost in smer. Hitrost je naključno, ne nujno celo število med 0 in 5, ki ga v začetku izbere konstruktor in ki se ne spreminja. Smer je v začetku naključna in se v vsakem koraku spremeni za naključen kot iz intervala [-20, 20]. Poleg tega se oseba, ki se zaleti v rob okna, odbije tako, kot so vas učili pri fiziki.

    Vse hitrosti in smeri morajo biti enako verjetne. Če v začetku izžrebate dve naključni števili, ki bosta predstavljali korake v smeri x in y, bodo nekatere hitrosti verjetnejše. Tudi naključno obračanje za +-20 stopinj boste težko naredili. Ubogajte in določite hitrost in smer, ne velikosti premikov po komponentah.

    Nujno poskrbite tudi, da bo takrat, ko se oseba zaleti v rob, odbojni koti enaki vpadnemu. Razmislite, kako. Od malo geometrije in risanja ni še nihče umrl.

    (Za pomoč: Oseba prileti pod kotom α (torej: to je njena smer premikanja). Zanima nas smer premikanja po odboju, α'. Vidimo (z nekim izrekom v zvezi s premico, ki seka vzporedne premice, pa lahko tudi dokažemo), da je kot, ki sem ga označil z β enak kotu α. Fiziki temu rečejo vpadni kot in ta je enak odbojnemu, v katerega sem prav tako napisal β. Če vemo kakšen je (zgornji) β (namreč enak kot α), pa znamo izračunati α'.

    To je ena situacija. Na podoben način poglejte še odboj od leve stene (stvar bo zelo podobna), potem pa še od zgornje in od spodnje. Odboj od zgornje in spodnje je pravzaprav bistveno enostavnejši od leve in desne, biti pa morate pozorni na to: kote merimo v smeri, nasprotni smeri urinega kazalca. Če gre kakšen kot v drugo smer, pa mu preprosto dodamo minus. Prav to sem pri gornji obravnavi odboja od desne stene nekoliko, a neškodljivo, kršil.)

Ko je metoda napisana, poženi program; ta bo sestavil sto oseb in klical metodo premik. Rezultat mora izgledati tako.

Ocena 7

Dodaj metodi:

  • okuzi_se(self), ki spremeni osebi krog v rdečo barvo. (Če je self.krog objekt, ki predstavlja nek krog, ki smo ga narisali z risar-jem, mu barvo spremenimo z risar.spremeni_barvo(self.krog, risar.rdeca)) in zabeleži, da je oseba okužena.
  • okuzi_bliznje(self, osebe), ki prejme seznam vseh oseb. V njem mora poiskati vse osebe, ki se dotikajo self-a (ali pa celo sekajo z njim) in jih okužiti tako, da pokliče njihovo (ne svoje!) metodo okuzi_se.

    Kako izračunati razdaljo med krogoma, si se učil(a) pri matematiki, pa tudi pri neki nalogi z vaj si se dotaknil tega vprašanja.

Metode okuzi_bliznje ne kliči sam. Pač pa poženi program. Ta bo v začetku okužil določeno število oseb, potem pa izvajal sumulacijo. Rezultat zdaj izgleda tako:

Ocena 8

Dodaj metodo

  • zdravi_se. Če je oseba bolna, ozdravi po tem, ko 150-krat pokličemo to metodo. Taka oseba je potem imuna na prihodnje okužbe, kar pokažemo tako, da jo pobarvamo z zeleno barvo.

Metodo okuzi_se dopolni tako, da

  • bo dodala potreben podatek, ki ga za svoje delovanje potrebuje metoda zdravi_se,
  • bo pazila, da oseba, ki že je bolna, ne more že v času svoje bolezni ponovno zboleti (saj je že bolna!) in na ta način podaljšati časa do ozdravitve,
  • se osebe, ki so prebolele bolezen, ne morejo več okužiti.

Če je vse narejeno pravilno, je simulacija videti tako kot v videu.

Ocena 9

  • Dodaj metodo vrni_krog, ki vrne krog, ki predstavlja osebo. To bo verjetno kar self.krog.
  • Dodaj metodo v_izolacijo, ki da osebo v izolacijo. To pokaže tako, da ga obarva rumeno (risar.zapolni). Če uporabiš novega risarja, bo program, ki je priložen nalogi, poskrbel, da se bo ta metoda poklicala ob kliku na posamezno osebo.

    Izolirana oseba se neha premikati. Konkretneje: če je oseba v izolaciji, se v naslednjih stotih klicih metode premik ne zgodi nič. Po stotih klicih te metode, oseba ni več v izolaciji, ni več rumena in se premika naprej.

  • Dodaj metodo je_izolirana, ki vrne True, če je oseba v izolaciji in False, če ni.

  • Metodi premik dodaj argument osebe, ki vsebuje seznam vseh oseb. Metodo premik potem spremeni tako, da se bodo vse osebe ob premikih izogibale izoliranih oseb. Konkretno: če bi se oseba ob nekem načrtovanem premiku približala katerikoli izolirani osebi na razdaljo manjšo od 20, se njena smer obrne za 180 stopinj, v tistem koraku (= v tem klicu funkcije premik) pa ne opravi premika. To funkcionalnost temeljito preskusi: ker se osebe premikajo kar hitro, si za izolacijo izbiraj takšne, ki so počasne. Ko daš nekoga v izolacijo, se mu nihče ne sme več približati (razen, če je že z njim).

    Da si ne zapletemo preveč življenja, je dovoljeno, da se osebe v bližini izoliranih oseb nekoliko zataknejo (sicer bi morali programirati "bežanje", kar bi bilo predvsem v primeru več izoliranih oseb lahko zoprno).

    Istočasno je lahko v izolaciji tudi večje število oseb.

Ocena 10

Napiši razred NIJZ z naslednjimi metodami.

  • Konstruktor počne, kar je treba,
  • sporoci_okuzbo() zabeleži, da se je okužila nova oseba,
  • sporoci_ozdravitev() zabeleži, da je nekdo ozdravel,
  • porocaj() se pokliče, ko je konec dneva. Metoda dopolni graf na dnu slike (glej posnetek!) s podatki za minuli dan. Pri tem zelena črta predstavlja skupno število doslej ozdravelih, rdeča črta pa predstavlja število trenutno bolnih.

Ker je NIJZ le eden, pripravi kar globalno spremenljivko nijz. Konkretno, tvoj program naj vsebuje še vrstico

nijz = NIJZ()

Nato dopolni ustrezne metode razreda Oseba tako, da bodo v pravih trenutkih poklicale nijz.sporoci_okuzbo() in nijz.sporoci_ozdravitev(). Metode porocaj() pa ne kliči sam, temveč ga kliče priloženi program, ki vodi simulacijo.

Razred NIJZ nima dostopa do celotnega seznama oseb in za ta dostop tudi ne išči bližnjic. (Torej: upri se skušnjavi, da bi toliko časa mučil risarja, da ti izda, koliko je krogcev katere barve!) Razred dobiva vse podatke prek metod sporoci_okuzbo in sporoci_ozdravitev.

Za lastno veselje

Igraj se s simulatorjem. Kaj se zgodi pri različnih gostotah prebivalstva? Tule imamo enake hitrosti premikanje in čase, ko je nekdo bolan, spreminja se le število ljudi, ki živijo na enako velikem področju. (Če vas video dolgočasi, ga pospešite, vendar glejte do konca, saj je fascinantno.)

Kaj pa, če je gostota konstantna (npr. 100) in spreminjamo hitrost gibanja? Ali pa število teh, ki se gibajo, ostali pa so doma, vendar jih lahko ti, ki se gibajo, obiščejo? In tako naprej ...

Simulator