// Numbas version: exam_results_page_options {"name": "Factorisation: Solving and Graphing Quadratics ", "extensions": ["jsxgraph", "quantities"], "custom_part_types": [{"source": {"pk": 2, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/2/edit"}, "name": "List of numbers", "short_name": "list-of-numbers", "description": "

The answer is a comma-separated list of numbers.

\n

The list is marked correct if each number occurs the same number of times as in the expected answer, and no extra numbers are present.

\n

You can optionally treat the answer as a set, so the number of occurrences doesn't matter, only whether each number is included or not.

", "help_url": "", "input_widget": "string", "input_options": {"correctAnswer": "join(\n if(settings[\"correctAnswerFractions\"],\n map(let([a,b],rational_approximation(x), string(a/b)),x,settings[\"correctAnswer\"])\n ,\n settings[\"correctAnswer\"]\n ),\n settings[\"separator\"] + \" \"\n)", "hint": {"static": false, "value": "if(settings[\"show_input_hint\"],\n \"Enter a list of numbers separated by {settings['separator']}.\",\n \"\"\n)"}, "allowEmpty": {"static": true, "value": true}}, "can_be_gap": true, "can_be_step": true, "marking_script": "bits:\nlet(b,filter(x<>\"\",x,split(studentAnswer,settings[\"separator\"])),\n if(isSet,list(set(b)),b)\n)\n\nexpected_numbers:\nlet(l,settings[\"correctAnswer\"] as \"list\",\n if(isSet,list(set(l)),l)\n)\n\nvalid_numbers:\nif(all(map(not isnan(x),x,interpreted_answer)),\n true,\n let(index,filter(isnan(interpreted_answer[x]),x,0..len(interpreted_answer)-1)[0], wrong, bits[index],\n warn(wrong+\" is not a valid number\");\n fail(wrong+\" is not a valid number.\")\n )\n )\n\nis_sorted:\nassert(sort(interpreted_answer)=interpreted_answer,\n multiply_credit(0.5,\"Not in order\")\n )\n\nincluded:\nmap(\n let(\n num_student,len(filter(x=y,y,interpreted_answer)),\n num_expected,len(filter(x=y,y,expected_numbers)),\n switch(\n num_student=num_expected,\n true,\n num_studentThe separate items in the student's answer

", "definition": "let(b,filter(x<>\"\",x,split(studentAnswer,settings[\"separator\"])),\n if(isSet,list(set(b)),b)\n)"}, {"name": "expected_numbers", "description": "", "definition": "let(l,settings[\"correctAnswer\"] as \"list\",\n if(isSet,list(set(l)),l)\n)"}, {"name": "valid_numbers", "description": "

Is every number in the student's list valid?

", "definition": "if(all(map(not isnan(x),x,interpreted_answer)),\n true,\n let(index,filter(isnan(interpreted_answer[x]),x,0..len(interpreted_answer)-1)[0], wrong, bits[index],\n warn(wrong+\" is not a valid number\");\n fail(wrong+\" is not a valid number.\")\n )\n )"}, {"name": "is_sorted", "description": "

Are the student's answers in ascending order?

", "definition": "assert(sort(interpreted_answer)=interpreted_answer,\n multiply_credit(0.5,\"Not in order\")\n )"}, {"name": "included", "description": "

Is each number in the expected answer present in the student's list the correct number of times?

", "definition": "map(\n let(\n num_student,len(filter(x=y,y,interpreted_answer)),\n num_expected,len(filter(x=y,y,expected_numbers)),\n switch(\n num_student=num_expected,\n true,\n num_studentHas every number been included the right number of times?

", "definition": "all(included)"}, {"name": "no_extras", "description": "

True if the student's list doesn't contain any numbers that aren't in the expected answer.

", "definition": "if(all(map(x in expected_numbers, x, interpreted_answer)),\n true\n ,\n incorrect(\"Your answer contains \"+extra_numbers[0]+\" but should not.\");\n false\n )"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "if(lower(studentAnswer) in [\"empty\",\"\u2205\"],[],\n map(\n if(settings[\"allowFractions\"],parsenumber_or_fraction(x,notationStyles), parsenumber(x,notationStyles))\n ,x\n ,bits\n )\n)"}, {"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "if(studentanswer=\"\",fail(\"You have not entered an answer\"),false);\napply(valid_numbers);\napply(included);\napply(no_extras);\ncorrectif(all_included and no_extras)"}, {"name": "notationStyles", "description": "", "definition": "[\"en\"]"}, {"name": "isSet", "description": "

Should the answer be considered as a set, so the number of times an element occurs doesn't matter?

", "definition": "settings[\"isSet\"]"}, {"name": "extra_numbers", "description": "

Numbers included in the student's answer that are not in the expected list.

", "definition": "filter(not (x in expected_numbers),x,interpreted_answer)"}], "settings": [{"name": "correctAnswer", "label": "Correct answer", "help_url": "", "hint": "The list of numbers that the student should enter. The order does not matter.", "input_type": "code", "default_value": "", "evaluate": true}, {"name": "allowFractions", "label": "Allow the student to enter fractions?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "correctAnswerFractions", "label": "Display the correct answers as fractions?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": false}, {"name": "isSet", "label": "Is the answer a set?", "help_url": "", "hint": "If ticked, the number of times an element occurs doesn't matter, only whether it's included at all.", "input_type": "checkbox", "default_value": false}, {"name": "show_input_hint", "label": "Show the input hint?", "help_url": "", "hint": "", "input_type": "checkbox", "default_value": true}, {"name": "separator", "label": "Separator", "help_url": "", "hint": "The substring that should separate items in the student's list", "input_type": "string", "default_value": ",", "subvars": false}], "public_availability": "always", "published": true, "extensions": []}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "Factorisation: Solving and Graphing Quadratics ", "tags": [], "metadata": {"description": "", "licence": "None specified"}, "statement": "

The following question will test you on factorising, solving, and graphing quadratic equations.

", "advice": "

Check out its graph:

\n

{graph({a}{c},{{a}{d}+{b}{c}},{b}{d})}

", "rulesets": {}, "extensions": ["jsxgraph", "quantities"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"a": {"name": "a", "group": "Ungrouped variables", "definition": "random(-9..9 except 0)", "description": "", "templateType": "anything", "can_override": false}, "b": {"name": "b", "group": "Ungrouped variables", "definition": "random(-9..9 except 0)", "description": "", "templateType": "anything", "can_override": false}, "c": {"name": "c", "group": "Ungrouped variables", "definition": "random(-1..9 except 0)", "description": "", "templateType": "anything", "can_override": false}, "d": {"name": "d", "group": "Ungrouped variables", "definition": "random(-9..9 except 0)", "description": "", "templateType": "anything", "can_override": false}, "cone": {"name": "cone", "group": "Ungrouped variables", "definition": "a*c", "description": "", "templateType": "anything", "can_override": false}, "ctwo": {"name": "ctwo", "group": "Ungrouped variables", "definition": "a*d+b*c", "description": "", "templateType": "anything", "can_override": false}, "cthree": {"name": "cthree", "group": "Ungrouped variables", "definition": "b*d", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["a", "b", "c", "d", "cone", "ctwo", "cthree"], "variable_groups": [], "functions": {"graph": {"parameters": [["a", "number"], ["b", "number"], ["c", "number"]], "type": "html", "language": "javascript", "definition": "// set up the board\n\n\nvar div = Numbas.extensions.jsxgraph.makeBoard('500px','500px',{boundingBox:[-10,82,10,-82],grid:true,withLabel:true,ticks:false});\n\nvar board = div.board;\n\nvar e = board.create('point',[2.1,0],{size:-1,name:'x'});\ne.setProperty({fixed:true});\nvar g = board.create('point',[0,10],{size:-1,name:'y'});\ng.setProperty({fixed:true});\nvar f = board.create('point',[-2,4*a-2*b+c],{size:5,name:'A'});\nf.setProperty({fixed:true});\nvar h = board.create('point',[-1,a-b+c],{size:5,name:'B'});\nh.setProperty({fixed:true});\nvar f = board.create('point',[0,c],{size:5,name:'C'});\nf.setProperty({fixed:true});\nvar f = board.create('point',[1,a+b+c],{size:5,name:'D'});\nf.setProperty({fixed:true});\nvar f = board.create('point',[2,4*a+2*b+c],{size:5,name:'E'});\nf.setProperty({fixed:true});\n\nboard.create('functiongraph',[function(x){ return a*x*x+b*x+c;},-2,2],{strokeColor:'blue',strokeWidth:2});\n\nreturn div;"}, "dragpoint": {"parameters": [], "type": "html", "language": "javascript", "definition": "// set up the board\nvar a = scope.variables.a.value*scope.variables.c.value;\nvar b = scope.variables.a.value*scope.variables.d.value + scope.variables.b.value*scope.variables.c.value;\nvar c = scope.variables.b.value*scope.variables.d.value;\n\n// finds the x-intercepts\nvar rootone = -scope.variables.b.value/scope.variables.a.value;\nvar roottwo = -scope.variables.d.value/scope.variables.c.value;\n\n// setting up the initial positions so that they're never the answer already\n\nvar topb = 1\nvar topd = 1\nvar cstart = 1\n\nif(Math.abs(scope.variables.b.value)==1) {\n var topb = 2 \n}\nif(Math.abs(scope.variables.d.value)==1) {\n var topd = 2 \n}\nif(Math.abs(c)==1) {\n var ctart = 2 \n}\n\n// setting up the initial position, just the numerator so that it's never starting on the solution\nif(rootone<=roottwo) {\n var bdenom1 = Math.abs(topb/scope.variables.a.value);\n var bdenom2 = Math.abs(topd/scope.variables.c.value);\n}\nif(rootone>roottwo) {\n var bdenom1 = Math.abs(topd/scope.variables.c.value);\n var bdenom2 = Math.abs(topb/scope.variables.a.value);\n}\n\n// setting up the snapsize\nif(rootone<=roottwo) {\n var denom1 = Math.abs(1/scope.variables.a.value);\n var denom2 = Math.abs(1/scope.variables.c.value);\n}\nif(rootone>roottwo) {\n var denom1 = Math.abs(1/scope.variables.c.value);\n var denom2 = Math.abs(1/scope.variables.a.value);\n}\n\n// setting up the dimension of the board so it can always incorporate the board\nvar side = Math.max(Math.abs(scope.variables.b.value/scope.variables.a.value), Math.abs(scope.variables.d.value/scope.variables.c.value));\n\nvar vertex = Math.abs(b*b/(4*a)-c)\nvar graphy = Math.max(vertex, Math.abs(c))\nvar div = Numbas.extensions.jsxgraph.makeBoard('500px','500px',{boundingBox:[-side-3,graphy+10,side+3,-graphy-10],grid:true,labels:true});\nvar board = div.board;\n\n\n// create axis labels\nvar label1 = board.create('point',[side+1,0.3],{name:'x',size:-1});\nlabel1.setProperty({fixed:true});\nvar label2 = board.create('point',[0.2,graphy+3],{name:'y',size:-1});\nlabel2.setProperty({fixed:true});\n \n//create draggable points\n\nvar line0 = board.create('line',[[-1/2,0],[0,0]],{visible: false});\nvar np0 = board.create('glider',[-bdenom1,0,line0],{name:'A',size:2,snapSizeX: denom1,snapToGrid: true});\nvar line1 = board.create('line',[[2,0],[0,0]],{visible: false});\nvar np1 = board.create('glider',[bdenom2,0,line1],{name:'B',size:2,snapSizeX: denom2,snapToGrid: true});\nvar line2 = board.create('line',[[0,0],[0,2]],{visible: false});\nvar np2 = board.create('glider',[0,-cstart,line2],{name:'C',size:2,snapSizeY: 1,snapToGrid: true});\n\n \n//shorthand to evaluate a mathematical expression to a number\nfunction evaluate(expression) {\n try {\n //var oneval = Math.parsedecimal_or_fraction(expression)\n var val = Numbas.jme.evaluate(expression,question.scope);\n return Numbas.jme.unwrapValue(val);\n }\n catch(e) {\n // if there's an error, return no number\n return NaN;\n }\n}\n \n// set up points array\nvar num_points = 3;\nvar points = [np0, np1, np2];\n \n// this function sets up the i^th point\nfunction make_point(i) {\n var point = points[i];\n var x=point[0];\n var y=point[1];\n\n // the contents of the input box for this point\n if(i==0) {\n var xstudentAnswer = question.parts[2].gaps[i].display.studentAnswer;\n }\n if(i==1) {\n var xstudentAnswer = question.parts[2].gaps[i].display.studentAnswer;\n }\n if(i==2) {\n var ystudentAnswer = question.parts[2].gaps[i].display.studentAnswer;\n }\n \n // watch the student's input and reposition the point when it changes. \n ko.computed(function() {\n if(i==(0)) {\n x = evaluate(xstudentAnswer());\n y = 0;\n }\n if(i==(1)) {\n x = evaluate(xstudentAnswer());\n y = 0;\n }\n if(i==2) {\n x = 0;\n y = evaluate(ystudentAnswer());\n }\n if(!(isNaN(x)) && !(isNaN(y)) && board.mode!=board.BOARD_MODE_DRAG) {\n point.moveTo([x,y],100);\n }\n });\n \n // when the student drags the point, update the gapfill input\n point.on('drag',function(){\n var x = Numbas.math.niceNumber(point.X());\n var y = Numbas.math.niceNumber(point.Y());\n if(i==0) {\n xstudentAnswer(x);\n }\n if(i==1) {\n xstudentAnswer(x);\n }\n if(i==2) {\n ystudentAnswer(y);\n } \n });\n}\n \n// create each point\nfor(var i=0;iFactorise \\[\\simplify[all,!noLeadingMinus]{{{a}*{c}}x^2 + {{a}*{d}+{b}*{c}}x+{{b}*{d}}}.\\]

", "alternatives": [{"type": "jme", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": false, "answer": "({a}x+{b})({c}x+{d})", "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": "x", "value": ""}]}], "answer": "({a}x+{b})({c}x+{d})", "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": "x", "value": ""}]}, {"type": "gapfill", "useCustomName": true, "customName": "Solve", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Hence or otherwise, write down the values of $x$ for which

\n

\\[\\simplify[all,!noLeadingMinus]{{{a}*{c}}x^2 + {{a}*{d}+{b}*{c}}x+{{b}*{d}}}=0.\\]

\n

$x=$ [[0]]; Write your numbers separated by comma. Use fractions where necessary.

", "gaps": [{"type": "list-of-numbers", "useCustomName": true, "customName": "Roots", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": false, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "settings": {"correctAnswer": "[-{b}/{a},-{d}/{c}]", "allowFractions": true, "correctAnswerFractions": true, "isSet": true, "show_input_hint": false, "separator": ","}}], "sortAnswers": false}, {"type": "gapfill", "useCustomName": true, "customName": "Graph", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

By dragging the points A, B, C, construct the graph of the function \\[y= \\simplify[all,!noLeadingMinus]{{{a}*{c}}x^2 + {{a}*{d}+{b}*{c}}x+{{b}*{d}}}.\\]

\n

Let A and B denote the leftmost and rightmost x-intercepts respectively. Let C denote the y-intercept.

\n

{dragpoint()}

\n

", "gaps": [{"type": "numberentry", "useCustomName": true, "customName": "Leftmost $x$-int", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "min(-{b}/{a},-{d}/{c})-0.001", "maxValue": "min(-{b}/{a},-{d}/{c})+0.001", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "Rightmost $x$-int", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "max(-{b}/{a},-{d}/{c})-0.001", "maxValue": "max(-{b}/{a},-{d}/{c})+0.001", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$y$-int", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{b}*{d}", "maxValue": "{b}*{d}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "Ting-Ying Chang", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/18011/"}]}]}], "contributors": [{"name": "Ting-Ying Chang", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/18011/"}]}