package atmsdriver.model; import java.util.List; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * A Station is a simulation of a station in a traffic network. * * A Station (LDS) contains static meta data about the station, and two dynamic * attributes, MLTotVol and OppTotVol. * A single LDS contains multiple * LoopDetectors, which contain data for a single lane on one direction of the * freeway. A LDS is specific to a single freeway, direction, and postmile. * * @author John A. Torres * @version 9/10/2017 */ public class Station implements Comparable { /* Static Station meta data */ final private int lineNum; final private int ldsID; // double check final private int drop; final private String location; final private List loops; final private int highwayNum; final private double postmile; final private DIRECTION direction; /* Dynamic Station data */ private int MLTotVol; private int OppTotVol; /* Constructor */ public Station(int lineNum, int ldsID, int drop, String location, List loops, int hwy, DIRECTION direction, double postmile) { this.lineNum = lineNum; this.ldsID = ldsID; this.drop = drop; this.loops = loops; this.location = location; this.postmile = postmile; this.direction = direction; this.highwayNum = hwy; this.MLTotVol = 0; this.OppTotVol = 0; } public int getHighwayNumber() { return this.highwayNum; } public DIRECTION getDirection() { return this.direction; } /** * Returns the station metadata in condensed form. This is just a quick * script function to make a proper highway metadata configuration file, so * that we can read the network faster. * * @return station metadata */ public String getStationMeta() { StringBuilder build = new StringBuilder(); build.append(Integer.toString(this.ldsID)); build.append(" "); build.append(Integer.toString(this.drop)); build.append(" "); build.append(Integer.toString(this.highwayNum)); build.append(" "); build.append(this.direction.getLetter()); build.append(" "); build.append(Double.toString(this.postmile)); build.append(" "); build.append(Integer.toString(loops.size())); build.append(" "); build.append(this.location); build.append("\n"); for (LoopDetector loop : loops) { build.append(loop.getLoopMeta()); } return build.toString(); } public double getPostmile() { return postmile; } /** * Compare this Station to another by postmile. Note: This might be better * as a Comparator since it checks only one field. */ @Override public int compareTo(Object otherStation) { // check for identity if (this == otherStation) { return 0; } // check that Object is of type Station, if not throw exception if (!(otherStation instanceof Station)) { throw new ClassCastException("A Station object expected."); } // get difference of values double otherStationPostmile = ((Station) otherStation).getPostmile(); double val = this.postmile - otherStationPostmile; // set appropriate comparable return value int retval = 0; if (val > 0) { retval = 1; } else if (val < 0) { retval = -1; } return retval; } private static enum XML_TAGS { STATION("Station"), LDS_ID("LDS_ID"), LINE_NUM("Line_Num"), DROP("Drop"), LOOPS("Loops"), LOCATION("Location"), POST_MILE("Post_Mile"), DIRECTION("Direction"), FREEWAY("Freeway"), ML_TOT_VOL("ML_Tot_Vol"), OPP_TOT_VOL("Opp_Tot_Vol"); String tag; private XML_TAGS(String n) { tag = n; } } public void toXML(Element currElem) { Document theDoc = currElem.getOwnerDocument(); Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag); currElem.appendChild(stationElement); Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag); ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.ldsID))); stationElement.appendChild(ldsIDElement); Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag); lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineNum))); stationElement.appendChild(lineNumElement); Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag); dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop))); stationElement.appendChild(dropElement); Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag); locationElement.appendChild(theDoc.createTextNode(this.location)); stationElement.appendChild(locationElement); Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag); postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile))); stationElement.appendChild(postMileElement); Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag); directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter())); stationElement.appendChild(directionElement); Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag); freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.highwayNum))); stationElement.appendChild(freewayElement); Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag); mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol))); stationElement.appendChild(mlElement); Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag); oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol))); stationElement.appendChild(oppElement); Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag); stationElement.appendChild(loopsElement); for (LoopDetector loop : loops) { loop.toXML(loopsElement); } } /** * Enum for freeway direction. * * @author John A. Torres * @version 9/10/2017 */ public static enum DIRECTION { NORTH, SOUTH, EAST, WEST; // All the first letters of the values, in order. private static String allLetters = "NSEW"; /** * Return the first letter of this enum. * * @return String first letter of this enum. */ public String getLetter() { return this.toString().substring(0, 1); } /** * Returns a direction given its first character. * * @param letter the first character of a direction * @return direction corresponding to letter * @pre letter must be one of allLetters */ public static DIRECTION toDirection(String letter) { return values()[allLetters.indexOf(letter.charAt(0))]; } } }