package mock.app; import mock.model.MockRace; import mock.model.Polars; import network.Messages.LatestMessages; import shared.dataInput.*; import shared.enums.XMLFileType; import shared.exceptions.InvalidBoatDataException; import shared.exceptions.InvalidRaceDataException; import shared.exceptions.InvalidRegattaDataException; import shared.exceptions.XMLReaderException; import shared.model.Constants; import java.io.IOException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; /** * A Race Event, this holds all of the race's information as well as handling the connection to its clients. */ public class Event { private String raceXML; private String regattaXML; private String boatXML; private XMLFileType xmlFileType; private Polars boatPolars; private MockOutput mockOutput; private LatestMessages latestMessages; /** * Constructs an event, using various XML files. * @param raceXML The race.xml file. * @param regattaXML The regatta.xml file. * @param boatXML The boat.xml file. * @param type How to read the file - e.g., load as resource. * @param boatPolars */ public Event(String raceXML, String regattaXML, String boatXML, XMLFileType type, Polars boatPolars) { this.raceXML = getRaceXMLAtCurrentTime(raceXML); this.boatXML = boatXML; this.regattaXML = regattaXML; this.xmlFileType = type; this.boatPolars = boatPolars; this.latestMessages = new LatestMessages(); try { this.mockOutput = new MockOutput(this.latestMessages); new Thread(mockOutput).start(); } catch (IOException e) { e.printStackTrace(); } } /** * Sends the initial race data and then begins race simulation. * @throws InvalidRaceDataException Thrown if the race xml file cannot be parsed. * @throws XMLReaderException Thrown if any of the xml files cannot be parsed. * @throws InvalidBoatDataException Thrown if the boat xml file cannot be parsed. * @throws InvalidRegattaDataException Thrown if the regatta xml file cannot be parsed. */ public void start() throws InvalidRaceDataException, XMLReaderException, InvalidBoatDataException, InvalidRegattaDataException { sendXMLs(); //Parse the XML files into data sources. RaceDataSource raceDataSource = new RaceXMLReader(this.raceXML, this.xmlFileType); BoatDataSource boatDataSource = new BoatXMLReader(this.boatXML, this.xmlFileType); RegattaDataSource regattaDataSource = new RegattaXMLReader(this.regattaXML, this.xmlFileType); //Create and start race. MockRace newRace = new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.latestMessages, this.boatPolars, Constants.RaceTimeScale); new Thread(newRace).start(); } /** * Sends out each xml string, via the mock output */ private void sendXMLs() { mockOutput.setRegattaXml(regattaXML); mockOutput.setRaceXml(raceXML); mockOutput.setBoatsXml(boatXML); } /** * Sets the xml description of the race to show the race was created now, and starts in 4 minutes * @param raceXML The race.xml contents. * @return String containing edited xml */ private String getRaceXMLAtCurrentTime(String raceXML) { //The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute. long millisecondsToAdd = Constants.RacePreStartTime + (1 * 60 * 1000); long secondsToAdd = millisecondsToAdd / 1000; //Scale the time using our time scalar. secondsToAdd = secondsToAdd / Constants.RaceTimeScale; DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); ZonedDateTime creationTime = ZonedDateTime.now(); raceXML = raceXML.replace("CREATION_TIME", dateFormat.format(creationTime)); raceXML = raceXML.replace("START_TIME", dateFormat.format(creationTime.plusSeconds(secondsToAdd))); return raceXML; } }