Commit 0c4d6ba6 by Felix Sun

Made explanation for hints field in crowdsource_hinter.py more clear.

Fixed various commenting things.

Removed an unused function in the crowdsourced module coffeescript.

Improved commenting in hint_manager.

Fixed pep and pylint violations.
parent 0b25e761
...@@ -29,13 +29,16 @@ class CrowdsourceHinterFields(object): ...@@ -29,13 +29,16 @@ class CrowdsourceHinterFields(object):
default='False') default='False')
debug = String(help='String "True"/"False" - allows multiple voting', scope=Scope.content, debug = String(help='String "True"/"False" - allows multiple voting', scope=Scope.content,
default='False') default='False')
# hints[answer] = {str(pk): [hint_text, #votes]} # Usage: hints[answer] = {str(pk): [hint_text, #votes]}
# hints is a dictionary that takes answer keys.
# Each value is itself a dictionary, accepting hint_pk strings as keys,
# and returning [hint text, #votes] pairs as values
hints = Dict(help='A dictionary containing all the active hints.', scope=Scope.content, default={}) hints = Dict(help='A dictionary containing all the active hints.', scope=Scope.content, default={})
mod_queue = Dict(help='A dictionary containing hints still awaiting approval', scope=Scope.content, mod_queue = Dict(help='A dictionary containing hints still awaiting approval', scope=Scope.content,
default={}) default={})
hint_pk = Integer(help='Used to index hints.', scope=Scope.content, default=0) hint_pk = Integer(help='Used to index hints.', scope=Scope.content, default=0)
# A list of previous answers this student made to this problem. # A list of previous answers this student made to this problem.
# Of the form (answer, (hint_pk_1, hint_pk_2, hint_pk_3)) for each problem. hint_pk's are # Of the form [answer, [hint_pk_1, hint_pk_2, hint_pk_3]] for each problem. hint_pk's are
# None if the hint was not given. # None if the hint was not given.
previous_answers = List(help='A list of previous submissions.', scope=Scope.user_state, default=[]) previous_answers = List(help='A list of previous submissions.', scope=Scope.user_state, default=[])
user_voted = Boolean(help='Specifies if the user has voted on this problem or not.', user_voted = Boolean(help='Specifies if the user has voted on this problem or not.',
...@@ -166,7 +169,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -166,7 +169,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
random.sample(local_hints[answer].items(), 2) random.sample(local_hints[answer].items(), 2)
rand_hint_1 = rand_hint_1[0] rand_hint_1 = rand_hint_1[0]
rand_hint_2 = rand_hint_2[0] rand_hint_2 = rand_hint_2[0]
self.previous_answers += [(answer, (best_hint_index, hint_index_1, hint_index_2))] self.previous_answers += [[answer, [best_hint_index, hint_index_1, hint_index_2]]]
return {'best_hint': best_hint, return {'best_hint': best_hint,
'rand_hint_1': rand_hint_1, 'rand_hint_1': rand_hint_1,
...@@ -185,7 +188,6 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -185,7 +188,6 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
""" """
# The student got it right. # The student got it right.
# Did he submit at least one wrong answer? # Did he submit at least one wrong answer?
out = ''
if len(self.previous_answers) == 0: if len(self.previous_answers) == 0:
# No. Nothing to do here. # No. Nothing to do here.
return return
......
...@@ -61,13 +61,6 @@ class @Hinter ...@@ -61,13 +61,6 @@ class @Hinter
target.val('') target.val('')
target.data('cleared', true) target.data('cleared', true)
feedback_ui_change: =>
# Make all of the previous-answer divs hidden.
@$('.previous-answer').css('display', 'none')
# But, now find the selected div, and make it visible.
selector = '#previous-answer-' + @$('#feedback-select option:selected').attr('value')
@$(selector).css('display', 'inline')
render: (content) -> render: (content) ->
if content if content
# Trim leading and trailing whitespace # Trim leading and trailing whitespace
......
...@@ -60,7 +60,7 @@ What would you say to help someone who got this wrong answer? ...@@ -60,7 +60,7 @@ What would you say to help someone who got this wrong answer?
% endfor % endfor
</div> </div>
<p>Read about <a class="expand-goodhint" href="javascript:;">what makes a good hint</a>.</p> <p>Read about <a class="expand-goodhint" href="javascript:void(0);">what makes a good hint</a>.</p>
<div class="goodhint" style="display:none"> <div class="goodhint" style="display:none">
<h4>What makes a good hint?</h4> <h4>What makes a good hint?</h4>
......
...@@ -22,7 +22,7 @@ from xmodule.modulestore.django import modulestore ...@@ -22,7 +22,7 @@ from xmodule.modulestore.django import modulestore
@ensure_csrf_cookie @ensure_csrf_cookie
def hint_manager(request, course_id): def hint_manager(request, course_id):
try: try:
course = get_course_with_access(request.user, course_id, 'staff', depth=None) get_course_with_access(request.user, course_id, 'staff', depth=None)
except Http404: except Http404:
out = 'Sorry, but students are not allowed to access the hint manager!' out = 'Sorry, but students are not allowed to access the hint manager!'
return HttpResponse(out) return HttpResponse(out)
...@@ -74,12 +74,17 @@ def get_hints(request, course_id, field): ...@@ -74,12 +74,17 @@ def get_hints(request, course_id, field):
other_field = 'mod_queue' other_field = 'mod_queue'
field_label = 'Approved Hints' field_label = 'Approved Hints'
other_field_label = 'Hints Awaiting Moderation' other_field_label = 'Hints Awaiting Moderation'
# The course_id is of the form school/number/classname.
# We want to use the course_id to find all matching definition_id's.
# To do this, just take the school/number part - leave off the classname.
chopped_id = '/'.join(course_id.split('/')[:-1]) chopped_id = '/'.join(course_id.split('/')[:-1])
chopped_id = re.escape(chopped_id) chopped_id = re.escape(chopped_id)
all_hints = XModuleContentField.objects.filter(field_name=field, definition_id__regex=chopped_id) all_hints = XModuleContentField.objects.filter(field_name=field, definition_id__regex=chopped_id)
# big_out_dict[problem id] = [[answer, {pk: [hint, votes]}], sorted by answer] # big_out_dict[problem id] = [[answer, {pk: [hint, votes]}], sorted by answer]
# big_out_dict maps a problem id to a list of [answer, hints] pairs, sorted in order of answer.
big_out_dict = {} big_out_dict = {}
# name_dict[problem id] = Display name of problem # id_to name maps a problem id to the name of the problem.
# id_to_name[problem id] = Display name of problem
id_to_name = {} id_to_name = {}
for hints_by_problem in all_hints: for hints_by_problem in all_hints:
...@@ -88,7 +93,6 @@ def get_hints(request, course_id, field): ...@@ -88,7 +93,6 @@ def get_hints(request, course_id, field):
if name is None: if name is None:
continue continue
id_to_name[hints_by_problem.definition_id] = name id_to_name[hints_by_problem.definition_id] = name
# Answer list contains (answer, dict_of_hints) tuples.
def answer_sorter(thing): def answer_sorter(thing):
""" """
...@@ -102,6 +106,7 @@ def get_hints(request, course_id, field): ...@@ -102,6 +106,7 @@ def get_hints(request, course_id, field):
# Put all non-numerical answers first. # Put all non-numerical answers first.
return float('-inf') return float('-inf')
# Answer list contains [answer, dict_of_hints] pairs.
answer_list = sorted(json.loads(hints_by_problem.value).items(), key=answer_sorter) answer_list = sorted(json.loads(hints_by_problem.value).items(), key=answer_sorter)
big_out_dict[hints_by_problem.definition_id] = answer_list big_out_dict[hints_by_problem.definition_id] = answer_list
...@@ -113,6 +118,7 @@ def get_hints(request, course_id, field): ...@@ -113,6 +118,7 @@ def get_hints(request, course_id, field):
'id_to_name': id_to_name} 'id_to_name': id_to_name}
return render_dict return render_dict
def location_to_problem_name(loc): def location_to_problem_name(loc):
""" """
Given the location of a crowdsource_hinter module, try to return the name of the Given the location of a crowdsource_hinter module, try to return the name of the
...@@ -229,4 +235,4 @@ def approve(request, course_id, field): ...@@ -229,4 +235,4 @@ def approve(request, course_id, field):
problem_dict[answer] = {} problem_dict[answer] = {}
problem_dict[answer][pk] = hint_to_move problem_dict[answer][pk] = hint_to_move
problem_in_hints.value = json.dumps(problem_dict) problem_in_hints.value = json.dumps(problem_dict)
problem_in_hints.save() problem_in_hints.save()
\ No newline at end of file
import unittest
import nose.tools
import json import json
from django.http import Http404
from django.test.client import Client, RequestFactory from django.test.client import Client, RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
import mitxmako.middleware
from courseware.models import XModuleContentField from courseware.models import XModuleContentField
from courseware.tests.factories import ContentFactory from courseware.tests.factories import ContentFactory
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
import instructor.hint_manager as view import instructor.hint_manager as view
from student.tests.factories import UserFactory, AdminFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class HintManagerTest(ModuleStoreTestCase): class HintManagerTest(ModuleStoreTestCase):
...@@ -36,7 +32,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -36,7 +32,7 @@ class HintManagerTest(ModuleStoreTestCase):
value=json.dumps({'1.0': {'1': ['Hint 1', 2], value=json.dumps({'1.0': {'1': ['Hint 1', 2],
'3': ['Hint 3', 12]}, '3': ['Hint 3', 12]},
'2.0': {'4': ['Hint 4', 3]} '2.0': {'4': ['Hint 4', 3]}
})) }))
ContentFactory.create(field_name='mod_queue', ContentFactory.create(field_name='mod_queue',
definition_id=self.problem_id, definition_id=self.problem_id,
value=json.dumps({'2.0': {'2': ['Hint 2', 1]}})) value=json.dumps({'2.0': {'2': ['Hint 2', 1]}}))
...@@ -48,13 +44,12 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -48,13 +44,12 @@ class HintManagerTest(ModuleStoreTestCase):
# (I can't figure out how to get fake structures into the modulestore.) # (I can't figure out how to get fake structures into the modulestore.)
view.location_to_problem_name = lambda loc: "Test problem" view.location_to_problem_name = lambda loc: "Test problem"
def test_student_block(self): def test_student_block(self):
""" """
Makes sure that students cannot see the hint management view. Makes sure that students cannot see the hint management view.
""" """
c = Client() c = Client()
user = UserFactory.create(username='student', email='student@edx.org', password='test') UserFactory.create(username='student', email='student@edx.org', password='test')
c.login(username='student', password='test') c.login(username='student', password='test')
out = c.get(self.url) out = c.get(self.url)
print out print out
...@@ -70,7 +65,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -70,7 +65,7 @@ class HintManagerTest(ModuleStoreTestCase):
def test_invalid_field_access(self): def test_invalid_field_access(self):
""" """
Makes sure that field names other than 'mod_queue' and 'hints' are Makes sure that field names other than 'mod_queue' and 'hints' are
rejected. rejected.
""" """
out = self.c.post(self.url, {'op': 'delete hints', 'field': 'all your private data'}) out = self.c.post(self.url, {'op': 'delete hints', 'field': 'all your private data'})
...@@ -110,7 +105,7 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -110,7 +105,7 @@ class HintManagerTest(ModuleStoreTestCase):
'3': ['Hint 3', 12]}), '3': ['Hint 3', 12]}),
('2.0', {'4': ['Hint 4', 3]}) ('2.0', {'4': ['Hint 4', 3]})
]} ]}
self.assertTrue(out['all_hints'] == expected) self.assertTrue(out['all_hints'] == expected)
def test_deletehints(self): def test_deletehints(self):
""" """
...@@ -167,6 +162,3 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -167,6 +162,3 @@ class HintManagerTest(ModuleStoreTestCase):
problem_hints = XModuleContentField.objects.get(field_name='hints', definition_id=self.problem_id).value problem_hints = XModuleContentField.objects.get(field_name='hints', definition_id=self.problem_id).value
self.assertTrue(json.loads(problem_hints)['2.0']['2'] == ['Hint 2', 1]) self.assertTrue(json.loads(problem_hints)['2.0']['2'] == ['Hint 2', 1])
self.assertTrue(len(json.loads(problem_hints)['2.0']) == 2) self.assertTrue(len(json.loads(problem_hints)['2.0']) == 2)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment