summaryrefslogtreecommitdiff
path: root/js/codeq/comms.js
blob: eece7e7bcd9facf0764468b7526c8c9839d2e932 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
(function () {

    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',
                '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,
        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 trace;
            // send max. 100 activities, do not be excessive
            if (activityQueue.length == 0) return resolveActivity();
            if (activityQueue.length > 100) {
                sendCount = 100;
                trace = activityQueue.slice(0, 100);
            }
            else {
                sendCount = activityQueue.length;
                trace = activityQueue;
            }
            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();
                }
            ).done();
        };

    codeq.comms = {
        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;
            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', {
                'sid': codeq.sid,
                'language': language,
                'problem_group': problem_group,
                'problem': problem
            });
        }
    };
})();