// Numbas version: finer_feedback_settings {"name": "Journey record", "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": "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": "Journey record", "tags": [], "metadata": {"description": "Given a data sheet with distances between cities and costs for different forms of transport, and some information about modes of transport used, fill in a form for a journey.
", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "{data_spreadsheet}
\nYou are travelling from {from} to {to}.
\nYou travel {distance_description}.
", "advice": "", "rulesets": {}, "extensions": ["jsxgraph", "sheets"], "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", "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/"}]}