diff --git a/common/lib/capa/capa/chem/chemtools.py b/common/lib/capa/capa/chem/chemtools.py index 41bf95b055..132bde17b4 100644 --- a/common/lib/capa/capa/chem/chemtools.py +++ b/common/lib/capa/capa/chem/chemtools.py @@ -1,8 +1,9 @@ from collections import OrderedDict +import json def vsepr_parse_user_answer(user_input): - d = OrderedDict(eval(user_input)) + d = OrderedDict(json.loads(user_input)) d['atoms'] = OrderedDict(sorted(d['atoms'].items())) return d @@ -10,16 +11,42 @@ def vsepr_parse_user_answer(user_input): def vsepr_build_correct_answer(geometry, atoms): correct_answer = OrderedDict() correct_answer['geometry'] = geometry - correct_answer['atoms'] = OrderedDict(atoms) + correct_answer['atoms'] = OrderedDict(sorted(atoms.items())) return correct_answer -def vsepr_grade(user_input, correct_answer): - print user_input, type(user_input) - print correct_answer, type(correct_answer) +def vsepr_grade(user_input, correct_answer, ignore_p_order=False, ignore_a_order=False, ignore_e_order=False): + """ Flags ignore_(a,p,e)_order are for checking order in axial, perepherial or equatorial positions + """ + # print user_input, type(user_input) + # print correct_answer, type(correct_answer) if user_input['geometry'] != correct_answer['geometry']: return False - if user_input['atoms'].values() != correct_answer['atoms'].values(): - return False - return True + # not order-aware comparisons + for ignore in [(ignore_p_order, 'p'), (ignore_e_order, 'e'), (ignore_a_order, 'a')]: + if ignore[0]: + # collecting atoms: + a_user = [v for k, v in user_input['atoms'].items() if k.startswith(ignore[1])] + a_correct = [v for k, v in correct_answer['atoms'].items() if k.startswith(ignore[1])] + # print ignore[0], ignore[1], a_user, a_correct + if len(a_user) != len(a_correct): + return False + if sorted(a_user) != sorted(a_correct): + return False + + # order-aware comparisons + for ignore in [(ignore_p_order, 'p'), (ignore_e_order, 'e'), (ignore_a_order, 'a')]: + if not ignore[0]: + # collecting atoms: + a_user = [v for k, v in user_input['atoms'].items() if k.startswith(ignore[1])] + a_correct = [v for k, v in correct_answer['atoms'].items() if k.startswith(ignore[1])] + # print '2nd', ignore[0], ignore[1], a_user, a_correct + if len(a_user) != len(a_correct): + return False + if len(a_correct) == 0: + continue + if a_user != a_correct: + return False + + return True