Updated start screen team list to show position in race. Created Yacht class to replace Boat class. Removed Boat class from XMLParser. Removed unused BoatParser.java.

#story[572]
This commit is contained in:
Zhi You Tan
2017-05-04 04:16:16 +12:00
parent 145d59df45
commit 07234ee33a
7 changed files with 229 additions and 169 deletions
@@ -14,6 +14,7 @@ import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane; 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 seng302.models.Yacht;
import seng302.models.parsers.StreamParser; import seng302.models.parsers.StreamParser;
import seng302.models.parsers.XMLParser; import seng302.models.parsers.XMLParser;
@@ -34,16 +35,20 @@ public class Controller implements Initializable {
@FXML @FXML
private Button switchToRaceViewButton; private Button switchToRaceViewButton;
@FXML @FXML
private TableView<XMLParser.BoatXMLObject.Boat> teamList; private TableView<Yacht> teamList;
@FXML @FXML
private TableColumn<XMLParser.BoatXMLObject.Boat, String> boatNameCol; private TableColumn<Yacht, String> boatNameCol;
@FXML @FXML
private TableColumn<XMLParser.BoatXMLObject.Boat, String> shortNameCol; private TableColumn<Yacht, String> shortNameCol;
@FXML @FXML
private TableColumn<XMLParser.BoatXMLObject.Boat, String> countryCol; private TableColumn<Yacht, String> countryCol;
@FXML
private TableColumn<Yacht, String> posCol;
@FXML @FXML
private Label realTime; private Label realTime;
private XMLParser xmlParser;
private void setContentPane(String jfxUrl){ private void setContentPane(String jfxUrl){
try{ try{
contentPane.getChildren().removeAll(); contentPane.getChildren().removeAll();
@@ -70,7 +75,7 @@ public class Controller implements Initializable {
*/ */
public void startStream() { public void startStream() {
if (StreamParser.isStreamStatus()) { if (StreamParser.isStreamStatus()) {
XMLParser xmlParser = StreamParser.getXmlObject(); xmlParser = StreamParser.getXmlObject();
streamButton.setVisible(false); streamButton.setVisible(false);
realTime.setVisible(true); realTime.setVisible(true);
timeTillLive.setVisible(true); timeTillLive.setVisible(true);
@@ -125,19 +130,32 @@ public class Controller implements Initializable {
} }
private void updateTeamList() { private void updateTeamList() {
ObservableList<XMLParser.BoatXMLObject.Boat> data = FXCollections.observableArrayList(); ObservableList<Yacht> data = FXCollections.observableArrayList();
teamList.setItems(data); teamList.setItems(data);
boatNameCol.setCellValueFactory( boatNameCol.setCellValueFactory(
new PropertyValueFactory<>("BoatName") new PropertyValueFactory<>("boatName")
); );
shortNameCol.setCellValueFactory( shortNameCol.setCellValueFactory(
new PropertyValueFactory<>("ShortName") new PropertyValueFactory<>("shortName")
); );
countryCol.setCellValueFactory( countryCol.setCellValueFactory(
new PropertyValueFactory<>("Country") new PropertyValueFactory<>("country")
); );
for (XMLParser.BoatXMLObject.Boat boat : StreamParser.getBoats()) { posCol.setCellValueFactory(
data.add(boat); new PropertyValueFactory<>("position")
);
if (StreamParser.isRaceStarted()) {
data.addAll(StreamParser.getBoatsPos().values());
} else {
for (Yacht boat : StreamParser.getBoats().values()) {
boat.setPosition("-");
data.add(boat);
}
} }
teamList.refresh();
// posCol.setSortType(TableColumn.SortType.ASCENDING);
// teamList.getSortOrder().add(posCol);
// posCol.setSortable(false);
} }
} }
-31
View File
@@ -21,10 +21,6 @@ public class Boat {
private int markLastPast; private int markLastPast;
private String shortName; private String shortName;
private int id; private int id;
// new attributes to boat
private int sourceID;
private String boatName;
private String country;
public Boat(String teamName) { public Boat(String teamName) {
this.teamName = teamName; this.teamName = teamName;
@@ -49,21 +45,6 @@ public class Boat {
this.id = id; this.id = id;
} }
/**
* New instance created by BoatsParser.
*
* @param sourceID source ID of the boat
* @param boatName full name of the boat
* @param shortName short name of the boat
* @param country country of the boat
*/
public Boat(int sourceID, String boatName, String shortName, String country) {
this.sourceID = sourceID;
this.boatName = boatName;
this.shortName = shortName;
this.country = country;
}
/** /**
* Returns the name of the team sailing the boat * Returns the name of the team sailing the boat
* *
@@ -159,16 +140,4 @@ public class Boat {
public int getId() { public int getId() {
return id; return id;
} }
public int getSourceID() {
return sourceID;
}
public String getBoatName() {
return boatName;
}
public String getCountry() {
return country;
}
} }
+114
View File
@@ -0,0 +1,114 @@
package seng302.models;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Yacht class for the racing boat.
*
* Class created to store more variables (eg. boat statuses) compared to the XMLParser boat class,
* also done outside Boat class because some old variables are not used anymore.
*/
public class Yacht {
private String boatType;
private Integer sourceID;
private String hullID; //matches HullNum in the XML spec.
private String shortName;
private String boatName;
private String country;
// Boat status
private Integer boatStatus;
private Integer legNumber;
private Integer penaltiesAwarded;
private Integer penaltiesServed;
private Long estimateTimeAtNextMark;
private Long estimateTimeAtFinish;
private String position;
public Yacht(String boatType, Integer sourceID, String hullID, String shortName, String boatName, String country) {
this.boatType = boatType;
this.sourceID = sourceID;
this.hullID = hullID;
this.shortName = shortName;
this.boatName = boatName;
this.country = country;
}
public String getBoatType() {
return boatType;
}
public Integer getSourceID() {
return sourceID;
}
public String getHullID() {
return hullID;
}
public String getShortName() {
return shortName;
}
public String getBoatName() {
return boatName;
}
public String getCountry() {
return country;
}
public Integer getBoatStatus() {
return boatStatus;
}
public void setBoatStatus(Integer boatStatus) {
this.boatStatus = boatStatus;
}
public Integer getLegNumber() {
return legNumber;
}
public void setLegNumber(Integer legNumber) {
this.legNumber = legNumber;
}
public Integer getPenaltiesAwarded() {
return penaltiesAwarded;
}
public void setPenaltiesAwarded(Integer penaltiesAwarded) {
this.penaltiesAwarded = penaltiesAwarded;
}
public Integer getPenaltiesServed() {
return penaltiesServed;
}
public void setPenaltiesServed(Integer penaltiesServed) {
this.penaltiesServed = penaltiesServed;
}
public Long getEstimateTimeAtNextMark() {
// DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
// return format.format(estimateTimeAtNextMark);
return estimateTimeAtNextMark;
}
public void setEstimateTimeAtNextMark(Long estimateTimeAtNextMark) {
this.estimateTimeAtNextMark = estimateTimeAtNextMark;
}
public String getEstimateTimeAtFinish() {
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
return format.format(estimateTimeAtFinish);
}
public void setEstimateTimeAtFinish(Long estimateTimeAtFinish) {
this.estimateTimeAtFinish = estimateTimeAtFinish;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
@@ -1,77 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import seng302.models.Boat;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Created by ryan_ on 30/04/2017.
*/
public class BoatsParser extends FileParser {
private Document doc;
public BoatsParser(String xmlString) {
this.doc = this.parseFile(xmlString);
}
/**
* Create a boat instance from a given node if 'Type' is 'Yacht'
*
* @param node a boat node
* @return an instance of Boat
*/
private Boat parseBoat(Node node) {
try {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.getAttribute("Type").equals("Yacht")) {
String sourceID = element.getAttribute("SourceID");
String boatName = element.getAttribute("BoatName");
String shortName = element.getAttribute("ShortName");
String stoweName = element.getAttribute("StoweName");
String country = element.getAttribute("Country");
Boat boat = new Boat(Integer.parseInt(sourceID), boatName, shortName, country);
return boat;
}
} else {
throw new NoSuchElementException("Cannot generate a boat by given node");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Returns a list of boats from the xml.
*
* @return a list of boats
*/
public List<Boat> getBoats() {
ArrayList<Boat> boats = new ArrayList<>();
try {
NodeList nodes = this.doc.getElementsByTagName("Boat");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Boat boat = parseBoat(node);
if (!(boat == null)) {
boats.add(boat);
}
}
return boats;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
@@ -5,6 +5,7 @@ import javafx.geometry.Point3D;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.models.Yacht;
import seng302.models.parsers.packets.BoatPositionPacket; import seng302.models.parsers.packets.BoatPositionPacket;
import seng302.models.parsers.packets.StreamPacket; import seng302.models.parsers.packets.StreamPacket;
@@ -37,7 +38,8 @@ public class StreamParser extends Thread{
private static boolean raceFinished = false; private static boolean raceFinished = false;
private static boolean streamStatus = false; private static boolean streamStatus = false;
private static long timeSinceStart = -1; private static long timeSinceStart = -1;
private static List<XMLParser.BoatXMLObject.Boat> boats = new ArrayList<>(); private static Map<Integer, Yacht> boats = new HashMap<>();
private static Map<Long, Yacht> boatsPos = new TreeMap<>();
private static double windDirection = 0; private static double windDirection = 0;
private static String currentTimeString; private static String currentTimeString;
@@ -201,17 +203,33 @@ public class StreamParser extends Thread{
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22)); long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
int noBoats = payload[22]; int noBoats = payload[22];
int raceType = payload[23]; int raceType = payload[23];
ArrayList<String> boatStatuses = new ArrayList<>(); // ArrayList<String> boatStatuses = new ArrayList<>();
boatsPos = new TreeMap<>();
for (int i = 0; i < noBoats; i++){ for (int i = 0; i < noBoats; i++){
Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20))); Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
String boatStatus = "SourceID: " + boatStatusSourceID; Yacht boat = boats.get((int)(long) boatStatusSourceID);
boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)]; boat.setBoatStatus((int)payload[28 + (i * 20)]);
boatStatus += "\nLegNumber: " + (int)payload[29 + (i * 20)]; boat.setLegNumber((int)payload[29 + (i * 20)]);
boatStatus += "\nPenaltiesAwarded: " + (int)payload[29 + (i * 20)]; boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
boatStatus += "\nPenaltiesServed: " + (int)payload[30 + (i * 20)]; boat.setPenaltiesServed((int)payload[30 + (i * 20)]);
boatStatus += "\nEstTimeAtNextMark: " + bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20))); Long estTimeAtNextMark = bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
boatStatus += "\nEstTimeAtFinish: " + bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20))); boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
boatStatuses.add(boatStatus); Long estTimeAtFinish = bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
boat.setEstimateTimeAtFinish(estTimeAtFinish);
boatsPos.put(estTimeAtFinish, boat);
// String boatStatus = "SourceID: " + boatStatusSourceID;
// boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)];
// boatStatus += "\nLegNumber: " + (int)payload[29 + (i * 20)];
// boatStatus += "\nPenaltiesAwarded: " + (int)payload[29 + (i * 20)];
// boatStatus += "\nPenaltiesServed: " + (int)payload[30 + (i * 20)];
// boatStatus += "\nEstTimeAtNextMark: " + bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
// boatStatus += "\nEstTimeAtFinish: " + bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
// boatStatuses.add(boatStatus);
}
int pos = 1;
for (Yacht yacht : boatsPos.values()) {
yacht.setPosition(String.valueOf(pos));
pos++;
} }
} }
@@ -478,11 +496,11 @@ public class StreamParser extends Thread{
} }
/** /**
* return list of boats from the server * return a map of boats with sourceID and the boat
* *
* @return list of boats * @return map of boats
*/ */
public static List<XMLParser.BoatXMLObject.Boat> getBoats() { public static Map<Integer, Yacht> getBoats() {
return boats; return boats;
} }
@@ -513,5 +531,14 @@ public class StreamParser extends Thread{
public static String getCurrentTimeString() { public static String getCurrentTimeString() {
return currentTimeString; return currentTimeString;
} }
/**
* used in boat position since tree map can sort position efficiently.
*
* @return a map of time to finish and boat.
*/
public static Map<Long, Yacht> getBoatsPos() {
return boatsPos;
}
} }
@@ -4,9 +4,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import seng302.models.Yacht;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Class to create an XML object from the XML Packet Messages. * Class to create an XML object from the XML Packet Messages.
@@ -392,9 +395,9 @@ public class XMLParser {
private ArrayList<Double> zoneLimits;// will only contain 5 elements. Limits 1-5 private ArrayList<Double> zoneLimits;// will only contain 5 elements. Limits 1-5
//Boats //Boats
ArrayList<Boat> boats; ArrayList<Yacht> boats;
//Competing boats //Competing boats
List<Boat> competingBoats = new ArrayList<>(); Map<Integer, Yacht> competingBoats = new HashMap<>();
/** /**
* Constructor for a BoatXMLObject. * Constructor for a BoatXMLObject.
@@ -427,10 +430,16 @@ public class XMLParser {
for (int i = 0; i < boatsList.getLength(); i++) { for (int i = 0; i < boatsList.getLength(); i++) {
Node currentBoat = boatsList.item(i); Node currentBoat = boatsList.item(i);
if (currentBoat.getNodeName().equals("Boat")) { if (currentBoat.getNodeName().equals("Boat")) {
Boat boat = new Boat(currentBoat); // Boat boat = new Boat(currentBoat);
Yacht boat = new Yacht(getNodeAttributeString(currentBoat, "Type"),
getNodeAttributeInt(currentBoat, "SourceID"),
getNodeAttributeString(currentBoat, "HullNum"),
getNodeAttributeString(currentBoat, "ShortName"),
getNodeAttributeString(currentBoat, "BoatName"),
getNodeAttributeString(currentBoat, "Country"));
this.boats.add(boat); this.boats.add(boat);
if (boat.getBoatType().equals("Yacht")) { if (boat.getBoatType().equals("Yacht")) {
competingBoats.add(boat); competingBoats.put(boat.getSourceID(), boat);
} }
} }
//System.out.println(this.getBoats()); //System.out.println(this.getBoats());
@@ -446,37 +455,37 @@ public class XMLParser {
public Double getMarkZoneSize() { return markZoneSize; } public Double getMarkZoneSize() { return markZoneSize; }
public Double getCourseZoneSize() { return courseZoneSize; } public Double getCourseZoneSize() { return courseZoneSize; }
public ArrayList<Double> getZoneLimits() { return zoneLimits; } public ArrayList<Double> getZoneLimits() { return zoneLimits; }
public ArrayList<Boat> getBoats() { return boats; } public ArrayList<Yacht> getBoats() { return boats; }
public List<Boat> getCompetingBoats() { public Map<Integer, Yacht> getCompetingBoats() {
return competingBoats; return competingBoats;
} }
public class Boat { // public class Boat {
//
private String boatType; // private String boatType;
private Integer sourceID; // private Integer sourceID;
private String hullID; //matches HullNum in the XML spec. // private String hullID; //matches HullNum in the XML spec.
private String shortName; // private String shortName;
private String boatName; // private String boatName;
private String country; // private String country;
//
Boat(Node boatNode) { // Boat(Node boatNode) {
this.boatType = getNodeAttributeString(boatNode, "Type"); // this.boatType = getNodeAttributeString(boatNode, "Type");
this.sourceID = getNodeAttributeInt(boatNode, "SourceID"); // this.sourceID = getNodeAttributeInt(boatNode, "SourceID");
this.hullID = getNodeAttributeString(boatNode, "HullNum"); // this.hullID = getNodeAttributeString(boatNode, "HullNum");
this.shortName = getNodeAttributeString(boatNode, "ShortName"); // this.shortName = getNodeAttributeString(boatNode, "ShortName");
this.boatName = getNodeAttributeString(boatNode, "BoatName"); // this.boatName = getNodeAttributeString(boatNode, "BoatName");
this.country = getNodeAttributeString(boatNode, "Country"); // this.country = getNodeAttributeString(boatNode, "Country");
} // }
//
public String getBoatType() { return boatType; } // public String getBoatType() { return boatType; }
public Integer getSourceID() { return sourceID; } // public Integer getSourceID() { return sourceID; }
public String getHullID() { return hullID; } // public String getHullID() { return hullID; }
public String getShortName() { return shortName; } // public String getShortName() { return shortName; }
public String getBoatName() { return boatName; } // public String getBoatName() { return boatName; }
public String getCountry() { return country; } // public String getCountry() { return country; }
//
} // }
} }
+5 -5
View File
@@ -46,17 +46,17 @@
</Label> </Label>
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" /> <Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
<Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="TOP" /> <Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="TOP" />
<TableView fx:id="teamList" maxWidth="510.0" prefHeight="200.0" prefWidth="210.0" GridPane.halignment="CENTER" GridPane.rowIndex="5"> <TableView fx:id="teamList" maxWidth="500.0" prefHeight="200.0" prefWidth="210.0" GridPane.halignment="CENTER" GridPane.rowIndex="5">
<columns> <columns>
<TableColumn fx:id="boatNameCol" editable="false" prefWidth="250.0" sortable="false" text="Boat Name" /> <TableColumn fx:id="posCol" editable="false" maxWidth="74.0" minWidth="74.0" prefWidth="74.0" resizable="false" sortable="false" text="Position" />
<TableColumn fx:id="shortNameCol" editable="false" prefWidth="125.0" sortable="false" text="Short Name" /> <TableColumn fx:id="boatNameCol" editable="false" maxWidth="171.0" minWidth="171.0" prefWidth="171.0" resizable="false" sortable="false" text="Boat Name" />
<TableColumn fx:id="countryCol" editable="false" prefWidth="125.0" sortable="false" text="Country" /> <TableColumn fx:id="shortNameCol" editable="false" maxWidth="107.0" minWidth="107.0" prefWidth="107.0" resizable="false" sortable="false" text="Short Name" />
<TableColumn fx:id="countryCol" editable="false" maxWidth="147.0" minWidth="147.0" prefWidth="147.0" resizable="false" sortable="false" text="Country" />
</columns> </columns>
<GridPane.margin> <GridPane.margin>
<Insets /> <Insets />
</GridPane.margin> </GridPane.margin>
</TableView> </TableView>
<Label text="*Team position in table do not correspond to race position" GridPane.halignment="CENTER" GridPane.rowIndex="6" GridPane.valignment="TOP" />
<Label fx:id="realTime" text="Local time" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" /> <Label fx:id="realTime" text="Local time" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
</children> </children>
</GridPane> </GridPane>