Commit 043e493b by Will Daly

Implement leaderboard authoring

parent 25412f9e
......@@ -99,7 +99,7 @@
</div>
<p class="setting-help">{% trans "The date and time when students can no longer submit responses." %}</p>
</li>
<li id="openassessment_sumbission_image_wrapper" class="field comp-setting-entry">
<li id="openassessment_submission_image_wrapper" class="field comp-setting-entry">
<div class="wrapper-comp-setting">
<label for="openassessment_submission_image_editor" class="setting-label">{% trans "Allow Image Responses"%}</label>
<select id="openassessment_submission_image_editor" class="input setting-input" name="image submission">
......@@ -109,6 +109,20 @@
</div>
<p class="setting-help">{% trans "Specify whether students can submit an image file along with their text response." %}</p>
</li>
<li id="openassessment_leaderboard_wrapper" class="field comp-setting-entry">
<div class="wrapper-comp-setting">
<label for="openassessment_leaderboard_editor" class="setting-label">{% trans "Number of Leaderboard Scores" %}</label>
<input
id="openassessment_leaderboard_editor"
class="input setting-input"
type="number"
value="{{ leaderboard_show }}"
min="0" max="99"
/>
</div>
<p class="setting-help">{% trans "Set the number of scores to display on the leaderboard. If set to 0, the leaderboard will not be shown." %}</p>
</li>
<li>
</ul>
<p class="openassessment_description" id="openassessment_step_select_description">
......
......@@ -380,7 +380,8 @@ class OpenAssessmentBlock(
create_rubric_dict(config['prompt'], config['rubric_criteria']),
config['rubric_assessments'],
submission_start=config['submission_start'],
submission_due=config['submission_due']
submission_due=config['submission_due'],
leaderboard_show=config['leaderboard_show']
)
block.rubric_criteria = config['rubric_criteria']
......
......@@ -72,6 +72,7 @@ EDITOR_UPDATE_SCHEMA = Schema({
Required('submission_start'): Any(datetime_validator, None),
Required('submission_due'): Any(datetime_validator, None),
Required('allow_file_upload'): bool,
Required('leaderboard_show'): int,
Required('assessments'): [
Schema({
Required('name'): All(utf8_validator, In(VALID_ASSESSMENT_TYPES)),
......
......@@ -402,6 +402,7 @@
"title": "The most important of all questions.",
"submission_start": "2014-01-02T12:15",
"submission_due": "2014-10-01T04:53",
"leaderboard_show": 12,
"criteria": [
{
"name": "criterion_1",
......@@ -482,6 +483,7 @@
"title": "Test title",
"submission_start": "2014-01-1T10:00:00",
"submission_due": "2014-10-1T10:00:00",
"leaderboard_show": 12,
"criteria": [
{
"name": "criterion_with_two_options",
......
......@@ -239,7 +239,9 @@ describe("OpenAssessment.Server", function() {
submissionDue: SUBMISSION_DUE,
criteria: CRITERIA,
assessments: ASSESSMENTS,
editorAssessmentsOrder: EDITOR_ASSESSMENTS_ORDER
editorAssessmentsOrder: EDITOR_ASSESSMENTS_ORDER,
imageSubmissionEnabled: true,
leaderboardNum: 15
});
expect($.ajax).toHaveBeenCalledWith({
type: "POST", url: '/update_editor_context',
......@@ -251,7 +253,9 @@ describe("OpenAssessment.Server", function() {
submission_due: SUBMISSION_DUE,
criteria: CRITERIA,
assessments: ASSESSMENTS,
editor_assessments_order: EDITOR_ASSESSMENTS_ORDER
editor_assessments_order: EDITOR_ASSESSMENTS_ORDER,
allow_file_upload: true,
leaderboard_show: 15
})
});
});
......
......@@ -48,6 +48,7 @@ describe("OpenAssessment.StudioView", function() {
submissionStart: "2014-01-02T12:15",
submissionDue: "2014-10-01T04:53",
imageSubmissionEnabled: false,
leaderboardNum: 12,
criteria: [
{
order_num: 0,
......@@ -149,6 +150,7 @@ describe("OpenAssessment.StudioView", function() {
expect(server.receivedData.submissionStart).toEqual(EXPECTED_SERVER_DATA.submissionStart);
expect(server.receivedData.submissionDue).toEqual(EXPECTED_SERVER_DATA.submissionDue);
expect(server.receivedData.imageSubmissionEnabled).toEqual(EXPECTED_SERVER_DATA.imageSubmissionEnabled);
expect(server.receivedData.leaderboardNum).toEqual(EXPECTED_SERVER_DATA.leaderboardNum);
// Criteria
for (var criterion_idx = 0; criterion_idx < EXPECTED_SERVER_DATA.criteria.length; criterion_idx++) {
......
......@@ -91,6 +91,14 @@ describe("OpenAssessment.EditSettingsView", function() {
expect(view.imageSubmissionEnabled()).toBe(false);
});
it("sets and loads the leaderboard number", function() {
view.leaderboardNum(18);
expect(view.leaderboardNum()).toEqual(18);
view.leaderboardNum(0);
expect(view.leaderboardNum()).toEqual(0);
});
it("builds a description of enabled assessments", function() {
// Depends on the template having an original order
// of training --> peer --> self --> ai
......@@ -157,6 +165,32 @@ describe("OpenAssessment.EditSettingsView", function() {
);
});
it("validates the leaderboard number field", function() {
// Valid value for the leaderboard number
view.leaderboardNum(0);
expect(view.validate()).toBe(true);
expect(view.validationErrors()).toEqual([]);
// Below the minimum
view.leaderboardNum(-1);
expect(view.validate()).toBe(false);
expect(view.validationErrors()).toContain(
"Leaderboard number is invalid"
);
// Clear validation errors
view.clearValidationErrors();
expect(view.validationErrors()).toEqual([]);
// Valid, near the maximum
view.leaderboardNum(100);
expect(view.validate()).toBe(true);
// Above the maximum
view.leaderboardNum(101);
expect(view.validate()).toBe(false);
});
it("validates assessment views", function() {
// Simulate one of the assessment views being invalid
assessmentViews[PEER].isValid = false;
......
......@@ -418,6 +418,7 @@ if (typeof OpenAssessment.Server == "undefined" || !OpenAssessment.Server) {
criteria (list of object literals): The rubric criteria.
assessments (list of object literals): The assessments the student will be evaluated on.
imageSubmissionEnabled (boolean): TRUE if image attachments are allowed.
leaderboardNum (int): The number of scores to show in the leaderboard.
Returns:
A JQuery promise, which resolves with no arguments
......@@ -435,7 +436,8 @@ if (typeof OpenAssessment.Server == "undefined" || !OpenAssessment.Server) {
criteria: kwargs.criteria,
assessments: kwargs.assessments,
editor_assessments_order: kwargs.editorAssessmentsOrder,
allow_file_upload: kwargs.imageSubmissionEnabled
allow_file_upload: kwargs.imageSubmissionEnabled,
leaderboard_show: kwargs.leaderboardNum
});
return $.Deferred(function(defer) {
$.ajax({
......
......@@ -193,6 +193,7 @@ OpenAssessment.StudioView.prototype = {
submissionDue: view.settingsView.submissionDue(),
assessments: view.settingsView.assessmentsDescription(),
imageSubmissionEnabled: view.settingsView.imageSubmissionEnabled(),
leaderboardNum: view.settingsView.leaderboardNum(),
editorAssessmentsOrder: view.settingsView.editorAssessmentsOrder()
}).done(
// Notify the client-side runtime that we finished saving
......
......@@ -27,6 +27,11 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews) {
"#openassessment_submission_due_time"
).install();
this.leaderboardIntField = new OpenAssessment.IntField(
$("#openassessment_leaderboard_editor", this.element),
{ min: 0, max: 100 }
);
this.initializeSortableAssessments();
};
......@@ -128,7 +133,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
imageSubmissionEnabled: function(isEnabled) {
var sel = $("#openassessment_submission_image_editor", this.settingsElement);
if (typeof(isEnabled) !== "undefined") {
if (isEnabled !== undefined) {
if (isEnabled) { sel.val(1); }
else { sel.val(0); }
}
......@@ -136,6 +141,24 @@ OpenAssessment.EditSettingsView.prototype = {
},
/**
Get or set the number of scores to show in the leaderboard.
If set to 0, the leaderboard will not be shown.
Args:
num (int, optional)
Returns:
int
**/
leaderboardNum: function(num) {
if (num !== undefined) {
this.leaderboardIntField.set(num);
}
return this.leaderboardIntField.get(num);
},
/**
Construct a list of enabled assessments and their properties.
......@@ -212,6 +235,7 @@ OpenAssessment.EditSettingsView.prototype = {
isValid = (this.startDatetimeControl.validate() && isValid);
isValid = (this.dueDatetimeControl.validate() && isValid);
isValid = (this.leaderboardIntField.validate() && isValid);
// Validate each of the *enabled* assessment views
$.each(this.assessmentViews, function() {
......@@ -240,10 +264,14 @@ OpenAssessment.EditSettingsView.prototype = {
if (this.dueDatetimeControl.validationErrors().length > 0) {
errors.push("Submission due is invalid");
}
if (this.leaderboardIntField.validationErrors().length > 0) {
errors.push("Leaderboard number is invalid");
}
$.each(this.assessmentViews, function() {
errors = errors.concat(this.validationErrors());
});
return errors;
},
......@@ -253,6 +281,7 @@ OpenAssessment.EditSettingsView.prototype = {
clearValidationErrors: function() {
this.startDatetimeControl.clearValidationErrors();
this.dueDatetimeControl.clearValidationErrors();
this.leaderboardIntField.clearValidationErrors();
$.each(this.assessmentViews, function() {
this.clearValidationErrors();
});
......
......@@ -114,6 +114,7 @@ class StudioMixin(object):
'criteria': criteria,
'feedbackprompt': self.rubric_feedback_prompt,
'allow_file_upload': self.allow_file_upload,
'leaderboard_show': self.leaderboard_show,
'editor_assessments_order': [
make_django_template_key(asmnt)
for asmnt in editor_assessments_order
......@@ -187,6 +188,7 @@ class StudioMixin(object):
data['assessments'],
submission_start=data['submission_start'],
submission_due=data['submission_due'],
leaderboard_show=data['leaderboard_show']
)
if not success:
return {'success': False, 'msg': self._('Validation error: {error}').format(error=msg)}
......@@ -203,6 +205,7 @@ class StudioMixin(object):
self.submission_start = data['submission_start']
self.submission_due = data['submission_due']
self.allow_file_upload = bool(data['allow_file_upload'])
self.leaderboard_show = data['leaderboard_show']
return {'success': True, 'msg': self._(u'Successfully updated OpenAssessment XBlock')}
......
......@@ -4,6 +4,7 @@
"title": "My new title.",
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -26,6 +27,7 @@
"no_prompt": {
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -74,6 +76,7 @@
"no_feedback_prompt": {
"prompt": "Test prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -123,6 +126,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -171,6 +175,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -221,6 +226,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -271,6 +277,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": "Hello",
......@@ -313,6 +320,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -354,6 +362,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "prompty",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
[]
],
......@@ -374,6 +383,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -415,6 +425,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -442,6 +453,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -478,6 +490,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -519,6 +532,7 @@
"feedback_prompt": "Feedback prompt",
"prompt": "Test Prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -669,6 +683,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -723,6 +738,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -775,6 +791,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -830,6 +847,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -885,6 +903,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -934,6 +953,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -990,6 +1010,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -1038,6 +1059,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -1087,6 +1109,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -1112,6 +1135,7 @@
"prompt": "Test Prompt",
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -1160,6 +1184,7 @@
"prompt": "Test Prompt",
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -1208,6 +1233,7 @@
"prompt": "Test Prompt",
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......@@ -1279,6 +1305,7 @@
"prompt": "Test Prompt",
"feedback_prompt": "Feedback prompt",
"allow_file_upload": false,
"leaderboard_show": 0,
"criteria": [
{
"order_num": 0,
......
......@@ -452,69 +452,6 @@
]
},
"leaderboard_num_zero": {
"xml": [
"<openassessment leaderboard_show=\"0\">",
"<title>Foo</title>",
"<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"<assessment name=\"self-assessment\" start=\"2014-04-01T00:00:00\" due=\"2014-06-01T00:00:00\" />",
"</assessments>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"<criterion>",
"<name>Test criterion</name>",
"<prompt>Test criterion prompt</prompt>",
"<option points=\"0\"><name>No</name><explanation>No explanation</explanation></option>",
"<option points=\"2\"><name>Yes</name><explanation>Yes explanation</explanation></option>",
"</criterion>",
"</rubric>",
"</openassessment>"
]
},
"leaderboard_num_negative": {
"xml": [
"<openassessment leaderboard_show=\"-1\">",
"<title>Foo</title>",
"<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"<assessment name=\"self-assessment\" start=\"2014-04-01T00:00:00\" due=\"2014-06-01T00:00:00\" />",
"</assessments>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"<criterion>",
"<name>Test criterion</name>",
"<prompt>Test criterion prompt</prompt>",
"<option points=\"0\"><name>No</name><explanation>No explanation</explanation></option>",
"<option points=\"2\"><name>Yes</name><explanation>Yes explanation</explanation></option>",
"</criterion>",
"</rubric>",
"</openassessment>"
]
},
"leaderboard_num_too_high": {
"xml": [
"<openassessment leaderboard_show=\"101\">",
"<title>Foo</title>",
"<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"<assessment name=\"self-assessment\" start=\"2014-04-01T00:00:00\" due=\"2014-06-01T00:00:00\" />",
"</assessments>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"<criterion>",
"<name>Test criterion</name>",
"<prompt>Test criterion prompt</prompt>",
"<option points=\"0\"><name>No</name><explanation>No explanation</explanation></option>",
"<option points=\"2\"><name>Yes</name><explanation>Yes explanation</explanation></option>",
"</criterion>",
"</rubric>",
"</openassessment>"
]
},
"leaderboard_num_not_integer": {
"xml": [
"<openassessment leaderboard_show=\"not_an_int\">",
......
......@@ -31,6 +31,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -80,6 +81,7 @@
"submission_start": "4014-02-10T09:46",
"title": "ɯʎ uǝʍ ʇıʇןǝ",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "peer-assessment",
......@@ -129,6 +131,7 @@
"submission_start": "4014-02-10T09:46",
"title": "My new title.",
"allow_file_upload": false,
"leaderboard_show": 0,
"assessments": [
{
"name": "student-training",
......@@ -189,6 +192,7 @@
"submission_due": "4014-02-27T09:46",
"submission_start": "4014-02-10T09:46",
"allow_file_upload": false,
"leaderboard_show": 0,
"title": "My new title.",
"assessments": [
{
......
......@@ -22,6 +22,7 @@ class StudioViewTest(XBlockHandlerTestCase):
"submission_start": "4014-02-10T09:46",
"submission_due": "4014-02-27T09:46",
"allow_file_upload": False,
"leaderboard_show": 4,
"assessments": [{"name": "self-assessment"}],
"editor_assessments_order": [
"student-training",
......@@ -127,6 +128,11 @@ class StudioViewTest(XBlockHandlerTestCase):
self.assertTrue(resp['success'], msg=resp.get('msg'))
@scenario('data/basic_scenario.xml')
def test_include_leaderboard_in_editor(self, xblock):
xblock.leaderboard_show = 15
self.assertEqual(xblock.editor_context()['leaderboard_show'], 15)
@scenario('data/basic_scenario.xml')
def test_update_editor_context_saves_assessment_order(self, xblock):
# Update the XBlock with a different editor assessment order
data = copy.deepcopy(self.UPDATE_EDITOR_DATA)
......@@ -140,6 +146,7 @@ class StudioViewTest(XBlockHandlerTestCase):
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_saves_assessment_order_with_ai(self, xblock):
# Update the XBlock with a different editor assessment order
......@@ -159,6 +166,15 @@ class StudioViewTest(XBlockHandlerTestCase):
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_saves_leaderboard(self, xblock):
data = copy.deepcopy(self.UPDATE_EDITOR_DATA)
data['leaderboard_show'] = 42
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.leaderboard_show, 42)
@file_data('data/invalid_update_xblock.json')
@scenario('data/basic_scenario.xml')
def test_update_context_invalid_request_data(self, xblock, data):
......
......@@ -334,3 +334,31 @@ class ValidationIntegrationTest(TestCase):
is_valid, msg = self.validator(mutated_rubric, no_example_based)
self.assertTrue(is_valid)
self.assertEqual(msg, u'')
def test_leaderboard_num_validation(self):
self._assert_leaderboard_num_valid(-1, False)
self._assert_leaderboard_num_valid(0, True)
self._assert_leaderboard_num_valid(1, True)
self._assert_leaderboard_num_valid(100, True)
self._assert_leaderboard_num_valid(101, False)
self._assert_leaderboard_num_valid(102, False)
def _assert_leaderboard_num_valid(self, num, expected_is_valid):
"""
Check that the leaderboard number is either valid or invalid.
Args:
num (int): The leaderboard number to check
expected_is_valid (bool): Whether the number is valid or invalid.
Raises:
AssertionError
"""
is_valid, msg = self.validator(self.RUBRIC, self.ASSESSMENTS, num)
if expected_is_valid:
self.assertTrue(is_valid, msg="Leaderboard num {num} should be valid".format(num=num))
self.assertEqual(msg, '')
else:
self.assertFalse(is_valid, msg="Leaderboard num {num} should be invalid".format(num=num))
self.assertEqual(msg, 'Leaderboard number is invalid.')
......@@ -2,6 +2,7 @@
Validate changes to an XBlock before it is updated.
"""
from collections import Counter
from submissions.api import MAX_TOP_SUBMISSIONS
from openassessment.assessment.serializers import rubric_from_dict, InvalidRubric
from openassessment.assessment.api.student_training import validate_training_examples
from openassessment.xblock.resolve_dates import resolve_dates, DateValidationError, InvalidDateFormat
......@@ -316,7 +317,7 @@ def validator(oa_block, _, strict_post_release=True):
callable, of a form that can be passed to `update_from_xml`.
"""
def _inner(rubric_dict, assessments, submission_start=None, submission_due=None):
def _inner(rubric_dict, assessments, leaderboard_show=0, submission_start=None, submission_due=None):
is_released = strict_post_release and oa_block.is_released()
......@@ -348,6 +349,10 @@ def validator(oa_block, _, strict_post_release=True):
if not success:
return (False, msg)
# Leaderboard
if leaderboard_show < 0 or leaderboard_show > MAX_TOP_SUBMISSIONS:
return (False, _("Leaderboard number is invalid."))
# Success!
return (True, u'')
......
......@@ -6,7 +6,6 @@ import lxml.etree as etree
import pytz
import dateutil.parser
import defusedxml.ElementTree as safe_etree
from submissions.api import MAX_TOP_SUBMISSIONS
class UpdateFromXmlError(Exception):
......@@ -755,13 +754,6 @@ def parse_from_xml(root):
if 'leaderboard_show' in root.attrib:
try:
leaderboard_show = int(root.attrib['leaderboard_show'])
if leaderboard_show < 1:
raise UpdateFromXmlError('The leaderboard must have a positive integer value.')
if leaderboard_show > MAX_TOP_SUBMISSIONS:
msg = 'The number of leaderboard scores must be less than {max_num}'.format(
max_num=MAX_TOP_SUBMISSIONS
)
raise UpdateFromXmlError(msg)
except (TypeError, ValueError):
raise UpdateFromXmlError('The leaderboard must have an integer value.')
......
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