// Numbas version: exam_results_page_options {"name": "Spreadsheets extension", "metadata": {"description": "", "licence": "None specified"}, "duration": 0, "percentPass": 0, "showQuestionGroupNames": false, "shuffleQuestionGroups": false, "showstudentname": true, "question_groups": [{"name": "Group", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": ["", "", "", ""], "variable_overrides": [[], [], [], []], "questions": [{"name": "Calculate areas of rooms in a house", "extensions": ["sheets"], "custom_part_types": [{"source": {"pk": 4, "author": {"name": "Christian Lawson-Perfect", "pk": 1}, "edit_page": "/beta/part_type/4/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "
An editable 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": "", "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": "", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "The total number of cells to be marked.
", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "", "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": "", "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": "", "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 mapping names to cell or range references, 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": "restricted", "published": false, "extensions": ["sheets"]}], "resources": [["question-resources/house-outline.svg", "/srv/numbas/beta/media/question-resources/house-outline.svg"]], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/beta/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}], "tags": [], "metadata": {"description": "", "licence": "None specified"}, "statement": "A surveyor has measured the rooms in a house and produced the following drawing (not to scale):
\n\nMeasurements are given in metres.
", "advice": "First write in the dimensions given on the drawing:
\n{update_range(dimensions_spreadsheet, \"B2:C6\", highlight_style)}
\nNext, calculate the area of each room, by multiplying the width by the height. Round to the nearest 0.01m2.
\n{update_range(areas_spreadsheet, \"D2:D6\", highlight_style)}
\nThen, add up the areas to find the total area:
\n{update_range(filled_spreadsheet, \"D7\", highlight_style)}
", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"raw_spreadsheet": {"name": "raw_spreadsheet", "group": "Spreadsheet", "definition": "spreadsheet_from_base64_file(safe(\"room-areas.xlsx\"), safe(\"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\"))", "description": "", "templateType": "spreadsheet", "can_override": false}, "spreadsheet": {"name": "spreadsheet", "group": "Spreadsheet", "definition": "raw_spreadsheet", "description": "", "templateType": "anything", "can_override": false}, "dimensions": {"name": "dimensions", "group": "Measurements", "definition": "[\n [x1+x2,y1],\n [x3,y1+y2+y3],\n [x1,y2],\n [x2,y2],\n [x1+x2,y3]\n]", "description": "", "templateType": "anything", "can_override": false}, "filled_spreadsheet": {"name": "filled_spreadsheet", "group": "Spreadsheet", "definition": "fill_range(areas_spreadsheet, \"D7\", [precround(total_area,2)])\n", "description": "The completed spreadsheet, with the total area cell filled in.
", "templateType": "anything", "can_override": false}, "areas": {"name": "areas", "group": "Ungrouped variables", "definition": "map(x*y,[x,y],dimensions)", "description": "The area of each room.
", "templateType": "anything", "can_override": false}, "names": {"name": "names", "group": "Ungrouped variables", "definition": "map(x[0],x,spreadsheet[\"A2:A6\"])", "description": "Names of the rooms.
", "templateType": "anything", "can_override": false}, "dims": {"name": "dims", "group": "Ungrouped variables", "definition": "map(\"{dpformat(w,2)} \u00d7 {dpformat(h,2)}\",[w,h],dimensions)", "description": "Strings describing the rooms' dimensions, to insert in the image.
", "templateType": "anything", "can_override": false}, "total_area": {"name": "total_area", "group": "Ungrouped variables", "definition": "sum(areas)", "description": "The total area of the house.
", "templateType": "anything", "can_override": false}, "dimensions_spreadsheet": {"name": "dimensions_spreadsheet", "group": "Spreadsheet", "definition": "fill_range(spreadsheet, \"B2:C6\", dimensions)", "description": "The spreadsheet with the dimensions filled in but not the areas.
", "templateType": "anything", "can_override": false}, "areas_spreadsheet": {"name": "areas_spreadsheet", "group": "Spreadsheet", "definition": "fill_range(dimensions_spreadsheet, \"D2:D6\", map(precround(x,2),x,areas))", "description": "The spreadsheet with dimensions and areas filled in.
", "templateType": "anything", "can_override": false}, "highlight_style": {"name": "highlight_style", "group": "Ungrouped variables", "definition": "[\"style\": [\"fill\": [\"fgColor\": [\"rgb\": \"ccccff\"]]]]", "description": "Style which fills in cells with a bright colour to highlight them.
", "templateType": "anything", "can_override": false}, "x1,x2,x3": {"name": "x1,x2,x3", "group": "Ungrouped variables", "definition": "repeat(precround(random(1..2#0.01),2), 3)", "description": "The three widths - the width of hallway 1, hallway 2, and the dining room.
", "templateType": "anything", "can_override": false}, "y1,y2,y3": {"name": "y1,y2,y3", "group": "Ungrouped variables", "definition": "repeat(precround(random(1..2#0.01),2), 3)", "description": "The three vertical measurements: kitchen, hallway, and living room.
", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["x1,x2,x3", "y1,y2,y3", "names", "dims", "areas", "total_area", "highlight_style"], "variable_groups": [{"name": "Spreadsheet", "variables": ["raw_spreadsheet", "spreadsheet", "dimensions_spreadsheet", "areas_spreadsheet", "filled_spreadsheet"]}, {"name": "Measurements", "variables": ["dimensions"]}], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "spreadsheet", "useCustomName": false, "customName": "", "marks": "30", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Fill in this survey form. Give lengths in metres to the nearest centimetre, and areas in square metres to the nearest 0.01 m2.
", "settings": {"initial_sheet": "spreadsheet", "correct_answer": "filled_spreadsheet", "disable_ranges": "[\"A1:D1\", \"A1:A6\",\"A7:C7\"]", "mark_ranges": "[\"Dimensions\": \"B2:C6\", \"Areas\": \"D2:D6\", \"Total area\": \"D7\"]", "marking_method": "per_range", "tolerance": "0.01"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Journey record", "extensions": ["sheets"], "custom_part_types": [{"source": {"pk": 4, "author": {"name": "Christian Lawson-Perfect", "pk": 1}, "edit_page": "/beta/part_type/4/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "An editable 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": "", "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": "", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "The total number of cells to be marked.
", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "", "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": "", "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": "", "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 mapping names to cell or range references, 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": "restricted", "published": false, "extensions": ["sheets"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/beta/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}], "tags": [], "metadata": {"description": "", "licence": "None specified"}, "statement": "{data_spreadsheet}
\nYou are travelling from {from} to {to}.
\nYou travel {distance_description}.
", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"raw_spreadsheet": {"name": "raw_spreadsheet", "group": "Journey record form", "definition": "spreadsheet_from_base64_file(safe(\"journey.xlsx\"), safe(\"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\"))", "description": "", "templateType": "spreadsheet", "can_override": false}, "filled_spreadsheet": {"name": "filled_spreadsheet", "group": "Journey record form", "definition": "fill_range(\n fill_range(\n fill_range(raw_spreadsheet, \"B2:B3\", [from,to]),\n \"B6:E10\",\n list(transpose(matrix([mode_distances,journey_cost,journey_co2,journey_time])))\n ),\n \"B11:E11\",\n totals\n)", "description": "", "templateType": "anything", "can_override": false}, "from,to": {"name": "from,to", "group": "Ungrouped variables", "definition": "shuffle(cities)", "description": "", "templateType": "anything", "can_override": false}, "cities": {"name": "cities", "group": "Cities", "definition": "data_spreadsheet[\"B2:E2\"][0]", "description": "", "templateType": "anything", "can_override": false}, "cost_per_km": {"name": "cost_per_km", "group": "Costs", "definition": "map(precround(x,2),x,[\n random(0.5..1.5#0),\n random(0.2..1#0),\n random(0.5..3#0),\n 0,\n random(0.01..0.05#0),\n])", "description": "The average cost per km of each mode of transport.
", "templateType": "anything", "can_override": false}, "co2_per_km": {"name": "co2_per_km", "group": "Costs", "definition": "map(precround(x,3),x,[\n random(0.15..0.2#0),\n random(0.1..0.15#0),\n random(0.03..0.06#0),\n 0,\n 0\n])", "description": "The average CO2 emissions per km of each mode of transport.
", "templateType": "anything", "can_override": false}, "speed": {"name": "speed", "group": "Costs", "definition": "[\n random(45..115#5),\n random(30..80#5),\n random(90..210#5),\n random(3..6),\n random(25..40)\n]", "description": "The average travel speed of each mode of transport.
", "templateType": "anything", "can_override": false}, "raw_data_spreadsheet": {"name": "raw_data_spreadsheet", "group": "Data spreadsheet", "definition": "spreadsheet_from_base64_file(safe(\"journey-data.xlsx\"), safe(\"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\"))", "description": "", "templateType": "spreadsheet", "can_override": false}, "data_spreadsheet": {"name": "data_spreadsheet", "group": "Data spreadsheet", "definition": "fill_range(raw_data_spreadsheet, \"B9:D13\", list(transpose(matrix([cost_per_km,co2_per_km,speed]))))", "description": "", "templateType": "anything", "can_override": false}, "distance": {"name": "distance", "group": "Distance travelled", "definition": "let(\n c1,indices(cities,from)[0],\n c2,indices(cities,to)[0],\n\n let(\n a,max(c1,c2),\n b,min(c1,c2),\n n,parsenumber(data_spreadsheet[\"{upper(letterordinal(a+1))}{b+3}\"],\"plain\"),\n \n if(isnan(n),0,n)\n )\n)", "description": "The distance between the chosen cities.
", "templateType": "anything", "can_override": false}, "mode_distances": {"name": "mode_distances", "group": "Distance travelled", "definition": "let(\n num_modes, random(2..3),\n shuffle(random_integer_partition(distance,num_modes)+repeat(0,5-num_modes))\n)", "description": "", "templateType": "anything", "can_override": false}, "transport_modes": {"name": "transport_modes", "group": "Distance travelled", "definition": "map(x[0],x,raw_spreadsheet[\"A6:A10\"])", "description": "", "templateType": "anything", "can_override": false}, "distance_description": {"name": "distance_description", "group": "Distance travelled", "definition": "let(\n used_modes, filter(x[0]>0,x,zip(mode_distances, transport_modes)),\n texts, map(\"{d}km {lower(mode)}\",[d,mode], used_modes[0..len(used_modes)]),\n \n if(len(used_modes)>1,\n join(texts[0..-1], \", \")\n +\n \", and the rest \"+lower(used_modes[-1][1])\n ,\n texts[0]\n )\n)", "description": "", "templateType": "anything", "can_override": false}, "journey_cost": {"name": "journey_cost", "group": "Costs", "definition": "map(precround(d*c,2),[d,c],zip(mode_distances,cost_per_km))", "description": "The incurred cost of each mode of transport.
", "templateType": "anything", "can_override": false}, "journey_co2": {"name": "journey_co2", "group": "Costs", "definition": "map(precround(d*c,3),[d,c],zip(mode_distances,co2_per_km))", "description": "", "templateType": "anything", "can_override": false}, "journey_time": {"name": "journey_time", "group": "Costs", "definition": "map(round(60*d/s),[d,s],zip(mode_distances,speed))", "description": "", "templateType": "anything", "can_override": false}, "totals": {"name": "totals", "group": "Costs", "definition": "map(precround(sum(l),2),l,[mode_distances,journey_cost,journey_co2,journey_time])", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["from,to"], "variable_groups": [{"name": "Data spreadsheet", "variables": ["raw_data_spreadsheet", "data_spreadsheet"]}, {"name": "Cities", "variables": ["cities"]}, {"name": "Costs", "variables": ["co2_per_km", "cost_per_km", "speed", "journey_cost", "journey_co2", "journey_time", "totals"]}, {"name": "Journey record form", "variables": ["raw_spreadsheet", "filled_spreadsheet"]}, {"name": "Distance travelled", "variables": ["mode_distances", "distance", "transport_modes", "distance_description"]}], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "spreadsheet", "useCustomName": false, "customName": "", "marks": "26", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "Using the data sheet above, fill in the journey record form below.
\nRound costs to the nearest penny, CO2 emissions to the nearest gram, and time to the nearest minute.
", "settings": {"initial_sheet": "raw_spreadsheet", "correct_answer": "filled_spreadsheet", "disable_ranges": "[\"A1:D1\",\"A2:A3\",\"A4:D4\",\"A5:D5\", \"A5:A11\"]", "mark_ranges": "[\n \"From and To\": \"B2:B3\",\n \"Distance travelled\": \"B6:B10\",\n \"Cost\": \"C6:C10\",\n \"CO2 emissions\": \"D6:D10\",\n \"Time\": \"E6:E10\",\n \"Totals\": \"B11:E11\"\n]", "marking_method": "per_cell", "tolerance": "0.01"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "PhET springs experiment", "extensions": ["jsxgraph", "sheets"], "custom_part_types": [{"source": {"pk": 4, "author": {"name": "Christian Lawson-Perfect", "pk": 1}, "edit_page": "/beta/part_type/4/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "An editable 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": "", "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": "", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "The total number of cells to be marked.
", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "", "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": "", "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": "", "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 mapping names to cell or range references, 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": "restricted", "published": false, "extensions": ["sheets"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/beta/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}], "tags": [], "metadata": {"description": "", "licence": "None specified"}, "statement": "\nSelect the Lab experiment.
\nChoose the strength of your spring. Keep the strength the same throughout the experiment.
\nMeasure 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": {}, "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"}, {"name": "Product fact sheet", "extensions": ["sheets"], "custom_part_types": [{"source": {"pk": 4, "author": {"name": "Christian Lawson-Perfect", "pk": 1}, "edit_page": "/beta/part_type/4/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "An editable 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": "", "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": "", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "The total number of cells to be marked.
", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "", "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": "", "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": "", "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 mapping names to cell or range references, 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": "restricted", "published": false, "extensions": ["sheets"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/beta/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}], "tags": [], "metadata": {"description": "", "licence": "None specified"}, "statement": "You're considering buying a new {product_name}. The manufacturer's website contains the following information:
\n\n\nThe new {product_name} does everything you need it do. Drawing only {electricity_use}W, it uses much less electricity than most towns. And invention fluid use is lower than ever, at a mere {fluid_use}ml per hour.
\nMeasuring {dimensions[0]}×{dimensions[1]}×{dimensions[2]}cm, where can't you put it?
\nPriced affordably at {currency(price,\"£\",\"p\")}, get one today!
\n
You also found some reviews online:
\n{reviews_table}
\nOne review noted that each {product_name} incurs {currency(externalised_costs,\"£\",\"p\")} in externalised costs.
", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"raw_spreadsheet": {"name": "raw_spreadsheet", "group": "Spreadsheet", "definition": "spreadsheet_from_base64_file(safe(\"product-fact-sheet.xlsx\"), safe(\"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\"))", "description": "", "templateType": "spreadsheet", "can_override": false}, "filled_spreadsheet": {"name": "filled_spreadsheet", "group": "Completed spreadsheet", "definition": "fill_ranges(raw_spreadsheet,\n [\n [\"B2\",[[product_name]]],\n [\"D2\", [[price]]],\n [\"F3:F6\", [[electricity_use],[fluid_use],[externalised_costs]]],\n [\"A5:C5\", [dimensions]],\n [\"B9:D9\", [review_counts]]\n ]\n)", "description": "", "templateType": "anything", "can_override": false}, "product_names": {"name": "product_names", "group": "Data", "definition": "[ \"Whizzo 3\", \"The New Gloop\", \"Vwlr\", \"Crumpetron\", \"Autocomb Pro\" ]", "description": "", "templateType": "list of strings", "can_override": false}, "product_name": {"name": "product_name", "group": "Data", "definition": "random(product_names)", "description": "", "templateType": "anything", "can_override": false}, "dimensions": {"name": "dimensions", "group": "Data", "definition": "repeat(random(10..100#5),3)", "description": "", "templateType": "anything", "can_override": false}, "electricity_use": {"name": "electricity_use", "group": "Data", "definition": "random(10..200#5)", "description": "", "templateType": "anything", "can_override": false}, "fluid_use": {"name": "fluid_use", "group": "Data", "definition": "random(300..900#10)", "description": "", "templateType": "anything", "can_override": false}, "externalised_costs": {"name": "externalised_costs", "group": "Data", "definition": "random(1000..9000#100)", "description": "", "templateType": "anything", "can_override": false}, "price": {"name": "price", "group": "Data", "definition": "random(59..409#10)", "description": "", "templateType": "anything", "can_override": false}, "individual_reviews": {"name": "individual_reviews", "group": "Data", "definition": "repeat(random(scores),5)", "description": "", "templateType": "anything", "can_override": false}, "all_reviewers": {"name": "all_reviewers", "group": "Data", "definition": "[ \"Invention Review\", \"Product Quarterly\", \"Whence Gizmos\", \"Doodads Today\", \"That Thingamajig\", \"Contraption Action\" ]", "description": "", "templateType": "list of strings", "can_override": false}, "reviewers": {"name": "reviewers", "group": "Data", "definition": "shuffle(all_reviewers)", "description": "", "templateType": "anything", "can_override": false}, "reviews_table": {"name": "reviews_table", "group": "Data", "definition": "table(zip(reviewers,individual_reviews),[\"Reviewer\",\"Score\"])", "description": "", "templateType": "anything", "can_override": false}, "review_counts": {"name": "review_counts", "group": "Data", "definition": "map(len(filter(x=score,x,individual_reviews)),score,scores)", "description": "", "templateType": "anything", "can_override": false}, "scores": {"name": "scores", "group": "Data", "definition": "[ \"Bad\", \"Neutral\", \"Good\" ]", "description": "", "templateType": "list of strings", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [{"name": "Spreadsheet", "variables": ["raw_spreadsheet"]}, {"name": "Data", "variables": ["product_names", "product_name", "dimensions", "electricity_use", "fluid_use", "externalised_costs", "price", "scores", "individual_reviews", "all_reviewers", "reviewers", "reviews_table", "review_counts"]}, {"name": "Completed spreadsheet", "variables": ["filled_spreadsheet"]}], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "spreadsheet", "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": "Before making a purchase, you always fill in a product fact sheet. Fill in the product fact sheet for the {product_name}, using the information above.
", "settings": {"initial_sheet": "raw_spreadsheet", "correct_answer": "filled_spreadsheet", "disable_ranges": "[\"A1:F1\", \"A2\",\"C2\",\"E2:F2\",\"A3:C3\",\"A4:C4\",\"E3:E5\",\"A7:D8\",\"A8:A9\"]", "mark_ranges": "[\n \"Product name\": \"B2\",\n \"Price\": \"D2\",\n \"Running costs\": \"F3:F5\",\n \"Dimensions\": \"A5:C5\",\n \"Reviews\": \"B9:D9\"\n]", "marking_method": "per_cell", "tolerance": "0"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}]}], "allowPrinting": true, "navigation": {"allowregen": true, "reverse": true, "browse": true, "allowsteps": true, "showfrontpage": false, "showresultspage": "oncompletion", "navigatemode": "menu", "onleave": {"action": "none", "message": ""}, "preventleave": false, "startpassword": ""}, "timing": {"allowPause": true, "timeout": {"action": "none", "message": ""}, "timedwarning": {"action": "none", "message": ""}}, "feedback": {"showactualmark": true, "showtotalmark": true, "showanswerstate": true, "allowrevealanswer": true, "advicethreshold": 0, "intro": "", "end_message": "", "reviewshowscore": true, "reviewshowfeedback": true, "reviewshowexpectedanswer": true, "reviewshowadvice": true, "feedbackmessages": []}, "diagnostic": {"knowledge_graph": {"topics": [], "learning_objectives": []}, "script": "diagnosys", "customScript": ""}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/beta/accounts/profile/1/"}], "extensions": ["jsxgraph", "sheets"], "custom_part_types": [{"source": {"pk": 4, "author": {"name": "Christian Lawson-Perfect", "pk": 1}, "edit_page": "/beta/part_type/4/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "An editable 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": "", "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": "", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "The total number of cells to be marked.
", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "", "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": "", "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": "", "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 mapping names to cell or range references, 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": "restricted", "published": false, "extensions": ["sheets"]}], "resources": [["question-resources/house-outline.svg", "/srv/numbas/beta/media/question-resources/house-outline.svg"]]}