Il sistema è suddiviso in quattro moduli principali:
Le tecnologie utilizzate, oltre a quelle obbligatorie, sono:
Il sistema é sviluppato come un sistema di simulazione a eventi dove ogni evento rappresenta un cambiamento dello stato della simulazione. É strutturato in diverse parti:
SimulationEngine rappresenta la parte centrale del sistema: ha il puro compito di eseguire uno step della simulazione e internamente mantiene lo stato della simulazione in modo immutabile, aggiornandolo ogni volta che viene eseguito uno step. Esegue in cascata tutti gli eventi, uno dopo l’altro, e alla fine ritorna il nuovo stato della simulazione. Non contiene logiche specifiche ma si limita a invocare gli eventi, rispettando un flusso di simulazione prestabilito. Questa impostazione riflette un’architettura event-driven, dove ogni evento è un’unità indipendente che incapsula una modifica ben definita sul sistema. Inoltre, questo approccio assicura un’alta coesione interna e una bassa dipendenza da altre parti del progetto, facilitando manutenzione, testing e riutilizzo.
Disease
rappresenta la malattia evolvibile dal giocatore durante la partita.
È principalmente composto da Trait
che ne determinano le caratteristiche.
I Trait
possono essere:
Transmissions
: modella come una malattia è in grado di trasmettersi e infettare la popolazioneSymptoms
: modella i sintomi della malattiaAbilities
: modella caratteristiche particolari come ad esempio la resistenza ai farmaci o a determinate condizioni climaticheÈ possibile aggiungere o rimuovere Trait
a Disease
:
EventBuffer
aggiunge un Event
al SimulationEngine
che richiede l’evoluzione o l’involuzione
di uno specifico Trait
selezionato nella pagina della malattiaEvent
determina casualmente se evolvere gratuitamente un nuovo Trait
tra quelli i Symptoms
evolvibili.Alcuni Trait
più avanzati richiedono l’acquisto di altri Trait
per essere evoluti. Per un
Symptom
basta che uno solo tra i suoi prerequisites
sia stato acquistato dal giocatore, mentre
per un Symptom
o un Transmission
tutti i prerequisites
devono essere evoluti.
Un Event
è adibito al calcolo tramite PopulationEffect
dei nuovi infetti e morti nei diversi Node
in base alle statistiche
dei Trait
presenti in Disease
.
Un Event
è adibito al calcolo dei punti dna, dipendenti dal numero di persone infettate e/o uccise
determinate da PopulationEffect
.
Durante la partita è possibile evolvere Trait
che alterano Cure
, modifiche sempre apportate tramite Event
o EventBuffer
.
Il sottosistema Mondo rappresenta la rete globale su cui si muove la popolazione e si diffonde la malattia. È composto da tre elementi principali:
Quando si applica una strategia di movimento, viene determinato non solo quante persone si spostano, ma anche quanti tra questi sono infetti, così da mantenere una propagazione realistica dell’infezione durante i trasferimenti.
Il sottosistema di ricerca della cura modella gli sforzi scientifici globali per sviluppare un rimedio alla malattia. È composto da due elementi chiave:
Il sistema di cura interagisce con:
Il sottosistema delle reazioni modella le risposte del mondo di gioco alla malattia e/o alla cura. Si basa su un meccanismo di regole condizionali associate ad azioni specifiche:
Le reazioni possono essere di vario tipo e comportano una modifica allo stato del mondo, come ad esempio la chiusura di collegamenti tra nodi, impedendo la diffusione della malattia.
La simulazione viene inizializzata e avviata tramite dsl con il comando setup
fornendo i seguenti elementi:
SimulationState
Disease
Cure
World
InfectionLogic
DeathLogic
Reactions
Time
Condizioni di fine simulazione
Scheduler
UpdatableView
ExecutionMode
Quando viene avviata l’applicazione, viene chiesto al giocatore di selezionare il Node
da dove vuole fare iniziare la sua Disease
.
Dopo la selezione, questa informazione viene passata al SimulationState
tramite dsl.
Il Controller
esegue ricorsivamente la catena di Event
dichiarati all’interno del SimulationEngine
su un thread separato
finché la simulazione non termina raggiungendo le condizioni di fine simulazione. Durante il loop, una volta che
tutti gli eventi sono stati eseguiti, il Controller
si occupa anche di richiamare l’aggiornamento della UpdatableView
passando il nuovo stato della simulazione, ottenuto dopo l’esecuzione della catena di eventi.
Il collegamento tra il Model e la View avviene durante il setup della simulazione: la DSL contiene la keyword binding
alla quale bisogna passare un oggetto che implementa l’interfaccia UpdatableView
e che contenga tutte le parti di view che si vogliono aggiornare.
Questo design si ispira al pattern Observer: la subscribe é mascherata dalla keyword binding
e il notify
é lasciato alla responsabilità del Controller
che, una volta ottenuto il nuovo stato della simulazione,
lo passa all’oggetto che implementa l’interfaccia UpdatableView
chiamandone l’aggiornamento.
Il Controller
fa quindi come da collante tra il Model e la View, permettendo di mantenere separati i due moduli.