// ========================================================================================
// IMPORTANT: You should not edit this file
// ========================================================================================

#ifndef _JOB_H_
#define _JOB_H_

#include <cassert>
#include "timestamp.h"

// The Job class holds all necessary information about each student
// autograding submission.  A Job object with an empty string for the
// course is used to represent an idle processor.

inline double MillisecondsToSeconds(uint64_t x) {
  return double(x) / 1000.0;
}

class Job {
public:
  // CONSTRUCTORS
  Job() : name("") {}
  Job(const std::string &course_, const std::string &gradeable_, const std::string &username_,
      const TimeStamp &upload_time, double r, int n) :
    course(course_),gradeable(gradeable_),username(username_),
    name(course+"_"+gradeable+"_"+username),
    runtime(r), upload(upload_time), nice(n)
  {
    assert (nice >= -20 && nice <= 20);
  }
  
  // ACCESSORS
  const std::string& getName() const { return name; }
  const std::string& getCourse() const { return course; }
  const std::string& getGradeable() const { return gradeable; }
  const std::string& getUsername() const { return username; }
  double getRuntime() const { assert (name != ""); return runtime; }
  const TimeStamp& getUploadTime() const { assert (name != ""); return upload; }
  const TimeStamp& getStartTime() const { assert (name != ""); return start; }
  const TimeStamp& getFinishTime() const { assert (name != ""); return finish; }
  int getNiceness() const { assert (name != ""); return nice; }
  
  double waiting_time() const {
    assert (name != ""); return MillisecondsToSeconds(elapsedMilliseconds(upload, start)); }
  double grading_time() const {
    assert (name != ""); return MillisecondsToSeconds(elapsedMilliseconds(start, finish)); }
  
  // MODIFIER
  void startGrading(const TimeStamp &s) { assert (name != "");
    start = s; finish = s; finish.addMilliseconds(int(1000*runtime)); }

  bool operator< (const Job &b) const {
    return nice > b.nice ||
      (nice == b.nice && !(upload < b.upload));
  }
  
private:
  // REPRESENTATION
  std::string course;
  std::string gradeable;
  std::string username;
  std::string name;
  double runtime;
  TimeStamp upload;
  TimeStamp start;
  TimeStamp finish;
  int nice;
};



#endif
