Commit 59c9ba27 by gradyward

Merge pull request #522 from edx/grady/ai-authoring

Grady/ai authoring
parents 189d18c7 58f45d79
...@@ -100,7 +100,11 @@ ...@@ -100,7 +100,11 @@
</ul> </ul>
<p class="openassessment_description" id="openassessment_step_select_description"> <p class="openassessment_description" id="openassessment_step_select_description">
{% trans "Select the steps that students must complete. All steps are optional, but every assignment must include at least one step. To change the order in which students will complete the steps, drag them into the desired order." %} {% if 'example_based_assessment' in editor_assessments_order %}
{% trans "In this assignment, you can include example based assessment, student training, peer assessment, and self assessment steps. Select the steps that you want below, and then drag them into the order that you want. If you include an example based assessment step, it must be the first step. If you include a student training step, it must precede the peer assessment step." %}
{% else %}
{% trans "In this assignment, you can include student training, peer assessment, and self assessment steps. Select the steps that you want below, and then drag them into the order that you want. If you include a student training step, it must precede the peer assessment step." %}
{% endif %}
</p> </p>
<ol id="openassessment_assessment_module_settings_editors"> <ol id="openassessment_assessment_module_settings_editors">
{% for assessment in editor_assessments_order %} {% for assessment in editor_assessments_order %}
......
...@@ -133,7 +133,6 @@ DEFAULT_ASSESSMENT_MODULES = [ ...@@ -133,7 +133,6 @@ DEFAULT_ASSESSMENT_MODULES = [
] ]
DEFAULT_EDITOR_ASSESSMENTS_ORDER = [ DEFAULT_EDITOR_ASSESSMENTS_ORDER = [
"example-based-assessment",
"student-training", "student-training",
"peer-assessment", "peer-assessment",
"self-assessment", "self-assessment",
......
...@@ -89,7 +89,8 @@ EDITOR_UPDATE_SCHEMA = Schema({ ...@@ -89,7 +89,8 @@ EDITOR_UPDATE_SCHEMA = Schema({
}) })
] ]
}) })
] ],
'examples_xml': utf8_validator,
}) })
], ],
Required('editor_assessments_order'): [ Required('editor_assessments_order'): [
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -14,7 +14,7 @@ describe("OpenAssessment edit assessment views", function() { ...@@ -14,7 +14,7 @@ describe("OpenAssessment edit assessment views", function() {
var testLoadXMLExamples = function(view) { var testLoadXMLExamples = function(view) {
var xml = "XML DEFINITIONS WOULD BE HERE"; var xml = "XML DEFINITIONS WOULD BE HERE";
view.exampleDefinitions(xml); view.exampleDefinitions(xml);
expect(view.description()).toEqual({ examples: xml }); expect(view.description()).toEqual({ examples_xml: xml });
}; };
beforeEach(function() { beforeEach(function() {
......
...@@ -95,8 +95,9 @@ OpenAssessment.StudioView.prototype = { ...@@ -95,8 +95,9 @@ OpenAssessment.StudioView.prototype = {
} }
// Initialize JQuery UI Tabs, and activates the appropriate tab. // Initialize JQuery UI Tabs, and activates the appropriate tab.
$(".openassessment_editor_content_and_tabs", this.element) $(".openassessment_editor_content_and_tabs", this.element)
.tabs() .tabs({
.tabs('option', 'active', OpenAssessment.lastOpenEditingTab); active: OpenAssessment.lastOpenEditingTab
});
}, },
/** /**
......
...@@ -390,13 +390,13 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = { ...@@ -390,13 +390,13 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = {
Example usage: Example usage:
>>> editTrainingView.description(); >>> editTrainingView.description();
{ {
examples: "XML DEFINITION HERE" examples_xml: "XML DEFINITION HERE",
} }
**/ **/
description: function() { description: function() {
return { return {
examples: this.exampleDefinitions() examples_xml: this.exampleDefinitions()
}; };
}, },
......
...@@ -287,6 +287,17 @@ ...@@ -287,6 +287,17 @@
height: 40px; height: 40px;
} }
#ai_training_examples{
margin: 5px 20px 10px 10px;
height: 300px;
width: Calc(100% - 20px);
resize: none;
font: inherit;
line-height: 110%;
font-size: 80%;
padding: 5px 10px;
}
.openassessment_assessment_module_settings_editor{ .openassessment_assessment_module_settings_editor{
padding: 0 15px 0 0; padding: 0 15px 0 0;
margin: 10px; margin: 10px;
......
...@@ -17,7 +17,8 @@ from openassessment.xblock.validation import validator ...@@ -17,7 +17,8 @@ from openassessment.xblock.validation import validator
from openassessment.xblock.data_conversion import create_rubric_dict, make_django_template_key from openassessment.xblock.data_conversion import create_rubric_dict, make_django_template_key
from openassessment.xblock.schema import EDITOR_UPDATE_SCHEMA from openassessment.xblock.schema import EDITOR_UPDATE_SCHEMA
from openassessment.xblock.resolve_dates import resolve_dates from openassessment.xblock.resolve_dates import resolve_dates
from openassessment.xblock.xml import serialize_examples_to_xml_str, parse_examples_from_xml_str
from xml import UpdateFromXmlError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -138,8 +139,8 @@ class StudioMixin(object): ...@@ -138,8 +139,8 @@ class StudioMixin(object):
logger.exception('Editor context is invalid') logger.exception('Editor context is invalid')
return {'success': False, 'msg': _('Error updating XBlock configuration')} return {'success': False, 'msg': _('Error updating XBlock configuration')}
# Check that the editor assessment order contains all the assessments # Check that the editor assessment order contains all the assessments. We are more flexible on example-based.
if set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) != set(data['editor_assessments_order']): if set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) != (set(data['editor_assessments_order']) - {'example-based-assessment'}):
logger.exception('editor_assessments_order does not contain all expected assessment types') logger.exception('editor_assessments_order does not contain all expected assessment types')
return {'success': False, 'msg': _('Error updating XBlock configuration')} return {'success': False, 'msg': _('Error updating XBlock configuration')}
...@@ -156,6 +157,24 @@ class StudioMixin(object): ...@@ -156,6 +157,24 @@ class StudioMixin(object):
if 'name' not in option: if 'name' not in option:
option['name'] = uuid4().hex option['name'] = uuid4().hex
# If example based assessment is enabled, we replace it's xml definition with the dictionary
# definition we expect for validation and storing.
for assessment in data['assessments']:
if assessment['name'] == 'example-based-assessment':
try:
assessment['examples'] = parse_examples_from_xml_str(assessment['examples_xml'])
except UpdateFromXmlError:
return {'success': False, 'msg': _(
u'Validation error: There was an error in the XML definition of the '
u'examples provided by the user. Please correct the XML definition before saving.')
}
except KeyError:
return {'success': False, 'msg': _(
u'Validation error: No examples were provided for example based assessment.'
)}
# This is where we default to EASE for problems which are edited in the GUI
assessment['algorithm_id'] = 'ease'
xblock_validator = validator(self) xblock_validator = validator(self)
success, msg = xblock_validator( success, msg = xblock_validator(
create_rubric_dict(data['prompt'], data['criteria']), create_rubric_dict(data['prompt'], data['criteria']),
...@@ -255,6 +274,13 @@ class StudioMixin(object): ...@@ -255,6 +274,13 @@ class StudioMixin(object):
else: else:
assessments['training'] = {'examples': [student_training_template], 'template': student_training_template} assessments['training'] = {'examples': [student_training_template], 'template': student_training_template}
example_based_assessment = self.get_assessment_module('example-based-assessment')
if example_based_assessment:
assessments['example_based_assessment'] = {
'examples': serialize_examples_to_xml_str(example_based_assessment)
}
return assessments return assessments
def _editor_assessments_order_context(self): def _editor_assessments_order_context(self):
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": "2014-02-27T09:46", "submission_due": "2014-02-27T09:46",
"submission_start": "2014-02-10T09:46" "submission_start": "2014-02-10T09:46"
}, },
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
"explanation": "Yes explanation" "explanation": "Yes explanation"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"feedback": "optional" "feedback": "optional"
} }
], ],
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": "2014-02-27T09:46", "submission_due": "2014-02-27T09:46",
"submission_start": "2014-02-10T09:46" "submission_start": "2014-02-10T09:46"
}, },
...@@ -154,7 +154,7 @@ ...@@ -154,7 +154,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_start": "2014-02-10T09:46" "submission_start": "2014-02-10T09:46"
}, },
...@@ -199,7 +199,7 @@ ...@@ -199,7 +199,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": "2012-02-27T09:46", "submission_due": "2012-02-27T09:46",
"submission_start": "2015-02-10T09:46", "submission_start": "2015-02-10T09:46",
"expected_error": "the start date '2015-02-10 09:46:00+00:00' cannot be later than the due date '2012-02-27 09:46:00+00:00'" "expected_error": "the start date '2015-02-10 09:46:00+00:00' cannot be later than the due date '2012-02-27 09:46:00+00:00'"
...@@ -246,7 +246,7 @@ ...@@ -246,7 +246,7 @@
"due": "2003-01-02T00:00" "due": "2003-01-02T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": "2012-02-27T09:46", "submission_due": "2012-02-27T09:46",
"submission_start": null, "submission_start": null,
"expected_error": "cannot be later" "expected_error": "cannot be later"
...@@ -286,7 +286,7 @@ ...@@ -286,7 +286,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -324,7 +324,7 @@ ...@@ -324,7 +324,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -344,7 +344,7 @@ ...@@ -344,7 +344,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -382,7 +382,7 @@ ...@@ -382,7 +382,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -408,7 +408,7 @@ ...@@ -408,7 +408,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -442,7 +442,7 @@ ...@@ -442,7 +442,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -480,7 +480,7 @@ ...@@ -480,7 +480,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
...@@ -519,7 +519,7 @@ ...@@ -519,7 +519,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null, "submission_start": null,
"expected_error": "error updating xblock configuration" "expected_error": "error updating xblock configuration"
...@@ -559,7 +559,7 @@ ...@@ -559,7 +559,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null, "submission_start": null,
"expected_error": "error updating xblock configuration" "expected_error": "error updating xblock configuration"
...@@ -599,13 +599,13 @@ ...@@ -599,13 +599,13 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"submission_due": null, "submission_due": null,
"submission_start": null "submission_start": null
}, },
"student_training_example_missing_answer": { "student_training_example_missing_answer": {
"criteria": [ "criteria": [
{ {
"order_num": 0, "order_num": 0,
"label": "тєѕт ¢яιтєяιση", "label": "тєѕт ¢яιтєяιση",
...@@ -652,7 +652,7 @@ ...@@ -652,7 +652,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"student_training_example_missing_options_selected": { "student_training_example_missing_options_selected": {
...@@ -701,7 +701,7 @@ ...@@ -701,7 +701,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"student_training_example_missing_criterion": { "student_training_example_missing_criterion": {
...@@ -753,7 +753,7 @@ ...@@ -753,7 +753,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"student_training_example_missing_option": { "student_training_example_missing_option": {
...@@ -805,7 +805,7 @@ ...@@ -805,7 +805,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"student_training_no_examples": { "student_training_no_examples": {
...@@ -850,7 +850,7 @@ ...@@ -850,7 +850,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"expected_error": "you must provide at least one example response for student training" "expected_error": "you must provide at least one example response for student training"
}, },
...@@ -903,7 +903,7 @@ ...@@ -903,7 +903,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"], "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"],
"expected_error": "example 1 has an extra option" "expected_error": "example 1 has an extra option"
}, },
...@@ -995,7 +995,7 @@ ...@@ -995,7 +995,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "self-assessment"]
}, },
"unrecognized_assessment_in_editor_assessments_order": { "unrecognized_assessment_in_editor_assessments_order": {
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"unicode": { "unicode": {
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"student_training": { "student_training": {
...@@ -149,7 +149,7 @@ ...@@ -149,7 +149,7 @@
"due": "4014-03-10T00:00" "due": "4014-03-10T00:00"
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
}, },
"already_has_criteria_and_options_names_assigned": { "already_has_criteria_and_options_names_assigned": {
...@@ -198,6 +198,6 @@ ...@@ -198,6 +198,6 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "example-based-assessment"] "editor_assessments_order": ["student-training", "peer-assessment", "self-assessment"]
} }
} }
...@@ -24,7 +24,6 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -24,7 +24,6 @@ class StudioViewTest(XBlockHandlerTestCase):
"allow_file_upload": False, "allow_file_upload": False,
"assessments": [{"name": "self-assessment"}], "assessments": [{"name": "self-assessment"}],
"editor_assessments_order": [ "editor_assessments_order": [
"example-based-assessment",
"student-training", "student-training",
"peer-assessment", "peer-assessment",
"self-assessment", "self-assessment",
...@@ -88,6 +87,13 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -88,6 +87,13 @@ class StudioViewTest(XBlockHandlerTestCase):
} }
] ]
EXAMPLE_BASED_ASSESSMENT_EXAMPLES = '<examples>' + \
'<example>' + \
'<answer> TEST ANSWER </answer>' + \
'<select criterion="Test criterion" option="Test option" />' + \
'</example>' + \
'</examples>'
ASSESSMENT_CSS_IDS = { ASSESSMENT_CSS_IDS = {
"example-based-assessment": "oa_ai_assessment_editor", "example-based-assessment": "oa_ai_assessment_editor",
"peer-assessment": "oa_peer_assessment_editor", "peer-assessment": "oa_peer_assessment_editor",
...@@ -105,6 +111,11 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -105,6 +111,11 @@ class StudioViewTest(XBlockHandlerTestCase):
frag = self.runtime.render(xblock, 'studio_view') frag = self.runtime.render(xblock, 'studio_view')
self.assertTrue(frag.body_html().find('openassessment-edit')) self.assertTrue(frag.body_html().find('openassessment-edit'))
@scenario('data/example_based_only.xml')
def test_render_studio_with_ai(self, xblock):
frag = self.runtime.render(xblock, 'studio_view')
self.assertTrue(frag.body_html().find('openassessment-edit'))
@file_data('data/update_xblock.json') @file_data('data/update_xblock.json')
@scenario('data/basic_scenario.xml') @scenario('data/basic_scenario.xml')
def test_update_editor_context(self, xblock, data): def test_update_editor_context(self, xblock, data):
...@@ -117,7 +128,6 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -117,7 +128,6 @@ class StudioViewTest(XBlockHandlerTestCase):
# Update the XBlock with a different editor assessment order # Update the XBlock with a different editor assessment order
data = copy.deepcopy(self.UPDATE_EDITOR_DATA) data = copy.deepcopy(self.UPDATE_EDITOR_DATA)
data['editor_assessments_order'] = [ data['editor_assessments_order'] = [
"example-based-assessment",
"student-training", "student-training",
"peer-assessment", "peer-assessment",
"self-assessment", "self-assessment",
...@@ -128,6 +138,25 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -128,6 +138,25 @@ class StudioViewTest(XBlockHandlerTestCase):
self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order']) self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order'])
@scenario('data/basic_scenario.xml') @scenario('data/basic_scenario.xml')
def test_update_editor_context_saves_assessment_order_with_ai(self, xblock):
# Update the XBlock with a different editor assessment order
data = copy.deepcopy(self.UPDATE_EDITOR_DATA)
data['assessments'] = [{
'name': 'example-based-assessment',
'examples_xml': self.EXAMPLE_BASED_ASSESSMENT_EXAMPLES
}]
data['editor_assessments_order'] = [
"example-based-assessment",
"student-training",
"peer-assessment",
"self-assessment",
]
xblock.published_date = None
resp = self.request(xblock, 'update_editor_context', json.dumps(data), response_format='json')
self.assertTrue(resp['success'], msg=resp.get('msg'))
self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order'])
@scenario('data/basic_scenario.xml')
def test_update_editor_context_assign_unique_names(self, xblock): def test_update_editor_context_assign_unique_names(self, xblock):
# Update the XBlock with a rubric that is missing # Update the XBlock with a rubric that is missing
# some of the (unique) names for rubric criteria/options. # some of the (unique) names for rubric criteria/options.
......
...@@ -66,6 +66,7 @@ def _is_valid_assessment_sequence(assessments): ...@@ -66,6 +66,7 @@ def _is_valid_assessment_sequence(assessments):
['student-training', 'peer-assessment'], ['student-training', 'peer-assessment'],
['student-training', 'peer-assessment', 'self-assessment'], ['student-training', 'peer-assessment', 'self-assessment'],
['student-training', 'self-assessment', 'peer-assessment'], ['student-training', 'self-assessment', 'peer-assessment'],
['self-assessment', 'student-training', 'peer-assessment'],
['example-based-assessment'], ['example-based-assessment'],
['example-based-assessment', 'self-assessment'], ['example-based-assessment', 'self-assessment'],
['example-based-assessment', 'peer-assessment'], ['example-based-assessment', 'peer-assessment'],
...@@ -74,6 +75,7 @@ def _is_valid_assessment_sequence(assessments): ...@@ -74,6 +75,7 @@ def _is_valid_assessment_sequence(assessments):
['example-based-assessment', 'student-training', 'peer-assessment'], ['example-based-assessment', 'student-training', 'peer-assessment'],
['example-based-assessment', 'student-training', 'peer-assessment', 'self-assessment'], ['example-based-assessment', 'student-training', 'peer-assessment', 'self-assessment'],
['example-based-assessment', 'student-training', 'self-assessment', 'peer-assessment'], ['example-based-assessment', 'student-training', 'self-assessment', 'peer-assessment'],
['example-based-assessment', 'self-assessment', 'student-training', 'peer-assessment'],
] ]
sequence = [asmnt.get('name') for asmnt in assessments] sequence = [asmnt.get('name') for asmnt in assessments]
...@@ -108,13 +110,8 @@ def validate_assessments(assessments, current_assessments, is_released): ...@@ -108,13 +110,8 @@ def validate_assessments(assessments, current_assessments, is_released):
# Ensure that we support this sequence of assessments. # Ensure that we support this sequence of assessments.
if not _is_valid_assessment_sequence(assessments): if not _is_valid_assessment_sequence(assessments):
msg = _( msg = _("The assessment order you selected is invalid.")
"For this assignment, you can set a peer assessment only, a self " return False, msg
"assessment only, or a peer assessment followed by a self "
"assessment. Student training is allowed only immediately before "
"peer assessment."
)
return (False, msg)
for assessment_dict in assessments: for assessment_dict in assessments:
# Number you need to grade is >= the number of people that need to grade you # Number you need to grade is >= the number of people that need to grade you
......
...@@ -803,3 +803,19 @@ def _unicode_to_xml(xml): ...@@ -803,3 +803,19 @@ def _unicode_to_xml(xml):
return safe_etree.fromstring(xml.encode('utf-8')) return safe_etree.fromstring(xml.encode('utf-8'))
except (ValueError, safe_etree.ParseError): except (ValueError, safe_etree.ParseError):
raise UpdateFromXmlError(_("An error occurred while parsing the XML content.")) raise UpdateFromXmlError(_("An error occurred while parsing the XML content."))
def parse_examples_from_xml_str(xml):
"""
Converts an XML string of examples (Student Training or AI) into a dictionary
representing the same information.
Args:
xml (unicode): The XML definition of the examples
Returns
(list of dict): The example definition
"""
examples_root = _unicode_to_xml(xml)
examples = examples_root.findall('example')
return parse_examples_xml(examples)
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