// Numbas version: finer_feedback_settings {"name": "MAS2908 Problem Solving Exercises 1", "metadata": {"description": "", "licence": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International"}, "duration": 0, "percentPass": 0, "showQuestionGroupNames": false, "shuffleQuestionGroups": false, "showstudentname": true, "question_groups": [{"name": "Question 1", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": [""], "variable_overrides": [[]], "questions": [{"name": "ggplots with moneydemand", "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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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:\nif(studentAnswer=nothing,\n []\n,\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)\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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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": "if(studentAnswer=nothing,\n []\n,\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)"}, {"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": "Clement Lee", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/21320/"}], "tags": [], "metadata": {"description": "", "licence": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International"}, "statement": "

You will need to use ggplot2 functions and the money demand dataset for this question. Download moneydemand.csv from the assignment page on Canvas. The dataset is a multivariate yearly time series with the following variables:

\n", "advice": "

library(ggplot2)
library(readr)

\n

ggplot(md, aes(x = logM, y = logYp)) +
  geom_point() +
  labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")

\n

ggplot(md, aes(x = year, y = Rs)) +
  geom_line() +
  geom_point() +
  labs(y = \"short term interest rate\")

\n

ggplot(md, aes(x = Rm)) +
  geom_histogram(binwidth = 0.3) +
  labs(x = \"rate of return on money\")

\n

ggplot(md, aes(x = year, y = logYp, colour = logSpp)) +
  geom_line() +
  scale_colour_viridis_b() +
  labs(y = \"log(real permanent income)\", colour = \"rate variability\")

\n

ggplot(md, aes(x = Rs, y = logM, size = Rm)) +
  geom_point() +
  labs(
    x = \"short term interest rate\",
    y = \"log(quantity of money)\",
    size = \"rate of return on money\"
  )

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true, "j": false}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "", "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 code to load the packages ggplot2 and readr.

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "library(ggplot2)\nlibrary(readr)", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "", "postamble": "si <- names(sessionInfo()$otherPkgs)", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct packages via library()\", \n 1, \n \"'readr' %in% si && 'ggplot2' %in% si\"]\n]", "validation_tests": "[\n [\"arithmetic works\", \"1+1 == 2\"]\n]", "variables": "dict()"}}, {"type": "information", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Run the above code i.e. copy your answers to RStudio console and press Enter. Next, run the following code to create the data frame md:

\n

md <- read_csv(\"moneydemand.csv\")

"}, {"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": "

The following code produces a scatterplot of logYp against logM:

\n

md |> ggplot() +
  geom_point(aes(x = logM, y = logYp)) +
  labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")

\n

Write code to simultaneously do the following:

\n
    \n
  1. create the same scatterplot, but with the use of the aes() function in ggplot(), and
  2. \n
  3. keep the axis labels the same as above.
  4. \n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = logM, y = logYp)) + \n geom_point() + \n labs(x = \"log(quantity of money)\", y = \"log(real permanent income)\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct place of aes()\", \n 1, \n \"identical(as.character(student_answer$mapping)[1:2], c('~logM', '~logYp')) &&\n identical(names(student_answer$mapping)[1:2], c('x', 'y'))\"],\n [\"Correct labels\",\n 1,\n \"identical(str_to_lower(student_answer$labels$x), 'log(quantity of money)') &&\n identical(str_to_lower(student_answer$labels$y), 'log(real permanent income)')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"],\n [\"Is a point plot\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint')\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

We would like to make a point and line plot of Rs over year. However, the following code produces an error:

\n

ggplot(md) + geom_line(aes(x = year, y = Rs)) + geom_point()

\n

Write code to simultaneously do the following:

\n
    \n
  1. fix the error and create the correct plot, and
  2. \n
  3. label the y-axis \"short term interest rate\".
  4. \n
", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "aes in both geoms", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md) + \n geom_line(aes(x = year, y = Rs)) + \n geom_point(aes(x = year, y = Rs)) + \n labs(y = \"short term interest rate\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()", "postamble_feedback_whitespace": false, "tests": "[\n [\"both geoms\", \n 1, \n \"identical(\n sort(sapply(student_answer$layers, function(x) class(x$geom)[1])), \n c('GeomLine', 'GeomPoint')\n )\"],\n [\"correct places of aes\", \n 1, \n \"identical(as.character(student_answer$layers[[1]]$mapping), c('~year', '~Rs')) &&\n identical(as.character(student_answer$layers[[2]]$mapping), c('~year', '~Rs')) &&\n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y')) &&\n identical(names(student_answer$layers[[2]]$mapping), c('x', 'y'))\n \"],\n [\"correct y-axis label\",\n 1,\n \"identical(student_answer$labels$y, 'short term interest rate')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = year, y = Rs)) + \n geom_line() + \n geom_point() + \n labs(y = \"short term interest rate\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)", "postamble_feedback_whitespace": false, "tests": "[\n [\"both geoms\", \n 1, \n \"identical(\n sort(sapply(student_answer$layers, function(x) class(x$geom)[1])), \n c('GeomLine', 'GeomPoint')\n )\n \"],\n [\"correct place of aes\", \n 1, \n \"identical(as.character(student_answer$mapping)[1:2], c('~year', '~Rs')) && \n identical(names(student_answer$mapping)[1:2], c('x', 'y'))\n \"],\n [\"correct y-axis label\",\n 1,\n \"identical(str_to_lower(student_answer$labels$y), 'short term interest rate')\"]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write code to simultaneously do the following:

\n
    \n
  1. make a histogram of Rm,
  2. \n
  3. set a sensible binwidth so that the number of bins is between 15 and 20, and
  4. \n
  5. label the x-axis \"rate of return on money\", and
  6. \n
\n

", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rm)) + \n geom_histogram(binwidth = 0.3) + \n labs(x = \"rate of return on money\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": true, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nbw <- student_answer$layers[[1]]$stat_params$binwidth", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct geom (histogram)\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomBar') && \n identical(class(student_answer$layers[[1]]$stat)[[1]], 'StatBin')\"\n ],\n [\"correct x-axis label\",\n 1,\n \"identical(str_to_lower(student_answer$labels$x), 'rate of return on money')\"],\n [\"Appropriate binwidth\", \n 1, \n \"!is.null(bw) && bw >= 0.3 && bw <= 0.5\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "4", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The following code attempts to plot logYp over year and coloured by logSpp:

\n

ggplot(md, aes(x = year, y = logYp, fill = logSpp)) + geom_line()

\n

However, running the code returns a warning, and no colours were displayed.

\n

Write code to simultaneously do the following:

\n
    \n
  1. fix the above issue,
  2. \n
  3. incorporate a binned colour palette for logSpp, and
  4. \n
  5. label the y-axis and colour scale \"log(real permanent income)\" and \"rate variability\", respectively.
  6. \n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = year, y = logYp, colour = logSpp)) + \n geom_line() + \n scale_colour_viridis_b() +\n labs(y = \"log(real permanent income)\", colour = \"rate variability\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\ncolour_list <- student_answer$scales$scales", "postamble_feedback_whitespace": false, "tests": "[\n [\"labels\", \n 1, \n \"identical(str_to_lower(student_answer$labels$y), 'log(real permanent income)') &&\n identical(str_to_lower(student_answer$labels$colour), 'rate variability')\n \"\n ],\n [\"colour as the correct aesthetic\",\n 1,\n \"xor(\n identical(names(student_answer$mapping)[3], 'colour'), \n identical(names(student_answer$layers[[1]]$mapping)[3], 'colour')\n )\"\n ],\n [\"used a colour palette\",\n 1,\n \"(length(colour_list) == 1) && ('colour' %in% colour_list[[1]]$aesthetics)\"\n ],\n [\"binned scale\",\n 1,\n \"('ScaleBinned' %in% class(colour_list[[1]]))\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"],\n [\"Is a line plot\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomLine')\"],\n [\"logSpp as the third variable\",\n \"xor(\n identical(as.character(student_answer$mapping)[3], '~logSpp'), \n identical(as.character(student_answer$layers[[1]]$mapping)[3], '~logSpp')\n )\"\n ]\n]", "variables": "dict()"}}, {"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 code to simultaneously do the following:

\n
    \n
  1. make a scatterplot of logM against Rs,
  2. \n
  3. use an appropriate non-colour aesthetic of the points representing Rm (meaning that the plot stays the same when printed on grey scale), and
  4. \n
  5. label the x-axis, y-axis and the aesthetic scale \"short term interest rate\", \"log(quantity of money)\", and \"rate of return on money\", respectively.
  6. \n
", "alternatives": [{"type": "mark-code-3", "useCustomName": true, "customName": "opacity", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rs, y = logM, alpha = Rm)) + \n geom_point() +\n labs(\n x = \"short term interest rate\", \n y = \"log(quantity of money)\", \n alpha = \"rate of return on money\"\n )", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels", "postamble_feedback_whitespace": false, "tests": "[\n [\"aesthetic\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping), c('~Rs', '~logM', '~Rm')), \n identical(as.character(student_answer$layers[[1]]$mapping), c('~Rs', '~logM', '~Rm'))\n ) && \n xor(\n identical(names(student_answer$mapping), c('x', 'y', 'alpha')), \n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y', 'alpha'))\n )\"\n ],\n [\"labels & point plot\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint') &&\n identical(str_to_lower(sal$x), 'short term interest rate') &&\n identical(str_to_lower(sal$y), 'log(quantity of money)') &&\n identical(str_to_lower(sal$alpha), 'rate of return on money')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(md, aes(x = Rs, y = logM, size = Rm)) + \n geom_point() +\n labs(\n x = \"short term interest rate\", \n y = \"log(quantity of money)\", \n size = \"rate of return on money\"\n )", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lmtest)\nabc <- attributes(moneydemand)$tsp\nmd <- \n as.data.frame(moneydemand)|> \n mutate(year = seq(abc[1], abc[2], by = abc[3])) |> \n select(year, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels", "postamble_feedback_whitespace": false, "tests": "[\n [\"aesthetic\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping), c('~Rs', '~logM', '~Rm')), \n identical(as.character(student_answer$layers[[1]]$mapping), c('~Rs', '~logM', '~Rm'))\n ) && \n xor(\n identical(names(student_answer$mapping), c('x', 'y', 'size')), \n identical(names(student_answer$layers[[1]]$mapping), c('x', 'y', 'size'))\n )\"\n ],\n [\"labels & point plot\", \n 1, \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomPoint') &&\n identical(str_to_lower(sal$x), 'short term interest rate') &&\n identical(str_to_lower(sal$y), 'log(quantity of money)') &&\n identical(str_to_lower(sal$size), 'rate of return on money')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(md, student_answer$data) || \n identical(md, student_answer$layers[[1]]$data)\"]\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}]}, {"name": "Question 2", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": [""], "variable_overrides": [[]], "questions": [{"name": "ggplots with seatbelts data", "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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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:\nif(studentAnswer=nothing,\n []\n,\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)\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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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": "if(studentAnswer=nothing,\n []\n,\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)"}, {"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": "Clement Lee", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/21320/"}], "tags": [], "metadata": {"description": "", "licence": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International"}, "statement": "

You will need to use ggplot2 functions and the seatbelts dataset for this question. Download seatbelts.csv from the assignment page on Canvas. The dataset is a multivariate yearly time series of road casualties in Great Britain, with the following variables:

\n", "advice": "

ggplot(seatbelts, aes(x = date, y = DriversKilled)) +
geom_line() +
labs(x = \"Year\", y = \"Car drivers killed\")

\n

ggplot(seatbelts, aes(x = PetrolPrice, fill = factor(law))) +
geom_histogram() +
scale_fill_manual(values = c(\"0\" = \"#E69F00\", \"1\" = \"#56B4E9\")) +
labs(x = \"Petrol price\", fill = \"Law in effect\")

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true, "j": false}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "information", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Run the code below i.e. copy the code to RStudio console and press Enter.

\n

library(readr)
library(ggplot2)
seatbelts <- read_csv(\"seatbelts.csv\")

"}, {"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": "

We would like to make a line plot of DriversKilled over date. However, the following code produces a plot that is not sensible:

\n

ggplot(seatbelts, aes(DriversKilled, date)) + geom_line()

\n

Write code to simultaneously do the following:

\n
    \n
  1. create the correct plot, and
  2. \n
  3. label the x-axis and y-axis \"Year\" and \"Car drivers killed\", respectively.
  4. \n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(seatbelts, aes(x = date, y = DriversKilled)) +\n geom_line() +\n labs(x = \"Year\", y = \"Car drivers killed\")", "correct_answer_subvars": true, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lubridate)\nseatbelts <- \n as.data.frame(Seatbelts)|> \n mutate(date = as.Date(\"1969-01-01\") + months(seq(nrow(Seatbelts))-1)) |>\n select(date, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct aesthetics\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping)[1:2], c('~date', '~DriversKilled')), \n identical(as.character(student_answer$layers[[1]]$mapping)[1:2], c('~date', '~DriversKilled'))\n ) && \n xor(\n identical(names(student_answer$mapping)[1:2], c('x', 'y')), \n identical(names(student_answer$layers[[1]]$mapping)[1:2], c('x', 'y'))\n )\"\n ],\n [\"Correct labels\", \n 1, \n \"identical(str_to_lower(sal$x), 'year') &&\n identical(str_to_lower(sal$y), 'car drivers killed')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(seatbelts, student_answer$data) || \n identical(seatbelts, student_answer$layers[[1]]$data)\"],\n [\"Is a line plot\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomLine')\"]\n]", "variables": "dict()"}}, {"type": "mark-code-3", "useCustomName": false, "customName": "", "marks": "3", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The following code attempts to plot the histogram of PetrolPrice, coloured by law:

\n

ggplot(seatbelts, aes(x = PetrolPrice, colour = factor(law))) + geom_histogram()

\n

Upon running the code, the colour display is not satisfactory.

\n

Write code to simultaneously do the following:

\n
    \n
  1. fill the interior of the histogram's bars by colours,
  2. \n
  3. incorporate the following fill palette:\n\n
  4. \n
  5. label the x-axis and fill scale \"Petrol price\" and \"Law in effect\", respectively.
  6. \n
", "settings": {"show_input_hint": true, "code_language": "webr", "correct_answer": "ggplot(seatbelts, aes(x = PetrolPrice, fill = factor(law))) + \n geom_histogram() + \n scale_fill_manual(values = c(\"0\" = \"#E69F00\", \"1\" = \"#56B4E9\")) +\n labs(x = \"Petrol price\", fill = \"Law in effect\")", "correct_answer_subvars": false, "show_stdout": true, "show_stderr": true, "show_marking_errors": false, "placeholder": "", "modifier": "", "preamble": "library(ggplot2)\nlibrary(dplyr)\nlibrary(lubridate)\nseatbelts <- \n as.data.frame(Seatbelts)|> \n mutate(date = as.Date(\"1969-01-01\") + months(seq(nrow(Seatbelts))-1)) |>\n select(date, everything())", "postamble": "student_answer <- last_plot()\nlibrary(stringr)\nsal <- student_answer$labels\nscales <- ggplot_build(student_answer)$plot$scales$get_scales(\"fill\")\npalette <- scales$palette(length(scales$get_limits()))", "postamble_feedback_whitespace": false, "tests": "[\n [\"Correct aesthetics\", \n 1, \n \"xor(\n identical(as.character(student_answer$mapping), c('~PetrolPrice', '~factor(law)')), \n identical(as.character(student_answer$layers[[1]]$mapping), c('~PetrolPrice', '~factor(law)'))\n ) && \n xor(\n identical(names(student_answer$mapping), c('x', 'fill')), \n identical(names(student_answer$layers[[1]]$mapping), c('x', 'fill'))\n )\"\n ],\n [\"Fill palette\",\n 1,\n \"identical(as.character(palette), c('#E69F00', '#56B4E9')) &&\n identical(names(palette), c('0', '1'))\"\n ],\n [\"Correct labels\", \n 1, \n \"identical(str_to_lower(sal$x), 'petrol price') &&\n identical(str_to_lower(sal$fill), 'law in effect')\"\n ]\n]", "validation_tests": "[\n [\"Is a ggplot object\",\n \"identical(sort(class(student_answer)), c('gg','ggplot'))\"],\n [\"ggplot object can be built\",\n \"(!inherits(try(ggplot_build(student_answer), silent = TRUE), 'try-error'))\"],\n [\"Correct data\",\n \"identical(seatbelts, student_answer$data) || \n identical(seatbelts, student_answer$layers[[1]]$data)\"],\n [\"Correct geom (histogram)\", \n \"identical(sapply(student_answer$layers, function(x) class(x$geom)[1]), 'GeomBar') && \n identical(class(student_answer$layers[[1]]$stat)[[1]], 'StatBin')\"\n ]\n]", "variables": "dict()"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}]}], "allowPrinting": true, "navigation": {"allowregen": false, "reverse": true, "browse": true, "allowsteps": true, "showfrontpage": true, "navigatemode": "sequence", "onleave": {"action": "none", "message": ""}, "preventleave": true, "typeendtoleave": false, "startpassword": "", "autoSubmit": true, "allowAttemptDownload": false, "downloadEncryptionKey": "", "showresultspage": "review"}, "timing": {"allowPause": true, "timeout": {"action": "none", "message": ""}, "timedwarning": {"action": "none", "message": ""}}, "feedback": {"enterreviewmodeimmediately": false, "showactualmarkwhen": "inreview", "showtotalmarkwhen": "always", "showanswerstatewhen": "inreview", "showpartfeedbackmessageswhen": "inreview", "showexpectedanswerswhen": "inreview", "showadvicewhen": "inreview", "allowrevealanswer": false, "intro": "

These written exercises assess all material taught up to 25/02/2026. The main purpose of this assignment is to provide practice for the exam so please use the feedback you receive in your revision. This assessment is worth 10% of the module.

\n

You will need to use two datasets; download moneydemand.csv and seatbelts.csv from Canvas to your working directory.

\n

Materials and topics covered include lecture notes Chapters 3-5 and practicals 3 and 4.

\n

Follow the instructions on the Numbas assignment and submit appropriate R code to the questions. The expected workflow for each part is:

\n
    \n
  1. You read the question on Numbas.
  2. \n
  3. You do some coding in RStudio to obtain the output required by the question.
  4. \n
  5. You submit the code to Numbas and save the answer.
  6. \n
", "end_message": "", "results_options": {"printquestions": true, "printadvice": true}, "feedbackmessages": [], "reviewshowexpectedanswer": true, "showanswerstate": false, "reviewshowfeedback": true, "showactualmark": false, "showtotalmark": true, "reviewshowscore": true, "reviewshowadvice": true}, "diagnostic": {"knowledge_graph": {"topics": [], "learning_objectives": []}, "script": "diagnosys", "customScript": ""}, "contributors": [{"name": "Clement Lee", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/21320/"}], "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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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:\nif(studentAnswer=nothing,\n []\n,\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)\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 warn(\"\"\"There was an error in your code.\"\"\");\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 warn(\"\"\"Your code failed the test {name}.\"\"\");\n fail(\"\"\"Your code failed the test {name}.\"\"\");false\n )\n ,\n warn(\"\"\"There was an error running the test {name}.\"\"\");\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": "if(studentAnswer=nothing,\n []\n,\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)"}, {"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": []}