// Numbas version: exam_results_page_options {"name": "Etain'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": [{"name": "Etain's copy of Upload data", "extensions": ["stats"], "functions": {}, "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.
"}, "ungrouped_variables": [], "rulesets": {}, "advice": "", "variable_groups": [], "statement": "This question will only work in browsers that support the HTML5 File API! For Internet Explorer users, that means version 10 onwards.
\nHow 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.
\nDownload 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.
", "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": {}, "variablesTest": {"maxRuns": 100, "condition": ""}, "showQuestionGroupNames": false, "question_groups": [{"name": "", "questions": [], "pickQuestions": 0, "pickingStrategy": "all-ordered"}], "tags": ["csv", "demo", "experiment", "statistics"], "parts": [{"showCorrectAnswer": true, "variableReplacementStrategy": "originalfirst", "prompt": "Your data
\nWeight (N) | Length (cm) |
---|---|
\n | \n |
$n$:
\n$\\sum x$:
\n$\\sum y$:
\n$\\sum x^2$:
\n$\\sum y^2$:
\n$\\sum xy$:
\n$\\alpha$:
\n$\\beta$:
\nCompute the following statistics from your data.
\n$\\sum x$ | \n$\\sum y$ | \n$\\sum x^2$ | \n$\\sum y^2$ | \n$\\sum xy$ | \n
---|---|---|---|---|
[[0]] | \n[[1]] | \n[[2]] | \n[[3]] | \n[[4]] | \n
Write an equation for the line of best fit through the data.
\n[[0]]
", "variableReplacements": [], "marks": 0, "scripts": {}, "type": "gapfill", "gaps": [{"showCorrectAnswer": true, "checkvariablenames": false, "vsetrange": [0, 1], "showpreview": true, "variableReplacements": [], "answer": "x", "checkingaccuracy": 0.001, "vsetrangepoints": 5, "expectedvariablenames": [], "marks": 1, "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"}}, "checkingtype": "absdiff", "type": "jme", "variableReplacementStrategy": "originalfirst"}]}], "type": "question", "contributors": [{"name": "Etain Kiely", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/1608/"}]}]}], "contributors": [{"name": "Etain Kiely", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/1608/"}]}