This commit is contained in:
Ross
2022-06-26 22:45:52 +01:00
parent 455be37922
commit e2c8f751f2
13 changed files with 108 additions and 705 deletions
+12 -64
View File
@@ -1,71 +1,19 @@
{% extends 'anatomy/exams.html' %}
{% extends 'generic/exam_scores_base.html' %}
{% block content %}
<div class="anatomy">
<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 %}
<div class="alert alert-warning" role="alert">
The following questions need marking
{% for exam_index in unmarked %}
<a href="{% url 'anatomy:mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
{% endfor %}
</div>
{% endif %}
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
<div id="stats-plot">{{plot|safe}}</div>
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm cid-score-table">
<tr>
<th>Candidate ID</th>
<th>Score</th>
</tr>
{% for user, value in user_answers_marks.items %}
<tr>
<td><a href="{% url 'cid_scores_admin' user %}">{{user}}</a></td>
<td>{{user}}</td>
<td>{{user_scores|get_item:user}}</td>
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Results as a table</h3>
<table class="table table-dark table-striped table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'anatomy:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% endfor %}
</tr>
</thead>
{% block table_answers %}
{% for question in questions %}
<tr>
<td><a href="{% url 'anatomy:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a></td>
{% for ans, score in by_question|get_item:question %}
<td class="user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</td>
<td><a href="{% url 'anatomy:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
</td>
{% comment %} {% for cid in cids %}
<td class="anatomy-ans user-answer-score-{{score_by_question|get_item:question|get_item:cid}}" title="answer score: {{score_by_question|get_item:question|get_item:cid}}">{{ans_by_question|get_item:question|get_item:cid}}</td>
{% endfor %} {% endcomment %}
{% for cid in cids %}
{% with by_question|get_item:question|get_item:cid as ans_score %}
<td class="anatomy-ans user-answer-score-{{ans_score.1}}" title="answer score: {{ans_score.1}}">{{ans_score.0}}</td>
{% endwith %}
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for score in user_scores_list %}
<td>{{score}}</td>
{% endfor %}
</tr>
</table>
{% endblock table_answers %}
</div>
{% endblock %}
@@ -1,81 +0,0 @@
{% extends 'anatomy/exams.html' %}
{% block content %}
<div id="stats-plot">{{plot|safe}}</div>
<div class="anatomy">
<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 %}
<div class="alert alert-warning" role="alert">
The following questions need marking
{% for exam_index in unmarked %}
<a href="{% url 'anatomy:mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
{% endfor %}
</div>
{% endif %}
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm cid-score-table">
<tr>
<th>Candidate ID</th>
<th>Score</th>
{% comment %} <th>Normalised Score</th> {% endcomment %}
</tr>
{% comment %} {% for user, value in user_answers_marks.items %} {% endcomment %}
{% for cid in cids %}
<tr>
<td><a href="{% url 'cid_scores_admin' cid %}">{{cid}}</a></td>
<td>{{user_scores|get_item:cid}}</td>
{% comment %} <td>{{user_scores_normalised|get_item:user}}</td> {% endcomment %}
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Answers as a table</h3>
<table class="table table-dark table-striped table-hover table-sm col-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'anatomy:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% comment %} <th><a href="">{{cid}}</a></th> {% endcomment %}
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td><a href="{% url 'anatomy:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
</td>
{% comment %} {% for cid in cids %}
<td class="anatomy-ans user-answer-score-{{score_by_question|get_item:question|get_item:cid}}" title="answer score: {{score_by_question|get_item:question|get_item:cid}}">{{ans_by_question|get_item:question|get_item:cid}}</td>
{% endfor %} {% endcomment %}
{% for cid in cids %}
{% with by_question|get_item:question|get_item:cid as ans_score %}
<td class="anatomy-ans user-answer-score-{{ans_score.1}}" title="answer score: {{ans_score.1}}">{{ans_score.0}}</td>
{% endwith %}
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for cid in cids %}
<td>{{user_scores|get_item:cid}}</td>
{% endfor %}
</tr>
</table>
</div>
{% endblock %}
+4
View File
@@ -71,6 +71,10 @@ urlpatterns = [
name="exam_question_detail",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path("exam/<int:exam_id>/report/email", views.GenericExamViews.exam_report_email, name="exam_report_email"),
path("exam/<int:exam_id>/report/email/status", views.GenericExamViews.exam_report_email_status, name="exam_report_email_status"),
path("exam/<int:exam_id>/report/<int:user_id>", views.GenericExamViews.exam_user_report, name="exam_user_report"),
path("exam/<int:exam_id>/report/<int:user_id>/email", views.GenericExamViews.exam_user_report_email, name="exam_user_report_email"),
path("exam/<int:pk>/authors", views.ExamAuthorUpdate.as_view(), name="exam_authors"),
path(
"exam/<int:pk>/json_edit",
-203
View File
@@ -399,126 +399,6 @@ def exam_scores_refresh(request, pk):
)
# @login_required
# def exam_scores_cid(request, pk):
# exam = get_object_or_404(Exam, pk=pk)
#
# if not exam.exam_mode:
# raise Http404("Packet not in exam mode")
#
# questions = exam.exam_questions.all()
#
# cids = (
# CidUserAnswer.objects.filter(question__in=questions, exam__id=pk)
# .order_by("cid")
# .values_list("cid", flat=True)
# .distinct()
# )
#
# user_answers_and_marks = defaultdict(list)
# user_answers_marks = defaultdict(list)
# user_answers = defaultdict(list)
# user_names = {}
#
# by_question = defaultdict(list)
# unmarked = set()
#
# # Loop through all candidates
# for cid in cids:
# # Convoluted (probably...)
# user_names[cid] = cid
# for q in questions:
# # Get user answer
# s = q.cid_user_answers.filter(cid=cid, exam__id=pk).first()
# if not s:
# # skip if no answer
# user_answers_marks[cid].append(0)
# user_answers[cid].append("")
# by_question[q].append(("", 0))
# continue
#
# ans = s.answer
# answer_score = s.get_answer_score()
# if answer_score == "unmarked":
# index = exam.get_question_index(q)
# unmarked.add(index)
# user_answers[cid].append(ans)
# user_answers_marks[cid].append(answer_score)
# user_answers_and_marks[cid].append((ans, answer_score))
#
# by_question[q].append((ans, answer_score))
#
# user_scores = {}
# for user in user_answers_marks:
# user_scores[user] = sum(
# [i for i in user_answers_marks[user] if i != "unmarked"]
# )
#
# user_scores_list = list(user_scores.values())
#
# if len(user_scores_list) < 1:
# mean = 0
# median = 0
# mode = 0
# fig_html = ""
# else:
# mean = statistics.mean(user_scores_list)
# median = statistics.median(user_scores_list)
# try:
# mode = statistics.mode(user_scores_list)
# except statistics.StatisticsError:
# mode = "No unique mode"
#
# df = user_scores_list
# fig = px.histogram(
# df,
# x=0,
# title="{}: distribution of scores".format(exam),
# labels={"0": "Score"},
# height=400,
# width=600,
# )
# fig_html = fig.to_html()
#
# max_score = len(questions) * 2
#
# exam.stats_mean = mean
# exam.stats_median = median
# exam.stats_mode = mode
#
# exam.stats_candidates = len(user_scores_list)
# exam.stats_max_possible = max_score
#
# exam.stats_min = min(user_scores_list)
# exam.stats_max = max(user_scores_list)
#
# exam.stats_graph = fig_html
# exam.save()
#
# return render(
# request,
# "anatomy/exam_scores.html",
# {
# "cids": cids,
# "exam": exam,
# "unmarked": unmarked,
# "questions": questions,
# "by_question": by_question,
# "user_answers": dict(user_answers),
# "user_answers_marks": dict(user_answers_marks),
# "user_scores": user_scores,
# "user_scores_list": user_scores_list,
# "user_names": user_names,
# "user_answers_and_marks": user_answers_and_marks,
# "max_score": max_score,
# "mean": mean,
# "median": median,
# "mode": mode,
# "plot": fig_html,
# },
# )
def exam_scores_cid_user(request, pk, cid, passcode):
exam = get_object_or_404(Exam, pk=pk)
@@ -589,89 +469,6 @@ def exam_scores_cid_user(request, pk, cid, passcode):
)
# @login_required
# def exam_scores(request, pk):
# exam = get_object_or_404(Exam, pk=pk)
# questions = exam.exam_questions.all()
# users = (CidUserAnswer.objects.filter(
# question__in=questions).values_list("user").distinct())
# user_answers_and_marks = defaultdict(list)
# user_answers_marks = defaultdict(list)
# user_answers = defaultdict(list)
# user_names = {}
# by_question = defaultdict(list)
# for u in users:
## Convoluted (probably...)
# user_names[u] = User.objects.filter(pk=u[0]).first().get_username()
# for q in questions:
# user_answer = q.user_answers.filter(user__in=u).first()
# if not user_answer:
# user_answers_marks[u].append(0)
# user_answers[u].append("")
# continue
# ans = user_answer.answer
# answer_score = user_answer.get_answer_score()
# user_answers[u].append(ans)
# user_answers_marks[u].append(answer_score)
# user_answers_and_marks[u].append((ans, answer_score))
# by_question[q].append(ans)
# user_scores = {}
# for user in user_answers_marks:
# user_scores[user] = sum(user_answers_marks[user])
# total = len(questions)
# return render(
# request,
# "anatomy/exam_scores.html",
# {
# "exam": exam,
# "questions": questions,
# "by_question": by_question,
# "user_answers": dict(user_answers),
# "user_answers_marks": dict(user_answers_marks),
# "user_scores": user_scores,
# "user_names": user_names,
# "user_answers_and_marks": user_answers_and_marks,
# },
# )
# def cid_scores(request, pk):
# #exam = get_object_or_404(Exam, pk=pk)
#
# # TODO:Need some kind of test for cid
# cid = pk
#
# #questions = exam.exam_questions.all()
# answers = CidUserAnswer.objects.filter(
# cid=cid)
#
#
# if not answers:
# raise Http404("cid not found")
#
# exam_ids = answers.values_list("exam").distinct()
#
# exams = Exam.objects.filter(id__in=exam_ids)
#
#
# return render(
# request,
# "anatomy/cid_scores.html",
# {
# "exams": exams,
# "cid": cid,
# },
# )
class AnatomyQuestionCreateBase(RevisionMixin, LoginRequiredMixin, CreateView):
model = AnatomyQuestion
@@ -1,16 +1,18 @@
{% extends 'rapids/exams.html' %}
{% extends exam.app_name|add:'/exams.html' %}
{% block content %}
<div id="stats-plot">{{plot|safe}}</div>
<div class="rapids">
<div class="">
<h2>{{ exam.name }}</h2>
User answer scores are cached, if you update or change an answer you will need to <a href="{% url 'rapids:exam_scores_refresh' exam.pk %}">refresh the scores</a>.
{% if cached_scores %}
User answer scores are cached, if you update or change an answer you will need to <a href="{% url exam.app_name|add:':exam_scores_refresh' exam.pk %}">refresh the scores</a>.
{% endif %}
{% if unmarked %}
<div class="alert alert-warning" role="alert">
The following questions need marking
{% for exam_index in unmarked %}
<a href="{% url 'rapids:mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
<a href="{% url exam.app_name|add:':mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
{% endfor %}
</div>
@@ -51,15 +53,17 @@
<tr>
<th>Candidate</th>
{% for cid in cids %}
{% comment %} <th><a href="{% url 'rapids:exam_scores_cid_user' exam.pk cid %}">{{cid}}</a></th> {% endcomment %}
{% comment %} <th><a href="{% url exam.app_name|add:':exam_scores_cid_user' exam.pk cid %}">{{cid}}</a></th> {% endcomment %}
<th><a href="">{{cids_user_id_map|get_item:cid}}</a></th>
{% endfor %}
</tr>
</thead>
{% for question in questions %}
{% block table_answers %}
{% endblock table_answers %}
{% comment %} {% for question in questions %}
<tr>
<td><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
<td><a href="{% url exam.app_name|add:':mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
{% if question.normal %}
[N]
{% else %}
@@ -72,7 +76,7 @@
{% endwith %}
{% endfor %}
</tr>
{% endfor %}
{% endfor %} {% endcomment %}
<tr>
<td>Score:</td>
{% for cid in cids %}
@@ -81,14 +85,7 @@
</tr>
</table>
Call breakdown
<ul>
{% for user, breakdown in user_answers_callstates.items %}
<li>
{{cids_user_id_map|get_item:user}} - {{breakdown}}
</li>
{% endfor %}
</ul>
{% block breakdown %}{% endblock breakdown %}
<details>
<summary>Email results</summary>
@@ -107,7 +104,7 @@
let additional_email = prompt("Please enter an additional email to send to (user and supervisor will automatically be used if available) if required");
let url = "{% url 'rapids:exam_report_email' exam_id=exam.pk %}";
let url = "{% url exam.app_name|add:':exam_report_email' exam_id=exam.pk %}";
if ( additional_email != null ) {
url = url + "?additional_email="+encodeURI(additional_email)
@@ -120,7 +117,7 @@
})
$("#email-results-check-button").click((evt) => {
window.location = "{% url 'rapids:exam_report_email_status' exam_id=exam.pk %}";
window.location = "{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}";
})
})
+5 -2
View File
@@ -1497,11 +1497,14 @@ class ExamViews(View, LoginRequiredMixin):
by_question = defaultdict(dict)
unmarked = set()
cached_scores = True
if self.app_name in ("rapids"):
user_answers_callstates = defaultdict(list)
user_answers_callstates_counted = {}
if self.app_name in ("physics", "sbas"):
cached_scores = False
questions = exam.exam_questions.all()
else:
questions = exam.exam_questions.all().prefetch_related("answers")
@@ -1642,7 +1645,6 @@ class ExamViews(View, LoginRequiredMixin):
user_data[u]["callstates"] = str(counted_callstates)
user_answers_callstates_counted[u] = counted_callstates
print(user_data)
exam.user_scores = user_data
@@ -1668,6 +1670,7 @@ class ExamViews(View, LoginRequiredMixin):
"median": median,
"mode": mode,
"plot": fig_html,
"cached_scores": cached_scores,
}
if self.app_name == "rapids":
@@ -1675,7 +1678,7 @@ class ExamViews(View, LoginRequiredMixin):
return render(
request,
f"{self.app_name}/exam_scores_new.html",
f"{self.app_name}/exam_scores.html",
template_variables,
)
+17 -60
View File
@@ -1,66 +1,23 @@
{% extends 'physics/exams.html' %}
{% extends 'generic/exam_scores_base.html' %}
{% block content %}
<div class="physics">
<h2>{{ exam.name }}</h2>
</div>
<div id="stats-block">
<h2>Stats</h2>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
<div id="stats-plot">
<h3>Distribution of results</h3>{{plot|safe}}
</div>
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm">
{% block table_answers %}
{% for question in questions %}
<tr>
<th>Candidate ID</th>
<th>Score</th>
</tr>
{% for user, value in user_answers_marks.items %}
<tr>
<td><a href="{% url 'cid_scores_admin' user %}">{{user}}</a></td>
<td>{{user_scores|get_item:user}}</td>
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Answers as a table</h3>
<table class="table table-dark table-striped table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'physics:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% endfor %}
</thead>
</tr>
{% for question in questions %}
<tr>
<td>Question {{forloop.counter}}</td>
{% for zipped_answers in by_question|get_item:question %}
<td>
<ol class="physics-ans" style="list-style-type: lower-alpha;">
{% for ans, score in zipped_answers %}
<li class="user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</li>
{% endfor %}
</ol>
<td>Question {{forloop.counter}}
</td>
{% for cid in cids %}
<td>
<ol class="physics-ans" style="list-style-type: lower-alpha;">
{% with by_question|get_item:question|get_item:cid as ans_score %}
{% for ans, score in ans_score %}
<li class="user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</li>
{% endfor %}
{% endwith %}
</ol>
</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for score in user_scores_list %}
<td>{{score}}</td>
{% endfor %}
<tr>
</table>
{% endfor %}
{% endblock %}
</div>
{% endblock %}
@@ -1,73 +0,0 @@
{% extends 'physics/exams.html' %}
{% block content %}
<div id="stats-plot">{{plot|safe}}</div>
<div class="physics">
<h2>{{ exam.name }}</h2>
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm cid-score-table">
<tr>
<th>Candidate ID</th>
<th>Score</th>
{% comment %} <th>Normalised Score</th> {% endcomment %}
</tr>
{% comment %} {% for user, value in user_answers_marks.items %} {% endcomment %}
{% for cid in cids %}
<tr>
<td><a href="{% url 'cid_scores_admin' cid %}">{{cid}}</a></td>
<td>{{user_scores|get_item:cid}}</td>
{% comment %} <td>{{user_scores_normalised|get_item:user}}</td> {% endcomment %}
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Answers as a table</h3>
<table class="table table-dark table-striped table-hover table-sm col-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'physics:exam_scores_cid_user' exam.pk cid None %}">{{cid}}</a></th>
{% comment %} <th><a href="">{{cid}}</a></th> {% endcomment %}
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td>Question {{forloop.counter}}
</td>
{% for cid in cids %}
<td>
<ol class="physics-ans" style="list-style-type: lower-alpha;">
{% with by_question|get_item:question|get_item:cid as ans_score %}
{% for ans, score in ans_score %}
<li class="user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</li>
{% endfor %}
{% endwith %}
</ol>
</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for cid in cids %}
<td>{{user_scores|get_item:cid}}</td>
{% endfor %}
</tr>
</table>
</div>
{% endblock %}
+4
View File
@@ -26,6 +26,10 @@ urlpatterns = [
name="exam_take_overview",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path("exam/<int:exam_id>/report/email", views.GenericExamViews.exam_report_email, name="exam_report_email"),
path("exam/<int:exam_id>/report/email/status", views.GenericExamViews.exam_report_email_status, name="exam_report_email_status"),
path("exam/<int:exam_id>/report/<int:user_id>", views.GenericExamViews.exam_user_report, name="exam_user_report"),
path("exam/<int:exam_id>/report/<int:user_id>/email", views.GenericExamViews.exam_user_report_email, name="exam_user_report_email"),
path("exam/<int:pk>/authors", views.ExamAuthorUpdate.as_view(), name="exam_authors"),
path(
"exam/<int:pk>/scores",
+30 -75
View File
@@ -1,79 +1,34 @@
{% extends 'rapids/exams.html' %}
{% extends 'generic/exam_scores_base.html' %}
{% block content %}
<div id="stats-plot">{{plot|safe}}</div>
<div class="rapids">
<h2>{{ exam.name }}</h2>
User answer scores are cached, if you update or change an answer you will need to <a href="{% url 'rapids:exam_scores_refresh' exam.pk %}">refresh the scores</a>.
{% if unmarked %}
<div class="alert alert-warning" role="alert">
The following questions need marking
{% for exam_index in unmarked %}
<a href="{% url 'rapids:mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
{% endfor %}
</div>
{% endif %}
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm cid-score-table">
<tr>
<th>Candidate ID</th>
<th>Score</th>
<th>Normalised Score</th>
</tr>
{% for user, value in user_answers_marks.items %}
<tr>
<td><a href="{% url 'cid_scores_admin' user %}">{{user}}</a></td>
<td>{{user_scores|get_item:user}}</td>
<td>{{user_scores_normalised|get_item:user}}</td>
</tr>
{% block table_answers %}
{% for question in questions %}
<tr>
<td><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
{% if question.normal %}
[N]
{% else %}
[A]
{% endif %}
</td>
{% for cid in cids %}
{% with by_question|get_item:question|get_item:cid as ans_score %}
<td class="user-answer-score-{{ans_score.1}}" title="answer score: {{ans_score.1}} [{{ans_score.2}}]">{{ans_score.0}}</td>
{% endwith %}
{% endfor %}
</table>
</div>
<div>
<h3>Answers as a table</h3>
<table class="table table-dark table-striped table-hover table-sm col-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'rapids:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% endfor %}
</tr>
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter}}</a>
{% if question.normal %}
[N]
{% else %}
[A]
{% endif %}
</td>
{% for ans, score in by_question|get_item:question %}
<td class="rapid-ans user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for score in user_scores_list %}
<td>{{score}}</td>
{% endfor %}
</tr>
</table>
</div>
{% endblock %}
{% endblock table_answers %}
{% block breakdown %}
<details>
<summary>Call breakdown</summary>
<ul>
{% for user, breakdown in user_answers_callstates.items %}
<li>
{{cids_user_id_map|get_item:user}} - {{breakdown}}
</li>
{% endfor %}
</ul>
</details>
{% endblock breakdown %}
+17 -59
View File
@@ -1,63 +1,21 @@
{% extends 'sbas/exams.html' %}
{% extends 'generic/exam_scores_base.html' %}
{% block content %}
<div class="sbas">
<h2>{{ exam.name }}</h2>
{% block table_answers %}
</div>
<div id="stats-block">
<h2>Stats</h2>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
<div id="stats-plot">
<h3>Distribution of results</h3>{{plot|safe}}
</div>
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm">
<tr>
<th>Candidate ID</th>
<th>Score</th>
</tr>
{% for user, value in user_answers_marks.items %}
<tr>
<td><a href="{% url 'cid_scores_admin' user %}">{{user}}</a></td>
<td>{{user_scores|get_item:user}}</td>
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Results as a table</h3>
<table class="table table-dark table-striped table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'sbas:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td>Question {{forloop.counter}}</td>
{% for ans, score in by_question|get_item:question %}
<td>
<span class="user-answer-score-{{score}}" title="answer score: {{score}}">{{ans}}</span>
</td>
{% for question in questions %}
<tr>
<td><a href="">Question {{forloop.counter}}</a>
</td>
{% comment %} {% for cid in cids %}
<td class="sbas-ans user-answer-score-{{score_by_question|get_item:question|get_item:cid}}" title="answer score: {{score_by_question|get_item:question|get_item:cid}}">{{ans_by_question|get_item:question|get_item:cid}}</td>
{% endfor %} {% endcomment %}
{% for cid in cids %}
{% with by_question|get_item:question|get_item:cid as ans_score %}
<td class="sbas-ans user-answer-score-{{ans_score.1}}" title="answer score: {{ans_score.1}}">{{ans_score.0}}</td>
{% endwith %}
{% endfor %}
</tr>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for score in user_scores_list %}
<td>{{score}}</td>
{% endfor %}
<tr>
</table>
</div>
{% endblock %}
{% endblock %}
-70
View File
@@ -1,70 +0,0 @@
{% extends 'sbas/exams.html' %}
{% block content %}
<div id="stats-plot">{{plot|safe}}</div>
<div class="sbas">
<h2>{{ exam.name }}</h2>
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Max score: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
</div>
<div>
<table class="table table-dark table-striped table-hover table-sm cid-score-table">
<tr>
<th>Candidate ID</th>
<th>Score</th>
{% comment %} <th>Normalised Score</th> {% endcomment %}
</tr>
{% comment %} {% for user, value in user_answers_marks.items %} {% endcomment %}
{% for cid in cids %}
<tr>
<td><a href="{% url 'cid_scores_admin' cid %}">{{cid}}</a></td>
<td>{{user_scores|get_item:cid}}</td>
{% comment %} <td>{{user_scores_normalised|get_item:user}}</td> {% endcomment %}
</tr>
{% endfor %}
</table>
</div>
<div>
<h3>Answers as a table</h3>
<table class="table table-dark table-striped table-hover table-sm col-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'sbas:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% comment %} <th><a href="">{{cid}}</a></th> {% endcomment %}
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td><a href="">Question {{forloop.counter}}</a>
</td>
{% comment %} {% for cid in cids %}
<td class="sbas-ans user-answer-score-{{score_by_question|get_item:question|get_item:cid}}" title="answer score: {{score_by_question|get_item:question|get_item:cid}}">{{ans_by_question|get_item:question|get_item:cid}}</td>
{% endfor %} {% endcomment %}
{% for cid in cids %}
{% with by_question|get_item:question|get_item:cid as ans_score %}
<td class="sbas-ans user-answer-score-{{ans_score.1}}" title="answer score: {{ans_score.1}}">{{ans_score.0}}</td>
{% endwith %}
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for cid in cids %}
<td>{{user_scores|get_item:cid}}</td>
{% endfor %}
</tr>
</table>
</div>
{% endblock %}
+4
View File
@@ -26,6 +26,10 @@ urlpatterns = [
name="exam_take_overview",
),
path("exam/<int:pk>/", views.GenericExamViews.exam_overview, name="exam_overview"),
path("exam/<int:exam_id>/report/email", views.GenericExamViews.exam_report_email, name="exam_report_email"),
path("exam/<int:exam_id>/report/email/status", views.GenericExamViews.exam_report_email_status, name="exam_report_email_status"),
path("exam/<int:exam_id>/report/<int:user_id>", views.GenericExamViews.exam_user_report, name="exam_user_report"),
path("exam/<int:exam_id>/report/<int:user_id>/email", views.GenericExamViews.exam_user_report_email, name="exam_user_report_email"),
path("exam/<int:pk>/authors", views.ExamAuthorUpdate.as_view(), name="exam_authors"),
path(
"exam/<int:pk>/scores",