source: tmcsimulator-scriptbuilder/trunk/src/scriptbuilder/structures/SimulationScript.java @ 103

Revision 103, 7.3 KB checked in by bmcguffin, 9 years ago (diff)

Individual incident editor window now shows the relevant incident as though it started at 00:00:00. When window is closed, the incident is re-inserted into the correct position.

Line 
1package scriptbuilder.structures;
2
3import java.awt.Color;
4import java.io.BufferedWriter;
5import java.io.File;
6import java.io.FileWriter;
7import java.util.ArrayList;
8import java.util.List;
9import java.util.Observable;
10import java.util.Vector;
11import javax.xml.parsers.SAXParserFactory;
12import scriptbuilder.structures.ScriptIncident.IncidentFocusedEvent;
13import scriptbuilder.structures.ScriptIncident.SliceChangedEvent;
14import scriptbuilder.structures.units.Unit;
15
16/**
17 * Representation of the script to be run by the TMC Simulator. Holds a list of
18 * incidents, which have start and end times and contain events.
19 *
20 * @author Greg Eddington <geddingt@calpoly.edu>
21 *
22 * @author Bryan McGuffin <bmcguffi@calpoly.edu>
23 * @version 2017/06/22
24 */
25public class SimulationScript extends Observable implements I_XML_Writable
26{
27
28    /**
29     * All default options for GUI colorings of incidents.
30     */
31    public static final Color[] incidentColors =
32    {
33        Color.BLACK,
34        Color.BLUE,
35        Color.RED,
36        new Color(0x38, 0x5E, 0x0F),
37        new Color(128, 0, 128),
38        Color.MAGENTA,
39        new Color(0x23, 0x6B, 0x8E),
40        Color.ORANGE,
41        new Color(0x60, 0x33, 0x11),
42        Color.GRAY
43    };
44
45    /**
46     * The file to which this script will be saved.
47     */
48    public File saveFile = null;
49
50    /**
51     * The name of this script.
52     */
53    public String title = "";
54
55    /**
56     * The incidents displayed by the GUI.
57     */
58    public List<ScriptIncident> incidents;
59
60    /**
61     * The units which participate in Unit events.
62     */
63    public List<Unit> units;
64
65    //Somewhere in the code, something assumes that the list of incidents
66    //contains exactly 10 items. Until I can find and un-break that, this will do.
67    private final int INCIDENT_FILL_COUNT = 10;
68
69    /**
70     * Number of incidents currently displayed.
71     */
72    public int numberOfIncidents;
73
74    /**
75     * Script handler for parsing incoming XML files.
76     */
77    private MyScriptHandler sh;
78
79    //TODO: Pretty much everything in this constructor is dummy data.
80    //Replace all of it.
81    /**
82     * Constructor. Backfill incident list with null objects, to be replaced
83     * later.
84     */
85    public SimulationScript()
86    {
87        sh = new MyScriptHandler(this);
88        incidents = new ArrayList<ScriptIncident>();
89        units = new ArrayList<Unit>();
90        numberOfIncidents = 0;
91
92        //Backfill with null incidents
93        for (int i = numberOfIncidents; i < INCIDENT_FILL_COUNT; i++)
94        {
95            incidents.add(null);
96        }
97    }
98
99    /**
100     * Update the script's observers.
101     *
102     */
103    public void update()
104    {
105        // The script has changed, notify observers
106        setChanged();
107        notifyObservers(this);
108    }
109
110    /**
111     * Tell this script's observers that there is a new slice event.
112     *
113     * @param e the slice focus event
114     */
115    public void broadcastEvent(SliceChangedEvent e)
116    {
117        // The slice focus has changed; pass the message
118        setChanged();
119        notifyObservers(e);
120    }
121
122    /**
123     * Tell this script's observers that there is a new slice event.
124     *
125     * @param e the incident focus event
126     */
127    public void broadcastEvent(IncidentFocusedEvent e)
128    {
129        // The slice focus has changed; pass the message
130        setChanged();
131        notifyObservers(e);
132    }
133
134    /**
135     * Load in an existing script from an XML file.
136     *
137     * @param f the file containing the script
138     */
139    public void loadScriptFromFile(File f)
140    {
141        try
142        {
143
144            SAXParserFactory.newInstance().newSAXParser().parse(f, sh);
145
146            Vector<ScriptIncident> inc = sh.getIncidents();
147            units = sh.getUnits();
148            for (ScriptIncident sci : inc)
149            {
150                addIncident(sci);
151            }
152        }
153        catch (Exception ex)
154        {
155            System.out.println("ERROR LOADING SCRIPT");
156            ex.printStackTrace();
157        }
158        this.update();
159    }
160
161    /**
162     * Add a new incident to the script.
163     *
164     * @param sci the incident to be added.
165     * @return true if there was enough room to add this incident.
166     */
167    public boolean addIncident(ScriptIncident sci)
168    {
169        if (numberOfIncidents < INCIDENT_FILL_COUNT)
170        {
171            incidents.set(numberOfIncidents++, sci);
172            return true;
173        }
174        return false;
175    }
176
177    /**
178     * Write this script, in proper XML format, to the file in question.
179     *
180     * @param f the destination savefile to be written.
181     */
182    public void saveScriptToFile(File f)
183    {
184        try
185        {
186            f.createNewFile();
187
188            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
189            bw.write(this.toXML());
190            bw.flush();
191            bw.close();
192
193        }
194        catch (Exception ex)
195        {
196            System.out.println("ERROR SAVING SCRIPT");
197            ex.printStackTrace();
198        }
199    }
200
201    @Override
202    public String toXML()
203    {
204        ArrayList<TimeSlice> slices = arrangeAllSlices();
205        String output = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
206        output += "<!DOCTYPE TMC_SCRIPT SYSTEM \"script.dtd\">\n";
207        output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.title + "\"");
208
209        if (units.size() > 0)
210        {
211            output += XMLWriter.openTag(ELEMENT.SCRIPT_DATA.tag);
212            for (Unit unit : units)
213            {
214                output += unit.toXML();
215            }
216            output += XMLWriter.closeTag(ELEMENT.SCRIPT_DATA.tag);
217        }
218        for (TimeSlice slice : slices)
219        {
220            output += slice.toXML();
221        }
222        output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag);
223        return output;
224    }
225
226    /**
227     * Arranges all timeslices in this script in chronological order, then by
228     * incident number.
229     *
230     * @return a list of all timeslices in the simulation script
231     */
232    public ArrayList<TimeSlice> arrangeAllSlices()
233    {
234        ArrayList<TimeSlice> list = new ArrayList<TimeSlice>();
235        int length = absoluteLength();
236
237        for (int i = 0; i < length; i++)
238        {
239            for (ScriptIncident inc : incidents)
240            {
241
242                if (inc != null && inc.slices.get(i) != null)
243                {
244                    list.add(inc.slices.get(i));
245                }
246            }
247        }
248        return list;
249    }
250
251    /**
252     * Gets the total length of the simulation in seconds.
253     *
254     * @return
255     */
256    public int absoluteLength()
257    {
258        int length = 0;
259        for (ScriptIncident inc : incidents)
260        {
261            if (inc != null)
262            {
263                inc.updateLength();
264                int currentLength = inc.length + inc.offset;
265                if (currentLength > length)
266                {
267                    length = currentLength;
268                }
269            }
270        }
271        return length;
272    }
273
274    /**
275     * Counts the number of incidents currently running.
276     *
277     * @return the number of non-null incidents currently in the script. A
278     * number between 0 and INCIDENT_FILL_COUNT, inclusive.
279     */
280    public int incidentCount()
281    {
282        int count = 0;
283        for (ScriptIncident inc : incidents)
284        {
285            if (inc != null)
286            {
287                count++;
288            }
289        }
290        return count;
291    }
292
293}
Note: See TracBrowser for help on using the repository browser.