Add a joyride tip, fix a couple bugs with quiz generation
authorCharles Connell <charles@connells.org>
Tue, 13 May 2014 14:17:32 +0000 (10:17 -0400)
committerCharles Connell <charles@connells.org>
Tue, 13 May 2014 14:17:32 +0000 (10:17 -0400)
karmaworld/apps/notes/models.py
karmaworld/apps/notes/views.py
karmaworld/apps/quizzes/create_quiz.py
karmaworld/apps/quizzes/tasks.py
karmaworld/templates/notes/note_base.html
karmaworld/templates/notes/note_quiz.html

index 7ac16939347334309c01cb059b63f6597a7a4ac6..9aecbcc8ee734d431c347b3ea71369d45ba2d559 100644 (file)
@@ -41,6 +41,7 @@ from karmaworld.apps.notes.search import SearchIndex
 from karmaworld.settings.manual_unique_together import auto_add_check_unique_together
 
 ANONYMOUS_UPLOAD_URLS = 'anonymous_upload_urls'
+KEYWORD_MTURK_THRESHOLD = 3
 
 logger = logging.getLogger(__name__)
 fs = FileSystemStorage(location=settings.MEDIA_ROOT)
@@ -287,6 +288,12 @@ class Note(Document):
         key.set_contents_from_string(html, headers=s3_upload_headers)
         key.set_xml_acl(all_read_xml_acl)
 
+    def remaining_thanks_for_mturk(self):
+        return KEYWORD_MTURK_THRESHOLD - self.thanks
+
+    def total_thanks_for_mturk(self):
+        return KEYWORD_MTURK_THRESHOLD
+
     def get_absolute_url(self):
         """ Resolve note url, use 'note' route and slug if slug
             otherwise use note.id
index ff906ff58cd8a03572bdd73bce046ffd2d241940..effd4a1689468e6ca3fb2e16fd7560412e32644c 100644 (file)
@@ -25,7 +25,7 @@ from django.views.generic import FormView
 from django.views.generic import View
 from django.views.generic.detail import SingleObjectMixin
 
-from karmaworld.apps.notes.models import Note
+from karmaworld.apps.notes.models import Note, KEYWORD_MTURK_THRESHOLD
 from karmaworld.apps.notes.forms import NoteForm, NoteDeleteForm
 
 
@@ -206,8 +206,12 @@ class NoteKeywordsView(FormView, SingleObjectMixin):
             word = form['keyword'].data
             definition = form['definition'].data
             id = form['id'].data
-            if word == '':
-                continue
+            if not word and not definition:
+                try:
+                    keyword_object = Keyword.objects.get(id=id)
+                    keyword_object.delete()
+                except (ValueError, ObjectDoesNotExist):
+                    pass
             try:
                 keyword_object = Keyword.objects.get(id=id)
             except (ValueError, ObjectDoesNotExist):
@@ -310,7 +314,7 @@ def process_note_thank_events(request_user, note):
 
     # If note thanks exceeds a threshold, create a Mechanical
     # Turk task to get some keywords for it
-    if note.thanks == 3:
+    if note.thanks == KEYWORD_MTURK_THRESHOLD:
         submit_extract_keywords_hit.delay(note)
 
 
index 13e76e5813d014846b2151e875cd7f41ff38c3d5..cd3bb6c1e6c0db193d79acd94413de84ac83b6e9 100644 (file)
@@ -14,7 +14,7 @@ class MultipleChoiceQuestion(BaseQuizQuestion):
         self.choices = choices
 
     def __unicode__(self):
-        return "Multiple choice: {0}: {1}".format(self.question_text, ", ".join(map(str, self.choices)))
+        return u"Multiple choice: {0}: {1}".format(self.question_text, ", ".join(map(str, self.choices)))
 
     def __str__(self):
         return unicode(self)
@@ -38,28 +38,13 @@ class MultipleChoiceOption(object):
         return str(self)
 
 
-class FlashCardQuestion(BaseQuizQuestion):
-    def __init__(self, keyword_side, definition_side):
-        self.keyword_side = keyword_side
-        self.definition_side = definition_side
-
-    def __unicode__(self):
-        return "Flash card: {0} / {1}".format(self.keyword_side, self.definition_side)
-
-    def __str__(self):
-        return unicode(self)
-
-    def __repr__(self):
-        return str(self)
-
-
 class TrueFalseQuestion(BaseQuizQuestion):
     def __init__(self, question_text, true):
         self.question_text = question_text
         self.true = true
 
     def __unicode__(self):
-        return "True or false: {0}".format(self.question_text)
+        return u"True or false: {0}".format(self.question_text)
 
     def __str__(self):
         return unicode(self)
@@ -88,7 +73,7 @@ def _create_keyword_multiple_choice(keyword, keywords):
                        text=other_keyword.word,
                        correct=False))
 
-    question_text = 'Pick the keyword to match "{d}"'.format(d=keyword.definition)
+    question_text = u'Pick the keyword to match "{d}"'.format(d=keyword.definition)
 
     return MultipleChoiceQuestion(question_text, choices)
 
@@ -101,7 +86,7 @@ def _create_definition_multiple_choice(keyword, keywords):
                        text=other_keyword.definition,
                        correct=False))
 
-    question_text = 'Pick the definition to match "{w}"'.format(w=keyword.word)
+    question_text = u'Pick the definition to match "{w}"'.format(w=keyword.word)
 
     return MultipleChoiceQuestion(question_text, choices)
 
@@ -115,20 +100,19 @@ def _create_keyword_definition_true_false(keyword, keywords):
         other_keyword = random.choice(keywords.exclude(id=keyword.id))
         definition = other_keyword.definition
 
-    question_text = 'The keyword "{w}" matches the definition "{d}"'. \
+    question_text = u'The keyword "{w}" matches the definition "{d}"'. \
         format(w=keyword.word, d=definition)
 
     return TrueFalseQuestion(question_text, true)
 
 
-def _create_keyword_flashcard_blank(keyword):
-    return FlashCardQuestion(keyword.definition, keyword.word)
-
-
 def quiz_from_keywords(note):
     keywords = Keyword.objects.filter(note=note)
     questions = []
 
+    if len(keywords) < 4:
+        return []
+
     for keyword in keywords:
         if keyword.word and keyword.definition:
             question_type = random.choice(GENERATED_QUESTION_TYPE)
index 133a7f7253e8bdc4d2b6b1a34f9f7cf3a53a854a..af6e67765f0684e5048321eeea5808332947d70f 100644 (file)
@@ -14,8 +14,8 @@ from karmaworld.apps.quizzes.models import Keyword
 
 logger = get_task_logger(__name__)
 
-HIT_TITLE = 'Choose keywords and descriptions from course notes'
-HIT_DESCRIPTION = "Read students' course notes on Karmanotes.org and " \
+HIT_TITLE = 'Help people learn by finding keywords in college course notes'
+HIT_DESCRIPTION = "Read students' course notes on KarmaNotes.org and " \
                   "identify 10 keywords along with descriptions of them"
 HIT_OVERVIEW_TEMPLATE = \
         '<p>Go to the page at KarmaNotes.org by clicking the link provided below. ' \
index b8abbcf4617fdb74e991e4a260e2d9063decd640..4b1593aaa4d19ef0af8f175a0fd0accfc4b5b1ce 100644 (file)
     <li data-id="keywords-tab-button" data-text="Awesome!" data-options="tip_location: top">
       <p>Keywords you define will appear here, and you can define new ones here too.</p>
     </li>
+    {% if note.thanks < 3 %}
+      <li data-id="thank-number" data-text="Awesome!" data-options="tip_location: top">
+        <p>Keywords and quizzes are automatically generated when a note gets {{ note.total_thanks_for_mturk }} thanks. This note needs {{ note.remaining_thanks_for_mturk }} more!</p>
+      </li>
+    {% endif %}
   </ol>
 
 {% endblock %}
index 64d7a0cad83bfdb5e1a8ba5bc1e7136ee6b95792..9126d2439da5e50b94107d51cdbaf041265b370e 100644 (file)
@@ -6,8 +6,8 @@
           These quiz questions have been randomly generated from the keywords and definitions associated
           with this note. Refresh to get different questions.
         {% else %}
-          No keywords with definitions have been supplied, so we can't generate any quiz questions.
-          Provide some key terms with their definitions, and we'll create questions based on them.
+          Not enough keywords with definitions have been supplied, so we can't generate any quiz questions.
+          Provide at least 4 key terms with their definitions, and we'll create questions based on them.
         {% endif %}
       </div>
     </div>