1 /** 2 * Scheduling-related definitions 3 */ 4 module eskomcalendar.schedule; 5 6 import std.datetime.systime : SysTime; 7 import std.json : JSONValue, JSONException; 8 import std.conv : to; 9 import eskomcalendar.exceptions; 10 11 /** 12 * Represents a schedule for a given area, 13 * this includes the stage and the start 14 * and end time 15 */ 16 public class Schedule 17 { 18 /** 19 * Area this schedule applies to 20 */ 21 private string area; 22 23 /** 24 * The stage level 25 */ 26 private ubyte stage; 27 28 /** 29 * Start and finish time 30 */ 31 private SysTime start, finish; 32 33 /** 34 * The source this schedule was gleamed from 35 */ 36 private string source; 37 38 /** 39 * Private constructor to disallow creation except 40 * via the static factory method 41 */ 42 private this() 43 { 44 45 } 46 47 /** 48 * Get's the name of the area this schedule is for 49 * 50 * Returns: the area's name 51 */ 52 public string getArea() 53 { 54 return area; 55 } 56 57 /** 58 * Returns the load shedding stage level 59 * 60 * Returns: the stage 61 */ 62 public ubyte getStage() 63 { 64 return stage; 65 } 66 67 /** 68 * Returns the starting time 69 * 70 * Returns: the starting time as a `SysTime` 71 */ 72 public SysTime getStart() 73 { 74 return start; 75 } 76 77 /** 78 * Returns the ending time 79 * 80 * Returns: the starting time as a `SysTime` 81 */ 82 public SysTime getFinish() 83 { 84 return finish; 85 } 86 87 /** 88 * Returns the source this schedule was gleamed from 89 * 90 * Returns: the source 91 */ 92 public string getSource() 93 { 94 return source; 95 } 96 97 /** 98 * Constructs a new `Schedule` from the provided JSON 99 * 100 * Params: 101 * json = the json to parse the schedule from 102 * Returns: the parsed `Schedule` 103 */ 104 public static Schedule fromJSON(JSONValue json) 105 { 106 Schedule schedule = new Schedule(); 107 108 try 109 { 110 schedule.area = json["area_name"].str(); 111 schedule.stage = cast(ubyte)(json["stage"].integer()); 112 schedule.start = SysTime.fromISOExtString(json["start"].str()); 113 schedule.finish = SysTime.fromISOExtString(json["finsh"].str()); 114 schedule.source = json["source"].str(); 115 } 116 catch(JSONException e) 117 { 118 throw new EskomCalendarException(ErrType.INVALID_SCHEDULE_DATA); 119 } 120 121 return schedule; 122 } 123 124 /** 125 * Returns a string representation of the schedule 126 * 127 * Returns: a `string` representation 128 */ 129 public override string toString() 130 { 131 return "Schedule [area: "~area~", stage: "~to!(string)(stage)~", from: "~start.toLocalTime().toSimpleString()~", to: "~finish.toLocalTime().toSimpleString()~"]"; 132 } 133 } 134 135 version(unittest) 136 { 137 import std.json : parseJSON; 138 } 139 140 /** 141 * Test building a `Schedule` from the example JSON 142 */ 143 unittest 144 { 145 string json = ` 146 { 147 "area_name": "western-cape-worscester", 148 "stage": 4, 149 "start": "2023-06-01T14:00:00+02:00", 150 "finsh": "2023-06-01T14:30:00+02:00", 151 "source": "https://twitter.com/Eskom_SA/status/1664250326818365440" 152 }`; 153 154 try 155 { 156 Schedule schedule = Schedule.fromJSON(parseJSON(json)); 157 158 assert(schedule.getArea() == "western-cape-worscester"); 159 assert(schedule.getStage() == 4); 160 assert(schedule.getStart() == SysTime.fromISOExtString("2023-06-01T14:00:00+02:00")); 161 assert(schedule.getFinish() == SysTime.fromISOExtString("2023-06-01T14:30:00+02:00")); 162 assert(schedule.getSource() == "https://twitter.com/Eskom_SA/status/1664250326818365440"); 163 } 164 catch(EskomCalendarException e) 165 { 166 assert(false); 167 } 168 } 169 170 /** 171 * Test building a `Schedule` from the example JSON 172 * buit where the JSON is BROKEN 173 */ 174 private unittest 175 { 176 string json = ` 177 { 178 "area_name": "western-cape-worscester", 179 "stage": 4, 180 "start": "2023-06-01T14:00:00+02:00", 181 "finsh": 2 182 }`; 183 184 try 185 { 186 Schedule schedule = Schedule.fromJSON(parseJSON(json)); 187 188 assert(false); 189 } 190 catch(EskomCalendarException e) 191 { 192 assert(e.getError() == ErrType.INVALID_SCHEDULE_DATA); 193 } 194 }