         maxScore / pointsPossible
       else
         qHigh = grades[grades.length - 1]
+
+    # v8's sort is not stable, this function ensures that the same submission
+    # will be dropped regardless of browser
+    @stableSubmissionSort: (sortFn, getAssignmentIdFn) ->
+      (a, b) ->
+        ret = sortFn(a, b)
+        if ret == 0
+          getAssignmentIdFn(a) - getAssignmentIdFn(b)
+        else
+          ret
 
     @calculate_total: (groupSums, ignoreUngraded, weightingScheme) ->
 

      keepHighest = submissions.length - dropLowest
      keepLowest  = keepHighest - dropHighest

      # make sure we drop the same submission regardless of order
      submissions.sort (a, b) ->
        a.submission.assignment_id - b.submission.assignment_id

      hasPointed = (s.total for s in submissions when s.total > 0).length > 0
      kept = if hasPointed
        @dropPointed submissions, cantDrop, keepHighest, keepLowest


        kept

      kept = keepHelper(submissions, keepHighest, @stableSubmissionSort(
        ([a,xx], [b,yy]) -> b - a,
        ([_score,s]) -> s.submission.assignment_id
      ))
      kept = keepHelper(kept, keepLowest, @stableSubmissionSort(
        ([a,xx], [b,yy]) -> a - b,
        ([_score,s]) -> s.submission.assignment_id
      ))

    @estimateQHigh: (pointed, unpointed, grades) ->
      if unpointed.length > 0
