Search in sources :

Example 6 with QuizScheduleService

use of de.tum.in.www1.artemis.service.scheduled.quiz.QuizScheduleService 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) 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) QuizScheduleService(de.tum.in.www1.artemis.service.scheduled.cache.quiz.QuizScheduleService) 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)

Example 7 with QuizScheduleService

use of de.tum.in.www1.artemis.service.scheduled.quiz.QuizScheduleService in project ArTEMiS by ls1intum.

the class QuizScheduleService method startSchedule.

/**
 * Start scheduler of quiz schedule service
 *
 * @param delayInMillis gap for which the QuizScheduleService should run repeatedly
 */
public void startSchedule(long delayInMillis) {
    if (scheduledProcessQuizSubmissions.isNull()) {
        try {
            var scheduledFuture = threadPoolTaskScheduler.scheduleAtFixedRate(new QuizProcessCacheTask(), 0, delayInMillis, TimeUnit.MILLISECONDS);
            scheduledProcessQuizSubmissions.set(scheduledFuture.getHandler());
            log.info("QuizScheduleService was started to run repeatedly with {} second delay.", delayInMillis / 1000.0);
        } catch (@SuppressWarnings("unused") DuplicateTaskException e) {
            log.warn("Quiz process cache task already registered");
        // this is expected if we run on multiple nodes
        }
        // schedule quiz start for all existing quizzes that are planned to start in the future
        List<QuizExercise> quizExercises = quizExerciseRepository.findAllPlannedToStartInTheFuture();
        log.info("Found {} quiz exercises with planned start in the future", quizExercises.size());
        for (QuizExercise quizExercise : quizExercises) {
            if (quizExercise.isCourseExercise()) {
                // only schedule quiz exercises in courses, not in exams
                // Note: the quiz exercise does not include questions and statistics, so we pass the id
                scheduleQuizStart(quizExercise.getId());
            }
        }
    } else {
        log.info("Cannot start quiz exercise schedule service, it is already RUNNING");
    }
}
Also used : QuizExercise(de.tum.in.www1.artemis.domain.quiz.QuizExercise)

Example 8 with QuizScheduleService

use of de.tum.in.www1.artemis.service.scheduled.quiz.QuizScheduleService in project Artemis by ls1intum.

the class QuizScheduleService method startSchedule.

/**
 * Start scheduler of quiz schedule service
 *
 * @param delayInMillis gap for which the QuizScheduleService should run repeatedly
 */
public void startSchedule(long delayInMillis) {
    if (scheduledProcessQuizSubmissions.isNull()) {
        try {
            var scheduledFuture = threadPoolTaskScheduler.scheduleAtFixedRate(new QuizProcessCacheTask(), 0, delayInMillis, TimeUnit.MILLISECONDS);
            scheduledProcessQuizSubmissions.set(scheduledFuture.getHandler());
            log.info("QuizScheduleService was started to run repeatedly with {} second delay.", delayInMillis / 1000.0);
        } catch (@SuppressWarnings("unused") DuplicateTaskException e) {
            log.warn("Quiz process cache task already registered");
        // this is expected if we run on multiple nodes
        }
        // schedule quiz start for all existing quizzes that are planned to start in the future
        List<QuizExercise> quizExercises = quizExerciseRepository.findAllPlannedToStartInTheFuture();
        log.info("Found {} quiz exercises with planned start in the future", quizExercises.size());
        for (QuizExercise quizExercise : quizExercises) {
            if (quizExercise.isCourseExercise()) {
                // only schedule quiz exercises in courses, not in exams
                // Note: the quiz exercise does not include questions and statistics, so we pass the id
                scheduleQuizStart(quizExercise.getId());
            }
        }
    } else {
        log.info("Cannot start quiz exercise schedule service, it is already RUNNING");
    }
}
Also used : QuizExercise(de.tum.in.www1.artemis.domain.quiz.QuizExercise)

Example 9 with QuizScheduleService

use of de.tum.in.www1.artemis.service.scheduled.quiz.QuizScheduleService in project Artemis by ls1intum.

the class QuizScheduleService method startSchedule.

/**
 * Start scheduler of quiz schedule service
 *
 * @param delayInMillis gap for which the QuizScheduleService should run repeatedly
 */
public void startSchedule(long delayInMillis) {
    if (scheduledProcessQuizSubmissions.isNull()) {
        try {
            var scheduledFuture = threadPoolTaskScheduler.scheduleAtFixedRate(new QuizProcessCacheTask(), 0, delayInMillis, TimeUnit.MILLISECONDS);
            scheduledProcessQuizSubmissions.set(scheduledFuture.getHandler());
            log.info("QuizScheduleService was started to run repeatedly with {} second delay.", delayInMillis / 1000.0);
        } catch (@SuppressWarnings("unused") DuplicateTaskException e) {
            log.warn("Quiz process cache task already registered");
        // this is expected if we run on multiple nodes
        }
        // schedule quiz start for all existing quizzes that are planned to start in the future
        List<QuizExercise> quizExercises = quizExerciseRepository.findAllPlannedToStartInTheFuture();
        log.info("Found {} quiz exercises with planned start in the future", quizExercises.size());
        for (QuizExercise quizExercise : quizExercises) {
            if (quizExercise.isCourseExercise()) {
                // only schedule quiz exercises in courses, not in exams
                // Note: the quiz exercise does not include questions and statistics, so we pass the id
                scheduleQuizStart(quizExercise.getId());
            }
        }
    } else {
        log.info("Cannot start quiz exercise schedule service, it is already RUNNING");
    }
}
Also used : QuizExercise(de.tum.in.www1.artemis.domain.quiz.QuizExercise)

Aggregations

QuizExercise (de.tum.in.www1.artemis.domain.quiz.QuizExercise)5 QuizSubmission (de.tum.in.www1.artemis.domain.quiz.QuizSubmission)4 SubmittedAnswer (de.tum.in.www1.artemis.domain.quiz.SubmittedAnswer)4 QuizSubmissionException (de.tum.in.www1.artemis.exception.QuizSubmissionException)4 Result (de.tum.in.www1.artemis.domain.Result)2 AssessmentType (de.tum.in.www1.artemis.domain.enumeration.AssessmentType)2 QuizMode (de.tum.in.www1.artemis.domain.enumeration.QuizMode)2 SubmissionType (de.tum.in.www1.artemis.domain.enumeration.SubmissionType)2 Participation (de.tum.in.www1.artemis.domain.participation.Participation)2 StudentParticipation (de.tum.in.www1.artemis.domain.participation.StudentParticipation)2 QuizExerciseRepository (de.tum.in.www1.artemis.repository.QuizExerciseRepository)2 QuizSubmissionRepository (de.tum.in.www1.artemis.repository.QuizSubmissionRepository)2 ResultRepository (de.tum.in.www1.artemis.repository.ResultRepository)2 EntityNotFoundException (de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException)2 ZonedDateTime (java.time.ZonedDateTime)2 ArrayList (java.util.ArrayList)2 Optional (java.util.Optional)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 MessageMapping (org.springframework.messaging.handler.annotation.MessageMapping)2