// Numbas version: exam_results_page_options {"name": "Tom's copy of Upload data", "extensions": ["stats"], "custom_part_types": [], "resources": [["question-resources/Data.csv", "/srv/numbas/media/question-resources/Data.csv"]], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"ungrouped_variables": [], "functions": {}, "parts": [{"variableReplacements": [], "scripts": {"mark": {"script": "var s = this.studentAnswer;\nvar compile = Numbas.jme.compile;\nvar match = Numbas.jme.display.matchTree(compile('??;left = ??;right'),compile(this.studentAnswer));\nconsole.log(match);", "order": "instead"}}, "marks": 0, "variableReplacementStrategy": "originalfirst", "prompt": "
\n

\n
\n

Your data

\n
\n\n\n\n\n\n\n\n\n\n\n
Weight (N)Length (cm)
\n
\n
\n

$n$:

\n

$\\sum x$:

\n

$\\sum y$:

\n

$\\sum x^2$:

\n

$\\sum y^2$:

\n

$\\sum xy$:

\n

$\\alpha$:

\n

$\\beta$:

\n
\n
\n
", "showCorrectAnswer": true, "type": "information"}, {"variableReplacements": [], "scripts": {}, "gaps": [{"variableReplacements": [], "type": "numberentry", "correctAnswerFraction": false, "minValue": "0", "showPrecisionHint": false, "maxValue": "0", "variableReplacementStrategy": "originalfirst", "allowFractions": false, "marks": 1, "showCorrectAnswer": true, "scripts": {"mark": {"script": "// get the computed stats\nvar stats = this.question.stats();\n// set the correct answer to the computed stat\nthis.settings.minvalue = stats.sx;\nthis.settings.maxvalue = stats.sx;\n// mark the student's answer\nNumberEntryPart.prototype.mark.apply(this);", "order": "instead"}}}, {"variableReplacements": [], "type": "numberentry", "correctAnswerFraction": false, "minValue": "0", "showPrecisionHint": false, "maxValue": "0", "variableReplacementStrategy": "originalfirst", "allowFractions": false, "marks": 1, "showCorrectAnswer": true, "scripts": {"mark": {"script": "var stats = this.question.stats();\nthis.settings.minvalue = stats.sy;\nthis.settings.maxvalue = stats.sy;\nNumberEntryPart.prototype.mark.apply(this);", "order": "instead"}}}, {"variableReplacements": [], "type": "numberentry", "correctAnswerFraction": false, "minValue": "0", "showPrecisionHint": false, "maxValue": "0", "variableReplacementStrategy": "originalfirst", "allowFractions": false, "marks": 1, "showCorrectAnswer": true, "scripts": {"mark": {"script": "var stats = this.question.stats();\nthis.settings.minvalue = stats.sxx;\nthis.settings.maxvalue = stats.sxx;\nNumberEntryPart.prototype.mark.apply(this);", "order": "instead"}}}, {"variableReplacements": [], "type": "numberentry", "correctAnswerFraction": false, "minValue": "0", "showPrecisionHint": false, "maxValue": "0", "variableReplacementStrategy": "originalfirst", "allowFractions": false, "marks": 1, "showCorrectAnswer": true, "scripts": {"mark": {"script": "var stats = this.question.stats();\nthis.settings.minvalue = stats.syy;\nthis.settings.maxvalue = stats.syy;\nNumberEntryPart.prototype.mark.apply(this);", "order": "instead"}}}, {"variableReplacements": [], "type": "numberentry", "correctAnswerFraction": false, "minValue": "0", "showPrecisionHint": false, "maxValue": "0", "variableReplacementStrategy": "originalfirst", "allowFractions": false, "marks": 1, "showCorrectAnswer": true, "scripts": {"mark": {"script": "var stats = this.question.stats();\nthis.settings.minvalue = stats.sxy;\nthis.settings.maxvalue = stats.sxy;\nNumberEntryPart.prototype.mark.apply(this);", "order": "instead"}}}], "marks": 0, "variableReplacementStrategy": "originalfirst", "prompt": "

Compute the following statistics from your data.

\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
$\\sum x$$\\sum y$$\\sum x^2$$\\sum y^2$$\\sum xy$
[[0]][[1]][[2]][[3]][[4]]
", "showCorrectAnswer": true, "type": "gapfill"}, {"variableReplacements": [], "scripts": {}, "gaps": [{"checkingaccuracy": 0.001, "variableReplacements": [], "answer": "x", "checkvariablenames": false, "marks": 1, "showpreview": true, "scripts": {"mark": {"script": "// get the computed stats from the student's data\nvar stats = question.stats();\n\n// check the student's answer is an equation\nthis.setCredit(0);\nvar rule = new jme.display.Rule('left=right',[],'left-right');\nvar match = rule.match(jme.compile(this.studentAnswer));\nif(!match) {\n this.markingComment('Your answer doesn\\'t look like an equation.');\n return;\n}\n\n// rearrange everything onto the left-hand side. We're in trouble if +y is on the right: I need my new pattern-matching algo!\nvar tree = {tok: new Numbas.jme.types.TOp('-'), args: [match.left,match.right]};\ntree = Numbas.jme.display.simplifyTree(tree,jme.collectRuleset('all',jme.builtinScope.rulesets),jme.builtinScope);\n// set the student's answer to the rearranged form\nthis.studentAnswer = jme.display.treeToJME(tree);\n\n// mark the answer (the correct answer was set in the preamble script as soon as the data were uploaded)\nJMEPart.prototype.mark.apply(this);", "order": "instead"}}, "variableReplacementStrategy": "originalfirst", "vsetrange": [0, 1], "expectedvariablenames": [], "vsetrangepoints": 5, "type": "jme", "showCorrectAnswer": true, "checkingtype": "absdiff"}], "marks": 0, "variableReplacementStrategy": "originalfirst", "prompt": "

Write an equation for the line of best fit through the data.

\n

[[0]]

", "showCorrectAnswer": true, "type": "gapfill"}], "statement": "

This question will only work in browsers that support the HTML5 File API! For Internet Explorer users, that means version 10 onwards.

\n

How does the length of a spring change when you suspend different masses from it? Make measurements of your spring's length when hanging various different weights from it.

\n

Download the data spreadsheet and open it in a program such as Microsoft Excel. Enter your data, save the file, and then upload it using the button below.

", "variable_groups": [], "variablesTest": {"maxRuns": 100, "condition": ""}, "rulesets": {}, "preamble": {"css": "#data-table {\n max-height: 30em;\n overflow-y: auto;\n display: inline-block;\n}\na, a:hover {\n color: blue;\n}\na:hover {\n text-decoration: underline;\n}", "js": "// read a csv file\nfunction readCSV(text) {\n var lines = text.split('\\n');\n return lines.map(function(line){return line.split(',')});\n}\n\n// wait until the question has been generated\nquestion.signals.on('HTMLAttached',function(e) {\n var display = question.display;\n\n // set up an observable for the data array\n var _data = display.data = ko.observableArray([]);\n \n // has the student uploaded data?\n display.gotData = ko.computed(function() {\n return _data().length>0;\n });\n \n // an observable object containing various computed statistics about the data - updates automatically when the data changes\n var stats = question.stats = ko.computed(function() {\n var data = _data();\n \n // weights are in the first column\n var weights = data.map(function(r){return r[0]});\n // lengths in the second column\n var lengths = data.map(function(r){return r[1]});\n \n // how many samples?\n var n = data.length;\n \n // components of the linear regression calculation\n var sx = jStat.sum(weights);\n var sy = jStat.sum(lengths);\n var sxx = jStat.sum(weights.map(function(x){return x*x}));\n var syy = jStat.sum(lengths.map(function(x){return x*x}));\n var sxy = jStat.sum(data.map(function(r){ return r[0]*r[1]}));\n \n // coefficients of the linear regression model\n var beta = (sxy - (sx*sy)/n)/(sxx-(sx*sx)/n);\n var alpha = (sy-beta*sx)/n;\n \n var stats = {\n sx: sx,\n sy: sy,\n sxx: sxx,\n syy: syy,\n sxy: sxy,\n alpha: alpha,\n beta: beta,\n n: data.length\n };\n \n return stats;\n });\n \n // format a number to 3 d.p.\n function niceNumber(n) {\n return Numbas.math.niceNumber(n,{precisionType: 'dp', precision: 3});\n }\n \n // set the correct answer to the part about the line of best fit - called whenever the data changes\n ko.computed(function() {\n var stats = question.stats();\n this.settings.correctAnswer = 'y - '+Numbas.math.niceNumber(stats.beta)+'x - '+Numbas.math.niceNumber(stats.alpha);\n this.display.correctAnswer = 'y = '+niceNumber(stats.beta)+'x + '+niceNumber(stats.alpha);\n },question.parts[2].gaps[0]);\n\n // code to read the file when it's uploaded\n $('#file').on('change',function(e) {\n var f = e.target.files[0];\n var reader = new FileReader();\n reader.onload = function(e) {\n var data = readCSV(e.target.result);\n _data(data.map(function(row){ return row.map(parseFloat)}).filter(function(row){return !isNaN(row[0])}));\n }\n reader.readAsText(f);\n });\n});"}, "variables": {}, "name": "Tom's copy of Upload data", "showQuestionGroupNames": false, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [], "pickQuestions": 0, "name": ""}], "type": "question", "advice": "", "extensions": ["stats"], "tags": ["csv", "demo", "experiment", "statistics"], "metadata": {"licence": "Creative Commons Attribution 4.0 International", "description": "

Get the student to upload their experimental data in a CSV file, then ask them to compute statistics on it.

"}, "contributors": [{"name": "Tom Stallard", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/841/"}]}]}], "contributors": [{"name": "Tom Stallard", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/841/"}]}