Search in sources :

Example 31 with Participation

use of de.tum.in.www1.artemis.domain.participation.Participation in project ArTEMiS by ls1intum.

the class ParticipationResource method createParticipation.

/**
 * POST  /participations : Create a new participation.
 *
 * @param participation the participation to create
 * @return the ResponseEntity with status 201 (Created) and with body the new participation, or with status 400 (Bad Request) if the participation has already an ID
 * @throws URISyntaxException if the Location URI syntax is incorrect
 */
@PostMapping("/participations")
@PreAuthorize("hasAnyRole('TA', 'INSTRUCTOR', 'ADMIN')")
@Timed
public ResponseEntity<Participation> createParticipation(@RequestBody Participation participation) throws URISyntaxException {
    log.debug("REST request to save Participation : {}", participation);
    Course course = participation.getExercise().getCourse();
    if (!courseService.userHasTAPermissions(course)) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
    }
    if (participation.getId() != null) {
        throw new BadRequestAlertException("A new participation cannot already have an ID", ENTITY_NAME, "idexists");
    }
    Participation result = participationService.save(participation);
    return ResponseEntity.created(new URI("/api/participations/" + result.getId())).headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())).body(result);
}
Also used : BadRequestAlertException(de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException) URI(java.net.URI) Timed(com.codahale.metrics.annotation.Timed) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize)

Example 32 with Participation

use of de.tum.in.www1.artemis.domain.participation.Participation in project ArTEMiS by ls1intum.

the class ExerciseService method cleanup.

/**
 * Delete build plans (except BASE) and optionally repositores of all exercise participations.
 *
 * @param id id of the exercise for which build plans in respective participations are deleted
 */
@Transactional
public java.io.File cleanup(Long id, boolean deleteRepositories) throws java.io.IOException {
    Exercise exercise = findOneLoadParticipations(id);
    log.info("Request to cleanup all participations for Exercise : {}", exercise.getTitle());
    List<Repository> studentRepositories = new ArrayList<>();
    Path finalZipFilePath = null;
    if (Optional.ofNullable(exercise).isPresent() && exercise instanceof ProgrammingExercise) {
        exercise.getParticipations().forEach(participation -> {
            if (participation.getBuildPlanId() != null) {
                // ignore participations without build plan id
                try {
                    continuousIntegrationService.get().deleteBuildPlan(participation.getBuildPlanId());
                } catch (BambooException ex) {
                    log.error(ex.getMessage());
                    if (ex.getCause() != null) {
                        log.error(ex.getCause().getMessage());
                    }
                }
                participation.setInitializationState(ParticipationState.INACTIVE);
                participation.setBuildPlanId(null);
                participationService.save(participation);
            }
            if (deleteRepositories == true && participation.getRepositoryUrl() != null) {
                // ignore participations without repository URL
                try {
                    // 1. clone the repository
                    Repository repo = gitService.get().getOrCheckoutRepository(participation);
                    // 2. collect the repo file
                    studentRepositories.add(repo);
                } catch (GitAPIException | IOException ex) {
                    log.error("Archiving and deleting the repository " + participation.getRepositoryUrlAsUrl() + " did not work as expected", ex);
                }
            }
        });
        if (deleteRepositories == false) {
            // in this case, we are done
            return null;
        }
        if (studentRepositories.isEmpty()) {
            log.info("No student repositories have been found.");
            return null;
        }
        // from here on, deleteRepositories is true and does not need to be evaluated again
        log.info("Create zip file for all repositories");
        Files.createDirectories(Paths.get("zippedRepos"));
        finalZipFilePath = Paths.get("zippedRepos", exercise.getCourse().getTitle() + " " + exercise.getTitle() + " Student Repositories.zip");
        zipAllRepositories(studentRepositories, finalZipFilePath);
        exercise.getParticipations().forEach(participation -> {
            if (participation.getRepositoryUrl() != null) {
                // ignore participations without repository URL
                try {
                    // 3. delete the locally cloned repo again
                    gitService.get().deleteLocalRepository(participation);
                } catch (IOException e) {
                    log.error("Archiving and deleting the repository " + participation.getRepositoryUrlAsUrl() + " did not work as expected", e);
                }
                // 4. finally delete the repository on the VC Server
                versionControlService.get().deleteRepository(participation.getRepositoryUrlAsUrl());
                participation.setRepositoryUrl(null);
                participation.setInitializationState(ParticipationState.FINISHED);
                participationService.save(participation);
            }
        });
        scheduleForDeletion(finalZipFilePath, 300);
    } else {
        log.info("Exercise with id {} is not an instance of ProgrammingExercise. Ignoring the request to cleanup repositories and build plan", id);
        return null;
    }
    return new java.io.File(finalZipFilePath.toString());
}
Also used : Path(java.nio.file.Path) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) ExerciseRepository(de.tum.in.www1.artemis.repository.ExerciseRepository) BambooException(de.tum.in.www1.artemis.exception.BambooException) IOException(java.io.IOException) Transactional(org.springframework.transaction.annotation.Transactional)

Example 33 with Participation

use of de.tum.in.www1.artemis.domain.participation.Participation in project ArTEMiS by ls1intum.

the class GitService method getOrCheckoutRepository.

/**
 * Get the local repository for a given participation.
 * If the local repo does not exist yet, it will be checked out.
 *
 * @param participation Participation the remote repository belongs to.
 * @return
 * @throws IOException
 * @throws GitAPIException
 */
public Repository getOrCheckoutRepository(Participation participation) throws IOException, GitAPIException {
    URL repoUrl = participation.getRepositoryUrlAsUrl();
    Repository repository = getOrCheckoutRepository(repoUrl);
    repository.setParticipation(participation);
    return repository;
}
Also used : Repository(de.tum.in.www1.artemis.domain.Repository) URL(java.net.URL)

Example 34 with Participation

use of de.tum.in.www1.artemis.domain.participation.Participation in project ArTEMiS by ls1intum.

the class QuizStatisticService method recalculateStatistics.

/**
 * 1. Go through all Results in the Participation and recalculate the score
 * 2. Recalculate the statistics of the given quizExercise
 *
 * @param quizExercise the changed QuizExercise object which will be used to recalculate the existing Results and Statistics
 */
public void recalculateStatistics(QuizExercise quizExercise) {
    // reset all statistics
    if (quizExercise.getQuizPointStatistic() != null) {
        quizExercise.getQuizPointStatistic().resetStatistic();
    } else {
        var quizPointStatistic = new QuizPointStatistic();
        quizExercise.setQuizPointStatistic(quizPointStatistic);
        quizPointStatistic.setQuiz(quizExercise);
        quizExercise.recalculatePointCounters();
    }
    for (QuizQuestion quizQuestion : quizExercise.getQuizQuestions()) {
        if (quizQuestion.getQuizQuestionStatistic() != null) {
            quizQuestion.getQuizQuestionStatistic().resetStatistic();
        }
    }
    // add the Results in every participation of the given quizExercise to the statistics
    for (Participation participation : studentParticipationRepository.findByExerciseId(quizExercise.getId())) {
        Result latestRatedResult = null;
        Result latestUnratedResult = null;
        // update all Results of a participation
        for (Result result : resultRepository.findAllByParticipationIdOrderByCompletionDateDesc(participation.getId())) {
            // find the latest rated Result
            if (Boolean.TRUE.equals(result.isRated()) && (latestRatedResult == null || latestRatedResult.getCompletionDate().isBefore(result.getCompletionDate()))) {
                latestRatedResult = result;
            }
            // find latest unrated Result
            if (Boolean.FALSE.equals(result.isRated()) && (latestUnratedResult == null || latestUnratedResult.getCompletionDate().isBefore(result.getCompletionDate()))) {
                latestUnratedResult = result;
            }
        }
        // update statistics with the latest rated und unrated Result
        quizExercise.addResultToAllStatistics(latestRatedResult);
        quizExercise.addResultToAllStatistics(latestUnratedResult);
    }
    // save changed Statistics
    quizPointStatisticRepository.save(quizExercise.getQuizPointStatistic());
    quizPointStatisticRepository.flush();
    for (QuizQuestion quizQuestion : quizExercise.getQuizQuestions()) {
        if (quizQuestion.getQuizQuestionStatistic() != null) {
            quizQuestionStatisticRepository.save(quizQuestion.getQuizQuestionStatistic());
            quizQuestionStatisticRepository.flush();
        }
    }
}
Also used : Participation(de.tum.in.www1.artemis.domain.participation.Participation) Result(de.tum.in.www1.artemis.domain.Result)

Example 35 with Participation

use of de.tum.in.www1.artemis.domain.participation.Participation in project ArTEMiS by ls1intum.

the class QuizSubmissionService method checkSubmissionForLiveModeOrThrow.

/**
 * Check that the user is allowed to currently submit to the specified exercise and throws an exception if not
 */
private void checkSubmissionForLiveModeOrThrow(Long exerciseId, String userLogin, String logText, long start) throws QuizSubmissionException {
    // check if submission is still allowed
    QuizExercise quizExercise = quizScheduleService.getQuizExercise(exerciseId);
    if (quizExercise == null) {
        // Fallback solution
        log.info("Quiz not in QuizScheduleService cache, fetching from DB");
        quizExercise = quizExerciseRepository.findByIdElseThrow(exerciseId);
        quizExercise.setQuizBatches(null);
    }
    log.debug("{}: Received quiz exercise for user {} in quiz {} in {} µs.", logText, userLogin, exerciseId, (System.nanoTime() - start) / 1000);
    if (!quizExercise.isQuizStarted() || quizExercise.isQuizEnded()) {
        throw new QuizSubmissionException("The quiz is not active");
    }
    var cachedSubmission = quizScheduleService.getQuizSubmission(exerciseId, userLogin);
    if (cachedSubmission.isSubmitted()) {
        // the old submission has not yet been processed, so don't allow a new one yet
        throw new QuizSubmissionException("You have already submitted the quiz");
    }
    if (quizExercise.getQuizMode() == QuizMode.SYNCHRONIZED) {
        // the batch exists if the quiz is active, otherwise a new inactive batch is returned
        if (!quizBatchService.getOrCreateSynchronizedQuizBatch(quizExercise).isSubmissionAllowed()) {
            throw new QuizSubmissionException("The quiz is not active");
        }
        // in synchronized mode we cache the participation after we processed the submission, so we can check there if the submission was already processed
        var cachedParticipation = quizScheduleService.getParticipation(exerciseId, userLogin);
        if (cachedParticipation != null && cachedParticipation.getResults().stream().anyMatch(r -> r.getSubmission().isSubmitted())) {
            throw new QuizSubmissionException("You have already submitted the quiz");
        }
    } else {
        // in the other modes the resubmission checks are done at join time and the student-batch association is removed when processing a submission
        var batch = quizBatchService.getQuizBatchForStudentByLogin(quizExercise, userLogin);
        // there is no way of distinguishing these two error cases without an extra db query
        if (batch.isEmpty()) {
            throw new QuizSubmissionException("You did not join or have already submitted the quiz");
        }
        if (!batch.get().isSubmissionAllowed()) {
            throw new QuizSubmissionException("The quiz is not active");
        }
    }
// TODO: additional checks that may be beneficial
// for example it is possible for students that are not members of the course to submit the quiz
// but for performance reasons the checks may have to be done in the quiz submission service where no feedback for the students can be generated
}
Also used : Logger(org.slf4j.Logger) QuizExercise(de.tum.in.www1.artemis.domain.quiz.QuizExercise) QuizSubmission(de.tum.in.www1.artemis.domain.quiz.QuizSubmission) QuizSubmissionException(de.tum.in.www1.artemis.exception.QuizSubmissionException) QuizScheduleService(de.tum.in.www1.artemis.service.scheduled.quiz.QuizScheduleService) ZonedDateTime(java.time.ZonedDateTime) Participation(de.tum.in.www1.artemis.domain.participation.Participation) LoggerFactory(org.slf4j.LoggerFactory) SubmissionType(de.tum.in.www1.artemis.domain.enumeration.SubmissionType) AssessmentType(de.tum.in.www1.artemis.domain.enumeration.AssessmentType) ArrayList(java.util.ArrayList) Result(de.tum.in.www1.artemis.domain.Result) EntityNotFoundException(de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException) QuizMode(de.tum.in.www1.artemis.domain.enumeration.QuizMode) Service(org.springframework.stereotype.Service) QuizExerciseRepository(de.tum.in.www1.artemis.repository.QuizExerciseRepository) Optional(java.util.Optional) StudentParticipation(de.tum.in.www1.artemis.domain.participation.StudentParticipation) SubmittedAnswer(de.tum.in.www1.artemis.domain.quiz.SubmittedAnswer) QuizSubmissionRepository(de.tum.in.www1.artemis.repository.QuizSubmissionRepository) ResultRepository(de.tum.in.www1.artemis.repository.ResultRepository) QuizSubmissionException(de.tum.in.www1.artemis.exception.QuizSubmissionException) QuizExercise(de.tum.in.www1.artemis.domain.quiz.QuizExercise)

Aggregations

StudentParticipation (de.tum.in.www1.artemis.domain.participation.StudentParticipation)181 WithMockUser (org.springframework.security.test.context.support.WithMockUser)138 Test (org.junit.jupiter.api.Test)124 ProgrammingExerciseStudentParticipation (de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation)70 Participation (de.tum.in.www1.artemis.domain.participation.Participation)54 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)50 ZonedDateTime (java.time.ZonedDateTime)47 ModelingSubmission (de.tum.in.www1.artemis.domain.modeling.ModelingSubmission)44 PreAuthorize (org.springframework.security.access.prepost.PreAuthorize)44 ModelingExercise (de.tum.in.www1.artemis.domain.modeling.ModelingExercise)42 EntityNotFoundException (de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException)42 AbstractSpringIntegrationBambooBitbucketJiraTest (de.tum.in.www1.artemis.AbstractSpringIntegrationBambooBitbucketJiraTest)38 QuizExercise (de.tum.in.www1.artemis.domain.quiz.QuizExercise)38 TextPlagiarismResult (de.tum.in.www1.artemis.domain.plagiarism.text.TextPlagiarismResult)34 Collectors (java.util.stream.Collectors)34 HttpHeaders (org.springframework.http.HttpHeaders)34 de.tum.in.www1.artemis.domain (de.tum.in.www1.artemis.domain)33 Result (de.tum.in.www1.artemis.domain.Result)33 Exam (de.tum.in.www1.artemis.domain.exam.Exam)32 ModelingPlagiarismResult (de.tum.in.www1.artemis.domain.plagiarism.modeling.ModelingPlagiarismResult)32