// ----------------------------------------------------------
  public WOComponent editNewerSubmissionScore() {
    WCComponent destination = null;
    if (!hasMessages()) {
      if (aNewerSubmission == null) {
        log.error("editNewerSubmissionScore(): null submission!");
      } else if (aNewerSubmission.result() == null) {
        log.error("editNewerSubmissionScore(): null submission result!");
        log.error("student = " + aNewerSubmission.user().userName());
      }
      prefs().setSubmissionRelationship(aNewerSubmission);

      //            destination = pageWithName(GradeStudentSubmissionPage.class);
      destination = (WCComponent) super.next();
      if (destination instanceof GradeStudentSubmissionPage) {
        GradeStudentSubmissionPage page = (GradeStudentSubmissionPage) destination;

        if (aUserSubmission != null) {
          page.availableSubmissions = userGroup().displayedObjects().immutableClone();
          page.thisSubmissionIndex = page.availableSubmissions.indexOf(aUserSubmission);
        }
      }

      destination.nextPage = this;
    }
    return destination;
  }
  // ----------------------------------------------------------
  public String newerSubmissionStatus() {
    String result = "feedback entered on earlier submission";
    if (aNewerSubmission.result() == null) {
      result = "suspended";
      EnqueuedJob job = aNewerSubmission.enqueuedJob();
      if (job == null) {
        result = "cancelled";
      } else if (!job.paused()) {
        result = "queued for grading";
      }
    }
    // check date of submission against date of feedback
    else if (aSubmission.result() != null
        && aSubmission.result().lastUpdated() != null
        && aNewerSubmission.submitTime().after(aSubmission.result().lastUpdated())) {
      result = "newer than feedback";
    }

    if (log.isDebugEnabled()) {
      log.debug("newerSubmissionStatus() for " + aNewerSubmission + " = " + result);
      if (aSubmission.result() != null && aSubmission.result().lastUpdated() != null) {
        log.debug("    selected submission last updated: " + aSubmission.result().lastUpdated());
      }
      log.debug("    newer submission on: " + aNewerSubmission.submitTime());
    }
    return result;
  }
 // ----------------------------------------------------------
 public ERXDisplayGroup<Submission> studentNewerSubmissions() {
   if (studentNewerSubmissions.masterObject() != aSubmission) {
     studentNewerSubmissions.setMasterObject(aSubmission);
     studentNewerSubmissions.setObjectArray(aSubmission.allSubmissions());
     studentNewerSubmissions
         .queryMin()
         .takeValueForKey(aSubmission.submitNumber() + 1, Submission.SUBMIT_NUMBER_KEY);
     studentNewerSubmissions.setQualifier(studentNewerSubmissions.qualifierFromQueryValues());
   }
   return studentNewerSubmissions;
 }
  // ----------------------------------------------------------
  protected void beforeAppendToResponse(WOResponse response, WOContext context) {
    log.debug("appendToResponse()");

    subStats = new HashMap<AssignmentOffering, Submission.CumulativeStats>();
    offerings.setObjectArray(assignmentOfferings(courseOfferings()));
    if (log.isDebugEnabled()) {
      log.debug("assignment offerings:");
      for (AssignmentOffering ao : offerings.allObjects()) {
        log.debug("\t" + ao);
      }
    }

    NSMutableArray<Submission> staffSubs = new NSMutableArray<Submission>();
    NSArray<User> admins = User.administrators(localContext());

    for (AssignmentOffering ao : offerings.displayedObjects()) {
      // Stuff the index variable into the public key so the group/stats
      // methods will work for us
      assignmentOffering = ao;
      NSArray<UserSubmissionPair> subs =
          Submission.submissionsForGrading(
              localContext(),
              ao,
              true, // omitPartners
              omitStaff,
              studentStats());
      userGroup().setObjectArray(subs);

      @SuppressWarnings("unchecked")
      NSArray<User> staff =
          ERXArrayUtilities.arrayByAddingObjectsFromArrayWithoutDuplicates(
              ao.courseOffering().staff(), admins);
      staffSubs.addAll(
          extractSubmissions(
              Submission.submissionsForGrading(
                  localContext(),
                  ao,
                  true, // omitPartners
                  staff,
                  null)));
    }

    staffSubmissionGroup.setObjectArray(staffSubs);

    selectedUserSubmissionForPickerDialog = null;
    allUserSubmissionsForNavigationForPickerDialog = null;

    super.beforeAppendToResponse(response, context);
  }
 // ----------------------------------------------------------
 public String newerSubmitTimeSpanClass() {
   if (aNewerSubmission.isLate()) {
     return "warn sm";
   } else {
     return "sm";
   }
 }
 // ----------------------------------------------------------
 public String submitTimeSpanClass() {
   if (aSubmission.isLate()) {
     return "warn";
   } else {
     return null;
   }
 }
  /**
   * Marks all the submissions shown that have been partially graded as being completed, sending
   * e-mail notifications as necessary.
   *
   * @return null to force this page to reload
   */
  public int markSubmissionsAsComplete() {
    int numberNotified = 0;

    assignmentOffering = offeringForAction;
    for (UserSubmissionPair pair : userGroup().allObjects()) {
      if (pair.userHasSubmission()) {
        Submission sub = pair.submission();

        if (sub.result().status() == Status.UNFINISHED
            || (sub.result().status() != Status.CHECK
                && !sub.assignmentOffering().assignment().usesTAScore())) {
          sub.result().setStatus(Status.CHECK);
          if (applyLocalChanges()) {
            numberNotified++;
            sub.emailNotificationToStudent("has been updated by the course staff");
          }
        }
      }
    }

    return numberNotified;
  }
  // ----------------------------------------------------------
  public WOComponent repartner() {
    for (UserSubmissionPair pair : userGroup().allObjects()) {
      Submission sub = pair.submission();

      if (sub != null && sub.result() != null) {
        for (Submission psub : sub.result().submissions()) {
          if (psub != sub
              && psub.assignmentOffering().assignment() != sub.assignmentOffering().assignment()) {
            log.warn(
                "found partner submission "
                    + psub.user()
                    + " #"
                    + psub.submitNumber()
                    + "\non incorrect assignment offering "
                    + psub.assignmentOffering());

            NSArray<AssignmentOffering> partnerOfferings =
                AssignmentOffering.objectsMatchingQualifier(
                    localContext(),
                    AssignmentOffering.courseOffering
                        .dot(CourseOffering.course)
                        .eq(sub.assignmentOffering().courseOffering().course())
                        .and(
                            AssignmentOffering.courseOffering
                                .dot(CourseOffering.students)
                                .eq(psub.user()))
                        .and(
                            AssignmentOffering.assignment.eq(
                                sub.assignmentOffering().assignment())));
            if (partnerOfferings.count() == 0) {
              log.error(
                  "Cannot locate correct assignment "
                      + "offering for partner"
                      + psub.user()
                      + " #"
                      + psub.submitNumber()
                      + "\non incorrect assignment offering "
                      + psub.assignmentOffering());
            } else {
              if (partnerOfferings.count() > 1) {
                log.warn(
                    "Multiple possible offerings for "
                        + "partner "
                        + psub.user()
                        + " #"
                        + psub.submitNumber()
                        + "\non incorrect assignment offering "
                        + psub.assignmentOffering());
                for (AssignmentOffering ao : partnerOfferings) {
                  log.warn("\t" + ao);
                }
              }

              psub.setAssignmentOfferingRelationship(partnerOfferings.get(0));
            }
          }
        }
      }
    }
    applyLocalChanges();
    return null;
  }
 // ----------------------------------------------------------
 public int mostRecentSubmissionNo() {
   return aSubmission.latestSubmission().submitNumber();
 }
 // ----------------------------------------------------------
 public boolean isMostRecentSubmission() {
   return aSubmission == aSubmission.latestSubmission();
 }
 // ----------------------------------------------------------
 public boolean hasTAScore() {
   return aSubmission.result().taScoreRaw() != null;
 }