Skip to content

Commit

Permalink
Problems can now be optional (student not required to fill something …
Browse files Browse the repository at this point in the history
…in).

Also add a nice fade out animation in the studio to see difference between
two succesive saves.

Fixes #49
  • Loading branch information
GuillaumeDerval committed Jun 23, 2015
1 parent 18efcfa commit 1f88132
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 10 deletions.
17 changes: 15 additions & 2 deletions common/tasks_code_boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ def input_is_consistent(self, taskInput):
# do not allow empty answers
try:
if len(taskInput[self.get_complete_id()]) == 0:
return False
if self._optional:
taskInput[self.get_complete_id()] = self._default_value
else:
return False
except:
return False

Expand All @@ -165,13 +168,18 @@ def __init__(self, problem, boxid, boxData):
BasicBox.__init__(self, problem, boxid, boxData)
if boxData["type"] == "input-text":
self._input_type = "text"
self._default_value = ""
elif boxData["type"] == "input-integer":
self._input_type = "integer"
self._default_value = "0"
elif boxData["type"] == "input-decimal":
self._input_type = "decimal"
self._default_value = "0.0"
else:
raise Exception("No such box type " + boxData["type"] + " in box " + boxid)

self._optional = boxData.get("optional", False)

if "maxChars" in boxData and isinstance(boxData['maxChars'], (int, long)) and boxData['maxChars'] > 0:
self._max_chars = boxData['maxChars']
elif "maxChars" in boxData:
Expand All @@ -194,7 +202,10 @@ def input_is_consistent(self, taskInput):
return False
# do not allow empty answers
if len(taskInput[self.get_complete_id()]) == 0:
return False
if self._optional:
taskInput[self.get_complete_id()] = ""
else:
return False
return True

def __init__(self, problem, boxid, boxData):
Expand All @@ -206,6 +217,8 @@ def __init__(self, problem, boxid, boxData):
else:
self._max_chars = 0

self._optional = boxData.get("optional", False)

if "lines" in boxData and isinstance(boxData['lines'], (int, long)) and boxData['lines'] > 0:
self._lines = boxData['lines']
elif "lines" in boxData:
Expand Down
7 changes: 4 additions & 3 deletions common/tasks_problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class CodeSingleLineProblem(BasicCodeProblem):

def __init__(self, task, problemid, content):
BasicCodeProblem.__init__(self, task, problemid, content)
self._boxes = [self._create_box("", {"type": "input-text"})]
self._boxes = [self._create_box("", {"type": "input-text", "optional": content.get("optional", False)})]

def get_type(self):
return "code-single-line"
Expand Down Expand Up @@ -179,9 +179,10 @@ def __init__(self, task, problemid, content):
self._boxes.append(self._create_box(boxid, box_content))
else:
if "language" in content:
self._boxes = [self._create_box("", {"type": "multiline", "language": content["language"]})]
self._boxes = [self._create_box("", {"type": "multiline", "language": content["language"],
"optional": content.get("optional", False)})]
else:
self._boxes = [self._create_box("", {"type": "multiline"})]
self._boxes = [self._create_box("", {"type": "multiline", "optional": content.get("optional", False)})]

def get_type(self):
return "code"
Expand Down
8 changes: 7 additions & 1 deletion doc/teacher_doc/task_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,14 @@ Here is a simple example for a code problem
Hello dear student!
I'm a multiline header!
name: A name
optional: false

*header* and *language* are only needed when using the frontend and are not mandatory.
This description typically displays on the frontend a box where student
can put their code.

*optional* is an optional field, that defaults to false, that indicates if this problem is mandatory or not.

Code problem input's are available in the *run* script (see :doc:`run_file`) directly with the
id of the problem.

Expand All @@ -102,6 +105,7 @@ Single code line problems
Hello dear student!
I'm another multiline header, parsed with *RST*!
name: Another problem
optional: false


Single line code problem input's are available in the *run* script (see :doc:`run_file`) directly with the
Expand All @@ -124,6 +128,7 @@ Advanced code problems are available:
boxId2:
type: input-text
maxChars: 10
optional: true
boxId3:
type: multiline
maxChars: 1000
Expand All @@ -133,7 +138,8 @@ Advanced code problems are available:
*Boxes* are displayable (on the frontend) input fields that allows the student
to fill more than one entry per problem. Different box types are available, all of them
are demonstrated above. Every configuration in the boxes (*maxChars*,*lines*,*language*)
is not mandatory, except *content* if the box type is *text*.
is not mandatory, except *content* if the box type is *text*, and the field *optional* (default to false),
that indicates if the box is mandatory or not.

In the *run* file (see :doc:`run_file`), boxes input are available with the name
*problem_id/box_id*
Expand Down
3 changes: 3 additions & 0 deletions frontend/pages/course_admin/task_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def parse_problem(self, problem_content):
if "headerIsHTML" in problem_content:
problem_content["headerIsHTML"] = True

if "optional" in problem_content:
problem_content["optional"] = True

if "multiple" in problem_content:
problem_content["multiple"] = True

Expand Down
16 changes: 13 additions & 3 deletions static/js/INGIniousStudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,21 @@ function studio_task_file_delete_tab(path)

/**
* Display a message indicating the status of a save action
* @param type
* @param message
*/
function studio_display_task_submit_message(content, type, dismissible)
{
code = getAlertCode(content,type,dismissible)
code = getAlertCode(content,type,dismissible);
$('#task_edit_submit_status').html(code);


if(dismissible)
{
window.setTimeout(function () {
$("#task_edit_submit_status").children().fadeTo(1000, 0).slideUp(1000, function () {
$(this).remove();
});
}, 2000);
}
}

/**
Expand Down Expand Up @@ -425,6 +433,8 @@ function studio_init_template_code(well, pid, problem)
$('#language-'+pid,well).val(problem["language"]);
if("type" in problem)
$('#type-'+pid,well).val(problem["type"]);
if ("optional" in problem && problem["optional"])
$('#optional-' + pid, well).attr('checked', true);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tasks/test/helloworld/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ name: Hello World!
problems:
question1:
name: Let's print it
type: code
language: python
header: 'def func():'
type: code
weight: 3.0
9 changes: 9 additions & 0 deletions templates/course_admin/edit_tabs/subproblem_templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@
</select>
</div>
</div>
<div class="form-group">
<label for="optional-PID" class="col-sm-2 control-label">Optional?</label>

<div class="col-sm-10">
<div class="checkbox"><label>
<input type="checkbox" id="optional-PID" name="problem[PID][optional]"/>&nbsp;
</label></div>
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<button class="btn btn-danger btn-sm btn-block" type="button" onclick="studio_subproblem_delete('PID')"><span class="glyphicon glyphicon-remove-sign"></span> Delete subproblem</button>
Expand Down

0 comments on commit 1f88132

Please sign in to comment.