diff --git a/HTML/Assets/Detectors/Lumilo/system_misuse.js b/HTML/Assets/Detectors/Lumilo/system_misuse.js index 1ed3899..14a7d1d 100644 --- a/HTML/Assets/Detectors/Lumilo/system_misuse.js +++ b/HTML/Assets/Detectors/Lumilo/system_misuse.js @@ -17,29 +17,249 @@ var mailer; //initialize any custom global variables for this detector here var prevStep = "" -var windowSize = 15; -var gamingThreshold = 5; -var hintAbuseThreshold = 5; +var windowSize = 10; //arbitrary: need to tune +var gamingThreshold = 5; //arbitrary: need to tune +var hintAbuseThreshold = 5; //arbitrary: need to tune var attemptWindow = Array.apply(null, Array(windowSize)).map(Number.prototype.valueOf,0); + + function frequent_gaming(){ } +function cognitive_gaming_detector(){ + +} + + function frequent_hint_abuse(){ } -function hint_abuse_detector(){ +function frequent_not_deliberate(){ } -function cognitive_gaming_detector(){ + +//hint abuse detector params +var help_variables = {"lastAction": "null", + "lastActionTime": "", + "seenAllHints": {}, + "lastHintLength": "", + "lastSenseOfWhatToDo": false + }; + +//TUNABLE PARAMETERS +var errorThreshold = 3; //currently arbitrary +var newStepThreshold = 3; //currently arbitrary +var familiarityThreshold = 0.4; +var senseOfWhatToDoThreshold = 0.6; +var hintIsHelpfulPlaceholder = true; //currently a dummy value (assumption that hint is always helpful...) + +//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 = e.data.tutor_data.skills; + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + if (parseFloat(rawSkills[property].pKnown)<=familiarityThreshold){ + return false; + } + } + } + return true; +} + +function isLowSkillStep_All(e){ + var rawSkills = e.data.tutor_data.skills; + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + if (parseFloat(rawSkills[property].pKnown)>=familiarityThreshold){ + return false; + } + } + } + return true; +} + +function isLowSkillStep_Some(e){ + var rawSkills = e.data.tutor_data.skills; + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + if (parseFloat(rawSkills[property].pKnown)<=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 = e.data.tutor_data.skills; + for (var property in rawSkills) { + if (rawSkills.hasOwnProperty(property)) { + if (parseFloat(rawSkills[property].pKnown)<=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 (isLowSkillStep_Some(e) && !lastActionIsError(e)){ //possible modifications...unless wheel-spinning? ... or even closer to Ido's would be to get rid of the "unless last step was error" qualification? + return("not acceptable/asked hint on low skill step"); + } + else{ + 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 "hint abuse"; + } + } + } + else{ + console.log("not deliberate") + return "hint abuse"; + } + + } + else{ + if (isLowSkillStep_Some(e) && !lastActionIsError(e)){ //possible modifications...unless wheel-spinning? ... or even closer to Ido's would be to get rid of the "unless last step was error" qualification? + return("preferred/try step on low skill step"); + } + 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"; + } + } + else{ + return "hint avoidance"; + } + } + else{ + return "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"; + } + + help_variables.lastSenseOfWhatToDo = senseOfWhatToDo(e); + +} +////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////// + function receive_transaction( e ){ //e is the data of the transaction from mailer from transaction assembler @@ -64,8 +284,7 @@ function receive_transaction( e ){ // // // - var booleanValues = [0, 1]; - detector_output.value = String(booleanValues[Math.floor(Math.random() * booleanValues.length)]) ; + } diff --git a/HTML/Assets/transaction_mailer_users.js b/HTML/Assets/transaction_mailer_users.js index 89cefd8..50b8a10 100644 --- a/HTML/Assets/transaction_mailer_users.js +++ b/HTML/Assets/transaction_mailer_users.js @@ -50,6 +50,21 @@ TransactionMailerUsers.create = function(path, txDestURL, scriptsDestURL, authTo } TransactionMailerUsers.active.push(detector); console.log("TransactionMailerUsers.create(): s, active["+i+"]=", s, TransactionMailerUsers.active[i]); + + detector.onmessage = function(e) + { + var sel = e.data.name; + var action = "UpdateVariable"; + var input = e.data.value; + + var sai = new CTATSAI(); + sai.setSelection(sel); + sai.setAction(action); + sai.setInput(input) + CTATCommShell.commShell.processComponentAction(sai=sai, tutorComponent=false, aTrigger="tutor") + }; + + } return TransactionMailerUsers; };