package mock.model; import network.Messages.BoatLocation; import network.Messages.BoatStatus; import network.Messages.LatestMessages; import network.Messages.RaceStatus; import network.Utils.AC35UnitConverter; import shared.model.CompoundMark; import shared.model.Constants; import shared.model.Mark; import java.util.ArrayList; import java.util.List; /** * Created by connortaylorbrown on 2/08/17. */ public class RaceServer { private MockRace race; private LatestMessages latestMessages; /** * The sequence number of the latest RaceStatus message sent or received. */ private int raceStatusSequenceNumber = 1; /** * The sequence number of the latest BoatLocation message sent or received. */ private int boatLocationSequenceNumber = 1; public RaceServer(MockRace race, LatestMessages latestMessages) { this.race = race; this.latestMessages = latestMessages; } /** * Parses an individual marker boat, and sends it to mockOutput. * @param mark The marker boat to parse. */ private void parseIndividualMark(Mark mark) { //Create message. BoatLocation boatLocation = new BoatLocation( mark.getSourceID(), mark.getPosition().getLatitude(), mark.getPosition().getLongitude(), this.boatLocationSequenceNumber, 0, 0, race.getRaceClock().getCurrentTimeMilli()); //Iterates the sequence number. this.boatLocationSequenceNumber++; this.latestMessages.setBoatLocation(boatLocation); } /** * Parse the compound marker boats through mock output. */ public void parseMarks() { for (CompoundMark compoundMark : race.getCompoundMarks()) { //Get the individual marks from the compound mark. Mark mark1 = compoundMark.getMark1(); Mark mark2 = compoundMark.getMark2(); //If they aren't null, parse them (some compound marks only have one mark). if (mark1 != null) { this.parseIndividualMark(mark1); } if (mark2 != null) { this.parseIndividualMark(mark2); } } } /** * Parse the boats in the race, and send it to mockOutput. */ public void parseBoatLocations() { //Parse each boat. for (MockBoat boat : race.getBoats()) { this.parseIndividualBoatLocation(boat); } } /** * Parses an individual boat, and sends it to mockOutput. * @param boat The boat to parse. */ private void parseIndividualBoatLocation(MockBoat boat) { BoatLocation boatLocation = new BoatLocation( boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), this.boatLocationSequenceNumber, boat.getBearing().degrees(), boat.getCurrentSpeed(), race.getRaceClock().getCurrentTimeMilli()); //Iterates the sequence number. this.boatLocationSequenceNumber++; this.latestMessages.setBoatLocation(boatLocation); } /** * Parses the race status, and sends it to mockOutput. */ public void parseRaceStatus() { //A race status message contains a list of boat statuses. List boatStatuses = new ArrayList<>(); //Add each boat status to the status list. for (MockBoat boat : race.getBoats()) { BoatStatus boatStatus = new BoatStatus( boat.getSourceID(), boat.getStatus(), boat.getCurrentLeg().getLegNumber(), boat.getEstimatedTimeAtNextMark().toInstant().toEpochMilli() ); boatStatuses.add(boatStatus); } //Convert wind direction and speed to ints. //TODO this conversion should be done inside the racestatus class. int windDirectionInt = AC35UnitConverter.encodeHeading(race.getWindDirection().degrees()); int windSpeedInt = (int) (race.getWindSpeed() * Constants.KnotsToMMPerSecond); //Create race status object, and send it. RaceStatus raceStatus = new RaceStatus( System.currentTimeMillis(), race.getRaceId(), race.getRaceStatusEnum().getValue(), race.getRaceClock().getStartingTimeMilli(), windDirectionInt, windSpeedInt, race.getRaceType().getValue(), boatStatuses); this.latestMessages.setRaceStatus(raceStatus); } }