def rubric_from_dict(rubric_dict): """Given a dict of rubric information, return the corresponding Rubric This will create the Rubric and its children if it does not exist already. Sample data (one criterion, two options):: { "prompts": [{"description": "Create a plan to deliver ora2!"}], "criteria": [ { "order_num": 0, "name": "realistic", "prompt": "Is the deadline realistic?", "options": [ { "order_num": 0, "points": 0, "name": "No", "explanation": "We need more time!" }, { "order_num": 1, "points": 2, "name": "Yes", "explanation": "We got this." }, ] } ] } """ rubric_dict = deepcopy(rubric_dict) # Calculate the hash based on the rubric content... content_hash = Rubric.content_hash_from_dict(rubric_dict) try: rubric = Rubric.objects.get(content_hash=content_hash) except Rubric.DoesNotExist: rubric_dict["content_hash"] = content_hash rubric_dict["structure_hash"] = Rubric.structure_hash_from_dict(rubric_dict) for crit_idx, criterion in enumerate(rubric_dict.get("criteria", {})): if "order_num" not in criterion: criterion["order_num"] = crit_idx for opt_idx, option in enumerate(criterion.get("options", {})): if "order_num" not in option: option["order_num"] = opt_idx rubric_serializer = RubricSerializer(data=rubric_dict) if not rubric_serializer.is_valid(): raise InvalidRubric(rubric_serializer.errors) rubric = rubric_serializer.save() return rubric
def test_structure_hash_extra_keys(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) # Same structure, add some extra keys altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['extra'] = 'extra!' altered_rubric['criteria'][0]['extra'] = 'extra!' altered_rubric['criteria'][0]['options'][0]['extra'] = 'extra!' second_hash = Rubric.structure_hash_from_dict(altered_rubric) # Expect that the two hashes are the same self.assertEqual(first_hash, second_hash)
def test_structure_hash_identical(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) # Same structure, but different text should have the same structure hash altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['prompts'] = [{"description": 'altered!'}] for criterion in altered_rubric['criteria']: criterion['prompt'] = 'altered!' for option in criterion['options']: option['explanation'] = 'altered!' second_hash = Rubric.structure_hash_from_dict(altered_rubric) # Expect that the two hashes are the same self.assertEqual(first_hash, second_hash)
def test_structure_hash_identical(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) # Same structure, but different text should have the same structure hash altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['prompts'] = [{"description": 'altered!'}] for criterion in altered_rubric['criteria']: criterion['prompt'] = 'altered!' for option in criterion['options']: option['explanation'] = 'altered!' second_hash = Rubric.structure_hash_from_dict(altered_rubric) # Expect that the two hashes are the same self.assertEqual(first_hash, second_hash)
def forwards(self, orm): """Calculate the structure hash for each rubric that doesn't have one.""" # The default value for the structure hash is an empty string # so rubrics created before the scheme migration will have # an empty string for the structure hash. for rubric in orm.Rubric.objects.filter(structure_hash="").select_related(): rubric_dict = { "criteria": [ { "name": criterion.name, "order_num": criterion.order_num, "options": [ { "name": option.name, "order_num": option.order_num, "points": option.points } for option in criterion.options.all() ] } for criterion in rubric.criteria.all() ] } # Ordinarily, we would use `orm.Rubric`, but we need access to the static method, # which South doesn't seem to provide. rubric.structure_hash = Rubric.structure_hash_from_dict(rubric_dict) rubric.save()
def rubric_from_dict(rubric_dict): """Given a dict of rubric information, return the corresponding Rubric This will create the Rubric and its children if it does not exist already. Sample data (one criterion, two options):: { "prompt": "Create a plan to deliver ora2!", "criteria": [ { "order_num": 0, "name": "realistic", "prompt": "Is the deadline realistic?", "options": [ { "order_num": 0, "points": 0, "name": "No", "explanation": "We need more time!" }, { "order_num": 1, "points": 2, "name": "Yes", "explanation": "We got this." }, ] } ] } """ rubric_dict = deepcopy(rubric_dict) # Calculate the hash based on the rubric content... content_hash = Rubric.content_hash_from_dict(rubric_dict) try: rubric = Rubric.objects.get(content_hash=content_hash) except Rubric.DoesNotExist: rubric_dict["content_hash"] = content_hash for crit_idx, criterion in enumerate(rubric_dict.get("criteria", {})): if "order_num" not in criterion: criterion["order_num"] = crit_idx for opt_idx, option in enumerate(criterion.get("options", {})): if "order_num" not in option: option["order_num"] = opt_idx rubric_serializer = RubricSerializer(data=rubric_dict) if not rubric_serializer.is_valid(): raise InvalidRubric(rubric_serializer.errors) rubric = rubric_serializer.save() return rubric
def test_structure_hash_option_points_changed(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['criteria'][0]['options'][0]['points'] = 'altered!' second_hash = Rubric.structure_hash_from_dict(altered_rubric) self.assertNotEqual(first_hash, second_hash)
def test_structure_hash_criterion_order_changed(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['criteria'][0]['order_num'] = 5 second_hash = Rubric.structure_hash_from_dict(altered_rubric) self.assertNotEqual(first_hash, second_hash)
def test_structure_hash_option_points_changed(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['criteria'][0]['options'][0]['points'] = 'altered!' second_hash = Rubric.structure_hash_from_dict(altered_rubric) self.assertNotEqual(first_hash, second_hash)
def test_structure_hash_criterion_order_changed(self): first_hash = Rubric.structure_hash_from_dict(RUBRIC) altered_rubric = copy.deepcopy(RUBRIC) altered_rubric['criteria'][0]['order_num'] = 5 second_hash = Rubric.structure_hash_from_dict(altered_rubric) self.assertNotEqual(first_hash, second_hash)