From 65ea569d9e55bfcde194dc2e98e7ff607e2f8b6a Mon Sep 17 00:00:00 2001 From: "Florian (Feuermagier)" Date: Sun, 22 Dec 2024 21:26:02 +0100 Subject: [PATCH] decouple programmingsubmission & correction round --- .../artemis4j/grading/PackedAssessment.java | 68 ++++++++++++ .../grading/ProgrammingExercise.java | 100 ++++++++++------- .../grading/ProgrammingSubmission.java | 102 +++--------------- .../ProgrammingSubmissionWithResults.java | 39 +++++++ .../kit/kastel/sdq/artemis4j/End2EndTest.java | 41 ++++--- .../kit/kastel/sdq/artemis4j/ExamTest.java | 15 ++- 6 files changed, 212 insertions(+), 153 deletions(-) create mode 100644 src/main/java/edu/kit/kastel/sdq/artemis4j/grading/PackedAssessment.java create mode 100644 src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmissionWithResults.java diff --git a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/PackedAssessment.java b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/PackedAssessment.java new file mode 100644 index 0000000..8101e0c --- /dev/null +++ b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/PackedAssessment.java @@ -0,0 +1,68 @@ +package edu.kit.kastel.sdq.artemis4j.grading; + +import edu.kit.kastel.sdq.artemis4j.ArtemisNetworkException; +import edu.kit.kastel.sdq.artemis4j.client.ProgrammingSubmissionDTO; +import edu.kit.kastel.sdq.artemis4j.client.ResultDTO; +import edu.kit.kastel.sdq.artemis4j.grading.metajson.AnnotationMappingException; +import edu.kit.kastel.sdq.artemis4j.grading.penalty.GradingConfig; + +import java.util.Optional; + +/** + * For API users, this is used in place of an assessment whenever we don't want to do + * the (expensive) deserialization of the assessment. + * The only semantic difference to an assessment is that this class does *not* imply a lock. + *

+ * Internally, this is just a glorified ResultDTO wrapper because we need a place + * to store the submission + * @param result + * @param submission + */ +public record PackedAssessment(ResultDTO result, CorrectionRound round, ProgrammingSubmission submission) { + public boolean isSubmitted() { + return result.completionDate() != null; + } + + public User getAssessor() { + return new User(result.assessor()); + } + + /** + * Locks and opens the assessment for this submission. + *

+ * If the submission has not been assessed by you, this might not be possible. + * + * @param config the config for the exercise + * @return the assessment if there are results for this submission + * @throws AnnotationMappingException If the annotations that were already + * present could not be mapped given the + * gradingConfig + */ + public Optional open(GradingConfig config) throws MoreRecentSubmissionException, ArtemisNetworkException, AnnotationMappingException { + return this.submission.getExercise().tryLockSubmission(this.submission.getId(), this.round, config); + } + + /** + * Opens the assessment for this submission without locking it. + *

+ * If the submission has not been assessed by you, you might not be able to + * change the assessment. + * + * @param config the config for the exercise + * @return the assessment if there are results for this submission + * @throws AnnotationMappingException If the annotations that were already + * present could not be mapped given the + * gradingConfig + */ + public Assessment openWithoutLock(GradingConfig config) throws ArtemisNetworkException, AnnotationMappingException { + return new Assessment(this.result, config, this.submission, this.round); + } + + public void cancel() throws ArtemisNetworkException { + ProgrammingSubmissionDTO.cancelAssessment(this.getConnection().getClient(), this.submission.getId()); + } + + private ArtemisConnection getConnection() { + return this.submission.getConnection(); + } +} diff --git a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingExercise.java b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingExercise.java index c5356f6..03d4eb5 100644 --- a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingExercise.java +++ b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingExercise.java @@ -74,19 +74,52 @@ public boolean hasSecondCorrectionRound() { return this.dto.secondCorrectionEnabled() != null && this.dto.secondCorrectionEnabled(); } - /** - * Fetches all submissions for this exercise. This may fetch *many* submissions, - * and does not cache the result, so be careful. - * - * @param correctionRound The correction round to fetch submissions for - * @param filterAssessedByTutor Whether to only fetch submissions that the - * current user has assessed - * @return a list of submissions - * @throws ArtemisNetworkException if the request fails - */ - public List fetchSubmissions(CorrectionRound correctionRound, boolean filterAssessedByTutor) + // /** + // * Fetches all submissions for this exercise. This may fetch *many* submissions, + // * and does not cache the result, so be careful. + // * + // * @param correctionRound The correction round to fetch submissions for + // * @param filterAssessedByTutor Whether to only fetch submissions that the + // * current user has assessed + // * @return a list of submissions + // * @throws ArtemisNetworkException if the request fails + // */ + // public List fetchSubmissions(CorrectionRound correctionRound, boolean filterAssessedByTutor) + // throws ArtemisNetworkException { + // + // if (correctionRound == CorrectionRound.SECOND && !this.hasSecondCorrectionRound()) { + // throw new IllegalArgumentException("This exercise does not have a second correction round"); + // } + // + // if (correctionRound == CorrectionRound.REVIEW) { + // throw new IllegalArgumentException("Can't fetch submissions for the review 'round'"); + // } + // + // return ProgrammingSubmissionDTO.fetchAll( + // this.getConnection().getClient(), + // this.getId(), + // correctionRound.toArtemis(), + // filterAssessedByTutor) + // .stream() + // .map(submissionDto -> new ProgrammingSubmission(submissionDto, this)) + // .toList(); + // } + + public List fetchAllSubmissions() throws ArtemisNetworkException { + // Artemis ignores the correction round since assessedByTutor is false + return ProgrammingSubmissionDTO.fetchAll( + this.getConnection().getClient(), + this.getId(), + 0, + true) + .stream() + .map(dto -> new ProgrammingSubmissionWithResults(new ProgrammingSubmission(dto, this))) + .toList(); + } + public List fetchMyAssessments(CorrectionRound correctionRound) + throws ArtemisNetworkException { if (correctionRound == CorrectionRound.SECOND && !this.hasSecondCorrectionRound()) { throw new IllegalArgumentException("This exercise does not have a second correction round"); } @@ -95,33 +128,25 @@ public List fetchSubmissions(CorrectionRound correctionRo throw new IllegalArgumentException("Can't fetch submissions for the review 'round'"); } - return ProgrammingSubmissionDTO.fetchAll( + var submissions = ProgrammingSubmissionDTO.fetchAll( this.getConnection().getClient(), this.getId(), correctionRound.toArtemis(), - filterAssessedByTutor) + true) .stream() - .map(submissionDto -> new ProgrammingSubmission(submissionDto, this, correctionRound)) + .map(submissionDto -> new ProgrammingSubmission(submissionDto, this)) .toList(); - } - public List fetchSubmissions(CorrectionRound correctionRound) - throws ArtemisNetworkException { - return this.fetchSubmissions( - correctionRound, - !this.getCourse().isInstructor(this.getConnection().getAssessor())); - } - - /** - * Fetches all submissions from correction round 1 and 2 (if enabled). - */ - public List fetchSubmissions() throws ArtemisNetworkException { - List submissions = new ArrayList<>(this.fetchSubmissions(CorrectionRound.FIRST)); - if (this.hasSecondCorrectionRound()) { - submissions.addAll(this.fetchSubmissions(CorrectionRound.SECOND)); + var assessments = new ArrayList(submissions.size()); + for (var submission : submissions) { + // TODO this may return more than one result for instructors + var results = submission.getDTO().nonAutomaticResults(); + if (results.size() != 1) { + throw new IllegalStateException("Too many non-automatic results"); + } + assessments.add(new PackedAssessment(results.get(0), correctionRound, submission)); } - - return submissions; + return assessments; } /** @@ -178,9 +203,8 @@ public Optional tryLockSubmission( this.getConnection().getClient(), submissionId, correctionRound.toArtemis()); if (locked.id() != submissionId) { - // Artemis automatically returns the most recent submission associated with the - // same participation - // as the requested submission + // Artemis automatically returns the most recent submission that is associated with the + // participation of the requested submission throw new MoreRecentSubmissionException( submissionId, locked.id(), locked.participation().id()); } @@ -199,16 +223,16 @@ public Optional tryLockSubmission( return Optional.empty(); } - var submission = new ProgrammingSubmission(locked, this, correctionRound); + var submission = new ProgrammingSubmission(locked, this); return Optional.of(new Assessment(result, gradingConfig, submission, correctionRound)); } - public int fetchOwnSubmissionCount(CorrectionRound correctionRound) throws ArtemisNetworkException { - return this.fetchSubmissions(correctionRound, true).size(); + public int fetchOwnAssessmentCount(CorrectionRound correctionRound) throws ArtemisNetworkException { + return this.fetchMyAssessments(correctionRound).size(); } public int fetchLockedSubmissionCount(CorrectionRound correctionRound) throws ArtemisNetworkException { - return (int) this.fetchSubmissions(correctionRound, true).stream() + return (int) this.fetchMyAssessments(correctionRound).stream() .filter(s -> !s.isSubmitted()) .count(); } diff --git a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmission.java b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmission.java index 0fc2dc9..cb9dbfb 100644 --- a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmission.java +++ b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmission.java @@ -1,19 +1,18 @@ /* Licensed under EPL-2.0 2024. */ package edu.kit.kastel.sdq.artemis4j.grading; -import java.nio.file.Path; -import java.time.ZonedDateTime; -import java.util.Objects; -import java.util.Optional; - import edu.kit.kastel.sdq.artemis4j.ArtemisClientException; import edu.kit.kastel.sdq.artemis4j.ArtemisNetworkException; -import edu.kit.kastel.sdq.artemis4j.client.AssessmentType; import edu.kit.kastel.sdq.artemis4j.client.ProgrammingSubmissionDTO; import edu.kit.kastel.sdq.artemis4j.client.ResultDTO; import edu.kit.kastel.sdq.artemis4j.grading.metajson.AnnotationMappingException; import edu.kit.kastel.sdq.artemis4j.grading.penalty.GradingConfig; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.Objects; +import java.util.Optional; + /** * A student's programming submission. A submission essentially consists of the * URL of a student's Git repository, along with a commit hash. We do not model @@ -22,12 +21,11 @@ public class ProgrammingSubmission extends ArtemisConnectionHolder { private final ProgrammingSubmissionDTO dto; - private final CorrectionRound correctionRound; private final User student; private final ProgrammingExercise exercise; public ProgrammingSubmission( - ProgrammingSubmissionDTO dto, ProgrammingExercise exercise, CorrectionRound correctionRound) { + ProgrammingSubmissionDTO dto, ProgrammingExercise exercise) { super(exercise); this.dto = dto; @@ -40,8 +38,6 @@ public ProgrammingSubmission( } else { this.student = null; } - - this.correctionRound = correctionRound; } public long getId() { @@ -79,10 +75,6 @@ public ProgrammingExercise getExercise() { return exercise; } - public CorrectionRound getCorrectionRound() { - return this.correctionRound; - } - public ZonedDateTime getSubmissionDate() { return this.dto.submissionDate(); } @@ -95,17 +87,6 @@ public Optional getLatestResult() { } } - /** - * Get the assessor of this assessment. - *

- * This is the user who has locked the submission. - * - * @return the assessor or empty if the submission has not been assessed - */ - public Optional getAssessor() { - return this.getRelevantResult().map(ResultDTO::assessor).map(User::new); - } - /** * Clones the submission, including the test repository, into the given path, * and checks out the submitted commit. This method uses the user's VCS access token, potentially creating a new one. @@ -131,7 +112,9 @@ public ClonedProgrammingSubmission cloneViaSSHInto(Path target) throws ArtemisCl } /** - * Tries to lock this submission. Locking is reentrant. + * Prefer the methods on PackedAssessment! + *

+ * Tries to lock this submission for a given correction round. Locking is reentrant. * * @return An empty optional if a *different* user has already locked the * submission, otherwise the assessment @@ -144,46 +127,21 @@ public ClonedProgrammingSubmission cloneViaSSHInto(Path target) throws ArtemisCl * corresponding student (i.e. * participation) */ - public Optional tryLock(GradingConfig gradingConfig) + public Optional tryLock(GradingConfig gradingConfig, CorrectionRound correctionRound) throws AnnotationMappingException, ArtemisNetworkException, MoreRecentSubmissionException { - return this.exercise.tryLockSubmission(this.getId(), this.getCorrectionRound(), gradingConfig); + return this.exercise.tryLockSubmission(this.getId(), correctionRound, gradingConfig); } - public boolean isSubmitted() { - var result = this.getRelevantResult(); - if (result.isEmpty() || result.get().completionDate() == null) { - return false; - } - - var assessmentType = result.get().assessmentType(); - return assessmentType == AssessmentType.MANUAL || assessmentType == AssessmentType.SEMI_AUTOMATIC; + public boolean isBuildFailed() { + return this.dto.buildFailed(); } /** - * Opens the assessment for this submission. - *

- * If the submission has not been assessed by you, you might not be able to - * change the assessment. - * - * @param config the config for the exercise - * @return the assessment if there are results for this submission - * @throws AnnotationMappingException If the annotations that were already - * present could not be mapped given the - * gradingConfig + * Be VERY careful with the dto's results, since their number may differ depending on the source of the dto. + * @return the corresponding dto */ - public Optional openAssessment(GradingConfig config) - throws AnnotationMappingException, ArtemisNetworkException { - ResultDTO resultDTO = this.getRelevantResult().orElse(null); - - if (resultDTO != null) { - return Optional.of(new Assessment(resultDTO, config, this, this.correctionRound)); - } - - return Optional.empty(); - } - - public boolean isBuildFailed() { - return this.dto.buildFailed(); + public ProgrammingSubmissionDTO getDTO() { + return this.dto; } @Override @@ -198,30 +156,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hashCode(this.getId()); } - - /** - * Returns the relevant result for this submission. - *

- * The difference between this method and {@link #getLatestResult()} is that - * when a submission has multiple results from different correction rounds, this - * method will return the result for the current correction round. If you want the - * latest result regardless of the correction round, use {@link #getLatestResult()}. - * - * @return the relevant result, if present - */ - public Optional getRelevantResult() { - var results = this.dto.nonAutomaticResults(); - - if (results.isEmpty()) { - return Optional.empty(); - } else if (results.size() == 1) { - // We only have one result, so the submission has - // probably been created for a specific correction round, - // or we only have one correction round - return Optional.of(results.get(0)); - } else { - // More than one result, so probably multiple correction rounds - return Optional.of(results.get(this.correctionRound.toArtemis())); - } - } } diff --git a/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmissionWithResults.java b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmissionWithResults.java new file mode 100644 index 0000000..0e0b931 --- /dev/null +++ b/src/main/java/edu/kit/kastel/sdq/artemis4j/grading/ProgrammingSubmissionWithResults.java @@ -0,0 +1,39 @@ +package edu.kit.kastel.sdq.artemis4j.grading; + +import java.util.Objects; + +public class ProgrammingSubmissionWithResults { + private final ProgrammingSubmission submission; + private final PackedAssessment firstRoundAssessment; + private final PackedAssessment secondRoundAssessment; + + public ProgrammingSubmissionWithResults(ProgrammingSubmission submission) { + this.submission = submission; + + var results = submission.getDTO().nonAutomaticResults(); + if (results.isEmpty()) { + this.firstRoundAssessment = null; + this.secondRoundAssessment = null; + } else if (results.size() == 1) { + this.firstRoundAssessment = new PackedAssessment(results.get(0), CorrectionRound.FIRST, submission); + this.secondRoundAssessment = null; + } else if (results.size() == 2){ + this.firstRoundAssessment = new PackedAssessment(results.get(0), CorrectionRound.FIRST, submission); + this.secondRoundAssessment = new PackedAssessment(results.get(1), CorrectionRound.SECOND, submission); + } else { + throw new IllegalStateException("Submission has more than two non-automatic results"); + } + } + + public ProgrammingSubmission getSubmission() { + return submission; + } + + public PackedAssessment getFirstRoundAssessment() { + return firstRoundAssessment; + } + + public PackedAssessment getSecondRoundAssessment() { + return secondRoundAssessment; + } +} diff --git a/src/test/java/edu/kit/kastel/sdq/artemis4j/End2EndTest.java b/src/test/java/edu/kit/kastel/sdq/artemis4j/End2EndTest.java index d56e009..82b2c49 100644 --- a/src/test/java/edu/kit/kastel/sdq/artemis4j/End2EndTest.java +++ b/src/test/java/edu/kit/kastel/sdq/artemis4j/End2EndTest.java @@ -18,7 +18,7 @@ import edu.kit.kastel.sdq.artemis4j.grading.Assessment; import edu.kit.kastel.sdq.artemis4j.grading.Course; import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingExercise; -import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingSubmission; +import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingSubmissionWithResults; import edu.kit.kastel.sdq.artemis4j.grading.TestResult; import edu.kit.kastel.sdq.artemis4j.grading.penalty.GradingConfig; import edu.kit.kastel.sdq.artemis4j.grading.penalty.MistakeType; @@ -45,7 +45,7 @@ class End2EndTest { private ArtemisConnection connection; private Course course; private ProgrammingExercise exercise; - private ProgrammingSubmission programmingSubmission; + private ProgrammingSubmissionWithResults programmingSubmission; private Assessment assessment; private GradingConfig gradingConfig; @@ -74,17 +74,17 @@ public void setup() throws ArtemisClientException, IOException { .findFirst() .orElseThrow(); - var submissions = this.exercise.fetchSubmissions(); + var submissions = this.exercise.fetchAllSubmissions(); this.programmingSubmission = submissions.stream() - .filter(a -> a.getParticipantIdentifier().equals(STUDENT_USER)) + .filter(s -> s.getSubmission().getParticipantIdentifier().equals(STUDENT_USER)) .findFirst() .orElseThrow(); this.gradingConfig = GradingConfig.readFromString( Files.readString(Path.of("src/test/resources/config.json")), this.exercise); - // ensure that the submission is locked - this.assessment = this.programmingSubmission.tryLock(this.gradingConfig).orElseThrow(); + // ensure that the submission is locked & clear the assessment + this.assessment = this.programmingSubmission.getFirstRoundAssessment().open(this.gradingConfig).orElseThrow(); this.assessment.clearAnnotations(); Assertions.assertTrue(this.assessment.getAnnotations().isEmpty()); @@ -105,7 +105,7 @@ void testCreationOfSimpleAnnotations() throws ArtemisClientException { this.assessment.submit(); // Check Assessments - this.assessment = this.programmingSubmission.tryLock(this.gradingConfig).orElseThrow(); + this.assessment = this.programmingSubmission.getFirstRoundAssessment().open(this.gradingConfig).orElseThrow(); List tests = this.assessment.getTestResults(); Assertions.assertEquals(13, tests.size()); @@ -125,7 +125,7 @@ void testCreationOfCustomAnnotation() throws ArtemisClientException { this.assessment.submit(); // Check Assessments - this.assessment = this.programmingSubmission.tryLock(this.gradingConfig).orElseThrow(); + this.assessment = this.programmingSubmission.getFirstRoundAssessment().open(this.gradingConfig).orElseThrow(); List tests = this.assessment.getTestResults(); Assertions.assertEquals(13, tests.size()); @@ -166,20 +166,17 @@ void testAssessmentFetchesFeedbacks() throws ArtemisClientException { this.assessment.addPredefinedAnnotation(mistakeType, "src/edu/kit/informatik/BubbleSort.java", 1, 2, null); this.assessment.submit(); - ProgrammingSubmission updatedSubmission = null; // find the programming submission that was just assessed in all submissions of // the exercise: - for (ProgrammingSubmission submission : this.exercise.fetchSubmissions()) { - if (submission.getId() == this.programmingSubmission.getId()) { - updatedSubmission = programmingSubmission; - break; - } - } + ProgrammingSubmissionWithResults updatedSubmission = this.exercise.fetchAllSubmissions().stream().filter( + s -> s.getSubmission().getParticipantIdentifier().equals(STUDENT_USER)).findFirst().orElseThrow(); - Assertions.assertEquals(this.programmingSubmission, updatedSubmission); + Assertions.assertEquals(this.programmingSubmission.getSubmission(), updatedSubmission.getSubmission()); - Assessment newAssessment = - updatedSubmission.openAssessment(this.gradingConfig).orElseThrow(); + Assessment newAssessment = updatedSubmission + .getFirstRoundAssessment() + .open(this.gradingConfig) + .orElseThrow(); Assertions.assertEquals(1, newAssessment.getAnnotations().size()); } @@ -219,7 +216,7 @@ void testMergingNotObservableInAssessments() throws ArtemisClientException { this.assessment.submit(); // Check Assessments - this.assessment = this.programmingSubmission.tryLock(this.gradingConfig).orElseThrow(); + this.assessment = this.programmingSubmission.getFirstRoundAssessment().open(this.gradingConfig).orElseThrow(); for (Annotation annotation : this.assessment.getAnnotations()) { Assertions.assertTrue( @@ -318,15 +315,15 @@ void testAnnotationMerging() throws ArtemisClientException { this.assessment.submit(); // the assessment will not show the merged annotations (it will unmerge them after loading) - this.assessment = this.programmingSubmission.tryLock(this.gradingConfig).orElseThrow(); + this.assessment = this.programmingSubmission.getFirstRoundAssessment().open(this.gradingConfig).orElseThrow(); // so we need to check the submission itself: - ResultDTO resultDTO = this.programmingSubmission.getRelevantResult().orElseThrow(); + ResultDTO resultDTO = this.programmingSubmission.getFirstRoundAssessment().result(); var feedbacks = ResultDTO.fetchDetailedFeedbacks( this.connection.getClient(), resultDTO.id(), - this.programmingSubmission.getParticipationId(), + this.programmingSubmission.getSubmission().getParticipationId(), resultDTO.feedbacks()); List feedbackTexts = new ArrayList<>(); diff --git a/src/test/java/edu/kit/kastel/sdq/artemis4j/ExamTest.java b/src/test/java/edu/kit/kastel/sdq/artemis4j/ExamTest.java index a326c00..0f6addc 100644 --- a/src/test/java/edu/kit/kastel/sdq/artemis4j/ExamTest.java +++ b/src/test/java/edu/kit/kastel/sdq/artemis4j/ExamTest.java @@ -20,6 +20,7 @@ import edu.kit.kastel.sdq.artemis4j.grading.ExamExerciseGroup; import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingExercise; import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingSubmission; +import edu.kit.kastel.sdq.artemis4j.grading.ProgrammingSubmissionWithResults; import edu.kit.kastel.sdq.artemis4j.grading.penalty.GradingConfig; import org.junit.jupiter.api.Test; @@ -50,9 +51,9 @@ void testExamAssessment() throws ArtemisClientException, IOException { GradingConfig config = GradingConfig.readFromString(Files.readString(Path.of("src/test/resources/config.json")), exercise); - ProgrammingSubmission roundOneSubmission = - findSubmission(exercise.fetchSubmissions(CorrectionRound.FIRST), STUDENT_USER); - Assessment roundOneAssessment = roundOneSubmission.tryLock(config).orElseThrow(); + var submission = findSubmission(exercise.fetchAllSubmissions(), STUDENT_USER); + + Assessment roundOneAssessment = submission.getFirstRoundAssessment().open(config).orElseThrow(); roundOneAssessment.clearAnnotations(); roundOneAssessment.addCustomAnnotation( config.getMistakeTypeById("custom"), @@ -63,9 +64,7 @@ void testExamAssessment() throws ArtemisClientException, IOException { -2.0); roundOneAssessment.submit(); - ProgrammingSubmission roundTwoSubmission = - findSubmission(exercise.fetchSubmissions(CorrectionRound.SECOND), STUDENT_USER); - Assessment roundTwoAssessment = roundTwoSubmission.tryLock(config).orElseThrow(); + Assessment roundTwoAssessment = submission.getSecondRoundAssessment().open(config).orElseThrow(); roundTwoAssessment.addCustomAnnotation( config.getMistakeTypeById("custom"), "src/edu/kit/informatik/BubbleSort.java", @@ -86,9 +85,9 @@ void testExamAssessment() throws ArtemisClientException, IOException { roundTwoAssessment.submit(); } - private ProgrammingSubmission findSubmission(List submissions, String student) { + private ProgrammingSubmissionWithResults findSubmission(List submissions, String student) { return submissions.stream() - .filter(submission -> submission.getParticipantIdentifier().equals(student)) + .filter(submission -> submission.getSubmission().getParticipantIdentifier().equals(student)) .findFirst() .orElseThrow(); }