// Numbas version: exam_results_page_options {"name": "Programming extension demo", "metadata": {"description": "

This exam collects some questions demonstrating different uses of the programming extension and the Code part type, to mark code written in Python and R.

", "licence": "Creative Commons Attribution 4.0 International"}, "duration": 0, "percentPass": "0", "showQuestionGroupNames": true, "shuffleQuestionGroups": false, "showstudentname": true, "question_groups": [{"name": "Python", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": ["", "", "Get the first item in a list", "Get the last item in a list", "Make a copy of a list", "Make a plot with matplotlib", "Exploration activity: Define a class, add methods to it, then use it"], "variable_overrides": [[], [], [], [], [], [], []], "questions": [{"name": "Assign a variable", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}], "tags": [], "metadata": {"description": "

This is the simplest demonstration of the \"code\" part type I could think of: write Python to assign x = 1.

\n

An alternative answer gives a hint if the student's code doesn't define x at all.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Assign the value 1 to the variable x.

", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "x is not defined", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "

The variable x is not defined.

\n

Assign a value to x like this:

\n
x = value
", "useAlternativeFeedback": false, "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "x=1", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"x is not defined\", 1, \"'x' not in locals()\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "x=1", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n py_mark_equal('x',1)\n]", "validation_tests": "[\n py_valid_defined('x')\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Compute the standard deviation of a sample using numpy", "extensions": ["programming", "stats"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

The student must write code to compute the standard deviation of an unknown list of measurements.

\n

The suggested answer uses numpy.std.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "

The numpy function std computes the standard deviation of an array.

\n

{code_block(\"import numpy\\nnumpy.std(sample)\",\"python\")}

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide', ['numpy']);", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

A set of measurements is stored in the variable sample.

\n

Compute the standard deviation of the sample.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "import numpy\nnumpy.std(sample)", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "import numpy\n\n# Now compute the standard deviation of sample\n", "modifier": "", "preamble": "from random import random\nsample = [random()*10 for i in range(20)]", "postamble": "studentAnswer = _\nimport numpy", "tests": "[\n [\"Standard deviation computed\", 1, \"\"\"\nstudentAnswer == numpy.std(sample)\n\"\"\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Get the first item in a list", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

Given a randomly-generated list, the student must write code to return its first value.

\n

There's an alternative to check if they get the second item, which they might do if they don't realise Python lists are zero-indexed.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "

In Python, the first item in a list has index 0.

\n

So, seq[0] returns the first item in seq.

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The variable seq is a list.

\n

Write code to get the first item in the list.

", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "seq[1]", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "

In Python, the first element of a list is element 0, not element 1.

", "useAlternativeFeedback": false, "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "seq[0]", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "from random import randrange\n\nseq = list(range(randrange(1000,2000), randrange(2000,3000)))", "postamble": "", "tests": "[\n [\"Got the first element\", 1, \"_ == seq[1]\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "seq[0]", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "from random import randrange\n\nseq = list(range(randrange(1000,2000), randrange(2000,3000)))", "postamble": "studentanswer = _", "tests": "[\n [\"Got the first element\", 1, \"studentanswer == seq[0]\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Get the last item in a list", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

Given an unknown list, the student has to write code to return the last item in the list.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "

There are two ways of getting the last item in a list in Python.

\n

The first is quite long-winded: seq[len(seq)-1].

\n

Python has a shorter notation: if you give a negative index, Python takes that from the length of the list automatically: seq[-1].

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The variable seq is a list.

\n

Write code to get the last item in the list.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "seq[-1]", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "from random import randrange\n\nseq = list(range(randrange(1000,2000), randrange(2000,3000)))", "postamble": "studentAnswer = _", "tests": "[\n [\"Got the last element\", 1, \"studentAnswer == seq[-1]\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Make a copy of a list", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

Given an unknown list, the student must write Python code to create a copy of it.

\n

There's an alternative to catch the case where the student's variable is just a reference to the original list.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "

In Python, a variable is a reference to an object. More than one variable can refer to the same object.

\n

If you wrote list2 = list1, then list2 would refer to the same object as list1, and any changes to list1 would be reflected in list2 as well.

\n

In order to make an independent copy, you should make a slice of list1:

\n

{code_block(\"list2 = list1[:]\", \"python\")}

\n

This creates a new list object, with all the same elements as list1.

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The variable list1 contains a list.

\n

Write code to assign a copy of the list to the variable list2.

", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "Didn't copy", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "

You have assigned list2 to the same object as list1, but not made a copy: if you change list1, list2 will also change.

", "useAlternativeFeedback": false, "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "list2 = list1[:]", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "from random import randrange\nlist1 = [randrange(1,10) for i in range(50)]", "postamble": "", "tests": "[\n [\"list1 == list2\", 1, \"list1 == list2\"]\n]", "validation_tests": "[\n py_valid_defined('list2')\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "list2 = list1[:]", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "from random import randrange\nlist1 = [randrange(1,10) for i in range(50)]", "postamble": "", "tests": "[\n [\"list2 is equal to list1, but not the same object\", 1, \"list1 == list2 and list1 is not list2\"]\n]", "validation_tests": "[\n py_valid_defined('list2')\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Make a plot with matplotlib", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}], "tags": [], "metadata": {"description": "

This question shows how to display a plot generated in matplotlib from code written by the student.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"python_plot_example": {"name": "python_plot_example", "group": "Ungrouped variables", "definition": "safe(\"ax = fig.add_subplot(111)\\nax.plot([1,2,3,4])\")", "description": "", "templateType": "long plain string", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["python_plot_example"], "variable_groups": [], "functions": {"r_load_files": {"parameters": [["files", "list of string"]], "type": "promise", "language": "javascript", "definition": "const mime_types = {\n '.pdf': 'application/pdf',\n '.svg': 'image/svg+xml'\n}\nreturn new Numbas.jme.types.TPromise(Numbas.extensions.programming.language_runners['webr'].load_webR().then(async (webR) => {\n var promises = [];\n files.forEach(filename => {\n promises.push(new Promise((resolve,reject) => {\n setTimeout(async function() {\n try {\n const buf = await webR.getFileData(filename);\n const extension = filename.match(/\\.[^.]*$/)[0];\n const mime_type = mime_types[extension] || 'text/plain';\n var blob = new Blob([buf], {type: mime_type});\n if(mime_type == 'text/plain' || mime_type == 'image/svg+xml') {\n const text = await blob.text();\n resolve({exists: true, text: text, mime_type});\n } else {\n resolve({exists: true, blob: URL.createObjectURL(blob), mime_type});\n }\n } catch(err) {\n resolve({exists: false, error: err.message});\n }\n },10);\n }));\n });\n const results = await Promise.all(promises);\n var o = {};\n results.forEach((value,i) => { o[files[i]] = jme.wrapValue(value); });\n return {\n r_files: new Numbas.jme.types.TDict(o)\n }\n}));"}, "show_pdf": {"parameters": [["url", "string"]], "type": "html", "language": "jme", "definition": "html(\"\"\"\"\"\")"}, "show_svg": {"parameters": [["text", "string"]], "type": "html", "language": "jme", "definition": "html(text)"}, "r_load_package": {"parameters": [["name", "string"]], "type": "anything", "language": "javascript", "definition": "return new Numbas.jme.types.TPromise(Numbas.extensions.programming.language_runners['webr'].load_webR().then(async (webR) => {\n await webR.loadPackage(name);\n return {};\n}));"}}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide', ['matplotlib']);", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": true, "customName": "Make a plot in Python", "marks": "0", "scripts": {}, "customMarkingAlgorithm": "mark:\n feedback(\"Here's your figure:\");\n feedback(html(code_result[4][\"stdout\"])) ", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": false, "showFeedbackIcon": false, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Make a plot using matplotlib. I've already set up a figure, called fig.

\n

{code_block(python_plot_example,\"python\")}

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "import sys\nimport matplotlib\n\nmatplotlib.use('Agg')\nimport matplotlib.pyplot as plt\nfig = plt.figure()\nfig.savefig(sys.stdout, format='svg')", "postamble": "fig.savefig(sys.stdout, format='svg')", "tests": "[\n [\"Test 1\", 1, \"True\"]\n]", "validation_tests": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Exploration activity: Define a class, add methods to it, then use it", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}, {"name": "Aamir Khan", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/4537/"}], "tags": [], "metadata": {"description": "

In four parts, the student builds up the definition of a class representing a rectangle. First they write the constructor, then add methods to compute area and perimeter.

\n

In the final part, they must use the methods to write a function which determines if a rectangle's area is larger than its perimeter.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"last_code": {"name": "last_code", "group": "Ungrouped variables", "definition": "\"# Preamble (this will get replaced)\"", "description": "", "templateType": "anything", "can_override": false}, "validation1": {"name": "validation1", "group": "Ungrouped variables", "definition": "[\n [\"Rectangle is defined\", \"'Rectangle' in locals()\"],\n [\"Rectangle is a class\", \"type(Rectangle) == type\"],\n [\"Rectangle has a width attribute\", \"hasattr(Rectangle(1,2),'width')\"],\n [\"Rectangle has a height attribute\", \"hasattr(Rectangle(1,2),'height')\"],\n]", "description": "

Validation tests for the first part, testing that the class is defined.

", "templateType": "anything", "can_override": false}, "validation_area": {"name": "validation_area", "group": "Ungrouped variables", "definition": "validation1 + [\n [\"Rectangle has a method 'area'\", \"hasattr(Rectangle,'area')\"]\n]", "description": "

Validation tests for the second part, testing that the Rectangle class has an area method.

", "templateType": "anything", "can_override": false}, "validation_perimeter": {"name": "validation_perimeter", "group": "Ungrouped variables", "definition": "validation_area + [\n [\"Rectangle has a method 'perimeter'\", \"hasattr(Rectangle,'perimeter')\"]\n]", "description": "

Validation tests for the third part, checking that the class has a perimeter method.

", "templateType": "anything", "can_override": false}, "validation_check_rectangle": {"name": "validation_check_rectangle", "group": "Ungrouped variables", "definition": "[\n [\"check_rectangle is defined\", \"'check_rectangle' in locals()\"]\n]", "description": "", "templateType": "anything", "can_override": false}, "postamble": {"name": "postamble", "group": "Ungrouped variables", "definition": "safe(\"# Test variables \\nfrom random import randrange, random\\n\\ndef random_rect():\\n width = randrange(2,10)\\n height = random()*8+2\\n r = Rectangle(width,height)\\n return (r, width, height)\")", "description": "", "templateType": "long plain string", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["last_code", "validation1", "validation_area", "validation_perimeter", "validation_check_rectangle", "postamble"], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('pyodide');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": true, "customName": "Create the Rectangle class", "marks": "5", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [{"label": "Add an area method", "rawLabel": "", "otherPart": 1, "variableReplacements": [{"variable": "last_code", "definition": "interpreted_answer"}], "availabilityCondition": "answered and credit=1", "penalty": "", "penaltyAmount": 0, "showPenaltyHint": true, "lockAfterLeaving": false}, {"label": "info", "rawLabel": "", "otherPart": 4, "variableReplacements": [], "availabilityCondition": "", "penalty": "", "penaltyAmount": 0, "showPenaltyHint": true, "lockAfterLeaving": false}], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": "Create the Rectangle class", "prompt": "

Create a class Rectangle with an __init__ method to set attributes width and height.

\n

It should be possible to call your class like this

\n

{code_block(\"r = Rectangle(2,3)\",[\"language\":\"python\"])}

\n

to create an object r representing a 2 x 3 rectangle.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "class Rectangle:\n def __init__(self, width, height):\n self.width = width\n self.height = height ", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "{postamble}\n\nr, width, height = random_rect()", "tests": "[\n [\"Rectangle class exists\", 1/5, \"isinstance(r, Rectangle)\"],\n [\"width is defined\", 1/5, \"hasattr(r,'width')\"],\n [\"width attribute is correct\", 1/5, \"r.width == width\"],\n [\"height is defined\", 1/5, \"hasattr(r,'height')\"],\n [\"height attribute is correct\", 1/5, \"r.height == height\"]\n]", "validation_tests": "validation1", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": true, "customName": "Add an area method", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [{"label": "Add a perimeter method", "rawLabel": "", "otherPart": 2, "variableReplacements": [{"variable": "last_code", "definition": "interpreted_answer"}], "availabilityCondition": "answered and credit=1", "penalty": "", "penaltyAmount": 0, "showPenaltyHint": true, "lockAfterLeaving": false}], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": "Add methods", "prompt": "

Add an area method to the class, such that, for example

\n

{code_block(\"r = Rectangle(2,3)\\nr.area()\",[\"language\":\"python\"])}

\n

would return the value 6.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "class Rectangle:\n def __init__(self, width, height):\n self.width = width\n self.height = height \n \n def area(self):\n return self.width * self.height", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "{last_code}", "modifier": "", "preamble": "", "postamble": "{postamble}\n\ndef test_area():\n r, width, height = random_rect()\n return r.area() == width*height", "tests": "[\n [\"Area method returns the area.\", 1, \"all(test_area() for i in range(10))\"],\n]", "validation_tests": "validation_area", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": true, "customName": "Add a perimeter method", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [{"label": "Use the class", "rawLabel": "", "otherPart": 3, "variableReplacements": [{"variable": "last_code", "definition": "interpreted_answer"}], "availabilityCondition": "answered and credit=1", "penalty": "", "penaltyAmount": 0, "showPenaltyHint": true, "lockAfterLeaving": false}], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": "Add methods", "prompt": "

The perimeter $p$ of a rectangle with side lengths $w$ and $h$ is

\n

\\[ p = 2w + 2h \\]

\n

Add a perimeter method to the class, such that, for example

\n

{code_block(\"r = Rectangle(2,3)\\nr.area()\",[\"language\":\"python\"])}

\n

would return the value 12.

\n

Keep the area method that you defined in the last part.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "class Rectangle:\n def __init__(self, width, height):\n self.width = width\n self.height = height \n \n def area(self):\n return self.width * self.height \n\n def perimeter(self):\n return 2*(self.width + self.height)", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "{last_code}", "modifier": "", "preamble": "", "postamble": "{postamble}\n\ndef test_perimeter():\n r, width, height = random_rect()\n return r.perimeter() == 2*(width + height)", "tests": "[\n [\"Perimeter method returns the perimeter.\", 1, \"all(test_perimeter() for i in range(10))\"],\n]", "validation_tests": "validation_perimeter", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": true, "customName": "Use the class", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": "Use the class", "prompt": "

Write a function check_rectangle(r) which takes an instance of your Rectangle class and returns True if its area is bigger than its perimeter.

", "settings": {"show_input_hint": true, "code_language": "pyodide", "correct_answer": "", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "def check_rectangle(r):\n pass", "modifier": "", "preamble": "{last_code}", "postamble": "{postamble}\n\ndef test_fn():\n r, width, height = random_rect()\n print(width, height, width*height > 2*(width+height))\n return check_rectangle(r) == (width*height > 2*(width+height))", "tests": "[\n [\"check_perimeter classifies some random rectangles correctly\", 1, \"all(test_fn() for i in range(10))\"],\n [\"returns False when area equals perimeter\", 1, \"check_rectangle(Rectangle(4,4))==False\"]\n]", "validation_tests": "validation_check_rectangle", "variables": "dict()"}}, {"type": "information", "useCustomName": true, "customName": "info", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": true, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

info

"}], "partsMode": "explore", "maxMarks": 0, "objectives": [{"name": "Create the Rectangle class", "limit": "5"}, {"name": "Add methods", "limit": "2"}, {"name": "Use the class", "limit": 1}], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}]}, {"name": "R", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": ["Assign a variable", " Write an R function to approximate $e$", " Query the built-in mtcars dataset", "Make a plot"], "variable_overrides": [[], [], [], []], "questions": [{"name": "Assign a variable", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}], "tags": [], "metadata": {"description": "

The student must write R code to assign the given value to the variable x.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "

In R, there are two common ways of assigning a variable:

\n

{code_block(\"x = \"+target,\"r\")}

\n

and

\n

{code_block(\"x <- \"+target,\"r\")}

\n

Both methods are equivalent.

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"target": {"name": "target", "group": "Ungrouped variables", "definition": "random(0 .. 100#1)", "description": "", "templateType": "randrange", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["target"], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('webr');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Set x equal to {target}.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "x <- {target}", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"x is equal to {target}\", 1, \"x=={target}\"]\n]", "validation_tests": "[\n [\"x exists\", \"exists('x')\"]\n]", "variables": "[\"target\":target]"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Write an R function to approximate $e$", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}], "tags": [], "metadata": {"description": "

In the first part, the student must write an R function to compute the first $n$ terms of the series $\\frac{1}{k!}$.

\n

In the second part, they must use that function to calculate an approximation to $e$ using a given number of terms of the series.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "

A fun approximation for the mathematical constant $e$ is,

\n

\\[e \\approx 1+\\displaystyle\\sum_{k=1}^{n}\\frac{1}{k!}\\]

\n

Let's calculate it using this method in R!

", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"randn": {"name": "randn", "group": "Ungrouped variables", "definition": "random(2..13)", "description": "

The number of terms of the series to compute.

", "templateType": "anything", "can_override": false}, "series_function": {"name": "series_function", "group": "Ungrouped variables", "definition": "safe(\"series <- function(n) {\\n k = 1:n\\n Sn = 1/factorial(k)\\n return(Sn)\\n}\")", "description": "", "templateType": "long plain string", "can_override": false}, "series_placeholder": {"name": "series_placeholder", "group": "Ungrouped variables", "definition": "safe(\"series = function(n){\\n # Complete the function\\n}\")", "description": "

The initial code for the first part, where the student has to write a function to compute the series $\\frac{1}{k!}$.

", "templateType": "long plain string", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["randn", "series_function", "series_placeholder"], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('webr', ['svglite']);", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

First, write a function named series that takes an argument n and returns $[S_1, S_2,\\dots S_n]$ as a vector, where $S_k = \\frac{1}{k!}$.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "{series_function}", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": false, "show_marking_errors": false, "placeholder": "{series_placeholder}", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"series function works\", 1, \"\"\"all.equal(series(7),1/factorial(1:7))\"\"\"]\n]", "validation_tests": "[\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [{"variable": "series_function", "part": "p0", "must_go_first": false}], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Next, use your function to appoximate $e$ using the appoximation above, using a value of $n=\\var{randn}$. Save this into the variable named eapprox.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "eapprox = 1+sum(series({randn}))", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "eapprox <- ", "modifier": "", "preamble": "{series_function}", "postamble": "", "tests": "[\n [\"e approximation is correct\", 1, \"eapprox == (1+sum(1/factorial(1:randn)))\"]\n]", "validation_tests": "[\n [\"eapprox exists\", \"exists('eapprox')\"]\n]", "variables": "dict('randn': randn)"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Query the built-in mtcars dataset", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}], "tags": [], "metadata": {"description": "

Several questions on interrogating the mtcars dataset built in to R.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "

The Motor Trend Car Road Tests data frame is built into R with the variable name mtcars.

\n

Before answering this question, first get a feel for the structure of the dataset by using commands such as head(mtcars) and help(mtcars).

", "advice": "

a)

\n

{code_block(part_a_answer,\"r\")}

\n

b)

\n

{code_block(part_b_answer,\"r\")}

\n

c)

\n

{code_block(part_c_answer,\"r\")}

\n

d)

\n

To calculate the maximum horsepower, run

\n

{code_block(part_d_code,\"r\")}

\n

e)

\n

To calculate the mean mpg of cars with 8 cylinders, run

\n

{code_block(part_e_code,\"r\")}

\n

f)

\n

To calculate the 75% quantile, run

\n

{code_block(part_f_code,\"r\")}

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"num_gears": {"name": "num_gears", "group": "Ungrouped variables", "definition": "random(3..5)", "description": "", "templateType": "anything", "can_override": false}, "disp_val": {"name": "disp_val", "group": "Ungrouped variables", "definition": "20*random(5..20)", "description": "", "templateType": "anything", "can_override": false}, "num_cyl": {"name": "num_cyl", "group": "Ungrouped variables", "definition": "random([4,6,8])", "description": "", "templateType": "anything", "can_override": false}, "part_a_answer": {"name": "part_a_answer", "group": "Ungrouped variables", "definition": "safe(\"gears = mtcars[mtcars$gear == {num_gears},]\")", "description": "", "templateType": "long plain string", "can_override": false}, "part_b_answer": {"name": "part_b_answer", "group": "Ungrouped variables", "definition": "safe(\"displ = mtcars[mtcars$disp>300,]\")", "description": "", "templateType": "long plain string", "can_override": false}, "part_c_answer": {"name": "part_c_answer", "group": "Ungrouped variables", "definition": "safe(\"mercs = mtcars[grep(\\'Merc\\', rownames(mtcars)),]\")", "description": "", "templateType": "long plain string", "can_override": false}, "part_d_code": {"name": "part_d_code", "group": "Ungrouped variables", "definition": "safe(\"max(mtcars$hp)\")", "description": "", "templateType": "long plain string", "can_override": false}, "part_e_code": {"name": "part_e_code", "group": "Ungrouped variables", "definition": "safe(\"mean(mtcars[mtcars$cyl == 8,]$mpg)\")", "description": "", "templateType": "long plain string", "can_override": false}, "part_f_code": {"name": "part_f_code", "group": "Ungrouped variables", "definition": "safe(\"as.numeric(quantile(mtcars[mtcars$cyl==4,]$mpg,0.75))\")", "description": "", "templateType": "long plain string", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["num_gears", "disp_val", "num_cyl", "part_a_answer", "part_b_answer", "part_c_answer", "part_d_code", "part_e_code", "part_f_code"], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('webr');", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write an R command to create new data frame named gears that contains only the cars with {num_gears} gears.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "{part_a_answer}", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "gears = ", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"Correct data frame\", 1, \"identical(gears, mtcars[mtcars$gear == num_gears,])\"]\n]", "validation_tests": "[\n [\"Data frame 'gears' exists\", \"exists('gears')\"]\n]", "variables": "['num_gears': num_gears]"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write an R command to create new data frame named displ that contains only the cars with more than {disp_val} cu.in. of displacement.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "{part_b_answer}", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "displ =", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"Correct data frame\", 1, \"identical(displ, mtcars[mtcars$disp>disp_val,])\"]\n]", "validation_tests": "[\n [\"Data frame 'displ' exists\", \"exists('displ')\"]\n]", "variables": "['disp_val':disp_val]"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write an R command to create new data frame named mercs that contains only the cars with \"Merc\" in their name.

\n

Hint: investigate the grep() function using R's help pages.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "{part_c_answer}", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "mercs =", "modifier": "", "preamble": "", "postamble": "", "tests": "[\n [\"Correct data frame\", 1, \"identical(mercs, mtcars[grep('Merc', rownames(mtcars)),])\"]\n]", "validation_tests": "[\n [\"Data frame 'mercs' exists\", \"exists('mercs')\"]\n]", "variables": "dict()"}}, {"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "pre_submit:\n[run_code(\"webr\",[part_d_code])]\n\ntarget: dec(\n replace_regex(safe(\"\\\\[1\\\\] \"),\"\",pre_submit[\"code_result\"][0][\"stdout\"],\"g\")\n)\n\nminvalue: target\n\nmaxvalue: target", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": false, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Find the the maximum gross horsepower in the full mtcars dataset.

", "minValue": "1", "maxValue": "1", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "pre_submit:\n[\n run_code(\"webr\",[part_e_code])\n]\n\n\ntarget: dec(\n replace_regex(safe(\"\\\\[1\\\\] \"),\"\",pre_submit[\"code_result\"][0][\"stdout\"],\"g\")\n)\n\nminvalue: target\n\nmaxvalue: target", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": false, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Find the mean mpg of cars with 8 cylinders.

", "minValue": "1", "maxValue": "1", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "precisionType": "dp", "precision": "1", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "pre_submit:\n[run_code(\"webr\",[part_f_code])]\n\ntarget: dec(\n replace_regex(safe(\"\\\\[1\\\\] \"),\"\",pre_submit[\"code_result\"][0][\"stdout\"],\"g\")\n)\n\nminvalue: target\n\nmaxvalue: target", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": false, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Find the 75% quantile of the mpg of cars with 4 cylinders.

", "minValue": "1", "maxValue": "1", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "precisionType": "dp", "precision": "1", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Make a plot", "extensions": ["programming"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "George Stagg", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/930/"}, {"name": "Aamir Khan", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/4537/"}], "tags": [], "metadata": {"description": "

Demonstrates how to display a plot generated in R.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"write_file_example": {"name": "write_file_example", "group": "Ungrouped variables", "definition": "safe(\"txt <- \\\"Hello World\\\"\\nwriteLines(txt, \\\"thing.txt\\\")\")", "description": "", "templateType": "long plain string", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["write_file_example"], "variable_groups": [], "functions": {}, "preamble": {"js": "Numbas.extensions.programming.preload('webr', ['svglite']);", "css": ""}, "parts": [{"type": "mark-code-3", "useCustomName": true, "customName": "Make a plot in R", "marks": "0", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": false, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write some R code to make a plot. Something like this should do the job:

\n

{code_block(\"hist(rnorm(1000,10,1))\", \"r\")}

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(svglite)\nsvg()", "postamble": "dev_result <- dev.off() # dev.off() returns some info that we don't care about, so it's assigned to a variable to prevent it from being printed out", "postamble_feedback_whitespace": false, "tests": "[\n\n]", "validation_tests": "[\n \n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}]}], "allowPrinting": true, "navigation": {"allowregen": true, "reverse": true, "browse": true, "allowsteps": true, "showfrontpage": false, "showresultspage": "oncompletion", "navigatemode": "menu", "onleave": {"action": "none", "message": ""}, "preventleave": false, "startpassword": "", "allowAttemptDownload": false, "downloadEncryptionKey": ""}, "timing": {"allowPause": true, "timeout": {"action": "none", "message": ""}, "timedwarning": {"action": "none", "message": ""}}, "feedback": {"showactualmark": true, "showtotalmark": true, "showanswerstate": true, "allowrevealanswer": true, "advicethreshold": 0, "intro": "

This exam collects some questions demonstrating the programming extension for Numbas.

\n

The extension is being developed on GitHub; if you have any questions about how to use it, notice a bug, or have a feature request, please file an issue there.

", "end_message": "", "reviewshowscore": true, "reviewshowfeedback": true, "reviewshowexpectedanswer": true, "reviewshowadvice": true, "feedbackmessages": []}, "diagnostic": {"knowledge_graph": {"topics": [], "learning_objectives": []}, "script": "diagnosys", "customScript": ""}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "Aamir Khan", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/4537/"}], "extensions": ["programming", "stats"], "custom_part_types": [{"source": {"pk": 195, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/195/edit"}, "name": "Code", "short_name": "mark-code-3", "description": "

Mark code provided by the student by running it and a series of validation and marking tests.

\n

The validation tests are used to reject an answer if the student has misunderstood the task, for example if they haven't defined a required variable or function.

\n

Marking tests check properties of the student's code. Each test awards a proportion of the available credit if it is passed.

\n

You can optionally show the student the STDOUT and/or STDERR when running their code.

\n

You can give a preamble and postamble which are run before and after the student's code, and also modify the student's code before running it.

", "help_url": "", "input_widget": "code-editor", "input_options": {"correctAnswer": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"correct_answer\"])\n,\n settings[\"correct_answer\"]\n)", "hint": {"static": false, "value": "\"Write \"+capitalise(language_synonym(settings[\"code_language\"]))+\" code\""}, "language": {"static": false, "value": "language_synonym(settings[\"code_language\"])"}, "placeholder": {"static": false, "value": "if(settings[\"correct_answer_subvars\"],\n render(settings[\"placeholder\"])\n,\n settings[\"placeholder\"]\n)"}, "theme": {"static": true, "value": "textmate"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\napply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)\n\ninterpreted_answer:\nstudentAnswer\n\nmain_result:\ncode_result[3]\n\nmarking_results:\ncode_result[6..(len(settings[\"tests\"])+6)]\n\nvalidation_results:\ncode_result[(len(settings[\"tests\"])+6)..len(code_result)]\n\nmain_error:\nassert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)\n\nmarking_test_feedback:\nmap(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)\n\nvalidation_test_feedback:\nmap(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)\n\ntotal_weight:\nsum(map(weight,[name,weight,code],settings[\"tests\"]))\n\npre_submit:\n[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]\n\ncode_result:\npre_submit[\"code_result\"]\n\nmain_stdout:\nsafe(main_result[\"stdout\"])\n\ncode_language:\nsettings[\"code_language\"]\n\npreamble_result:\ncode_result[2]\n\npreamble_stderr:\npreamble_result[\"stderr\"]\n\npostamble_result:\ncode_result[4]\n\npostamble_stderr:\npostamble_result[\"stderr\"]\n\npostamble_feedback:\nassert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)\n\nmatplotlib_preamble:\nif(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)\n\nmatplotlib_postamble:\nswitch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)\n\nmatplotlib_result:\ncode_result[5]\n\nmatplotlib_feedback:\nswitch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n\n\nimages:\nflatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))\n\nshow_images:\nassert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "apply(main_error);\napply(show_images);\napply(matplotlib_feedback);\napply(postamble_feedback);\napply(validation_test_feedback);\napply(marking_test_feedback)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "main_result", "description": "

The result of running the student's code and the preamble, without any tests.

\n

Normally used to detect errors in the student's code.

", "definition": "code_result[3]"}, {"name": "marking_results", "description": "

The results of running the marking tests.

", "definition": "code_result[6..(len(settings[\"tests\"])+6)]"}, {"name": "validation_results", "description": "

The results of running the validation tests.

", "definition": "code_result[(len(settings[\"tests\"])+6)..len(code_result)]"}, {"name": "main_error", "description": "

Show STDOUT if allowed.

\n

Check the student's code runs on its own. Fail if there was an error, and show STDERR if allowed.

", "definition": "assert(main_stdout=\"\" or not settings[\"show_stdout\"],\n feedback(\"Your code produced this output:
{escape_html(main_stdout)}
\")\n);\nassert(main_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in your code:
{escape_html(main_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in your code.\")\n )\n)"}, {"name": "marking_test_feedback", "description": "

Feedback on the marking tests. For each test, if the test was passed then add the corresponding amount of credit. If there was an error, show the error.

", "definition": "map(\n let(\n [name,weight,code], test,\n header, \"Test: {name} \",\n if(r[\"success\"],\n let(\n result, r[\"result\"],\n max_credit, weight/total_weight,\n credit, if(result isa \"number\", result, award(1,result)),\n switch(\n credit=0, negative_feedback(header+\"was not passed.\"),\n credit=1, add_credit(max_credit, header+\"was passed.\"),\n add_credit(credit*max_credit, header+\"was partially passed.\")\n )\n )\n ,\n if(settings[\"show_marking_errors\"],\n negative_feedback(\"\"\"There was an error:
{escape_html(r[\"stderr\"])}
\"\"\")\n ,\n negative_feedback(header+\"was not passed.\")\n )\n )\n ),\n [test,r],\n zip(settings[\"tests\"],marking_results)\n)"}, {"name": "validation_test_feedback", "description": "

Give feedback on the validation tests. If any of them are not passed, the student's answer is invalid.

", "definition": "map(\n let([name,code], test,\n if(r[\"success\"],\n if(r[\"result\"],\n true\n ,\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n fail(\"\"\"There was an error running the test {name}:
{escape_html(r[\"stderr\"])}
\"\"\")\n )\n ),\n [test,r],\n zip(settings[\"validation_tests\"],validation_results)\n)"}, {"name": "total_weight", "description": "

The sum of the weights of the marking tests. Each test's weight is divided by this to produce a proportion of the available credit.

", "definition": "sum(map(weight,[name,weight,code],settings[\"tests\"]))"}, {"name": "pre_submit", "description": "

The code blocks to run.

\n

In order, they are:

\n", "definition": "[run_code(code_language,\n [\n matplotlib_preamble,\n variables_as_code(language_synonym(code_language), settings[\"variables\"]),\n render(settings[\"preamble\"]),\n if(trim(settings[\"modifier\"])=\"\", studentAnswer, eval(expression(settings[\"modifier\"]))),\n render(settings[\"postamble\"]),\n matplotlib_postamble\n ]\n +map(code,[name,marks,code],settings[\"tests\"])\n +map(code,[name,code],settings[\"validation_tests\"])\n)]"}, {"name": "code_result", "description": "

The results of the code blocks: a list with an entry corresponding to each block of code.

", "definition": "pre_submit[\"code_result\"]"}, {"name": "main_stdout", "description": "

The stdout from the student's code.

", "definition": "safe(main_result[\"stdout\"])"}, {"name": "code_language", "description": "

The language the code is written in. Either \"pyodide\" (Python) or \"webr\" (R)

", "definition": "settings[\"code_language\"]"}, {"name": "preamble_result", "description": "

The result of running the preamble block.

", "definition": "code_result[2]"}, {"name": "preamble_stderr", "description": "

The STDERR produced by the preamble block.

", "definition": "preamble_result[\"stderr\"]"}, {"name": "postamble_result", "description": "

The result of running the postamble.

", "definition": "code_result[4]"}, {"name": "postamble_stderr", "description": "

The STDERR produced by the postamble block.

", "definition": "postamble_result[\"stderr\"]"}, {"name": "postamble_feedback", "description": "

Show the STDOUT from the postamble, if there is any.

", "definition": "assert(postamble_result[\"stdout\"]=\"\",\n feedback(\n if(settings[\"postamble_feedback_whitespace\"],\n html(\"\"\"
{escape_html(postamble_result[\"stdout\"])}
\"\"\")\n ,\n postamble_result[\"stdout\"]\n )\n )\n);\nassert(postamble_result[\"success\"],\n if(settings[\"show_stderr\"],\n fail(\"\"\"There was an error in the marking routine postamble:
{escape_html(postamble_result[\"stderr\"])}
\"\"\")\n ,\n fail(\"There was an error in the marking routine postamble.\")\n )\n)"}, {"name": "matplotlib_preamble", "description": "

Preamble for a hack to ensure that figures produced by matplotlib in Python are displayed.

\n

This code clears the matplotlib output, if matplotlib has been loaded.

", "definition": "if(code_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n plt.clf() \n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_postamble", "description": "

A hack to show any figures produced with matplotlib in the stdout.

", "definition": "switch(\ncode_language=\"pyodide\",\n safe(\"\"\"\nimport sys\nif 'matplotlib' in sys.modules:\n import matplotlib.pyplot as plt\n fig = plt.gcf()\n if fig.get_axes():\n fig.savefig(sys.stdout, format='svg')\n\"\"\"),\n \"\"\n)"}, {"name": "matplotlib_result", "description": "

The result of running the matplotlib hack.

", "definition": "code_result[5]"}, {"name": "matplotlib_feedback", "description": "

Feedback from the matplotlib hack: if a figure is produced, it's displayed as SVG here.

", "definition": "switch(\ncode_language=\"pyodide\",\n assert(matplotlib_result[\"stdout\"]=\"\",\n feedback(matplotlib_result[\"stdout\"])\n ),\n \"\"\n)\n\n"}, {"name": "images", "description": "

Any images produced by the code blocks.

", "definition": "flatten(map(\n get(r,\"images\",[]),\n r,\n code_result\n))"}, {"name": "show_images", "description": "

Show the images produced by the code.

", "definition": "assert(len(images)=0 or not settings[\"show_stdout\"],\n feedback(\"Your code produced the following {pluralise(len(images),'image','images')}:\");\n map(\n feedback(html(x)),\n x,\n images\n )\n)"}], "settings": [{"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "code_language", "label": "Code language", "help_url": "", "hint": "The language that the student's code will be written in.", "input_type": "dropdown", "default_value": "pyodide", "choices": [{"value": "pyodide", "label": "Python"}, {"value": "webr", "label": "R"}]}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "correct_answer_subvars", "label": "Substitute question variables into the correct answer?", "help_url": "", "hint": "If ticked, then JME expressions between curly braces will be evaluated and substituted into the correct answer.

If not ticked, then the correct answer will be displayed exactly as it is.", "input_type": "checkbox", "default_value": true}, {"name": "show_stdout", "label": "Show stdout?", "help_url": "", "hint": "If ticked, the STDOUT produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_stderr", "label": "Show stderr?", "help_url": "", "hint": "If ticked, the STDERR produced after running the student's code will be shown in the feedback.", "input_type": "checkbox", "default_value": true}, {"name": "show_marking_errors", "label": "Show errors produced by marking tests?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "placeholder", "label": "Placeholder", "help_url": "", "hint": "Initial text for the code editor", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "modifier", "label": "Student code modifier", "help_url": "", "hint": "JME expression to modify the student's submitted code before being passed to the marking template. The student's code is available as the string variable studentAnswer.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "preamble", "label": "Preamble", "help_url": "", "hint": "This code is run before the student's code. Define anything that the student's code or your tests need.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble", "label": "Postamble", "help_url": "", "hint": "This code is run after the student's code but before the validation and unit tests.", "input_type": "code", "default_value": "", "evaluate": false}, {"name": "postamble_feedback_whitespace", "label": "Format postamble output as code?", "help_url": "", "hint": "If ticked, any output produced by the postamble will be formatted in monospace font, with whitespace preserved. If not ticked, it'll be presented as prose text or HTML.", "input_type": "checkbox", "default_value": false}, {"name": "tests", "label": "Marking tests", "help_url": "", "hint": "A list of tests used to mark the student's answer.
Each item is a list with three values:
\n", "input_type": "code", "default_value": "[\n [\"Test 1\", 1, \"True\"]\n]", "evaluate": true}, {"name": "validation_tests", "label": "Validation tests", "help_url": "", "hint": "

A list of tests used to validate that the student's code is acceptable.
Each item is a list with two string values:

\n", "input_type": "code", "default_value": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "evaluate": true}, {"name": "variables", "label": "Variables to include in code", "help_url": "", "hint": "Give a dictionary mapping variable names to their values. These variables will be available in the code that is run.", "input_type": "code", "default_value": "dict()", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["programming"]}], "resources": []}