Packages
ami
0.3.4
0.3.9
0.3.8
retired
0.3.7
retired
0.3.6
retired
0.3.5
retired
0.3.4
retired
0.3.3
retired
0.3.2
retired
0.3.1
retired
0.3.0
retired
0.2.9
retired
0.2.8
retired
0.2.7
retired
0.2.6
retired
0.2.5
retired
0.2.3
retired
0.2.2
retired
0.2.1
retired
0.2.0
retired
0.1.9
retired
0.1.8
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
Package containing all AMI Models shared between micro-services.
Retired package: Security issue - retiring
Current section
Files
Jump to
Current section
Files
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