package seng302.Model; import seng302.Controllers.RaceController; import seng302.GPSCoordinate; import java.util.*; /** * Parent class for races * Created by fwy13 on 3/03/17. */ public abstract class Race implements Runnable { protected BoatInRace[] startingBoats; protected ArrayList legs; protected RaceController controller; protected int boatsFinished = 0; private int SLEEP_TIME = 1000; //time in milliseconds to pause in a paced loop /** * Initailiser for Race * @param boats Takes in an array of boats that are participating in the race. * @param marks Number of marks in order that the boats pass in order to complete the race. */ public Race(BoatInRace[] boats, ArrayList marks, RaceController controller) { this.startingBoats = boats; this.legs = marks; this.legs.add(new Leg("Finish")); this.controller = controller; } public Race(BoatInRace[] boats, ArrayList marks) { this(boats, marks, null); } public void run() { updateController(); preRace(); simulateRace(); } private void preRace() { //show the boats participating. System.out.println("Boats Participating:"); System.out.println("===================="); for (int i = 0; i < startingBoats.length; i++) { System.out.println(i + 1 + ". " + startingBoats[i].getName() + ", Speed: " + Math.round(startingBoats[i].getVelocity() * 1.94384) + "kn"); startingBoats[i].setCurrentLeg(legs.get(0)); } } /** * Starts the Race Simulation, playing the race start to finish with the timescale. * This prints the boats participating, the order that the events occur in time order, and the respective information of the events. */ private void simulateRace() { long timeRaceStarted = System.currentTimeMillis(); long totalTimeElapsed; long timeLoopStarted; long timeLoopEnded; long minutes; long currentTimeInSeconds; long remainingSeconds; while (boatsFinished < startingBoats.length) { timeLoopStarted = System.currentTimeMillis(); totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted; long currentTime = System.currentTimeMillis() - timeRaceStarted; currentTimeInSeconds = currentTime / 1000; minutes = currentTimeInSeconds / 60; remainingSeconds = currentTimeInSeconds % 60; System.out.println(minutes + ":" + remainingSeconds); for (BoatInRace boat : startingBoats) { updatePosition(boat, SLEEP_TIME); checkPosition(boat, totalTimeElapsed); } try { timeLoopEnded = System.currentTimeMillis(); Thread.sleep(SLEEP_TIME - (timeLoopEnded - timeLoopStarted)); } catch (InterruptedException e) { return; } } } protected void checkPosition(BoatInRace boat, long timeElapsed) { if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()){ updateController(); //boat has passed onto new leg if (boat.getCurrentLeg().getName().equals("Finish")) { //boat has finished boat.setTimeFinished(timeElapsed); boatsFinished++; } else { boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance()); Leg nextLeg = legs.get(boat.getCurrentLeg().getLegNumber() + 1); boat.setCurrentLeg(nextLeg); boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg()); } } } protected void updateController() { if(controller != null) controller.updateInfoTable(this); } public BoatInRace[] getStartingBoats() { return startingBoats; } /** * This function is a function that generates the Race and populates the events list. * Is automatically called by the initialiser function, so that simulateRace() does not return an empty race. * @see Race#simulateRace() */ protected abstract void updatePosition(BoatInRace boat, int millisecondsElapsed); }