// Numbas version: finer_feedback_settings {"name": "PhET springs experiment", "extensions": ["jsxgraph", "sheets"], "custom_part_types": [{"source": {"pk": 242, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/242/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "

An editable spreadsheet. Ranges of cells can be disabled, and you can specify ranges of cells to be marked. A cell is marked correct if its value is equal to the value in the expected answer spreadsheet.

", "help_url": "", "input_widget": "spread-sheet", "input_options": {"correctAnswer": "settings[\"correct_answer\"]", "hint": {"static": true, "value": ""}, "initial_sheet": {"static": false, "value": "disable_cells(settings[\"initial_sheet\"], settings[\"disable_ranges\"])"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "correctAnswer:\nsettings[\"correct_answer\"]\n\nmark:\nif(sum(mark_ranges)=0,\n incorrect(),\n apply(mark_ranges)\n)\n\ninterpreted_answer:\nstudentAnswer\n\nrange_cells:\nmap(parse_range(ref),ref,values(settings[\"mark_ranges\"]))\n\ntotal_cells:\nlen(flatten(range_cells))\n\nrange_weights:\nswitch(\n settings[\"marking_method\"]=\"per_cell\",\n map(len(r)/total_cells, r, range_cells),\n // otherwise, mark per range\n repeat(1/len(range_cells), len(range_cells))\n)\n\nmark_ranges:\nmap(\n let(\n range_credit,\n sum(map(\n let(\n correctCellString, correctAnswer[c],\n correctCellNumber, parsenumber(correctCellString, notation_styles),\n studentCellString, studentAnswer[c],\n studentCellNumber, parsenumber(studentCellString, notation_styles),\n award(\n 1/len(cells), \n if(isnan(correctCellNumber) and correctCellString<>\"\",\n lower(correctCellString) = lower(studentCellString),\n abs(studentCellNumber - if(isnan(correctCellNumber),0,correctCellNumber)) <= settings[\"tolerance\"]\n )\n )\n ),\n c,\n cells\n )),\n message,\n switch(\n range_credit=0,\n if(len(cells)=1, \"This entry is incorrect.\", \"All entries in this range are incorrect.\"),\n range_credit=1,\n if(len(cells)=1, \"This entry is correct.\", \"All entries in this range are correct.\"),\n //otherwise\n \"Some entries in this range are correct.\"\n ),\n assert(len(cells)=0, add_credit(range_credit*w, \"{name}: \"+message)); \n range_credit\n ),\n [cells,w,name],\n zip(range_cells, range_weights, keys(settings[\"mark_ranges\"]))\n)\n\nnotation_styles:\n[\"plain\",\"si-en\"]", "marking_notes": [{"name": "correctAnswer", "description": "

A spreadsheet representing the expected answer.

", "definition": "settings[\"correct_answer\"]"}, {"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "if(sum(mark_ranges)=0,\n incorrect(),\n apply(mark_ranges)\n)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "range_cells", "description": "

For each range to be marked, the addresses of the cells in that range.

", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "

The total number of cells to be marked. Cells in overlapping ranges will be counted once for each range they're in.

", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "

The weight of each range, as a proportion of the available credit.

", "definition": "switch(\n settings[\"marking_method\"]=\"per_cell\",\n map(len(r)/total_cells, r, range_cells),\n // otherwise, mark per range\n repeat(1/len(range_cells), len(range_cells))\n)"}, {"name": "mark_ranges", "description": "

Mark each of the ranges specified by the question author.

", "definition": "map(\n let(\n range_credit,\n sum(map(\n let(\n correctCellString, correctAnswer[c],\n correctCellNumber, parsenumber(correctCellString, notation_styles),\n studentCellString, studentAnswer[c],\n studentCellNumber, parsenumber(studentCellString, notation_styles),\n award(\n 1/len(cells), \n if(isnan(correctCellNumber) and correctCellString<>\"\",\n lower(correctCellString) = lower(studentCellString),\n abs(studentCellNumber - if(isnan(correctCellNumber),0,correctCellNumber)) <= settings[\"tolerance\"]\n )\n )\n ),\n c,\n cells\n )),\n message,\n switch(\n range_credit=0,\n if(len(cells)=1, \"This entry is incorrect.\", \"All entries in this range are incorrect.\"),\n range_credit=1,\n if(len(cells)=1, \"This entry is correct.\", \"All entries in this range are correct.\"),\n //otherwise\n \"Some entries in this range are correct.\"\n ),\n assert(len(cells)=0, add_credit(range_credit*w, \"{name}: \"+message)); \n range_credit\n ),\n [cells,w,name],\n zip(range_cells, range_weights, keys(settings[\"mark_ranges\"]))\n)"}, {"name": "notation_styles", "description": "

Accepted number notation styles for a value in an individual cell.

", "definition": "[\"plain\",\"si-en\"]"}], "settings": [{"name": "initial_sheet", "label": "Initial sheet", "help_url": "", "hint": "A spreadsheet object giving the initial state of the sheet that the student should fill in.", "input_type": "code", "default_value": "", "evaluate": true}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A spreadsheet object representing a correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": true}, {"name": "disable_ranges", "label": "Ranges to disable", "help_url": "", "hint": "A list of cell or range references, denoting the cells that should not be editable.", "input_type": "code", "default_value": "[]", "evaluate": true}, {"name": "mark_ranges", "label": "Ranges to mark", "help_url": "", "hint": "A dictionary of cell or range references, mapping names to ranges of cells, denoting the cells that should be compared for equality with the expected answer.", "input_type": "code", "default_value": "dict()", "evaluate": true}, {"name": "marking_method", "label": "Marking method", "help_url": "", "hint": "", "input_type": "dropdown", "default_value": "per_cell", "choices": [{"value": "per_cell", "label": "Each cell has the same weight"}, {"value": "per_range", "label": "Each range has the same weight"}]}, {"name": "tolerance", "label": "Allowed margin of error", "help_url": "", "hint": "", "input_type": "code", "default_value": "0", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["sheets"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "PhET springs experiment", "tags": [], "metadata": {"description": "

An experiment using a PhET applet. The student can attach masses of different weights to a spring, and is asked to measure and record how far it stretches. Their measurements are shown on a graph, and they're asked to estimate the formula for the length in terms of the mass.

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

In this experiment you will establish a formula for how far a spring stretches when you attach a mass to it.

\n

\n

Select the Lab experiment.

\n

Choose the strength of your spring. Keep the strength the same throughout the experiment.

\n

Measure the difference between the unstretched length and the resting position for a variety of masses, and enter your measurements in the table below.

", "advice": "", "rulesets": {}, "extensions": ["jsxgraph", "sheets"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"raw_spreadsheet": {"name": "raw_spreadsheet", "group": "Ungrouped variables", "definition": "spreadsheet_from_base64_file(safe(\"spring.xlsx\"), safe(\"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\"))", "description": "", "templateType": "spreadsheet", "can_override": false}, "blank_spreadsheet": {"name": "blank_spreadsheet", "group": "Ungrouped variables", "definition": "slice(raw_spreadsheet,\"A1:C6\")", "description": "

The spreadsheet with some rows added

", "templateType": "anything", "can_override": false}, "plot": {"name": "plot", "group": "Ungrouped variables", "definition": "jsxgraph(\n 600,600,[-25,110,310,-5],\n dict(map([\"p{i}\", [\"point\",[0,0], [\"id\": \"p{i}\", \"withLabel\": false]]],i,0..4)),\n [\"axes\":true]\n)", "description": "", "templateType": "anything", "can_override": false}, "k": {"name": "k", "group": "Ungrouped variables", "definition": "let(valid_entries, filter(not (isnan(x[0]) or isnan(x[1])), x, zip(masses,lengths)),\n sum(map(l/m, [m,l], valid_entries))/len(valid_entries)\n)", "description": "", "templateType": "anything", "can_override": false}, "masses": {"name": "masses", "group": "Ungrouped variables", "definition": "map(parsenumber(x,\"plain\"),[x],filled_spreadsheet[\"A2:A6\"])", "description": "", "templateType": "anything", "can_override": false}, "lengths": {"name": "lengths", "group": "Ungrouped variables", "definition": "map(parsenumber(x,\"plain\"),[x],filled_spreadsheet[\"B2:B6\"])", "description": "", "templateType": "anything", "can_override": false}, "filled_spreadsheet": {"name": "filled_spreadsheet", "group": "Ungrouped variables", "definition": "fill_range(blank_spreadsheet, \"A2:C6\",\n [\n [\"6\",\"1\", \"0.1666\"],\n [\"12\",\"2\", \"0.1666\"],\n [\"18\",\"3\", \"0.1666\"],\n [\"24\",\"4\", \"0.1666\"],\n [\"30\",\"5\", \"0.1666\"],\n ]\n)", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["raw_spreadsheet", "blank_spreadsheet", "plot", "filled_spreadsheet", "masses", "lengths", "k"], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": "iframe.phet {\n width: 100%;\n height: 80vh;\n}"}, "parts": [{"type": "spreadsheet", "useCustomName": false, "customName": "", "marks": "0", "scripts": {}, "customMarkingAlgorithm": "masses: map(parsenumber(x,\"plain\"),[x],studentAnswer[\"A2:A6\"])\n\nlengths: map(parsenumber(x,\"plain\"),[x],studentAnswer[\"B2:B6\"])\n\npoints: map(plot[\"p{i}\"], i, 0..4)\n\npositions:\n map(vector(mass,length), [mass, length], filter(not (isnan(x[0]) or isnan(x[1])), x, zip(masses,lengths)))\n\njxg_input:\n flatten(map(\n [ jxg_show(p,not (isnan(mass) or isnan(length))),\n jxg_set_position(p, vector(mass, length))\n ],\n [p,mass,length],\n zip(points, masses, lengths)\n ))", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": false, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "settings": {"initial_sheet": "blank_spreadsheet", "correct_answer": "blank_spreadsheet", "disable_ranges": "[\"A1:C1\"]", "mark_ranges": "dict()", "marking_method": "per_cell", "tolerance": "0"}}, {"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": "

{plot}

"}, {"type": "gapfill", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [{"variable": "filled_spreadsheet", "part": "p0", "must_go_first": true}], "variableReplacementStrategy": "alwaysreplace", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Write a formula for the length, $l$, in terms of the mass, $m$

\n

$l = $ [[0]]

", "gaps": [{"type": "jme", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "answer": "{k}*m", "answerSimplification": "fractionnumbers", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "caseSensitive": false, "valuegenerators": [{"name": "m", "value": ""}]}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "type": "question", "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}]}], "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}