use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseScheduleService method invokeOperationOnAllParticipationsThatSatisfy.
/**
* Invokes the given <code>operation</code> on all student participations that satisfy the <code>condition</code>-{@link Predicate}.
* <p>
*
* @param programmingExerciseId the programming exercise whose participations should be processed
* @param operation the operation to perform
* @param condition the condition that tests whether to invoke the operation on a participation
* @param operationName the name of the operation, this is only used for logging
* @return a list containing all participations for which the operation has failed with an exception
* @throws EntityNotFoundException if the programming exercise can't be found.
*/
private List<ProgrammingExerciseStudentParticipation> invokeOperationOnAllParticipationsThatSatisfy(Long programmingExerciseId, BiConsumer<ProgrammingExercise, ProgrammingExerciseStudentParticipation> operation, Predicate<ProgrammingExerciseStudentParticipation> condition, String operationName) {
log.info("Invoking (scheduled) task '{}' for programming exercise with id {}.", operationName, programmingExerciseId);
ProgrammingExercise programmingExercise = programmingExerciseRepository.findWithEagerStudentParticipationsById(programmingExerciseId).orElseThrow(() -> new EntityNotFoundException("ProgrammingExercise", programmingExerciseId));
List<ProgrammingExerciseStudentParticipation> failedOperations = new ArrayList<>();
for (StudentParticipation studentParticipation : programmingExercise.getStudentParticipations()) {
ProgrammingExerciseStudentParticipation programmingExerciseStudentParticipation = (ProgrammingExerciseStudentParticipation) studentParticipation;
try {
if (condition.test(programmingExerciseStudentParticipation)) {
operation.accept(programmingExercise, programmingExerciseStudentParticipation);
}
} catch (Exception e) {
log.error(String.format("'%s' failed for programming exercise with id %d for student repository with participation id %d", operationName, programmingExercise.getId(), studentParticipation.getId()), e);
failedOperations.add(programmingExerciseStudentParticipation);
}
}
return failedOperations;
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseParticipation method isLocked.
/**
* Check if the participation is locked.
* This is the case when the participation is a ProgrammingExerciseStudentParticipation,
* the buildAndTestAfterDueDate of the exercise is set and the due date has passed,
* or if manual correction is involved and the due date has passed.
*
* Locked means that the student can't make any changes to their repository anymore.
* While we can control this easily in the remote VCS, we need to check this manually
* for the local repository on the Artemis server.
*
* @return true if repository is locked, false if not.
*/
@JsonIgnore
default boolean isLocked() {
if (!(this instanceof ProgrammingExerciseStudentParticipation)) {
return false;
}
final ProgrammingExercise programmingExercise = getProgrammingExercise();
final ZonedDateTime now = ZonedDateTime.now();
boolean isAfterDueDate = false;
if (getIndividualDueDate() != null) {
isAfterDueDate = now.isAfter(getIndividualDueDate());
} else if (programmingExercise.getDueDate() != null) {
isAfterDueDate = now.isAfter(programmingExercise.getDueDate());
}
// Editing is allowed if build and test after due date is not set and no manual correction is involved
// (this should match CodeEditorStudentContainerComponent.repositoryIsLocked on the client-side)
boolean isEditingAfterDueAllowed = programmingExercise.getBuildAndTestStudentSubmissionsAfterDueDate() == null && programmingExercise.getAssessmentType() != AssessmentType.MANUAL && programmingExercise.getAssessmentType() != AssessmentType.SEMI_AUTOMATIC && !programmingExercise.areManualResultsAllowed();
return isAfterDueDate && !isEditingAfterDueAllowed;
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseParticipationResource method getParticipationWithLatestResultForStudentParticipation.
/**
* Get the given student participation with its latest result and feedbacks.
*
* @param participationId for which to retrieve the student participation with latest result and feedbacks.
* @return the ResponseEntity with status 200 (OK) and the participation with its latest result in the body.
*/
@GetMapping("/programming-exercise-participations/{participationId}/student-participation-with-latest-result-and-feedbacks")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<Participation> getParticipationWithLatestResultForStudentParticipation(@PathVariable Long participationId) {
ProgrammingExerciseStudentParticipation participation = programmingExerciseStudentParticipationRepository.findStudentParticipationWithLatestResultAndFeedbacksAndRelatedSubmissions(participationId).orElseThrow(() -> new EntityNotFoundException("Participation", participationId));
if (!programmingExerciseParticipationService.canAccessParticipation(participation)) {
throw new AccessForbiddenException("participation", participationId);
}
if (!authCheckService.isAtLeastTeachingAssistantForExercise(participation.getExercise())) {
// hide details that should not be shown to the students
participation.getExercise().filterSensitiveInformation();
participation.getResults().forEach(result -> filterSensitiveInformationInResult(participation, result));
}
return ResponseEntity.ok(participation);
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingSubmissionResultSimulationResource method createNewProgrammingExerciseResult.
/**
* This method is used to notify artemis that there is a new programming exercise build result.
* This result is only a SIMULATION for the testing of programming exercises without a connection
* to the VCS and CI server
* This functionality is only for testing purposes (noVersionControlAndContinuousIntegrationAvailable)
* @param exerciseId id of the exercise
* @return HTTP OK and Result
*/
@PostMapping(Endpoints.RESULTS_SIMULATION)
@PreAuthorize("hasRole('EDITOR')")
public ResponseEntity<Result> createNewProgrammingExerciseResult(@PathVariable Long exerciseId) {
log.debug("Received result notify (NEW)");
User user = userRepository.getUserWithGroupsAndAuthorities();
ProgrammingExercise programmingExercise = programmingExerciseRepository.findByIdWithStudentParticipationsAndLegalSubmissionsElseThrow(exerciseId);
var studentParticipation = participationService.findOneByExerciseAndParticipantAnyState(programmingExercise, user).orElseThrow(() -> new EntityNotFoundException("Participation for programming exercise " + programmingExercise.getId() + " and user " + user.getLogin() + " not found!"));
var programmingExerciseStudentParticipation = (ProgrammingExerciseStudentParticipation) studentParticipation;
Result result = programmingSubmissionResultSimulationService.createResult(programmingExerciseStudentParticipation);
messagingService.broadcastNewResult(programmingExerciseStudentParticipation, result);
log.info("The new result for {} was saved successfully", programmingExerciseStudentParticipation.getBuildPlanId());
try {
return ResponseEntity.created(new URI("/api/results" + result.getId())).body(result);
} catch (URISyntaxException e) {
log.error("Error while simulating a result", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createAlert(applicationName, "An error occurred while simulating a result: " + e.getMessage(), "errorResult")).body(null);
}
}
use of de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation in project ArTEMiS by ls1intum.
the class ProgrammingExerciseTest method findAppropriateSubmissionRespectingIndividualDueDate.
@ParameterizedTest(name = "{displayName} [{index}] {argumentsWithNames}")
@ValueSource(booleans = { true, false })
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
void findAppropriateSubmissionRespectingIndividualDueDate(boolean isSubmissionAfterIndividualDueDate) {
ProgrammingExercise exercise = programmingExerciseRepository.findByIdElseThrow(programmingExerciseId);
exercise.setDueDate(ZonedDateTime.now());
exercise = programmingExerciseRepository.save(exercise);
ProgrammingSubmission submission = new ProgrammingSubmission();
submission.setType(SubmissionType.OTHER);
if (isSubmissionAfterIndividualDueDate) {
submission.setSubmissionDate(ZonedDateTime.now().plusHours(26));
} else {
// submission time after exercise due date but before individual due date
submission.setSubmissionDate(ZonedDateTime.now().plusHours(1));
}
submission = database.addProgrammingSubmission(exercise, submission, "student1");
ProgrammingExerciseStudentParticipation participation = participationRepository.findByExerciseIdAndStudentLogin(programmingExerciseId, "student1").get();
participation.setIndividualDueDate(ZonedDateTime.now().plusDays(1));
submission.setParticipation(participation);
Submission latestValidSubmission = exercise.findAppropriateSubmissionByResults(Set.of(submission));
if (isSubmissionAfterIndividualDueDate) {
assertThat(latestValidSubmission).isNull();
} else {
assertThat(latestValidSubmission).isEqualTo(submission);
}
}
Aggregations