use of de.tum.in.www1.artemis.domain.quiz.QuizExercise in project Artemis by ls1intum.
the class QuizSubmissionWebsocketService method saveSubmission.
// TODO it would be nice to have some kind of startQuiz call that creates the participation with an initialization date. This should happen when the quiz is first shown
// to the user. Then we also could find out how long students work on the quiz on average
/**
* Saves a quiz submission into the hash maps. Submitted quizzes are marked to be saved into the database in the QuizScheduleService
*
* @param exerciseId the exerciseID to the corresponding QuizExercise
* @param quizSubmission the submission which should be saved
* @param principal refers to the user who initiated the request
*/
@MessageMapping("/topic/quizExercise/{exerciseId}/submission")
public void saveSubmission(@DestinationVariable Long exerciseId, @Payload QuizSubmission quizSubmission, Principal principal) {
// Without this, custom jpa repository methods don't work in websocket channel.
SecurityUtils.setAuthorizationObject();
String username = principal.getName();
try {
QuizSubmission updatedQuizSubmission = quizSubmissionService.saveSubmissionForLiveMode(exerciseId, quizSubmission, username, false);
// send updated submission over websocket (use a thread to prevent that the outbound channel blocks the inbound channel (e.g. due a slow client))
// to improve the performance, this is currently deactivated: slow clients might lead to bottlenecks so that more important messages can not be distributed any more
// new Thread(() -> sendSubmissionToUser(username, exerciseId, quizSubmission)).start();
// log.info("WS.Inbound: Sent quiz submission (async) back to user {} in quiz {} after {} µs ", principal.getName(), exerciseId, (System.nanoTime() - start) / 1000);
} catch (QuizSubmissionException ex) {
// send error message over websocket (use a thread to prevent that the outbound channel blocks the inbound channel (e.g. due a slow client))
new Thread(() -> messagingTemplate.convertAndSendToUser(username, "/topic/quizExercise/" + exerciseId + "/submission", new WebsocketError(ex.getMessage()))).start();
}
}
use of de.tum.in.www1.artemis.domain.quiz.QuizExercise in project Artemis by ls1intum.
the class QuizScheduleService method removeUnnecessaryObjectsBeforeSendingToClient.
private void removeUnnecessaryObjectsBeforeSendingToClient(StudentParticipation participation) {
if (participation.getExercise() != null) {
var quizExercise = (QuizExercise) participation.getExercise();
// we do not need the course and lectures
quizExercise.setCourse(null);
// students should not see statistics
// TODO: this would be useful, but leads to problems when the quiz schedule service wants to access the statistics again later on
// quizExercise.setQuizPointStatistic(null);
// quizExercise.getQuizQuestions().forEach(quizQuestion -> quizQuestion.setQuizQuestionStatistic(null));
}
// submissions are part of results, so we do not need them twice
participation.setSubmissions(null);
participation.setParticipant(null);
if (participation.getResults() != null && participation.getResults().size() > 0) {
QuizSubmission quizSubmission = (QuizSubmission) participation.getResults().iterator().next().getSubmission();
if (quizSubmission != null && quizSubmission.getSubmittedAnswers() != null) {
for (SubmittedAnswer submittedAnswer : quizSubmission.getSubmittedAnswers()) {
if (submittedAnswer.getQuizQuestion() != null) {
// we do not need all information of the questions again, they are already stored in the exercise
var question = submittedAnswer.getQuizQuestion();
submittedAnswer.setQuizQuestion(question.copyQuestionId());
}
}
}
}
}
use of de.tum.in.www1.artemis.domain.quiz.QuizExercise in project Artemis by ls1intum.
the class QuizScheduleService method executeQuizStartNowTask.
/**
* Internal method to start and send the {@link QuizExercise} to the clients when called
*/
void executeQuizStartNowTask(Long quizExerciseId) {
quizCache.performCacheWriteIfPresent(quizExerciseId, quizExerciseCache -> {
quizExerciseCache.getQuizStart().clear();
log.debug("Removed quiz {} start tasks", quizExerciseId);
return quizExerciseCache;
});
log.debug("Sending quiz {} start", quizExerciseId);
QuizExercise quizExercise = quizExerciseRepository.findOneWithQuestionsAndStatistics(quizExerciseId);
updateQuizExercise(quizExercise);
quizMessagingService.sendQuizExerciseToSubscribedClients(quizExercise, "start-now");
}
use of de.tum.in.www1.artemis.domain.quiz.QuizExercise in project Artemis by ls1intum.
the class DatabaseUtilService method createSubmissionAndResult.
public Result createSubmissionAndResult(StudentParticipation studentParticipation, long scoreAwarded, boolean rated) {
Exercise exercise = studentParticipation.getExercise();
Submission submission;
if (exercise instanceof ProgrammingExercise) {
submission = new ProgrammingSubmission();
} else if (exercise instanceof ModelingExercise) {
submission = new ModelingSubmission();
} else if (exercise instanceof TextExercise) {
submission = new TextSubmission();
} else if (exercise instanceof FileUploadExercise) {
submission = new FileUploadSubmission();
} else if (exercise instanceof QuizExercise) {
submission = new QuizSubmission();
} else {
throw new RuntimeException("Unsupported exercise type: " + exercise);
}
submission.setType(SubmissionType.MANUAL);
submission.setParticipation(studentParticipation);
submission = submissionRepository.saveAndFlush(submission);
Result result = ModelFactory.generateResult(rated, scoreAwarded);
result.setParticipation(studentParticipation);
result.setSubmission(submission);
result.completionDate(ZonedDateTime.now());
submission.addResult(result);
submission = submissionRepository.saveAndFlush(submission);
return submission.getResults().get(0);
}
use of de.tum.in.www1.artemis.domain.quiz.QuizExercise in project Artemis by ls1intum.
the class DatabaseUtilService method addExerciseGroupsAndExercisesToExam.
public Exam addExerciseGroupsAndExercisesToExam(Exam exam, boolean withProgrammingExercise) {
// text
ModelFactory.generateExerciseGroup(true, exam);
// quiz
ModelFactory.generateExerciseGroup(true, exam);
// file upload
ModelFactory.generateExerciseGroup(true, exam);
// modeling
ModelFactory.generateExerciseGroup(true, exam);
// bonus text
ModelFactory.generateExerciseGroup(true, exam);
// not included text
ModelFactory.generateExerciseGroup(true, exam);
exam.setNumberOfExercisesInExam(6);
exam.setMaxPoints(24);
exam = examRepository.save(exam);
// NOTE: we have to reassign, otherwise we get problems, because the objects have changed
var exerciseGroup0 = exam.getExerciseGroups().get(0);
var exerciseGroup1 = exam.getExerciseGroups().get(1);
var exerciseGroup2 = exam.getExerciseGroups().get(2);
var exerciseGroup3 = exam.getExerciseGroups().get(3);
var exerciseGroup4 = exam.getExerciseGroups().get(4);
var exerciseGroup5 = exam.getExerciseGroups().get(5);
TextExercise textExercise1 = ModelFactory.generateTextExerciseForExam(exerciseGroup0);
TextExercise textExercise2 = ModelFactory.generateTextExerciseForExam(exerciseGroup0);
textExercise1.setKnowledge(textAssessmentKnowledgeService.createNewKnowledge());
textExercise2.setKnowledge(textAssessmentKnowledgeService.createNewKnowledge());
exerciseGroup0.setExercises(Set.of(textExercise1, textExercise2));
exerciseRepo.save(textExercise1);
exerciseRepo.save(textExercise2);
QuizExercise quizExercise1 = createQuizForExam(exerciseGroup1);
QuizExercise quizExercise2 = createQuizForExam(exerciseGroup1);
exerciseGroup1.setExercises(Set.of(quizExercise1, quizExercise2));
exerciseRepo.save(quizExercise1);
exerciseRepo.save(quizExercise2);
FileUploadExercise fileUploadExercise1 = ModelFactory.generateFileUploadExerciseForExam("pdf", exerciseGroup2);
FileUploadExercise fileUploadExercise2 = ModelFactory.generateFileUploadExerciseForExam("pdf", exerciseGroup2);
exerciseGroup2.setExercises(Set.of(fileUploadExercise1, fileUploadExercise2));
exerciseRepo.save(fileUploadExercise1);
exerciseRepo.save(fileUploadExercise2);
ModelingExercise modelingExercise1 = ModelFactory.generateModelingExerciseForExam(DiagramType.ClassDiagram, exerciseGroup3);
ModelingExercise modelingExercise2 = ModelFactory.generateModelingExerciseForExam(DiagramType.ClassDiagram, exerciseGroup3);
modelingExercise1.setKnowledge(modelAssessmentKnowledgeService.createNewKnowledge());
modelingExercise2.setKnowledge(modelAssessmentKnowledgeService.createNewKnowledge());
exerciseGroup3.setExercises(Set.of(modelingExercise1, modelingExercise2));
exerciseRepo.save(modelingExercise1);
exerciseRepo.save(modelingExercise2);
TextExercise bonusTextExercise = ModelFactory.generateTextExerciseForExam(exerciseGroup4);
bonusTextExercise.setIncludedInOverallScore(IncludedInOverallScore.INCLUDED_AS_BONUS);
bonusTextExercise.setKnowledge(textAssessmentKnowledgeService.createNewKnowledge());
exerciseGroup4.setExercises(Set.of(bonusTextExercise));
exerciseRepo.save(bonusTextExercise);
TextExercise notIncludedTextExercise = ModelFactory.generateTextExerciseForExam(exerciseGroup5);
notIncludedTextExercise.setIncludedInOverallScore(IncludedInOverallScore.NOT_INCLUDED);
notIncludedTextExercise.setKnowledge(textAssessmentKnowledgeService.createNewKnowledge());
exerciseGroup5.setExercises(Set.of(notIncludedTextExercise));
exerciseRepo.save(notIncludedTextExercise);
if (withProgrammingExercise) {
// programming
ModelFactory.generateExerciseGroup(true, exam);
exam.setNumberOfExercisesInExam(7);
exam.setMaxPoints(29);
exam = examRepository.save(exam);
var exerciseGroup6 = exam.getExerciseGroups().get(6);
// Programming exercises need a proper setup for 'prepare exam start' to work
ProgrammingExercise programmingExercise1 = ModelFactory.generateProgrammingExerciseForExam(exerciseGroup6);
exerciseRepo.save(programmingExercise1);
addTemplateParticipationForProgrammingExercise(programmingExercise1);
addSolutionParticipationForProgrammingExercise(programmingExercise1);
exerciseGroup6.setExercises(Set.of(programmingExercise1));
}
return exam;
}
Aggregations