<commit_before>from collections import OrderedDict
import json
import unittest


def vsepr_parse_user_answer(user_input):
    d = OrderedDict(json.loads(user_input))
    d['atoms'] = OrderedDict(sorted(d['atoms'].items()))
    return d


def vsepr_build_correct_answer(geometry, atoms):
    correct_answer = OrderedDict()
    correct_answer['geometry'] = geometry
    correct_answer['atoms'] = OrderedDict(sorted(atoms.items()))
    return correct_answer


def vsepr_grade(user_input, correct_answer, convert_to_perepherial=False):
    """
        Allowed cases:
            c0, a, e
            c0, p
    """
    # 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']['c0'] != correct_answer['atoms']['c0']:
        return False

    if convert_to_perepherial:
        # convert user_input from (a,e,e1,e2) to (p)
        # correct_answer must be set in (p) using this flag
        user_input['atoms'] = {'p' + str(i): v for i, v in enumerate(user_input['atoms'].values())}

    for ea_position in ['p', 'a', 'e', 'e1', 'e2']:
        # collecting atoms:
        a_user = [v for k, v in user_input['atoms'].items() if k.startswith(ea_position)]
        a_correct = [v for k, v in correct_answer['atoms'].items() if k.startswith(ea_position)]
        # print a_user, a_correct
        if len(a_user) != len(a_correct):
            return False
        if sorted(a_user) != sorted(a_correct):
            return False

    return True


class Test_Grade(unittest.TestCase):
    ''' test grade function '''

    def test_incorrect_geometry(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX3E0","atoms":{"c0":"B","p0":"F","p1":"B","p2":"F"}}')
        self.assertFalse(vsepr_grade(user_answer, correct_answer))

    def test_incorrect_positions(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX4E0","atoms":{"c0":"B","p0":"F","p1":"B","p2":"F"}}')
        self.assertFalse(vsepr_grade(user_answer, correct_answer))

    def test_correct_answer(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX4E0","atoms":{"c0":"N","p0":"H","p1":"(ep)","p2":"H", "p3":"H"}}')
        self.assertTrue(vsepr_grade(user_answer, correct_answer))<commit_msg>changed syntax to support e1,e2 in AX6 and add convert_to_p behavior<commit_after>import json
import unittest
import itertools

def vsepr_parse_user_answer(user_input):
    return json.loads(user_input)


def vsepr_build_correct_answer(geometry, atoms):
    return {'geometry': geometry, 'atoms': atoms}


def vsepr_grade(user_input, correct_answer, convert_to_perepherial=False):
    """
        Allowed cases:
            c0, a, e
            c0, p
    """
    # import ipdb; ipdb.set_trace()
    # 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']['c0'] != correct_answer['atoms']['c0']:
        return False

    if convert_to_perepherial:
        # convert user_input from (a,e,e1,e2) to (p)
        # correct_answer must be set in (p) using this flag
        c0 = user_input['atoms'].pop('c0')
        user_input['atoms'] = {'p' + str(i): v for i, v in enumerate(user_input['atoms'].values())}
        user_input['atoms']['c0'] = c0

    # special case for AX6
    if 'e10' in correct_answer['atoms']:  # need check e1x, e2x symmetry for AX6..
        a_user = {}
        a_correct = {}
        for ea_position in ['a', 'e1', 'e2']:  # collecting positions:
            a_user[ea_position] = [v for k, v in user_input['atoms'].items() if k.startswith(ea_position)]
            a_correct[ea_position] = [v for k, v in correct_answer['atoms'].items() if k.startswith(ea_position)]

        correct = [sorted(a_correct['a'])] + [sorted(a_correct['e1'])] + [sorted(a_correct['e2'])]
        for permutation in itertools.permutations(['a', 'e1', 'e2']):
            if correct == [sorted(a_user[permutation[0]])] + [sorted(a_user[permutation[1]])] + [sorted(a_user[permutation[2]])]:
                return True
        return False

    else:  # no need to checl e1x,e2x symmetry - convert them to ex
        if 'e10' in user_input['atoms']:  # e1x exists, it is AX6.. case
            e_index = 0
            for k, v in user_input['atoms'].items():
                if len(k) == 3:  # e1x
                    del user_input['atoms'][k]
                    user_input['atoms']['e' + str(e_index)] = v
                    e_index += 1

        # common case
        for ea_position in ['p', 'a', 'e']:
            # collecting atoms:
            a_user = [v for k, v in user_input['atoms'].items() if k.startswith(ea_position)]
            a_correct = [v for k, v in correct_answer['atoms'].items() if k.startswith(ea_position)]
            # print a_user, a_correct
            if len(a_user) != len(a_correct):
                return False
            if sorted(a_user) != sorted(a_correct):
                return False

        return True


class Test_Grade(unittest.TestCase):
    ''' test grade function '''

    def test_incorrect_geometry(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX3E0","atoms":{"c0":"B","p0":"F","p1":"B","p2":"F"}}')
        self.assertFalse(vsepr_grade(user_answer, correct_answer))

    def test_incorrect_positions(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX4E0","atoms":{"c0":"B","p0":"F","p1":"B","p2":"F"}}')
        self.assertFalse(vsepr_grade(user_answer, correct_answer))

    def test_correct_answer(self):
        correct_answer = vsepr_build_correct_answer(geometry="AX4E0", atoms={"c0": "N", "p0": "H", "p1": "(ep)", "p2": "H", "p3": "H"})
        user_answer = vsepr_parse_user_answer(u'{"geometry":"AX4E0","atoms":{"c0":"N","p0":"H","p1":"(ep)","p2":"H", "p3":"H"}}')
        self.assertTrue(vsepr_grade(user_answer, correct_answer))
{'fraction_non_alphanumeric': 0.17388706304152973, 'fraction_numerical': 0.01882282641171198, 'mean_word_length': 3.5023537323470073, 'pattern_counts': {'":': 68, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2256650', 'n_tokens_mistral': 2416, 'n_tokens_neox': 2365, 'n_words': 474}