diff --git a/physics/forms.py b/physics/forms.py index a5db8f9f..5ae1116a 100755 --- a/physics/forms.py +++ b/physics/forms.py @@ -27,6 +27,8 @@ class CidUserAnswerForm(ModelForm): super(CidUserAnswerForm, self).__init__(*args, **kwargs) #self.fields['answer'].required = False + + # This should be made generic? class ExamForm(ModelForm): class Meta: diff --git a/physics/templates/physics/exam_finish.html b/physics/templates/physics/exam_finish.html new file mode 100644 index 00000000..5f88b574 --- /dev/null +++ b/physics/templates/physics/exam_finish.html @@ -0,0 +1,23 @@ +{% extends 'base.html' %} + +{% block content %} +CID: {{cid}} + +

Exam: {{exam.name}}

+ +

Questions

+{{answer_count}} out of {{exam_length}} questions answered. Click to go to question. +
+{% for question, answer in question_answer_tuples %} + +{% endfor %} +
+ +{% endblock %} + +{% block js %} + +{% endblock %} \ No newline at end of file diff --git a/physics/templates/physics/exam_start.html b/physics/templates/physics/exam_start.html new file mode 100755 index 00000000..f3d4027e --- /dev/null +++ b/physics/templates/physics/exam_start.html @@ -0,0 +1,25 @@ +{% extends 'base.html' %} + +{% block content %} + +

{{exam.name}}

+ +Enter your CID in the below box.
+ + + + + +{% endblock %} diff --git a/physics/templates/physics/exam_take.html b/physics/templates/physics/exam_take.html old mode 100644 new mode 100755 index 863811a9..b4b3c194 --- a/physics/templates/physics/exam_take.html +++ b/physics/templates/physics/exam_take.html @@ -1,280 +1,104 @@ -{% extends 'physics/base.html' %} +{% extends 'base.html' %} {% block content %} - -
-

Exam: {{ exam.name }}

- - - -
- Candidate number: -
- -

Questions

- - {% autoescape off %} -
    - {% for question in questions.all %} - -
  1. - {{ question.stem }} -
      -
    1. - {{ question.a }}: -
    2. -
    3. - {{ question.b }}: -
    4. -
    5. - {{ question.c }}: -
    6. -
    7. - {{ question.d }}: -
    8. -
    9. - {{ question.e }}: -
    10. -
    -
  2. - {% endfor %} -
- {% endautoescape %} - - - - +CID: {{cid}} +
+

Question [{{pos|add:1}}/{{exam_length}}]

+ {% if exam.publish_results %} + + {% endif %} + +
+

{{question.stem|safe}}

+
+ - - - +
{% endblock %} + +{% block js %} + +{% endblock %} +{% block css %} + +{% endblock %} \ No newline at end of file diff --git a/physics/templates/physics/exam_take_old.html b/physics/templates/physics/exam_take_old.html new file mode 100644 index 00000000..863811a9 --- /dev/null +++ b/physics/templates/physics/exam_take_old.html @@ -0,0 +1,280 @@ +{% extends 'physics/base.html' %} + +{% block content %} + +
+

Exam: {{ exam.name }}

+ + + +
+ Candidate number: +
+ +

Questions

+ + {% autoescape off %} +
    + {% for question in questions.all %} + +
  1. + {{ question.stem }} +
      +
    1. + {{ question.a }}: +
    2. +
    3. + {{ question.b }}: +
    4. +
    5. + {{ question.c }}: +
    6. +
    7. + {{ question.d }}: +
    8. +
    9. + {{ question.e }}: +
    10. +
    +
  2. + {% endfor %} +
+ {% endautoescape %} + + + + +
+ + + + + +{% endblock %} diff --git a/physics/urls.py b/physics/urls.py index 93228f27..b0e84d90 100644 --- a/physics/urls.py +++ b/physics/urls.py @@ -13,7 +13,10 @@ urlpatterns = [ #path("question//update", views.QuestionUpdate.as_view(), name="anatomy_question_update"), #path("exam///mark", views.mark, name="mark"), #path("exam//mark", views.mark_overview, name="mark_overview"), - path("exam//take", views.exam_take, name="exam_take"), + path("exam//take_old", views.exam_take_old, name="exam_take_old"), + path("exam////take", views.exam_take, name="exam_take"), + path("exam//start", views.exam_start, name="exam_start"), + path("exam///finish", views.exam_finish, name="exam_finish"), path("exam//", views.PhysicsExamViews.exam_overview, name="exam_overview"), path("exam//scores", views.exam_scores_cid, name="exam_scores_cid"), diff --git a/physics/views.py b/physics/views.py index 41158f74..0992e566 100644 --- a/physics/views.py +++ b/physics/views.py @@ -46,7 +46,7 @@ from rest_framework.pagination import PageNumberPagination from django.core.exceptions import PermissionDenied -from .forms import ExamForm +from .forms import CidUserAnswerForm, ExamForm from .decorators import user_is_author_or_physics_checker, user_is_exam_author_or_physics_checker class AuthorOrCheckerRequiredMixin(object): @@ -240,7 +240,7 @@ def exam_scores_cid_user(request, pk, sk): ) -def exam_take(request, pk): +def exam_take_old(request, pk): exam = get_object_or_404(Exam, pk=pk) @@ -251,13 +251,129 @@ def exam_take(request, pk): return render( request, - "physics/exam_take.html", + "physics/exam_take_old.html", { "exam": exam, "questions": questions, }, ) +def exam_start(request, pk): + exam = get_object_or_404(Exam, pk=pk) + + if not exam.active: + raise Http404("Exam not found") + + return render( + request, + "physics/exam_start.html", + { + "exam": exam, + }, + ) + +def exam_finish(request, pk, cid): + exam = get_object_or_404(Exam, pk=pk) + + questions = exam.exam_questions.all() + + answers = CidUserAnswer.objects.filter( + cid=cid, exam=exam) + + answer_question_map = {} + for ans in answers: + answer_question_map[ans.question] = ans + + question_answer_tuples = [] + answer_count = 0 + for q in questions: + if q in answer_question_map and answer_question_map[q].answer: + question_answer_tuples.append((q, answer_question_map[q])) + answer_count += 1 + else: + question_answer_tuples.append((q, None)) + + if not exam.active: + raise Http404("Exam not found") + + return render( + request, + "physics/exam_finish.html", + { + "exam": exam, + "cid": cid, + "question_answer_tuples": question_answer_tuples, + "answer_count": answer_count, + "exam_length": len(questions), + }, + ) + +def exam_take(request, pk, sk, cid): + + exam = get_object_or_404(Exam, pk=pk) + + if not exam.active: + raise Http404("Exam not found") + + question = exam.exam_questions.all()[sk] + + exam_length = len(exam.exam_questions.all()) + + pos = exam.get_question_index(question) + + answer = question.cid_user_answers.filter( + cid=cid, exam=exam).first() + + if request.method == "POST": + if answer: + form = CidUserAnswerForm(request.POST, instance=answer) + else: + form = CidUserAnswerForm(request.POST) + if form.is_valid(): + answer = form.save(commit=False) + answer.cid = cid + answer.question = question + answer.exam = exam + # answer.published_date = timezone.now() + answer.save() + if "next" in request.POST: + return redirect("sbas:exam_take", pk=pk, sk=pos + 1, cid=cid) + elif "previous" in request.POST: + return redirect("sbas:exam_take", pk=pk, sk=pos - 1, cid=cid) + elif "finish" in request.POST: + return redirect("sbas:exam_finish", pk=pk, cid=cid) + elif "goto" in request.POST: + return redirect("sbas:exam_take", pk=pk, sk=int(request.POST.get("goto")), cid=cid) + else: + form = CidUserAnswerForm(instance=answer) + + previous = -1 + if sk > 0: + previous = sk - 1 + next = sk + 1 + if sk == exam_length - 1: + next = False + + saved_answer = False + if answer is not None: + saved_answer = answer.answer + + + return render( + request, + "physics/exam_take.html", + { + "form": form, + "cid": cid, + "exam": exam, + "question": question, + "next": next, + "previous": previous, + "exam_length": exam_length, + "pos": pos, + "saved_answer": saved_answer, + }, + ) def loadJsonAnswer(answer): # As access is not restricted make sure the data appears valid