From f1ea82cf7912c9714a216b670d1b3fa3ad10a546 Mon Sep 17 00:00:00 2001 From: Ken Holstein Date: Fri, 7 Jul 2017 20:57:12 -0400 Subject: [PATCH] dummy detectors for individual deep-dive and class-level displays (except for 'common errors') --- .../1416.brd} | 0 .../Lumilo/BKT_skill_and_error_tracker.js | 295 ++++++++++++++++++ .../Lumilo/current_problem_history.js | 153 +++++++++ HTML/Assets/Detectors/currentAttemptCount.js | 2 +- .../transaction_mailer_users.js | 3 +- .../mail-worker.js} | 0 .../transaction_mailer_users.js} | 2 +- HTML/detectorAdaptivityDemo1.html | 57 ---- HTML/fractionAddition.html | 2 +- 9 files changed, 453 insertions(+), 61 deletions(-) rename FinalBRDs/{detectorAdaptivityDemo1.brd => detector_adaptivity_demos/1416.brd} (100%) create mode 100644 HTML/Assets/Detectors/Lumilo/BKT_skill_and_error_tracker.js create mode 100644 HTML/Assets/Detectors/Lumilo/current_problem_history.js rename HTML/Assets/{mail-worker_updateVarTable.js => tutor_adaptivity/mail-worker.js} (100%) rename HTML/Assets/{transaction_mailer_users_updateVarTable.js => tutor_adaptivity/transaction_mailer_users.js} (98%) delete mode 100644 HTML/detectorAdaptivityDemo1.html diff --git a/FinalBRDs/detectorAdaptivityDemo1.brd b/FinalBRDs/detector_adaptivity_demos/1416.brd similarity index 100% rename from FinalBRDs/detectorAdaptivityDemo1.brd rename to FinalBRDs/detector_adaptivity_demos/1416.brd diff --git a/HTML/Assets/Detectors/Lumilo/BKT_skill_and_error_tracker.js b/HTML/Assets/Detectors/Lumilo/BKT_skill_and_error_tracker.js new file mode 100644 index 0000000..dbae14d --- /dev/null +++ b/HTML/Assets/Detectors/Lumilo/BKT_skill_and_error_tracker.js @@ -0,0 +1,295 @@ +//detector template + +//add output variable name below +var variableName = "BKT_skill_and_error_tracker"; + +//initializations (do not touch) +var detector_output = {name: variableName, + category: "Dashboard", + value: "0, none", + history: "", + skill_names: "", + step_id: "", + transaction_id: "", + time: "" + }; +var mailer; + +//declare any custom global variables that will be initialized +//based on "remembered" values across problem boundaries, here +// (initialize these at the bottom of this file, inside of self.onmessage) +var skillLevelsAttemptsErrors; +var onboardSkills; + +//declare and/or initialize any other custom global variables for this detector here... +var stepCounter = {}; +// +//[optional] single out TUNABLE PARAMETERS below +var BKTparams = {p_transit: 0.2, + p_slip: 0.1, + p_guess: 0.2, + p_know: 0.25}; + + +// +//############################### +//############################### +//############################### +//############################### +// + +function updateSkillLevelsAttemptsErrors(e){ + // + // + // to insert + // + // + // +} + +function updateSkillLevelsAttemptsErrors(e, rawSkills, currStepCount){ + for (var skill in rawSkills) { + if (rawSkills.hasOwnProperty(skill)){ + if( skill in skillLevelsAttemptsErrors ){ + if(currStepCount==1){ + skillLevelsAttemptsErrors[skill][0] += 1; + } + skillLevelsAttemptsErrors[skill][1] = parseFloat(rawSkills[skill]["p_know"]); + skillLevelsAttemptsErrors[skill][2].shift(); + skillLevelsAttemptsErrors[skill][2].push(format_error(e)); + } + else{ + skillLevelsAttemptsErrors[skill] = [1, parseFloat(rawSkills[skill]["p_know"]), [null, null, null, null, format_error(e)] ]; + } + } + } +} + +function format_areas_of_struggle_data(e){ + // + // + // to insert + // + // + // +} + +// +//############################### +//############################### +//############################### +//############################### +// + +function clone(obj) { + var copy; + + // Handle the 3 simple types, and null or undefined + if (null == obj || "object" != typeof obj) return obj; + + // Handle Date + if (obj instanceof Date) { + copy = new Date(); + copy.setTime(obj.getTime()); + return copy; + } + + // Handle Array + if (obj instanceof Array) { + copy = []; + for (var i = 0, len = obj.length; i < len; i++) { + copy[i] = clone(obj[i]); + } + return copy; + } + + // Handle Object + if (obj instanceof Object) { + copy = {}; + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]); + } + return copy; + } + + throw new Error("Unable to copy obj! Its type isn't supported."); +} + + + +function receive_transaction( e ){ + //e is the data of the transaction from mailer from transaction assembler + + //set conditions under which transaction should be processed + //(i.e., to update internal state and history, without + //necessarily updating external state and history) + if(e.data.actor == 'student' && e.data.tool_data.selection !="done" && e.data.tool_data.action != "UpdateVariable"){ + //do not touch + rawSkills = e.data.tutor_data.skills + var currSkills = [] + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + currSkills.push(rawSkills[property].name + "/" + rawSkills[property].category) + } + } + detector_output.skill_names = currSkills; + detector_output.step_id = e.data.tutor_data.step_id; + + //custom processing (insert code here) + + //######## BKT ########## + var currStep = e.data.tutor_data.selection; + for (var i in currSkills){ + var skill = currSkills[i]; + + if(!(currStep in stepCounter)){ + if (!(skill in onboardSkills)){ //if this skill has not been encountered before + onboardSkills[skill] = clone(BKTparams); + } + + var p_know_tminus1 = onboardSkills[skill]["p_know"]; + var p_slip = onboardSkills[skill]["p_slip"]; + var p_guess = onboardSkills[skill]["p_guess"]; + var p_transit = onboardSkills[skill]["p_transit"]; + + console.log(onboardSkills[skill]["p_know"]); + + + if (e.data.tutor_data.action_evaluation.toLowerCase()=="correct"){ + var p_know_given_obs = (p_know_tminus1*(1-p_slip))/( (p_know_tminus1*(1-p_slip)) + ((1-p_know_tminus1)*p_guess) ); + } + else{ + var p_know_given_obs = (p_know_tminus1*p_slip)/( (p_know_tminus1*p_slip) + ((1-p_know_tminus1)*(1-p_guess)) ); + } + + onboardSkills[skill]["p_know"] = p_know_given_obs + (1 - p_know_given_obs)*p_transit; + + //following TutorShop, round down to two decimal places + onboardSkills[skill]["p_know"] = Math.floor(onboardSkills[skill]["p_know"] * 100) / 100; + + console.log("engine BKT: ", e.data.tutor_data.skills[0].pKnown); + console.log(onboardSkills[skill]["p_know"]); + } + + } + + + //keep track of num attempts on each step + if(currStep in stepCounter){ + stepCounter[currStep] += 1; + } + else{ + stepCounter[currStep] = 1; + } + + //######################## + + //updateSkillLevelsAttemptsErrors(e, rawSkills, currStepCount); + + + //detector_output.value = format_areas_of_struggle_data(e); + + //PLACEHOLDER + var skill_1__name = "fakeSkill1"; + var skill_1__attempt_count = "22"; + var skill_1__error_history = " 2x + 3x = 10 \\n _____ = [x] @ 2x + 3x = 10 \\n _____ = [10x] @ 2x + 3x = 10 \\n [2x] = 10 @ 2x + 3x = 10 \\n [x] = 10 @ 2x + 3x = 10 \\n [5 + x] = 10"; + var skill_2__name = "fakeSkill2"; + var skill_2__attempt_count = "47"; + var skill_2__error_history = " 2x + 3x = 10 \\n _____ = [x] @ 2x + 3x = 10 \\n _____ = [10x] @ 2x + 3x = 10 \\n [2x] = 10 @ 2x + 3x = 10 \\n [x] = 10 @ 2x + 3x = 10 \\n [5 + x] = 10"; + var skill_3__name = "fakeSkill3"; + var skill_3__attempt_count = "172"; + var skill_3__error_history = " 2x + 3x = 10 \\n _____ = [x] @ 2x + 3x = 10 \\n _____ = [10x] @ 2x + 3x = 10 \\n [2x] = 10 @ 2x + 3x = 10 \\n [x] = 10 @ 2x + 3x = 10 \\n [5 + x] = 10"; + + var dummyValue1 = skill_1__name + "," + skill_1__attempt_count + "," + skill_1__error_history + ";" + skill_2__name + "," + skill_2__attempt_count + "," + skill_2__error_history; + var dummyValue2 = skill_3__name + "," + skill_3__attempt_count + "," + skill_3__error_history + ";" + skill_2__name + "," + skill_2__attempt_count + "," + skill_2__error_history; + var dummyValues = [dummyValue1, dummyValue2]; + detector_output.value = String(dummyValues[Math.floor(Math.random() * dummyValues.length)]); + + detector_output.history = JSON.stringify([skillLevelsAttemptsErrors, onboardSkills]); + + } + + //set conditions under which detector should update + //external state and history + if(e.data.actor == 'student' && e.data.tool_data.selection !="done" && e.data.tool_data.action != "UpdateVariable"){ + detector_output.time = new Date(); + detector_output.transaction_id = e.data.transaction_id; + + //custom processing (insert code here) + + + + mailer.postMessage(detector_output); + postMessage(detector_output); + console.log("output_data = ", detector_output); + } +} + + +self.onmessage = function ( e ) { + console.log(variableName, " self.onmessage:", e, e.data, (e.data?e.data.commmand:null), (e.data?e.data.transaction:null), e.ports); + switch( e.data.command ) + { + case "connectMailer": + mailer = e.ports[0]; + mailer.onmessage = receive_transaction; + break; + case "initialize": + for (initItem in e.data.initializer){ + if (e.data.initializer[initItem].name == variableName){ + detector_output.history = e.data.initializer[initItem].history; + detector_output.value = e.data.initializer[initItem].value; + } + } + + //optional: In "detectorForget", specify conditions under which a detector + //should NOT remember their most recent value and history (using the variable "detectorForget"). + //(e.g., setting the condition to "true" will mean that the detector + // will always be reset between problems... and setting the condition to "false" + // means that the detector will never be reset between problems) + // + detectorForget = false; + // + // + + if (detectorForget){ + detector_output.history = ""; + detector_output.value = null; + } + + + //optional: If any global variables are based on remembered values across problem boundaries, + // these initializations should be written here + // + // + if (detector_output.history == "" || detector_output.history == null){ + //in the event that the detector history is empty, + //initialize variables to your desired 'default' values + // + skillLevelsAttemptsErrors = {}; + onboardSkills = {}; + } + else{ + //if the detector history is not empty, you can access it via: + // JSON.parse(detector_output.history); + //...and initialize your variables to your desired values, based on + //this history + // + var all_history = JSON.parse(detector_output.history); + skillLevelsAttemptsErrors = all_history[0]; + onboardSkills = all_history[1]; + + } + + detector_output.time = new Date(); + mailer.postMessage(detector_output); + postMessage(detector_output); + console.log("output_data = ", detector_output); + + break; + default: + break; + + } + +} \ No newline at end of file diff --git a/HTML/Assets/Detectors/Lumilo/current_problem_history.js b/HTML/Assets/Detectors/Lumilo/current_problem_history.js new file mode 100644 index 0000000..04633cd --- /dev/null +++ b/HTML/Assets/Detectors/Lumilo/current_problem_history.js @@ -0,0 +1,153 @@ +//detector template + +//add output variable name below +var variableName = "current_problem_history" + +//initializations (do not touch) +var detector_output = {name: variableName, + category: "Dashboard", + value: "0, none", + history: "", + skill_names: "", + step_id: "", + transaction_id: "", + time: "" + }; +var mailer; + +//declare any custom global variables that will be initialized +//based on "remembered" values across problem boundaries, here +// (initialize these at the bottom of this file, inside of self.onmessage) +// +// +// +// +// + + +//declare and/or initialize any other custom global variables for this detector here +// +// +// +// +// + +function receive_transaction( e ){ + //e is the data of the transaction from mailer from transaction assembler + + //set conditions under which transaction should be processed + //(i.e., to update internal state and history, without + //necessarily updating external state and history) + if(e.data.actor == 'student' && e.data.tool_data.action != "UpdateVariable"){ + //do not touch + rawSkills = e.data.tutor_data.skills + var currSkills = [] + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + currSkills.push(rawSkills[property].name + "/" + rawSkills[property].category) + } + } + detector_output.skill_names = currSkills; + detector_output.step_id = e.data.tutor_data.step_id; + + //custom processing (insert code here) + // + // + // + // + // + var dummyStep1 = "3x + 3 = _____"; + var dummyStep2 = "3x + 3 = 24"; + var dummyStep3 = "3x + 3 = 24 \\n 3x = _____"; + var dummyStep4 = "3x + 3 = 24 \\n 3x = 24 -3"; + var dummyStep5 = "3x + 3 = 24 \\n 3x = 24 -3 \\n 3x = _____"; + var dummyStep6 = "3x + 3 = 24 \\n 3x = 24 -3 \\n 3x = 21"; + var dummyStep7 = "3x + 3 = 24 \\n 3x = 24 -3 \\n 3x = 21 \\n 3x [- 3] = _____"; + + var dummyValue1 = dummyStep1 + "," + dummyStep2 + "," + dummyStep3; + var dummyValue2 = dummyStep1 + "," + dummyStep2 + "," + dummyStep3 + "," + dummyStep4 + "," +dummyStep5 + "," + dummyStep6 + "," + dummyStep7; + + var dummyValues = [dummyValue1, dummyValue2]; + detector_output.value = String(dummyValues[Math.floor(Math.random() * dummyValues.length)]); + + + } + + //set conditions under which detector should update + //external state and history + if(e.data.actor == 'student' && e.data.tool_data.action != "UpdateVariable"){ + detector_output.time = new Date(); + detector_output.transaction_id = e.data.transaction_id; + + //custom processing (insert code here) + // + // + // + // + // + + mailer.postMessage(detector_output); + postMessage(detector_output); + console.log("output_data = ", detector_output); + } +} + + +self.onmessage = function ( e ) { + console.log(variableName, " self.onmessage:", e, e.data, (e.data?e.data.commmand:null), (e.data?e.data.transaction:null), e.ports); + switch( e.data.command ) + { + case "connectMailer": + mailer = e.ports[0]; + mailer.onmessage = receive_transaction; + break; + case "initialize": + for (initItem in e.data.initializer){ + if (e.data.initializer[initItem].name == variableName){ + detector_output.history = e.data.initializer[initItem].history; + detector_output.value = e.data.initializer[initItem].value; + } + } + + //optional: In "detectorForget", specify conditions under which a detector + //should NOT remember their most recent value and history (using the variable "detectorForget"). + //(e.g., setting the condition to "true" will mean that the detector + // will always be reset between problems... and setting the condition to "false" + // means that the detector will never be reset between problems) + // + detectorForget = true; + // + // + + if (detectorForget){ + detector_output.history = ""; + detector_output.value = 0; + } + + + //optional: If any global variables are based on remembered values across problem boundaries, + // these initializations should be written here + // + // + if (detector_output.history == "" || detector_output.history == null){ + //in the event that the detector history is empty, + //initialize variables to your desired 'default' values + // + // + } + else{ + //if the detector history is not empty, you can access it via: + // JSON.parse(detector_output.history); + //...and initialize your variables to your desired values, based on + //this history + // + // + } + + break; + default: + break; + + } + +} \ No newline at end of file diff --git a/HTML/Assets/Detectors/currentAttemptCount.js b/HTML/Assets/Detectors/currentAttemptCount.js index 44f7058..b42186d 100644 --- a/HTML/Assets/Detectors/currentAttemptCount.js +++ b/HTML/Assets/Detectors/currentAttemptCount.js @@ -106,7 +106,7 @@ self.onmessage = function ( e ) { // if (detectorForget){ - detector_output.history = ""; + detector_output.history = {}; detector_output.value = 0; } diff --git a/HTML/Assets/networking_for_replay/transaction_mailer_users.js b/HTML/Assets/networking_for_replay/transaction_mailer_users.js index c2539d0..f58faa4 100644 --- a/HTML/Assets/networking_for_replay/transaction_mailer_users.js +++ b/HTML/Assets/networking_for_replay/transaction_mailer_users.js @@ -12,7 +12,8 @@ TransactionMailerUsers = "Detectors/Lumilo/student_doing_well__moving_average.js", "Detectors/Lumilo/critical_struggle.js", "Detectors/Lumilo/invisible_hand_raise.js", - "Detectors/BKT.js"], + "Detectors/current_problem_history.js", + "Detectors/BKT_skill_and_error_tracker.js"], active: [] }; diff --git a/HTML/Assets/mail-worker_updateVarTable.js b/HTML/Assets/tutor_adaptivity/mail-worker.js similarity index 100% rename from HTML/Assets/mail-worker_updateVarTable.js rename to HTML/Assets/tutor_adaptivity/mail-worker.js diff --git a/HTML/Assets/transaction_mailer_users_updateVarTable.js b/HTML/Assets/tutor_adaptivity/transaction_mailer_users.js similarity index 98% rename from HTML/Assets/transaction_mailer_users_updateVarTable.js rename to HTML/Assets/tutor_adaptivity/transaction_mailer_users.js index 28ea8e2..2129cee 100644 --- a/HTML/Assets/transaction_mailer_users_updateVarTable.js +++ b/HTML/Assets/tutor_adaptivity/transaction_mailer_users.js @@ -3,7 +3,7 @@ TransactionMailerUsers = process_transactions_url: "", process_detectors_url: "", authenticity_token: "", - mailerURL: "mail-worker_updateVarTable.js", + mailerURL: "mail-worker.js", mailer: null, mailerPort: null, scripts: ["Detectors/currentAttemptCount.js", diff --git a/HTML/detectorAdaptivityDemo1.html b/HTML/detectorAdaptivityDemo1.html deleted file mode 100644 index 738f576..0000000 --- a/HTML/detectorAdaptivityDemo1.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - Fraction Addition - - - - - - - - - -
- Your browser does not support CTAT. Please update or use another browser. - -
- -
-
-
-
-
+
-
=
-
=
-
=
- -
-
-
-
- -
-
- -
-
- -
- -
-
-
-
-
-
- - diff --git a/HTML/fractionAddition.html b/HTML/fractionAddition.html index 1f6e4c6..f37a547 100644 --- a/HTML/fractionAddition.html +++ b/HTML/fractionAddition.html @@ -17,7 +17,7 @@ - +