package pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.service
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.context.TestConfiguration
import pt.ulisboa.tecnico.socialsoftware.tutor.BeanConfiguration
import pt.ulisboa.tecnico.socialsoftware.tutor.SpockTest
import pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.domain.TeacherDashboard
import pt.ulisboa.tecnico.socialsoftware.tutor.exceptions.ErrorMessage
import pt.ulisboa.tecnico.socialsoftware.tutor.exceptions.TutorException
import pt.ulisboa.tecnico.socialsoftware.tutor.user.domain.Teacher
import spock.lang.Unroll
import pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.domain.QuizStats;
import pt.ulisboa.tecnico.socialsoftware.tutor.quiz.domain.Quiz
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.MultipleChoiceAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.QuestionAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.answer.domain.QuizAnswer
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.MultipleChoiceQuestion
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.Option
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.Question
import pt.ulisboa.tecnico.socialsoftware.tutor.quiz.domain.Quiz
import pt.ulisboa.tecnico.socialsoftware.tutor.quiz.domain.QuizQuestion
import pt.ulisboa.tecnico.socialsoftware.tutor.utils.DateHandler
import pt.ulisboa.tecnico.socialsoftware.tutor.user.domain.Student
import pt.ulisboa.tecnico.socialsoftware.tutor.auth.domain.AuthUser
import pt.ulisboa.tecnico.socialsoftware.tutor.teacherdashboard.dto.TeacherDashboardDto
import pt.ulisboa.tecnico.socialsoftware.tutor.question.domain.Course
import pt.ulisboa.tecnico.socialsoftware.tutor.execution.domain.CourseExecution
@DataJpaTest
class QuizStatPedroTest extends SpockTest {
def teacher
def teacher2
def teacherDashboard
def quiz
def quizQuestion
def student
def otherExternalCourse
def otherExternalCourseExecution
def setup() {
createExternalCourseAndExecution()
createOtherExternalCourseAndExecution()
teacher = new Teacher(USER_1_NAME, false)
userRepository.save(teacher)
teacher2 = new Teacher(USER_2_NAME, false)
userRepository.save(teacher2)
}
def createQuizStat() {
def quizStat = new QuizStats()
quizStatsRepository.save(quizStat)
return quizStat
}
def createOtherExternalCourseAndExecution() {
otherExternalCourse = new Course(COURSE_2_NAME, Course.Type.TECNICO)
courseRepository.save(otherExternalCourse)
otherExternalCourseExecution = new CourseExecution(otherExternalCourse, COURSE_2_ACRONYM, COURSE_2_ACADEMIC_TERM, Course.Type.TECNICO, LOCAL_DATE_TODAY)
courseExecutionRepository.save(otherExternalCourseExecution)
}
def createQuiz(type = Quiz.QuizType.PROPOSED.toString()) {
// Quiz
def quiz = new Quiz()
quiz.setTitle("Quiz Title")
quiz.setType(type)
quiz.setCourseExecution(externalCourseExecution)
quiz.setCreationDate(DateHandler.now())
quiz.setAvailableDate(DateHandler.now())
quizRepository.save(quiz)
// Add Question
def question = createQuestion()
quizQuestion = createQuizQuestion(quiz, question)
return quiz
}
def createQuizForCourseExecution(type = Quiz.QuizType.PROPOSED.toString(), secondCourseExecution, quizTitle) {
// Quiz
def quiz = new Quiz()
quiz.setTitle(quizTitle)
quiz.setType(type)
quiz.setCourseExecution(secondCourseExecution)
quiz.setCreationDate(DateHandler.now())
quiz.setAvailableDate(DateHandler.now())
quizRepository.save(quiz)
// Add Question
def question = createQuestion()
quizQuestion = createQuizQuestion(quiz, question)
return quiz
}
def createQuestion() {
def newQuestion = new Question()
newQuestion.setTitle(QUESTION_1_TITLE)
newQuestion.setCourse(externalCourse)
def questionDetails = new MultipleChoiceQuestion()
newQuestion.setQuestionDetails(questionDetails)
questionRepository.save(newQuestion)
def option = new Option()
option.setContent(OPTION_1_CONTENT)
option.setCorrect(true)
option.setSequence(0)
option.setQuestionDetails(questionDetails)
optionRepository.save(option)
def optionKO = new Option()
optionKO.setContent(OPTION_2_CONTENT)
optionKO.setCorrect(false)
optionKO.setSequence(1)
optionKO.setQuestionDetails(questionDetails)
optionRepository.save(optionKO)
return newQuestion;
}
def createQuizQuestion(quiz, question) {
def quizQuestion = new QuizQuestion(quiz, question, 0)
quizQuestionRepository.save(quizQuestion)
return quizQuestion
}
def answerQuiz(quizQuestion, quiz, student, completed = true, date = DateHandler.now()) {
def quizAnswer = new QuizAnswer()
quizAnswer.setCompleted(completed)
quizAnswer.setCreationDate(date)
quizAnswer.setAnswerDate(date)
quizAnswer.setStudent(student)
quizAnswer.setQuiz(quiz)
quizAnswerRepository.save(quizAnswer)
def questionAnswer = new QuestionAnswer()
questionAnswer.setTimeTaken(1)
questionAnswer.setQuizAnswer(quizAnswer)
questionAnswer.setQuizQuestion(quizQuestion)
questionAnswerRepository.save(questionAnswer)
def answerDetails
def correctOption = quizQuestion.getQuestion().getQuestionDetails().getCorrectOption()
answerDetails = new MultipleChoiceAnswer(questionAnswer, correctOption)
questionAnswer.setAnswerDetails(answerDetails)
answerDetailsRepository.save(answerDetails)
return questionAnswer
}
def createStudent(username) {
def student = new Student(USER_1_USERNAME, username, USER_1_EMAIL, false, AuthUser.Type.TECNICO)
student.addCourse(externalCourseExecution)
userRepository.save(student)
return student;
}
// um teste do updateAll em que há 2 teachers na mesma course execution. a discilina so teve 1 coure exevutoon
def "update 2 created teacher dashboards at the same time, both of them in the same course execution"() {
given: "2 teachers who just joined a course execution"
teacher.addCourse(externalCourseExecution)
teacher2.addCourse(externalCourseExecution)
and: "a new dashboard for each teacher"
teacherDashboardService.createTeacherDashboard(externalCourseExecution.getId(), teacher.getId())
teacherDashboardService.createTeacherDashboard(externalCourseExecution.getId(), teacher2.getId())
and: "a created quiz in that course execution"
def quiz = createQuiz()
when: "we update all the teacher dashboards"
teacherDashboardService.updateAllTeacherDashboards()
then: "the quiz statistics are updated for both teachers"
def quizStatsDtoList = teacherDashboardService.getTeacherDashboard(externalCourseExecution.getId(), teacher.getId()).getTeacherDashboardQuizStats()
quizStatsDtoList.size() == 1 // corresponding to the single course execution
quizStatsDtoList.get(0).getNumQuizzes() == 1
quizStatsDtoList.get(0).getNumUniqueAnsweredQuizzes() == 0
quizStatsDtoList.get(0).getAverageQuizzesSolved() == 0
def quizStatsDtoList2 = teacherDashboardService.getTeacherDashboard(externalCourseExecution.getId(), teacher2.getId()).getTeacherDashboardQuizStats()
quizStatsDtoList2.size() == 1 // corresponding to the single course execution
quizStatsDtoList2.get(0).getNumQuizzes() == 1
quizStatsDtoList2.get(0).getNumUniqueAnsweredQuizzes() == 0
quizStatsDtoList2.get(0).getAverageQuizzesSolved() == 0
and: "the quiz statistics are persisted"
quizStatsRepository.count() == 2L
}
// um teste do updateAll em que há 2 teachers em course executions diferentes
// aumentar o teste para ter todas as estatisticas diferentes de 0
// fazer com que cada courseExecution tenha 1 estatistica diferente
def "update 2 created teacher dashboards at the same time, in different courses"() {
given: "2 teachers who each joined 1 course execution"
teacher.addCourse(externalCourseExecution)
teacher2.addCourse(otherExternalCourseExecution)
and: "a created quiz in each course execution"
def quiz = createQuiz()
def quiz2 = createQuizForCourseExecution(otherExternalCourseExecution, "My quiz")
def quiz3 = createQuizForCourseExecution(otherExternalCourseExecution, "My other quiz")
when: "we update all the teacher dashboards"
teacherDashboardService.updateAllTeacherDashboards()
then: "the quiz statistics are updated for both teachers"
def quizStatsDtoList = teacherDashboardService.getTeacherDashboard(externalCourseExecution.getId(), teacher.getId()).getTeacherDashboardQuizStats()
quizStatsDtoList.size() == 1 // corresponding to the single course execution
quizStatsDtoList.get(0).getNumQuizzes() == 1
quizStatsDtoList.get(0).getNumUniqueAnsweredQuizzes() == 0
quizStatsDtoList.get(0).getAverageQuizzesSolved() == 0
def quizStatsDtoList2 = teacherDashboardService.getTeacherDashboard(otherExternalCourseExecution.getId(), teacher2.getId()).getTeacherDashboardQuizStats()
quizStatsDtoList2.size() == 1 // corresponding to the single course execution
quizStatsDtoList2.get(0).getNumQuizzes() == 2
quizStatsDtoList2.get(0).getNumUniqueAnsweredQuizzes() == 0
quizStatsDtoList2.get(0).getAverageQuizzesSolved() == 0
and: "the quiz statistics are persisted"
quizStatsRepository.count() == 2L
}
// um teste do updateAll em que há 2 teachers, 1 com dashboard criado e outro sem dashboard criado, na mesma course execution
// um teste do updateAll em que há 2 teachers, 1 com dashbaord
@TestConfiguration
static class LocalBeanConfiguration extends BeanConfiguration {}
}