From 07dd978c5f54a7735dbeabbc8f86f722d217e56a Mon Sep 17 00:00:00 2001 From: Ellen Spertus Date: Fri, 15 Dec 2023 18:05:05 -0800 Subject: [PATCH] Enable ordering results --- .../com/spertus/jacquard/common/Result.java | 52 +++++++++++++++++++ .../publisher/GradescopePublisher.java | 7 ++- .../spertus/jacquard/publisher/Publisher.java | 15 +++++- .../java/com/spertus/jacquard/ResultTest.java | 34 ++++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/spertus/jacquard/common/Result.java b/src/main/java/com/spertus/jacquard/common/Result.java index 3f7f5a6..de5fbfc 100644 --- a/src/main/java/com/spertus/jacquard/common/Result.java +++ b/src/main/java/com/spertus/jacquard/common/Result.java @@ -297,4 +297,56 @@ public static void changeVisibility( final List results, final Visibility visibility) { results.forEach((Result r) -> r.setVisibility(visibility)); } + + /** + * The publication order for results. The default is {@link #NATURAL}. + * + * @see {@link #reorderResults(List, Order)} + */ + public enum Order { + /** + * The order in which they were generated. In other words, + * this will not reorder elements. + */ + // This relies on Collection.sort() being stable, per API + // https://stackoverflow.com/a/44452446/631051 + NATURAL((r1, r2) -> 0), + + /** + * Alphabetical order by result name. + */ + ALPHABETICAL(Comparator.comparing(r -> r.name)), + + /** + * In increasing order by maximum score. + */ + INCREASING_MAX_SCORE(Comparator.comparing(r -> r.maxScore)), + + /** + * In decreasing order by maximum score. + */ + DECREASING_MAX_SCORE(Comparator.comparing(r -> -r.maxScore)); + + private Comparator comparator; + + Order(Comparator comparator) { + this.comparator = comparator; + } + } + + /** + * Produces a sorted copy of the results. + * + * @param results the results + * @param order the ordering + * @return the sorted result list + */ + public static List reorderResults(List results, Order order) { + // This copies the list rather than sorting in place for two reasons: + // 1. The list parameter might be immutable. + // 2. To avoid side effects. + List mutableResults = new ArrayList<>(results); + Collections.sort(mutableResults, order.comparator); + return mutableResults; + } } diff --git a/src/main/java/com/spertus/jacquard/publisher/GradescopePublisher.java b/src/main/java/com/spertus/jacquard/publisher/GradescopePublisher.java index 25e98cb..723a5e9 100644 --- a/src/main/java/com/spertus/jacquard/publisher/GradescopePublisher.java +++ b/src/main/java/com/spertus/jacquard/publisher/GradescopePublisher.java @@ -32,10 +32,13 @@ public String serializeResults(final List results) { } @Override - public boolean publishResults(final List results) { + public boolean publishResults(final List results, Result.Order order) { try { if (Files.exists(RESULTS_PATH)) { - Files.write(RESULTS_PATH.resolve(RESULTS_FILE_NAME), serializeResults(results).getBytes()); + List sortedResults = Result.reorderResults(results, order); + Files.write( + RESULTS_PATH.resolve(RESULTS_FILE_NAME), + serializeResults(sortedResults).getBytes()); return true; } } catch (IOException e) { diff --git a/src/main/java/com/spertus/jacquard/publisher/Publisher.java b/src/main/java/com/spertus/jacquard/publisher/Publisher.java index 86df6cf..176f2c4 100644 --- a/src/main/java/com/spertus/jacquard/publisher/Publisher.java +++ b/src/main/java/com/spertus/jacquard/publisher/Publisher.java @@ -28,7 +28,20 @@ public abstract class Publisher { * @param results the results * @return whether the results were successfully published */ - public abstract boolean publishResults(List results); + public boolean publishResults(List results) { + return publishResults(results, Result.Order.NATURAL); + } + + /** + * Publishes the results in a manner appropriate for the external grading + * tool. This does nothing (and returns {@code false}) if it detects that + * it is not running within the tool (i.e., is on a development machine). + * + * @param results the results + * @param order how to order the results + * @return whether the results were successfully published + */ + public abstract boolean publishResults(List results, Result.Order order); /** * Displays the results in a human-readable format. diff --git a/src/test/java/com/spertus/jacquard/ResultTest.java b/src/test/java/com/spertus/jacquard/ResultTest.java index d880b53..ae2a2ce 100644 --- a/src/test/java/com/spertus/jacquard/ResultTest.java +++ b/src/test/java/com/spertus/jacquard/ResultTest.java @@ -3,12 +3,23 @@ import com.spertus.jacquard.common.*; import org.junit.jupiter.api.*; +import java.util.List; + import static org.junit.jupiter.api.Assertions.assertEquals; public class ResultTest { + private Result rBigSuccess; + private Result rHugeFailure; + private Result rMixed; + private List results; + @BeforeEach public void setup() { Autograder.initForTest(); + rBigSuccess = Result.makeSuccess("big success", 10, "big success message"); + rHugeFailure = Result.makeFailure("huge Failure", 15, "huge failure message"); + rMixed = Result.makeResult("mixed success", 3.0, 6.0, "mixed success message"); + results = List.of(rBigSuccess, rHugeFailure, rMixed); } @Test @@ -33,4 +44,27 @@ public void testChangedDefaultVisibility() { Autograder.resetForTest(); // keep from affecting downstream tests } } + + @Test + public void testReorderNaturally() { + assertEquals( + List.of(rBigSuccess, rHugeFailure, rMixed), + Result.reorderResults(results, Result.Order.NATURAL) + ); + } + + @Test + public void testReorderAlphabetically() { + assertEquals(List.of(rBigSuccess, rHugeFailure, rMixed), Result.reorderResults(results, Result.Order.ALPHABETICAL)); + } + + @Test + public void testReorderDecreasingMaxScore() { + assertEquals(List.of(rHugeFailure, rBigSuccess, rMixed), Result.reorderResults(results, Result.Order.DECREASING_MAX_SCORE)); + } + + @Test + public void testReorderIncreasingMaxScore() { + assertEquals(List.of(rMixed, rBigSuccess, rHugeFailure), Result.reorderResults(results, Result.Order.INCREASING_MAX_SCORE)); + } }