3 # Copyright (C) 2014 FinalsClub Foundation
4 from itertools import chain
6 from django.core.exceptions import ObjectDoesNotExist
7 from django.core.urlresolvers import reverse
8 from django.forms.formsets import formset_factory
9 from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponseNotFound, HttpResponse
11 from django.views.generic import DetailView, FormView
12 from django.views.generic.detail import SingleObjectMixin
13 from django.views.generic.edit import FormMixin, ProcessFormView
14 from karmaworld.apps.notes.models import Note
15 from karmaworld.apps.quizzes.forms import KeywordForm
16 from karmaworld.apps.quizzes.models import Quiz, ALL_QUESTION_CLASSES, Keyword, BaseQuizQuestion, \
17 ALL_QUESTION_CLASSES_NAMES, MultipleChoiceQuestion, MultipleChoiceOption, TrueFalseQuestion, FlashCardQuestion
18 from karmaworld.utils import ajax_pk_base, ajax_base
21 class QuizView(DetailView):
22 queryset = Quiz.objects.all()
24 context_object_name = 'quiz' # name passed to template
25 template_name = 'quizzes/quiz.html'
27 def get_context_data(self, **kwargs):
29 for cls in ALL_QUESTION_CLASSES:
31 [(cls.__name__, o) for o in cls.objects.filter(quiz=self.object)]
34 result_list = sorted(chain.from_iterable(all_questions),
35 key=lambda o: o[1].timestamp,
38 kwargs['questions'] = result_list
39 kwargs['quiz'] = self.object
41 return super(QuizView, self).get_context_data(**kwargs)
44 class KeywordEditView(FormView):
45 template_name = 'quizzes/keyword_edit.html'
46 form_class = formset_factory(KeywordForm)
48 def get(self, requests, *args, **kwargs):
50 return super(KeywordEditView, self).get(requests, *args, **kwargs)
52 def post(self, requests, *args, **kwargs):
54 return super(KeywordEditView, self).post(requests, *args, **kwargs)
56 def lookup_note(self):
57 self.note = Note.objects.get(slug=self.kwargs['slug'])
59 def get_success_url(self):
60 return reverse('keyword_edit', args=(self.note.course.school.slug, self.note.course.slug, self.note.slug))
62 def get_initial(self):
63 existing_keywords = self.note.keyword_set.order_by('id')
64 initial_data = [{'keyword': keyword.word, 'definition': keyword.definition, 'id': keyword.pk}
65 for keyword in existing_keywords]
68 def get_context_data(self, **kwargs):
69 kwargs['note'] = self.note
70 kwargs['prototype_form'] = KeywordForm
71 return super(KeywordEditView, self).get_context_data(**kwargs)
73 def form_valid(self, formset):
75 word = form['keyword'].data
76 definition = form['definition'].data
81 keyword_object = Keyword.objects.get(id=id)
82 except (ValueError, ObjectDoesNotExist):
83 keyword_object = Keyword()
85 keyword_object.note = self.note
86 keyword_object.word = word
87 keyword_object.definition = definition
90 return super(KeywordEditView, self).form_valid(formset)
93 def quiz_answer(request):
94 """Handle an AJAX request checking if a quiz answer is correct"""
95 if not (request.method == 'POST' and request.is_ajax()):
96 # return that the api call failed
97 return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'must be a POST ajax request'}),
98 mimetype="application/json")
101 question_type_str = request.POST['question_type']
102 if question_type_str not in ALL_QUESTION_CLASSES_NAMES:
103 raise Exception("Not a valid question type")
104 question_type_class = ALL_QUESTION_CLASSES_NAMES[question_type_str]
105 question = question_type_class.objects.get(id=request.POST['id'])
109 if question_type_class is MultipleChoiceQuestion:
110 answer = MultipleChoiceOption.objects.get(id=request.POST['answer'])
111 if answer.question == question and answer.correct:
114 elif question_type_class is TrueFalseQuestion:
115 answer = request.POST['answer'] == 'true'
116 correct = question.true == answer
118 elif question_type_class is FlashCardQuestion:
119 answer = request.POST['answer'].lower()
120 correct = question.keyword_side.lower() == answer
123 return HttpResponseBadRequest(json.dumps({'status': 'fail',
124 'message': e.message,
125 'exception': e.__class__.__name__}),
126 mimetype="application/json")
128 return HttpResponse(json.dumps({'correct': correct}), mimetype="application/json")
131 def set_keyword(annotation_uri, keyword, definition, ranges):
133 keyword = Keyword.objects.get(note_id=annotation_uri, word=keyword, ranges=ranges)
134 keyword.definition = definition
136 except ObjectDoesNotExist:
137 Keyword.objects.create(note_id=annotation_uri, word=keyword, definition=definition, ranges=ranges)
140 def delete_keyword(annotation_uri, keyword, definition, ranges):
141 keyword = Keyword.objects.get(note_id=annotation_uri, word=keyword, definition=definition, ranges=ranges)
142 keyword.definition = definition
146 def process_set_delete_keyword(request):
147 annotator_data = json.loads(request.raw_post_data)
148 annotation_uri = annotator_data['uri']
149 keyword = annotator_data['quote']
150 definition = annotator_data['text']
151 ranges = json.dumps(annotator_data['ranges'])
154 if request.method in ('POST', 'PUT'):
155 set_keyword(annotation_uri, keyword, definition, ranges)
156 elif request.method == 'DELETE':
157 delete_keyword(annotation_uri, keyword, definition, ranges)
159 return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': e.message}),
160 mimetype="application/json")
163 def set_delete_keyword_annotator(request):
164 return ajax_base(request, process_set_delete_keyword, ('POST', 'PUT', 'DELETE'))
167 def get_keywords_annotator(request):
168 annotation_uri = request.GET['uri']
171 keywords = Keyword.objects.filter(note_id=annotation_uri).exclude(ranges=None)
173 'total': len(keywords),
176 for keyword in keywords:
178 'quote': keyword.word,
179 'text': keyword.definition,
180 'ranges': json.loads(keyword.ranges),
181 'created': keyword.timestamp.isoformat(),
183 keywords_data['rows'].append(keyword_data)
185 return HttpResponse(json.dumps(keywords_data), mimetype='application/json')
187 except ObjectDoesNotExist, e:
188 return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': e.message}),
189 mimetype="application/json")
192 def get_keywords_datatables(request):
193 annotation_uri = request.GET['uri']
196 keywords = Keyword.objects.filter(note_id=annotation_uri)
198 'total': len(keywords),
201 for keyword in keywords:
203 'quote': keyword.word,
204 'text': keyword.definition,
205 'ranges': json.loads(keyword.ranges),
206 'created': keyword.timestamp.isoformat(),
208 keywords_data['rows'].append(keyword_data)
210 return HttpResponse(json.dumps(keywords_data), mimetype='application/json')
212 except ObjectDoesNotExist, e:
213 return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': e.message}),
214 mimetype="application/json")