Current section

Files

Jump to
ami lib quiz_grader.ex
Raw

lib/quiz_grader.ex

defmodule QuizGrader do
require Ami.Gettext
import Ecto.Query
alias Ami.{
Repo,
Enrollment,
Quiz,
User,
UserAnswer,
Score,
Answer,
Gettext
}
def grade(params) do
enrollment =
Repo.get(Enrollment, params["enrollment_id"])
|> Repo.preload([:scores, course_period: [:course]])
quiz =
Repo.get(Quiz, params["quiz_id"])
|> Repo.preload(questions: [answers: from(a in Answer, order_by: [asc: a.id])])
user =
Repo.get(User, params["user_id"])
|> Repo.preload(:profile)
score = Score.find(quiz.id, enrollment.id)
if score != nil do
{
Gettext.gettext(
"You have already taken this quiz - Please move on to the activity and next lesson."
),
enrollment,
quiz,
user
}
else
user_answers =
Map.drop(params, [
"course_id",
"enrollment_id",
"lesson_id",
"quiz_id",
"user_id",
"submit_confirmed"
])
correct_answers = correct_answers(user_answers, quiz)
total_questions = total_questions(quiz)
quiz_score = score(user_answers, quiz)
if length(Map.to_list(user_answers)) != total_questions do
{
Gettext.gettext("Please answer all the questions to get a grade for this quiz"),
enrollment,
quiz,
user
}
else
user_answers
|> save_answers(enrollment, quiz, user)
Score.insert_changeset(%Score{}, %{
value: quiz_score,
answers_correct: correct_answers,
total_questions: total_questions,
quiz_id: quiz.id,
user_id: user.id,
enrollment_id: enrollment.id,
course_id: enrollment.course_period.course_id,
course_period_id: enrollment.course_period.id
})
|> Repo.insert()
# Update the enrollment progress binary
{:ok, enrollment} =
enrollment
|> Repo.preload([:scores, course_period: [:course]], force: true)
|> Enrollment.update_progress()
{:ok, enrollment} = Enrollment.update_course_flags(enrollment)
{:ok, enrollment} =
Ecto.Changeset.change(enrollment, %{updated_at: Timex.now()})
|> Repo.update()
{:ok, enrollment} =
if enrollment.course_started == false do
Ecto.Changeset.change(enrollment, %{course_started: true, updated_at: Timex.now()})
|> Repo.update()
else
{:ok, enrollment}
end
if quiz.title == "Final Exam" do
{
Gettext.gettext(
"Congratulations on completing your final exam! You scored %{score}%. Now, please go to the Final Assignment tab and review, complete and submit your assignment to complete the course.",
score: quiz_score
),
enrollment,
quiz,
user
}
else
{Gettext.gettext("You scored a %{score}% on this quiz.", score: quiz_score), enrollment,
quiz, user}
end
end
end
end
defp save_answers(answers, enrollment, quiz, user) do
Enum.each(answers, fn {k, v} ->
question = Enum.find(quiz.questions, &(&1.id == String.to_integer(k)))
answer = Enum.find(question.answers, &(&1.value == v))
UserAnswer.changeset(%UserAnswer{}, %{
user_id: user.id,
answer_id: answer.id,
course_period_id: enrollment.course_period.id,
question_id: question.id,
quiz_id: quiz.id
})
|> Repo.insert()
end)
answers
end
defp correct_answers(answers, quiz) do
Enum.filter(answers, fn {k, v} ->
question = Enum.find(quiz.questions, &(&1.id == String.to_integer(k)))
correct_answer = Enum.find(question.answers, &(&1.correct_answer == true))
correct_answer.value == v
end)
|> length()
end
defp total_questions(quiz), do: length(quiz.questions)
defp score(answers, quiz) do
(correct_answers(answers, quiz) * 100 / total_questions(quiz))
|> Float.round()
|> Kernel.trunc()
end
end