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.paint.Color;
|
||||
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.Mark;
|
||||
import seng302.models.mark.MarkType;
|
||||
import seng302.models.mark.SingleMark;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -24,103 +28,129 @@ import static java.lang.Math.abs;
|
||||
|
||||
/**
|
||||
* Created by ptg19 on 15/03/17.
|
||||
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
||||
*/
|
||||
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() {
|
||||
gc = canvas.getGraphicsContext2D();
|
||||
gc.scale(5,5);
|
||||
gc.scale(5, 5);
|
||||
RaceController raceController = new RaceController();
|
||||
raceController.initializeRace();
|
||||
race = raceController.getRace();
|
||||
timelineInfos = new HashMap<>();
|
||||
|
||||
HashMap<Boat, List> boat_events = race.getEvents();
|
||||
// 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));
|
||||
}
|
||||
|
||||
// overriding the handle so that it can clean canvas and redraw boats and course marks
|
||||
AnimationTimer timer = new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
gc.clearRect(0,0,760,360);
|
||||
gc.clearRect(0, 0, 760, 360);
|
||||
drawCourse();
|
||||
drawBoats();
|
||||
}
|
||||
};
|
||||
|
||||
generateTimeline();
|
||||
|
||||
// starts the timer and reads events from each boat's time line
|
||||
timer.start();
|
||||
for (TimelineInfo timelineInfo: timelineInfos.values()){
|
||||
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
||||
Timeline timeline = timelineInfo.getTimeline();
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
int diameter = 2;
|
||||
gc.setFill(color);
|
||||
gc.fillOval(x, y, diameter, diameter);
|
||||
}
|
||||
|
||||
private void drawCourse(){
|
||||
for (Mark mark: race.getCourse()){
|
||||
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);
|
||||
}
|
||||
|
||||
else if (mark.getMarkType() == MarkType.GATE_MARK){
|
||||
double x;
|
||||
double y;
|
||||
GateMark gateMark = (GateMark) mark;
|
||||
Mark mark1 = gateMark.getSingleMark1();
|
||||
Mark mark2 = gateMark.getSingleMark1();
|
||||
|
||||
x = abs(mark1.getLatitude() - 32.313291) * 1000; // to prevent negative longtitude
|
||||
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);
|
||||
/**
|
||||
* 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.fillOval(x, y, 2, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a gate mark which contains two single marks
|
||||
*
|
||||
* @param gateMark
|
||||
*/
|
||||
private void drawGateMark(GateMark gateMark) {
|
||||
drawSingleMark(gateMark.getSingleMark1());
|
||||
drawSingleMark(gateMark.getSingleMark2());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class OldApp {
|
||||
|
||||
// If race was created
|
||||
if (race != null) {
|
||||
race.displayStartingBoats();
|
||||
//race.displayStartingBoats();
|
||||
|
||||
System.out.println("\n\n");
|
||||
System.out.println("######################");
|
||||
@@ -96,7 +96,7 @@ public class OldApp {
|
||||
System.out.println("######################");
|
||||
|
||||
//race.showRaceMarkerResults();
|
||||
race.displayFinishingOrder();
|
||||
//race.displayFinishingOrder();
|
||||
|
||||
} else {
|
||||
System.out.println("There was an error creating the race. Exiting.");
|
||||
|
||||
@@ -1,46 +1,28 @@
|
||||
package seng302.models;
|
||||
|
||||
import seng302.models.mark.*;
|
||||
import seng302.models.mark.Mark;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
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 {
|
||||
private ArrayList<Boat> boats; // The boats in 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 List<Mark> course; // Marks in the race
|
||||
private int numberOfBoats = 0;
|
||||
private long startTime = 0;
|
||||
private double timeScale = 1;
|
||||
|
||||
/**
|
||||
* Race class containing the boats and legs in the race
|
||||
*/
|
||||
* Race class containing the boats and legs in the race
|
||||
*/
|
||||
public Race() {
|
||||
this.boats = new ArrayList<Boat>();
|
||||
this.finishingOrder = new ArrayList<Boat>();
|
||||
this.course = new ArrayList<Mark>();
|
||||
|
||||
// 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());
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
this.boats = new ArrayList<>();
|
||||
this.finishingOrder = new ArrayList<>();
|
||||
this.course = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +32,6 @@ public class Race {
|
||||
*/
|
||||
public void addBoat(Boat boat) {
|
||||
boats.add(boat);
|
||||
numberOfBoats += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,14 +57,6 @@ public class Race {
|
||||
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
|
||||
@@ -95,38 +68,7 @@ public class Race {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param timeScale
|
||||
*/
|
||||
@@ -138,107 +80,41 @@ public class Race {
|
||||
* Generate all events that will happen during the race.
|
||||
*/
|
||||
private void generateEvents() {
|
||||
//calculate the time every boat passes each leg, and create an event
|
||||
|
||||
for (Boat boat : this.boats) {
|
||||
double totalDistance = 0;
|
||||
int numberOfMarks = this.course.size();
|
||||
|
||||
for(int i = 0; i < numberOfMarks; i++){
|
||||
Double time = (Double) (1000 * totalDistance / boat.getVelocity());
|
||||
for (int i = 0; i < numberOfMarks; i++) {
|
||||
Double time = (1000 * totalDistance / boat.getVelocity());
|
||||
|
||||
// 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));
|
||||
|
||||
try {
|
||||
events.get(boat).add(event);
|
||||
|
||||
} catch (NullPointerException e) {
|
||||
events.put(boat, new ArrayList<Event>(Arrays.asList(event)));
|
||||
events.put(boat, new ArrayList<>(Arrays.asList(event)));
|
||||
}
|
||||
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
|
||||
* 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
|
||||
* Starts a race and generates all events for the race.
|
||||
*/
|
||||
public void startRace() {
|
||||
// record start time.
|
||||
this.startTime = System.currentTimeMillis();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user