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 @ 194

Revision 194, 13.3 KB checked in by sdanthin, 6 years ago (diff)

SimulationScript?.java added System paths in place of "/" for cross platform compatability

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 boolean saved;
82   
83    //TODO: Pretty much everything in this constructor is dummy data.
84    //Replace all of it.
85    /**
86     * Constructor. Backfill incident list with null objects, to be replaced
87     * later.
88     */
89    public SimulationScript()
90    {
91        sh = new MyScriptHandler(this);
92        incidents = new ArrayList<ScriptIncident>();
93        units = new ArrayList<Unit>();
94        numberOfIncidents = 0;
95        saved = true;
96
97        //Backfill with null incidents
98        for (int i = numberOfIncidents; i < INCIDENT_FILL_COUNT; i++)
99        {
100            incidents.add(null);
101        }
102    }
103   
104    /**
105     * checks and sees if this object has the unit passed.
106     * @param unitID
107     * @return does this SimulationScript have unitnum?
108     */
109    public boolean hasUnit(String unitID){
110        boolean indicator = false;
111        if(units.size()!=0){
112            for(Unit u : units){
113               if(unitID.equals(u.UnitNum)){
114                   indicator = true;
115               }
116            }
117        }
118           
119        return indicator;
120    }
121    /**
122     * creates a dummy unit that only has unit number
123     * @param unitNum
124     */
125    public void addDummyUnit(String unitNum){
126        Unit dummy = new Unit();
127        dummy.UnitNum = unitNum;
128        units.add(dummy);
129    }
130    /**
131     * Update the script's observers.
132     *
133     */
134    public void update()
135    {
136        // The script has changed, notify observers
137        //use to rewrite the save indicator
138        //System.out.println("Script changed");
139        setChanged();
140        notifyObservers(this);
141        saved = false;
142       
143       
144    }
145   
146
147    /**
148     * Tell this script's observers that there is a new slice event.
149     *
150     * @param e the slice focus event
151     */
152    public void broadcastEvent(SliceChangedEvent e)
153    {
154        // The slice focus has changed; pass the message
155        setChanged();
156        notifyObservers(e);
157    }
158
159    /**
160     * Tell this script's observers that there is a new slice event.
161     *
162     * @param e the incident focus event
163     */
164    public void broadcastEvent(IncidentFocusedEvent e)
165    {
166        // The slice focus has changed; pass the message
167        setChanged();
168        notifyObservers(e);
169    }
170
171    /**
172     * Load in an existing script from an XML file.
173     *
174     * @param f the file containing the script
175     */
176    public void loadScriptFromFile(File f)
177    {
178        try
179        {
180
181            SAXParserFactory.newInstance().newSAXParser().parse(f, sh);
182
183            Vector<ScriptIncident> inc = sh.getIncidents();
184            units = sh.getUnits();
185            for (ScriptIncident sci : inc)
186            {
187                addIncident(sci);
188            }
189        }
190        catch (Exception ex)
191        {
192            System.out.println("ERROR LOADING SCRIPT");
193            ex.printStackTrace();
194        }
195        System.out.println("H");
196        for(Unit testUnit : units){
197            System.out.println(testUnit.toXML());
198        }
199        this.update();
200    }
201   
202    /**
203     * Load in an existing list of units from an XML file.
204     * @param inStream the input stream for the file containing the units
205     */
206    public void loadUnitsFromFile(java.io.InputStream inStream){
207        try
208        {
209            SAXParserFactory.newInstance().newSAXParser().parse(inStream, sh);
210            units.addAll(sh.getUnits());
211        }
212        catch (Exception ex)
213        {
214            System.out.println("ERROR LOADING UNITS");
215            ex.printStackTrace();
216        }
217        this.update();
218    }
219
220    /**
221     * Add a new incident to the script.
222     *
223     * @param sci the incident to be added.
224     * @return true if there was enough room to add this incident.
225     */
226    public boolean addIncident(ScriptIncident sci)
227    {
228        if (numberOfIncidents < INCIDENT_FILL_COUNT)
229        {
230            incidents.set(numberOfIncidents++, sci);
231            return true;
232        }
233        return false;
234    }
235
236    /**
237     * Write this script, in proper XML format, to the file in question.
238     *
239     * @param f the destination savefile to be written.
240     */
241    public void saveScriptToFile(File f)
242    {
243        try
244        {
245            f.createNewFile();
246
247            BufferedWriter bw = new BufferedWriter(new FileWriter(f));
248            bw.write(this.toXML());
249            bw.flush();
250            bw.close();
251
252        }
253        catch (Exception ex)
254        {
255            System.out.println("ERROR SAVING SCRIPT");
256            ex.printStackTrace();
257        }
258        try
259        {
260            createAudioDirectory(Paths.get(f.getCanonicalPath()).getParent());
261        }
262        catch(IOException ex)
263        {
264            System.err.println("there was a problem creating the audio directories.");
265        }
266       
267       
268        saved = true;
269    }
270   
271    /**
272     * Creates the proper audio directory using the I_AudioEvent types.
273     * @param path of audio directory root
274     */
275    private void createAudioDirectory(Path path){
276        String separator = System.getProperty("file.separator");
277        File f = new File(path.toString()+separator+"audio");
278        if(!f.exists())
279        {
280            f.mkdir();
281            //scan through to see what is already there and if there is no existing audio directory, create it.
282        }
283        for(ScriptIncident i : incidents)
284        {
285            if(i!=null)
286            {
287                String name = ((Integer) i.number).toString();
288                File incidentFolder = new File(path.toString()+separator+"audio"+separator+name);
289                if(!incidentFolder.exists())
290                {
291                    //create an incidentfolder since one does not already exist
292                    incidentFolder.mkdir();
293                }
294
295               
296                for(TimeSlice slice : i.getSlices())
297                {
298                    for(I_ScriptEvent event : slice.events)
299                    {
300                        if(event instanceof I_AudioEvent)
301                        {
302                            //if the event is a chp radio event
303                            //then add the dummy file to the subdirectory created
304                            //CURRENTLY this ONLY is implemented for CHPRadioEvent, so it will need to be changed later.
305                            CHPRadioEvent radioEvent = (CHPRadioEvent) event;
306
307                            String output = radioEvent.toScriptFile();
308                            //optimally, this line should use the ID, but to account for files being read in, it needs to be the radiofile name
309                            File newAudioScript = new File(
310                                    path.toString()+
311                                            separator+
312                                            "Audio"+
313                                            separator+
314                                            name+
315                                            separator+
316                                            radioEvent.radioFile.replaceAll(".mp3","")+
317                                            ".txt");
318                           
319                            try
320                            {
321                                newAudioScript.createNewFile();
322                                BufferedWriter bw = new BufferedWriter(new FileWriter(newAudioScript));
323                                bw.write(output);
324                                bw.flush();
325                                bw.close();
326                            }catch(Exception e)
327                            {
328                                //to find the bug that triggers this Exception, we need to print out the lines that
329                                System.err.println("there was a problem creating your text files for: " + radioEvent.radioFile + "\n" + e.getMessage());
330                            }
331
332                        }
333                    }
334                }
335
336               
337            }
338
339           
340        }
341       
342       
343    }
344    @Override
345    public String toXML()
346    {
347        ArrayList<TimeSlice> slices = arrangeAllSlices();
348        String output = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
349        output += XMLWriter.internalDTD();
350        output += XMLWriter.openTag(ELEMENT.TMC_SCRIPT.tag + " title=\"" + this.title + "\"");
351
352        if (units.size() > 0)
353        {
354            output += XMLWriter.openTag(ELEMENT.SCRIPT_DATA.tag);
355            for (Unit unit : units)
356            {
357                output += unit.toXML();
358            }
359            output += XMLWriter.closeTag(ELEMENT.SCRIPT_DATA.tag);
360        }
361        for (TimeSlice slice : slices)
362        {
363            output += slice.toXML();
364        }
365        output += XMLWriter.closeTag(ELEMENT.TMC_SCRIPT.tag);
366        return output;
367    }
368
369    /**
370     * Arranges all timeslices in this script in chronological order, then by
371     * incident number.
372     *
373     * @return a list of all timeslices in the simulation script
374     */
375    public ArrayList<TimeSlice> arrangeAllSlices()
376    {
377        ArrayList<TimeSlice> list = new ArrayList<TimeSlice>();
378        int length = absoluteLength();
379
380        for (int i = 0; i < length; i++)
381        {
382            for (ScriptIncident inc : incidents)
383            {
384
385                if (inc != null && inc.slices.get(i) != null)
386                {
387                    list.add(inc.slices.get(i));
388                }
389            }
390        }
391        return list;
392    }
393
394    /**
395     * Gets the total length of the simulation in seconds.
396     *
397     * @return
398     */
399    public int absoluteLength()
400    {
401        int length = 0;
402        for (ScriptIncident inc : incidents)
403        {
404            if (inc != null)
405            {
406                inc.updateLength();
407                int currentLength = inc.length + inc.offset;
408                if (currentLength > length)
409                {
410                    length = currentLength;
411                }
412            }
413        }
414        return length;
415    }
416
417    /**
418     * Counts the number of incidents currently running.
419     *
420     * @return the number of non-null incidents currently in the script. A
421     * number between 0 and INCIDENT_FILL_COUNT, inclusive.
422     */
423    public int incidentCount()
424    {
425        int count = 0;
426        for (ScriptIncident inc : incidents)
427        {
428            if (inc != null)
429            {
430                count++;
431            }
432        }
433        return count;
434    }
435   
436    /** Given a color, find its index in the incidentColors.
437     * @param color a java color
438     * @return the index of color in incidentColors, or last index if color isn't
439     * in incidentColors.  The last item in incidentColors should be black.
440     */
441    public static int lookupColor(Color color)
442    {
443        int idx = 0;
444        // search color array for target
445        while(idx < incidentColors.length && !incidentColors[idx].equals(color))
446        { 
447            idx++;
448        }
449        // if color not found, return index of last item.
450        if (idx == incidentColors.length) 
451        {
452            return idx-1;
453        }
454        else return idx;
455    }
456}
Note: See TracBrowser for help on using the repository browser.