Reformatted and refactored the canvas controller

#fix #refactor #story[377]
This commit is contained in:
Haoming Yin
2017-03-20 17:23:33 +13:00
parent 3b8dd11758
commit ee34e5028f
3 changed files with 109 additions and 203 deletions
@@ -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,13 +28,15 @@ 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();
@@ -40,29 +46,7 @@ public class CanvasController {
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) {
@@ -71,6 +55,10 @@ public class CanvasController {
drawBoats();
}
};
generateTimeline();
// starts the timer and reads events from each boat's time line
timer.start();
for (TimelineInfo timelineInfo : timelineInfos.values()) {
Timeline timeline = timelineInfo.getTimeline();
@@ -78,6 +66,36 @@ public class CanvasController {
}
}
/**
* 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);
@@ -85,42 +103,54 @@ public class CanvasController {
}
}
/**
* 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);
}
/**
* Draws the course.
*/
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
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);
}
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);
}
}
/**
* Draw a gate mark which contains two single marks
*
* @param gateMark
*/
private void drawGateMark(GateMark gateMark) {
drawSingleMark(gateMark.getSingleMark1());
drawSingleMark(gateMark.getSingleMark2());
}
}
+2 -2
View File
@@ -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.");
+9 -133
View File
@@ -1,19 +1,18 @@
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
* 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;
@@ -21,26 +20,9 @@ public class 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
@@ -94,37 +67,6 @@ public class Race {
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
*
@@ -138,14 +80,13 @@ 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());
Double time = (1000 * totalDistance / boat.getVelocity());
// If there are singleMarks after this event
if (i < numberOfMarks - 1) {
@@ -155,88 +96,23 @@ public class Race {
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) {
this.course = course;