diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/codeq/comms.js | 107 | ||||
-rw-r--r-- | js/prolog.js | 13 |
2 files changed, 70 insertions, 50 deletions
diff --git a/js/codeq/comms.js b/js/codeq/comms.js index eece7e7..cff1015 100644 --- a/js/codeq/comms.js +++ b/js/codeq/comms.js @@ -1,7 +1,5 @@ (function () { - var activityQueue = []; - var send = function (service, json) { if (json instanceof Object) json = codeq.jsonize(json); return Q.Promise(function (resolve, reject, notify) { @@ -24,37 +22,42 @@ }); }; - var sendCount = 0, - resolveWaiters = [], - currentSolution = null, - resolveActivity = function () { + var activities = {}, // keyed by problem_id: activity info waiting to be sent to the server + activityKeys = [], // the keys to activities dictionary + resolveActivity = function (promiseResolvers) { var i; // signal everyone that the queue is flushed - for (i = 0; i < resolveWaiters.length; i++) { + for (i = 0; i < promiseResolvers.length; i++) { try { - resolveWaiters[i][0](); + promiseResolvers[i][0](); } catch (e) {} } - resolveWaiters.length = 0; + promiseResolvers.length = 0; }, sendActivityInternal = function () { - var trace; + var activityKey, activityDescriptor, trace, sendCount; // send max. 100 activities, do not be excessive - if (activityQueue.length == 0) return resolveActivity(); - if (activityQueue.length > 100) { + if (activityKeys.length == 0) return; + activityKey = activityKeys[0]; + activityDescriptor = activities[activityKey]; + trace = activityDescriptor.trace; + if (trace.length > 100) { sendCount = 100; - trace = activityQueue.slice(0, 100); + trace = trace.slice(0, 100); } else { - sendCount = activityQueue.length; - trace = activityQueue; + sendCount = trace.length; } - send('trace', {'trace': trace, 'solution': currentSolution}).then( + send('activity', {'trace': trace, 'solution': activityDescriptor.solution, 'problem_id': activityDescriptor.problem_id, 'sid': codeq.sid}).then( function sendActivitySuccess() { - activityQueue.splice(0, sendCount); - if (activityQueue.length > 0) sendActivityInternal(); - else resolveActivity(); + activityDescriptor.trace.splice(0, sendCount); + if (activityDescriptor.trace.length > 0) sendActivityInternal(); + else { + delete activities[activityKey]; + activityKeys.shift(); + resolveActivity(activityDescriptor.promiseResolvers); + } }, function sendActivityFailure() { Q.delay(500).then(sendActivityInternal).done(); @@ -63,45 +66,59 @@ }; codeq.comms = { - sendActivity: function commsSendActivity (json, solution) { + sendActivity: function commsSendActivity (trace, solution, problem_id) { 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); + var triggerSending = activityKeys.length == 0, + activityDescriptor = activities[problem_id], + problemTrace, promiseResolvers, i; + if (!activityDescriptor) { + problemTrace = []; + promiseResolvers = []; + activityDescriptor = { + 'problem_id': problem_id, + 'trace': problemTrace, + 'solution': solution, + 'promiseResolvers': promiseResolvers + }; + activities[problem_id] = activityDescriptor; + activityKeys.push(problem_id); + } + else { + problemTrace = activityDescriptor.trace; + promiseResolvers = activityDescriptor.promiseResolvers; + if (solution) activityDescriptor.solution = solution; + } + if (trace instanceof Array) { + for (i = 0; i < trace.length; i++) { + problemTrace.push(trace[i]); } } else { - json['sid'] = codeq.sid; - activityQueue.push(json); + problemTrace.push(trace); } - if (solution) currentSolution = solution; - resolveWaiters.push([resolve, reject]); + promiseResolvers.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; - 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(); + sendQuery: function commsSendQuery (query, problem_id) { + var existingActivity = activities[problem_id], + tmp; + query['sid'] = codeq.sid; + if (existingActivity) { + tmp = query['trace']; + if (tmp) { + // the trace will be sent separately, so it will be in the proper order + tmp.splice(0, 0, existingActivity.trace.length, 0); // add two parameters in front, they will form the first two parameters to the following splice() invocation + existingActivity.trace.splice.apply(existingActivity.trace, tmp); + delete query['trace']; } - activityQueue.length = 0; - if (currentSolution) json['solution'] = currentSolution; + tmp = query['program']; + if (tmp) existingActivity.solution = tmp; } - return send('query', json); + return send('query', query); }, getProblem: function commsGetProblem (language, problem_group, problem) { diff --git a/js/prolog.js b/js/prolog.js index 429ac72..e252393 100644 --- a/js/prolog.js +++ b/js/prolog.js @@ -33,19 +33,20 @@ if (promptMode) { terminal.pause(); codeq.comms.sendQuery({ + 'problem_id': problem_id, 'step': 'run', 'program': editor.getDoc().getValue(), 'query': command, - 'problem_id': problem_id, 'trace': activityHandler.addAndPurge({'typ': 'slv', 'qry': command}) - }).then(tcs, tcf).done(); + }, problem_id).then(tcs, tcf).done(); } else { // not in prompt mode -- we should never land here, but handle it anyway codeq.comms.sendQuery({ + 'problem_id': problem_id, 'step': 'end', 'trace': activityHandler.addAndPurge({'typ': 'stp'}) - }).then(tcs, tcf).done(); + }, problem_id).then(tcs, tcf).done(); } }, { 'history': true, @@ -63,17 +64,19 @@ // space or semicolon -> show next answer event.which = 59; // semicolon codeq.comms.sendQuery({ + 'problem_id': problem_id, 'step': 'next', 'trace': activityHandler.addAndPurge({'typ': 'nxt'}) - }).then(tcs, tcf).done(); + }, problem_id).then(tcs, tcf).done(); } else { // everything else: stop searching for answers event.which = 46; // full stop codeq.comms.sendQuery({ + 'problem_id': problem_id, 'step': 'end', 'trace': activityHandler.addAndPurge({'typ': 'stp'}) - }).then(tcs, tcf).done(); + }, problem_id).then(tcs, tcf).done(); } } }); |