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

Revision 83, 7.6 KB checked in by bmcguffin, 9 years ago (diff)

Fixed a bug in which adding a new incident didn't increment the counter for number of incidents, which in turn allowed incidents loaded from the palette to erroneously overwrite incidents previously created from scratch in the main window.

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