diff --git a/README.md b/README.md
index 2425dc5fd000494daff5259bab6bbd5783e10798..2f6f39e7f87ba1ed3cb696fb181d9404cdac72fd 100644
--- a/README.md
+++ b/README.md
@@ -1,92 +1,156 @@
-# bagnini con prof
+# CORSO INGEGNERIA DEL SOFTWARE A.A. 2022/23
 
+# Esame del 6 luglio 2023
 
+* `<Cognome> <Nome> <matricola>`
 
-## Getting started
+Dopo avere effettuato il **fork** su `gitlab.di.unimi.it` e il **clone** in
+locale, modificate questo README
+inserendo i vostri dati seguendo lo schema sopra riportato.
+Concedete quindi i permessi di lettura (livello **reporter**) al vostro progetto su gitlab ai
+docenti (`carlo.bellettini` e `mattia.monga`).
 
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+## Processo
 
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
+Il progetto va implementato secondo la *metodologia TDD*, utilizzando `git flow`, quindi occorre iniziare con un `git flow init`.
+Poi ripetere i passi seguenti fino ad aver implementato tutte le funzionalità richieste:
 
-## Add your files
+* creare un nuovo *branch* per la funzionalità corrente attraverso l'esecuzione del comando `git flow feature start`,
+* implementare un test per le funzionalità volute;
+* verificare che **il codice compili correttamente**, ma l'**esecuzione del test fallisca**;
+  solo a questo punto effettuare un *commit* iniziando il messaggio di commit con la stringa `ROSSO:`,
+* aggiungere la minima implementazione necessaria a realizzare la funzionalità, in modo che **il
+  test esegua con successo**; solo a questo punto
+  effettua un *commit* iniziando il messaggio di commit con la stringa `VERDE:`,
+* procedere, se necessario, al **refactoring** del codice, accertandosi che le modifiche non
+  comportino il fallimento di alcun test; solo in questo caso fa seguire a ogni
+  passo un *commit* iniziando il messaggio di commit con la stringa `REFACTORING:`,
+* eseguire il *merge* del *branch* per la funzionalità sviluppata all'interno del *branch develop*
+  attraverso il comando `git flow feature finish`,
+* **solo in fase di rilascio**, esegue una *release* all'interno del *branch master* attraverso il comando `git flow release start` e successivamente `git flow release finish`,
+* effettua un *push* (di tutti i *branch*) con `git push origin --all` e poi `git push origin --tags`.
 
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+# SAPORE DI SALE
 
-```
-cd existing_repo
-git remote add origin https://gitlab.di.unimi.it/francesco.fontana4/bagnini-con-prof.git
-git branch -M main
-git push -uf origin main
-```
+Obiettivo dell'esercizio è progettare e realizzare un insieme di classi atte a
+produrre un programma Java che per la gestione di una spiaggia con zone
+presidiate da bagnini.
 
-## Integrate with your tools
+Ogni bagnino segnala la propria presenza nella zona di competenza: ciò avviene
+inviando un messaggio all'arrivo e all'abbandono della zona. Durante la
+permanenza il bagnino può inviare messaggi che informano sullo stato della
+balneabilità, indicando il colore convenzionale della bandiera corrispondente:
+ROSSA (pericolo elevato), GIALLA (rischio medio, solo nuotatori esperti), VERDE
+(nuoto sicuro), VIOLA (presenza di meduse).
 
-- [ ] [Set up project integrations](https://gitlab.di.unimi.it/francesco.fontana4/bagnini-con-prof/-/settings/integrations)
+- All'arrivo il bagnino indica il proprio nome cioè una stringa alfabetica:
+  -  UNIVOCA (cioè non ci possono essere due bagnini attivi con lo stesso nome) 
+  -  NON VUOTA
+  -  di non più di 30 caratteri;
+- La segnalazione di abbandono della postazione non prevede indicazioni nel campo di testo e chiaramente ha successo solo se la postazione era presidiata ;
+- Le segnalazioni sullo stato di balneabilità 
+  sono permesse solo dopo una segnalazione di arrivo e consistono nella indicazione del colore della bandiera esposta;
+  - I colori della bandiera devono essere indicati esclusivamente con le stringhe
+    dell'insieme ROSSA, GIALLA, VERDE, VIOLA.
 
-## Collaborate with your team
 
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
+Nell'esempio ci sono 4 zone di presidio con i bottoni per svolgere le operazioni sopra indicate
+e 2 display.
+Quello a sinistra indica lo
+stato della 4 zone della nostra spiaggia, mentre quello a destra la postazione in cui si trovano i agnini attivi. 
 
-## Test and Deploy
+In particolare nella vista display a sinistra per ogni zona/postazione verrà scritto a secondo del caso:
+- **postazione non presidiata**
+- **\[**  _numpostazione_ **\]** _nome bagnino_  **segnala**  _messaggio di stato dipendente dall'ultima bandiera segnalata_
 
-Use the built-in continuous integration in GitLab.
+ad esempio: [2] Carlo segnala presenza di meduse
 
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
 
-***
+Nella vista display a destra verrà invece scritto per ogni bagnino attivo (e in ordine alfabetico:
+- _nome bagnino_  **è alla postazione**  _numero postazione_
 
-# Editing this README
 
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
 
-## Suggestions for a good README
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
+## TRACCIA
 
-## Name
-Choose a self-explaining name for your project.
+Completare, in modo da realizzare un'organizzazione del sistema di tipo
+*Model-View-Presenter*.
 
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
 
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
 
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
+Vi vengono fornite già due classi *Viste* del sistema:
 
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
+- `PostazioneView`: la vista che permette (vedi metodo `addHandlers`) di:
+  - Comunicare arrivo di un bagnino in una zona;
+  - Comunicare abbandono di un bagnino da una zona;
+  - Comunicare il colore della bandiera scelto dal bagnino per una zona;
+- `DisplayView`: un display generale che permette di visualizzare alcune righe
+  di testo e può essere usato per visualizzare sia la situazione delle zone, che la posizione dei bagnini.
 
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
 
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
+Viene fornita anche una prima versione della classe `Main`, e una classe (`GUITest`) contenente solo alcuni test d'integrazione/validazione.
 
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
+**TUTTE LE CLASSI DATE POSSONO ESSERE MODIFICATE (CANCELLATE, COMPLETATE) PER
+ADERIRE A DIFFERENTI IDEE DI
+PROGETTAZIONE**
 
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
+Lanciando il codice attuale (tramite il task **run** di gradle) si ottiene inizialmente una
+interfaccia come quella nella figura sottostante.
 
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
+![start](img_0.png)
 
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
 
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
+Ad esempio partendo dalla seguente situazione iniziale
 
-## License
-For open source projects, say how it is licensed.
+![start](img_1.png)
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
+la sequenza di operazioni (con l'ultima che causerà errore):
+- Arrivo alla postazione 1 del bagnino "Mario"
+- che segnala la bandiera ROSSA;
+- Arrivo alla postazione 0 del bagnino "Luigi"
+- che segnala la bandiera GIALLA;
+- Arrivo alla postazione 3 del bagnino "Giovanni"
+- che segnala la bandiera GRIGIA;
+
+porterebbe alla  situazione:
+
+![start](img_2.png)
+
+
+### Suggerimenti
+
+Oltre all'uso del pattern _Model-View-Presenter_, vi consigliamo di considerare
+lo sfruttamento
+al fine di scrivere un codice migliore anche di altri pattern (ad es. il pattern
+_Strategy_, o il pattern _Template_) e in
+ogni caso di prestare grande attenzione al rispetto dei principi **SOLID** di
+buona progettazione Object Oriented.
+
+Prestare estrema attenzione anche a garantire una corretta encapsulation dello
+stato da parte delle varie classi (ad
+esempio del Model) in modo da garantire l'assenza di **escaping references**  anche di
+solo parte dello stato.
+
+### Testing
+
+Mano a mano che si sviluppa il progetto, si deve controllare di mantenere una
+copertura, sia dei comandi che delle
+decisioni, soddisfacente (se inferiore al 100% inserire un commento che spieghi
+perché non è possibile raggiungerlo).
+
+Sono presenti anche alcuni test di integrazione.
+Vi dovrebbero essere di aiuto anche per capire cosa serve fare (cioè come
+specifiche).
+
+Può essere utile oltre ai test di unità che scrivete durante il TDD prevedere di aggiungere anche qualche test di
+integrazione per verificare che il sistema funzioni correttamente anche facendo interagire le diverse classi reali.
+
+### Consegna
+
+Al termine del laboratorio dovete impacchettare l'ultima versione stabile (non ci possono essere test di unità che
+falliscono) a cui siete arrivati come una _release_ di gitflow chiamata
+"consegna" ed effettuare un ultimo *push* anche di tutti i rami locali (comprese quindi eventuali feature aperte ma non
+completate e non presenti nella realease "consegna"):
+`git push origin --all` e poi `git push origin --tags`
+
+## **Verificate su `gitlab.di.unimi.it`** che ci sia la completa traccia dei *commit* effettuati e di averne dato visibilità ai docenti.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..f6354823603ecf66cb0fbd482b764a9295f195ed
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,48 @@
+plugins {
+    id 'java'
+    id 'application'
+    id 'org.openjfx.javafxplugin' version '0.0.13'
+    id "org.unbroken-dome.test-sets" version "4.0.0"
+}
+
+application.mainClass = 'it.unimi.di.sweng.esame.Main'
+
+javafx {
+    version = '17'
+    modules = [ 'javafx.controls']
+}
+
+
+repositories {
+    mavenCentral()
+}
+
+testSets {
+    integrationTest
+}
+
+dependencies {
+    implementation 'org.jetbrains:annotations:24.0.1'
+
+    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
+    testImplementation 'org.assertj:assertj-core:3.24.2'
+
+    testImplementation 'org.hamcrest:hamcrest-core:2.2'
+    testImplementation 'org.mockito:mockito-core:5.2.0'
+
+    integrationTestImplementation "org.testfx:testfx-junit5:4.0.16-alpha"
+    integrationTestImplementation 'org.testfx:testfx-core:4.0.16-alpha'
+}
+
+test {
+    useJUnitPlatform()
+}
+
+integrationTest {
+    useJUnitPlatform();
+}
+
+
+check.dependsOn integrationTest
+integrationTest.mustRunAfter test
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f398c33c4b08dabb3f1275e57706c2de4effb50c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
+networkTimeout=10000
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/img_0.png b/img_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..93b597372b103411e45b3dddce69725bf766b85f
Binary files /dev/null and b/img_0.png differ
diff --git a/img_1.png b/img_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..a6128a682ae4b93187e9284665ea5067676834a4
Binary files /dev/null and b/img_1.png differ
diff --git a/img_2.png b/img_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a9ec904f944609c26e31e75923a5f7b0785b209
Binary files /dev/null and b/img_2.png differ
diff --git a/src/integrationTest/java/it/unimi/di/sweng/esame/GUITest.java b/src/integrationTest/java/it/unimi/di/sweng/esame/GUITest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e23f961e283deb5ae6caf07cca3d26c64b2e7f8
--- /dev/null
+++ b/src/integrationTest/java/it/unimi/di/sweng/esame/GUITest.java
@@ -0,0 +1,202 @@
+package it.unimi.di.sweng.esame;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.matchesPattern;
+import static org.hamcrest.Matchers.startsWith;
+import static org.testfx.api.FxAssert.verifyThat;
+import static org.testfx.matcher.control.LabeledMatchers.hasText;
+
+import it.unimi.di.sweng.esame.views.DisplayView;
+import it.unimi.di.sweng.esame.views.PostazioneView;
+import javafx.collections.ObservableList;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.GridPane;
+import javafx.stage.Stage;
+import org.assertj.core.util.introspection.FieldSupport;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.testfx.api.FxRobot;
+import org.testfx.framework.junit5.ApplicationExtension;
+import org.testfx.framework.junit5.Start;
+
+@ExtendWith(ApplicationExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class GUITest {
+
+  private Label[] elencoPostazioni;
+  private Label[] elencoBagnini;
+  private final TextField[] inputMessage = new TextField[Main.NUMPOSTAZIONI];
+  private final Button[][] bottoni = new Button[Main.NUMPOSTAZIONI][];
+  private final Label[] errorMessage = new Label[Main.NUMPOSTAZIONI];
+  private final Label[] bagniniNomi = new Label[Main.NUMPOSTAZIONI];
+
+  @Start
+  public void start(Stage primaryStage) {
+    Main m = new Main();
+    m.start(primaryStage);
+
+    GridPane gp = (GridPane) primaryStage.getScene().getRoot();
+    ObservableList<Node> view = gp.getChildren();
+
+    PostazioneView[] postazioniView = new PostazioneView[Main.NUMPOSTAZIONI];
+    for (int i = 0; i < Main.NUMPOSTAZIONI; i++) {
+      postazioniView[i] = (PostazioneView) view.get(i);
+      bottoni[i] = FieldSupport.EXTRACTION.fieldValue("button", Button[].class, postazioniView[i]);
+      inputMessage[i] = FieldSupport.EXTRACTION.fieldValue("textField", TextField.class, postazioniView[i]);
+      errorMessage[i] = FieldSupport.EXTRACTION.fieldValue("error", Label.class, postazioniView[i]);
+      bagniniNomi[i] = FieldSupport.EXTRACTION.fieldValue("bagnino", Label.class, postazioniView[i]);
+    }
+
+    DisplayView leftView = (DisplayView) view.get(Main.NUMPOSTAZIONI);
+    DisplayView rightView = (DisplayView) view.get(Main.NUMPOSTAZIONI + 1);
+
+    elencoPostazioni = FieldSupport.EXTRACTION.fieldValue("rows", Label[].class, leftView);
+    elencoBagnini = FieldSupport.EXTRACTION.fieldValue("rows", Label[].class, rightView);
+  }
+
+  void selezioneContenutoCasellaTesto(FxRobot robot, TextField field) {
+    robot.doubleClickOn(field).clickOn(field); //triplo click per selezionare tutto
+  }
+
+  @Test
+  public void testArrivaOK(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Carlo");
+    robot.clickOn(bottoni[2][0]);
+    verifyThat(errorMessage[2], hasText(""));
+    verifyThat(elencoPostazioni[2], hasText("[2] Carlo segnala ancora nulla"));
+    verifyThat(elencoBagnini[0], hasText("Carlo è alla postazione 2"));
+    verifyThat(bagniniNomi[2] , hasText("Carlo"));
+  }
+
+  @Test
+  public void testArrivaNomeVuotoFail(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("");
+    robot.clickOn(bottoni[2][0]);
+    verifyThat(errorMessage[2], hasText("nome vuoto"));
+    verifyThat(elencoPostazioni[2], hasText("postazione non presidiata"));
+  }
+
+  @Test
+  public void testArrivaNomeLungoFail(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Nometroppolungomapropriopropriopriprio");
+    robot.clickOn(bottoni[2][0]);
+    verifyThat(errorMessage[2], hasText("nome troppo lungo"));
+    verifyThat(elencoPostazioni[2], hasText("postazione non presidiata"));
+  }
+
+
+  @Test
+  public void testVaViaNonpresenteFail(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("");
+    robot.clickOn(bottoni[2][2]);
+    verifyThat(errorMessage[2], hasText("Bagnino non presente"));
+    verifyThat(elencoPostazioni[2], hasText("postazione non presidiata"));
+  }
+
+  @Test
+  public void testSegnalaBandieraVuota(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[1]);
+    robot.write("");
+    robot.clickOn(bottoni[1][1]);
+    verifyThat(errorMessage[1], hasText("Indicare colore bandiera"));
+  }
+
+  @Test
+  public void testSegnalaBandieraSbagliata(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[1]);
+    robot.write("TURCHESE");
+    robot.clickOn(bottoni[1][1]);
+    verifyThat(errorMessage[1], hasText("Bandiera non valida"));
+  }
+
+  @Test
+  public void testSegnalaBandieraDaPostazioneVuota(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[1]);
+    robot.write("ROSSA");
+    robot.clickOn(bottoni[1][1]);
+    verifyThat(errorMessage[1], hasText("postazione non presidiata"));
+  }
+
+
+  @Test
+  public void testSegnalaBandieraOK(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Carlo");
+    robot.clickOn(bottoni[2][0]);
+
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("ROSSA");
+    robot.clickOn(bottoni[2][1]);
+    verifyThat(errorMessage[2], hasText(""));
+    verifyThat(elencoPostazioni[2], hasText("[2] Carlo segnala pericolo elevato"));
+
+  }
+
+
+  @Test
+  public void testArrivaBagninoFail(FxRobot robot) {
+
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Carlo");
+    robot.clickOn(bottoni[2][0]);
+
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Mattia");
+    robot.clickOn(bottoni[2][0]);
+
+    verifyThat(errorMessage[2], hasText("postazione già occupata"));
+  }
+
+  @Test
+  public void testArrivaBagninoFail2(FxRobot robot) {
+
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Carlo");
+    robot.clickOn(bottoni[2][0]);
+
+    selezioneContenutoCasellaTesto(robot, inputMessage[0]);
+    robot.write("Carlo");
+    robot.clickOn(bottoni[0][0]);
+
+    verifyThat(errorMessage[0], hasText("bagnino già presente in altra postazione"));
+  }
+
+  @Test
+  public void testOrdinamentoListaBagnini(FxRobot robot) {
+    selezioneContenutoCasellaTesto(robot, inputMessage[0]);
+    robot.write("Violetta");
+    selezioneContenutoCasellaTesto(robot, inputMessage[2]);
+    robot.write("Mattia");
+    selezioneContenutoCasellaTesto(robot, inputMessage[1]);
+    robot.write("Carlo");
+    selezioneContenutoCasellaTesto(robot, inputMessage[3]);
+    robot.write("Anna");
+
+    robot.clickOn(bottoni[2][0]);
+    robot.clickOn(bottoni[1][0]);
+    robot.clickOn(bottoni[3][0]);
+    robot.clickOn(bottoni[0][0]);
+
+    verifyThat(elencoBagnini[0], hasText("Anna è alla postazione 3"));
+    verifyThat(elencoBagnini[1], hasText(startsWith("Carlo è alla postazione 1")));
+    verifyThat(elencoBagnini[2], hasText(startsWith("Mattia è alla postazione 2")));
+    verifyThat(elencoBagnini[3], hasText(startsWith("Violetta è alla postazione 0")));
+
+    robot.clickOn(bottoni[1][2]);
+
+    verifyThat(elencoBagnini[0], hasText("Anna è alla postazione 3"));
+    verifyThat(elencoBagnini[1], hasText(startsWith("Mattia è alla postazione 2")));
+    verifyThat(elencoBagnini[2], hasText(startsWith("Violetta è alla postazione 0")));
+  }
+}
diff --git a/src/main/java/it/unimi/di/sweng/esame/Main.java b/src/main/java/it/unimi/di/sweng/esame/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..bac96d8e30be0382fc0a8c25ff2bd9b2ac7920da
--- /dev/null
+++ b/src/main/java/it/unimi/di/sweng/esame/Main.java
@@ -0,0 +1,62 @@
+package it.unimi.di.sweng.esame;
+
+
+import it.unimi.di.sweng.esame.views.DisplayView;
+import it.unimi.di.sweng.esame.views.PostazioneView;
+import javafx.application.Application;
+import javafx.geometry.Insets;
+import javafx.scene.Scene;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.layout.GridPane;
+import javafx.scene.paint.Color;
+import javafx.stage.Stage;
+
+
+
+public class Main extends Application {
+
+  public static final int NUMPOSTAZIONI = 4;
+
+  public static void main(String[] args) {
+    launch(args);
+  }
+
+  @Override
+  public void start(Stage primaryStage) {
+
+    primaryStage.setTitle("Baywatch");
+
+    PostazioneView[] postazioneView = new PostazioneView[NUMPOSTAZIONI];
+
+    for (int i = 0; i < NUMPOSTAZIONI; i++) {
+      postazioneView[i] = new PostazioneView();
+    }
+
+
+    DisplayView leftSideView = new DisplayView("Elenco postazioni", NUMPOSTAZIONI);
+    DisplayView rightSideView = new DisplayView("Elenco Bagnini", NUMPOSTAZIONI);
+
+    GridPane gridPane = new GridPane();
+    gridPane.setBackground(new Background(new BackgroundFill(Color.DARKOLIVEGREEN, CornerRadii.EMPTY, Insets.EMPTY)));
+    gridPane.setPadding(new Insets(10, 10, 10, 10));
+
+    for (int i = 0; i < NUMPOSTAZIONI; i++) {
+      gridPane.add(postazioneView[i], i % 2, i / 2);
+    }
+
+
+    gridPane.add(leftSideView, 0, 2);
+    gridPane.add(rightSideView, 1, 2);
+
+    //TODO creare presenters e connettere model e view
+
+
+    //model.notifyObservers();
+
+    Scene scene = new Scene(gridPane);
+    primaryStage.setScene(scene);
+    primaryStage.show();
+  }
+}
diff --git a/src/main/java/it/unimi/di/sweng/esame/presenters/Presenter.java b/src/main/java/it/unimi/di/sweng/esame/presenters/Presenter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7857756ae86019707ffc9f844e8ec3ad21646376
--- /dev/null
+++ b/src/main/java/it/unimi/di/sweng/esame/presenters/Presenter.java
@@ -0,0 +1,5 @@
+package it.unimi.di.sweng.esame.presenters;
+
+public interface Presenter {
+  void action(String text1, String text2);
+}
diff --git a/src/main/java/it/unimi/di/sweng/esame/views/DisplayView.java b/src/main/java/it/unimi/di/sweng/esame/views/DisplayView.java
new file mode 100644
index 0000000000000000000000000000000000000000..addba0da968b33e06acfbe43411bf3b58f8f8e9d
--- /dev/null
+++ b/src/main/java/it/unimi/di/sweng/esame/views/DisplayView.java
@@ -0,0 +1,43 @@
+package it.unimi.di.sweng.esame.views;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.Label;
+import javafx.scene.layout.*;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import org.jetbrains.annotations.NotNull;
+
+public class DisplayView extends Region {
+  @NotNull private final Label[] rows;
+
+  public DisplayView(@NotNull String title, int rows) {
+    this.rows = new Label[rows];
+    setBackground(new Background(
+        new BackgroundFill(Color.LIGHTBLUE, new CornerRadii(5.0), Insets.EMPTY)));
+    setBorder(new Border(
+        new BorderStroke(null, BorderStrokeStyle.SOLID, new CornerRadii(5.0), new BorderWidths(2))));
+
+    GridPane grid = new GridPane();
+    grid.setPadding(new Insets(10, 10, 10, 10));
+    Label title1 = new Label(title);
+    title1.setFont(Font.font("sans", 20));
+    grid.add(title1, 0, 0);
+    for (int i = 0; i < rows; i++) {
+      this.rows[i] = new Label(String.format("%-35s","Row #" + i));
+      this.rows[i].setPadding(new Insets(10, 10, 10, 10));
+      this.rows[i].setFont(Font.font("monospace", 14));
+      grid.add(this.rows[i], 0, i + 1);
+    }
+    this.getChildren().add(grid);
+  }
+
+  public void set(int i, @NotNull String s) {
+    rows[i].setText(s);
+  }
+
+  public int size() {
+    return rows.length;
+  }
+
+
+}
diff --git a/src/main/java/it/unimi/di/sweng/esame/views/PostazioneView.java b/src/main/java/it/unimi/di/sweng/esame/views/PostazioneView.java
new file mode 100644
index 0000000000000000000000000000000000000000..ede20a0ac4cd69d191519abe8b1b4e070f799ecb
--- /dev/null
+++ b/src/main/java/it/unimi/di/sweng/esame/views/PostazioneView.java
@@ -0,0 +1,83 @@
+package it.unimi.di.sweng.esame.views;
+
+import it.unimi.di.sweng.esame.presenters.Presenter;
+import javafx.geometry.Insets;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.*;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PostazioneView extends Region {
+
+  @NotNull
+  private final TextField textField;
+  @NotNull
+  private final Label error;
+  @NotNull
+  private final Button[] button = new Button[3];
+
+  @NotNull
+  private final Label bagnino;
+
+
+  public PostazioneView() {
+    bagnino = new Label("postazione non presidiata");
+    bagnino.setFont(Font.font("sans", 24));
+    button[0] = new Button("Arriva");
+    button[1] = new Button("Segnala");
+    button[2] = new Button("Va via");
+    textField = new TextField();
+    error = new Label("");
+    textField.setFont(Font.font("sans", 20));
+
+    setBackground(new Background(
+        new BackgroundFill(Color.LIGHTGRAY, new CornerRadii(5.0), Insets.EMPTY)));
+    setBorder(new Border(
+        new BorderStroke(null, BorderStrokeStyle.SOLID, new CornerRadii(5.0), new BorderWidths(2))));
+
+    GridPane grid = new GridPane();
+    grid.setPadding(new Insets(10, 10, 10, 10));
+
+    grid.add(bagnino, 0, 0, 3, 1);
+    grid.add(textField, 0, 2, 3, 1);
+    for (int i = 0; i < 3; i++) {
+      grid.add(button[i], i, 1);
+      button[i].setFont(Font.font("sans", 20));
+    }
+    grid.add(error, 0, 3, 3, 1);
+
+    this.getChildren().add(grid);
+  }
+
+  public void addHandlers(@NotNull Presenter presenter) {
+    /*Arriva */
+    button[0].setOnAction(eh -> presenter.action(button[0].getText(), textField.getText()));
+    /*Segnala*/
+    button[1].setOnAction(eh -> presenter.action(button[1].getText(), bagnino.getText() + "," + textField.getText()));
+    /*Va via */
+    button[2].setOnAction(eh -> presenter.action(button[2].getText(), bagnino.getText()));
+  }
+
+
+  public void showError(@NotNull String s) {
+    error.setText(s);
+    setBackground(new Background(
+        new BackgroundFill(Color.YELLOW, new CornerRadii(5.0), Insets.EMPTY)));
+  }
+
+
+  public void showSuccess() {
+    error.setText("");
+    textField.clear();
+    setBackground(new Background(
+        new BackgroundFill(Color.LIGHTGRAY, new CornerRadii(5.0), Insets.EMPTY)));
+  }
+
+  public void setBagnino(@Nullable String s) {
+    bagnino.setText(s);
+  }
+}
diff --git a/src/test/java/it/unimi/di/sweng/esame/VariTest.java b/src/test/java/it/unimi/di/sweng/esame/VariTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2efd1febdded288a2e50436413df6ed5f4eb559
--- /dev/null
+++ b/src/test/java/it/unimi/di/sweng/esame/VariTest.java
@@ -0,0 +1,10 @@
+package it.unimi.di.sweng.esame;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.assertj.core.api.Assertions;
+
+
+class VariTest {
+
+}
\ No newline at end of file