diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index d01e8692..db1e823e 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -10,13 +10,12 @@ public class App extends Application { @Override public void start(Stage primaryStage) throws Exception { - System.out.println(getClass().getResource("/RaceView.fxml")); - Parent root = FXMLLoader.load(getClass().getResource("/RaceView.fxml")); primaryStage.setTitle("RaceVision"); primaryStage.setScene(new Scene(root)); - seng302.models.OldApp.main(); // Run this to show how positions are updated +// seng302.models.OldApp.main(); // Run this to show how positions are updated +// seng302.controllers.RaceController.initializeRace(); primaryStage.show(); } diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 5700e3a6..34ce2267 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -11,6 +11,13 @@ import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import javafx.util.Duration; +import seng302.models.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static java.lang.Math.abs; /** * Created by ptg19 on 15/03/17. @@ -18,19 +25,73 @@ import javafx.util.Duration; public class CanvasController { @FXML private Canvas canvas; + public void initialize() { GraphicsContext gc = canvas.getGraphicsContext2D(); + gc.scale(5,5); + RaceController raceController = new RaceController(); + raceController.initializeRace(); + Race race = raceController.getRace(); + HashMap timelineInfos = new HashMap<>(); + + HashMap boat_events = race.getEvents(); +// System.out.println(boat_events); + for (Boat boat : boat_events.keySet()) { + DoubleProperty x = new SimpleDoubleProperty(); + DoubleProperty y = new SimpleDoubleProperty(); + List keyFrames = new ArrayList<>(); + List events = boat_events.get(boat); + for (Event event: events){ + keyFrames.add( +// new KeyFrame(Duration.seconds(event.getDistanceBetweenMarks()/event.getBoat().getVelocity()), + new KeyFrame(Duration.seconds(event.getTime()/60/60/5), + new KeyValue(x, event.getMark().getLatitude()), + new KeyValue(y, event.getMark().getLongitude()) + ) + ); +// drawBoat(gc, event.getMark().getLatitude(), event.getMark().getLongitude(), Colors.getColor()); + System.out.println(event.getMark().getName()); + } + timelineInfos.put(boat, new TimelineInfo(new Timeline(keyFrames.toArray(new KeyFrame[keyFrames.size()])), x, y)); + } + + AnimationTimer timer = new AnimationTimer() { + @Override + public void handle(long now) { + GraphicsContext gc = canvas.getGraphicsContext2D(); + gc.clearRect(0,0,760,360); + gc.setFill(Color.FORESTGREEN); + for (Boat boat: timelineInfos.keySet()){ + TimelineInfo timelineInfo = timelineInfos.get(boat); +// System.out.println(timelineInfo.getX().doubleValue()); +// System.out.println(timelineInfo.getY().doubleValue()); + drawBoat(gc, timelineInfo.getX().doubleValue(), timelineInfo.getY().doubleValue(), boat.getColor()); + } + } + }; + timer.start(); + for (TimelineInfo timelineInfo: timelineInfos.values()){ + Timeline timeline = timelineInfo.getTimeline(); + timeline.play(); + } + +// drawBoat(gc, 0, 0, Color.GREEN); +// drawBoat(gc, 100, 100, Color.BLUE); +// drawBoat(gc, 32.296577, -64.854304, Color.RED); +// drawBoat(gc, 32.293771, -64.855242, Color.RED); +// drawBoat(gc, 32.317379, -64.839291, Color.GREEN); +// drawBoat(gc, 32.317257, -64.836260, Color.GREEN); +// drawBoat(gc, 32.313291, -64.887057, Color.YELLOW); + - drawBoat(gc, 0, 0, Color.GREEN); - drawBoat(gc, 100, 100, Color.BLUE); - drawBoat(gc, 32.296577, -64.854304, Color.RED); - drawBoat(gc, 32.293771 , -64.855242, Color.RED); } private void drawBoat(GraphicsContext gc, double x, double y, Color color) { - x += 180; // to prevent negative longtitude - y += 90; // to prevent negative latitude - int diameter = 10; + x = abs(x - 32.313291) * 1000; // to prevent negative longtitude + y = abs(y + 64.887057) * 1000; // to prevent negative latitude + +// y = abs(y); + int diameter = 2; gc.setFill(color); gc.fillOval(x, y, diameter, diameter); } diff --git a/src/main/java/seng302/controllers/RaceController.java b/src/main/java/seng302/controllers/RaceController.java new file mode 100644 index 00000000..bad178d2 --- /dev/null +++ b/src/main/java/seng302/controllers/RaceController.java @@ -0,0 +1,92 @@ +package seng302.controllers; + +import seng302.models.Boat; +import seng302.models.FileParser; +import seng302.models.Mark; +import seng302.models.Race; + +import java.io.FileNotFoundException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; +import java.util.Random; + +/** + * Created by zyt10 on 17/03/17. + * run before CanvasController to initialize race events + * the CanvasController then uses the event data to make the animations + */ +public class RaceController { + Race race = null; + public void initializeRace() { + String raceConfigFile; + raceConfigFile = "doc/examples/config.json"; + + try { + race = createRace(raceConfigFile); + } catch (Exception e) { + System.out.println("There was an error creating the race."); + } + + if (race != null) { + race.startRace(); + } else { + System.out.println("There was an error creating the race. Exiting."); + } + } + + public Race createRace(String configFile) throws Exception { + Race race = new Race(); + FileParser fp; + + // Read team names from file + try{ + fp = new FileParser(configFile); + } + catch (FileNotFoundException e){ + System.out.println("Config file does not exist"); + return null; + } + + ArrayList boatNames = new ArrayList<>(); + ArrayList> teams = fp.getTeams(); + + //get race size + int numberOfBoats = (int) fp.getRaceSize(); + + //get time scale + double timeScale = fp.getTimeScale(); + race.setTimeScale(timeScale); + + for (Map team : teams) { + boatNames.add((String) team.get("team-name")); + } + + // Shuffle team names + long seed = System.nanoTime(); + Collections.shuffle(boatNames, new Random(seed)); + + if (numberOfBoats > Array.getLength(boatNames.toArray())) { + return null; + } + + // Add boats to the race + for (int i = 0; i < numberOfBoats; i++) { + race.addBoat(new Boat(boatNames.get(i), (Double) (teams.get(i).get("velocity")))); + } + + // Add marks to race in order + race.addMark(new Mark("Start", 32.296038,-64.854401 )); + race.addMark(new Mark("Mid Mark", 32.292881,-64.843231 )); + race.addMark(new Mark("Leeward Gate", 32.283808,-64.850012 )); + race.addMark(new Mark("Windward Gate", 32.309908,-64.833665 )); + race.addMark(new Mark("Finish", 32.318439,-64.837367 )); + + return race; + } + + public Race getRace() { + return race; + } +} diff --git a/src/main/java/seng302/models/Race.java b/src/main/java/seng302/models/Race.java index a084edd4..649319b9 100644 --- a/src/main/java/seng302/models/Race.java +++ b/src/main/java/seng302/models/Race.java @@ -1,5 +1,6 @@ package seng302.models; +import seng302.models.mark.Mark; import seng302.models.mark.SingleMark; import java.lang.reflect.Array; @@ -11,8 +12,8 @@ import java.util.*; public class Race { private ArrayList boats; // The boats in the race private ArrayList finishingOrder; // The order in which the boats finish the race - private PriorityQueue events; // The events that occur in the race - private ArrayList singleMarks; // Marks in the race + private HashMap events = new HashMap<>(); // The events that occur in the race + private ArrayList marks; // Marks in the race private int numberOfBoats = 0; private long startTime = 0; private double timeScale = 1; @@ -23,24 +24,24 @@ public class Race { public Race() { this.boats = new ArrayList(); this.finishingOrder = new ArrayList(); - this.singleMarks = new ArrayList(); + this.marks = new ArrayList(); // create a priority queue with a custom Comparator to order events - this.events = new PriorityQueue(new Comparator() { - @Override - public int compare(Event o1, Event o2) { - Double time1 = o1.getTime(); - Double time2 = o2.getTime(); - - // order event asc. by time. if tie appears, then order team - // name alphabetically. - if (time1 != time2) { - return time1.compareTo(time2); - } else { - return o1.getBoat().getTeamName().compareTo(o2.getBoat().getTeamName()); - } - } - }); +// this.events = new PriorityQueue(new Comparator() { +// @Override +// public int compare(Event o1, Event o2) { +// Double time1 = o1.getTime(); +// Double time2 = o2.getTime(); +// +// // order event asc. by time. if tie appears, then order team +// // name alphabetically. +// if (time1 != time2) { +// return time1.compareTo(time2); +// } else { +// return o1.getBoat().getTeamName().compareTo(o2.getBoat().getTeamName()); +// } +// } +// }); } /** @@ -142,23 +143,28 @@ public class Race { for (Boat boat : this.boats) { double totalDistance = 0; - int numberOfMarks = this.singleMarks.size(); + int numberOfMarks = this.marks.size(); for(int i = 0; i < numberOfMarks; i++){ Double time = (Double) (1000 * totalDistance / boat.getVelocity()); // If there are singleMarks after this event if (i < numberOfMarks-1) { - Event event = new Event(time, boat, singleMarks.get(i), singleMarks.get(i + 1)); - events.add(event); - totalDistance += event.getDistanceBetweenMarks(); + Event event = new Event(time, boat, marks.get(i), marks.get(i + 1)); + try { + events.get(boat).add(event); + + } catch (NullPointerException e) { + events.put(boat, new ArrayList(Arrays.asList(event))); + } + totalDistance += event.getDistanceBetweenMarks(); } - // There are no more singleMarks after this event - else{ - Event event = new Event(time, boat, singleMarks.get(i)); - events.add(event); - } + // There are no more marks after this event +// else{ +// Event event = new Event(time, boat, marks.get(i)); +// events.put(boat, new ArrayList(Arrays.asList(event))); +// } } } } @@ -179,40 +185,40 @@ public class Race { * Iterate over events in the race and print the * event string for each event */ - public void iterateEvents() { - // iterates all events. ends when no event in events. - - while (!events.isEmpty()) { - Event peekEvent = events.peek(); - long currentTime = (long) ((System.currentTimeMillis() - this.startTime) * this.timeScale); - - if (currentTime > peekEvent.getTime()) { - Event nextEvent = events.poll(); - - // Display a summary of the event - System.out.println(nextEvent.getEventString()); - - // Display latitude and longitude - if (!nextEvent.getIsFinishingEvent()){ - System.out.println(nextEvent.getMark().getLatitude() + ", " + nextEvent.getNextMark().getLongitude()); - } - - System.out.println(); - - // If event is a boat finishing the race - if (nextEvent.getIsFinishingEvent()) { - this.finishingOrder.add(nextEvent.getBoat()); - } - } - - // Wait for 100ms to throttle the while loop - try { - Thread.sleep(100); - } catch (java.lang.InterruptedException e) { - continue; - } - } - } +// public void iterateEvents() { +// // iterates all events. ends when no event in events. +// +// while (!events.isEmpty()) { +// Event peekEvent = events.peek(); +// long currentTime = (long) ((System.currentTimeMillis() - this.startTime) * this.timeScale); +// +// if (currentTime > peekEvent.getTime()) { +// Event nextEvent = events.poll(); +// +// // Display a summary of the event +// System.out.println(nextEvent.getEventString()); +// +// // Display latitude and longitude +// if (!nextEvent.getIsFinishingEvent()){ +// System.out.println(nextEvent.getMark().getLatitude() + ", " + nextEvent.getNextMark().getLongitude()); +// } +// +// System.out.println(); +// +// // If event is a boat finishing the race +// if (nextEvent.getIsFinishingEvent()) { +// this.finishingOrder.add(nextEvent.getBoat()); +// } +// } +// +// // Wait for 100ms to throttle the while loop +// try { +// Thread.sleep(100); +// } catch (java.lang.InterruptedException e) { +// continue; +// } +// } +// } /** * Start the race and print each marker with the order @@ -221,8 +227,8 @@ public class Race { public void startRace() { // record start time. generateEvents(); - this.startTime = System.currentTimeMillis(); - iterateEvents(); +// this.startTime = System.currentTimeMillis(); +// iterateEvents(); } /** @@ -230,6 +236,10 @@ public class Race { * @param singleMark, the singleMark to add */ public void addMark(SingleMark singleMark){ - this.singleMarks.add(singleMark); + this.marks.add(singleMark); + } + + public HashMap getEvents() { + return events; } } \ No newline at end of file diff --git a/src/main/java/seng302/models/TimelineInfo.java b/src/main/java/seng302/models/TimelineInfo.java new file mode 100644 index 00000000..867ce67b --- /dev/null +++ b/src/main/java/seng302/models/TimelineInfo.java @@ -0,0 +1,31 @@ +package seng302.models; + +import javafx.animation.Timeline; +import javafx.beans.property.DoubleProperty; + + +/** + * Created by zyt10 on 17/03/17. + * this class is literally just to associate a timeline with a DoubleProperty x and y + */ +public class TimelineInfo { + private Timeline timeline; + private DoubleProperty x; + private DoubleProperty y; + + public TimelineInfo(Timeline timeline, DoubleProperty x, DoubleProperty y) { + this.timeline = timeline; + this.x = x; + this.y = y; + } + + public Timeline getTimeline() { + return timeline; + } + public DoubleProperty getX() { + return x; + } + public DoubleProperty getY() { + return y; + } +}