Warning: Can't use blame annotator:
svn blame failed on trunk/src/scriptbuilder/structures/ScriptIncident.java: ("Can't find a temporary directory: Internal error", 20014)

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

Revision 195, 16.8 KB checked in by sdanthin, 6 years ago (diff)

SimulationScript?.java now prepends a zero if the number of the incident is less than 0, and starts incidents at index 1.
ScriptIncident?.java modified where the ID is set to accommodate for the above logic. see #222

RevLine 
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;
10import scriptbuilder.structures.ScriptEvent.ScriptEventType;
11import scriptbuilder.structures.events.I_AudioEvent;
12import scriptbuilder.structures.events.AudioEvent;
13
14/**
15 * A script incident. It has an ID number, a name, and a description. It may
16 * contain several script events. It also has a color in the GUI window, and is
17 * collapsible. Incidents may start as soon as the script begins to run, or they
18 * can be offset from the start of the script.
19 *
20 * @author Greg Eddington <geddingt@calpoly.edu>
21 * @author Bryan McGuffin
22 * @version 2017/06/29
23 */
24public class ScriptIncident implements I_XML_Writable
25{
26
27    /**
28     * The moments in time which have associated events.
29     */
30    public TreeMap<Integer, TimeSlice> slices;
31
32    /**
33     * GUI display color of this slice.
34     */
35    public Color color;
36
37    /**
38     * ID number for this incident.
39     */
40    public int number;
41
42    /**
43     * Name of the incident.
44     */
45    public String name;
46
47    /**
48     * Description of the incident.
49     */
50    public String description;
51   
52    /**
53     * Length, in seconds, of the incident.
54     */
55    public int length = 0;
56
57    /**
58     * If true, incident appears minimized.
59     */
60    public boolean collapsed = false;
61
62    /**
63     * Number of seconds between start of simulation and start of this incident.
64     */
65    public int offset = 0;
66
67    /**
68     * Start position of the latest timeslice.
69     */
70    private int latestStart = 0;
71
72    /**
73     * Number of events in this incident.
74     */
75    public int eventCount = 0;
76   
77    public int audioEventCount = 0;
78
79    public SimulationScript script;
80
81    /**
82     * Basic constructor.
83     *
84     * @param number The incident ID number
85     * @param name The name of the incident
86     * @param description The description of the incident
87     * @param script The script object holding this incident
88     */
89    public ScriptIncident(int number, String name, String description,
90            SimulationScript script)
91    {
92        color = Color.BLACK;
93        this.number = number;
94        this.name = name;
95        this.description = description;
96        this.script = script;
97        slices = new TreeMap<Integer, TimeSlice>();
98    }
99
100    /**
101     * Constructor with color parameter.
102     *
103     * @param color The color to use in the GUI for this event
104     * @param number The incident ID number
105     * @param name The name of the incident
106     * @param description The description of the incident
107     * @param script The script object holding this incident
108     */
109    public ScriptIncident(Color color, int number, String name,
110            String description, SimulationScript script)
111    {
112        this.color = color;
113        this.number = number;
114        this.name = name;
115        this.description = description;
116        this.script = script;
117        slices = new TreeMap<Integer, TimeSlice>();
118    }
119
120    /**
121     * Constructor with color and offset parameters.
122     *
123     * @param color The color to use in the GUI for this event
124     * @param number The incident ID number
125     * @param name The name of the incident
126     * @param description The description of the incident
127     * @param script The script object holding this incident
128     * @param offset Number of seconds after 00:00:00 that this incident begins
129     */
130    public ScriptIncident(Color color, int number, String name,
131            String description, SimulationScript script,
132            int offset)
133    {
134        this.color = color;
135        this.number = number;
136        this.name = name;
137        this.description = description;
138        this.script = script;
139        slices = new TreeMap<Integer, TimeSlice>();
140        this.setOffset(offset);
141    }
142   
143//    /**
144//     * Constructor with type and location parameters.
145//     * @param color
146//     * @param number
147//     * @param name
148//     * @param description
149//     * @param script
150//     * @param offset
151//     * @param type
152//     * @param location
153//     */
154//    public ScriptIncident(Color color, int number, String name,
155//            String description, SimulationScript script,
156//            int offset, String type, String location)
157//    {
158//        this.color = color;
159//        this.number = number;
160//        this.name = name;
161//        this.description = description;
162//        this.script = script;
163//        slices = new TreeMap<Integer, TimeSlice>();
164//        this.setOffset(offset);
165//        this.location = location;
166//        this.type = type;
167//        insertCadData(offset, new CadData(type,location));
168//    }
169
170    /**
171     * Set whether or not the incident is fully visible or in a compacted state.
172     *
173     * @param collapsed True if the event is compacted
174     */
175    public void setCollapsed(boolean collapsed)
176    {
177        this.collapsed = collapsed;
178        script.update();
179    }
180
181    /**
182     * Set the delay time between the start of the script and the start of this
183     * incident.
184     *
185     * @param offset Number of seconds after 00:00:00 that this incident begins
186     */
187    public void setOffset(int offset)
188    {
189        int old = this.offset;
190        this.offset = offset;
191        TreeMap<Integer, TimeSlice> newSlices = new TreeMap<Integer, TimeSlice>();
192
193        int latest = 0;
194
195        for (Integer k : slices.keySet())
196        {
197            newSlices.put(k + (offset - old), slices.get(k));
198            latest = k + (offset - old);
199        }
200
201        latestStart = latest;
202
203        for (TimeSlice ts : newSlices.values())
204        {
205            ts.shift(offset - old);
206        }
207
208        slices = newSlices;
209        updateLength();
210        script.update();
211    }
212    /**
213     * shifts all timeslices over by timeAdd amount starting at offset
214     * @param offset amount of time preceding where we want to move all of the following events.
215     * @param timeAdd amount of time added after offset
216     */
217    public void moveAllFollowingEvents(int offset, int timeAdd)
218    {
219        //int old = this.offset;
220        TreeMap<Integer, TimeSlice> newSlices = new TreeMap<Integer, TimeSlice>();
221
222       
223
224        for (Integer k : slices.keySet())
225        {
226            if(k<offset)
227            {
228                newSlices.put(k, slices.get(k));
229            }else
230            {
231                if(k+timeAdd >0)
232                {
233                    newSlices.put(k+timeAdd, slices.get(k));
234                }else
235                {
236                    newSlices.put(0, slices.get(k));
237                }
238               
239            }
240           
241           
242        }
243        for (TimeSlice ts : newSlices.values())
244        {
245            if(ts.getTime()>offset )
246            {
247                if( ts.getTime()+timeAdd>=0)
248                {
249                    ts.shift(timeAdd);
250                }
251                else
252                {
253                    ts.shift(-ts.getTime());
254                }
255               
256            }
257           
258        }
259        latestStart = (latestStart + timeAdd>0) ? latestStart + timeAdd: 0;
260        slices = newSlices;
261        updateLength();
262        script.update();
263    }
264    /**
265     * Adds an event to the correct timeslice when imported from an XML file.
266     * @param ev Event to be added to the timeslice.
267     * @param start Time when event needs to be added.
268     */
269    public void addNewEventFromXML(I_ScriptEvent ev, int start)
270    {
271        TimeSlice t = slices.get(start);
272        if(t==null)
273        {
274            t = new TimeSlice(start,this);
275            slices.put(start,t); 
276        }
277        t.addEvent(ev);
278        eventCount++;
279
280        //If this is the latest start time in the incident, update that number
281        if (start > latestStart)
282        {
283            latestStart = start;
284        }
285        //If this event is earlier than all previous events, or if there are
286        //no other events, the offset is equal to this event's start time
287        if (start < offset || eventCount == 1)
288        {
289            offset = start;
290            //System.out.println("Offset: " + offset);
291        }
292        updateLength();
293       
294    }
295    /**
296     * Add a new script event to this incident.
297     *
298     * @param ev The new event
299     * @param start Start time of this event, in seconds, from the beginning of
300     * the simulation
301     */
302    public void addNewEvent(I_ScriptEvent ev, int start)
303    {
304       
305       
306        //Check to see if there's already a timeslice here
307        TimeSlice t = slices.get(start);
308        //logic to check if the added event needs to also have an associated audio event.
309       
310        //If not, make one; then, add the event to it
311        if (t == null)
312        {
313            t = new TimeSlice(start, this);
314            slices.put(start, t);
315        }
316       
317        //checks if event to add is an I_AudioEvent and if the I_AudioEvent already has an AudioEvent to connect with it
318        if(ev instanceof I_AudioEvent){
319           
320           
321            //checks to see if there is already a filename in the I_AudioEvent, if so, set the AudioEvent ID. This is because the ID is not stored within the Script itself.
322            if(!((I_AudioEvent) ev).getFileName().equals(""))
323            {
324                ((I_AudioEvent) ev).setID(((I_AudioEvent) ev).getFileName().replaceAll(".mp3",""));
325            }
326            // checks to see if the I_AudioEvent already has an ID or not, if not, set one based on the audioEventCount.
327            if(((I_AudioEvent) ev).getID().equals(""))
328            {
329                audioEventCount++;
330                //ternary expression here just prepends an extra 0 to the ID of the audioEvent if its eventcount is less than 10
331                ((I_AudioEvent) ev).setID(number+((audioEventCount<10)? "0"+Integer.toString(audioEventCount):Integer.toString(audioEventCount)));
332               
333            }
334            if(t.getCorrespondingAudioEvent((I_AudioEvent)ev)==null)
335            {
336                AudioEvent audio = (AudioEvent) ScriptEvent.factoryByType(ScriptEventType.AUDIO_EVENT);
337
338                //sets AudioEvent id to id of I_AudioEvent
339                audio.id = ((I_AudioEvent) ev).getID();
340                //sets I_AudioEvent filename to the AudioEvent id
341                ((I_AudioEvent) ev).setFileName(audio.id+ ".mp3");
342                //sets the file path of the AudioEvent based on its internal id
343                audio.setAudioFilePathRelative();
344                //adds AudioEvent to the timeslice
345                t.addEvent(audio);
346            }
347           
348           
349        }
350        t.addEvent(ev);
351        eventCount++;
352
353        //If this is the latest start time in the incident, update that number
354        if (start > latestStart)
355        {
356            latestStart = start;
357        }
358        //If this event is earlier than all previous events, or if there are
359        //no other events, the offset is equal to this event's start time
360        if (start < offset || eventCount == 1)
361        {
362            offset = start;
363            //System.out.println("Offset: " + offset);
364        }
365        updateLength();
366    }
367
368    /**
369     * Get an array of all valid timeSlices.
370     *
371     * @return List of timeSlices which are not null
372     */
373    public ArrayList<TimeSlice> getSlices()
374    {
375        ArrayList<TimeSlice> arr = new ArrayList<TimeSlice>();
376        for (int i = 0; i <= latestStart; i++)
377        {
378            TimeSlice ts = slices.get(i);
379            if (ts != null)
380            {
381                arr.add(ts);
382            }
383        }
384        return arr;
385    }
386
387    /**
388     * Write this incident, in proper XML form, to the file in question.
389     *
390     * @param f the destination savefile
391     */
392    public void saveIncidentToFile(File f)
393    {
394        try
395        {
396            f.createNewFile();
397
398            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
399            bw.write(this.toXML());
400            bw.flush();
401            bw.close();
402
403        }
404        catch (Exception ex)
405        {
406            System.out.println("ERROR SAVING SCRIPT");
407            ex.printStackTrace();
408        }
409    }
410
411    @Override
412    public String toXML()
413    {
414        String output = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
415        output += XMLWriter.internalDTD();
416        output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.script.title + "\"");
417
418        for (TimeSlice slice : slices.values())
419        {
420            output += slice.toXML();
421        }
422        output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag);
423        return output;
424    }
425
426    public void insertCadData(long currentEventTime, CadData cad)
427    {
428        int time = (int) currentEventTime;
429
430        TimeSlice slice;
431
432        if (slices.get(time) == null)
433        {
434            slices.put(time, new TimeSlice(time, this));
435        }
436        slice = slices.get(time);
437        slice.cadData = cad;
438    }
439   
440    public CadData getCadData(long currentEventTime)
441    {
442        int time = (int) currentEventTime;
443        TimeSlice slice;
444       
445        slice = slices.get(time);
446        return slice.cadData;
447    }
448
449    /**
450     * Update the offset and apparent length of this incident. The offset is the
451     * start time of the earliest event in the incident. The length is the time
452     * that the latest, longest-lasting event ends, minus the offset.
453     */
454    public void updateLength()
455    {
456        int lengthSoFar = 0;
457        for (int i = 0; i <= latestStart; i++)
458        {
459            TimeSlice ts = slices.get(i);
460            if (ts != null)
461            {
462                int reach = ts.getTime() + ts.getEffectiveDuration() - offset;
463                if (reach > lengthSoFar)
464                {
465                    lengthSoFar = reach;
466                }
467            }
468        }
469        length = lengthSoFar;
470    }
471
472    /**
473     * An event which is fired if the focused slice changes.
474     */
475    public static class SliceChangedEvent
476    {
477
478        /**
479         * The slice which has received focus in this event.
480         */
481        public TimeSlice slice;
482
483        SliceChangedEvent(TimeSlice slice)
484        {
485            this.slice = slice;
486        }
487    }
488
489    /**
490     * Update and cause the system to focus on the given timeslice.
491     *
492     * @param i Index of the slice to focus on
493     */
494    public void setSliceActive(int i)
495    {
496        if (this.slices.get(i) != null)
497        {
498            script.broadcastEvent(new SliceChangedEvent(this.slices.get(i)));
499        }
500    }
501
502    /**
503     * An event which is fired if the focused incident changes.
504     */
505    public static class IncidentFocusedEvent
506    {
507
508        /**
509         * The incident which has received focus in this event.
510         */
511        public ScriptIncident incident;
512
513        IncidentFocusedEvent(ScriptIncident i)
514        {
515            incident = i;
516        }
517    }
518
519    /**
520     * Update and cause the system to focus on this incident.
521     */
522    public void setIncidentActive()
523    {
524        script.broadcastEvent(new IncidentFocusedEvent(this));
525    }
526
527    /**
528     * String representation of this incident.
529     *
530     * @return String of the form "[Incident number] - [Incident name]"
531     */
532    @Override
533    public String toString()
534    {
535        return this.number + " - " + this.name;
536    }
537
538    /**
539     * Remove the timeslice at the given position.
540     *
541     * @param seconds absolute start time of the timeslice to remove.
542     */
543    public void removeTimeSlice(int seconds)
544    {
545        //remove the timeslice
546        this.slices.remove(seconds);
547
548        //offset is equivalent to start time of earliest slice
549        if (seconds == offset)
550        {
551            if (slices.size() > 0)
552            {
553                offset = slices.firstKey();
554            }
555            else
556            {
557                offset = 0;
558            }
559        }
560        this.updateLength();
561        script.update();
562    }
563
564    /**
565     * Shifts the start time of a given event in this incident. The first event
566     * in the incident cannot be shifted.
567     *
568     * @param evt the event to be relocated
569     * @param oldTime the current start time of the event
570     * @param newTime the destination start time of the event
571     * @return true if the event is shifted over properly
572     * @pre the event in question exists
573     * @pre oldTime != newTime
574     */
575    public boolean changeEventStart(I_ScriptEvent evt, int oldTime, int newTime)
576    {
577        if (!(oldTime == 0 && newTime > oldTime))
578        {
579            if(evt instanceof I_AudioEvent)
580            {
581                //todo: need to figure out how to remove the audioEvent tha corresponds with the
582                this.slices.get(oldTime).removeCorrespondingAudioEvent((I_AudioEvent)evt);
583                //this.addNewEvent(evt,newTime)
584            }
585            this.slices.get(oldTime).events.remove(evt);
586            this.addNewEvent(evt, newTime);
587            return true;
588        }
589        return false;
590    }
591}
Note: See TracBrowser for help on using the repository browser.