diff --git a/HTML/Assets/Detectors/Lumilo/Struggle/struggle__moving_average.js b/HTML/Assets/Detectors/Lumilo/Struggle/struggle__moving_average.js
deleted file mode 100644
index 200ab05..0000000
--- a/HTML/Assets/Detectors/Lumilo/Struggle/struggle__moving_average.js
+++ /dev/null
@@ -1,591 +0,0 @@
-//detector template
-
-//add output variable name below
-var variableName = "struggle"
-
-//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 attemptWindow;
-var intervalID;
-var onboardSkills;
-var initTime;
-
-//declare and/or initialize any other custom global variables for this detector here
-var stepCounter = {};
-var help_model_output;
-var help_variables = {"lastAction": "null",
- "lastActionTime": "",
- "seenAllHints": {},
- "lastHintLength": "",
- "lastSenseOfWhatToDo": false
- };
-var attemptCorrect;
-var elaborationString = " ";
-//
-//[optional] single out TUNABLE PARAMETERS below
-var windowSize = 10;
-var threshold = 3;
-var BKTparams = {p_transit: 0.2,
- p_slip: 0.1,
- p_guess: 0.2,
- p_know: 0.25};
-var errorThreshold = 2; //currently arbitrary
-var newStepThreshold = 1; //currently arbitrary
-var familiarityThreshold = 0.4;
-var senseOfWhatToDoThreshold = 0.6;
-var hintIsHelpfulPlaceholder = true; //currently a dummy value (assumption that hint is always helpful...)
-var seedTime = 25;
-
-
-//
-//###############################
-//##### Help model ######
-//###############################
-//###############################
-//
-
-//non-controversial
-function lastActionIsHint(e){
- if (help_variables.lastAction == "hint"){return true;}
- else{return false;}
-}
-function lastActionIsError(e){
- if (help_variables.lastAction == "error"){return true;}
- else{return false;}
-}
-function seenAllHintLevels(e){
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "hint"){
- if (e.data.tutor_data.selection in help_variables.seenAllHints){
- return help_variables.seenAllHints[e.data.tutor_data.selection];
- }
- else{return false;}
- }
- else{
- if (e.data.tool_data.selection in help_variables.seenAllHints){
- return help_variables.seenAllHints[e.data.tool_data.selection];
- }
- else{return false;}
- }
-}
-function isCorrect(e){
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "correct"){return true;}
- else{return false;}
-}
-
-function secondsSinceLastAction(e){
- var currTime = new Date();
- diff = currTime.getTime() - help_variables.lastActionTime.getTime();
- console.log("time elapsed: ", diff/1000)
- return (diff / 1000);
-}
-
-//less controversial
-function isDeliberate(e){
- var hintThreshold = (help_variables.lastHintLength/600)*60;
-
- if (lastActionIsError(e)){
- return (secondsSinceLastAction(e) > errorThreshold);
- }
- else if (lastActionIsHint(e)){
- return (secondsSinceLastAction(e) > hintThreshold);
- }
- else{
- return (secondsSinceLastAction(e) > newStepThreshold);
- }
-}
-
-//more controversial...
-function isFamiliar(e){
- var rawSkills = onboardSkills;
- for (var property in rawSkills) {
- if (rawSkills.hasOwnProperty(property)) {
- if (parseFloat(rawSkills[property]["p_know"])<=familiarityThreshold){
- return false;
- }
- }
- }
- return true;
-}
-
-function isLowSkillStep_All(e){
- var rawSkills = onboardSkills;
- for (var property in rawSkills) {
- if (rawSkills.hasOwnProperty(property)) {
- if (parseFloat(rawSkills[property]["p_know"])>=familiarityThreshold){
- return false;
- }
- }
- }
- return true;
-}
-
-function isLowSkillStep_Some(e){
- var rawSkills = onboardSkills;
- for (var property in rawSkills) {
- if (rawSkills.hasOwnProperty(property)) {
- if (parseFloat(rawSkills[property]["p_know"])<=familiarityThreshold){
- return true;
- }
- }
- }
- return false;
-}
-
-function hintIsHelpful(e){
- return hintIsHelpfulPlaceholder;
-}
-function lastActionUnclearFix(e){
- if (help_variables.lastSenseOfWhatToDo == false){return true;}
- else{return false;}
-}
-function senseOfWhatToDo(e){
- var sel = e.data.tutor_data.selection;
- var rawSkills = onboardSkills;
- for (var property in rawSkills) {
- if (rawSkills.hasOwnProperty(property)) {
- if (parseFloat(rawSkills[property]["p_know"])<=senseOfWhatToDoThreshold){
- return false;
- }
- }
- }
- return true;
-}
-
-//evaluation of each step
-function evaluateAction(e){
- var sel = e.data.tutor_data.selection;
- var outcome = e.data.tutor_data.action_evaluation.toLowerCase();
-
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "hint"){
- console.log("isHint")
- if (isDeliberate(e)){
- console.log("isDeliberate")
- if (!seenAllHintLevels(e) &&
- (!isFamiliar(e)
- || (lastActionIsError(e) && lastActionUnclearFix(e))
- || (lastActionIsHint(e) && !hintIsHelpful(e))) ){
- return "preferred/ask hint";
- }
- else if ( (isFamiliar(e) && !senseOfWhatToDo(e) )
- || (lastActionIsHint(e)) ){
- return "acceptable/ask hint";
- }
- else{
- return "not acceptable/hint abuse";
- }
-
- }
- else{
- console.log("not deliberate")
- return "not acceptable/hint abuse";
- }
-
- }
- else{
- if (isDeliberate(e)){
- if ( (isFamiliar(e) && (!(lastActionIsError(e) && lastActionUnclearFix(e))) )
- || (lastActionIsHint(e) && hintIsHelpful(e))
- ){
- return "preferred/try step";
- }
- else if (seenAllHintLevels(e) &&
- (!(lastActionIsError(e) && lastActionUnclearFix(e))) ){
- return "preferred/try step";
- }
- else if (isCorrect(e)){
- return "acceptable/try step";
- }
- else if (seenAllHintLevels(e)){
- if (lastActionIsError(e) && lastActionUnclearFix(e)){
- return "ask teacher for help/try step";
- }
- }
- else{
- return "not acceptable/hint avoidance";
- }
- }
- else{
- return "not acceptable/not deliberate";
- }
- }
-
-}
-
-function updateHistory(e){
- help_variables.lastActionTime = new Date();
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "hint"){
- help_variables.lastAction = "hint";
- help_variables.lastHintLength = e.data.tutor_data.tutor_advice.split(' ').length;
- if (help_variables.seenAllHints[e.data.tutor_data.selection] != true){
- help_variables.seenAllHints[e.data.tutor_data.selection] = (e.data.tutor_data.current_hint_number == e.data.tutor_data.total_hints_available);
- }
- }
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "incorrect"){
- help_variables.lastAction = "error";
- }
- if (e.data.tutor_data.action_evaluation.toLowerCase() == "correct"){
- help_variables.lastAction = "correct";
- }
-
- help_variables.lastSenseOfWhatToDo = senseOfWhatToDo(e);
-
-}
-
-//
-//###############################
-//###############################
-//###############################
-//###############################
-//
-
-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 secondsSince(initTime){
- var currTime = new Date();
- diff = currTime.getTime() - initTime.getTime();
- console.log("time elapsed: ", diff/1000)
- return (diff / 1000);
-}
-
-function checkTimeElapsed(initTime) {
- var timeDiff = secondsSince(initTime);
- var currTimeMessage = detector_output.value.split(',')[1];
- console.log(currTimeMessage);
- if( timeDiff > (600-seedTime)){
- if (currTimeMessage!=" > 10 min"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > 10 min, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
- else if( timeDiff > (300-seedTime)){
- if (currTimeMessage!=" > 5 min"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > 5 min, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
- else if( timeDiff > (120-seedTime)){
- if (currTimeMessage!=" > 2 min"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > 2 min, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
- else if( timeDiff > (60-seedTime)){
- if (currTimeMessage!=" > 1 min"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > 1 min, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
- else if( timeDiff > (45-seedTime)){
- if (currTimeMessage!=" > 45 s"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > 45 s, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
- else{
- console.log(currTimeMessage == " > " + seedTime.toString() + " s");
- if(currTimeMessage!=" > " + seedTime.toString() + " s"){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > " + seedTime.toString() + " s, " + elaborationString;
- detector_output.time = new Date();
- mailer.postMessage(detector_output);
- postMessage(detector_output);
- console.log("output_data = ", detector_output);
- }
- }
-}
-
-
-
-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;
- }
-
- //#######
-
- if (help_variables.lastAction!="null"){
- help_model_output = evaluateAction(e);
- }
- else{
- help_model_output = "preferred"; //first action in whole tutor is set to "preferred" by default
- }
-
- // attemptCorrect = (e.data.tutor_data.action_evaluation.toLowerCase() == "correct") ? 1 : 0;
- // attemptWindow.shift();
- // attemptWindow.push(attemptCorrect);
-
- // ignore further hint requests if student has already seen all hint levels for this step (i.e., these do not contribute to struggle detector)
- if(seenAllHintLevels(e) && e.data.tutor_data.action_evaluation.toLowerCase() == "hint"){
- console.log("is hint request on step for which student has already seen all hints: no direct/immediate effect on struggle detector");
- }
- else{
- attemptCorrect = (e.data.tutor_data.action_evaluation.toLowerCase() == "correct") ? 1 : 0;
- attemptWindow.shift();
- attemptWindow.push(attemptCorrect);
- }
-
- if (help_model_output == "ask teacher for help/try step"){
- for(var i=0; i<(windowSize-threshold); i++){
- attemptWindow.shift();
- attemptWindow.push(0)};
- }
-
- var sumCorrect = attemptWindow.reduce(function(pv, cv) { return pv + cv; }, 0);
- console.log(attemptWindow);
-
- updateHistory(e);
- console.log(help_model_output);
-
- }
-
- //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)
-
- // elaboration string
- if (sumCorrect<=threshold){
- if(help_model_output == "ask teacher for help/try step"){
- elaborationString = "hints aren't helping";
- }
- else if(help_model_output == "not acceptable/hint avoidance"){
- elaborationString = "not using hints";
- }
- else{
- elaborationString = "lots of errors";
- }
- }
- else{
- elaborationString = " ";
- }
-
-
- if (detector_output.value.split(',')[0]=="0" && (sumCorrect <= threshold)){
- initTime = new Date();
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.value = "1, > " + seedTime.toString() + " s, " + elaborationString;
- detector_output.time = new Date();
-
- intervalID = setInterval( function() { checkTimeElapsed(initTime);} , 3000);
-
- }
- else if (detector_output.value.split(',')[0]!="0" && (sumCorrect <= threshold)){
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.time = new Date();
- }
- else{
- detector_output.value = "0, > 0 s, " + elaborationString;
- detector_output.history = JSON.stringify([attemptWindow, initTime, onboardSkills]);
- detector_output.time = new Date();
-
- clearInterval(intervalID);
- }
-
- 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 = 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){
- attemptWindow = Array.apply(null, Array(windowSize)).map(Number.prototype.valueOf,1);
- onboardSkills = {};
- }
- else{
- var all_history = JSON.parse(detector_output.history);
- attemptWindow = all_history[0];
- initTime = new Date(all_history[1]);
- onboardSkills = all_history[2];
-
- if(detector_output.value.split(',')[0]!="0"){
- intervalID = setInterval( function() { checkTimeElapsed(initTime);} , 3000);
- }
- }
-
- 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