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;
};