summaryrefslogtreecommitdiff
path: root/js/codeq
diff options
context:
space:
mode:
Diffstat (limited to 'js/codeq')
-rw-r--r--js/codeq/comms.js64
-rw-r--r--js/codeq/core.js33
-rw-r--r--js/codeq/login.js183
3 files changed, 280 insertions, 0 deletions
diff --git a/js/codeq/comms.js b/js/codeq/comms.js
new file mode 100644
index 0000000..fb5d348
--- /dev/null
+++ b/js/codeq/comms.js
@@ -0,0 +1,64 @@
+(function () {
+
+ var activityQueue = [];
+
+ var send = function (service, json) {
+ return Q.Promise(function (resolve, reject, notify) {
+ $.ajax({
+ 'type': 'POST',
+ 'url': codeq.urlPrefix + service,
+ 'accepts': 'application/json',
+ 'contentType': 'application/json; charset=UTF-8', // type of our request
+ 'data': json,
+ 'processData': false, // don't process outgoing data
+ 'dataType': 'json', // expected type of the response
+ 'timeout': 60000, // one minute
+ 'error': function sendErrorHandler(jqXHR, textStatus, errorThrown) {
+ reject(new Error(errorThrown || textStatus));
+ },
+ 'success': function sendSuccessHandler(data, textStatus, jqXHR) {
+ resolve(data);
+ }
+ });
+ });
+ };
+
+ var sendCount = 0,
+ sendActivityInternal = function () {
+ var request;
+ // send max. 100 activities, do not be excessive
+ if (activityQueue.length > 100) {
+ sendCount = 100;
+ request = '[' + activityQueue.slice(0, 100).join(',') + ']';
+ }
+ else {
+ sendCount = activityQueue.length;
+ request = '[' + activityQueue.join(',') + ']';
+ }
+ send('activity', request).then(
+ function sendActivitySuccess() {
+ activityQueue.splice(0, sendCount);
+ if (activityQueue.length > 0) sendActivityInternal();
+ },
+ function sendActivityFailure() {
+ Q.delay(500).then(sendActivityInternal).done();
+ }
+ ).done();
+ };
+
+ 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
+ }
+ },
+
+ sendQuery: function commsSendQuery (json) {
+ json['sid'] = codeq.sid;
+ return send('query', codeq.jsonize(json));
+ }
+ };
+})();
diff --git a/js/codeq/core.js b/js/codeq/core.js
new file mode 100644
index 0000000..f13a019
--- /dev/null
+++ b/js/codeq/core.js
@@ -0,0 +1,33 @@
+window.siteDefinition = { logLevel: 'debug' }; // for debug purposes
+
+window.codeq = {
+ /**
+ * XML namespaces.
+ */
+ ns: {
+ svg: 'http://www.w3.org/2000/svg'
+ },
+
+ noOnlineStatus: !('onLine' in navigator),
+
+ /**
+ * REST API URL prefix.
+ */
+ urlPrefix: '/codeq/',
+
+ /**
+ * Returns the number of Unicode code points in the given string.
+ *
+ * @param s {string}
+ * @returns {number}
+ */
+ codePointCount: function (s) {
+ var n = 0, i, code;
+ for (i = s.length - 1; i >= 0; i--) {
+ code = s.charCodeAt(i);
+ if ((code >= 0xd800) && (code < 0xe000)) i++;
+ n++;
+ }
+ return n;
+ }
+};
diff --git a/js/codeq/login.js b/js/codeq/login.js
new file mode 100644
index 0000000..d449835
--- /dev/null
+++ b/js/codeq/login.js
@@ -0,0 +1,183 @@
+(function(){
+ var groups = {
+ 'family_relations': {
+ 'name': 'Family relations',
+ 'problems': [
+ {'id': 'ancestor_2', 'name': 'ancestor/2'},
+ {'id': 'aunt_2', 'name': 'aunt/2'},
+ {'id': 'brother_2', 'name': 'brother/2'},
+ {'id': 'connected_3', 'name': 'connected/3'},
+ {'id': 'cousin_2', 'name': 'cousin/2'}
+ ]
+ },
+ 'lists': {
+ 'name': 'Lists',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ },
+ 'sorting': {
+ 'name': 'Sorting',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ },
+ 'other': {
+ 'name': 'Other',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ },
+ 'sets': {
+ 'name': 'Sets',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ },
+ 'trees': {
+ 'name': 'Trees',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ },
+ 'license_plates': {
+ 'name': 'License plates',
+ },
+ 'clp_fd': {
+ 'name': 'CLP(FD',
+ 'problems': [
+ {'id': 'gcd_3', 'name': 'gcd/3'},
+ {'id': 'magic_1', 'name': 'magic/1'},
+ {'id': 'puzzle_abc_3', 'name': 'puzzle_abc/3'},
+ {'id': 'puzzle_beth_1', 'name': 'puzzle_beth/1'},
+ {'id': 'puzzle_momson_2', 'name': 'puzzle_momson/2'},
+ {'id': 'puzzle_ratio_2', 'name': 'puzzle_ratio/2'},
+ {'id': 'tobase_3', 'name': 'tobase/3'}
+ ]
+ },
+ 'clp_r': {
+ 'name': 'CLP(R)',
+ 'problems': [
+ {'id': 'bounding_box_3', 'name': 'bounding_box/3'},
+ {'id': 'center_3', 'name': 'center/3'},
+ {'id': 'linear_opts_3', 'name': 'linear_opts/3'},
+ {'id': 'max_sum_2', 'name': 'max_sum/2'},
+ {'id': 'megabytes_2', 'name': 'megabytes/2'},
+ {'id': 'turkey_3', 'name': 'turkey/3'}
+ ]
+ },
+ 'dcg': {
+ 'name': 'DCG',
+ 'problems': [
+ {'id': 'ab_2', 'name': 'ab/2'},
+ {'id': 'digit_2', 'name': 'digit/2'},
+ {'id': 'expr_2', 'name': 'expr/2'},
+ {'id': 'expr_3', 'name': 'expr/3'},
+ {'id': 'flower_2', 'name': 'flower/2'}
+ ]
+ },
+ 'denotational_semantics': {
+ 'name': 'Denotational semantics',
+ 'problems': [
+ {'id': 'algol_3', 'name': 'algol/3'},
+ {'id': 'algol_for_3', 'name': 'algol_for/3'},
+ {'id': 'algol_if_3', 'name': 'algol_if/3'},
+ {'id': 'prog_8puzzle_2', 'name': 'prog_8puzzle/2'},
+ {'id': 'prog_8puzzle_3', 'name': 'prog_8puzzle/3'}
+ ]
+ },
+ 'old_exams': {
+ 'name': 'Old exams',
+ 'problems': [
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''},
+ {'id': '', 'name': ''}
+ ]
+ }
+ };
+
+ $("#submit").on('click', function () {
+ var group = $('#problem_group').val(),
+ problem = $('#problems').val();
+ if (!group) alert('Choose a problem group');
+ else if (!problem) alert('Choose a problem');
+ else {
+ $.ajax({
+ 'type': 'POST',
+ 'url': '/codeq/login',
+ 'accepts': 'application/json',
+ 'contentType': 'application/json; charset=UTF-8',
+ 'data': JSON.stringify({
+ 'username': $('#username').val(),
+ 'password': $('#password').val()
+ }),
+ 'processData': false,
+ 'dataType': 'json',
+ 'error': function loginErrorHandler(jqXHR, textStatus, errorThrown) {
+ alert('Request for login failed: ' + (errorThrown || textStatus));
+ },
+ 'success': function loginSuccessHandler(data, textStatus, jqXHR) {
+ if (data && (data.code === 0)) {
+ window.location = 'prolog.html#sid=' + data.sid + '/grp=' + group + '/prb=' + problem;
+ }
+ else {
+ alert('Login failed: code=' + data.code + ', reason=' + data.message);
+ }
+ }
+ });
+ }
+ });
+
+ $(document).ready(function () {
+ var jqGroup = $('#problem_group'),
+ jqProblems = $('#problems'),
+ id, g, first_group, html = [];
+
+ for (id in groups) {
+ g = groups[id];
+ html.push('<option value="', id, '">', g.name, '</option>\n');
+ }
+ jqGroup.html(html.join(''));
+ first_group = html[1];
+ html = null;
+
+ jqGroup.on('click', function () {
+ var g = groups[jqGroup.val()],
+ html = [],
+ problems, i, p;
+ if (g) {
+ problems = g.problems;
+ for (i = 0; i < problems.length; i++) {
+ p = problems[i];
+ if (!p.id) continue;
+ html.push('<option value="', p.id, '">', p.name, '</option>\n')
+ }
+ }
+ jqProblems.html(html.join(''));
+ });
+
+ jqGroup.val(first_group);
+ });
+})(); \ No newline at end of file