In our game we've decided to add 2 features : a full GUI that lets the payer choose if they want to host or join a game and the second one being the tickets changing colour upon full or part completion. The gui required thee creation of quite a few new classes and modification in already existing ones, yet the ticket idea was quicker to implement. Changing the ticket colour : First of all we had to create a method in the class Ticket that would tell us if It has been fully completed, partly completed or not at all. This has been done with two public methods : isFullyDone and isPartlyDone, each taking a StationConnectivity as a parameter (lets call it sc) and returning a boolean. IsFully done, calls the method points(StationConnectivity sc) on each trip of the ticket and checks that ALL of the return values of this method are greater than 0, meaning they have been all completed and the points given for them are also all positive. isPartlyDone also takes a StationConnectivity as a parameter and works in a similar way, calling the points(sc) method on all of its trips, yet this time we check that AT LEAST ONE trip is done AND that AT LEAST ONE trip isn't (int returned by points will be smaller than 0). Now, we knew that this method will have to be accessed from an instance of DecksViewCreator that shows the graphical part, yet there had to be a connection via instances of other classes, not to break the encapsulation. Thus, we realised that an instance of the class PlayerState would have access to a Station Connectivity and could call the earlier described methods from the class Ticket (implemented by two methods with the same names, taking a ticket as a parameter, calling the method on the ticket in question and passing the StationPartition of the player in question as the parameter, returning the same boolean as the Ticket method). Finally, the last piece between the DecksViewCreator and the PlayerState was thee class ObservableGameState. In it, we created an attribute that keeps track if the tickets are completed/patly completed/ not at all completed. We did this with a map, who's keys are Tickets and values are BooleanProperties. This map would then be updated in the method setState, adding a new ticket to the map if needed and renewing the value of a key if it has changed (done trough calling the two methods in the class PlayerState on the attribute of type PlayerState that is assigned to an instance of ObservableGameState). Finally, we added two methods (again with thee same names as before) that would take a ticket as an argument and return a ReadonlyBooleanProperty assigned as the value to the ticket passed as the argument (in the map described earlier). Finally, in the part of the program that has access to the graphical representation of ones tickets is the instance of DecksViewCreator, that, in the method createHandView creates a ListView of tickets. Our idea was to modify the appearance of its elements with the method setCellFactory, thus modifying the default cell appearance. Without touching css, the quickest way we found to change font colours was by overriding the method updateItem, that for each unique item contained in our ListView, would change the font colour, depending if it has been completed or not (calling the two methods on the instance of observable game state passed as a parameter to the method createHandView). Finally, we want the tickets to change colour when they change state through the game. That's why for each ticket, contained in our ListView, we set a listener. Though, we do it trough the ObservableList of tickets, that is used to create the ListView. Since we want to add listeners to tickets when they are added, we start by adding a listener to the observable list, them inside, for each item of the ListView (each ticket), we set a listener on the return value of the fullyDon/partlyDone methods from the observableGameState inside which we execute the same code as described in the beginning of this paragraph : calling setCellFactory on the instance of ListView ... changing the font colours. GUI implementation : We've created a few windows that would facilitate the usage of this program. Now, when running the method main in thee class Main, the user will be greeted by our welcome screen with a train gif playing, The name of thee game will slowly fade in and by clicking anywhere on the screen, a new window will appear where you will able to either has or join a game. After closing one or another two things can happen: 1) Host a game : you'll be asked to enter the names of the two players, clicking confirm after each entry. The button, starting the game will only be activated after two valid names were entered (not empty strings). If you enter an empty string (don't write anything), the program will indicate your error by making the border of the box red. When clicking the button that starts the game, a few things happen : - A waiting window a appears and shows a little animation along with a few informations as the IP address (which is most likely false btw) and the port number (which should be valid unless you use ngrok) - A modified version of ServerMain is called, in our modifications we decided to make int instantiable to be able to pass it the information that otherwise would be passed as params to the program directly. Another thing we've modified in ServerMain is what happens in the "connection" part of the method start. We didn't want our program to freeze because of the method accept so we decided to call it in a new thread and as soon as the connection has been established, call a method in the main javaFX thread (where the game would be launched). The easiest way we found to do this was by giving ServerMain an attribute that would stock the Socket to which one has connected. We do this with an ObjectProperty on which we then attach a listener, since the only moment when the content of the property is modified, is straight after the connection has taken place, there's no way the part of code, starting the game will be called upon without the connection being made before that. It may be a bit over complicated for nothing, yet this way, the user can actually quit this connection screen and decide to join a game instead. 2) Join a game : you'll be asked to enter the IP address and port number of the game you're joining. As before, an empty string will not be considered as valid for a the IP address and the port number will only accept numbers as an entry (we've wrote a little verification method in Preconditions to be sure that were not parsing letters into an int). This way we avoid problems in the future. The button that connects you to a server is only activated when all the requirements are met. Again, a few things happen when it's pressed : - A waiting window appears that shows another little animation along with a few informations : the IP address and the port number you've entered. - A slightly modified version of ClientMain is called upon. We create an instance of this class by passing as parameters the two connection informations received from the previous screen (IP/port num), then call the method start, which then does the same thing as ClientMain before. It would take a while (and wouldn't be very interesting) to explain how we created each of these windows, since it's basic usage of JavaFX that uses techniques seen throughout the project. We should, however precise that all of the classes working on this part of the project are in the package ch.epfl.tchu.gui.menus. - WelcomeScreen is the class that creates the into window (with the train gif), - ChoiceScreen is that class that creates the window where you are able to choose between hosing and joining a game, - EntryCreator is the window that asks the user to enter their information (both for hosts and for clients), - WaitingScreen creates the window that is shown while connection (both hosts and clients) -PlayerType is an enum that has two instances : HOST and CLIENT, this is made to ease the usage of classes EntryCreator and WaitingScreen.