summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/codeq/comms.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/js/codeq/comms.js b/js/codeq/comms.js
index b04a2fc..140e48e 100644
--- a/js/codeq/comms.js
+++ b/js/codeq/comms.js
@@ -1,4 +1,8 @@
(function () {
+ // ================================================================================
+ // Errors generated in this module
+ // ================================================================================
+
var BinaryMessageError = function (message) {
var e = new Error(message);
this.message = message;
@@ -22,6 +26,10 @@
MessageParseError.prototype = new Error();
MessageParseError.prototype.name = 'MessageParseError';
+ // ================================================================================
+ // engine.io communication support functions (long polling / websocket communication)
+ // ================================================================================
+
var currentTID = 0, // transaction ID of the next message
sid = null, // session ID, changes after each successful initial login
socket = null,
@@ -152,6 +160,57 @@
}
};
+ // ================================================================================
+ // AJAX communication support functions (loading of static web resources)
+ // ================================================================================
+
+ var languageCache = {},// language defs, keyed by language identifier
+ problemCache = {},// problem cache, 3-level, keyed by: language, problem group, and problem identifier
+ ajaxGet = function (url) {
+ return Q.Promise(function (resolve, reject, notify) {
+ $.ajax({
+ dataType: 'application/json',
+ type: 'GET',
+ url: url,
+ error: function (jqXHR, textStatus, errorThrown) {
+ codeq.log.error('AJAX to ' + url + ' failed with status ' + textStatus, errorThrown);
+ reject(errorThrown || new Error(textStatus));
+ },
+ success: function (data, textStatus, jqXHR) {
+ var s;
+ if ((typeof data === 'object') && (data !== null)) {
+ // got a JSON
+ resolve(data);
+ }
+ else {
+ s = 'AJAX to ' + url + ' did not result in a JSON object';
+ if (typeof data === 'string') {
+ s += ', the response was:\n' + data;
+ }
+ else if (typeof textStatus === 'string') {
+ s += ', status was: ' + textStatus;
+ }
+ codeq.log.error(s);
+ reject(new Error(s));
+ }
+ }
+ });
+ });
+ },
+ ajaxPrefix;
+
+ ajaxPrefix = location.pathname;
+ if (!ajaxPrefix) ajaxPrefix = '/';
+ else if (ajaxPrefix[ajaxPrefix.length - 1] !== '/') {
+ ajaxPrefix = ajaxPrefix.split('/');
+ ajaxPrefix[ajaxPrefix.length - 1] = '';
+ ajaxPrefix = ajaxPrefix.join('/');
+ }
+
+ // ================================================================================
+ // This module's API methods
+ // ================================================================================
+
codeq.comms = {
'connect': function () {
var deferred = Q.defer();
@@ -320,6 +379,33 @@
}
}
}
+ },
+
+ 'getLanguageDef': function (identifier) {
+ var x = languageCache[identifier];
+ if ((typeof x === 'object') && (x !== null)) {
+ // already defined
+ if (typeof x.then === 'function') {
+ // it's a promise, it means it's not resolved yet
+ return x;
+ }
+ else {
+ // return a resolved promise with the cached value
+ return Q(x);
+ }
+ }
+ x = ajaxGet(ajaxPrefix + identifier + '/language.json').then(
+ function getLanguageDefSuccess(data) {
+ languageCache[identifier] = data;
+ return data; // proxy further
+ },
+ function getLanguageDefFail(exception) {
+ delete languageCache[identifier];
+ throw exception || new Error('Could not load language ' + identifer); // proxy further
+ }
+ );
+ languageCache[identifier] = x;
+ return x;
}
};
})();