001package edu.pdx.cs.joy.grader.gradebook; 002 003import edu.pdx.cs.joy.ParserException; 004 005import java.io.File; 006import java.io.FileNotFoundException; 007import java.io.IOException; 008import java.io.PrintWriter; 009import java.time.LocalDateTime; 010 011/** 012 * This class represents an assignment give to students in The Joy of Coding. 013 * 014 * @author David Whitlock 015 */ 016public class Assignment extends NotableImpl { 017 018 public enum AssignmentType { 019 PROJECT, 020 QUIZ, 021 OTHER, 022 POA, 023 OPTIONAL 024 } 025 026 027 public enum ProjectType { 028 APP_CLASSES, 029 TEXT_FILE, 030 PRETTY_PRINT, 031 KOANS, 032 XML, 033 DATABASE, 034 REST, 035 ANDROID 036 } 037 038 private final String name; 039 private String description; 040 private double points; 041 private int canvasId; 042 private AssignmentType type; 043 private LocalDateTime dueDate; 044 private ProjectType projectType; 045 046 /** 047 * Creates a new <code>Assignment</code> with the given name and 048 * point value. 049 */ 050 public Assignment(String name, double points) { 051 this.name = name; 052 this.points = points; 053 this.type = AssignmentType.PROJECT; 054 this.setDirty(false); 055 } 056 057 /** 058 * Returns the name of this <code>Assignment</code> 059 */ 060 public String getName() { 061 return this.name; 062 } 063 064 /** 065 * Returns the number of points this <code>Assignment</code> is 066 * worth 067 */ 068 public double getPoints() { 069 return this.points; 070 } 071 072 /** 073 * Sets the number of points that this <code>Assignment</code> is 074 * worth. 075 */ 076 public Assignment setPoints(double points) { 077 this.setDirty(true); 078 this.points = points; 079 return this; 080 } 081 082 /** 083 * Returns a description of this <code>Assignment</code> 084 */ 085 public String getDescription() { 086 return this.description; 087 } 088 089 /** 090 * Sets the description of this <code>Assignment</code> 091 */ 092 public Assignment setDescription(String description) { 093 this.setDirty(true); 094 this.description = description; 095 return this; 096 } 097 098 /** 099 * Returns the type of this <code>Assignment</code> 100 */ 101 public AssignmentType getType() { 102 return this.type; 103 } 104 105 /** 106 * Sets the type of this <code>Assignment</code> 107 */ 108 public Assignment setType(AssignmentType type) { 109 this.setDirty(true); 110 this.type = type; 111 return this; 112 } 113 114 115 public Assignment setCanvasId(int canvasId) { 116 this.canvasId = canvasId; 117 this.setDirty(true); 118 return this; 119 } 120 121 public int getCanvasId() { 122 return canvasId; 123 } 124 125 126 /** 127 * Returns a brief textual description of this 128 * <code>Assignment</code> 129 */ 130 public String toString() { 131 return "Assignment " + this.getName() + " worth " + 132 this.getPoints(); 133 } 134 135 136 private static PrintWriter err = new PrintWriter(System.err, true); 137 138 /** 139 * Prints usage information about the main program. 140 */ 141 private static void usage() { 142 err.println("\njava Assignment [options] -xmlFile xmlFile " + 143 "-name name"); 144 err.println(" where [options] are:"); 145 err.println(" -points points Points assignment is worth"); 146 err.println(" -description desc Description of assignment"); 147 err.println(" -type type Type of assignment " + 148 "(PROJECT, QUIZ, or OTHER)"); 149 err.println(" -note note Note about assignment"); 150 err.println("\n"); 151 System.exit(1); 152 } 153 154 /** 155 * Main program that creates/edits an <code>Assignment</code> in a 156 * grade book stored in an XML file. 157 */ 158 public static void main(String[] args) { 159 String fileName = null; 160 String name = null; 161 String points = null; 162 String desc = null; 163 AssignmentType type = null; 164 String note = null; 165 166 // Parse the command line 167 for (int i = 0; i < args.length; i++) { 168 if (args[i].equals("-xmlFile")) { 169 if (++i >= args.length) { 170 err.println("** Missing XML file name"); 171 usage(); 172 } 173 174 fileName = args[i]; 175 176 } else if (args[i].equals("-name")) { 177 if (++i >= args.length) { 178 err.println("** Missing assignment name"); 179 usage(); 180 } 181 182 name = args[i]; 183 184 } else if (args[i].equals("-points")) { 185 if (++i >= args.length) { 186 err.println("** Missing points value"); 187 usage(); 188 } 189 190 points = args[i]; 191 192 } else if (args[i].equals("-description")) { 193 if (++i >= args.length) { 194 err.println("** Missing description"); 195 usage(); 196 } 197 198 desc = args[i]; 199 200 } else if (args[i].equals("-type")) { 201 if (++i >= args.length) { 202 err.println("** Missing type"); 203 usage(); 204 } 205 206 // Make sure type is valid 207 switch (args[i]) { 208 case "PROJECT": 209 type = AssignmentType.PROJECT; 210 break; 211 case "QUIZ": 212 type = AssignmentType.QUIZ; 213 break; 214 case "POA": 215 type = AssignmentType.POA; 216 break; 217 case "OTHER": 218 type = AssignmentType.OTHER; 219 break; 220 case "OPTIONAL": 221 type = AssignmentType.OPTIONAL; 222 break; 223 default: 224 err.println("** Invalid type: " + args[i]); 225 usage(); 226 break; 227 } 228 229 } else if (args[i].equals("-note")) { 230 if (++i >= args.length) { 231 err.println("** Missing note"); 232 usage(); 233 } 234 235 note = args[i]; 236 237 } else { 238 err.println("** Unknown option: " + args[i]); 239 } 240 } 241 242 // Verify command line 243 if (fileName == null) { 244 err.println("** No file name specified"); 245 usage(); 246 } 247 248 if (name == null) { 249 err.println("** No assignment name specified"); 250 usage(); 251 } 252 253 File file = new File(fileName); 254 if (!file.exists()) { 255 err.println("** Grade book file " + fileName + 256 " does not exist"); 257 System.exit(1); 258 } 259 260 if (name == null) { 261 err.println("** No assignment name specified"); 262 usage(); 263 } 264 265 GradeBook book = null; 266 try { 267 XmlGradeBookParser parser = new XmlGradeBookParser(file); 268 book = parser.parse(); 269 270 } catch (FileNotFoundException ex) { 271 err.println("** Could not find file: " + ex.getMessage()); 272 System.exit(1); 273 274 } catch (IOException ex) { 275 err.println("** IOException during parsing: " + ex.getMessage()); 276 System.exit(1); 277 278 } catch (ParserException ex) { 279 err.println("** Exception while parsing " + file + ": " + ex); 280 System.exit(1); 281 } 282 283 // Get the assignment 284 Assignment assign = book.getAssignment(name); 285 if (assign == null) { 286 // Did we specify a points value? 287 if (points == null) { 288 err.println("** No points specified"); 289 usage(); 290 } 291 292 double value = -1.0; 293 try { 294 value = Double.parseDouble(points); 295 296 } catch (NumberFormatException ex) { 297 err.println("** Not a valid point value: " + points); 298 System.exit(1); 299 } 300 301 if (value < 0.0) { 302 err.println("** Not a valid point value: " + value); 303 System.exit(1); 304 } 305 306 // Create a new Assignment 307 assign = new Assignment(name, value); 308 book.addAssignment(assign); 309 } 310 311 // Set the properties of the assignment 312 if (desc != null) { 313 assign.setDescription(desc); 314 } 315 316 if (type != null) { 317 assign.setType(type); 318 } 319 320 if (note != null) { 321 assign.addNote(note); 322 } 323 324 // Write the grade book back out to the XML file 325 try { 326 XmlDumper dumper = new XmlDumper(file); 327 dumper.dump(book); 328 329 } catch (IOException ex) { 330 err.println("** While dumping to " + file + ": " + ex); 331 System.exit(1); 332 } 333 } 334 335 public void setDueDate(LocalDateTime dueDate) { 336 this.dueDate = dueDate; 337 } 338 339 public LocalDateTime getDueDate() { 340 return dueDate; 341 } 342 343 public boolean isSubmissionLate(LocalDateTime submissionTime) { 344 if (this.dueDate == null) { 345 return false; 346 347 } else { 348 return submissionTime.isAfter(this.dueDate); 349 } 350 } 351 352 public Assignment setProjectType(ProjectType projectType) { 353 this.projectType = projectType; 354 return this; 355 } 356 357 public ProjectType getProjectType() { 358 return projectType; 359 } 360 361}