mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Reformatted and refactored the canvas controller
#fix #refactor #story[377]
This commit is contained in:
@@ -11,10 +11,14 @@ import javafx.scene.canvas.Canvas;
|
|||||||
import javafx.scene.canvas.GraphicsContext;
|
import javafx.scene.canvas.GraphicsContext;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import seng302.models.*;
|
import seng302.models.Boat;
|
||||||
|
import seng302.models.Event;
|
||||||
|
import seng302.models.Race;
|
||||||
|
import seng302.models.TimelineInfo;
|
||||||
import seng302.models.mark.GateMark;
|
import seng302.models.mark.GateMark;
|
||||||
import seng302.models.mark.Mark;
|
import seng302.models.mark.Mark;
|
||||||
import seng302.models.mark.MarkType;
|
import seng302.models.mark.MarkType;
|
||||||
|
import seng302.models.mark.SingleMark;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -24,103 +28,129 @@ import static java.lang.Math.abs;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ptg19 on 15/03/17.
|
* Created by ptg19 on 15/03/17.
|
||||||
|
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
||||||
*/
|
*/
|
||||||
public class CanvasController {
|
public class CanvasController {
|
||||||
@FXML private Canvas canvas;
|
|
||||||
Race race;
|
|
||||||
GraphicsContext gc;
|
|
||||||
HashMap<Boat, TimelineInfo> timelineInfos;
|
|
||||||
|
|
||||||
|
private Race race;
|
||||||
|
private GraphicsContext gc;
|
||||||
|
private HashMap<Boat, TimelineInfo> timelineInfos;
|
||||||
|
@FXML
|
||||||
|
private Canvas canvas;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
gc = canvas.getGraphicsContext2D();
|
gc = canvas.getGraphicsContext2D();
|
||||||
gc.scale(5,5);
|
gc.scale(5, 5);
|
||||||
RaceController raceController = new RaceController();
|
RaceController raceController = new RaceController();
|
||||||
raceController.initializeRace();
|
raceController.initializeRace();
|
||||||
race = raceController.getRace();
|
race = raceController.getRace();
|
||||||
timelineInfos = new HashMap<>();
|
timelineInfos = new HashMap<>();
|
||||||
|
|
||||||
HashMap<Boat, List> boat_events = race.getEvents();
|
// overriding the handle so that it can clean canvas and redraw boats and course marks
|
||||||
// System.out.println(boat_events);
|
|
||||||
|
|
||||||
// generating timelines
|
|
||||||
for (Boat boat : boat_events.keySet()) {
|
|
||||||
DoubleProperty x = new SimpleDoubleProperty();
|
|
||||||
DoubleProperty y = new SimpleDoubleProperty();
|
|
||||||
List<KeyFrame> keyFrames = new ArrayList<>();
|
|
||||||
List<Event> 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() {
|
AnimationTimer timer = new AnimationTimer() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(long now) {
|
public void handle(long now) {
|
||||||
gc.clearRect(0,0,760,360);
|
gc.clearRect(0, 0, 760, 360);
|
||||||
drawCourse();
|
drawCourse();
|
||||||
drawBoats();
|
drawBoats();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
generateTimeline();
|
||||||
|
|
||||||
|
// starts the timer and reads events from each boat's time line
|
||||||
timer.start();
|
timer.start();
|
||||||
for (TimelineInfo timelineInfo: timelineInfos.values()){
|
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
||||||
Timeline timeline = timelineInfo.getTimeline();
|
Timeline timeline = timelineInfo.getTimeline();
|
||||||
timeline.play();
|
timeline.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawBoats(){
|
/**
|
||||||
for (Boat boat: timelineInfos.keySet()){
|
* Generates time line for each boat, and stores time time into timelineInfos hash map
|
||||||
|
*/
|
||||||
|
private void generateTimeline() {
|
||||||
|
HashMap<Boat, List> boat_events = race.getEvents();
|
||||||
|
for (Boat boat : boat_events.keySet()) {
|
||||||
|
// x, y are the real time coordinates
|
||||||
|
DoubleProperty x = new SimpleDoubleProperty();
|
||||||
|
DoubleProperty y = new SimpleDoubleProperty();
|
||||||
|
|
||||||
|
List<KeyFrame> keyFrames = new ArrayList<>();
|
||||||
|
List<Event> events = boat_events.get(boat);
|
||||||
|
// iterates all events and convert each event to keyFrame, then add them into a list
|
||||||
|
for (Event event : events) {
|
||||||
|
keyFrames.add(
|
||||||
|
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||||
|
new KeyValue(x, event.getMark().getLatitude()),
|
||||||
|
new KeyValue(y, event.getMark().getLongitude())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// uses the lists generated above to create a Timeline for the boat.
|
||||||
|
timelineInfos.put(boat, new TimelineInfo(new Timeline(keyFrames.toArray(new KeyFrame[keyFrames.size()])), x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws all the boats.
|
||||||
|
*/
|
||||||
|
private void drawBoats() {
|
||||||
|
for (Boat boat : timelineInfos.keySet()) {
|
||||||
TimelineInfo timelineInfo = timelineInfos.get(boat);
|
TimelineInfo timelineInfo = timelineInfos.get(boat);
|
||||||
drawBoat(timelineInfo.getX().doubleValue(), timelineInfo.getY().doubleValue(), boat.getColor());
|
drawBoat(timelineInfo.getX().doubleValue(), timelineInfo.getY().doubleValue(), boat.getColor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a boat with given (x, y) position in the given color
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
private void drawBoat(double x, double y, Color color) {
|
private void drawBoat(double x, double y, Color color) {
|
||||||
x = abs(x - 32.313291) * 1000; // to prevent negative longtitude
|
x = abs(x - 32.313291) * 1000; // to prevent negative longitude
|
||||||
y = abs(y + 64.887057) * 1000; // to prevent negative latitude
|
y = abs(y + 64.887057) * 1000; // to prevent negative latitude
|
||||||
|
|
||||||
// y = abs(y);
|
|
||||||
int diameter = 2;
|
int diameter = 2;
|
||||||
gc.setFill(color);
|
gc.setFill(color);
|
||||||
gc.fillOval(x, y, diameter, diameter);
|
gc.fillOval(x, y, diameter, diameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawCourse(){
|
/**
|
||||||
for (Mark mark: race.getCourse()){
|
* Draws the course.
|
||||||
|
*/
|
||||||
|
private void drawCourse() {
|
||||||
|
for (Mark mark : race.getCourse()) {
|
||||||
|
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||||
|
drawSingleMark((SingleMark) mark);
|
||||||
|
} else if (mark.getMarkType() == MarkType.GATE_MARK) {
|
||||||
|
drawGateMark((GateMark) mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a given mark on canvas
|
||||||
|
*
|
||||||
|
* @param singleMark
|
||||||
|
*/
|
||||||
|
private void drawSingleMark(SingleMark singleMark) {
|
||||||
|
double x = abs(singleMark.getLatitude() - 32.313291) * 1000; // to prevent negative longitude
|
||||||
|
double y = abs(singleMark.getLongitude() + 64.887057) * 1000; // to prevent negative latitude
|
||||||
gc.setFill(Color.BLACK);
|
gc.setFill(Color.BLACK);
|
||||||
|
|
||||||
if (mark.getMarkType() == MarkType.SINGLE_MARK){
|
|
||||||
double x = abs(mark.getLatitude() - 32.313291) * 1000; // to prevent negative longtitude
|
|
||||||
double y = abs(mark.getLongitude() + 64.887057) * 1000; // to prevent negative latitude
|
|
||||||
|
|
||||||
gc.fillOval(x, y, 2, 2);
|
gc.fillOval(x, y, 2, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (mark.getMarkType() == MarkType.GATE_MARK){
|
/**
|
||||||
double x;
|
* Draw a gate mark which contains two single marks
|
||||||
double y;
|
*
|
||||||
GateMark gateMark = (GateMark) mark;
|
* @param gateMark
|
||||||
Mark mark1 = gateMark.getSingleMark1();
|
*/
|
||||||
Mark mark2 = gateMark.getSingleMark1();
|
private void drawGateMark(GateMark gateMark) {
|
||||||
|
drawSingleMark(gateMark.getSingleMark1());
|
||||||
x = abs(mark1.getLatitude() - 32.313291) * 1000; // to prevent negative longtitude
|
drawSingleMark(gateMark.getSingleMark2());
|
||||||
y = abs(mark1.getLongitude() + 64.887057) * 1000; // to prevent negative latitude
|
|
||||||
gc.fillOval(x, y, 2, 2);
|
|
||||||
|
|
||||||
x = abs(mark2.getLatitude() - 32.313291) * 1000; // to prevent negative longtitude
|
|
||||||
y = abs(mark2.getLongitude() + 64.887057) * 1000; // to prevent negative latitude
|
|
||||||
gc.fillOval(x, y, 2, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class OldApp {
|
|||||||
|
|
||||||
// If race was created
|
// If race was created
|
||||||
if (race != null) {
|
if (race != null) {
|
||||||
race.displayStartingBoats();
|
//race.displayStartingBoats();
|
||||||
|
|
||||||
System.out.println("\n\n");
|
System.out.println("\n\n");
|
||||||
System.out.println("######################");
|
System.out.println("######################");
|
||||||
@@ -96,7 +96,7 @@ public class OldApp {
|
|||||||
System.out.println("######################");
|
System.out.println("######################");
|
||||||
|
|
||||||
//race.showRaceMarkerResults();
|
//race.showRaceMarkerResults();
|
||||||
race.displayFinishingOrder();
|
//race.displayFinishingOrder();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("There was an error creating the race. Exiting.");
|
System.out.println("There was an error creating the race. Exiting.");
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
package seng302.models;
|
package seng302.models;
|
||||||
|
|
||||||
import seng302.models.mark.*;
|
import seng302.models.mark.Mark;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Race class containing the boats and legs in the race
|
* Race class containing the boats and legs in the race
|
||||||
*/
|
* Created by mra106 on 8/3/2017.
|
||||||
|
*/
|
||||||
public class Race {
|
public class Race {
|
||||||
private ArrayList<Boat> boats; // The boats in the race
|
private ArrayList<Boat> boats; // The boats in the race
|
||||||
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
|
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
|
||||||
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in the race
|
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in the race
|
||||||
private List<Mark> course; // Marks in the race
|
private List<Mark> course; // Marks in the race
|
||||||
private int numberOfBoats = 0;
|
|
||||||
private long startTime = 0;
|
private long startTime = 0;
|
||||||
private double timeScale = 1;
|
private double timeScale = 1;
|
||||||
|
|
||||||
@@ -21,26 +20,9 @@ public class Race {
|
|||||||
* Race class containing the boats and legs in the race
|
* Race class containing the boats and legs in the race
|
||||||
*/
|
*/
|
||||||
public Race() {
|
public Race() {
|
||||||
this.boats = new ArrayList<Boat>();
|
this.boats = new ArrayList<>();
|
||||||
this.finishingOrder = new ArrayList<Boat>();
|
this.finishingOrder = new ArrayList<>();
|
||||||
this.course = new ArrayList<Mark>();
|
this.course = new ArrayList<>();
|
||||||
|
|
||||||
// create a priority queue with a custom Comparator to order events
|
|
||||||
// this.events = new PriorityQueue<Event>(new Comparator<Event>() {
|
|
||||||
// @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());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +32,6 @@ public class Race {
|
|||||||
*/
|
*/
|
||||||
public void addBoat(Boat boat) {
|
public void addBoat(Boat boat) {
|
||||||
boats.add(boat);
|
boats.add(boat);
|
||||||
numberOfBoats += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,14 +57,6 @@ public class Race {
|
|||||||
return this.finishingOrder.toArray(new Boat[this.finishingOrder.size()]);
|
return this.finishingOrder.toArray(new Boat[this.finishingOrder.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of boats in the race
|
|
||||||
*
|
|
||||||
* @returns the number of boats in the race
|
|
||||||
*/
|
|
||||||
public int getNumberOfBoats() {
|
|
||||||
return numberOfBoats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of boats in the race
|
* Returns a list of boats in the race
|
||||||
@@ -94,37 +67,6 @@ public class Race {
|
|||||||
return boats.toArray(new Boat[boats.size()]);
|
return boats.toArray(new Boat[boats.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints the order in which the boats finished the race
|
|
||||||
*/
|
|
||||||
public void displayFinishingOrder() {
|
|
||||||
int numberOfBoats = this.getNumberOfBoats();
|
|
||||||
Boat[] boats = this.getFinishedBoats();
|
|
||||||
|
|
||||||
System.out.println("--- Finishing Order ---");
|
|
||||||
|
|
||||||
for (int i = 0; i < Array.getLength(boats); i++) {
|
|
||||||
System.out.println("#" + Integer.toString(i + 1) + " - " + boats[i].getTeamName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints the list of boats competing in the race
|
|
||||||
*/
|
|
||||||
public void displayStartingBoats() {
|
|
||||||
int numberOfBoats = this.getNumberOfBoats();
|
|
||||||
Boat[] boats = this.getBoats();
|
|
||||||
|
|
||||||
System.out.println("######################");
|
|
||||||
System.out.println("# Competing Boats ");
|
|
||||||
System.out.println("######################");
|
|
||||||
|
|
||||||
for (int i = 0; i < numberOfBoats; i++) {
|
|
||||||
String velocityKnots = String.format("%1.2f", boats[i].getVelocity() * 1.943844492);
|
|
||||||
|
|
||||||
System.out.println(boats[i].getTeamName() + " Velocity: " + velocityKnots + " Knots/s");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Sets time scale
|
* Sets time scale
|
||||||
*
|
*
|
||||||
@@ -138,107 +80,41 @@ public class Race {
|
|||||||
* Generate all events that will happen during the race.
|
* Generate all events that will happen during the race.
|
||||||
*/
|
*/
|
||||||
private void generateEvents() {
|
private void generateEvents() {
|
||||||
//calculate the time every boat passes each leg, and create an event
|
|
||||||
|
|
||||||
for (Boat boat : this.boats) {
|
for (Boat boat : this.boats) {
|
||||||
double totalDistance = 0;
|
double totalDistance = 0;
|
||||||
int numberOfMarks = this.course.size();
|
int numberOfMarks = this.course.size();
|
||||||
|
|
||||||
for(int i = 0; i < numberOfMarks; i++){
|
for (int i = 0; i < numberOfMarks; i++) {
|
||||||
Double time = (Double) (1000 * totalDistance / boat.getVelocity());
|
Double time = (1000 * totalDistance / boat.getVelocity());
|
||||||
|
|
||||||
// If there are singleMarks after this event
|
// If there are singleMarks after this event
|
||||||
if (i < numberOfMarks-1) {
|
if (i < numberOfMarks - 1) {
|
||||||
Event event = new Event(time, boat, course.get(i), course.get(i + 1));
|
Event event = new Event(time, boat, course.get(i), course.get(i + 1));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
events.get(boat).add(event);
|
events.get(boat).add(event);
|
||||||
|
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
events.put(boat, new ArrayList<Event>(Arrays.asList(event)));
|
events.put(boat, new ArrayList<>(Arrays.asList(event)));
|
||||||
}
|
}
|
||||||
totalDistance += event.getDistanceBetweenMarks();
|
totalDistance += event.getDistanceBetweenMarks();
|
||||||
}
|
}
|
||||||
// There are no more marks after this event
|
|
||||||
// else{
|
|
||||||
// Event event = new Event(time, boat, marks.get(i));
|
|
||||||
// events.put(boat, new ArrayList<Event>(Arrays.asList(event)));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates how far a boat has travelled in meters
|
|
||||||
*
|
|
||||||
* @param velocity the velocity of boat
|
|
||||||
* @return a float number of distance the boat has been travelled
|
|
||||||
*/
|
|
||||||
public float getDistanceTravelled(long velocity) {
|
|
||||||
long timeDiff = System.currentTimeMillis() - this.startTime;
|
|
||||||
long timeElapse = (long) (timeDiff / 1000 * this.timeScale);
|
|
||||||
return timeElapse * velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over events in the race and print the
|
* Starts a race and generates all events for the race.
|
||||||
* 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;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the race and print each marker with the order
|
|
||||||
* in which the boats passed that marker
|
|
||||||
*/
|
*/
|
||||||
public void startRace() {
|
public void startRace() {
|
||||||
// record start time.
|
// record start time.
|
||||||
|
this.startTime = System.currentTimeMillis();
|
||||||
generateEvents();
|
generateEvents();
|
||||||
// this.startTime = System.currentTimeMillis();
|
|
||||||
// iterateEvents();
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Add a singleMark to the race (in order)
|
|
||||||
// * @param singleMark, the singleMark to add
|
|
||||||
// */
|
|
||||||
// public void addMark(SingleMark singleMark){
|
|
||||||
// this.marks.add(singleMark);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void addCourse(List<Mark> course){
|
public void addCourse(List<Mark> course) {
|
||||||
this.course = course;
|
this.course = course;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user