SimCity

Progetto di Programmazione di Febbraio 2014

Modalità di realizzazione e consegna

Il seguente progetto è destinato agli studenti che vogliano sostenere l'esame di Programmazione 2 nel mese di Febbraio. Va realizzato in gruppi di due o tre persone (eccezionalmente saranno ammessi gruppi di una sola persona, previa richiesta di autorizzazione). Se siete interessati a svolgerlo:

Dopo la data di consegna, verrà pubblicato l'elenco dei gruppi ammessi all'orale e verranno indicate le date in cui gli orali avranno luogo.

Introduzione

Dovete realizzare un insieme di classi per simulare gli spostamenti delle persone in un modello semplice ma preciso di città. Si richiede che il programma stampi, dato questo modello, una serie di proprietà statistiche, come ad esempio gli edifici più affollati e le strade più trafficate.

La città viene rappresentata come una serie di edifici e di strade. Una strada collega una coppia di edifici; esistono strade a senso unico e strade a doppio senso, che possono essere percorse indifferentemente in entrambi i sensi.

Le persone poste nella città così creata si muovono in base a regole probabilistiche basate sull'ora del giorno: ogni edificio deve avere infatti una probabilità in ingresso e una probabilità in uscita, entrambe dipendenti dall'ora del giorno e dal numero di persone già presenti nell'edificio. Una persona che si trovi in un certo edificio edificio in cui sono in tutto presenti x persone uscirà dall'edificio all'ora t: Math.random() < edificio.getExitingProbability(t,x)

Se questo viene valutato a false, la persona resterà nell'edificio fino all'ora successiva, e ripeterà il controllo. Se questo viene invece valutato a true, la persona uscirà dall'edificio e dovrà controllare tutte le strade che partono dall'edificio edificio valutando, per ognuna, la probabilità di ingresso nell'edificio che si trova dall'altro lato della strada; in altre parole, dovrà controllare se Math.random() < altroEdificio.getEnteringProbability(t,y) dove y è il numero di persone presenti in altroEdificio.

In caso affermativo, la persona si sposterà nell'altro edificio (percorrendo quindi la strada che li collega). Altrimenti, verrà presa in esame un'altra strada, e così via. Se nessuno dei tentativi ha dato un esito positivo, la persona resterà nell'edificio di partenza per un'altra ora.

Per aiutarvi a scrivere tutto questo, nel paragrafo ArrayList si spiegherà come usare le ArrayList, che possono rendere più semplice il progetto. Nel paragrafo Classi verranno forniti tutti i dettagli delle classi richieste. Nel paragrafo Caratteristiche aggiuntive verranno esposte delle ulteriori funzionalità che potete implementare, se volete, in un secondo momento. Infine, nel paragrafo Esempio di esecuzione riportiamo un esempio possibile del main e dell'output ottenuto.

Il progetto verrò valutato non solo in base al suo corretto funzionamento, ma anche in base alla pulizia del codice ed alla sua documentazione (si consiglia di scrivere i commenti javadoc e di commentare il codice).

ArrayList

Le ArrayList (nel pacchetto java.util) servono a rappresentare delle liste di oggetti il cui numero non è noto in partenza. Sono quindi simili agli array, ma più flessibili. In particolare, può tornarvi utile creare una ArrayList di Strade e una ArrayList di Edifici. Ecco alcuni esempi d'uso:

Per confronto, vediamo come le stesse operazioni vengono fatte sugli array:

Se preferite, nulla vi vieta di usare gli array Edificio[] o Strada[] laddove il progetto richiede una ArrayList<Edificio> o ArrayList<Strada>. Questo però potrebbe rendervi il tutto molto più complicato.

Classi e interfacce

Descriviamo ora nei dettagli come realizzare le classi necessarie al progetto. Se lo ritenete, potete apportare cambiamenti alle segnature dei metodi proposti ed anche -- a vostro rischio e pericolo -- alla struttura delle Classi; ovviamente, rimanendo all'interno dei requisiti esposti nel paragrafo introduttivo.

N.B.: Oltre ai metodi qui indicati, ricordatevi di aggiungere ad ogni classe un metodo toString() valido.

Interfaccia Edificio

Rappresenta uno degli edifici della città. Sotto forniamo alcuni esempi di classi che implementano questa interfaccia.

Classe Strada

Ad ogni strada sono associate due estremità (i due edifici che la strada collega bidirezionalmente) e un intero (il numero di persone che sono fino ad ora transitate lungo quella strada).

Classe Citta

Una città è un insieme di edifici e di strade. Inoltre contiene dentro di sé un orario (segnato dalla torre dell'orologio): alla creazione tale orario è 0 (mezzanotte), e viene incrementato ogni volta che viene chiamato il metodo passaOra().

Classe Persona

Una persona è caratterizzata da un nome, da una città in cui vive, da un edificio in cui si trova inizialmente.

Classe Simulazione

Si tratta di una classe che permette di simulare gli spostamenti di un certo numero di persone in una città.

Classi degli edifici

PostoDiLavoro

Rappresenta un edificio in cui possono lavorare delle persone. Quando viene creato gli viene assegnato un nome, un orario di inizio dell'attività (per esempio, 8), un orario di fine dell'attività (per esempio, 18) e un'importanza (un valore fra 0 e 1). La probabilità di entrata è pari all'importanza durante l'orario di lavoro, ed è 0 altrimenti. La probabilità di uscita è 0 durante l'orario di lavoro e 1 fuori da tale orario.

Case

Questa classe rappresenta il "quartiere residenziale" della città, ovvero dove abitano i suoi abitanti. La probabilità di ingresso è 0.05 fra le 8:00 e le 18:00, ed è 0.90 altrimenti. La probabilità di uscita è 0 nelle ore notturne e 0.90 nelle ore diurne (vedi metodo isOraDiurna di Citta). Notate che si assume che esista una sola istanza di questa classe, che rappresenta l'intero insieme delle case esistenti nella città.

SedeAttivita

Questa è una classe astratta che rappresenta le sedi di attività pubbliche. Una SedeAttivita è caratterizzata da un nome e da un'importanza (un valore fra 0 e 1). Ogni sottoclasse concreta fornisce un metodo * abstract boolean isAperta(int ora) che dice se quell'attività è aperta a una data ora. La probabilità di ingresso è 0 quando l'attività non è aperta, ed è pari all'importanza quando è aperta. La probabilità di uscita è 1 quando l'attività non è aperta, ed è 0.3 quando è aperta.

DiscoClub, CentroCommerciale, Pub

Sono tutte sottoclassi concrete di SedeAttivita, ognuna delle quali fornisce un'opportuna implementazione del metodo isAperta.

Scuola

Questa è una classe di edifici con una probabilità di ingresso pari a 0.3 dalle 8:00 alle 13:00, e 0 fuori da questi orari. La probabilità di uscita è 0 dalle 8:00 alle 13:00, e 1 fuori da questi orari.

Ospedale

Questa è una classe di edifici con una probabilità di ingresso pari a 0.05 nelle ore diurne, e 0.01 nelle ore notturne. La probabilità di uscita è 0.9 a qualunque ora.

Caratteristiche aggiuntive

Arricchite il vostro progetto aggiungendo altre funzionalità (seguono alcuni esempi). Per ogni funzionalità aggiuntiva fate in modo di fornire un'adeguata documentazione (vedi quanto detto sopra nelle modalità di consegna).

  1. Fate in modo che l'utente non possa creare più di un'edificio Case nella stessa città.
  2. Provate a arricchire l'insieme delle statistiche che vengono prodotte durante la simulazione. Alcuni esempi potrebbero essere: il numero di edifici visitati da ogni persona, il tempo medio speso in ciascun edificio, il numero di volte in cui ogni persona ha tentato di uscire dall'edificio in cui si trova senza riuscirci.

Esempio di esecuzione

Main

    Citta citta = new Citta();

    // crea la citta'
    Edificio casa = new Case();
    citta.addEdificio(new Ospedale());
    citta.addEdificio(new PostoDiLavoro("Software House Ltd.",  0.5));
    citta.addEdificio(new PostoDiLavoro("Buy'N'Large Corp.", 0.9));
    citta.addEdificio(casa);
    citta.addEdificio(new Scuola("Liceo Scientifico"));
    citta.addEdificio(new Scuola("Medie"));
    citta.addEdificio(new Scuola("Istituto Tecnico"));
    citta.addEdificio(new Pub());
    citta.addEdificio(new CentroCommerciale());
    citta.addEdificio(new Discoclub());

    // crea le strade
    for (Edificio a : citta.getEdifici())
        for (Edificio b : citta.getEdifici())
            if (!a.equals(b))
                if (!(a instanceof PostoDiLavoro && b instanceof PostoDiLavoro))
                    citta.creaStrada(a, b);

    // esegue la simulazione
    Simulazione sim = new Simulazione(citta, 100, 96, casa);
    sim.run();

    // stampa i dati
    sim.printStatisticheLuoghi();
    sim.printTrafficoStrade(50);
    Strada piuTrafficata = sim.trovaStradaPiuTrafficata();
    System.out.println("La strada piu' trafficata e' " + piuTrafficata + " (" + piuTrafficata.getNumeroPedaggi() + " pedaggi)");

Standard Output

===============ESECUZIONE=================
0:00 (giorno 0)...
1:00 (giorno 0)...
2:00 (giorno 0)...

[…]

=====LUOGHI PIU' AFFOLLATI ORA PER ORA=====
0:00 (giorno 0)-> Case (100)
1:00 (giorno 0)-> Case (100)
2:00 (giorno 0)-> Case (100)
3:00 (giorno 0)-> Case (100)
4:00 (giorno 0)-> Case (100)
5:00 (giorno 0)-> Case (100)
6:00 (giorno 0)-> Case (100)
7:00 (giorno 0)-> Case (92)
8:00 (giorno 0)-> Case (79)
9:00 (giorno 0)-> Buy'N'Large Corp. (30)
10:00 (giorno 0)-> Buy'N'Large Corp. (31)
11:00 (giorno 0)-> Buy'N'Large Corp. (32)
12:00 (giorno 0)-> Buy'N'Large Corp. (32)
13:00 (giorno 0)-> Buy'N'Large Corp. (65)
14:00 (giorno 0)-> Buy'N'Large Corp. (65)
15:00 (giorno 0)-> Buy'N'Large Corp. (65)
16:00 (giorno 0)-> Buy'N'Large Corp. (65)
17:00 (giorno 0)-> Buy'N'Large Corp. (65)
18:00 (giorno 0)-> Case (93)
19:00 (giorno 0)-> Case (87)
20:00 (giorno 0)-> Case (83)
21:00 (giorno 0)-> Case (78)
22:00 (giorno 0)-> Case (74)
23:00 (giorno 0)-> Case (77)
0:00 (giorno 1)-> Case (81)
1:00 (giorno 1)-> Case (96)

[…]

============= TRAFFICO STRADE =============
Strada<Software House Ltd.,Case> -> 87 pedaggi
Strada<Buy'N'Large Corp.,Case> -> 202 pedaggi
Strada<Case,Software House Ltd.> -> 95 pedaggi
Strada<Case,Buy'N'Large Corp.> -> 194 pedaggi
Strada<Case,Pub> -> 154 pedaggi
Strada<Pub,Case> -> 135 pedaggi
===========================================
La strada piu' trafficata e' Strada<Buy'N'Large Corp.,Case> (202 pedaggi)