.
This commit is contained in:
+4
-4
@@ -490,10 +490,10 @@ class CidUserAnswer(models.Model):
|
|||||||
mark = 0
|
mark = 0
|
||||||
|
|
||||||
return mark
|
return mark
|
||||||
else:
|
|
||||||
q = self.question
|
q = self.question
|
||||||
ans = self.answer_compare
|
ans = self.answer_compare
|
||||||
marked_ans = q.answers.filter(answer_compare__iexact=ans).first()
|
marked_ans = q.answers.filter(answer_compare__iexact=ans).first()
|
||||||
|
|
||||||
mark = "unmarked"
|
mark = "unmarked"
|
||||||
if marked_ans is not None:
|
if marked_ans is not None:
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"exam/<int:pk>/scores/refresh",
|
"exam/<int:pk>/scores/refresh",
|
||||||
views.exam_scores_refresh,
|
views.AnatomyExamViews.exam_scores_refresh,
|
||||||
# cache_page(60 * 1)(views.exam_scores_cid),
|
# cache_page(60 * 1)(views.exam_scores_cid),
|
||||||
name="exam_scores_refresh",
|
name="exam_scores_refresh",
|
||||||
),
|
),
|
||||||
|
|||||||
+1
-1
@@ -987,7 +987,7 @@ def question_save_annotation(request, pk):
|
|||||||
|
|
||||||
|
|
||||||
AnatomyExamViews = ExamViews(
|
AnatomyExamViews = ExamViews(
|
||||||
Exam, AnatomyQuestion, "anatomy", "anatomy", loadJsonAnswer
|
Exam, AnatomyQuestion, CidUserAnswer, "anatomy", "anatomy", loadJsonAnswer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+31
-8
@@ -215,9 +215,10 @@ def generic_exam_json_edit(request):
|
|||||||
|
|
||||||
|
|
||||||
class ExamViews(View, LoginRequiredMixin):
|
class ExamViews(View, LoginRequiredMixin):
|
||||||
def __init__(self, exam, question, app, question_type, loadJsonAnswer):
|
def __init__(self, exam, question, cid_user_answer, app, question_type, loadJsonAnswer):
|
||||||
self.Exam = exam
|
self.Exam = exam
|
||||||
self.Question = question
|
self.Question = question
|
||||||
|
self.CidUserAnswer = cid_user_answer
|
||||||
self.app_name = app
|
self.app_name = app
|
||||||
self.question_type = question_type
|
self.question_type = question_type
|
||||||
self.loadJsonAnswer = loadJsonAnswer
|
self.loadJsonAnswer = loadJsonAnswer
|
||||||
@@ -417,6 +418,29 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@method_decorator(login_required)
|
||||||
|
def exam_scores_refresh(self, request, pk):
|
||||||
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
|
if not exam.exam_mode:
|
||||||
|
raise Http404("Packet not in exam mode")
|
||||||
|
|
||||||
|
questions = exam.exam_questions.all()
|
||||||
|
|
||||||
|
cids = self.CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
|
||||||
|
|
||||||
|
# Force a score update
|
||||||
|
for c in cids:
|
||||||
|
c.get_answer_score(cached=False)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"rapids/base.html",
|
||||||
|
{
|
||||||
|
"simple_content": "Answer scores updated",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
def exam_cids(self, request, exam_id):
|
def exam_cids(self, request, exam_id):
|
||||||
exam = get_object_or_404(self.Exam, pk=exam_id)
|
exam = get_object_or_404(self.Exam, pk=exam_id)
|
||||||
@@ -966,17 +990,13 @@ class CidUserView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
# user = self.request.user
|
# user = self.request.user
|
||||||
|
|
||||||
filters = { "archive": False, "exam_mode": True}
|
filters = {"archive": False, "exam_mode": True}
|
||||||
|
|
||||||
physics_exams = [
|
physics_exams = [(i.name, i.pk) for i in PhysicsExam.objects.filter(**filters)]
|
||||||
(i.name, i.pk) for i in PhysicsExam.objects.filter(**filters)
|
|
||||||
]
|
|
||||||
rapid_exams = [(i.name, i.pk) for i in RapidExam.objects.filter(**filters)]
|
rapid_exams = [(i.name, i.pk) for i in RapidExam.objects.filter(**filters)]
|
||||||
sba_exams = [(i.name, i.pk) for i in SbasExam.objects.filter(**filters)]
|
sba_exams = [(i.name, i.pk) for i in SbasExam.objects.filter(**filters)]
|
||||||
longs_exams = [(i.name, i.pk) for i in LongExam.objects.filter(**filters)]
|
longs_exams = [(i.name, i.pk) for i in LongExam.objects.filter(**filters)]
|
||||||
anatomy_exams = [
|
anatomy_exams = [(i.name, i.pk) for i in AnatomyExam.objects.filter(**filters)]
|
||||||
(i.name, i.pk) for i in AnatomyExam.objects.filter(**filters)
|
|
||||||
]
|
|
||||||
|
|
||||||
cid_user_groups = [
|
cid_user_groups = [
|
||||||
(i.name, i.pk) for i in CidUserGroup.objects.filter(archive=False)
|
(i.name, i.pk) for i in CidUserGroup.objects.filter(archive=False)
|
||||||
@@ -990,6 +1010,7 @@ class CidUserView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
context["cid_user_groups"] = cid_user_groups
|
context["cid_user_groups"] = cid_user_groups
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
def group_view(request):
|
def group_view(request):
|
||||||
@@ -1001,6 +1022,7 @@ def group_view(request):
|
|||||||
{"groups": groups},
|
{"groups": groups},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
def group_email(request, pk):
|
def group_email(request, pk):
|
||||||
@@ -1017,6 +1039,7 @@ def group_email(request, pk):
|
|||||||
{"users": users},
|
{"users": users},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
def manage_cid_users(request):
|
def manage_cid_users(request):
|
||||||
|
|||||||
+1
-1
@@ -1169,7 +1169,7 @@ def long_series_order_upload_filename(request, pk):
|
|||||||
return redirect("longs:long_series_detail", pk=pk)
|
return redirect("longs:long_series_detail", pk=pk)
|
||||||
|
|
||||||
|
|
||||||
LongExamViews = ExamViews(Exam, Long, "longs", "long", loadJsonAnswer)
|
LongExamViews = ExamViews(Exam, Long, CidUserAnswer, "longs", "long", loadJsonAnswer)
|
||||||
|
|
||||||
|
|
||||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||||
|
|||||||
+1
-1
@@ -452,7 +452,7 @@ def loadJsonAnswer(answer):
|
|||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
PhysicsExamViews = ExamViews(Exam, Question, "physics", "physics", loadJsonAnswer)
|
PhysicsExamViews = ExamViews(Exam, Question, CidUserAnswer, "physics", "physics", loadJsonAnswer)
|
||||||
|
|
||||||
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -685,7 +685,17 @@ class CidUserAnswer(models.Model):
|
|||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("rapids:user_answer_view", kwargs={"pk": self.pk})
|
return reverse("rapids:user_answer_view", kwargs={"pk": self.pk})
|
||||||
|
|
||||||
def get_answer_score(self):
|
def get_answer_score(self, cached=True):
|
||||||
|
if cached and self.score:
|
||||||
|
if self.score == Answer.MarkOptions.CORRECT:
|
||||||
|
mark = 2
|
||||||
|
elif self.score == Answer.MarkOptions.HALF_MARK:
|
||||||
|
mark = 1
|
||||||
|
elif self.score == Answer.MarkOptions.INCORRECT:
|
||||||
|
mark = 0
|
||||||
|
|
||||||
|
return mark
|
||||||
|
|
||||||
q = self.question
|
q = self.question
|
||||||
|
|
||||||
# First step we check that the normal/abnormal states match
|
# First step we check that the normal/abnormal states match
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
Rapids
|
Rapids
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
@@ -13,20 +13,23 @@ Rapids
|
|||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
{% if simple_content %}
|
||||||
|
{{simple_content}}
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
Rapids:
|
Rapids:
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<a href="{% url 'rapids:index' %}">Packets</a> /
|
<a href="{% url 'rapids:index' %}">Packets</a> /
|
||||||
<a href="{% url 'rapids:exam_list' %}">Exams</a> /
|
<a href="{% url 'rapids:exam_list' %}">Exams</a> /
|
||||||
<a href="{% url 'rapids:exam_create' %}" title="Create a new exam">Create Exam</a> /
|
<a href="{% url 'rapids:exam_create' %}" title="Create a new exam">Create Exam</a> /
|
||||||
<a href="{% url 'rapids:rapid_view' %}">Questions</a> /
|
<a href="{% url 'rapids:rapid_view' %}">Questions</a> /
|
||||||
<a href="{% url 'rapids:rapid_create' %}" title="Create a new question">Create Question</a>
|
<a href="{% url 'rapids:rapid_create' %}" title="Create a new question">Create Question</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
/ <a href="{% url 'rapids:user_answer_table_view' %}" title="User answers">Answers</a>
|
/ <a href="{% url 'rapids:user_answer_table_view' %}" title="User answers">Answers</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% comment %} </br>
|
{% comment %} </br>
|
||||||
Questions by:
|
Questions by:
|
||||||
<span id="authors-link"><a href="{% url 'rapids:author_list' %}">author</a></span> {% endcomment %}
|
<span id="authors-link"><a href="{% url 'rapids:author_list' %}">author</a></span> {% endcomment %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<div id="stats-plot">{{plot|safe}}</div>
|
<div id="stats-plot">{{plot|safe}}</div>
|
||||||
<div class="rapids">
|
<div class="rapids">
|
||||||
<h2>{{ exam.name }}</h2>
|
<h2>{{ exam.name }}</h2>
|
||||||
|
User answer scores are cached, if you update or change an answer you will need to <a href="{% url 'anatomy:exam_scores_refresh' exam.pk %}">refresh the scores</a>.
|
||||||
|
|
||||||
{% if unmarked %}
|
{% if unmarked %}
|
||||||
<div class="alert alert-warning" role="alert">
|
<div class="alert alert-warning" role="alert">
|
||||||
|
|||||||
@@ -75,6 +75,12 @@ urlpatterns = [
|
|||||||
cache_page(60 * 1)(views.exam_scores_cid),
|
cache_page(60 * 1)(views.exam_scores_cid),
|
||||||
name="exam_scores_cid",
|
name="exam_scores_cid",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"exam/<int:pk>/scores/refresh",
|
||||||
|
views.RapidExamViews.exam_scores_refresh,
|
||||||
|
# cache_page(60 * 1)(views.exam_scores_cid),
|
||||||
|
name="exam_scores_refresh",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"exam/<int:pk>/scores/<int:cid>/<str:passcode>/",
|
"exam/<int:pk>/scores/<int:cid>/<str:passcode>/",
|
||||||
views.exam_scores_cid_user,
|
views.exam_scores_cid_user,
|
||||||
|
|||||||
+1
-1
@@ -928,7 +928,7 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
|||||||
success_url = reverse_lazy("rapids:rapid_view")
|
success_url = reverse_lazy("rapids:rapid_view")
|
||||||
|
|
||||||
|
|
||||||
RapidExamViews = ExamViews(Exam, Rapid, "rapids", "rapid", loadJsonAnswer)
|
RapidExamViews = ExamViews(Exam, Rapid, CidUserAnswer, "rapids", "rapid", loadJsonAnswer)
|
||||||
|
|
||||||
|
|
||||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||||
|
|||||||
+1
-1
@@ -373,7 +373,7 @@ def exam_take(request, pk, sk, cid, passcode):
|
|||||||
def loadJsonAnswer(answer):
|
def loadJsonAnswer(answer):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
SbasExamViews = ExamViews(Exam, Question, "sbas", "sbas", loadJsonAnswer)
|
SbasExamViews = ExamViews(Exam, Question, CidUserAnswer, "sbas", "sbas", loadJsonAnswer)
|
||||||
|
|
||||||
class QuestionView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class QuestionView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
||||||
model = Question
|
model = Question
|
||||||
|
|||||||
Reference in New Issue
Block a user