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

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

Revision 195, 13.9 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.io.IOException;
8import java.util.ArrayList;
9import java.util.List;
10import java.util.Observable;
11import java.util.Vector;
12import javax.xml.parsers.SAXParserFactory;
13import scriptbuilder.structures.ScriptIncident.IncidentFocusedEvent;
14import scriptbuilder.structures.ScriptIncident.SliceChangedEvent;
15import scriptbuilder.structures.events.*;
16import scriptbuilder.structures.units.Unit;
17import java.nio.file.Path;
18import java.nio.file.Paths;
19import java.util.TreeMap;
20
21/**
22 * Representation of the script to be run by the TMC Simulator. Holds a list of
23 * incidents, which have start and end times and contain events.
24 *
25 * @author Greg Eddington <geddingt@calpoly.edu>
26 *
27 * @author Bryan McGuffin <bmcguffi@calpoly.edu>
28 * @author Sebastien Danthinne <sdanthin@calpoly.edu>
29 * @version 2017/06/22
30 */
31public class SimulationScript extends Observable implements I_XML_Writable
32{
33
34    /**
35     * Strings to show in the incident color combo box.  Last item should be black,
36     * which will be used if invalid color is provided to lookupColor().
37     */
38    public static final String[] colorNames = {"BLUE", "RED", "CYAN", "GREEN", 
39        "ORANGE", "MAGENTA", "YELLOW", "BLACK"};
40    /**
41     * Allowed color choices for incident display.
42     * These colors must match the items in colorNames.
43     */
44    public static final Color[] incidentColors = {Color.BLUE, Color.RED, Color.CYAN, 
45        Color.GREEN, Color.ORANGE, Color.MAGENTA, Color.YELLOW, Color.BLACK};
46    /**
47     * The file to which this script will be saved.
48     */
49    public File saveFile = null;
50
51    /**
52     * The name of this script.
53     */
54    public String title = "";
55
56    /**
57     * The incidents displayed by the GUI.
58     */
59    public List<ScriptIncident> incidents;
60
61    /**
62     * The units which participate in Unit events.
63     */
64    public List<Unit> units; 
65
66    //Somewhere in the code, something assumes that the list of incidents
67    //contains exactly 10 items. Until I can find and un-break that, this will do.
68    //todo: this incident fill count error
69    private final int INCIDENT_FILL_COUNT = 10;
70
71    /**
72     * Number of incidents currently displayed.
73     */
74    public int numberOfIncidents;
75
76    /**
77     * Script handler for parsing incoming XML files.
78     */
79    private MyScriptHandler sh;
80   
81    public final String audioDirectory = "Audio";
82
83   
84    public boolean saved;
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        saved = true;
99
100        //Backfill with null incidents
101        for (int i = numberOfIncidents; i < INCIDENT_FILL_COUNT; i++)
102        {
103            incidents.add(null);
104        }
105    }
106   
107    /**
108     * checks and sees if this object has the unit passed.
109     * @param unitID
110     * @return does this SimulationScript have unitnum?
111     */
112    public boolean hasUnit(String unitID){
113        boolean indicator = false;
114        if(units.size()!=0){
115            for(Unit u : units){
116               if(unitID.equals(u.UnitNum)){
117                   indicator = true;
118               }
119            }
120        }
121           
122        return indicator;
123    }
124    /**
125     * creates a dummy unit that only has unit number
126     * @param unitNum
127     */
128    public void addDummyUnit(String unitNum){
129        Unit dummy = new Unit();
130        dummy.UnitNum = unitNum;
131        units.add(dummy);
132    }
133    /**
134     * Update the script's observers.
135     *
136     */
137    public void update()
138    {
139        // The script has changed, notify observers
140        //use to rewrite the save indicator
141        //System.out.println("Script changed");
142        setChanged();
143        notifyObservers(this);
144        saved = false;
145       
146       
147    }
148   
149
150    /**
151     * Tell this script's observers that there is a new slice event.
152     *
153     * @param e the slice focus event
154     */
155    public void broadcastEvent(SliceChangedEvent e)
156    {
157        // The slice focus has changed; pass the message
158        setChanged();
159        notifyObservers(e);
160    }
161
162    /**
163     * Tell this script's observers that there is a new slice event.
164     *
165     * @param e the incident focus event
166     */
167    public void broadcastEvent(IncidentFocusedEvent e)
168    {
169        // The slice focus has changed; pass the message
170        setChanged();
171        notifyObservers(e);
172    }
173
174    /**
175     * Load in an existing script from an XML file.
176     *
177     * @param f the file containing the script
178     */
179    public void loadScriptFromFile(File f)
180    {
181        try
182        {
183
184            SAXParserFactory.newInstance().newSAXParser().parse(f, sh);
185
186            Vector<ScriptIncident> inc = sh.getIncidents();
187            units = sh.getUnits();
188            for (ScriptIncident sci : inc)
189            {
190                addIncident(sci);
191            }
192        }
193        catch (Exception ex)
194        {
195            System.out.println("ERROR LOADING SCRIPT");
196            ex.printStackTrace();
197        }
198        System.out.println("H");
199        for(Unit testUnit : units){
200            System.out.println(testUnit.toXML());
201        }
202        this.update();
203    }
204   
205    /**
206     * Load in an existing list of units from an XML file.
207     * @param inStream the input stream for the file containing the units
208     */
209    public void loadUnitsFromFile(java.io.InputStream inStream){
210        try
211        {
212            SAXParserFactory.newInstance().newSAXParser().parse(inStream, sh);
213            units.addAll(sh.getUnits());
214        }
215        catch (Exception ex)
216        {
217            System.out.println("ERROR LOADING UNITS");
218            ex.printStackTrace();
219        }
220        this.update();
221    }
222
223    /**
224     * Add a new incident to the script.
225     *
226     * @param sci the incident to be added.
227     * @return true if there was enough room to add this incident.
228     */
229    public boolean addIncident(ScriptIncident sci)
230    {
231        if (numberOfIncidents < INCIDENT_FILL_COUNT)
232        {
233            incidents.set(numberOfIncidents++, sci);
234            return true;
235        }
236        return false;
237    }
238
239    /**
240     * Write this script, in proper XML format, to the file in question.
241     *
242     * @param f the destination savefile to be written.
243     */
244    public void saveScriptToFile(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        try
262        {
263            createAudioDirectory(Paths.get(f.getCanonicalPath()).getParent());
264        }
265        catch(IOException ex)
266        {
267            System.err.println("there was a problem creating the audio directories.");
268        }
269       
270       
271        saved = true;
272    }
273   
274    /**
275     * Creates the proper audio directory using the I_AudioEvent types.
276     * @param path of audio directory root
277     */
278    private void createAudioDirectory(Path path){
279        String separator = System.getProperty("file.separator");
280        File f = new File(path.toString()+separator+audioDirectory);
281        if(!f.exists())
282        {
283            f.mkdir();
284            //scan through to see what is already there and if there is no existing audio directory, create it.
285        }
286        for(ScriptIncident i : incidents)
287        {
288            if(i!=null)
289            {
290                String name = ((Integer) i.number).toString();
291                File incidentFolder = new File(path.toString()+separator+audioDirectory+separator+name);
292                if(!incidentFolder.exists())
293                {
294                    //create an incidentfolder since one does not already exist
295                    incidentFolder.mkdir();
296                }
297
298               
299                for(TimeSlice slice : i.getSlices())
300                {
301                    for(I_ScriptEvent event : slice.events)
302                    {
303                        if(event instanceof I_AudioEvent)
304                        {
305                            //if the event is a chp radio event
306                            //then add the dummy file to the subdirectory created
307                            //CURRENTLY this ONLY is implemented for CHPRadioEvent, so it will need to be changed later.
308                            CHPRadioEvent radioEvent = (CHPRadioEvent) event;
309
310                            String output = radioEvent.toScriptFile();
311                            //optimally, this line should use the ID, but to account for files being read in, it needs to be the radiofile name
312                            System.out.println("Attempting to create file: "+ path.toString()+
313                                            separator+
314                                            audioDirectory+
315                                            separator+
316                                            name+
317                                            separator+
318                                            radioEvent.radioFile.replaceAll(".mp3","")+
319                                            ".txt");
320                            File newAudioScript = new File(
321                                    path.toString()+
322                                            separator+
323                                            audioDirectory+
324                                            separator+
325                                            name+
326                                            separator+
327                                            radioEvent.radioFile.replaceAll(".mp3","")+
328                                            ".txt");
329                           
330                            try
331                            {
332                                newAudioScript.createNewFile();
333                                BufferedWriter bw = new BufferedWriter(new FileWriter(newAudioScript));
334                                bw.write(output);
335                                bw.flush();
336                                bw.close();
337                            }catch(Exception e)
338                            {
339                                //to find the bug that triggers this Exception, we need to print out the lines that
340                                System.err.println("there was a problem creating your text files for: " + radioEvent.radioFile + "\n" + e.getMessage());
341                            }
342
343                        }
344                    }
345                }
346
347               
348            }
349
350           
351        }
352       
353       
354    }
355    @Override
356    public String toXML()
357    {
358        ArrayList<TimeSlice> slices = arrangeAllSlices();
359        String output = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
360        output += XMLWriter.internalDTD();
361        output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.title + "\"");
362
363        if (units.size() > 0)
364        {
365            output += XMLWriter.openTag(ELEMENT.SCRIPT_DATA.tag);
366            for (Unit unit : units)
367            {
368                output += unit.toXML();
369            }
370            output += XMLWriter.closeTag(ELEMENT.SCRIPT_DATA.tag);
371        }
372        for (TimeSlice slice : slices)
373        {
374            output += slice.toXML();
375        }
376        output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag);
377        return output;
378    }
379
380    /**
381     * Arranges all timeslices in this script in chronological order, then by
382     * incident number.
383     *
384     * @return a list of all timeslices in the simulation script
385     */
386    public ArrayList<TimeSlice> arrangeAllSlices()
387    {
388        ArrayList<TimeSlice> list = new ArrayList<TimeSlice>();
389        int length = absoluteLength();
390
391        for (int i = 0; i < length; i++)
392        {
393            for (ScriptIncident inc : incidents)
394            {
395
396                if (inc != null && inc.slices.get(i) != null)
397                {
398                    list.add(inc.slices.get(i));
399                }
400            }
401        }
402        return list;
403    }
404
405    /**
406     * Gets the total length of the simulation in seconds.
407     *
408     * @return
409     */
410    public int absoluteLength()
411    {
412        int length = 0;
413        for (ScriptIncident inc : incidents)
414        {
415            if (inc != null)
416            {
417                inc.updateLength();
418                int currentLength = inc.length + inc.offset;
419                if (currentLength > length)
420                {
421                    length = currentLength;
422                }
423            }
424        }
425        return length;
426    }
427
428    /**
429     * Counts the number of incidents currently running.
430     *
431     * @return the number of non-null incidents currently in the script. A
432     * number between 0 and INCIDENT_FILL_COUNT, inclusive.
433     */
434    public int incidentCount()
435    {
436        int count = 0;
437        for (ScriptIncident inc : incidents)
438        {
439            if (inc != null)
440            {
441                count++;
442            }
443        }
444        return count;
445    }
446   
447    /** Given a color, find its index in the incidentColors.
448     * @param color a java color
449     * @return the index of color in incidentColors, or last index if color isn't
450     * in incidentColors.  The last item in incidentColors should be black.
451     */
452    public static int lookupColor(Color color)
453    {
454        int idx = 0;
455        // search color array for target
456        while(idx < incidentColors.length && !incidentColors[idx].equals(color))
457        { 
458            idx++;
459        }
460        // if color not found, return index of last item.
461        if (idx == incidentColors.length) 
462        {
463            return idx-1;
464        }
465        else return idx;
466    }
467}
Note: See TracBrowser for help on using the repository browser.