package scriptbuilder.structures; import java.awt.Color; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Observable; import java.util.TreeMap; import scriptbuilder.structures.events.I_ScriptEvent; /** * A script incident. It has an ID number, a name, and a description. It may * contain several script events. It also has a color in the GUI window, and is * collapsible. Incidents may start as soon as the script begins to run, or they * can be offset from the start of the script. * * @author Greg Eddington * @author Bryan McGuffin * @version 2017/06/29 */ public class ScriptIncident { /** * The moments in time which have associated events. */ public TreeMap slices; /** * GUI display color of this slice. */ public Color color; /** * ID number for this incident. */ public int number; /** * Name of the incident. */ public String name; /** * Description of the incident. */ public String description; /** * Length, in seconds, of the incident. */ public int length = 0; /** * If true, incident appears minimized. */ public boolean collapsed = false; /** * Number of seconds between start of simulation and start of this incident. */ public int offset = 0; /** * Start position of the latest timeslice. */ private int latestStart = 0; /** * Number of events in this incident. */ public int eventCount = 0; SimulationScript script; /** * Basic constructor. * * @param number The incident ID number * @param name The name of the incident * @param description The description of the incident * @param script The script object holding this incident */ public ScriptIncident(int number, String name, String description, SimulationScript script) { color = Color.BLACK; this.number = number; this.name = name; this.description = description; this.script = script; slices = new TreeMap(); } /** * Constructor with color parameter. * * @param color The color to use in the GUI for this event * @param number The incident ID number * @param name The name of the incident * @param description The description of the incident * @param script The script object holding this incident */ public ScriptIncident(Color color, int number, String name, String description, SimulationScript script) { this.color = color; this.number = number; this.name = name; this.description = description; this.script = script; slices = new TreeMap(); } /** * Constructor with color and offset parameters. * * @param color The color to use in the GUI for this event * @param number The incident ID number * @param name The name of the incident * @param description The description of the incident * @param script The script object holding this incident * @param offset Number of seconds after 00:00:00 that this incident begins */ public ScriptIncident(Color color, int number, String name, String description, SimulationScript script, int offset) { this.color = color; this.number = number; this.name = name; this.description = description; this.script = script; slices = new TreeMap(); this.setOffset(offset); } /** * Set whether or not the incident is fully visible or in a compacted state. * * @param collapsed True if the event is compacted */ public void setCollapsed(boolean collapsed) { this.collapsed = collapsed; script.update(); } /** * Set the delay time between the start of the script and the start of this * incident. * * @param offset Number of seconds after 00:00:00 that this incident begins */ public void setOffset(int offset) { this.offset = offset; script.update(); } /** * Add a new script event to this incident. * * @param ev The new event * @param start Start time of this event, in seconds, from the beginning of * the simulation */ public void addNewEvent(I_ScriptEvent ev, int start) { TimeSlice t = slices.get(start); if (t == null) { //System.out.println("Generating new slice at time " + start); t = new TimeSlice(start, this); t.addEvent(ev); slices.put(start, t); } else { t.addEvent(ev); } eventCount++; if (start > latestStart) { latestStart = start; //System.out.println("Latest Start: " + latestStart); } if (start < offset) { offset = start; //System.out.println("Offset: " + offset); } updateLength(); } /** * Get an array of all valid timeSlices. * * @return List of timeSlices which are not null */ public ArrayList getSlices() { ArrayList arr = new ArrayList(); for (int i = 0; i <= latestStart; i++) { TimeSlice ts = slices.get(i); if (ts != null) { arr.add(ts); } } return arr; } /** * Update the offset and apparent length of this incident. The offset is the * start time of the earliest event in the incident. The length is the time * that the latest, longest-lasting event ends, minus the offset. */ private void updateLength() { int lengthSoFar = 0; for (int i = 0; i <= latestStart; i++) { TimeSlice ts = slices.get(i); if (ts != null) { int reach = ts.getTime() + ts.getEffectiveDuration() - offset; if (reach > lengthSoFar) { lengthSoFar = reach; } } } length = lengthSoFar; } /** * An event which is fired if the focused slice changes. */ public static class SliceChangedEvent { public TimeSlice slice; SliceChangedEvent(TimeSlice slice) { this.slice = slice; } } /** * Update and cause the system to focus on the given timeslice. * * @param i Index of the slice to focus on */ public void setSliceActive(int i) { if (this.slices.get(i) != null) { script.broadcastEvent(new SliceChangedEvent(this.slices.get(i))); } } /** * An event which is fired if the focused incident changes. */ public static class IncidentFocusedEvent { public ScriptIncident incident; IncidentFocusedEvent(ScriptIncident i) { incident = i; } } /** * Update and cause the system to focus on this incident. */ public void setIncidentActive() { script.broadcastEvent(new IncidentFocusedEvent(this)); } /** * String representation of this incident. * * @return String of the form "[Incident number] - [Incident name]" */ @Override public String toString() { return this.number + " - " + this.name; } }