Commit c602fdbf by solashirai Committed by Piotr Mitros

changes to flow of hinting/feedback mostly in place

parent e22d313f
......@@ -8,7 +8,7 @@ import pkg_resources
import random
from xblock.core import XBlock
from xblock.fields import Scope, Dict, List
from xblock.fields import Scope, Dict, List, Boolean
from xblock.fragment import Fragment
log = logging.getLogger(__name__)
......@@ -26,13 +26,10 @@ class CrowdsourceHinter(XBlock):
# This is a list of incorrect answer submissions made by the student. this list is mostly used for
# feedback, to find which incorrect answer's hint a student voted on.
WrongAnswers = List([], scope=Scope.user_state)
# This list will keep track of what student answers didn't have a hint to show them. This list is used for
# the feedback stage, where students will be prompted and strongly encouraged to provide a hint for such hintless answers.
NoHintsFor = List([], scope=Scope.user_state)
# A dictionary of default hints. default hints will be shown to students when there are no matches with the
# student's incorrect answer within the hint_database dictionary (i.e. no students have made hints for the
# particular incorrect answer)
DefaultHints = Dict(default={'default_hint': 0}, scope=Scope.content)
DefaultHints = Dict(default={}, scope=Scope.content)
# List of which hints have been shown to the student
# this list is used to prevent the same hint from showing up to a student (if they submit the same incorrect answers
# multiple times)
......@@ -44,12 +41,11 @@ class CrowdsourceHinter(XBlock):
# This is a dictionary of hints that have been flagged. the values represent the incorrect answer submission, and the
# keys are the hints the corresponding hints. hints with identical text for differing answers will all not show up for the
# student.
Flagged = Dict(default={"This is a hint that should be flagged": "answer2"}, scope=Scope.user_state_summary)
Flagged = Dict(default={}, scope=Scope.user_state_summary)
# This string determines whether or not to show only the best (highest rated) hint to a student
# When set to 'True' only the best hint will be shown to the student.
# Details on operation when set to 'False' are to be finalized.
# TODO: make this into a boolean instead of a dict
show_best = Dict(default={'showbest': 'True'}, scope=Scope.user_state_summary)
show_best = Boolean(default = True, scope=Scope.user_state_summary)
def student_view(self, context=None):
"""
......@@ -132,9 +128,11 @@ class CrowdsourceHinter(XBlock):
eqplace = answer.index("=") + 1
answer = answer[eqplace:]
remaining_hints = str(self.find_hints(answer))
print(answer)
print(remaining_hints)
if remaining_hints != str(0):
best_hint = max(self.hint_database[str(answer)].iteritems(), key=operator.itemgetter(1))[0]
if self.show_best['showbest'] == 'True':
if self.show_best:
# if set to show best, only the best hint will be shown. Different hitns will not be shown
# for multiple submissions/hint requests
if best_hint not in self.Flagged.keys():
......@@ -145,7 +143,6 @@ class CrowdsourceHinter(XBlock):
if best_hint not in self.Flagged.keys():
self.Used.append(best_hint)
return {'HintsToUse': best_hint, "StudentAnswer": answer}
else:
# choose another random hint for the answer.
temporary_hints_list = []
for hint_keys in self.hint_database[str(answer)]:
......@@ -153,26 +150,20 @@ class CrowdsourceHinter(XBlock):
if hint_keys not in self.Flagged:
temporary_hints_list.append(str(hint_keys))
not_used = random.choice(temporary_hints_list)
else:
if best_hint not in self.Used:
# choose highest rated hint for the incorrect answer
if best_hint not in self.Flagged.keys():
self.Used.append(best_hint)
return {'HintsToUse': best_hint, "StudentAnswer": answer}
self.Used.append(not_used)
return {'HintsToUse': not_used, "StudentAnswer": answer}
else:
temporary_hints_list = []
for hint_keys in self.DefaultHints:
if hint_keys not in self.Used:
temporary_hints_list.append(str(hint_keys))
if len(temporary_hints_list) != 0:
not_used = random.choice(temporary_hints_list)
self.Used.append(not_used)
return {'HintsToUse': not_used, "StudentAnswer": answer}
else:
# if there are no more hints left in either the database or defaults
self.Used.append(str("There are no hints for" + " " + answer))
self.NoHintsFor.append(answer)
return {'HintsToUse': "Sorry, there are no more hints for this answer.", "StudentAnswer": answer}
self.Used.append(not_used)
return {'HintsToUse': not_used, "StudentAnswer": answer}
return {'HintsToUse': "Sorry, there are no hints for this answer.", "StudentAnswer": answer}
def find_hints(self, answer):
"""
......@@ -181,6 +172,8 @@ class CrowdsourceHinter(XBlock):
Args:
answer: This is equal to answer from get_hint, the answer the student submitted
Returns 0 if no hints to show exist
"""
isflagged = []
isused = 0
......@@ -194,6 +187,7 @@ class CrowdsourceHinter(XBlock):
if hint_keys == flagged_keys:
isflagged.append(hint_keys)
if str(hint_keys) in self.Used:
if self.show_best is False:
isused += 1
if (len(self.hint_database[str(answer)]) - len(isflagged) - isused) > 0:
return str(1)
......@@ -219,10 +213,10 @@ class CrowdsourceHinter(XBlock):
if len(self.WrongAnswers) == 0:
return
else:
print(self.Used)
for index in range(0, len(self.Used)):
# each index is a hint that was used, in order of usage
for answer_keys in self.hint_database:
if str(self.Used[index]) in self.hint_database[str(answer_keys)]:
if str(self.Used[index]) in self.hint_database[self.WrongAnswers[index]]:
# add new key (hint) to feedback_data with a value (incorrect answer)
feedback_data[str(self.Used[index])] = str(self.WrongAnswers[index])
else:
......@@ -334,27 +328,9 @@ class CrowdsourceHinter(XBlock):
else:
temporary_dictionary[str(data_hint)] -= 1
self.hint_database[str(answer_data)] = temporary_dictionary
print(self.hint_database)
return str(temporary_dictionary[str(data_hint)])
def remove_symbols(self, answer_data):
"""
For removing colons and such from answers to prevent weird things from happening. Not sure if this is properly functional.
Args:
answer_data: This is equal to the data['answer'] in self.rate_hint
Returns:
answer_data: This is equal to the argument answer_data except that symbols have been
replaced by text (hopefully)
"""
answer_data = answer_data.replace('ddeecciimmaallppooiinntt', '.')
answer_data = answer_data.replace('qquueessttiioonnmmaarrkk', '?')
answer_data = answer_data.replace('ccoolloonn', ':')
answer_data = answer_data.replace('sseemmiiccoolloonn', ';')
answer_data = answer_data.replace('eeqquuaallss', '=')
answer_data = answer_data.replace('qquuoottaattiioonnmmaarrkkss', '"')
return answer_data
@XBlock.json_handler
def moderate_hint(self, data, suffix=''):
"""
......@@ -422,7 +398,7 @@ class CrowdsourceHinter(XBlock):
return [
("CrowdsourceHinter",
"""<vertical_demo>
<crowdsourcehinter/>
</vertical_demo>
"""),
<crowdsourcehinter/>
</vertical_demo>
"""),
]
......@@ -14,11 +14,7 @@
.csh_hint_value{
display: flex;
margin-left: 10px;
}
.csh_rating_data{
width: 10%;
vertical-align: middle;
flex-direction: column;
}
.crowdsourcehinter_block .csh_HintsToUse {
......@@ -37,8 +33,6 @@
}
.csh_hint_data{
justify-content: center;
width: 90%;
display: flex;
flex-direction: column;
}
......
<script type='x-tmpl/mustache' id='show_hint_feedback'>
<div class='csh_hint_value' value="{{hintvalue}}">
<div class='csh_hint_data'>
<div class="csh_hint">{{hint}}</div>
</div>
<div class='csh_rating_data'>
<div role="button" class="csh_rate_hint" data-rate="upvote" data-icon="arrow-u" aria-label="upvote">
<b>This hint was helpful</b>
</div>
//<div class ="csh_rating"> {{rating}} </div>
<div role="button" class="csh_rate_hint" data-rate="downvote" aria-label="downvote">
<b>This hint was not helpful</b>
</div>
</div>
<div class='csh_hint_data'>
<div class="csh_hint">{{hint}}</div>
<div role="button" class="csh_rate_hint" data-rate="flag" data-icon="flag" aria-label="flag">
<b>Report this hint</b>
</div>
......
......@@ -38,7 +38,7 @@ function CrowdsourceHinter(runtime, element){
}else{
$('.csh_correct', element).show();
$('.csh_correct', element).text("You're correct! Please help us improve our hints by voting on them, or submit your own hint!");
$(".csh_HintsToUse", element).text(" ");
$(".csh_hint_reveal", element).hide();
//send empty data for ajax call because not having a data field causes error
$.ajax({
type: "POST",
......@@ -58,7 +58,7 @@ function CrowdsourceHinter(runtime, element){
type: "POST",
url: runtime.handlerUrl(element, 'get_feedback'),
data: JSON.stringify({"isStaff":"false"}),
success: getStudentFeedback
success: getFeedback
});
}
}
......@@ -72,11 +72,11 @@ function CrowdsourceHinter(runtime, element){
$('.csh_HintsToUse', element).text(result.HintsToUse);
}
function showHintFeedback(hint){
function showHintFeedback(hint, student_answer){
//Append answer-specific hints for each student answer during the feedback stage.
//This appended div includes upvote/downvote/flagging buttons, the hint, and the hint's rating
$(".csh_student_answer", element).each(function(){
if ($(this).find("span").text() == result.student_answer){
if ($(this).find("span").text() == student_answer){
var html = "";
$(function(){
var data = {
......@@ -105,18 +105,14 @@ function CrowdsourceHinter(runtime, element){
function setStudentAnswers(student_answers){
//Append divs for each answer the student submitted before correctly answering the question.
//showHintFeedback appends new hints into these divs.
for(var i = 0; i < student_answers.length; i++){
var html = "";
$(function(){
var template = $('#show_answer_feedback').html();
var data = {
answer: student_answers[i]
answer: student_answers
};
html = Mustache.render(template, data);
});
$(".csh_feedback", element).append(html);
}
}
function getFeedback(result){
//Set up the student feedback stage. Each student answer and all answer-specific hints for that answer are shown
......@@ -134,17 +130,18 @@ function CrowdsourceHinter(runtime, element){
$(".csh_student_answer", element).each(function(){
if ($(this).find("span").text() == student_answer){
var html = "";
$(function(){
var template = $('#show_no_hints').html();
var data = {};
html = Mustache.render(template, data);
});
$(this).append(html);
console.log(html);
$(this).find("span").append(html);
}
});
}
//flagged hints have their corresponding answer set to "Flagged"
showHintFeedback(hint);
else{
showHintFeedback(hint, student_answer);
}
});
isShowingHintFeedback = true;
}
......@@ -188,7 +185,7 @@ function CrowdsourceHinter(runtime, element){
type: "POST",
url: runtime.handlerUrl(element, 'get_ratings'),
data: JSON.stringify({"student_answer": answerdata, "hint": newhint}),
success: showHintFeedback
success: showHintFeedback(newhint, answerdata)
});
}
});
......
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