Commit a0c81873 by Sola

pulled remote

parents 02c5d095 deb1d23b
...@@ -21,17 +21,18 @@ class CrowdXBlock(XBlock): ...@@ -21,17 +21,18 @@ class CrowdXBlock(XBlock):
""" """
# Database of hints. hints are stored as such: {"incorrect_answer": {"hint": rating}}. each key (incorrect answer) # Database of hints. hints are stored as such: {"incorrect_answer": {"hint": rating}}. each key (incorrect answer)
# has a corresponding dictionary (in which hints are keys and the hints' ratings are the values). # has a corresponding dictionary (in which hints are keys and the hints' ratings are the values).
hint_database = Dict(default={'answer': {'hint': 5}}, scope=Scope.user_state_summary) # Temporary values have been added into the hint_database for testing purposes (will be removed in the future)
hint_database = Dict(default={'answer': {'hint': 1}}, scope=Scope.user_state_summary)
# This is a dictionary of hints that will be used to determine what hints to show a student. # This is a dictionary of hints that will be used to determine what hints to show a student.
# flagged hints are not included in this dictionary of hints # flagged hints are not included in this dictionary of hints
HintsToUse = Dict({}, scope=Scope.user_state) HintsToUse = Dict(}, scope=Scope.user_state)
# This is a list of incorrect answer submissions made by the student. this list is mostly used for # 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. # feedback, to find which incorrect answer's hint a student voted on.
WrongAnswers = List([], scope=Scope.user_state) WrongAnswers = List([], scope=Scope.user_state)
# A dictionary of default hints. default hints will be shown to students when there are no matches with the # 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 # student's incorrect answer within the hint_database dictionary (i.e. no students have made hints for the
# particular incorrect answer) # particular incorrect answer)
DefaultHints = Dict(default={'default_hint': 0}, scope=Scope.content) DefaultHints = Dict(default={}, scope=Scope.content)
# List of which hints from the HintsToUse dictionary have been shown to the student # List of which hints from the HintsToUse dictionary 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 # this list is used to prevent the same hint from showing up to a student (if they submit the same incorrect answers
# multiple times) # multiple times)
...@@ -117,7 +118,7 @@ class CrowdXBlock(XBlock): ...@@ -117,7 +118,7 @@ class CrowdXBlock(XBlock):
answer = str(data["submittedanswer"]) answer = str(data["submittedanswer"])
answer = answer.lower() # for analyzing the student input string I make it lower case. answer = answer.lower() # for analyzing the student input string I make it lower case.
found_equal_sign = 0 found_equal_sign = 0
remaining_hints = int(0) hints_used = 0
# the string returned by the event problem_graded is very messy and is different # the string returned by the event problem_graded is very messy and is different
# for each problem, but after all of the numbers/letters there is an equal sign, after which the # for each problem, but after all of the numbers/letters there is an equal sign, after which the
# student's input is shown. I use the function below to remove everything before the first equal # student's input is shown. I use the function below to remove everything before the first equal
...@@ -127,33 +128,30 @@ class CrowdXBlock(XBlock): ...@@ -127,33 +128,30 @@ class CrowdXBlock(XBlock):
found_equal_sign = 1 found_equal_sign = 1
eqplace = answer.index("=") + 1 eqplace = answer.index("=") + 1
answer = answer[eqplace:] answer = answer[eqplace:]
remaining_hints = int(self.find_hints(answer)) self.find_hints(answer)
if remaining_hints != int(0): # add hints to the self.HintsToUse dictionary. Will likely be replaced
if max(self.hint_database[str(answer)].iteritems(), key=operator.itemgetter(1))[0] not in self.Used: # soon by simply looking within the self.hint_database for hints.
if str(answer) not in self.hint_database:
# add incorrect answer to hint_database if no precedent exists
self.hint_database[str(answer)] = {}
self.HintsToUse.clear()
self.HintsToUse.update(self.DefaultHints)
if max(self.HintsToUse.iteritems(), key=operator.itemgetter(1))[0] not in self.Used:
# choose highest rated hint for the incorrect answer # choose highest rated hint for the incorrect answer
if max(self.hint_database[str(answer)].iteritems(), key=operator.itemgetter(1))[0] not in self.Flagged.keys(): if max(self.HintsToUse.iteritems(), key=operator.itemgetter(1))[0] not in self.Flagged.keys():
self.Used.append(max(self.hint_database[str(answer)].iteritems(), key=operator.itemgetter(1))[0]) self.Used.append(max(self.HintsToUse.iteritems(), key=operator.itemgetter(1))[0])
return {'HintsToUse': max(self.hint_database[str(answer)].iteritems(), key=operator.itemgetter(1))[0]} return {'HintsToUse': max(self.HintsToUse.iteritems(), key=operator.itemgetter(1))[0]}
else: else:
# choose another random hint for the answer. # choose another random hint for the answer.
temporary_hints_list = [] not_used = random.choice(self.HintsToUse.keys())
for hint_keys in self.hint_database[str(answer)]: for used_hints in self.Used:
if hint_keys not in self.Used and hint_keys not in self.Flagged: if used_hints in self.HintsToUse.keys():
temporary_hints_list.append(str(hint_keys)) hints_used += 1
not_used = random.choice(temporary_hints_list) if str(len(self.HintsToUse)) > str(hints_used):
else: while not_used in self.Used:
if max(self.DefaultHints.iteritems(), key=operator.itemgetter(1))[0] not in self.Used: # loop through hints to ensure no hint is shown twice
# choose highest rated hint for the incorrect answer while not_used in self.Flagged.keys():
if max(self.DefaultHints.iteritems(), key=operator.itemgetter(1))[0] not in self.Flagged.keys(): not_used = random.choice(self.HintsToUse.keys())
self.Used.append(max(self.DefaultHints.iteritems(), key=operator.itemgetter(1))[0])
return {'HintsToUse': max(self.DefaultHints.iteritems(), key=operator.itemgetter(1))[0]}
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)
else: else:
# if there are no more hints left in either the database or defaults # if there are no more hints left in either the database or defaults
self.Used.append(str("There are no hints for" + " " + answer)) self.Used.append(str("There are no hints for" + " " + answer))
...@@ -169,25 +167,28 @@ class CrowdXBlock(XBlock): ...@@ -169,25 +167,28 @@ class CrowdXBlock(XBlock):
Args: Args:
answer: This is equal to answer from get_hint, the answer the student submitted answer: This is equal to answer from get_hint, the answer the student submitted
""" """
hints_exist = 0
isflagged = [] isflagged = []
isused = 0
self.WrongAnswers.append(str(answer)) # add the student's input to the temporary list, for later use self.WrongAnswers.append(str(answer)) # add the student's input to the temporary list, for later use
# add hints to the self.HintsToUse dictionary. Will likely be replaced for answer_keys in self.hint_database:
# soon by simply looking within the self.hint_database for hints. # look through answer keys to find a match with the student's answer, and add
if str(answer) not in self.hint_database: # the hints that exist for said answer into the HintsToUse dict.
# add incorrect answer to hint_database if no precedent exists hints = str(self.hint_database[str(answer_keys)])
self.hint_database[str(answer)] = {} if str(answer_keys) == str(answer):
return str(0) self.HintsToUse.clear()
for hint_keys in self.hint_database[str(answer)]: self.HintsToUse.update(ast.literal_eval(hints))
for hint_keys in self.HintsToUse:
for flagged_keys in self.Flagged: for flagged_keys in self.Flagged:
if str(hint_keys) == str(flagged_keys): if str(hint_keys) == str(flagged_keys):
isflagged.append(hint_keys) isflagged.append(hint_keys)
if str(hint_keys) in self.Used: for flagged_keys in isflagged:
isused += 1 # remove flagged keys from the HintsToUse
if (len(self.hint_database[str(answer)]) - len(isflagged) - isused) > 0: del self.HintsToUse[flagged_keys]
return str(1) for answer_keys in self.HintsToUse:
else: if answer_keys not in self.Used:
return str(0) hints_exist = 1
if hints_exist == 0:
self.HintsToUse.update(self.DefaultHints)
@XBlock.json_handler @XBlock.json_handler
def get_feedback(self, data, suffix=''): def get_feedback(self, data, suffix=''):
...@@ -236,8 +237,6 @@ class CrowdXBlock(XBlock): ...@@ -236,8 +237,6 @@ class CrowdXBlock(XBlock):
else: else:
self.no_hints(index) self.no_hints(index)
feedback_data[str("There are no hints for" + " " + str(self.WrongAnswers[index]))] = str(self.WrongAnswers[index]) feedback_data[str("There are no hints for" + " " + str(self.WrongAnswers[index]))] = str(self.WrongAnswers[index])
self.Used = []
self.WrongAnswers = []
return feedback_data return feedback_data
def no_hints(self, index): def no_hints(self, index):
...@@ -258,8 +257,8 @@ class CrowdXBlock(XBlock): ...@@ -258,8 +257,8 @@ class CrowdXBlock(XBlock):
Hint ratings in hint_database are updated and the resulting hint rating (or flagged status) is returned to JS. Hint ratings in hint_database are updated and the resulting hint rating (or flagged status) is returned to JS.
Args: Args:
data['student_answer']: The incorrect answer that corresponds to the hint that is being voted on data['answer']: The incorrect answer that corresponds to the hint that is being voted on
data['used_hint']: The hint that is being voted on data['value']: The hint that is being voted on
data['student_rating']: The rating chosen by the student. The value is -1, 1, or 0. data['student_rating']: The rating chosen by the student. The value is -1, 1, or 0.
Returns: Returns:
...@@ -267,30 +266,29 @@ class CrowdXBlock(XBlock): ...@@ -267,30 +266,29 @@ class CrowdXBlock(XBlock):
If the hint has already been voted on, 'You have already voted on this hint!' If the hint has already been voted on, 'You have already voted on this hint!'
will be returned to JS. will be returned to JS.
""" """
original_data = data['student_answer'] # original strings are saved to return later original_data = data['answer'] # original strings are saved to return later
answer_data = data['student_answer'] answer_data = data['answer']
# answer_data is manipulated to remove symbols to prevent errors that # answer_data is manipulated to remove symbols to prevent errors that
# might arise due to certain symbols. I don't think I have this fully working but am not sure. # might arise due to certain symbols. I don't think I have this fully working but am not sure.
data_rating = data['student_rating'] data_rating = data['student_rating']
data_hint = data['used_hint'] data_value = data['value']
answer_data = self.remove_symbols(answer_data) answer_data = self.remove_symbols(answer_data)
if str(data['student_rating']) == str(0): if str(data['student_rating']) == str(0):
# if student flagged hint # if student flagged hint
self.hint_flagged(data['used_hint'], answer_data) self.hint_flagged(data['value'], answer_data)
return {"rating": 'thiswasflagged', 'origdata': original_data} return {"rating": 'thiswasflagged', 'origdata': original_data}
print(str(self.Voted))
if str(answer_data) not in self.Voted: if str(answer_data) not in self.Voted:
self.Voted.append(str(answer_data)) # add data to Voted to prevent multiple votes self.Voted.append(str(answer_data)) # add data to Voted to prevent multiple votes
rating = self.change_rating(data_hint, int(data_rating), answer_data) # change hint rating rating = self.change_rating(data_value, int(data_rating), answer_data) # change hint rating
if str(rating) == str(0): if str(rating) == str(0):
# if the rating is "0", return "zzeerroo" instead. "0" showed up as "null" in JS # if the rating is "0", return "zzeerroo" instead. "0" showed up as "null" in JS
return {"rating": str('zzeerroo'), 'used_hint': data_hint} return {"rating": str('zzeerroo'), 'origdata': original_data}
else: else:
return {"rating": str(rating), 'used_hint': data_hint} return {"rating": str(rating), 'origdata': original_data}
else: else:
return {"rating": str('You have already voted on this hint!'), 'used_hint': data_hint} return {"rating": str('You have already voted on this hint!'), 'origdata': original_data}
def hint_flagged(self, data_hint, answer_data): def hint_flagged(self, data_value, answer_data):
""" """
This is used to add a hint to the self.flagged dictionary. When a hint is returned with the rating This is used to add a hint to the self.flagged dictionary. When a hint is returned with the rating
of 0, it is considered to be flagged. of 0, it is considered to be flagged.
......
...@@ -22,14 +22,14 @@ class CrowdXBlock(XBlock): ...@@ -22,14 +22,14 @@ class CrowdXBlock(XBlock):
# Database of hints. hints are stored as such: {"incorrect_answer": {"hint": rating}}. each key (incorrect answer) # Database of hints. hints are stored as such: {"incorrect_answer": {"hint": rating}}. each key (incorrect answer)
# has a corresponding dictionary (in which hints are keys and the hints' ratings are the values). # has a corresponding dictionary (in which hints are keys and the hints' ratings are the values).
<<<<<<< HEAD <<<<<<< HEAD
hint_database = Dict(default={'answer': {'hint': 5}}, scope=Scope.user_state_summary)
=======
# Temporary values have been added into the hint_database for testing purposes (will be removed in the future) # Temporary values have been added into the hint_database for testing purposes (will be removed in the future)
hint_database = Dict(default={'answer': {'hint': 1}}, scope=Scope.user_state_summary) hint_database = Dict(default={'answer': {'hint': 1}}, scope=Scope.user_state_summary)
======= >>>>>>> deb1d23b2088dbdb6e497cfeeca7cf537eb9d5fd
hint_database = Dict(default={'answer': {'hint': 5}}, scope=Scope.user_state_summary)
>>>>>>> master
# This is a dictionary of hints that will be used to determine what hints to show a student. # This is a dictionary of hints that will be used to determine what hints to show a student.
# flagged hints are not included in this dictionary of hints # flagged hints are not included in this dictionary of hints
HintsToUse = Dict({}, scope=Scope.user_state) HintsToUse = Dict(}, scope=Scope.user_state)
# This is a list of incorrect answer submissions made by the student. this list is mostly used for # 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. # feedback, to find which incorrect answer's hint a student voted on.
WrongAnswers = List([], scope=Scope.user_state) WrongAnswers = List([], scope=Scope.user_state)
...@@ -83,6 +83,28 @@ class CrowdXBlock(XBlock): ...@@ -83,6 +83,28 @@ class CrowdXBlock(XBlock):
return data.decode("utf8") return data.decode("utf8")
@XBlock.json_handler @XBlock.json_handler
def clear_temp(self, data, suffix=''):
""" TODO: Remove or fix.
This clears all temprorary lists/dictionaries. This may not be relevant any longer
but is intended to prevent hints from messing up when changing between units within
a section.
"""
remove_list = []
# a list is used to systematically remove all key/values from a dictionary.
# there may be a much cleaner way to do this but I could not find one very easily.
# This whole function will probably be removed if scopes are corrected later.
for used_hints in self.Used:
remove_list.append(used_hints)
for items in remove_list:
self.Used.remove(items)
remove_list = []
for wrong_answers in self.WrongAnswers:
remove_list.append(wrong_answers)
for items in remove_list:
self.WrongAnswers.remove(items)
self.HintsToUse.clear()
@XBlock.json_handler
def get_hint(self, data, suffix=''): def get_hint(self, data, suffix=''):
""" """
Returns hints to students. Hints are placed into the HintsToUse dictionary if it is found that they Returns hints to students. Hints are placed into the HintsToUse dictionary if it is found that they
...@@ -279,35 +301,45 @@ class CrowdXBlock(XBlock): ...@@ -279,35 +301,45 @@ class CrowdXBlock(XBlock):
of 0, it is considered to be flagged. of 0, it is considered to be flagged.
Args: Args:
data_hint: This is equal to the data['used_hint'] in self.rate_hint data_value: This is equal to the data['value'] in self.rate_hint
answer_data: This is equal to the data['student_answer'] in self.rate_hint answer_data: This is equal to the data['answer'] in self.rate_hint
""" """
for answer_keys in self.hint_database: for answer_keys in self.hint_database:
if answer_keys == data_hint: if answer_keys == data_value:
for hint_keys in self.hint_database[str(answer_keys)]: for hint_keys in self.hint_database[str(answer_keys)]:
if str(hint_keys) == answer_data: if str(hint_keys) == answer_data:
self.Flagged[str(hint_keys)] = str(answer_keys) self.Flagged[str(hint_keys)] = str(answer_keys)
def change_rating(self, data_hint, data_rating, answer_data): def change_rating(self, data_value, data_rating, answer_data):
""" """
This function is used to change the rating of a hint when it is voted on. This function is used to change the rating of a hint when it is voted on.
Initiated by rate_hint. The temporary_dictionary is manipulated to be used Initiated by rate_hint. The temporary_dictionary is manipulated to be used
in self.rate_hint in self.rate_hint
Args: Args:
data_hint: This is equal to the data['used_hint'] in self.rate_hint data_value: This is equal to the data['value'] in self.rate_hint
data_rating: This is equal to the data['student_rating'] in self.rate_hint data_rating: This is equal to the data['student_rating'] in self.rate_hint
answer_data: This is equal to the data['student_answer'] in self.rate_hint answer_data: This is equal to the data['answer'] in self.rate_hint
Returns: Returns:
The rating associated with the hint is returned. This rating is identical The rating associated with the hint is returned. This rating is identical
to what would be found under self.hint_database[answer_string[hint_string]] to what would be found under self.hint_database[answer_string[hint_string]]
""" """
temporary_dictionary = str(self.hint_database[str(answer_data)]) for hint_keys in self.Used:
if str(hint_keys) == str(answer_data):
# use index of hint used to find the hint within self.hint_database
answer = self.Used.index(str(answer_data))
for answer_keys in self.hint_database:
temporary_dictionary = str(self.hint_database[str(answer_keys)])
temporary_dictionary = (ast.literal_eval(temporary_dictionary)) temporary_dictionary = (ast.literal_eval(temporary_dictionary))
temporary_dictionary[str(data_hint)] += int(data_rating) # if I remember correctly, changing the rating values in self.hint_database
self.hint_database[str(answer_data)] = temporary_dictionary # didn't work correctly for some reason, so instead I manipulated this
return str(temporary_dictionary[str(data_hint)]) # temporary dictionary and then set self.hint_database to equal it.
# probably due to scope error (which also is affecting the studio interactions)
if str(answer_keys) == str(self.WrongAnswers[answer]):
temporary_dictionary[self.Used[int(answer)]] += int(data_rating)
self.hint_database[str(answer_keys)] = temporary_dictionary
return str(temporary_dictionary[self.Used[int(answer)]])
def remove_symbols(self, answer_data): def remove_symbols(self, answer_data):
""" """
...@@ -359,9 +391,9 @@ class CrowdXBlock(XBlock): ...@@ -359,9 +391,9 @@ class CrowdXBlock(XBlock):
data['answer']: This is the incorrect answer for which the student is submitting a new hint. data['answer']: This is the incorrect answer for which the student is submitting a new hint.
""" """
submission = data['submission'].replace('ddeecciimmaallppooiinntt', '.') submission = data['submission'].replace('ddeecciimmaallppooiinntt', '.')
answer = data['answer'].replace('ddeecciimmaallppooiinntt', '.') hint_id = data['answer'].replace('ddeecciimmaallppooiinntt', '.')
for answer_keys in self.hint_database: for answer_keys in self.hint_database:
if str(answer_keys) == str(answer): if str(answer_keys) == self.WrongAnswers[self.Used.index(hint_id)]:
# find the answer for which a hint is being submitted # find the answer for which a hint is being submitted
if str(submission) not in self.hint_database[str(answer_keys)]: if str(submission) not in self.hint_database[str(answer_keys)]:
temporary_dictionary = str(self.hint_database[str(answer_keys)]) temporary_dictionary = str(self.hint_database[str(answer_keys)])
...@@ -374,15 +406,17 @@ class CrowdXBlock(XBlock): ...@@ -374,15 +406,17 @@ class CrowdXBlock(XBlock):
return return
else: else:
# if the hint exists already, simply upvote the previously entered hint # if the hint exists already, simply upvote the previously entered hint
if str(submission) in self.DefaultHints: hint_index = self.Used.index(submission)
self.DefaultHints[str(submission)] += int(1) for default_hints in self.DefaultHints:
if default_hints == self.Used[int(hint_index)]:
self.DefaultHints[str(default_hints)] += int(1)
return return
else: for answer_keys in self.hint_database:
temporary_dictionary = str(self.hint_database[str(answer)]) temporary_dictionary = str(self.hint_database[str(answer_keys)])
temporary_dictionary = (ast.literal_eval(temporary_dictionary)) temporary_dictionary = (ast.literal_eval(temporary_dictionary))
temporary_dictionary[str(submission)] += int(data['rating']) if str(answer_keys) == str(self.WrongAnswers[int(hint_index)]):
self.hint_database[str(answer)] = temporary_dictionary temporary_dictionary[self.Used[int(hint_index)]] += int(data['rating'])
return self.hint_database[str(answer_keys)] = temporary_dictionary
@XBlock.json_handler @XBlock.json_handler
def studiodata(self, data, suffix=''): def studiodata(self, data, suffix=''):
......
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