Skip to content

Commit

Permalink
in inclass quizzes server decides what is the next question
Browse files Browse the repository at this point in the history
  • Loading branch information
ritosilva committed Jan 5, 2024
1 parent ee6d18d commit afd6402
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package pt.ulisboa.tecnico.socialsoftware.tutor.answer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.retry.annotation.Backoff;
Expand Down Expand Up @@ -47,6 +49,8 @@

@Service
public class AnswerService {
private static final Logger logger = LoggerFactory.getLogger(AnswerService.class);

@Autowired
private Mailer mailer;

Expand Down Expand Up @@ -370,7 +374,10 @@ public StatementQuizDto getQuizByQRCode(int userId, int quizId) {
QuizAnswer quizAnswer = getQuizAnswer(student, quiz);

if (quiz.getAvailableDate() == null || DateHandler.now().isAfter(quiz.getAvailableDate())) {
return getPreparedStatementQuizDto(student, quiz, quizAnswer);
StatementQuizDto result = getPreparedStatementQuizDto(student, quiz, quizAnswer);
if (quiz.isOneWay() && quiz.getConclusionDate() != null)
logger.info("Student {} for quiz answer {} get quiz {} with sequence {}", student.getUsername(), quizAnswer.getId(), result);
return result;
} else { // Send timer
StatementQuizDto quizDto = new StatementQuizDto();
quizDto.setTimeToAvailability(ChronoUnit.MILLIS.between(DateHandler.now(), quiz.getAvailableDate()));
Expand Down Expand Up @@ -398,7 +405,10 @@ public StatementQuizDto startQuiz(int userId, int quizId) {

QuizAnswer quizAnswer = getQuizAnswer(student, quiz);

return getPreparedStatementQuizDto(student, quiz, quizAnswer);
StatementQuizDto result = getPreparedStatementQuizDto(student, quiz, quizAnswer);
if (quiz.isOneWay() && quiz.getConclusionDate() != null)
logger.info("Student {} for quiz answer {} get quiz {} with sequence {}", student.getUsername(), quizAnswer.getId(), result);
return result;
}

private void commonChecks(Student student, Quiz quiz) {
Expand Down Expand Up @@ -481,16 +491,20 @@ public StatementQuestionDto getQuestionForQuizAnswer(Integer questionId, Stateme
QuizAnswer quizAnswer = quizAnswerRepository.findById(answer.getQuizAnswerId())
.orElseThrow(() -> new TutorException(QUIZ_ANSWER_NOT_FOUND));

try {
quizAnswer.checkCanGetQuestion(questionId);
} catch (TutorException te) {
Integer sequenceQuestionId = quizAnswer.checkCorrectSequenceQuestion(answer.getSequence(), questionId);

if (!sequenceQuestionId.equals(questionId)) {
logger.info("Student of quiz answer {} tried to get question id {} with sequence {} but the correct question id is {}",
quizAnswer.getId(), questionId, answer.getSequence() + 1, sequenceQuestionId);

mailer.sendSimpleMail(mailUsername, "rito.silva@tecnico.ulisboa.pt",
Mailer.QUIZZES_TUTOR_SUBJECT + " Alert", "In course "
+ quizAnswer.getQuiz().getCourseExecution().getCourse().getName()
+ ", the following behavior was detected but the student *was not able* to answer questions out of the predefined order: "
+ te.getMessage());
+ ", the student tried to get a sequence-question (" + answer.getSequence() + "," + questionId + ")"
+ " out of the predefined order but the correct question is " + sequenceQuestionId);
}
Question question = questionRepository.findById(questionId)

Question question = questionRepository.findById(sequenceQuestionId)
.orElseThrow(() -> new TutorException(QUESTION_NOT_FOUND, questionId));

return new StatementQuestionDto(question);
Expand All @@ -509,7 +523,7 @@ public void submitAnswer(String username, int quizId, StatementAnswerDto answer)
} catch (TutorException te) {
for (Teacher teacher : quizAnswer.getQuiz().getCourseExecution().getTeachers()) {
mailer.sendSimpleMail(mailUsername, teacher.getEmail(),
Mailer.QUIZZES_TUTOR_SUBJECT + " Alert", "The following behavior was detected but the student *was not able* to answer questions out of the predefined order: " + te.getMessage());
Mailer.QUIZZES_TUTOR_SUBJECT + " Alert", "The student tried to answer questions out of the predefined order: " + te.getMessage());
}

throw te;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -84,10 +85,13 @@ public QuizAnswer(Student student, Quiz quiz) {

for (int i = 0; i < quizQuestions.size(); i++) {
new QuestionAnswer(this, quizQuestions.get(i), i);
}

if (quiz.isOneWay() && quiz.getType().equals(Quiz.QuizType.IN_CLASS)) {
this.questionIds.add(quizQuestions.get(i).getQuestion().getId());
}
if (quiz.isOneWay() && quiz.getType().equals(Quiz.QuizType.IN_CLASS)) {
questionIds = getQuestionAnswers().stream()
.sorted(Comparator.comparing(QuestionAnswer::getSequence))
.map(questionAnswer -> questionAnswer.getQuestion().getId())
.collect(Collectors.toList());
}
}

Expand Down Expand Up @@ -218,20 +222,19 @@ public void calculateQuestionStatistics() {
}
}

public void checkCanGetQuestion(Integer questionId) {
public Integer checkCorrectSequenceQuestion(Integer sequence, Integer questionId) {
if (!questionIds.isEmpty()) {
if (currentSequenceQuestion < questionIds.size() - 1
&& questionIds.get(currentSequenceQuestion + 1).equals(questionId)) {
currentSequenceQuestion = currentSequenceQuestion + 1;

logger.info("Student {} for quiz answer {} get question id {} with sequence {}", getStudent().getUsername(), getId(), questionId, currentSequenceQuestion);
} else if (!questionIds.get(currentSequenceQuestion).equals(questionId)) {
throw new TutorException(INVALID_QUIZ_ANSWER_SEQUENCE,
getStudent().getUsername() + " tried to get question with ID "
+ questionId + " when they sequence is " + (currentSequenceQuestion + 1)
+ " and the question IDs sequence is " + questionIds.stream().map(String::valueOf).collect(Collectors.joining(", ")));
if (sequence.equals(currentSequenceQuestion + 1)) {
currentSequenceQuestion = sequence;
}

logger.info("Student {} for quiz answer {} get question id {} with sequence {}", getStudent().getUsername(), getId(), questionId, (currentSequenceQuestion + 1));
logger.info("Question ids {}", questionIds);

return questionIds.get(currentSequenceQuestion);
}

return questionId;
}

public void checkIsCurrentQuestion(Integer questionId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@

public class StatementAnswerDto implements Serializable {
private Integer timeTaken;

private Integer timeToSubmission;

private Integer sequence;

private Integer quizAnswerId;

private Integer questionAnswerId;

private Integer questionId;

private Integer quizQuestionId;

private DiscussionDto userDiscussion;

private StatementAnswerDetailsDto answerDetails;
Expand All @@ -32,8 +39,8 @@ public StatementAnswerDto(QuestionAnswer questionAnswer) {

this.answerDetails = questionAnswer.getStatementAnswerDetailsDto();

if (questionAnswer.getDiscussion() != null){
this.userDiscussion = new DiscussionDto(questionAnswer.getDiscussion(),false);
if (questionAnswer.getDiscussion() != null) {
this.userDiscussion = new DiscussionDto(questionAnswer.getDiscussion(), false);
}
}

Expand Down Expand Up @@ -93,7 +100,7 @@ public void setTimeToSubmission(Integer timeToSubmission) {
this.timeToSubmission = timeToSubmission;
}

public AnswerDetails getAnswerDetails(QuestionAnswer questionAnswer){
public AnswerDetails getAnswerDetails(QuestionAnswer questionAnswer) {
return this.getAnswerDetails() != null ? this.answerDetails.getAnswerDetails(questionAnswer) : null;
}

Expand All @@ -117,10 +124,13 @@ public void setUserDiscussion(DiscussionDto userDiscussion) {
public String toString() {
return "StatementAnswerDto{" +
"timeTaken=" + timeTaken +
", timeToSubmission=" + timeToSubmission +
", sequence=" + sequence +
", quizAnswerId=" + quizAnswerId +
", questionAnswerId=" + questionAnswerId +
", questionId=" + questionId +
", quizQuestionId=" + quizQuestionId +
", timeToSubmission=" + timeToSubmission +
", userDiscussion=" + userDiscussion +
", answerDetails=" + answerDetails +
'}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@

public class StatementQuestionDto implements Serializable {
private String content;

private ImageDto image;

private Integer sequence;

private Integer questionId;

private StatementQuestionDetailsDto questionDetails;
Expand All @@ -36,6 +39,8 @@ public StatementQuestionDto(Question question) {
this.image = new ImageDto(question.getImage());

this.questionDetails = question.getStatementQuestionDetailsDto();

this.questionId = question.getId();
}

public String getContent() {
Expand Down Expand Up @@ -76,6 +81,7 @@ public String toString() {
"content='" + content + '\'' +
", image=" + image +
", sequence=" + sequence +
", questionId=" + questionId +
", questionDetails=" + questionDetails +
'}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,31 @@

public class StatementQuizDto implements Serializable {
private Integer id;

private Integer quizAnswerId;

private String title;

private boolean oneWay;

private boolean timed;

private String availableDate;

private String conclusionDate;

private Integer questionOrder = 0;

private Long timeToAvailability;

private Long timeToSubmission;

private List<StatementQuestionDto> questions = new ArrayList<>();

private List<StatementAnswerDto> answers = new ArrayList<>();

public StatementQuizDto() {}
public StatementQuizDto() {
}

public StatementQuizDto(QuizAnswer quizAnswer, boolean complete) {
this.id = quizAnswer.getQuiz().getId();
Expand Down Expand Up @@ -64,7 +76,7 @@ public StatementQuizDto(QuizAnswer quizAnswer, List<QuestionAnswerItem> items) {

List<QuestionAnswerItem> finalItems = new ArrayList<>();
for (int i = 0; i < items.size() - 1; i++) {
if (!items.get(i).getQuizQuestionId().equals(items.get(i+1).getQuizQuestionId())) {
if (!items.get(i).getQuizQuestionId().equals(items.get(i + 1).getQuizQuestionId())) {
finalItems.add(items.get(i));
}
}
Expand Down Expand Up @@ -185,8 +197,10 @@ public String toString() {
", quizAnswerId=" + quizAnswerId +
", title='" + title + '\'' +
", oneWay=" + oneWay +
", timed=" + timed +
", availableDate='" + availableDate + '\'' +
", conclusionDate='" + conclusionDate + '\'' +
", questionOrder=" + questionOrder +
", timeToAvailability=" + timeToAvailability +
", timeToSubmission=" + timeToSubmission +
", questions=" + questions +
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/views/student/quiz/QuizView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ export default class QuizView extends Vue {
this.statementQuiz.questions[order].image = question.image;
this.statementQuiz.questions[order].questionDetails =
question.questionDetails;
// ensure that the questions ids are equal to que returned by the server
this.statementQuiz.questions[order].questionId = question.questionId;
this.statementQuiz.answers[order].questionId = question.questionId;
} catch (error) {
await this.$store.dispatch('error', error);
await this.$router.push({ name: 'available-quizzes' });
Expand Down

0 comments on commit afd6402

Please sign in to comment.