summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorAleš Smodiš <aless@guru.si>2015-08-25 19:03:17 +0200
committerAleš Smodiš <aless@guru.si>2015-08-25 19:03:17 +0200
commita524c37795ad465b3e578019d3062e038cf9be44 (patch)
tree364d4479074585385a1c2986605fb06b20113699 /js
parent1973db21715555e7b668c83e6aace2c7499f8eaa (diff)
Work on sending activity trace.
Diffstat (limited to 'js')
-rw-r--r--js/codeq/comms.js71
-rw-r--r--js/prolog.js87
2 files changed, 122 insertions, 36 deletions
diff --git a/js/codeq/comms.js b/js/codeq/comms.js
index d2c2910..eece7e7 100644
--- a/js/codeq/comms.js
+++ b/js/codeq/comms.js
@@ -3,6 +3,7 @@
var activityQueue = [];
var send = function (service, json) {
+ if (json instanceof Object) json = codeq.jsonize(json);
return Q.Promise(function (resolve, reject, notify) {
$.ajax({
'type': 'POST',
@@ -24,21 +25,36 @@
};
var sendCount = 0,
+ resolveWaiters = [],
+ currentSolution = null,
+ resolveActivity = function () {
+ var i;
+ // signal everyone that the queue is flushed
+ for (i = 0; i < resolveWaiters.length; i++) {
+ try {
+ resolveWaiters[i][0]();
+ }
+ catch (e) {}
+ }
+ resolveWaiters.length = 0;
+ },
sendActivityInternal = function () {
- var request;
+ var trace;
// send max. 100 activities, do not be excessive
+ if (activityQueue.length == 0) return resolveActivity();
if (activityQueue.length > 100) {
sendCount = 100;
- request = '[' + activityQueue.slice(0, 100).join(',') + ']';
+ trace = activityQueue.slice(0, 100);
}
else {
sendCount = activityQueue.length;
- request = '[' + activityQueue.join(',') + ']';
+ trace = activityQueue;
}
- send('activity', request).then(
+ send('trace', {'trace': trace, 'solution': currentSolution}).then(
function sendActivitySuccess() {
activityQueue.splice(0, sendCount);
if (activityQueue.length > 0) sendActivityInternal();
+ else resolveActivity();
},
function sendActivityFailure() {
Q.delay(500).then(sendActivityInternal).done();
@@ -47,27 +63,54 @@
};
codeq.comms = {
- sendActivity: function commsSendActivity (json) {
- var triggerSending = activityQueue.length == 0;
- json['sid'] = codeq.sid;
- activityQueue.push(codeq.jsonize(json));
- if (triggerSending) {
- setTimeout(sendActivityInternal, 0); // async trigger: see if you can collect some more payload
- }
+ sendActivity: function commsSendActivity (json, solution) {
+ return Q.Promise(function (resolve, reject, notify) {
+ var triggerSending = activityQueue.length == 0,
+ i, js;
+ if (json instanceof Array) {
+ for (i = 0; i < json.length; i++) {
+ js = json[i];
+ js['sid'] = codeq.sid;
+ activityQueue.push(js);
+ }
+ }
+ else {
+ json['sid'] = codeq.sid;
+ activityQueue.push(json);
+ }
+ if (solution) currentSolution = solution;
+ resolveWaiters.push([resolve, reject]);
+ if (triggerSending) {
+ setTimeout(sendActivityInternal, 0); // async trigger: see if you can collect some more payload
+ }
+ });
},
sendQuery: function commsSendQuery (json) {
+ var thisTrace;
json['sid'] = codeq.sid;
- return send('query', codeq.jsonize(json));
+ if (activityQueue.length > 0) {
+ thisTrace = json['trace'];
+ if (thisTrace instanceof Array) {
+ activityQueue.splice(0, 0, 0, 0); // add two zeros in front, they will form the first two parameters to the next splice()
+ thisTrace.splice.apply(thisTrace, activityQueue);
+ }
+ else {
+ json['trace'] = activityQueue.slice();
+ }
+ activityQueue.length = 0;
+ if (currentSolution) json['solution'] = currentSolution;
+ }
+ return send('query', json);
},
getProblem: function commsGetProblem (language, problem_group, problem) {
- return send('get_problem', codeq.jsonize({
+ return send('get_problem', {
'sid': codeq.sid,
'language': language,
'problem_group': problem_group,
'problem': problem
- }));
+ });
}
};
})();
diff --git a/js/prolog.js b/js/prolog.js
index 50b9176..429ac72 100644
--- a/js/prolog.js
+++ b/js/prolog.js
@@ -6,7 +6,7 @@
// a constant
var firstCharacterPos = {'line': 0, 'ch': 0};
- var makePrologTerminalHandler = function (jqConsole, editor, problem_id) {
+ var makePrologTerminalHandler = function (jqConsole, editor, problem_id, activityHandler) {
var promptMode = true, // default: query composition; alternative: query result browsing
tcs = function terminalCommandSuccess (data) {
var t, lines, i;
@@ -36,16 +36,15 @@
'step': 'run',
'program': editor.getDoc().getValue(),
'query': command,
-// 'language': 'prolog',
-// 'problem_group': problem_group,
-// 'problem': problem
- 'problem_id': problem_id
+ 'problem_id': problem_id,
+ 'trace': activityHandler.addAndPurge({'typ': 'slv', 'qry': command})
}).then(tcs, tcf).done();
}
else {
// not in prompt mode -- we should never land here, but handle it anyway
codeq.comms.sendQuery({
- 'step': 'end'
+ 'step': 'end',
+ 'trace': activityHandler.addAndPurge({'typ': 'stp'})
}).then(tcs, tcf).done();
}
}, {
@@ -64,14 +63,16 @@
// space or semicolon -> show next answer
event.which = 59; // semicolon
codeq.comms.sendQuery({
- 'step': 'next'
+ 'step': 'next',
+ 'trace': activityHandler.addAndPurge({'typ': 'nxt'})
}).then(tcs, tcf).done();
}
else {
// everything else: stop searching for answers
event.which = 46; // full stop
codeq.comms.sendQuery({
- 'step': 'end'
+ 'step': 'end',
+ 'trace': activityHandler.addAndPurge({'typ': 'stp'})
}).then(tcs, tcf).done();
}
}
@@ -80,6 +81,56 @@
return {};
};
+ var makeActivityHandler = function (editor) {
+ var lastActivityMillis = Date.now(),
+ deltaActivityMillis = function deltaActivityMillisFunc () {
+ var now = Date.now(),
+ dt = Math.max(0, Math.min(30000, now - lastActivityMillis)); // 0 sec <= dt <= 30 sec
+ lastActivityMillis = now;
+ return dt;
+ },
+ queue = [],
+ ts = null,
+ timer = function () {
+ var promise;
+ ts = null;
+ if (queue.length === 0) return Q(true);
+ promise = codeq.comms.sendActivity(queue, editor.getDoc().getValue());
+ queue.length = 0;
+ return promise;
+ },
+ flush = function () {
+ clearTimeout(ts);
+ return timer();
+ };
+
+ return {
+ "trace": function (trace) {
+ trace['dt'] = deltaActivityMillis();
+ return trace;
+ },
+ 'queue': function (trace) {
+ queue.push(trace);
+ if (ts === null) setTimeout(timer, 10000); // flush every 10 seconds
+ },
+ 'queueTrace': function (trace) {
+ this.queue(this.trace(trace));
+ },
+ 'flush': flush,
+ 'addAndPurge': function (trace) {
+ var accumulatedTrace = queue;
+ queue = [];
+ trace['dt'] = deltaActivityMillis();
+ accumulatedTrace.push(trace);
+ if (ts !== null) {
+ clearTimeout(ts);
+ ts = null;
+ }
+ return accumulatedTrace;
+ }
+ };
+ };
+
/**
* Creates a new handler for the given Prolog assignment definition.
*
@@ -93,6 +144,7 @@
jqConsole = $('#console'),
jqHints = $('#info'),
editor = CodeMirror(jqEditor[0], { cursorHeight: 0.85, lineNumbers: true, matchBrackets: true }),
+ activityHandler = makeActivityHandler(editor),
/* controller = jqConsole.console({
promptLabel: '?- ',
commandValidate: function (line) {
@@ -106,7 +158,7 @@
promptHistory: false,
welcomeMessage: 'Prolog REPL.'
}),*/
- terminal = makePrologTerminalHandler(jqConsole, editor, problem.id),
+ terminal = makePrologTerminalHandler(jqConsole, editor, problem.id, activityHandler),
/** Object.<string, HintDefinition> */
hintDefs = problem.hint,
hintCounter = 0, // for generating unique class-names
@@ -211,13 +263,6 @@
hintCleaners.push(close);
}
- },
- lastActivityMillis = Date.now(),
- deltaActivityMillis = function deltaActivityMillisFunc () {
- var now = Date.now(),
- dt = Math.max(0, Math.min(30000, now - lastActivityMillis)); // 0 sec <= dt <= 30 sec
- lastActivityMillis = now;
- return dt;
};
editor.setValue(info.solution);
@@ -226,15 +271,14 @@
editor.on('change', function (instance, changeObj) {
var doc = editor.getDoc(),
- pos = codeq.codePointCount(doc.getRange(firstCharacterPos, changeObj.from)),
- dt = deltaActivityMillis();
+ pos = codeq.codePointCount(doc.getRange(firstCharacterPos, changeObj.from));
if (changeObj.removed) {
-// codeq.comms.sendActivity({'typ': 'rm', 'dt': dt, 'off': pos, 'len': codeq.codePointCount(changeObj.removed)});
+ activityHandler.queueTrace({'typ': 'rm', 'off': pos, 'len': codeq.codePointCount(changeObj.removed)});
}
if (changeObj.text) {
-// codeq.comms.sendActivity({'typ': 'ins', 'dt': dt, 'off': pos, 'txt': changeObj.text});
+ activityHandler.queueTrace({'typ': 'ins', 'off': pos, 'txt': changeObj.text});
}
});
@@ -297,8 +341,7 @@
// $(jqButtons.get(2)).on('click', function () { handler.processServerHints([{id:'drop_down', start: 20, end: 26, choices:['ena', 'dva', 'tri']}]); });
$('#btn_code_run').on('click', function () {
- var doc = editor.getDoc(),
- dt = deltaActivityMillis();
+ var doc = editor.getDoc();
// codeq.comms.sendActivity({'typ': 'slv', 'dt': dt, 'qry': });
// handler.processServerHints([{id:'list_empty'}]);
});