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