diff --git a/HTML/Assets/networking_for_replay/mail-worker.js b/HTML/Assets/networking_for_replay/mail-worker.js
new file mode 100644
index 0000000..8cf84a2
--- /dev/null
+++ b/HTML/Assets/networking_for_replay/mail-worker.js
@@ -0,0 +1,115 @@
+var process_transactions_url = null;
+var process_detectors_url = null;
+var authenticity_token = "";
+var txAssembler = null;
+var detectors = [];
+
+var trans_Q = [];
+var detector_Q = [];
+
+//called when data is received from txAssembler
+function receive_transaction( e ){
+ //e is the data of the transaction from mailer from transaction assembler
+ console.log("receiving transaction in mail-worker:", e, e.data);
+ trans_Q.push(e.data);
+ for( var i = 0; i < detectors.length; i++ ){
+ detectors[i].postMessage(e.data);
+ }
+}
+
+//called when data is received from the detectors
+function receive_detector_results( e ){
+ var data = e.data;
+ console.log("receiving detector results in mail-worker");
+ if (data != undefined)
+ {
+ detector_Q.push(data);
+
+ console.log("sending detector results to replay outer frame");
+ //
+ postMessage(e.data);
+ //
+ //
+ //
+ }
+}
+
+
+//Connect mailer to txAssembler and Detectors
+self.onmessage = function ( e ) {
+ console.log("mail-worker self.onmessage:", e, e.data, e.data.commmand, e.ports);
+ switch( e.data.command )
+ {
+ case "process_transactions_url":
+ process_transactions_url = e.data.process_transactions_url;
+ process_detectors_url = e.data.process_detectors_url;
+ authenticity_token = e.data.authenticity_token;
+ break;
+ case "connectTransactionAssembler":
+ txAssembler = e.ports[0];
+ txAssembler.onmessage = receive_transaction;
+ break;
+ case "connectDetector":
+ var t = e.ports[0];
+ t.onmessage = receive_detector_results;
+ detectors.push(t);
+ }
+}
+
+
+
+
+/** Send all of the data to the server when in this interval */
+setInterval(function()
+{
+ /* Send Transactions in queue */
+ if (trans_Q.length != 0)
+ {
+ console.log("sending trans to server from mail-worker");
+
+ var trans = {"authenticity_token": authenticity_token, "transactions":[]};
+ trans.transactions = trans_Q;
+ trans_Q = [];
+
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ //console.log( xhttp.responseText );
+ }
+ };
+ //xhttp.open("POST", "GET THIS FROM OCTAV", true);
+ //xhttp.send( JSON.stringify(trans) );
+ xhttp.open("POST", process_transactions_url, true); // fake_server.php
+ xhttp.setRequestHeader("Content-type", "application/json");
+ xhttp.send( JSON.stringify(trans) );
+ }
+ else{
+ //console.log("trans_Q is empty in mail_worker");
+ }
+
+ /* Send Detector results in queue */
+ if (detector_Q.length != 0)
+ {
+ console.log("sending detector results to server from mail-worker");
+
+ detect = {"authenticity_token": authenticity_token, "detector_results":[]};
+ detect.detector_results = detector_Q;
+ detector_Q = [];
+
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ //console.log( xhttp.responseText );
+ }
+ };
+ //xhttp.open("POST", "GET THIS FROM OCTAV", true);
+ //xhttp.send( JSON.stringify(detect) );
+ xhttp.open("POST", process_detectors_url, true); // fake_server.php
+ xhttp.setRequestHeader("Content-type", "application/json");
+ xhttp.send( JSON.stringify(detect) );
+
+ }
+ else{
+ //console.log("detector_Q is empty in mail-worker");
+ }
+},200); //CHANGEME TO WHAT INTERVAL YOU WANT
diff --git a/HTML/Assets/networking_for_replay/transaction_mailer_users.js b/HTML/Assets/networking_for_replay/transaction_mailer_users.js
new file mode 100644
index 0000000..6dacb97
--- /dev/null
+++ b/HTML/Assets/networking_for_replay/transaction_mailer_users.js
@@ -0,0 +1,89 @@
+TransactionMailerUsers =
+{
+ process_transactions_url: "",
+ process_detectors_url: "",
+ authenticity_token: "",
+ mailerURL: "mail-worker.js",
+ mailer: null,
+ mailerPort: null,
+ scripts: ["Detectors/Lumilo/idle.js",
+ "Detectors/Lumilo/system_misuse.js",
+ "Detectors/Lumilo/struggle__moving_average.js",
+ "Detectors/Lumilo/student_doing_well__moving_average.js",
+ "Detectors/Lumilo/critical_struggle.js",
+ "Detectors/Lumilo/invisible_hand_raise.js"],
+ active: []
+};
+
+var init = "";
+
+
+TransactionMailerUsers.create = function(path, txDestURL, scriptsDestURL, authToken, scriptsInitzer)
+{
+
+ console.log("TransactionMailerUsers.create(): at entry, init", init );
+
+ TransactionMailerUsers.mailer = new Worker(path+'/'+TransactionMailerUsers.mailerURL);
+
+ //listen for detector results
+ TransactionMailerUsers.mailer.addEventListener("message", function(e) {
+ console.log("sending new message to initWorker: " + JSON.stringify(e.data));
+ parent.parent.initWorker.port.postMessage(["newDetectorResult", e.data]);
+ }, false);
+
+ TransactionMailerUsers.mailer.postMessage({ command: "process_transactions_url", "process_transactions_url": txDestURL, "process_detectors_url": scriptsDestURL, "authenticity_token": authToken});
+ TransactionMailerUsers.process_transactions_url = txDestURL;
+ TransactionMailerUsers.authenticity_token = authToken;
+ TransactionMailerUsers.process_detectors_url = scriptsDestURL;
+
+ var channel = new MessageChannel();
+ TransactionMailerUsers.mailer.postMessage(
+ { command: "connectTransactionAssembler" },
+ [ channel.port1 ]
+ );
+ TransactionMailerUsers.mailerPort = channel.port2;
+ TransactionMailerUsers.mailerPort.onmessage = function(event) {
+ console.log("From mailer: "+event);
+ };
+
+ //initialization
+ parent.parent.initWorker.port.addEventListener("message", function(e) {
+ if (e.data[0] == "init"){
+ init = e.data[1];
+
+ for(var i = 0; i < TransactionMailerUsers.scripts.length; ++i)
+ {
+ var s = path + '/' + TransactionMailerUsers.scripts[i];
+ var detector = new Worker(s);
+ var mc = new MessageChannel();
+ TransactionMailerUsers.mailer.postMessage({ command: "connectDetector" }, [ mc.port1 ]);
+ detector.postMessage({ command: "connectMailer" }, [ mc.port2 ]);
+
+ detector.postMessage({ command: "initialize", initializer: init });
+ console.log("TransactionMailerUsers.create(): sent command: initialize, init ", init );
+
+ TransactionMailerUsers.active.push(detector);
+ console.log("TransactionMailerUsers.create(): s, active["+i+"]=", s, TransactionMailerUsers.active[i]);
+ }
+ }
+ if (e.data[0] == "newDetectorResult"){
+ console.log("from initWorker: " + JSON.stringify(e.data));
+ }
+
+ }, false);
+
+ parent.parent.initWorker.port.postMessage(["getInit", 0]);
+
+ return TransactionMailerUsers;
+};
+
+TransactionMailerUsers.sendTransaction = function(tx)
+{
+ TransactionMailerUsers.mailerPort.postMessage(tx); // post to listener in other thread
+
+ var tmUsers = TransactionMailerUsers.active;
+ for(var i = 0; i < tmUsers; ++i)
+ {
+ tmUsers[i].postMessage(tx);
+ }
+};