mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Created a simple red blink on a top of a yacht given source id.
Created and updated methods reading yacht event packet to translate to collision alert on visualiser. WIP: sending yacht event packet to inform collision #story[1117]
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
package seng302.model.stream.parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores parsed data from yacht event code packet
|
||||||
|
*/
|
||||||
|
public class YachtEventData {
|
||||||
|
private Long subjectId;
|
||||||
|
private Long incidentId;
|
||||||
|
private Integer eventId;
|
||||||
|
private Long timeStamp;
|
||||||
|
|
||||||
|
public YachtEventData(Long subjectId, Long incidentId, Integer eventId, Long timeStamp) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
this.incidentId = incidentId;
|
||||||
|
this.eventId = eventId;
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSubjectId() {
|
||||||
|
return subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getIncidentId() {
|
||||||
|
return incidentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getEventId() {
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTimeStamp() {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,15 +13,12 @@ import org.xml.sax.InputSource;
|
|||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import seng302.model.stream.packets.PacketType;
|
import seng302.model.stream.packets.PacketType;
|
||||||
import seng302.model.stream.packets.StreamPacket;
|
import seng302.model.stream.packets.StreamPacket;
|
||||||
import seng302.model.stream.parser.MarkRoundingData;
|
import seng302.model.stream.parser.*;
|
||||||
import seng302.model.stream.parser.PositionUpdateData;
|
|
||||||
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
|
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
|
||||||
import seng302.model.stream.parser.RaceStartData;
|
|
||||||
import seng302.model.stream.parser.RaceStatusData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StreamParser is a utilities class for taking byte data, formatted according to the AC35
|
* StreamParser is a utilities class for taking byte data, formatted according to the AC35 streaming
|
||||||
* streaming protocol, and parsing it into basic data types or collections.
|
* protocol, and parsing it into basic data types or collections.
|
||||||
*
|
*
|
||||||
* Created by kre39 on 23/04/17.
|
* Created by kre39 on 23/04/17.
|
||||||
*/
|
*/
|
||||||
@@ -34,8 +31,9 @@ public class StreamParser {
|
|||||||
* @return the packet sequence number if the packet is of type HEARTBEAT, null otherwise.
|
* @return the packet sequence number if the packet is of type HEARTBEAT, null otherwise.
|
||||||
*/
|
*/
|
||||||
public static Long extractHeartBeat(StreamPacket packet) {
|
public static Long extractHeartBeat(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.HEARTBEAT)
|
if (packet.getType() != PacketType.HEARTBEAT) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
long heartbeat = bytesToLong(packet.getPayload());
|
long heartbeat = bytesToLong(packet.getPayload());
|
||||||
System.out.println("heartbeat = " + heartbeat);
|
System.out.println("heartbeat = " + heartbeat);
|
||||||
return heartbeat;
|
return heartbeat;
|
||||||
@@ -52,8 +50,9 @@ public class StreamParser {
|
|||||||
* containing the parsed packet data.
|
* containing the parsed packet data.
|
||||||
*/
|
*/
|
||||||
public static RaceStatusData extractRaceStatus(StreamPacket packet) {
|
public static RaceStatusData extractRaceStatus(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.RACE_STATUS)
|
if (packet.getType() != PacketType.RACE_STATUS) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
long currentTime = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long currentTime = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
@@ -70,7 +69,6 @@ public class StreamParser {
|
|||||||
windDir, rawWindSpeed, raceStatus, currentTime, expectedStartTime
|
windDir, rawWindSpeed, raceStatus, currentTime, expectedStartTime
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// long timeTillStart =
|
// long timeTillStart =
|
||||||
// ((new Date(expectedStartTime)).getTime() - (new Date(currentTime)).getTime()) / 1000;
|
// ((new Date(expectedStartTime)).getTime() - (new Date(currentTime)).getTime()) / 1000;
|
||||||
//
|
//
|
||||||
@@ -139,8 +137,9 @@ public class StreamParser {
|
|||||||
* DISPLAY_TEXT_MESSAGE.
|
* DISPLAY_TEXT_MESSAGE.
|
||||||
*/
|
*/
|
||||||
public static List<String> extractDisplayMessage(StreamPacket packet) {
|
public static List<String> extractDisplayMessage(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.DISPLAY_TEXT_MESSAGE)
|
if (packet.getType() != PacketType.DISPLAY_TEXT_MESSAGE) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
List<String> message = new ArrayList<>();
|
List<String> message = new ArrayList<>();
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
@@ -168,8 +167,9 @@ public class StreamParser {
|
|||||||
public static Document extractXmlMessage(StreamPacket packet) {
|
public static Document extractXmlMessage(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.RACE_XML &&
|
if (packet.getType() != PacketType.RACE_XML &&
|
||||||
packet.getType() != PacketType.REGATTA_XML &&
|
packet.getType() != PacketType.REGATTA_XML &&
|
||||||
packet.getType() != PacketType.BOAT_XML )
|
packet.getType() != PacketType.BOAT_XML) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageType = payload[9];
|
int messageType = payload[9];
|
||||||
@@ -194,8 +194,8 @@ public class StreamParser {
|
|||||||
* Extracts the race start status from the packet and returns it as a long array.
|
* Extracts the race start status from the packet and returns it as a long array.
|
||||||
*
|
*
|
||||||
* @param packet Packet parsed in to use the payload
|
* @param packet Packet parsed in to use the payload
|
||||||
* @return An array of form [raceID, raceStartTime, notificationType, timeStamp] or null if
|
* @return An array of form [raceID, raceStartTime, notificationType, timeStamp] or null if the
|
||||||
* the packet type is not of RACE_START_STATUS.
|
* packet type is not of RACE_START_STATUS.
|
||||||
*/
|
*/
|
||||||
public static RaceStartData extractRaceStartStatus(StreamPacket packet) {
|
public static RaceStartData extractRaceStartStatus(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.RACE_START_STATUS) {
|
if (packet.getType() != PacketType.RACE_START_STATUS) {
|
||||||
@@ -212,23 +212,25 @@ public class StreamParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the the byte array in a StreamPacket for yacht events to retrieve the necessary info
|
* Parses the the byte array in a StreamPacket for yacht events to retrieve the necessary info
|
||||||
* and returns it a an array of longs.
|
* and returns it as YachtEventData.
|
||||||
*
|
*
|
||||||
* @param packet Packet parsed in to use the payload
|
* @param packet Packet parsed in to use the payload
|
||||||
* @return the event data in the form [boatID, incidentID, eventID, timeStamp]. Returns null if
|
* @return the event data in the form of YachtEventData. Returns null if the packet is not of
|
||||||
* the packet is not of type YACHT_EVENT_CODE.
|
* type YACHT_EVENT_CODE.
|
||||||
*/
|
*/
|
||||||
public static long[] extractYachtEventCode(StreamPacket packet) {
|
public static YachtEventData extractYachtEventCode(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.YACHT_EVENT_CODE)
|
if (packet.getType() != PacketType.YACHT_EVENT_CODE) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
|
long ackNumber = bytesToLong(Arrays.copyOfRange(payload, 7, 9));
|
||||||
long raceId = bytesToLong(Arrays.copyOfRange(payload, 9, 13));
|
long raceId = bytesToLong(Arrays.copyOfRange(payload, 9, 13));
|
||||||
long subjectId = bytesToLong(Arrays.copyOfRange(payload, 13, 17));
|
long subjectId = bytesToLong(Arrays.copyOfRange(payload, 13, 17));
|
||||||
long incidentId = bytesToLong(Arrays.copyOfRange(payload, 17, 21));
|
long incidentId = bytesToLong(Arrays.copyOfRange(payload, 17, 21));
|
||||||
int eventId = payload[21];
|
int eventId = payload[21];
|
||||||
return new long[] {subjectId, incidentId, eventId, timeStamp};
|
return new YachtEventData(subjectId, incidentId, eventId, timeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -239,8 +241,9 @@ public class StreamParser {
|
|||||||
* Returns null if the packet is not of type YACHT_ACTION_CODE.
|
* Returns null if the packet is not of type YACHT_ACTION_CODE.
|
||||||
*/
|
*/
|
||||||
public static long[] extractYachtActionCode(StreamPacket packet) {
|
public static long[] extractYachtActionCode(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.YACHT_ACTION_CODE)
|
if (packet.getType() != PacketType.YACHT_ACTION_CODE) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
@@ -258,8 +261,9 @@ public class StreamParser {
|
|||||||
* CHATTER_TEXT.
|
* CHATTER_TEXT.
|
||||||
*/
|
*/
|
||||||
public static String extractChatterText(StreamPacket packet) {
|
public static String extractChatterText(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.CHATTER_TEXT)
|
if (packet.getType() != PacketType.CHATTER_TEXT) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
int messageType = payload[1];
|
int messageType = payload[1];
|
||||||
@@ -276,8 +280,9 @@ public class StreamParser {
|
|||||||
* is not of type BOAT_LOCATION.
|
* is not of type BOAT_LOCATION.
|
||||||
*/
|
*/
|
||||||
public static PositionUpdateData extractBoatLocation(StreamPacket packet) {
|
public static PositionUpdateData extractBoatLocation(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.BOAT_LOCATION)
|
if (packet.getType() != PacketType.BOAT_LOCATION) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int deviceType = (int) payload[15];
|
int deviceType = (int) payload[15];
|
||||||
long timeValid = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long timeValid = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
@@ -293,10 +298,11 @@ public class StreamParser {
|
|||||||
double groundSpeed = bytesToLong(Arrays.copyOfRange(payload, 38, 40)) / 1000.0;
|
double groundSpeed = bytesToLong(Arrays.copyOfRange(payload, 38, 40)) / 1000.0;
|
||||||
|
|
||||||
DeviceType type;
|
DeviceType type;
|
||||||
if (deviceType == 1)
|
if (deviceType == 1) {
|
||||||
type = DeviceType.YACHT_TYPE;
|
type = DeviceType.YACHT_TYPE;
|
||||||
else
|
} else {
|
||||||
type = DeviceType.MARK_TYPE;
|
type = DeviceType.MARK_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
return new PositionUpdateData((int) boatId, type, lat, lon, heading, groundSpeed);
|
return new PositionUpdateData((int) boatId, type, lat, lon, heading, groundSpeed);
|
||||||
}
|
}
|
||||||
@@ -309,8 +315,9 @@ public class StreamParser {
|
|||||||
* if packet is not of type MARK_ROUNDING.
|
* if packet is not of type MARK_ROUNDING.
|
||||||
*/
|
*/
|
||||||
public static MarkRoundingData extractMarkRounding(StreamPacket packet) {
|
public static MarkRoundingData extractMarkRounding(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.MARK_ROUNDING)
|
if (packet.getType() != PacketType.MARK_ROUNDING) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
@@ -325,16 +332,17 @@ public class StreamParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list containing the string value of data within the given stream packet for
|
* Returns a list containing the string value of data within the given stream packet for course
|
||||||
* course wind.
|
* wind.
|
||||||
*
|
*
|
||||||
* @param packet The packet containing the payload
|
* @param packet The packet containing the payload
|
||||||
* @return the string values of the wind packet. Returns null if the packet is not of type
|
* @return the string values of the wind packet. Returns null if the packet is not of type
|
||||||
* COURSE_WIND.
|
* COURSE_WIND.
|
||||||
*/
|
*/
|
||||||
public static List<String> extractCourseWind(StreamPacket packet) {
|
public static List<String> extractCourseWind(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.COURSE_WIND)
|
if (packet.getType() != PacketType.COURSE_WIND) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
int selectedWindId = payload[1];
|
int selectedWindId = payload[1];
|
||||||
@@ -366,13 +374,13 @@ public class StreamParser {
|
|||||||
* Returns the parsed data from a StreamPacket for average wind data.
|
* Returns the parsed data from a StreamPacket for average wind data.
|
||||||
*
|
*
|
||||||
* @param packet The packet containing the payload
|
* @param packet The packet containing the payload
|
||||||
* @return The wind data in the form
|
* @return The wind data in the form [rawPeriod, rawSamplePeriod, period2, speed2, period3,
|
||||||
* [rawPeriod, rawSamplePeriod, period2, speed2, period3, speed3, period4, speed4, timestamp]
|
* speed3, period4, speed4, timestamp] or null if the packet is not of type AVG_WIND.
|
||||||
* or null if the packet is not of type AVG_WIND.
|
|
||||||
*/
|
*/
|
||||||
public static long[] extractAvgWind(StreamPacket packet) {
|
public static long[] extractAvgWind(StreamPacket packet) {
|
||||||
if (packet.getType() != PacketType.AVG_WIND)
|
if (packet.getType() != PacketType.AVG_WIND) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
int messageVersionNo = payload[0];
|
int messageVersionNo = payload[0];
|
||||||
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
long timeStamp = bytesToLong(Arrays.copyOfRange(payload, 1, 7));
|
||||||
@@ -410,8 +418,7 @@ public class StreamParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* takes an array of up to 7 bytes and returns a positive
|
* takes an array of up to 7 bytes and returns a positive long constructed from the input bytes
|
||||||
* long constructed from the input bytes
|
|
||||||
*
|
*
|
||||||
* @param bytes the byte array to conver to Long
|
* @param bytes the byte array to conver to Long
|
||||||
* @return a positive long if there is less than 7 bytes -1 otherwise
|
* @return a positive long if there is less than 7 bytes -1 otherwise
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import seng302.model.stream.parser.MarkRoundingData;
|
|||||||
import seng302.model.stream.parser.PositionUpdateData;
|
import seng302.model.stream.parser.PositionUpdateData;
|
||||||
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
|
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
|
||||||
import seng302.model.stream.parser.RaceStatusData;
|
import seng302.model.stream.parser.RaceStatusData;
|
||||||
|
import seng302.model.stream.parser.YachtEventData;
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
import seng302.model.stream.xml.parser.RegattaXMLData;
|
import seng302.model.stream.xml.parser.RegattaXMLData;
|
||||||
import seng302.gameServer.server.messages.BoatActionMessage;
|
import seng302.gameServer.server.messages.BoatActionMessage;
|
||||||
@@ -117,7 +118,8 @@ public class GameClient {
|
|||||||
* @return the lobby controller.
|
* @return the lobby controller.
|
||||||
*/
|
*/
|
||||||
private LobbyController loadLobby() {
|
private LobbyController loadLobby() {
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(GameClient.class.getResource("/views/LobbyView.fxml"));
|
FXMLLoader fxmlLoader = new FXMLLoader(
|
||||||
|
GameClient.class.getResource("/views/LobbyView.fxml"));
|
||||||
try {
|
try {
|
||||||
holderPane.getChildren().clear();
|
holderPane.getChildren().clear();
|
||||||
holderPane.getChildren().add(fxmlLoader.load());
|
holderPane.getChildren().add(fxmlLoader.load());
|
||||||
@@ -200,14 +202,19 @@ public class GameClient {
|
|||||||
case MARK_ROUNDING:
|
case MARK_ROUNDING:
|
||||||
updateMarkRounding(StreamParser.extractMarkRounding(packet));
|
updateMarkRounding(StreamParser.extractMarkRounding(packet));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case YACHT_EVENT_CODE:
|
||||||
|
showCollisionAlert(StreamParser.extractYachtEventCode(packet));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startRaceIfAllDataReceived() {
|
private void startRaceIfAllDataReceived() {
|
||||||
if (allXMLReceived() && raceView == null)
|
if (allXMLReceived() && raceView == null) {
|
||||||
loadRaceView();
|
loadRaceView();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean allXMLReceived() {
|
private boolean allXMLReceived() {
|
||||||
return courseData != null && allBoatsMap != null && regattaData != null;
|
return courseData != null && allBoatsMap != null && regattaData != null;
|
||||||
@@ -263,9 +270,10 @@ public class GameClient {
|
|||||||
int placing = 1;
|
int placing = 1;
|
||||||
for (Yacht otherYacht : allBoatsMap.values()) {
|
for (Yacht otherYacht : allBoatsMap.values()) {
|
||||||
if (otherYacht.getSourceId() != boatData[0] &&
|
if (otherYacht.getSourceId() != boatData[0] &&
|
||||||
yacht.getLegNumber() <= otherYacht.getLegNumber())
|
yacht.getLegNumber() <= otherYacht.getLegNumber()) {
|
||||||
placing++;
|
placing++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
yacht.setPositionInteger(placing);
|
yacht.setPositionInteger(placing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,6 +287,7 @@ public class GameClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the key-pressed event from the text field.
|
* Handle the key-pressed event from the text field.
|
||||||
|
*
|
||||||
* @param e The key event triggering this call
|
* @param e The key event triggering this call
|
||||||
*/
|
*/
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
@@ -328,4 +337,14 @@ public class GameClient {
|
|||||||
public RaceXMLData getCourseData() {
|
public RaceXMLData getCourseData() {
|
||||||
return courseData;
|
return courseData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells race view to show a collision animation.
|
||||||
|
*/
|
||||||
|
private void showCollisionAlert(YachtEventData yachtEventData) {
|
||||||
|
// 1 is used by team 28 to show collision
|
||||||
|
if (yachtEventData.getEventId() == 1) {
|
||||||
|
raceView.showCollision(yachtEventData.getSubjectId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,14 @@ import java.util.Comparator;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javafx.animation.Animation;
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.AnimationTimer;
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
@@ -17,8 +22,10 @@ import javafx.scene.layout.AnchorPane;
|
|||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.scene.shape.Polygon;
|
import javafx.scene.shape.Polygon;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.util.Duration;
|
||||||
import seng302.model.Colors;
|
import seng302.model.Colors;
|
||||||
import seng302.model.GeoPoint;
|
import seng302.model.GeoPoint;
|
||||||
import seng302.model.Limit;
|
import seng302.model.Limit;
|
||||||
@@ -114,7 +121,8 @@ public class GameView extends Pane {
|
|||||||
if (lastTime == 0) {
|
if (lastTime == 0) {
|
||||||
lastTime = now;
|
lastTime = now;
|
||||||
} else {
|
} else {
|
||||||
if (now - lastTime >= (1e8 / 60)) { //Fix for framerate going above 60 when minimized
|
if (now - lastTime >= (1e8
|
||||||
|
/ 60)) { //Fix for framerate going above 60 when minimized
|
||||||
long oldFrameTime = frameTimes[frameTimeIndex];
|
long oldFrameTime = frameTimes[frameTimeIndex];
|
||||||
frameTimes[frameTimeIndex] = now;
|
frameTimes[frameTimeIndex] = now;
|
||||||
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length;
|
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length;
|
||||||
@@ -142,8 +150,8 @@ public class GameView extends Pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First find the top right and bottom left points' geo locations, then retrieve
|
* First find the top right and bottom left points' geo locations, then retrieve map from google
|
||||||
* map from google to display on image view. - Haoming 22/5/2017
|
* to display on image view. - Haoming 22/5/2017
|
||||||
*/
|
*/
|
||||||
private void drawGoogleMap() {
|
private void drawGoogleMap() {
|
||||||
findMetersPerPixel();
|
findMetersPerPixel();
|
||||||
@@ -308,6 +316,7 @@ public class GameView extends Pane {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws all the boats.
|
* Draws all the boats.
|
||||||
|
*
|
||||||
* @param yachts The yachts to set in the race
|
* @param yachts The yachts to set in the race
|
||||||
*/
|
*/
|
||||||
public void setBoats(List<Yacht> yachts) {
|
public void setBoats(List<Yacht> yachts) {
|
||||||
@@ -383,8 +392,8 @@ public class GameView extends Pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the point
|
* Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the point with
|
||||||
* with the leftmost point, rightmost point, southern most point and northern most point
|
* the leftmost point, rightmost point, southern most point and northern most point
|
||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private void findMinMaxPoint(List<GeoPoint> points) {
|
private void findMinMaxPoint(List<GeoPoint> points) {
|
||||||
@@ -418,13 +427,17 @@ public class GameView extends Pane {
|
|||||||
referenceAngle = Math.abs(
|
referenceAngle = Math.abs(
|
||||||
GeoUtility.getBearingRad(referencePoint, minLonPoint)
|
GeoUtility.getBearingRad(referencePoint, minLonPoint)
|
||||||
);
|
);
|
||||||
referencePointX = bufferSize + distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility.getDistance(referencePoint, minLonPoint);
|
referencePointX =
|
||||||
|
bufferSize + distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility
|
||||||
|
.getDistance(referencePoint, minLonPoint);
|
||||||
referenceAngle = Math.abs(GeoUtility.getDistance(referencePoint, maxLatPoint));
|
referenceAngle = Math.abs(GeoUtility.getDistance(referencePoint, maxLatPoint));
|
||||||
referencePointY = canvasHeight - (bufferSize + bufferSize);
|
referencePointY = canvasHeight - (bufferSize + bufferSize);
|
||||||
referencePointY -= distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility.getDistance(referencePoint, maxLatPoint);
|
referencePointY -= distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility
|
||||||
|
.getDistance(referencePoint, maxLatPoint);
|
||||||
referencePointY = referencePointY / 2;
|
referencePointY = referencePointY / 2;
|
||||||
referencePointY += bufferSize;
|
referencePointY += bufferSize;
|
||||||
referencePointY += distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility.getDistance(referencePoint, maxLatPoint);
|
referencePointY += distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility
|
||||||
|
.getDistance(referencePoint, maxLatPoint);
|
||||||
} else {
|
} else {
|
||||||
referencePointY = canvasHeight - bufferSize;
|
referencePointY = canvasHeight - bufferSize;
|
||||||
referenceAngle = Math.abs(
|
referenceAngle = Math.abs(
|
||||||
@@ -433,8 +446,11 @@ public class GameView extends Pane {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
referencePointX = bufferSize;
|
referencePointX = bufferSize;
|
||||||
referencePointX += distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility.getDistance(referencePoint, minLonPoint);
|
referencePointX += distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility
|
||||||
referencePointX += ((canvasWidth - (bufferSize + bufferSize)) - (minLonToMaxLon * distanceScaleFactor)) / 2;
|
.getDistance(referencePoint, minLonPoint);
|
||||||
|
referencePointX +=
|
||||||
|
((canvasWidth - (bufferSize + bufferSize)) - (minLonToMaxLon * distanceScaleFactor))
|
||||||
|
/ 2;
|
||||||
}
|
}
|
||||||
if (horizontalInversion) {
|
if (horizontalInversion) {
|
||||||
referencePointX = canvasWidth - bufferSize - (referencePointX - bufferSize);
|
referencePointX = canvasWidth - bufferSize - (referencePointX - bufferSize);
|
||||||
@@ -494,20 +510,28 @@ public class GameView extends Pane {
|
|||||||
);
|
);
|
||||||
// System.out.println("distanceFromReference = " + distanceFromReference);
|
// System.out.println("distanceFromReference = " + distanceFromReference);
|
||||||
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
|
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
|
||||||
xAxisLocation += Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
xAxisLocation += Math
|
||||||
yAxisLocation -= Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
|
yAxisLocation -= Math
|
||||||
|
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
} else if (angleFromReference >= 0) {
|
} else if (angleFromReference >= 0) {
|
||||||
angleFromReference = angleFromReference - Math.PI / 2;
|
angleFromReference = angleFromReference - Math.PI / 2;
|
||||||
xAxisLocation += Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
xAxisLocation += Math
|
||||||
yAxisLocation += Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
|
yAxisLocation += Math
|
||||||
|
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
} else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) {
|
} else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) {
|
||||||
angleFromReference = Math.abs(angleFromReference);
|
angleFromReference = Math.abs(angleFromReference);
|
||||||
xAxisLocation -= Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
xAxisLocation -= Math
|
||||||
yAxisLocation -= Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
|
yAxisLocation -= Math
|
||||||
|
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
} else {
|
} else {
|
||||||
angleFromReference = Math.abs(angleFromReference) - Math.PI / 2;
|
angleFromReference = Math.abs(angleFromReference) - Math.PI / 2;
|
||||||
xAxisLocation -= Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
xAxisLocation -= Math
|
||||||
yAxisLocation += Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
|
yAxisLocation += Math
|
||||||
|
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
}
|
}
|
||||||
if (horizontalInversion) {
|
if (horizontalInversion) {
|
||||||
xAxisLocation = canvasWidth - bufferSize - (xAxisLocation - bufferSize);
|
xAxisLocation = canvasWidth - bufferSize - (xAxisLocation - bufferSize);
|
||||||
@@ -583,4 +607,35 @@ public class GameView extends Pane {
|
|||||||
gameObjects.add(annotations.get(playerYacht));
|
gameObjects.add(annotations.get(playerYacht));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given yacht geopoint by race view controller, drawCollision will calculate canvas X and Y and
|
||||||
|
* display a flashing red circle on collision point.
|
||||||
|
*
|
||||||
|
* @param collisionPoint yacht collision point
|
||||||
|
*/
|
||||||
|
public void drawCollision(GeoPoint collisionPoint) {
|
||||||
|
System.out.println("ran");
|
||||||
|
Point2D point = findScaledXY(collisionPoint);
|
||||||
|
Circle circle = new Circle(point.getX(), point.getY(), 10.0, Color.RED);
|
||||||
|
gameObjects.add(circle);
|
||||||
|
|
||||||
|
Timeline timeline = new Timeline();
|
||||||
|
timeline.setCycleCount(1);
|
||||||
|
EventHandler<ActionEvent> blink = (ActionEvent event) -> {
|
||||||
|
if (circle.getFill() == Color.RED) {
|
||||||
|
circle.setFill(Color.TRANSPARENT);
|
||||||
|
} else {
|
||||||
|
circle.setFill(Color.RED);
|
||||||
|
}
|
||||||
|
System.out.println("beep boop");
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyFrame keyframe = new KeyFrame(Duration.millis(200), blink);
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(keyframe);
|
||||||
|
timeline.play();
|
||||||
|
|
||||||
|
// gameObjects.remove(circle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to add any new yachts into the race that may have started late or not have had data received yet
|
* Used to add any new yachts into the race that may have started late or not have had data
|
||||||
|
* received yet
|
||||||
*/
|
*/
|
||||||
private void updateSparkLine() {
|
private void updateSparkLine() {
|
||||||
// TODO: 2/08/17 there is about 0 chance of this working. Once we are keeping track of boat positions it can be fixed.
|
// TODO: 2/08/17 there is about 0 chance of this working. Once we are keeping track of boat positions it can be fixed.
|
||||||
@@ -248,7 +249,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
.filter(spark -> !raceSparkLine.getData().contains(spark))
|
.filter(spark -> !raceSparkLine.getData().contains(spark))
|
||||||
.forEach(spark -> {
|
.forEach(spark -> {
|
||||||
raceSparkLine.getData().add(spark);
|
raceSparkLine.getData().add(spark);
|
||||||
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
|
spark.getNode().lookup(".chart-series-line")
|
||||||
|
.setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -260,6 +262,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the yachts sparkline of the desired yacht and using the new leg number
|
* Updates the yachts sparkline of the desired yacht and using the new leg number
|
||||||
|
*
|
||||||
* @param yacht The yacht to be updated on the sparkline
|
* @param yacht The yacht to be updated on the sparkline
|
||||||
* @param legNumber the leg number that the position will be assigned to
|
* @param legNumber the leg number that the position will be assigned to
|
||||||
*/
|
*/
|
||||||
@@ -284,6 +287,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the rgb string of the yachts colour to use for the chart via css
|
* gets the rgb string of the yachts colour to use for the chart via css
|
||||||
|
*
|
||||||
* @param yachtId id of yacht passed in to get the yachts colour
|
* @param yachtId id of yacht passed in to get the yachts colour
|
||||||
* @return the colour as an rgb string
|
* @return the colour as an rgb string
|
||||||
*/
|
*/
|
||||||
@@ -302,8 +306,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises a timer which updates elements of the RaceView such as wind direction, yacht
|
* Initialises a timer which updates elements of the RaceView such as wind direction, yacht
|
||||||
* orderings etc.. which are dependent on the info from the stream parser constantly.
|
* orderings etc.. which are dependent on the info from the stream parser constantly. Updates of
|
||||||
* Updates of each of these attributes are called ONCE EACH SECOND
|
* each of these attributes are called ONCE EACH SECOND
|
||||||
*/
|
*/
|
||||||
private void initializeUpdateTimer() {
|
private void initializeUpdateTimer() {
|
||||||
timer.scheduleAtFixedRate(new TimerTask() {
|
timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
@@ -318,9 +322,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all corners until ones SeqID matches with the yachts current leg number.
|
* Iterates over all corners until ones SeqID matches with the yachts current leg number. Then
|
||||||
* Then it gets the compoundMarkID of that corner and uses it to fetch the appropriate mark
|
* it gets the compoundMarkID of that corner and uses it to fetch the appropriate mark Returns
|
||||||
* Returns null if no next mark found.
|
* null if no next mark found.
|
||||||
|
*
|
||||||
* @param bg The BoatGroup to find the next mark of
|
* @param bg The BoatGroup to find the next mark of
|
||||||
* @return The next Mark or null if none found
|
* @return The next Mark or null if none found
|
||||||
*/
|
*/
|
||||||
@@ -476,8 +481,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
|
|
||||||
private Point2D getPointRotation(Point2D ref, Double distance, Double angle) {
|
private Point2D getPointRotation(Point2D ref, Double distance, Double angle) {
|
||||||
Double newX = ref.getX() + (ref.getX() + distance -ref.getX())*Math.cos(angle) - (ref.getY() + distance -ref.getY())*Math.sin(angle);
|
Double newX = ref.getX() + (ref.getX() + distance - ref.getX()) * Math.cos(angle)
|
||||||
Double newY = ref.getY() + (ref.getX() + distance -ref.getX())*Math.sin(angle) + (ref.getY() + distance -ref.getY())*Math.cos(angle);
|
- (ref.getY() + distance - ref.getY()) * Math.sin(angle);
|
||||||
|
Double newY = ref.getY() + (ref.getX() + distance - ref.getX()) * Math.sin(angle)
|
||||||
|
+ (ref.getY() + distance - ref.getY()) * Math.cos(angle);
|
||||||
|
|
||||||
return new Point2D(newX, newY);
|
return new Point2D(newX, newY);
|
||||||
}
|
}
|
||||||
@@ -502,8 +509,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialised the combo box with any yachts currently in the race and adds the required listener
|
* Initialised the combo box with any yachts currently in the race and adds the required
|
||||||
* for the combobox to take action upon selection
|
* listener for the combobox to take action upon selection
|
||||||
*/
|
*/
|
||||||
private void initialiseBoatSelectionComboBox() {
|
private void initialiseBoatSelectionComboBox() {
|
||||||
yachtSelectionComboBox.setItems(
|
yachtSelectionComboBox.setItems(
|
||||||
@@ -595,4 +602,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
this.courseData = raceData;
|
this.courseData = raceData;
|
||||||
gameView.updateBorder(raceData.getCourseLimit());
|
gameView.updateBorder(raceData.getCourseLimit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by game client after receiving yacht event packet. Parameter subject id is the
|
||||||
|
* offending yacht. This function in turn will pass the yacht location to game view to display a
|
||||||
|
* collision alert.
|
||||||
|
*
|
||||||
|
* @param subjectId source id of offending yacht
|
||||||
|
*/
|
||||||
|
public void showCollision(Long subjectId) {
|
||||||
|
System.out.println("showcollision " + subjectId);
|
||||||
|
System.out.println(participants.get((int) (long) subjectId).getLocation());
|
||||||
|
gameView.drawCollision(participants.get((int) (long) subjectId).getLocation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user