Commit fc8acb61 by Felix Sun

Changed voting dialog to only display one tab per answer.

No tests for this, yet.

Conflicts:
	common/lib/xmodule/xmodule/crowdsource_hinter.py
	common/templates/hinter_display.html
parent 87500a47
...@@ -188,8 +188,8 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -188,8 +188,8 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
Args: Args:
`data` -- not actually used. (It is assumed that the answer is correct.) `data` -- not actually used. (It is assumed that the answer is correct.)
Output keys: Output keys:
- 'index_to_hints' maps previous answer indices to hints that the user saw earlier. - 'answer_to_hints': a nested dictionary.
- 'index_to_answer' maps previous answer indices to the actual answer submitted. answer_to_hints[answer][hint_pk] returns the text of the hint.
""" """
# 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?
...@@ -199,27 +199,24 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -199,27 +199,24 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
# Make a hint-voting interface for each wrong answer. The student will only # Make a hint-voting interface for each wrong answer. The student will only
# be allowed to make one vote / submission, but he can choose which wrong answer # be allowed to make one vote / submission, but he can choose which wrong answer
# he wants to look at. # he wants to look at.
# index_to_hints[previous answer #] = [(hint text, hint pk), + ] answer_to_hints = {} #answer_to_hints[answer text][hint pk] -> hint text
index_to_hints = {}
# index_to_answer[previous answer #] = answer text
index_to_answer = {}
# Go through each previous answer, and populate index_to_hints and index_to_answer. # Go through each previous answer, and populate index_to_hints and index_to_answer.
for i in xrange(len(self.previous_answers)): for i in xrange(len(self.previous_answers)):
answer, hints_offered = self.previous_answers[i] answer, hints_offered = self.previous_answers[i]
index_to_hints[i] = [] if answer not in answer_to_hints:
index_to_answer[i] = answer answer_to_hints[answer] = {}
if answer in self.hints: if answer in self.hints:
# Go through each hint, and add to index_to_hints # Go through each hint, and add to index_to_hints
for hint_id in hints_offered: for hint_id in hints_offered:
if hint_id is not None: if (hint_id is not None) and (hint_id not in answer_to_hints[answer]):
try: try:
index_to_hints[i].append((self.hints[answer][str(hint_id)][0], hint_id)) answer_to_hints[answer][hint_id] = self.hints[answer][str(hint_id)][0]
except KeyError: except KeyError:
# Sometimes, the hint that a user saw will have been deleted by the instructor. # Sometimes, the hint that a user saw will have been deleted by the instructor.
continue continue
return {'index_to_hints': index_to_hints, 'index_to_answer': index_to_answer} return {'answer_to_hints': answer_to_hints}
def tally_vote(self, data): def tally_vote(self, data):
""" """
...@@ -229,27 +226,29 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -229,27 +226,29 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
`data` -- expected to have the following keys: `data` -- expected to have the following keys:
'answer': ans_no (index in previous_answers) 'answer': ans_no (index in previous_answers)
'hint': hint_pk 'hint': hint_pk
'pk_list': We will return a list of how many votes each hint has so far.
It's up to the browser to specify which hints to return vote counts for.
Every pk listed here will have a hint count returned.
Returns key 'hint_and_votes', a list of (hint_text, #votes) pairs. Returns key 'hint_and_votes', a list of (hint_text, #votes) pairs.
""" """
if self.user_voted: if self.user_voted:
return {} return json.dumps({'contents': 'Sorry, but you have already voted!'})
ans_no = int(data['answer']) ans = data['answer']
hint_no = str(data['hint']) hint_pk = str(data['hint'])
answer = self.previous_answers[ans_no][0] pk_list = json.loads(data['pk_list'])
# We use temp_dict because we need to do a direct write for the database to update. # We use temp_dict because we need to do a direct write for the database to update.
temp_dict = self.hints temp_dict = self.hints
temp_dict[answer][hint_no][1] += 1 temp_dict[ans][hint_pk][1] += 1
self.hints = temp_dict self.hints = temp_dict
# Don't let the user vote again! # Don't let the user vote again!
self.user_voted = True self.user_voted = True
# Return a list of how many votes each hint got. # Return a list of how many votes each hint got.
hint_and_votes = [] hint_and_votes = []
for hint_no in self.previous_answers[ans_no][1]: for vote_pk in pk_list:
if hint_no is None: hint_and_votes.append(temp_dict[ans][vote_pk])
continue
hint_and_votes.append(temp_dict[answer][str(hint_no)])
hint_and_votes.sort(key=lambda pair: pair[1], reverse=True)
# Reset self.previous_answers. # Reset self.previous_answers.
self.previous_answers = [] self.previous_answers = []
return {'hint_and_votes': hint_and_votes} return {'hint_and_votes': hint_and_votes}
...@@ -266,7 +265,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule): ...@@ -266,7 +265,7 @@ class CrowdsourceHinterModule(CrowdsourceHinterFields, XModule):
""" """
# Do html escaping. Perhaps in the future do profanity filtering, etc. as well. # Do html escaping. Perhaps in the future do profanity filtering, etc. as well.
hint = escape(data['hint']) hint = escape(data['hint'])
answer = self.previous_answers[int(data['answer'])][0] answer = data['answer']
# Only allow a student to vote or submit a hint once. # Only allow a student to vote or submit a hint once.
if self.user_voted: if self.user_voted:
return {'message': 'Sorry, but you have already voted!'} return {'message': 'Sorry, but you have already voted!'}
......
...@@ -28,6 +28,10 @@ class @Hinter ...@@ -28,6 +28,10 @@ class @Hinter
$: (selector) -> $: (selector) ->
$(selector, @el) $(selector, @el)
jq_escape: (string) =>
# Escape a string for jquery selector use.
return string.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&')
bind: => bind: =>
window.update_schematics() window.update_schematics()
@$('input.vote').click @vote @$('input.vote').click @vote
...@@ -44,14 +48,17 @@ class @Hinter ...@@ -44,14 +48,17 @@ class @Hinter
vote: (eventObj) => vote: (eventObj) =>
target = @$(eventObj.currentTarget) target = @$(eventObj.currentTarget)
post_json = {'answer': target.data('answer'), 'hint': target.data('hintno')} parent_div_selector = '#previous-answer-' + @jq_escape(target.attr('data-answer'))
all_pks = @$(parent_div_selector).attr('data-all-pks')
console.debug(all_pks)
post_json = {'answer': target.attr('data-answer'), 'hint': target.data('hintno'), 'pk_list': all_pks}
$.postWithPrefix "#{@url}/vote", post_json, (response) => $.postWithPrefix "#{@url}/vote", post_json, (response) =>
@render(response.contents) @render(response.contents)
submit_hint: (eventObj) => submit_hint: (eventObj) =>
target = @$(eventObj.currentTarget) target = @$(eventObj.currentTarget)
textarea_id = '#custom-hint-' + target.data('answer') textarea_id = '#custom-hint-' + @jq_escape(target.attr('data-answer'))
post_json = {'answer': target.data('answer'), 'hint': @$(textarea_id).val()} post_json = {'answer': target.attr('data-answer'), 'hint': @$(textarea_id).val()}
$.postWithPrefix "#{@url}/submit_hint",post_json, (response) => $.postWithPrefix "#{@url}/submit_hint",post_json, (response) =>
@render(response.contents) @render(response.contents)
......
...@@ -25,21 +25,25 @@ ...@@ -25,21 +25,25 @@
<div id="answer-tabs"> <div id="answer-tabs">
<ul> <ul>
% for index, answer in index_to_answer.items(): % for answer in answer_to_hints:
<li><a href="#previous-answer-${index}"> ${answer} </a></li> <li><a href="#previous-answer-${answer}"> ${answer} </a></li>
% endfor % endfor
</ul> </ul>
% for index, answer in index_to_answer.items(): % for answer, pk_dict in answer_to_hints.items():
<div class = "previous-answer" id="previous-answer-${index}"> <%
import json
all_pks = json.dumps(pk_dict.keys())
%>
<div class = "previous-answer" id="previous-answer-${answer}" data-all-pks='${all_pks}'>
<div class = "hint-inner-container"> <div class = "hint-inner-container">
% if index in index_to_hints and len(index_to_hints[index]) > 0: % if len(pk_dict) > 0:
<p> <p>
Which hint would be most effective to show a student who also got ${answer}? Which hint would be most effective to show a student who also got ${answer}?
</p> </p>
% for hint_text, hint_pk in index_to_hints[index]: % for hint_pk, hint_text in pk_dict.items():
<p> <p>
<input class="vote" data-answer="${index}" data-hintno="${hint_pk}" type="button" value="Vote"/> <input class="vote" data-answer="${answer}" data-hintno="${hint_pk}" type="button" value="Vote">
${hint_text} ${hint_text}
</p> </p>
% endfor % endfor
...@@ -50,12 +54,12 @@ ...@@ -50,12 +54,12 @@
<p> <p>
What hint would you give a student who made the same mistake you did? Please don't give away the answer. What hint would you give a student who made the same mistake you did? Please don't give away the answer.
</p> </p>
<textarea cols="50" class="custom-hint" id="custom-hint-${index}"> <textarea cols="50" class="custom-hint" id="custom-hint-${answer}">
What would you say to help someone who got this wrong answer? What would you say to help someone who got this wrong answer?
(Don't give away the answer, please.) (Don't give away the answer, please.)
</textarea> </textarea>
<br/><br/> <br/><br/>
<input class="submit-hint" data-answer="${index}" type="button" value="submit"> <input class="submit-hint" data-answer="${answer}" type="button" value="submit">
</div></div> </div></div>
% endfor % endfor
</div> </div>
......
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