package mock.app; import mock.dataInput.PolarParser; import mock.model.MockRace; import mock.model.Polars; import mock.model.RaceLogic; 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 javax.xml.transform.TransformerException; import java.io.IOException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; 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 static Event theEvent = new Event(); private String raceXML; private String regattaXML; private String boatXML; private XMLFileType xmlFileType; private Polars boatPolars; private ConnectionAcceptor mockOutput; private LatestMessages latestMessages; /** * Constructs an event, using various XML files. */ private Event() { try { this.raceXML = getRaceXMLAtCurrentTime(XMLReader.readXMLFileToString("mock/mockXML/raceTest.xml", StandardCharsets.UTF_8)); this.boatXML = XMLReader.readXMLFileToString("mock/mockXML/boatsSinglePlayer.xml", StandardCharsets.UTF_8); this.regattaXML = XMLReader.readXMLFileToString("mock/mockXML/regattaTest.xml", StandardCharsets.UTF_8); this.xmlFileType = XMLFileType.Contents; this.boatPolars = PolarParser.parse("mock/polars/acc_polars.csv"); this.latestMessages = new LatestMessages(); this.mockOutput = new ConnectionAcceptor(latestMessages); } catch (IOException e) { e.printStackTrace(); } catch (XMLReaderException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } } public static Event getEvent() { return theEvent; } public String getAddress() throws UnknownHostException { return mockOutput.getAddress(); } public int getPort() { return mockOutput.getServerPort(); } /** * 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 { new Thread(mockOutput).start(); 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. RaceLogic newRace = new RaceLogic(new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.latestMessages, this.boatPolars, Constants.RaceTimeScale), this.latestMessages); 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; } }