// Numbas version: exam_results_page_options {"name": "Long division in a spreadsheet", "extensions": ["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": "Aspreadsheet
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": "Long division in a spreadsheet", "tags": [], "metadata": {"description": "The student is asked to calculate a division by the method of long division, which they should enter in a grid.
\nThe process is simulated and the order in which cells are filled in is recorded, so the marking feedback tries to identify the first cell that the student got wrong, or should try to fill in next.
\nThey're asked to give the quotient as a plain number in a second part, to check that they can interpret the finished grid properly.
", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "I've calculated $\\var{example_a} \\div \\var{example_b}$ by long division:
\n{example_finished}
\nSo $\\var{example_a} \\div \\var{example_b} = \\var{example_a/example_b}$.
", "advice": "", "rulesets": {}, "extensions": ["sheets"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"sheet,correct_sheet,cell_order": {"name": "sheet,correct_sheet,cell_order", "group": "Ungrouped variables", "definition": "complete_long_division(a,b)", "description": "", "templateType": "anything", "can_override": false}, "b,c": {"name": "b,c", "group": "Ungrouped variables", "definition": "repeat(random(11..200 except [example_c, example_b]),2)", "description": "", "templateType": "anything", "can_override": false}, "a": {"name": "a", "group": "Ungrouped variables", "definition": "b*c", "description": "", "templateType": "anything", "can_override": false}, "example_sheet, example_finished, example_cell_order": {"name": "example_sheet, example_finished, example_cell_order", "group": "Ungrouped variables", "definition": "complete_long_division(example_a, example_b)", "description": "", "templateType": "anything", "can_override": false}, "example_c, example_b": {"name": "example_c, example_b", "group": "Ungrouped variables", "definition": "[123,41]", "description": "", "templateType": "anything", "can_override": false}, "example_a": {"name": "example_a", "group": "Ungrouped variables", "definition": "example_b * example_c", "description": "", "templateType": "anything", "can_override": false}, "na": {"name": "na", "group": "Ungrouped variables", "definition": "int(len(string(a)))", "description": "", "templateType": "anything", "can_override": false}, "nb": {"name": "nb", "group": "Ungrouped variables", "definition": "int(len(string(b)))", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["sheet,correct_sheet,cell_order", "b,c", "example_sheet, example_finished, example_cell_order", "example_c, example_b", "example_a", "a", "na", "nb"], "variable_groups": [], "functions": {"long_division_steps": {"parameters": [["a", "number"], ["b", "number"]], "type": "anything", "language": "javascript", "definition": "// a/b\n\n// get the digits of x as a list of integers\nfunction digits_of(x) {\n return (x+'').split('').map(d=>parseInt(d));\n}\n\n// Given a list of digits, produce the number it represents.\nfunction from_digits(digits) {\n\tlet t = 0;\n for(let d of digits) {\n t = 10*t + d;\n }\n return t;\n}\n\nconst a_digits = digits_of(a);\nconst b_digits = digits_of(b);\n\n// Sort two numbers represented as lists of digits, lexicographically: look at most-significant digits first, and put the biggest values first.\nfunction compare_digits(d1,d2) {\n for(let i=0;iNow you calculate $\\var{a} \\div \\var{b}$ by long division.
\nYou can press the Submit button at any time to check you're doing it right, or to get a hint about what to do next.
", "settings": {"initial_sheet": "sheet", "correct_answer": "correct_sheet", "disable_ranges": "[]", "mark_ranges": "dict()", "marking_method": "per_cell", "tolerance": "0"}}, {"type": "numberentry", "useCustomName": true, "customName": "So what's the answer?", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "So what is $\\var{a} \\div \\var{b}$?
", "minValue": "a/b", "maxValue": "a/b", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}]}], "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}