diff --git a/common/lib/xmodule/xmodule/crowdsource_hinter.py b/common/lib/xmodule/xmodule/crowdsource_hinter.py
index 1d424b7fff..97120bbf1c 100644
--- a/common/lib/xmodule/xmodule/crowdsource_hinter.py
+++ b/common/lib/xmodule/xmodule/crowdsource_hinter.py
@@ -42,6 +42,14 @@ class CrowdsourceHinterFields(object):
user_voted = Boolean(help='Specifies if the user has voted on this problem or not.',
scope=Scope.user_state, default=False)
+ moderate = String(help='''If 'True', then all hints must be approved by staff before
+ becoming visible.
+ This field is automatically populated from the xml metadata.''', scope=Scope.settings,
+ default='False')
+
+ mod_queue = Dict(help='''Contains hints that have not been approved by the staff yet. Structured
+ identically to the hints dictionary.''', scope=Scope.content, default={})
+
class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
''' An Xmodule that makes crowdsourced hints.
@@ -115,7 +123,11 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
print self.hints
answer = self.ans_to_text(get)
# Look for a hint to give.
+<<<<<<< HEAD
if answer not in self.hints:
+=======
+ if (answer not in self.hints) or (len(self.hints[answer]) == 0):
+>>>>>>> Began work on instructor view to hinting system.
# No hints to give. Return.
self.previous_answers += [(answer, (None, None, None))]
return json.dumps({'contents': ' '})
@@ -126,12 +138,23 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
if len(self.hints[answer]) == 1:
rand_hint_1 = ''
rand_hint_2 = ''
+<<<<<<< HEAD
self.previous_answers += [(answer, (0, None, None))]
elif len(self.hints[answer]) == 2:
best_hint = self.hints[answer][0][0]
rand_hint_1 = self.hints[answer][1][0]
rand_hint_2 = ''
self.previous_answers += [(answer, (0, 1, None))]
+=======
+ self.previous_answers += [[answer, [best_hint_index, None, None]]]
+ elif n_hints == 2:
+ best_hint = self.hints[answer].values()[0][0]
+ best_hint_index = self.hints[answer].keys()[0]
+ rand_hint_1 = self.hints[answer].values()[1][0]
+ hint_index_1 = self.hints[answer].keys()[1]
+ rand_hint_2 = ''
+ self.previous_answers += [[answer, [best_hint_index, hint_index_1, None]]]
+>>>>>>> Began work on instructor view to hinting system.
else:
hint_index_1, hint_index_2 = random.sample(xrange(len(self.hints[answer])), 2)
rand_hint_1 = self.hints[answer][hint_index_1][0]
@@ -163,10 +186,20 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
'" style="display:none"> Which hint was most helpful when you got the wrong answer of '\
+ answer + '?'
# Add each hint to the html string, with a vote button.
- for j, hint_id in enumerate(hints_offered):
+ for hint_id in hints_offered:
if hint_id != None:
+<<<<<<< HEAD
out += '
' + self.hints[answer][hint_id][0]
+=======
+ hint_id = str(hint_id)
+ try:
+ out += '
' + self.hints[answer][hint_id][0]
+ except KeyError:
+ # Sometimes, the hint that a user saw will have been deleted by the instructor.
+ continue
+>>>>>>> Began work on instructor view to hinting system.
# Or, let the student create his own hint
@@ -227,15 +260,45 @@ What would you say to help someone who got this wrong answer?
answer = self.previous_answers[int(get['answer'])][0]
# Add the new hint to self.hints. (Awkward because a direct write
# is necessary.)
+<<<<<<< HEAD
temp_dict = self.hints
temp_dict[answer].append([hint, 1]) # With one vote (the user himself).
self.hints = temp_dict
+=======
+ if self.moderate:
+ temp_dict = self.mod_queue
+ else:
+ temp_dict = self.hints
+ if answer in temp_dict:
+ temp_dict[answer][self.hint_pk] = [hint, 1] # With one vote (the user himself).
+ else:
+ temp_dict[answer] = {self.hint_pk: [hint, 1]}
+ self.hint_pk += 1
+ if self.moderate:
+ self.mod_queue = temp_dict
+ else:
+ self.hints = temp_dict
+>>>>>>> Began work on instructor view to hinting system.
# Mark the user has having voted; reset previous_answers
self.user_voted = True
self.previous_answers = []
return json.dumps({'contents': 'Thank you for your hint!'})
+<<<<<<< HEAD
+=======
+ def delete_hint(self, answer, hint_id):
+ '''
+ From the answer, delete the hint with hint_id.
+ Not designed to be accessed via POST request, for now.
+ -LIKELY DEPRECATED.
+ '''
+ temp_hints = self.hints
+ del temp_hints[answer][str(hint_id)]
+ self.hints = temp_hints
+
+
+>>>>>>> Began work on instructor view to hinting system.
class CrowdsourceHinterDescriptor(CrowdsourceHinterFields, XmlDescriptor):
module_class = CrowdsourceHinterModule
stores_state = True
diff --git a/lms/djangoapps/instructor/hint_manager.py b/lms/djangoapps/instructor/hint_manager.py
new file mode 100644
index 0000000000..431d3f5d7c
--- /dev/null
+++ b/lms/djangoapps/instructor/hint_manager.py
@@ -0,0 +1,138 @@
+'''
+Views for hint management.
+'''
+
+from collections import defaultdict
+import csv
+import json
+import logging
+from markupsafe import escape
+import os
+import re
+import requests
+from requests.status_codes import codes
+import urllib
+from collections import OrderedDict
+
+from StringIO import StringIO
+
+from django.conf import settings
+from django.contrib.auth.models import User, Group
+from django.http import HttpResponse, Http404
+from django_future.csrf import ensure_csrf_cookie
+from django.views.decorators.cache import cache_control
+from mitxmako.shortcuts import render_to_response, render_to_string
+from django.core.urlresolvers import reverse
+
+from courseware.courses import get_course_with_access
+from courseware.models import XModuleContentField
+
+
+@ensure_csrf_cookie
+def hint_manager(request, course_id):
+ try:
+ course = get_course_with_access(request.user, course_id, 'staff', depth=None)
+ except Http404:
+ out = 'Sorry, but students are not allowed to access the hint manager!'
+ return
+ if request.method == 'GET':
+ out = get_hints(request, course_id, 'mod_queue')
+ return render_to_response('courseware/hint_manager.html', out)
+ field = request.POST['field']
+ if not (field == 'mod_queue' or field == 'hints'):
+ # Invalid field. (Don't let users continue - they may overwrite other db's)
+ return
+ if request.POST['op'] == 'delete hints':
+ delete_hints(request, course_id, field)
+ if request.POST['op'] == 'switch fields':
+ pass
+ if request.POST['op'] == 'change votes':
+ change_votes(request, course_id, field)
+ rendered_html = render_to_string('courseware/hint_manager_inner.html', get_hints(request, course_id, field))
+ return HttpResponse(json.dumps({'success': True, 'contents': rendered_html}))
+
+
+
+def get_hints(request, course_id, field):
+ # field indicates the database entry that we are modifying.
+ # Right now, the options are 'hints' or 'mod_queue'.
+ # DON'T TRUST field attributes that come from ajax. Use an if statement
+ # to make sure the field is valid before plugging into functions.
+
+ out = ''
+ if field == 'mod_queue':
+ other_field = 'hints'
+ field_label = 'Hints Awaiting Moderation'
+ other_field_label = 'Approved Hints'
+ elif field == 'hints':
+ other_field = 'mod_queue'
+ field_label = 'Approved Hints'
+ other_field_label = 'Hints Awaiting Moderation'
+ chopped_id = '/'.join(course_id.split('/')[:-1])
+ chopped_id = re.escape(chopped_id)
+ all_hints = XModuleContentField.objects.filter(field_name=field, definition_id__regex=chopped_id)
+ for problem in all_hints:
+ out += '
'
+ out += '' + hint[0] + \
+ '
Votes: '
+ out += '
+ ${hint[0]}
+
+ Votes:
+