use of de.tum.in.www1.artemis.domain.enumeration.Visibility in project Artemis by ls1intum.
the class ProgrammingExerciseTestCaseService method update.
/**
* Update the updatable attributes of the provided test case dtos. Returns an entry in the set for each test case that could be updated.
*
* @param exerciseId of exercise the test cases belong to.
* @param testCaseProgrammingExerciseTestCaseDTOS of the test cases to update the weights and visibility of.
* @return the updated test cases.
* @throws EntityNotFoundException if the programming exercise could not be found.
*/
public Set<ProgrammingExerciseTestCase> update(Long exerciseId, Set<ProgrammingExerciseTestCaseDTO> testCaseProgrammingExerciseTestCaseDTOS) throws EntityNotFoundException {
ProgrammingExercise programmingExercise = programmingExerciseRepository.findWithTestCasesById(exerciseId).orElseThrow(() -> new EntityNotFoundException("Programming Exercise", exerciseId));
Set<ProgrammingExerciseTestCase> existingTestCases = programmingExercise.getTestCases();
Set<ProgrammingExerciseTestCase> updatedTests = new HashSet<>();
for (ProgrammingExerciseTestCaseDTO programmingExerciseTestCaseDTO : testCaseProgrammingExerciseTestCaseDTOS) {
Optional<ProgrammingExerciseTestCase> matchingTestCaseOpt = existingTestCases.stream().filter(testCase -> testCase.getId().equals(programmingExerciseTestCaseDTO.getId())).findFirst();
if (matchingTestCaseOpt.isEmpty()) {
continue;
}
ProgrammingExerciseTestCase matchingTestCase = matchingTestCaseOpt.get();
matchingTestCase.setWeight(programmingExerciseTestCaseDTO.getWeight());
matchingTestCase.setVisibility(programmingExerciseTestCaseDTO.getVisibility());
matchingTestCase.setBonusMultiplier(programmingExerciseTestCaseDTO.getBonusMultiplier());
matchingTestCase.setBonusPoints(programmingExerciseTestCaseDTO.getBonusPoints());
validateTestCase(matchingTestCase);
updatedTests.add(matchingTestCase);
}
if (!isTestCaseWeightSumValid(programmingExercise, existingTestCases)) {
throw new BadRequestAlertException("The sum of all test case weights is 0 or below.", "TestCaseGrading", "weightSumError", true);
}
testCaseRepository.saveAll(updatedTests);
programmingExerciseTaskService.updateTasksFromProblemStatement(programmingExercise);
// At least one test was updated with a new weight or runAfterDueDate flag. We use this flag to inform the instructor about outdated student results.
programmingSubmissionService.setTestCasesChangedAndTriggerTestCaseUpdate(exerciseId);
return updatedTests;
}
use of de.tum.in.www1.artemis.domain.enumeration.Visibility in project Artemis by ls1intum.
the class ProgrammingExerciseTestCaseResource method updateTestCases.
/**
* Update the changeable fields of the provided test case dtos.
* We don't transfer the whole test case object here, because we need to make sure that only weights and visibility can be updated!
* Will only return test case objects in the response that could be updated.
*
* @param exerciseId of exercise the test cases belong to.
* @param testCaseProgrammingExerciseTestCaseDTOS of the test cases to update the weights and visibility of.
* @return the set of test cases for the given programming exercise.
*/
@PatchMapping(Endpoints.UPDATE_TEST_CASES)
@PreAuthorize("hasRole('EDITOR')")
public ResponseEntity<Set<ProgrammingExerciseTestCase>> updateTestCases(@PathVariable Long exerciseId, @RequestBody Set<ProgrammingExerciseTestCaseDTO> testCaseProgrammingExerciseTestCaseDTOS) {
log.debug("REST request to update the weights {} of the exercise {}", testCaseProgrammingExerciseTestCaseDTOS, exerciseId);
var programmingExercise = programmingExerciseRepository.findByIdWithTemplateAndSolutionParticipationElseThrow(exerciseId);
authCheckService.checkHasAtLeastRoleForExerciseElseThrow(Role.EDITOR, programmingExercise, null);
Set<ProgrammingExerciseTestCase> updatedTests = programmingExerciseTestCaseService.update(exerciseId, testCaseProgrammingExerciseTestCaseDTOS);
// A test case is now marked as AFTER_DUE_DATE: a scheduled score update might be needed.
if (updatedTests.stream().anyMatch(ProgrammingExerciseTestCase::isAfterDueDate)) {
programmingExerciseService.scheduleOperations(programmingExercise.getId());
}
// We don't need the linked exercise here.
for (ProgrammingExerciseTestCase testCase : updatedTests) {
testCase.setExercise(null);
}
return ResponseEntity.ok(updatedTests);
}
use of de.tum.in.www1.artemis.domain.enumeration.Visibility in project Artemis by ls1intum.
the class ProgrammingExerciseGradingServiceTest method shouldRecalculateScoreWithTestCaseBonusButNoExerciseBonus.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void shouldRecalculateScoreWithTestCaseBonusButNoExerciseBonus() {
// Set up test cases with bonus
var testCases = testCaseService.findByExerciseId(programmingExercise.getId()).stream().collect(Collectors.toMap(ProgrammingExerciseTestCase::getTestName, Function.identity()));
testCases.get("test1").active(true).visibility(Visibility.ALWAYS).weight(5.).bonusMultiplier(1D).setBonusPoints(7D);
testCases.get("test2").active(true).visibility(Visibility.ALWAYS).weight(2.).bonusMultiplier(2D).setBonusPoints(0D);
testCases.get("test3").active(true).visibility(Visibility.ALWAYS).weight(3.).bonusMultiplier(1D).setBonusPoints(10.5D);
testCaseRepository.saveAll(testCases.values());
Participation participation = database.addStudentParticipationForProgrammingExercise(programmingExercise, "student1");
var result1 = new Result();
result1.setParticipation(participation);
result1 = updateAndSaveAutomaticResult(result1, false, false, true);
var result2 = new Result();
result2.setParticipation(participation);
result2 = updateAndSaveAutomaticResult(result2, true, false, false);
var result3 = new Result();
result3.setParticipation(participation);
result3 = updateAndSaveAutomaticResult(result3, false, true, false);
var result4 = new Result();
result4.setParticipation(participation);
result4 = updateAndSaveAutomaticResult(result4, false, true, true);
var result5 = new Result();
result5.setParticipation(participation);
result5 = updateAndSaveAutomaticResult(result5, true, true, true);
var result6 = new Result();
result6.setParticipation(participation);
result6 = updateAndSaveAutomaticResult(result6, false, false, false);
// Build failure
var resultBF = new Result().feedbacks(List.of()).rated(true).score(0D).hasFeedback(false).resultString("Build Failed").completionDate(ZonedDateTime.now()).assessmentType(AssessmentType.AUTOMATIC);
resultBF.setParticipation(participation);
gradingService.calculateScoreForResult(resultBF, programmingExercise, true);
// Missing feedback
var resultMF = new Result();
resultMF.setParticipation(participation);
var feedbackMF = new Feedback().result(result).text("test3").positive(true).type(FeedbackType.AUTOMATIC).result(resultMF);
// List must be mutable
resultMF.feedbacks(new ArrayList<>(List.of(feedbackMF))).rated(true).score(0D).hasFeedback(true).completionDate(ZonedDateTime.now()).assessmentType(AssessmentType.AUTOMATIC);
gradingService.calculateScoreForResult(resultMF, programmingExercise, true);
// Assertions result1 - calculated
assertThat(result1.getScore()).isEqualTo(55D, Offset.offset(offsetByTenThousandth));
assertThat(result1.getResultString()).isEqualTo("1 of 3 passed");
assertThat(result1.getHasFeedback()).isTrue();
assertThat(result1.isSuccessful()).isFalse();
assertThat(result1.getFeedbacks()).hasSize(3);
// Assertions result2 - calculated
assertThat(result2.getScore()).isEqualTo(66.6667);
assertThat(result2.getResultString()).isEqualTo("1 of 3 passed");
assertThat(result2.getHasFeedback()).isTrue();
assertThat(result2.isSuccessful()).isFalse();
assertThat(result2.getFeedbacks()).hasSize(3);
// Assertions result3 - calculated
assertThat(result3.getScore()).isEqualTo(40D);
assertThat(result3.getResultString()).isEqualTo("1 of 3 passed");
assertThat(result3.getHasFeedback()).isTrue();
assertThat(result3.isSuccessful()).isFalse();
assertThat(result3.getFeedbacks()).hasSize(3);
// Assertions result4 - calculated
assertThat(result4.getScore()).isEqualTo(95D, Offset.offset(offsetByTenThousandth));
assertThat(result4.getResultString()).isEqualTo("2 of 3 passed");
assertThat(result4.getHasFeedback()).isTrue();
assertThat(result4.isSuccessful()).isFalse();
assertThat(result4.getFeedbacks()).hasSize(3);
// Assertions result5 - capped to 100
assertThat(result5.getScore()).isEqualTo(100D);
assertThat(result5.getResultString()).isEqualTo("3 of 3 passed");
assertThat(result5.getHasFeedback()).isFalse();
assertThat(result5.isSuccessful()).isTrue();
assertThat(result5.getFeedbacks()).hasSize(3);
// Assertions result6 - only negative feedback
assertThat(result6.getScore()).isEqualTo(0D);
assertThat(result6.getResultString()).isEqualTo("0 of 3 passed");
assertThat(result6.getHasFeedback()).isTrue();
assertThat(result6.isSuccessful()).isFalse();
assertThat(result6.getFeedbacks()).hasSize(3);
// Assertions resultBF - build failure
assertThat(resultBF.getScore()).isEqualTo(0D);
// Won't get touched by the service method
assertThat(resultBF.getResultString()).isEqualTo("Build Failed");
assertThat(resultBF.getHasFeedback()).isFalse();
// Won't get touched by the service method
assertThat(resultBF.isSuccessful()).isNull();
assertThat(resultBF.getFeedbacks()).isEmpty();
// Assertions resultMF - missing feedback will be created but is negative
assertThat(resultMF.getScore()).isEqualTo(55D, Offset.offset(offsetByTenThousandth));
assertThat(resultMF.getResultString()).isEqualTo("1 of 3 passed");
// Generated missing feedback is omitted
assertThat(resultMF.getHasFeedback()).isFalse();
assertThat(resultMF.isSuccessful()).isFalse();
// Feedback is created for test cases if missing
assertThat(resultMF.getFeedbacks()).hasSize(3);
}
use of de.tum.in.www1.artemis.domain.enumeration.Visibility in project Artemis by ls1intum.
the class ProgrammingExerciseGradingServiceTest method shouldRecalculateScoreWithTestCaseBonusAndExerciseBonus.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void shouldRecalculateScoreWithTestCaseBonusAndExerciseBonus() {
// Set up test cases with bonus
var testCases = testCaseService.findByExerciseId(programmingExercise.getId()).stream().collect(Collectors.toMap(ProgrammingExerciseTestCase::getTestName, Function.identity()));
testCases.get("test1").active(true).visibility(Visibility.ALWAYS).weight(4.).bonusMultiplier(1D).setBonusPoints(0D);
testCases.get("test2").active(true).visibility(Visibility.ALWAYS).weight(3.).bonusMultiplier(3D).setBonusPoints(21D);
testCases.get("test3").active(true).visibility(Visibility.ALWAYS).weight(3.).bonusMultiplier(2D).setBonusPoints(14D);
testCaseRepository.saveAll(testCases.values());
// Score should be capped at 200%
programmingExercise.setBonusPoints(programmingExercise.getMaxPoints());
programmingExerciseRepository.save(programmingExercise);
Participation participation = database.addStudentParticipationForProgrammingExercise(programmingExercise, "student1");
var result1 = new Result();
result1.setParticipation(participation);
result1 = updateAndSaveAutomaticResult(result1, false, false, true);
var result2 = new Result();
result2.setParticipation(participation);
result2 = updateAndSaveAutomaticResult(result2, true, false, true);
var result3 = new Result();
result3.setParticipation(participation);
result3 = updateAndSaveAutomaticResult(result3, true, true, false);
var result4 = new Result();
result4.setParticipation(participation);
result4 = updateAndSaveAutomaticResult(result4, false, true, true);
// Assertions result1 - calculated
assertThat(result1.getScore()).isEqualTo(93.3333);
assertThat(result1.getResultString()).isEqualTo("1 of 3 passed");
assertThat(result1.getHasFeedback()).isTrue();
assertThat(result1.isSuccessful()).isFalse();
assertThat(result1.getFeedbacks()).hasSize(3);
// Assertions result2 - calculated
assertThat(result2.getScore()).isEqualTo(133.3333);
assertThat(result2.getResultString()).isEqualTo("2 of 3 passed");
assertThat(result2.getHasFeedback()).isTrue();
assertThat(result2.isSuccessful()).isTrue();
assertThat(result2.getFeedbacks()).hasSize(3);
// Assertions result3 - calculated
assertThat(result3.getScore()).isEqualTo(180D, Offset.offset(offsetByTenThousandth));
assertThat(result3.getResultString()).isEqualTo("2 of 3 passed");
assertThat(result3.getHasFeedback()).isTrue();
assertThat(result3.isSuccessful()).isTrue();
assertThat(result3.getFeedbacks()).hasSize(3);
// Assertions result4 - capped at 200%
assertThat(result4.getScore()).isEqualTo(200D);
assertThat(result4.getResultString()).isEqualTo("2 of 3 passed");
assertThat(result4.getHasFeedback()).isTrue();
assertThat(result4.isSuccessful()).isTrue();
assertThat(result4.getFeedbacks()).hasSize(3);
}
Aggregations