package scriptbuilder.structures; import java.awt.Color; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.List; import java.util.Observable; import java.util.Vector; import javax.xml.parsers.SAXParserFactory; import scriptbuilder.structures.ScriptIncident.IncidentFocusedEvent; import scriptbuilder.structures.ScriptIncident.SliceChangedEvent; import scriptbuilder.structures.units.Unit; /** * Representation of the script to be run by the TMC Simulator. Holds a list of * incidents, which have start and end times and contain events. * * @author Greg Eddington * * @author Bryan McGuffin * @version 2017/06/22 */ public class SimulationScript extends Observable implements I_XML_Writable { /** * All default options for GUI colorings of incidents. */ public static final Color[] incidentColors = { Color.BLACK, Color.BLUE, Color.RED, new Color(0x38, 0x5E, 0x0F), new Color(128, 0, 128), Color.MAGENTA, new Color(0x23, 0x6B, 0x8E), Color.ORANGE, new Color(0x60, 0x33, 0x11), Color.GRAY }; /** * The file to which this script will be saved. */ public File saveFile = null; /** * The name of this script. */ public String title = ""; /** * The incidents displayed by the GUI. */ public List incidents; /** * The units which participate in Unit events. */ public List units; //Somewhere in the code, something assumes that the list of incidents //contains exactly 10 items. Until I can find and un-break that, this will do. private final int INCIDENT_FILL_COUNT = 10; /** * Number of incidents currently displayed. */ public int numberOfIncidents; /** * Script handler for parsing incoming XML files. */ private MyScriptHandler sh; //TODO: Pretty much everything in this constructor is dummy data. //Replace all of it. /** * Constructor. Backfill incident list with null objects, to be replaced * later. */ public SimulationScript() { sh = new MyScriptHandler(this); incidents = new ArrayList(); units = new ArrayList(); numberOfIncidents = 0; //Backfill with null incidents for (int i = numberOfIncidents; i < INCIDENT_FILL_COUNT; i++) { incidents.add(null); } } /** * Update the script's observers. * */ public void update() { // The script has changed, notify observers setChanged(); notifyObservers(this); } /** * Tell this script's observers that there is a new slice event. * * @param e the slice focus event */ public void broadcastEvent(SliceChangedEvent e) { // The slice focus has changed; pass the message setChanged(); notifyObservers(e); } /** * Tell this script's observers that there is a new slice event. * * @param e the incident focus event */ public void broadcastEvent(IncidentFocusedEvent e) { // The slice focus has changed; pass the message setChanged(); notifyObservers(e); } /** * Load in an existing script from an XML file. * * @param f the file containing the script */ public void loadScriptFromFile(File f) { try { SAXParserFactory.newInstance().newSAXParser().parse(f, sh); Vector inc = sh.getIncidents(); units = sh.getUnits(); for (ScriptIncident sci : inc) { addIncident(sci); } } catch (Exception ex) { System.out.println("ERROR LOADING SCRIPT"); ex.printStackTrace(); } this.update(); } /** * Add a new incident to the script. * * @param sci the incident to be added. * @return true if there was enough room to add this incident. */ public boolean addIncident(ScriptIncident sci) { if (numberOfIncidents < INCIDENT_FILL_COUNT) { incidents.set(numberOfIncidents++, sci); return true; } return false; } /** * Write this script, in proper XML format, to the file in question. * * @param f the destination savefile to be written. */ public void saveScriptToFile(File f) { try { f.createNewFile(); BufferedWriter bw = new BufferedWriter(new FileWriter(f)); bw.write(this.toXML()); bw.flush(); bw.close(); } catch (Exception ex) { System.out.println("ERROR SAVING SCRIPT"); ex.printStackTrace(); } } @Override public String toXML() { ArrayList slices = arrangeAllSlices(); String output = "\n"; output += "\n"; output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.title + "\""); if (units.size() > 0) { output += XMLWriter.openTag(ELEMENT.SCRIPT_DATA.tag); for (Unit unit : units) { output += unit.toXML(); } output += XMLWriter.closeTag(ELEMENT.SCRIPT_DATA.tag); } for (TimeSlice slice : slices) { output += slice.toXML(); } output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag); return output; } /** * Arranges all timeslices in this script in chronological order, then by * incident number. * * @return a list of all timeslices in the simulation script */ public ArrayList arrangeAllSlices() { ArrayList list = new ArrayList(); int length = absoluteLength(); for (int i = 0; i < length; i++) { for (ScriptIncident inc : incidents) { if (inc != null && inc.slices.get(i) != null) { list.add(inc.slices.get(i)); } } } return list; } /** * Gets the total length of the simulation in seconds. * * @return */ public int absoluteLength() { int length = 0; for (ScriptIncident inc : incidents) { if (inc != null) { inc.updateLength(); int currentLength = inc.length + inc.offset; if (currentLength > length) { length = currentLength; } } } return length; } /** * Counts the number of incidents currently running. * * @return the number of non-null incidents currently in the script. A * number between 0 and INCIDENT_FILL_COUNT, inclusive. */ public int incidentCount() { int count = 0; for (ScriptIncident inc : incidents) { if (inc != null) { count++; } } return count; } }