// Numbas version: exam_results_page_options {"name": "JSXGraph Conference 2021 demo", "metadata": {"description": "

Some questions demonstrating the JSXGraph extension, for my talk at the JSXGraph conference 2021.

", "licence": "Creative Commons Attribution 4.0 International"}, "duration": 0, "percentPass": "0", "showQuestionGroupNames": false, "shuffleQuestionGroups": false, "showstudentname": true, "question_groups": [{"name": "Group", "pickingStrategy": "all-ordered", "pickQuestions": 1, "questionNames": ["", "", "", "", "", ""], "variable_overrides": [[], [], [], [], [], []], "questions": [{"name": "Move point to given coordinates", "extensions": ["jsxgraph", "programming"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

The student is shown a diagram containing a single point at the origin. They must move the point to the given integer coordinates.

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

The point should be here:

\n

{correct_diagram}

\n

$\\var[rowvector]{coords}$ means that the horizontal position should be $\\var{x}$, and the vertical position should be $\\var{y}$.

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"coords": {"name": "coords", "group": "Ungrouped variables", "definition": "vector(x,y)", "description": "", "templateType": "anything", "can_override": false}, "diagram": {"name": "diagram", "group": "Ungrouped variables", "definition": "jessiecode(400,400,\"\"\"\n point(0,0) <>;\n\"\"\")", "description": "", "templateType": "anything", "can_override": false}, "x": {"name": "x", "group": "Ungrouped variables", "definition": "random(-3..3 except 0)", "description": "", "templateType": "anything", "can_override": false}, "y": {"name": "y", "group": "Ungrouped variables", "definition": "random(-3..3 except [0,x])", "description": "", "templateType": "anything", "can_override": false}, "correct_diagram": {"name": "correct_diagram", "group": "Ungrouped variables", "definition": "jessiecode(400,400,\"\"\"\n A = point({x},{y}) <>;\n segment([0,{y}],A) <>;\n segment([{x},0],A) <>;\n\"\"\")", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["x", "y", "coords", "diagram", "correct_diagram"], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "extension", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "student_pos: jxg_position(diagram[\"A\"])\n\nmark:\n correctif(student_pos=coords)\n\ninterpreted_answer: student_pos", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Move the dot to the coordinates $\\var[rowvector]{coords}$.

\n

{diagram}

"}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Create a line with given gradient", "extensions": ["jsxgraph", "programming"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

The student is shown a diagram containing a line between two points. They're given a gradient and $y$-intercept.

\n

They must manipulate the line or the points so that the line has the given gradient and $y$-intercept.

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

The line should look like this:

\n

{correct_diagram}

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"gradient": {"name": "gradient", "group": "Ungrouped variables", "definition": "dy/dx", "description": "

The gradient that the student's line should have. Designed to be a nice fraction.

", "templateType": "anything", "can_override": false}, "diagram": {"name": "diagram", "group": "Ungrouped variables", "definition": "jessiecode(400,400,[-5,10,10,-5],\"\"\"\n a = point(1,0) <>;\n b = point(2,0) <>;\n line = line(a,b) <>;\n\"\"\")", "description": "

The diagram shown to the student.

", "templateType": "anything", "can_override": false}, "dx": {"name": "dx", "group": "Ungrouped variables", "definition": "random(1..5)", "description": "

A randomly chosen change in x to get a nice gradient.

", "templateType": "anything", "can_override": false}, "dy": {"name": "dy", "group": "Ungrouped variables", "definition": "random(-5..5 except 0)", "description": "

A randomly chosen change in y to get a nice gradient.

", "templateType": "anything", "can_override": false}, "y_intercept": {"name": "y_intercept", "group": "Ungrouped variables", "definition": "random(0..4)", "description": "

The point at which the student's line should cross the y axis.

", "templateType": "anything", "can_override": false}, "x_intercept": {"name": "x_intercept", "group": "Ungrouped variables", "definition": "let([g,y], gradient_intercept_pair,\n -y/g\n)", "description": "

The position at which the line crosses the x axis

", "templateType": "anything", "can_override": false}, "gradient_intercept_pair": {"name": "gradient_intercept_pair", "group": "Ungrouped variables", "definition": "[gradient,y_intercept]", "description": "

The gradient and y-intercept of the line as a pair, to be replaced by the student's answer for adaptive marking in part b.

", "templateType": "anything", "can_override": false}, "correct_diagram": {"name": "correct_diagram", "group": "Ungrouped variables", "definition": "jessiecode(400,400,[-5,10,10,-5],\"\"\"\n a = point(0,{y_intercept}) <>;\n b = point({x_intercept},0) <>;\n line = line(a,b) <>;\n\"\"\")", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["dx", "dy", "gradient", "y_intercept", "diagram", "gradient_intercept_pair", "x_intercept", "correct_diagram"], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "extension", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "student_line: diagram[\"l\"]\n\nstudent_gradient: jxg_slope(student_line)\n\nstudent_intercept: jxg_rise(student_line)\n\ncorrect_gradient (Does the student's line have the right gradient?):\n if(student_gradient=gradient, \n add_credit(0.5,\"Your line has the right gradient.\"),\n negative_feedback(\"Your line does not have the correct gradient (yours has {student_gradient}).\")\n )\n\ncorrect_intercept (Does the student's line have the right y-intercept?):\n if(student_intercept=y_intercept, \n add_credit(0.5,\"Your line has the right $y$-intercept.\"),\n negative_feedback(\"Your line does not have the correct $y$-intercept (yours has {student_intercept}).\")\n )\n\nmark:\n apply(correct_gradient);\n apply(correct_intercept)\n\ninterpreted_answer: [student_gradient,student_intercept]", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Construct a line with gradient {gradient} and $y$-intercept {y_intercept}.

\n

You can move the line by dragging it, or move the two points individually.

\n

{diagram}

"}, {"type": "gapfill", "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": "

Where does the line cross the $x$ axis?

\n

$x = $ [[0]]

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [{"variable": "gradient_intercept_pair", "part": "p0", "must_go_first": false}], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": "0.5", "exploreObjective": null, "minValue": "x_intercept", "maxValue": "x_intercept", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Free oscillations of a pendulum", "extensions": ["jsxgraph", "programming"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas-editor.mas.ncl.ac.uk/accounts/profile/3/"}, {"name": "Christopher Graham", "profile_url": "https://numbas-editor.mas.ncl.ac.uk/accounts/profile/73/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "

Solving 2nd order differential equation for pendulum, with and without damping.

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

In the absence of air resistance, the equation of motion of a bob, of mass $m$, at the end of a pendulum of length $l$ is

\n

\\[ ml\\frac{\\mathrm{d}^2\\theta}{\\mathrm{d}t^2} = -mg\\sin\\theta\\text{.} \\]

\n

In the small angle approximation, $\\sin\\theta\\approx\\theta$, this reduces to

\n

\\[ \\frac{\\mathrm{d}^2\\theta}{\\mathrm{d}t^2}+\\frac{g}{l}\\theta = 0\\text{.} \\]

", "advice": "

a)

\n

We have a second order constant coefficient differential equation,

\n

\\[ \\frac{\\mathrm{d}^2\\theta}{\\mathrm{d}t^2}+\\frac{g}{l}\\theta = 0 \\text{.} \\]

\n

Setting $\\theta = e^{\\lambda t}$, we obtain the auxiliary equation

\n

\\[ \\lambda^2 + \\frac{g}{l} = 0 \\implies \\lambda = \\pm i\\sqrt{\\frac{g}{l}} \\text{.} \\]

\n

The general solution for an auxiliary equation with complex roots is

\n

\\[ \\theta(t) = A\\sin\\omega t + B\\cos\\omega t \\text{,} \\]

\n

where $\\omega = \\sqrt{\\frac{g}{l}}$ is the angular frequency of the oscillations, also known as the natural frequency: the frequency with which the pendulum oscillates in the absence of external forcing).

\n

Note that

\n

\\[ \\frac{\\mathrm{d}\\theta}{\\mathrm{d}t} = A\\omega\\cos\\omega t - B\\omega\\sin\\omega t \\text{.} \\]

\n

Applying the initial conditions:

\n

\\begin{align}
\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t} (0) = 0 &=A\\omega\\cos(0) - B\\omega\\sin(0) \\text{,}  \\\\
&= A\\omega \\text{,} \\\\
\\therefore A &= 0 \\text{.}
\\end{align}

\n

\\begin{align}
\\theta (0) =\\frac{\\pi}{\\var{theta0_frac}} &=B\\cos(0) \\text{,}  \\\\
\\therefore B &=\\frac{\\pi}{\\var{theta0_frac}} \\text{.}
\\end{align}

\n

Therefore our solution is

\n

\\[ \\theta(t) = \\frac{\\pi}{\\var{theta0_frac}}\\cos\\left(\\sqrt{\\frac{g}{l}}t\\right)\\text{.} \\]

\n

Using the given values for $g$ and $l$,

\n

\\[ \\theta(t) = \\frac{\\pi}{\\var{theta0_frac}}\\cos\\left(\\sqrt{\\frac{\\var{g}}{\\var{l}}}t\\right)\\text{.} \\]

\n

\n

b)

\n

The time period of oscillations is given by

\n

\\[ T = \\frac{2\\pi}{\\omega} = 2\\pi\\sqrt{\\frac{l}{g}} =2\\pi\\sqrt{\\frac{\\var{l}}{\\var{g}}} = \\var{precround(T,2)} \\text{ s.} \\]

\n

c)

\n

Differentiating our solution from part (a), we have

\n

\\[ \\frac{d\\theta}{dt} = -\\frac{\\pi}{\\var{theta0_frac}}\\omega \\sin\\omega t\\text{.} \\]

\n

This is at its maximum when $\\sin \\omega t = -1$, 

\n

\\[ \\left(\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t}\\right)_{\\text{max}} = \\frac{\\pi}{\\var{theta0_frac}}\\omega =\\frac{\\pi}{\\var{theta0_frac}}\\sqrt{\\frac{\\var{g}}{\\var{l}}} = \\var{precround(theta0*sqrt(g/l),2)}\\text{ rad s}^{-1 }\\text{.} \\]

\n

d)

\n

With the addition of a damping term, our differential equation becomes

\n

\\[ \\frac{\\mathrm{d}^2\\theta}{\\mathrm{d}t^2}+\\frac{k}{m}\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t}+\\frac{g}{l}\\theta = 0\\text{.} \\]

\n

This is still a constant-coefficient second-order differential equation, however the extra term changes the auxiliary equation. For convenience we can let $\\beta = \\frac{k}{2m}$ (we will later find that this is $\\beta$ as asked for in the question) and $\\omega^2 = \\frac{g}{l}$, as before, to put our auxiliary equation in the form

\n

\\[ \\lambda^2 + 2\\beta \\lambda + \\omega^2 = 0\\text{,} \\]

\n

which has the solutions

\n

\\[ \\begin{align} \\lambda &=-\\frac{2\\beta}{2}\\pm \\frac{\\sqrt{2\\beta^2-4\\omega^2}}{2} \\\\
 &= -\\beta\\pm \\sqrt{\\beta^2-\\omega^2} \\\\
 &= -\\beta\\pm i\\sqrt{\\omega^2-\\beta^2}\\text{.} \\end{align}\\]

\n

Note that the values in our problem have determined that $\\omega >\\beta$. As in part (a), we have an auxiliary equation with complex roots:

\n

\\[\\theta(t) = e^{-\\beta t}\\left[A\\sin\\left(\\sqrt{\\omega^2-\\beta^2}\\; t\\right) + B\\cos\\left(\\sqrt{\\omega^2-\\beta^2}\\; t\\right)\\right]\\text{.} \\]

\n

Using the values and initial conditions from part (a), this becomes

\n

\\[\\theta(t) = \\frac{\\pi}{\\var{theta0_frac}}e^{-\\beta t}\\cos\\left(\\sqrt{\\frac{\\var{g}}{\\var{l}}-\\beta^2}\\; t\\right)\\text{,} \\]

\n

with

\n

\\[ \\beta = \\frac{k}{2m} = \\frac{\\var{k}}{2\\times\\var{m}} = \\var{precround(beta,2)}\\text{.}\\]

\n

e)

\n

The amplitude of the oscillation is at 5% of the initial release angle when

\n

\\[ e^{-\\beta t} = 0.05\\text{.} \\]

\n

The time taken is therefore

\n

\\[ t = -\\frac{\\ln{(0.05)}}{\\beta}=-\\frac{\\ln{(0.05)}}{\\var{precround(beta,2)}} = \\var{precround(damping5,2)}\\text{ s.} \\]

\n

", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"g": {"name": "g", "group": "Ungrouped variables", "definition": "9.81", "description": "

gravitational acceleration (ms^-2)

", "templateType": "number", "can_override": false}, "T": {"name": "T", "group": "Ungrouped variables", "definition": "2*pi*sqrt(l/g)", "description": "

Time period of the undamped oscillations (seconds)

", "templateType": "anything", "can_override": false}, "theta0": {"name": "theta0", "group": "Ungrouped variables", "definition": "pi/theta0_frac", "description": "

Release angle of the pendulum

", "templateType": "anything", "can_override": false}, "m": {"name": "m", "group": "Ungrouped variables", "definition": "random(2..6)", "description": "

mass of the bob (kg)

", "templateType": "anything", "can_override": false}, "theta0_frac": {"name": "theta0_frac", "group": "Ungrouped variables", "definition": "random(3,5,6)", "description": "

Question displays pi/theta0_frac.

", "templateType": "anything", "can_override": false}, "is_under_damped": {"name": "is_under_damped", "group": "damping", "definition": "(g/l)-k/(2*m) > 0", "description": "

Is the system under-damped? (this should be true)

", "templateType": "anything", "can_override": false}, "damping5": {"name": "damping5", "group": "damping", "definition": "-ln(0.05)/beta", "description": "

Time taken for amplitude to reduce to 5% of original.

", "templateType": "anything", "can_override": false}, "l": {"name": "l", "group": "Ungrouped variables", "definition": "random(3..6)", "description": "

length of the pendulum rod (m)

", "templateType": "anything", "can_override": false}, "damping0p01": {"name": "damping0p01", "group": "damping", "definition": "abs(log(0.0001))/beta", "description": "

Time taken for amplitude to reduce to 0.001% of original.

", "templateType": "anything", "can_override": false}, "beta": {"name": "beta", "group": "damping", "definition": "k/(2*m)", "description": "

decay rate

", "templateType": "anything", "can_override": false}, "k": {"name": "k", "group": "damping", "definition": "random(2..5)", "description": "

friction coefficient (kgs-1)

", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["g", "l", "m", "T", "theta0_frac", "theta0"], "variable_groups": [{"name": "damping", "variables": ["k", "beta", "damping5", "damping0p01", "is_under_damped"]}], "functions": {"jsx_pendulum": {"parameters": [], "type": "html", "language": "javascript", "definition": "// Get Numbas variables\nvar g = question.unwrappedVariables.g; // grav acc.\nvar l = question.unwrappedVariables.l; // length of rod\nvar m = question.unwrappedVariables.m; // mass of bob\nvar theta0 = question.unwrappedVariables.theta0; // initial angle\n\n// Set up board\nvar div = Numbas.extensions.jsxgraph.makeBoard('600px','250px',\n {\n boundingBox:[-5, 0.2, 9, -6],\n axis:false,\n showNavigation:false,\n grid:false\n }\n);\n\nvar board = div.board; \n\nboard.options = JXG.merge(board.options,{\n elements: {\n fixed: true\n },\n point: {\n showInfobox: false\n },\n text: {\n highlightStrokeOpacity: 1\n }\n});\n\n\n// Pendulum 1: exact solution \nvar p3 = board.create('point', [0.02, 0], {visible:false, size: 3});\nvar c2 = board.create('circle', [p3, [0.02,5]], {visible:false, name: 'circle', size: 3});\nvar pp4 = board.create('glider', [0.02,5, c2], {visible: true, name: '', size: 8, color: 'red', highlightFillColor: 'red', strokeWidth: 0, highlightStrokeWidth: 0});\n\n\n// Pendulum 2: student solution\nvar p1 = board.create('point', [0, 0], {visible:false, size: 3});\nvar c1 = board.create('circle', [p1, [0,5]], {visible:false, name: 'circle', size: 3});\nvar pp2 = board.create('glider', [0,5, c1], {visible: true, name: '', size: 8, color: '#91bcd8', highlightFillColor: '#91bcd8', strokeWidth: 0, highlightStrokeWidth: 0});\n\n// Decor\nvar line1 = board.create('line', [[-2,0],[2,0]],{color: 'grey', highlightStrokeColor: 'grey',straightFirst:false, straightLast:false, strokeWidth: 10});\nvar line2 = board.create('line', [[0.02,0],[0.02,-5]],{color: 'grey', highlightStrokeColor: 'grey',straightFirst:false, straightLast:false, strokeWidth: 1, dash:1});\n\n// Pendulum rods\nvar line3 = board.create('line', [p3, pp4], {visible:true, straightFirst: false,straightLast: false, color: 'red', highlightStrokeColor: 'red', strokeWidth: 3});\nvar line4 = board.create('line', [p1, pp2], {visible:true, straightFirst: false,straightLast: false, color: '#91bcd8', highlightStrokeColor: '#91bcd8', strokeWidth: 3});\n\n// Info panel \nvar tt2 = board.create('text',[5,-0.3,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt3 = board.create('text',[5.5,-1.5,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt4 = board.create('text',[5.5,-2,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 13});\nvar tt5 = board.create('text',[5.5,-3.5,''],{visible: false, color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt6 = board.create('text',[5.5,-4,''],{visible: false, color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt7 = board.create('text',[5.5,-1,'Correct solution'],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt8 = board.create('text',[5.5,-3,'Your solution'],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar tt9 = board.create('text',[5.5,-4,'Enter an answer below to preview your solution.'],{color: '#AAA', highlightStrokeColor: '#aaa', fontSize: 14});\n\n// Shaded background\nvar sq = board.create('polygon',[[4.5,-5],[9,-5],[9,0.2],[4.5,0.2]], {color: '#DDD', highlightFillColor: '#ddd', vertices: {visible: false},borders: {strokeWidth: 3,lineCap: 'round',visible: false}});\n\n// Pendulum icons\nvar p5 = board.create('point', [5, -1.5], {color: '#91bcd8', highlightFillColor: '#91bcd8', highlightStrokeWidth:0, strokeWidth: 0, size: 8, name: ''});\nvar p6 = board.create('point', [5, -3.5], {color: 'red', highlightFillColor: 'red', size: 8, highlightStrokeWidth:0, strokeWidth: 0, name: ''});\nvar l5 = board.create('line', [p5, [p5.X(),p5.Y()+0.5]], {straightFirst: false,straightLast: false, color: '#91bcd8', highlightStrokeColor: '#91bcd8', strokeWidth: 3});\nvar l6 = board.create('line', [p6, [p6.X(),p6.Y()+0.5]], {straightFirst: false,straightLast: false, color: 'red', highlightStrokeColor: 'red', strokeWidth: 3});\n\n// Start button\nvar button1 = board.create('button', [-4.9,-1, '► Restart', function() {\n startAnimation(theta0);\n board.update();\n}], {fontSize: 16});\n\nvar isInDragMode = false;\n\n// Get the student's function (t is the independant variable)\nvar tree;\nvar nscope = new Numbas.jme.Scope([Numbas.jme.builtinScope]);\nfunction userf(t){\n if(tree) {\n try {\n var val = nscope.evaluate(tree, {t:t});\n if(val.type!=='number') {\n throw(new Error(\"not a number\"));\n }\n return val.value;\n }\n catch(e) {\n return 0;\n }\n } else {\n return 0;\n }\n}\n\n\n// The animation\nfunction startAnimation(start_pos) {\n // Run animations \n var duration = 0.5 * 1e5; \n\n // Path of the correct solution\n pp2.moveAlong(function() {\n return function(t) {\n if (t >= duration) {\n // Restart the animation\n startAnimation(start_pos);\n }\n t = t/1000;\n var angle1 = start_pos*Math.cos(Math.sqrt(g/l) * t);\n var angled1 = -Math.sqrt(g/l)*start_pos*Math.sin(Math.sqrt(g/l) * t);\n var angle2 = -Math.PI/2+angle1;\n tt2._setUpdateText('t = '+t.toFixed(0)+'s');\n tt3._setUpdateText('θ = '+angle1.toFixed(1)+'rad');\n tt4._setUpdateText('dθ/dt = '+angled1.toFixed(1)+'rads-1');\n return [p1.X()+l*Math.cos(angle2),p1.Y()+l*Math.sin(angle2)];\n }; \n }());\n\n // Path of the student's solution\n pp4.moveAlong(function() { \n return function(t) {\n if (t >= duration) {\n // Restart the animation\n startAnimation(start_pos);\n }\n t = t/1000;\n var utheta = userf(t);\n angle1=-Math.PI/2+utheta;\n angled1=(utheta-userf(t-0.001))/0.001;\n tt5._setUpdateText('θ = '+utheta.toFixed(1)+'rad');\n tt6._setUpdateText('dθ/dt = '+angled1.toFixed(1)+'rads-1'); \n return [p3.X()+l*Math.cos(angle1),p3.Y()+l*Math.sin(angle1)];\n }; \n }());\n}\n\n//pick up the student answer\nquestion.signals.on('HTMLAttached',function(e) {\n startAnimation(theta0); \n ko.computed(function(){\n var expr = question.getPart('p0g0').display.studentAnswer();\n try {\n tree = Numbas.jme.compile(expr,scope);\n }\n catch(e) {\n tree = null;\n }\n\n if(tree){\n startAnimation(theta0);\n tt5.setAttribute({visible: true});\n tt6.setAttribute({visible: true});\n tt9.setAttribute({visible: false});\n board.update();\n } else {\n tt9.setAttribute({visible: true});\n tt5.setAttribute({visible: false});\n tt6.setAttribute({visible: false});\n }\n\n });\n}); \n\n\nreturn div;\n\n"}, "jsx_pendulum2": {"parameters": [], "type": "html", "language": "javascript", "definition": "// Get Numbas variables\nvar g = question.unwrappedVariables.g; // grav acc.\nvar l = question.unwrappedVariables.l; // length of rod\nvar m = question.unwrappedVariables.m; // mass of bob\nvar theta0 = question.unwrappedVariables.theta0; // initial angle\nvar k = question.unwrappedVariables.k; // friction coefficient\nvar damping0p01 = question.unwrappedVariables.damping0p01;\n\n// Set up board\nvar div = Numbas.extensions.jsxgraph.makeBoard('600px','250px',\n {\n boundingBox:[-5, 0.2, 9, -6],\n axis:false,\n showNavigation:false,\n grid:false\n }\n);\n\nvar board2 = div.board; \n\nboard2.options = JXG.merge(board2.options,{\n elements: {\n fixed: true\n },\n point: {\n showInfobox: false\n },\n text: {\n highlightStrokeOpacity: 1\n }\n});\n\n// Pendulum 1: exact solution \nvar p3 = board2.create('point', [0.02, 0], {visible:false, size: 3});\nvar c2 = board2.create('circle', [p3, [0.02,5]], {visible:false, name: 'circle', size: 3});\nvar p4 = board2.create('glider', [0.02,5, c2], {visible: true, name: '', size: 8, color: 'red', highlightFillColor: 'red', strokeWidth: 0, highlightStrokeWidth: 0});\n\n\n// Pendulum 2: student solution\nvar p1 = board2.create('point', [0, 0], {visible:false, size: 3});\nvar c1 = board2.create('circle', [p1, [0,5]], {visible:false, name: 'circle', size: 3});\nvar p2 = board2.create('glider', [0,5, c1], {visible: true, name: '', size: 8, color: '#91bcd8', highlightFillColor: '#91bcd8', strokeWidth: 0, highlightStrokeWidth: 0});\n\n// Decor\nvar l1 = board2.create('line', [[-2,0],[2,0]],{color: 'grey', highlightStrokeColor: 'grey',straightFirst:false, straightLast:false, strokeWidth: 10});\nvar l2 = board2.create('line', [[0.02,0],[0.02,-5]],{color: 'grey', highlightStrokeColor: 'grey',straightFirst:false, straightLast:false, strokeWidth: 1, dash:1});\n//t1 = board2.create('text',[4,-2,\"Enter a solution for θ(t) in the box below to preview your solution\"],{color: 'grey', fontSize: 16});\n\n// Pendulum rods\nvar l3 = board2.create('line', [p3, p4], {visible:true, straightFirst: false,straightLast: false, color: 'red', highlightStrokeColor: 'red', strokeWidth: 3});\nvar l4 = board2.create('line', [p1, p2], {visible:true, straightFirst: false,straightLast: false, color: '#91bcd8', highlightStrokeColor: '#91bcd8', strokeWidth: 3});\n\n// Info panel \nvar t2 = board2.create('text',[5,-0.3,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t3 = board2.create('text',[5.5,-1.5,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t4 = board2.create('text',[5.5,-2,''],{color: '#444', highlightStrokeColor: '#444', fontSize: 13});\nvar t5 = board2.create('text',[5.5,-3.5,''],{visible: false, color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t6 = board2.create('text',[5.5,-4,''],{visible: false, color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t7 = board2.create('text',[5.5,-1,'Correct solution'],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t8 = board2.create('text',[5.5,-3,'Your solution'],{color: '#444', highlightStrokeColor: '#444', fontSize: 14});\nvar t9 = board2.create('text',[5.5,-4,'Enter an answer below to preview your solution.'],{color: '#AAA', highlightStrokeColor: '#AAA', fontSize: 14});\n\n// Shaded background\nvar sq = board2.create('polygon',[[4.5,-5],[9,-5],[9,0.2],[4.5,0.2]], {color: '#DDD', highlightFillColor: '#DDD', vertices: {visible: false},borders: {strokeWidth: 3,lineCap: 'round',visible: false}});\n\n// Pendulum icons\nvar p5 = board2.create('point', [5, -1.5], {color: '#91bcd8', highlightFillColor: '#91bcd8', size: 8, name: '', strokeWidth: 0, highlightStrokeWidth: 0});\nvar p6 = board2.create('point', [5, -3.5], {color: 'red', highlightFillColor: 'red', size: 8, name: '', strokeWidth: 0, highlightStrokeWidth: 0});\nvar l5 = board2.create('line', [p5, [p5.X(),p5.Y()+0.5]], {straightFirst: false,straightLast: false, color: '#91bcd8', highlightStrokeColor: '#91bcd8', strokeWidth: 3});\nvar l6 = board2.create('line', [p6, [p6.X(),p6.Y()+0.5]], {straightFirst: false,straightLast: false, color: 'red', highlightStrokeColor: 'red', strokeWidth: 3});\n\n// Start button\nbutton1 = board2.create('button', [-4.9,-1, '► Restart', function() {\n startAnimation2(theta0);\n board2.update();\n }], {fontSize: 16, fixed: true}),\n\n\nisInDragMode = false;\n\n// the student's beta\nvar student_beta = null;\n\n// The animation\nfunction startAnimation2(start_pos) {\n\n var duration = 1e5; \n\n // Path of the correct solution\n p2.moveAlong(function() {\n return function(t) {\n if (t >= duration) {\n // Restart the animation\n startAnimation2(start_pos);\n }\n t = t/1000;\n var beta = k/(2*m);\n // Calculate theta \n var angle1= start_pos*Math.exp(-beta*t)*Math.cos(Math.sqrt((g/l)-beta) * t);\n var angle2=-Math.PI/2+angle1;\n t2._setUpdateText('t = '+t.toFixed(0)+'s');\n t3._setUpdateText('θ = '+angle1.toFixed(1)+'rad');\n\n if(t>0.01){\n // Fudge dtheta/dt\n var anglelast = start_pos*Math.exp(-beta*(t-0.01))*Math.cos(Math.sqrt((g/l)-beta) * (t-0.01) );\n var anglediff = (angle1-anglelast)/0.01; \n t4._setUpdateText('dθ/dt = '+anglediff.toFixed(1)+'rads-1');\n }\n return [p1.X()+l*Math.cos(angle2),p1.Y()+l*Math.sin(angle2)];\n }; \n }()\n );\n\n // Path of the student's solution\n p4.moveAlong(function() { \n return function(t) {\n if (t >= duration) {\n // Restart the animation\n startAnimation2(start_pos); \n }\n t = t/1000;\n try {\n if(student_beta===null) {\n throw(new Error(\"beta is not set\"));\n }\n var beta = student_beta || 0;\n var angle1 = start_pos*Math.exp(-beta*t)*Math.cos(Math.sqrt((g/l)-beta) * t);\n var angle2 = -Math.PI/2+angle1;\n\n if(isNaN(angle1) || isNaN(angle2)) {\n throw(new Error(\"angle NaN\"));\n }\n t5._setUpdateText('θ = '+angle1.toFixed(1)+'rad');\n\n if(t>0.01){\n // Fudge dtheta/dt\n anglelast= start_pos*Math.exp(-beta*(t-0.01))*Math.cos(Math.sqrt((g/l)-beta) * (t-0.01) );\n anglediff = (angle1-anglelast)/0.01; \n t6._setUpdateText('dθ/dt = '+anglediff.toFixed(1)+'rads-1');\n } \n\n return [p3.X()+l*Math.cos(angle2),p3.Y()+l*Math.sin(angle2)];\n } catch(e) {\n t5._setUpdateText('θ is not a real number!');\n t6._setUpdateText('');\n return [p3.X(),p3.Y()-l];\n }\n }; \n }());\n\n\n}\n\n// Start the animation with initial condition\nstartAnimation2(theta0);\n\n//pick up the student answer\nquestion.signals.on('HTMLAttached',function(e) {\n var part = question.getPart('p3g0');\n ko.computed(function(){\n var expr = part.display.studentAnswer();\n try {\n student_beta = Numbas.util.parseNumber(expr,part.settings.allowFractions,part.settings.allowFractions);\n if(isNaN(student_beta)) {\n throw(new Error(\"Not a number\"));\n }\n }\n catch(e) {\n student_beta = null;\n }\n console.log(student_beta);\n\n if(student_beta!==null){\n startAnimation2(theta0);\n t5.setAttribute({visible: true});\n t6.setAttribute({visible: true});\n t9.setAttribute({visible: false});\n board2.update();\n } else {\n t5.setAttribute({visible: false});\n t6.setAttribute({visible: false});\n t9.setAttribute({visible: true});\n board2.update();\n }\n\n });\n}); \n\n\nreturn div;\n\n"}}, "preamble": {"js": "", "css": ".JXGtext button{\n color: black;\n background-color: #a2d1f0;\n border: 1px solid #91bcd8;\n border-radius: 6px;\n}\n\n.JXGtext button:hover{\n background-color: #91bcd8;\n}"}, "parts": [{"type": "gapfill", "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": "

{jsx_pendulum()}

\n

You are told that $g=\\var{g}\\textrm{ms}^{-2}$ and that the length of the pendulum's rod $l = \\var{l}$ m. 

\n

Solve for $\\theta(t)$ with initial conditions $\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t}(0)=0$,  $\\theta(0)=\\frac{\\pi}{\\var{theta0_frac}}$. 

\n

$\\theta(t) = $ [[0]]

", "gaps": [{"type": "jme", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "answer": "(pi/{theta0_frac})*cos(sqrt({g}/{l})*t)", "answerSimplification": "all,!fractionnumbers", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": true, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "caseSensitive": false, "valuegenerators": [{"name": "t", "value": ""}]}], "sortAnswers": false}, {"type": "gapfill", "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": "

What is the time period of the undamped oscillations?

\n

$T = $ [[0]]s

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "T", "maxValue": "T", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": "2", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}, {"type": "gapfill", "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": "

Determine the maximum angular velocity of the bob.

\n

$\\left(\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t}\\right)_{\\text{max}} = $ [[0]] rad s$^{-1}$.

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{theta0*sqrt(g/l)}", "maxValue": "{theta0*sqrt(g/l)}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": "2", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}, {"type": "gapfill", "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": "

Introducing a friction coefficient, $k$, that is proportional to the speed of the bob, the equation of motion becomes

\n

\\[ \\frac{\\mathrm{d}^2\\theta}{\\mathrm{d}t^2}+\\frac{k}{m}\\frac{\\mathrm{d}\\theta}{\\mathrm{d}t}+\\frac{g}{l}\\theta = 0\\text{.} \\]

\n

Let $k=\\var{k}\\textrm{kg s}^{-1}$ and $m=\\var{m}$kg. The initial conditions in part (a) yield the solution

\n

\\[\\theta(t) = \\frac{\\pi}{\\var{theta0_frac}}e^{-\\beta t}\\cos\\left(t \\;\\sqrt{\\frac{\\var{g}}{\\var{l}}-\\beta^2}\\right)\\text{.} \\]

\n

Determine the value of $\\beta$.

\n

$\\beta = $ [[0]]

\n

{jsx_pendulum2()}

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{k/(2*m)}", "maxValue": "{k/(2*m)}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": "2", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}, {"type": "gapfill", "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": "

After how long do the amplitude of oscillations decay to 5% of the initial release angle?

\n

[[0]]s

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{damping5}", "maxValue": "{damping5}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": "2", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Graph of a quadratic function", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": ["JSXgraph", "jsxgraph", "Jsxgraph", "plot", "quadratic"], "metadata": {"description": "

Compute a table of values for a quadratic function. A JSXgraph plot shows the curve going through the entered values.

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

You are given the quadratic formula

\n

$y=\\simplify[std]{{a}x^2+{c}}$

", "advice": "", "rulesets": {"std": ["all", "fractionNumbers"]}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"a": {"name": "a", "group": "Ungrouped variables", "definition": "random(-2,-1,-0.5,0.5,1,2)", "description": "", "templateType": "anything", "can_override": false}, "c": {"name": "c", "group": "Ungrouped variables", "definition": "random(-4..4 except 0)", "description": "", "templateType": "anything", "can_override": false}, "ys": {"name": "ys", "group": "Ungrouped variables", "definition": "map(a*x^2+c,x,-3..3)", "description": "

The $y$-coordinates of the points to plot.

", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["a", "c", "ys"], "variable_groups": [], "functions": {}, "preamble": {"js": "function dragpoint_board() {\n var scope = question.scope;\n \n var a = scope.variables.a.value;\n var c = scope.variables.c.value;\n var maxy = Math.max(Math.abs(a*9+c),Math.abs(c));\n \n var div = Numbas.extensions.jsxgraph.makeBoard('250px','400px',{boundingBox:[-5,maxy+3,5,-maxy-3],grid:true});\n $(question.display.html).find('#dragpoint').append(div);\n \n var board = div.board;\n \n //shorthand to evaluate a mathematical expression to a number\n function evaluate(expression) {\n try {\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\n var num_points = 7;\n var points = [];\n \n \n // this function sets up the i^th point\n function make_point(i) {\n \n // calculate initial coordinates\n var x = i-(num_points-1)/2;\n \n // create an invisible vertical line for the point to slide along\n var line = board.create('line',[[x,0],[x,1]],{visible: false});\n \n // create the point\n var point = points[i] = board.create(\n 'glider',\n [i-(num_points-1)/2,0,line],\n {\n name:'',\n size:2,\n snapSizeY: 0.1, // the point will snap to y-coordinates which are multiples of 0.1\n snapToGrid: true\n }\n );\n \n // the contents of the input box for this point\n var studentAnswer = question.parts[1].gaps[i].display.studentAnswer;\n \n // watch the student's input and reposition the point when it changes. \n ko.computed(function() {\n y = evaluate(studentAnswer());\n if(!(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 y = Numbas.math.niceNumber(point.Y());\n studentAnswer(y);\n });\n \n }\n \n // create each point\n for(var i=0;iThe graph of this formula is:

", "minMarks": 0, "maxMarks": 1, "shuffleChoices": false, "displayType": "radiogroup", "displayColumns": 0, "showCellAnswerState": true, "choices": ["

An upwards-opening parabola

", "

A downwards-opening parabola

"], "matrix": ["if(a>0,1,0)", "if(a>0,0,1)"], "distractors": ["", ""]}, {"type": "gapfill", "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": "

Fill in the table of values for $y=\\simplify[std]{{a}x^2+{c}}$:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
$x$$-3$$-2$$-1$$0$$1$$2$$3$
$y$[[0]][[1]][[2]][[3]][[4]][[5]][[6]]
\n
", "gaps": [{"type": "numberentry", "useCustomName": true, "customName": "$x=-3$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[0]", "maxValue": "ys[0]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=-2$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[1]", "maxValue": "ys[1]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=-1$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[2]", "maxValue": "ys[2]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=0$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[3]", "maxValue": "ys[3]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=1$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[4]", "maxValue": "ys[4]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=2$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[5]", "maxValue": "ys[5]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "$x=3$", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "ys[6]", "maxValue": "ys[6]", "correctAnswerFraction": false, "allowFractions": true, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}, {"type": "matrix", "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": "

Give the coordinates of the turning point of the parabola.

", "correctAnswer": "matrix([0,c])", "correctAnswerFractions": false, "numRows": 1, "numColumns": "2", "allowResize": false, "tolerance": 0, "markPerCell": false, "allowFractions": true, "minColumns": 1, "maxColumns": 0, "minRows": 1, "maxRows": 0}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Use student input in a JSXGraph diagram", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}], "tags": ["graphs", "JSXgraph", "jsxgraph", "Jsxgraph"], "metadata": {"description": "

There are copious comments in the definition of the function eqnline about the voodoo needed to have a JSXGraph diagram interact with the input box for a part.

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

{eqnline(a,b,x2,y2)}

\n

The above graph shows a line which has an equation of the form $y=ax+b$, where $a$ and $b$ are integers.

\n

You are given two points on the line, $(0,\\var{b})$ and $(\\var{x2},\\var{y2})$, as indicated on the diagram.

", "advice": "\n

First Method.

\n

You are given that the line goes through $(0,\\var{b})$ and $(-1,\\var{b-a})$ and the equation of the line is of the form $y=ax+b$

\n

Hence:

\n

1) At $x=0$ we have $y=\\var{b}$, and this gives $\\var{b}=a \\times 0 +b =b$ on putting $x=0$ into $y=ax+b$.

\n

So $b=\\var{b}$.

\n

2) At $x=-1$ we have $y=\\var{b-a}$, and this gives $\\var{b-a}=a \\times (-1) +b =\\simplify[all,!collectNumbers]{-a+{b}}$ on putting $x=-1$ into $y=ax+b$.

\n

On rearranging we obtain $a=\\simplify[all,!collectNumbers]{{b}-{b-a}}=\\var{a}$. 

\n

So $a=\\var{a}$.

\n

So the equation of the line is $\\simplify{y={a}*x+{b}}$.

\n

Second Method.

\n

The equation $y=ax+b$ tells us that the graph crosses the $y$-axis (when $x=0$) at $y=b$.

\n

So looking at the graph we immediately see that $b=\\var{b}$.

\n

$a$ is the gradient of the line and is given by the change from $(-1,\\var{b-a})$ to $(0,\\var{b})$:

\n

\\[a=\\frac{\\text{Change in y}}{\\text{Change in x}}=\\frac{\\simplify[all,!collectNumbers]{({b-a}-{b})}}{-1-0}=\\var{a}\\]

\n\n", "rulesets": {}, "variables": {"x2": {"name": "x2", "group": "Ungrouped variables", "definition": "random(-3..3 except -1..1)", "description": "", "templateType": "anything"}, "y2": {"name": "y2", "group": "Ungrouped variables", "definition": "x2*a+b", "description": "", "templateType": "anything"}, "b": {"name": "b", "group": "Ungrouped variables", "definition": "random(-6..6 except [0,a])", "description": "", "templateType": "anything"}, "a": {"name": "a", "group": "Ungrouped variables", "definition": "random(-4..4 except 0)", "description": "", "templateType": "anything"}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["x2", "b", "a", "y2"], "variable_groups": [], "functions": {"eqnline": {"parameters": [["a", "number"], ["b", "number"], ["x2", "number"], ["y2", "number"]], "type": "html", "language": "javascript", "definition": "// This function creates the board and sets it up, then returns an\n// HTML div tag containing the board.\n \n// The line is described by the equation \n// y = a*x + b\n\n// This function takes as its parameters the coefficients a and b,\n// and the coordinates (x2,y2) of a point on the line.\n\n// First, make the JSXGraph board.\n// The function provided by the JSXGraph extension wraps the board up in \n// a div tag so that it's easier to embed in the page.\nvar div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',\n{boundingBox: [-13,16,13,-16],\n axis: false,\n showNavigation: false,\n grid: true\n});\n \n// div.board is the object created by JSXGraph, which you use to \n// manipulate elements\nvar board = div.board; \n\n// create the x-axis.\nvar xaxis = board.create('line',[[0,0],[1,0]], { strokeColor: 'black', fixed: true});\nvar xticks = board.create('ticks',[xaxis,2],{\n drawLabels: true,\n label: {offset: [-4, -10]},\n minorTicks: 0\n});\n\n// create the y-axis\nvar yaxis = board.create('line',[[0,0],[0,1]], { strokeColor: 'black', fixed: true });\nvar yticks = board.create('ticks',[yaxis,2],{\ndrawLabels: true,\nlabel: {offset: [-20, 0]},\nminorTicks: 0\n});\n\n// create the static line based on the coefficients a and b\nvar line1 = board.create('line',[[0,b],[1,a+b]],{fixed:true, strokeWidth: 1});\n\n// mark the two given points - one on the y-axis, and one at (x2,y2)\nvar p1 = board.create('point',[0,b],{fixed:true, size:3, name: 'P_1', face: 'cross'});\nvar p2 = board.create('point',[x2,y2],{fixed:true, size:3, name: 'P_2', face: 'cross'});\n\n// Now we can do the clever stuff with the student's answer!\n// We'll add a curve to the board which is a plot of a function we provide.\n// That function will parse the student's input and evaluate it.\n\n// The variable `studentExpression` will store the parsed version of\n// the student's expression.\nvar studentExpression;\n\n// This function evaluates the student's expression at a given point `t`.\nfunction makestudentline(x){\n // Create a JME scope with the variable x set to the given value.\n var nscope = new Numbas.jme.Scope([\nNumbas.jme.builtinScope,\n{variables: {x: new Numbas.jme.types.TNum(x)}}\n ]);\n \n // If the student's input has been parsed, evaluate it\n if(studentExpression) {\ntry {\n var val = Numbas.jme.evaluate(studentExpression,nscope).value;\n return val;\n}\ncatch(e) {\n // If there was an error evaluating the student's expression\n // (wrong variables, or some other weirdness)\n // throw an error\n throw(e)\n}\n }\n // Otherwise, if the student's expression hasn't been parsed\n // (they haven't written anything, or they wrote bad syntax)\n // return 0\n else {\nreturn 0;\n }\n}\nvar studentline = board.create('functiongraph', \n [makestudentline,-13,13],\n {strokeColor:'black', strokeWidth: 3, visible: false}\n );\n\n// This is where some voodoo happens.\n// Because the HTML for the question is inserted into the page after the function eqnline\n// is called, we need to wait until the 'question-html-attached' event is fired\n// to do the interaction with the student input box.\n// So:\n\n// When the question is inserted into the page\nquestion.signals.on('HTMLAttached',function(e) {\n\n // Create a Knockout.js observable\n ko.computed(function(){\n // Get the student's input string from part 0, gap 0.\n var studentString = question.getPart('p0g0').display.studentAnswer();\n\n // Try to parse it as a JME expression\n try {\n studentExpression = Numbas.jme.compile(studentString,scope);\n\n // If the student didn't write anything, compile returns null\n if(studentExpression === null)\n throw(new Error('no expression'));\n\n // If everything worked, show the line and update it\n // (this calls makestudentline on a few points)\n studentline.showElement();\n studentline.updateCurve();\n }\n catch(e) {\n // If something went wrong, hide the curve\n studentExpression = null;\n studentline.hideElement();\n }\n\n board.update();\n });\n}); \n\nreturn div;"}}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "gapfill", "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": "

Write the equation of the line in the diagram. The line described by your equation will also be drawn on the diagram.

\n

$y=\\;$[[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": "{a}x+{b}", "answerSimplification": "all", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": [{"name": "x", "value": ""}]}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always"}, {"name": "Link a JSXGraph diagram to part inputs", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "tags": [], "metadata": {"description": "", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "

{diagram}

", "advice": "", "rulesets": {}, "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"diagram": {"name": "diagram", "group": "Ungrouped variables", "definition": "jessiecode(400,400,\"\"\"\n\n A = point(0,0) <>;\n C = circle(A,1) <>;\n \n P = point({p[0]},{p[1]}) <>;\n \n guide = circle(P,1) <>;\n\"\"\")", "description": "", "templateType": "anything", "can_override": false}, "p": {"name": "p", "group": "Ungrouped variables", "definition": "vector(random(0..4),random(1..4))", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["diagram", "p"], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "gapfill", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "centre: jxg_position(diagram[\"A\"])\n\nradius: jxg_radius(diagram[\"C\"])\n\nin_right_quadrant:\n if(centre[0]>0 and centre[1]>0,\n add_credit(1/2, \"The centre of your circle is in the top-right quadrant.\")\n , negative_feedback(\"Your circle is not in the top-right quadrant.\")\n )\n\ntouches_point:\n if(isclose(len(centre-p),radius),\n add_credit(1/2, \"Your circle is touching the point.\")\n , negative_feedback(\"Your circle is not touching the point.\")\n )\n\nmark:\n apply(in_right_quadrant);\n apply(touches_point)\n\ninterpreted_answer: [centre, radius]", "extendBaseMarkingAlgorithm": false, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Make the circle touch the point $P = \\var[rowvector]{p}$. The circle's centre must be in the top-right quadrant of the graph.

\n

You can change its radius and the position of its centre.

\n

Radius: [[0]]

\n

Coordinates of the centre: [[1]]

", "stepsPenalty": 0, "steps": [{"type": "m_n_2", "useCustomName": true, "customName": "Show a hint", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "jxg_input:\n [\n jxg_show(diagram[\"guide\"], studentAnswer[0][0])\n ]", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

If you tick the box below, a circle with radius 1 centred on $P$ will be shown.

", "minMarks": 0, "maxMarks": 0, "shuffleChoices": false, "displayType": "checkbox", "displayColumns": 0, "minAnswers": 0, "maxAnswers": 0, "warningType": "none", "showCellAnswerState": true, "markingMethod": "sum ticked cells", "choices": ["Show the guide circle"], "matrix": [0], "distractors": [""]}], "gaps": [{"type": "numberentry", "useCustomName": true, "customName": "Radius", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "jxg_input:\n [\n jxg_set(diagram[\"C\"],\"Radius\",studentNumber)\n ]", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "1", "maxValue": "1", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "matrix", "useCustomName": true, "customName": "Coordinates of the centre", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "jxg_input:\n [ jxg_set_position(diagram[\"A\"],studentMatrix[0]) ]\n\njxg_output:\n let([x,y],jxg_position(diagram[\"A\"]),\n [[string(x),string(y)]]\n )", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "correctAnswer": "transpose(vector(0,0))", "correctAnswerFractions": false, "numRows": 1, "numColumns": "2", "allowResize": false, "tolerance": 0, "markPerCell": false, "allowFractions": false, "minColumns": 1, "maxColumns": 0, "minRows": 1, "maxRows": 0}], "sortAnswers": false}], "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": true, "startpassword": ""}, "timing": {"allowPause": true, "timeout": {"action": "none", "message": ""}, "timedwarning": {"action": "none", "message": ""}}, "feedback": {"showactualmark": true, "showtotalmark": true, "showanswerstate": true, "allowrevealanswer": true, "advicethreshold": 0, "intro": "", "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": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}], "extensions": ["jsxgraph", "mas-codeassess"], "custom_part_types": [], "resources": []}