source: tmcsimulator-scriptbuilder/trunk/src/scriptbuilder/structures/ScriptIncident.java @ 117

Revision 117, 10.2 KB checked in by bmcguffin, 9 years ago (diff)

Redesigned the method by which the first event in an event is added to relative time 00:00:00.

Added a second timestamp panel to the incident editor screen, which displays absolute script time in red. The original timestamp panel displays time relative to the start of the incident, in black.

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.TreeMap;
9import scriptbuilder.structures.events.I_ScriptEvent;
10
11/**
12 * A script incident. It has an ID number, a name, and a description. It may
13 * contain several script events. It also has a color in the GUI window, and is
14 * collapsible. Incidents may start as soon as the script begins to run, or they
15 * can be offset from the start of the script.
16 *
17 * @author Greg Eddington <geddingt@calpoly.edu>
18 * @author Bryan McGuffin
19 * @version 2017/06/29
20 */
21public class ScriptIncident implements I_XML_Writable
22{
23
24    /**
25     * The moments in time which have associated events.
26     */
27    public TreeMap<Integer, TimeSlice> slices;
28
29    /**
30     * GUI display color of this slice.
31     */
32    public Color color;
33
34    /**
35     * ID number for this incident.
36     */
37    public int number;
38
39    /**
40     * Name of the incident.
41     */
42    public String name;
43
44    /**
45     * Description of the incident.
46     */
47    public String description;
48
49    /**
50     * Length, in seconds, of the incident.
51     */
52    public int length = 0;
53
54    /**
55     * If true, incident appears minimized.
56     */
57    public boolean collapsed = false;
58
59    /**
60     * Number of seconds between start of simulation and start of this incident.
61     */
62    public int offset = 0;
63
64    /**
65     * Start position of the latest timeslice.
66     */
67    private int latestStart = 0;
68
69    /**
70     * Number of events in this incident.
71     */
72    public int eventCount = 0;
73
74    SimulationScript script;
75
76    /**
77     * Basic constructor.
78     *
79     * @param number The incident ID number
80     * @param name The name of the incident
81     * @param description The description of the incident
82     * @param script The script object holding this incident
83     */
84    public ScriptIncident(int number, String name, String description,
85            SimulationScript script)
86    {
87        color = Color.BLACK;
88        this.number = number;
89        this.name = name;
90        this.description = description;
91        this.script = script;
92        slices = new TreeMap<Integer, TimeSlice>();
93    }
94
95    /**
96     * Constructor with color parameter.
97     *
98     * @param color The color to use in the GUI for this event
99     * @param number The incident ID number
100     * @param name The name of the incident
101     * @param description The description of the incident
102     * @param script The script object holding this incident
103     */
104    public ScriptIncident(Color color, int number, String name,
105            String description, SimulationScript script)
106    {
107        this.color = color;
108        this.number = number;
109        this.name = name;
110        this.description = description;
111        this.script = script;
112        slices = new TreeMap<Integer, TimeSlice>();
113    }
114
115    /**
116     * Constructor with color and offset parameters.
117     *
118     * @param color The color to use in the GUI for this event
119     * @param number The incident ID number
120     * @param name The name of the incident
121     * @param description The description of the incident
122     * @param script The script object holding this incident
123     * @param offset Number of seconds after 00:00:00 that this incident begins
124     */
125    public ScriptIncident(Color color, int number, String name,
126            String description, SimulationScript script,
127            int offset)
128    {
129        this.color = color;
130        this.number = number;
131        this.name = name;
132        this.description = description;
133        this.script = script;
134        slices = new TreeMap<Integer, TimeSlice>();
135        this.setOffset(offset);
136    }
137
138    /**
139     * Set whether or not the incident is fully visible or in a compacted state.
140     *
141     * @param collapsed True if the event is compacted
142     */
143    public void setCollapsed(boolean collapsed)
144    {
145        this.collapsed = collapsed;
146        script.update();
147    }
148
149    /**
150     * Set the delay time between the start of the script and the start of this
151     * incident.
152     *
153     * @param offset Number of seconds after 00:00:00 that this incident begins
154     */
155    public void setOffset(int offset)
156    {
157        int old = this.offset;
158        this.offset = offset;
159        TreeMap<Integer, TimeSlice> newSlices = new TreeMap<Integer, TimeSlice>();
160
161        int latest = 0;
162
163        for (Integer k : slices.keySet())
164        {
165            newSlices.put(k + (offset - old), slices.get(k));
166            latest = k + (offset - old);
167        }
168
169        latestStart = latest;
170
171        for (TimeSlice ts : newSlices.values())
172        {
173            ts.shift(offset - old);
174        }
175
176        slices = newSlices;
177        updateLength();
178        script.update();
179    }
180
181    /**
182     * Add a new script event to this incident.
183     *
184     * @param ev The new event
185     * @param start Start time of this event, in seconds, from the beginning of
186     * the simulation
187     */
188    public void addNewEvent(I_ScriptEvent ev, int start)
189    {
190        //Check to see if there's already a timeslice here
191        TimeSlice t = slices.get(start);
192        //If not, make one; then, add the event to it
193        if (t == null)
194        {
195            t = new TimeSlice(start, this);
196            t.addEvent(ev);
197            slices.put(start, t);
198        }
199        else
200        {
201            t.addEvent(ev);
202        }
203        eventCount++;
204
205        //If this is the latest start time in the incident, update that number
206        if (start > latestStart)
207        {
208            latestStart = start;
209        }
210            //If this event is earlier than all previous events, or if there are
211        //no other events, the offset is equal to this event's start time
212        if (start < offset || eventCount == 1)
213        {
214            offset = start;
215            //System.out.println("Offset: " + offset);
216        }
217        updateLength();
218    }
219
220    /**
221     * Get an array of all valid timeSlices.
222     *
223     * @return List of timeSlices which are not null
224     */
225    public ArrayList<TimeSlice> getSlices()
226    {
227        ArrayList<TimeSlice> arr = new ArrayList<TimeSlice>();
228        for (int i = 0; i <= latestStart; i++)
229        {
230            TimeSlice ts = slices.get(i);
231            if (ts != null)
232            {
233                arr.add(ts);
234            }
235        }
236        return arr;
237    }
238
239    /**
240     * Write this incident, in proper XML form, to the file in question.
241     *
242     * @param f the destination savefile
243     */
244    public void saveIncidentToFile(File f)
245    {
246        try
247        {
248            f.createNewFile();
249
250            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
251            bw.write(this.toXML());
252            bw.flush();
253            bw.close();
254
255        }
256        catch (Exception ex)
257        {
258            System.out.println("ERROR SAVING SCRIPT");
259            ex.printStackTrace();
260        }
261    }
262
263    @Override
264    public String toXML()
265    {
266        String output = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
267        output += "<!DOCTYPE TMC_SCRIPT SYSTEM \"script.dtd\">\n";
268        output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.script.title + "\"");
269
270        for (TimeSlice slice : slices.values())
271        {
272            output += slice.toXML();
273        }
274        output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag);
275        return output;
276    }
277
278    void insertCadData(long currentEventTime, CadData cad)
279    {
280        int time = (int) currentEventTime;
281
282        TimeSlice slice;
283
284        if (slices.get(time) == null)
285        {
286            slices.put(time, new TimeSlice(time, this));
287        }
288        slice = slices.get(time);
289        slice.cadData = cad;
290    }
291
292    /**
293     * Update the offset and apparent length of this incident. The offset is the
294     * start time of the earliest event in the incident. The length is the time
295     * that the latest, longest-lasting event ends, minus the offset.
296     */
297    public void updateLength()
298    {
299        int lengthSoFar = 0;
300        for (int i = 0; i <= latestStart; i++)
301        {
302            TimeSlice ts = slices.get(i);
303            if (ts != null)
304            {
305                int reach = ts.getTime() + ts.getEffectiveDuration() - offset;
306                if (reach > lengthSoFar)
307                {
308                    lengthSoFar = reach;
309                }
310            }
311        }
312        length = lengthSoFar;
313    }
314
315    /**
316     * An event which is fired if the focused slice changes.
317     */
318    public static class SliceChangedEvent
319    {
320
321        /**
322         * The slice which has received focus in this event.
323         */
324        public TimeSlice slice;
325
326        SliceChangedEvent(TimeSlice slice)
327        {
328            this.slice = slice;
329        }
330    }
331
332    /**
333     * Update and cause the system to focus on the given timeslice.
334     *
335     * @param i Index of the slice to focus on
336     */
337    public void setSliceActive(int i)
338    {
339        if (this.slices.get(i) != null)
340        {
341            script.broadcastEvent(new SliceChangedEvent(this.slices.get(i)));
342        }
343    }
344
345    /**
346     * An event which is fired if the focused incident changes.
347     */
348    public static class IncidentFocusedEvent
349    {
350
351        /**
352         * The incident which has received focus in this event.
353         */
354        public ScriptIncident incident;
355
356        IncidentFocusedEvent(ScriptIncident i)
357        {
358            incident = i;
359        }
360    }
361
362    /**
363     * Update and cause the system to focus on this incident.
364     */
365    public void setIncidentActive()
366    {
367        script.broadcastEvent(new IncidentFocusedEvent(this));
368    }
369
370    /**
371     * String representation of this incident.
372     *
373     * @return String of the form "[Incident number] - [Incident name]"
374     */
375    @Override
376    public String toString()
377    {
378        return this.number + " - " + this.name;
379    }
380
381    /**
382     * Remove the timeslice at the given position.
383     *
384     * @param seconds absolute start time of the timeslice to remove.
385     */
386    public void removeTimeSlice(int seconds)
387    {
388        //remove the timeslice
389        this.slices.remove(seconds);
390
391        //offset is equivalent to start time of earliest slice
392        if (seconds == offset)
393        {
394            offset = slices.firstKey();
395        }
396        this.updateLength();
397        script.update();
398    }
399}
Note: See TracBrowser for help on using the repository browser.