Completed
Push — master ( aeb336...b5febe )
by Pieter
02:23
created

Connection.handleError   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 9
rs 9.6666
c 1
b 0
f 0
1
const GitAmp = (function(exports, $) {
2
    'use strict';
3
4
    /**
5
     * AudioPlayer
6
     */
7
    const AudioPlayer = (function() {
8
        const maxPitch = 100.0;
9
        const logUsed  = 1.0715307808111486871978099;
10
11
        const maximumSimultaneousNotes = 2;
12
        const soundLength = 300;
13
14
        function AudioPlayer() {
15
            this.currentlyPlayingSounds = 0;
16
17
            this.sounds = {
18
                celesta: this.initializeCelesta(),
19
                clav: this.initializeClav(),
20
                swells: this.initializeSwells()
21
            };
22
23
            //noinspection JSUnresolvedVariable
24
            exports.Howler.volume(volume);
25
        }
26
27
        AudioPlayer.prototype.initializeCelesta = function() {
28
            const sounds = [];
29
30
            for (let i = 1; i <= 24; i++) {
31
                let filename = (i > 9) ? 'c0' + i : 'c00' + i;
32
33
                //noinspection JSUnresolvedFunction
34
                sounds.push(new Howl({
0 ignored issues
show
Bug introduced by
The variable Howl seems to be never declared. If this is a global, consider adding a /** global: Howl */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
35
                    src : [
36
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + filename + '.ogg',
37
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/celesta/' + filename + '.mp3'
38
                    ],
39
                    volume : 0.7,
40
                    buffer: true
41
                }));
42
            }
43
44
            return sounds;
45
        };
46
47
        AudioPlayer.prototype.initializeClav = function() {
48
            const sounds = [];
49
50
            for (let i = 1; i <= 24; i++) {
51
                let filename = (i > 9) ? 'c0' + i : 'c00' + i;
52
53
                //noinspection JSUnresolvedFunction
54
                sounds.push(new Howl({
0 ignored issues
show
Bug introduced by
The variable Howl seems to be never declared. If this is a global, consider adding a /** global: Howl */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
55
                    src : [
56
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + filename + '.ogg',
57
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/clav/' + filename + '.mp3'
58
                    ],
59
                    volume : 0.7,
60
                    buffer: true
61
                }));
62
            }
63
64
            return sounds;
65
        };
66
67
        AudioPlayer.prototype.initializeSwells = function() {
68
            const sounds = [];
69
70
            for (let i = 1; i <= 3; i++) {
71
                //noinspection JSUnresolvedFunction
72
                sounds.push(new Howl({
0 ignored issues
show
Bug introduced by
The variable Howl seems to be never declared. If this is a global, consider adding a /** global: Howl */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
73
                    src : [
74
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.ogg',
75
                        'https://d1fz9d31zqor6x.cloudfront.net/sounds/swells/swell' + i + '.mp3'
76
                    ],
77
                    volume : 0.7,
78
                    buffer: true
79
                }));
80
            }
81
82
            return sounds;
83
        };
84
85
        AudioPlayer.prototype.getSoundIndex = function(size, type) {
86
            const pitch = 100 - Math.min(maxPitch, Math.log(size + logUsed) / Math.log(logUsed));
87
            let index   = Math.floor(pitch / 100.0 * this.sounds[type].length);
88
89
            index += Math.floor(Math.random() * 4) - 2;
90
            index = Math.min(this.sounds[type].length - 1, index);
91
            index = Math.max(1, index);
92
93
            return index;
94
        };
95
96
        AudioPlayer.prototype.playSound = function(sound) {
97
            if (this.currentlyPlayingSounds >= maximumSimultaneousNotes) {
98
                return;
99
            }
100
101
            sound.play();
102
103
            this.currentlyPlayingSounds++;
104
105
            setTimeout(function() {
106
                this.currentlyPlayingSounds--;
107
            }.bind(this), soundLength);
108
        };
109
110
        AudioPlayer.prototype.playCelesta = function(size) {
111
            this.playSound(this.sounds.celesta[this.getSoundIndex(size, 'celesta')]);
112
        };
113
114
        AudioPlayer.prototype.playClav = function(size) {
115
            this.playSound(this.sounds.clav[this.getSoundIndex(size, 'clav')]);
116
        };
117
118
        AudioPlayer.prototype.playSwell = function() {
119
            this.playSound(this.sounds.swells[Math.round(Math.random() * (this.sounds.swells.length - 1))]);
120
        };
121
122
        return AudioPlayer;
123
    }());
124
125
    /**
126
     * Gui
127
     */
128
    const Gui = (function() {
129
        function Gui() {
130
            this.setupVolumeSlider();
131
        }
132
133
        Gui.prototype.setupVolumeSlider = function() {
134
            //noinspection JSUnresolvedFunction
135
            $('#volumeSlider').slider({
136
                max: 100,
137
                min: 0,
138
                value: volume * 100,
139
                slide: function (event, ui) {
140
                    //noinspection JSUnresolvedVariable
141
                    exports.Howler.volume(ui.value/100.0);
142
                },
143
                change: function (event, ui) {
144
                    //noinspection JSUnresolvedVariable
145
                    exports.Howler.volume(ui.value/100.0);
146
                }
147
            });
148
        };
149
150
        return Gui;
151
    }());
152
153
    /**
154
     * ConnectedUsersMessage
155
     */
156
    function ConnectedUsersMessage(response) {
157
        //noinspection JSUnresolvedVariable
158
        this.count = response.connectedUsers;
159
    }
160
161
    ConnectedUsersMessage.prototype.getCount = function() {
162
        return this.count;
163
    };
164
165
    /**
166
     * EventMessage
167
     */
168
    function EventMessage(event) {
169
        this.event = event;
170
    }
171
172
    EventMessage.prototype.getId = function() {
173
        //noinspection JSUnresolvedVariable
174
        return this.event.id;
175
    };
176
177
    EventMessage.prototype.getType = function() {
178
        //noinspection JSUnresolvedVariable
179
        return this.event.type;
180
    };
181
182
    EventMessage.prototype.getAction = function() {
183
        //noinspection JSUnresolvedVariable
184
        return this.event.action;
185
    };
186
187
    EventMessage.prototype.getRepositoryName = function() {
188
        //noinspection JSUnresolvedVariable
189
        return this.event.repoName;
190
    };
191
192
    EventMessage.prototype.getActorName = function() {
193
        //noinspection JSUnresolvedVariable
194
        return this.event.actorName;
195
    };
196
197
    EventMessage.prototype.getUrl = function() {
198
        //noinspection JSUnresolvedVariable
199
        return this.event.eventUrl;
200
    };
201
202
    EventMessage.prototype.getMessage = function() {
203
        //noinspection JSUnresolvedVariable
204
        return this.event.message;
205
    };
206
207
    /**
208
     * EventMessageCollection
209
     */
210
    function EventMessageCollection(response) {
211
        this.events = [];
212
213
        for (let i = 0; i < response.length; i++) {
214
            this.events.push(new EventMessage(response[i]));
215
        }
216
    }
217
218
    EventMessageCollection.prototype.forEach = function(callback) {
219
        for (let i = 0; i < this.events.length; i++) {
220
            callback(this.events[i]);
221
        }
222
    };
223
224
    /**
225
     * EventMessagesFactory
226
     */
227
    function EventMessagesFactory () {
228
    }
229
230
    EventMessagesFactory.prototype.build = function(response) {
231
        const parsedResponse = JSON.parse(response.data);
232
233
        if (parsedResponse.hasOwnProperty('connectedUsers')) {
234
            return new ConnectedUsersMessage(parsedResponse);
235
        }
236
237
        return new EventMessageCollection(parsedResponse);
238
    };
239
240
    /**
241
     * EventQueue
242
     */
243
    function EventQueue() {
244
        this.queue = [];
245
    }
246
247
    EventQueue.prototype.append = function(eventMessages) {
248
        eventMessages.forEach(function(event) {
249
            if (this.exists(event)) {
250
                return;
251
            }
252
253
            this.queue.push(event);
254
        }.bind(this));
255
256
        if (this.queue.length > 1000) {
257
            this.queue = this.queue.slice(0, 1000);
258
        }
259
    };
260
261
    EventQueue.prototype.exists = function(event) {
262
        for (let i = 0; i < this.queue.length; i++) {
263
            if (event.getId() === this.queue[i].getId()) {
264
                return true;
265
            }
266
        }
267
268
        return false;
269
    };
270
271
    EventQueue.prototype.get = function() {
272
        return this.queue.shift();
273
    };
274
275
    EventQueue.prototype.count = function() {
276
        return this.queue.length;
277
    };
278
279
    /**
280
     * Connection
281
     */
282
    function Connection(eventMessageFactory) {
283
        this.eventMessageFactory = eventMessageFactory;
284
285
        this.connection = null;
286
        this.handlers   = [];
287
    }
288
289
    Connection.prototype.start = function() {
290
        let protocol = 'ws://';
291
292
        if (exports.location.protocol === "https:") {
293
            protocol = 'wss://';
294
        }
295
296
        this.connection = new WebSocket(protocol + exports.location.host + '/ws');
0 ignored issues
show
Bug introduced by
The variable WebSocket seems to be never declared. If this is a global, consider adding a /** global: WebSocket */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
297
298
        this.connection.addEventListener('message', this.handleMessage.bind(this));
299
        this.connection.addEventListener('open', this.handleOpen.bind(this));
300
        this.connection.addEventListener('close', this.handleClose.bind(this));
301
        this.connection.addEventListener('error', this.handleError.bind(this));
302
    };
303
304
    Connection.prototype.registerHandler = function(handler) {
305
        this.handlers.push(handler);
306
    };
307
308
    Connection.prototype.handleMessage = function(response) {
309
        const message = this.eventMessageFactory.build(response);
310
311
        for (let i = 0; i < this.handlers.length; i++) {
312
            this.handlers[i](message);
313
        }
314
    };
315
316
    Connection.prototype.handleOpen = function() {
317
        document.getElementsByTagName('svg')[0].style.backgroundColor = svg_background_color_online;
318
        document.getElementsByTagName('header')[0].style.backgroundColor = svg_background_color_online;
319
320
        const elements = document.querySelectorAll('.events-remaining-text, .events-remaining-value, .online-users-div');
321
322
        for (let i = 0; i < elements.length; i++) {
323
            elements[i].style.visibility = 'visible';
324
        }
325
    };
326
327
    Connection.prototype.handleClose = function() {
328
        document.getElementsByTagName('svg')[0].style.backgroundColor = svg_background_color_offline;
329
        document.getElementsByTagName('header')[0].style.backgroundColor = svg_background_color_offline;
330
331
        this.connection = null;
332
    };
333
334
    Connection.prototype.handleError = function() {
335
        this.handleClose();
336
337
        const reTryInterval = setInterval(function() {
338
            if (this.connection !== null) {
339
                clearInterval(reTryInterval);
340
341
                return;
342
            }
343
344
            this.start();
345
        }.bind(this), 5000);
346
    };
347
348
    /**
349
     * Application
350
     */
351
    function Application() {
352
        this.queue = new EventQueue();
353
        this.audio = new AudioPlayer();
354
        this.gui   = new Gui();
355
    }
356
357
    Application.prototype.run = function() {
358
        const connection = new Connection(new EventMessagesFactory());
359
360
        connection.registerHandler(this.process.bind(this));
361
362
        connection.start();
363
364
        this.loop();
365
    };
366
367
    Application.prototype.process = function(message) {
368
        if (message instanceof ConnectedUsersMessage) {
369
            document.getElementsByClassName('online-users-count')[0].textContent = message.getCount();
370
371
            return;
372
        }
373
374
        this.queue.append(message);
375
    };
376
377
    Application.prototype.loop = function() {
378
        setTimeout(function() {
379
            this.processEvent(this.queue.get());
380
381
            document.getElementsByClassName('events-remaining-value')[0].textContent = this.queue.count();
382
383
            this.loop();
384
        }.bind(this), Math.floor(Math.random() * 1000) + 500);
385
    };
386
387
    Application.prototype.processEvent = function(event) {
388
        if (!event.getMessage()) {
389
            return;
390
        }
391
392
        if (event.getType() === 'IssuesEvent' || event.getType() === 'IssueCommentEvent') {
393
            this.audio.playClav(event.getMessage().length * 1.1);
394
        } else if(event.getType() === 'PushEvent') {
395
            this.audio.playCelesta(event.getMessage().length * 1.1);
396
        }else{
397
            this.audio.playSwell();
398
        }
399
400
        drawEvent(event, svg);
401
    };
402
403
    return Application;
404
}(window, jQuery));
405
406
var svg = d3.select("#area").append("svg");
1 ignored issue
show
Bug introduced by
The variable d3 seems to be never declared. If this is a global, consider adding a /** global: d3 */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
407
408
$(function() {
409
    new GitAmp().run();
410
});
411
412
var element;
413
var drawingArea;
414
var width;
415
var height;
416
var volume = 0.6;
417
418
var scale_factor = 6,
419
    max_life = 20000;
420
421
var svg_background_color_online  = '#232323',
422
    svg_background_color_offline = '#232323',
423
    svg_text_color               = '#FFFFFF',
424
    edit_color                   = '#FFFFFF';
425
426
$(function(){
427
  element = document.documentElement;
428
  drawingArea = document.getElementsByTagName('#area');
429
  width  = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
430
  height = (window.innerHeight - $('header').height()) || (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
431
  $('svg').css('background-color', svg_background_color_online);
432
  $('header').css('background-color', svg_background_color_online);
433
  $('svg text').css('color', svg_text_color);
434
435
  // Main drawing area
436
  //svg = d3.select("#area").append("svg");
437
  svg.attr({width: width, height: height});
438
  svg.style('background-color', svg_background_color_online);
439
440
  // For window resizes
441
  var update_window = function() {
442
      width  = window.innerWidth || element.clientWidth || drawingArea.clientWidth;
443
      height = (window.innerHeight - $('header').height()) || (element.clientHeight - $('header').height()) || (drawingArea.clientHeight - $('header').height());
444
      svg.attr("width", width).attr("height", height);
445
  };
446
  window.onresize = update_window;
447
  update_window();
448
});
449
450
function drawEvent(event, svg_area) {
451
    var starting_opacity = 1;
452
    var opacity = 1 / (100 / event.getMessage().length);
453
    if (opacity > 0.5) opacity = 0.5;
0 ignored issues
show
Unused Code introduced by
The assignment to variable opacity seems to be never used. Consider removing it.
Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
454
455
    var size = event.getMessage().length;
456
    var label_text;
457
    var ring_radius = 80;
458
    var ring_anim_duration = 3000;
459
    svg_text_color = '#FFFFFF';
460
461
    switch(event.getType()){
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
462
        case "PushEvent":
463
            label_text = event.getActorName() + " pushed to " + event.getRepositoryName();
464
            edit_color = '#22B65D';
465
            break;
466
        case "PullRequestEvent":
467
            label_text = event.getActorName() + " " +
468
                event.getAction() + " " + " a PR for " + event.getRepositoryName();
469
            edit_color = '#8F19BB';
470
            ring_anim_duration = 10000;
471
            ring_radius = 600;
472
            break;
473
        case "IssuesEvent":
474
            label_text = event.getActorName() + " " +
475
                event.getAction() + " an issue in " + event.getRepositoryName();
476
            edit_color = '#ADD913';
477
            break;
478
        case "IssueCommentEvent":
479
            label_text = event.getActorName() + " commented in " + event.getRepositoryName();
480
            edit_color = '#FF4901';
481
            break;
482
        case "ForkEvent":
483
            label_text = event.getActorName() + " forked " + event.getRepositoryName();
484
            edit_color = '#0184FF';
485
            break;
486
        case "CreateEvent":
487
            label_text = event.getActorName() + " created " + event.getRepositoryName();
488
            edit_color = '#00C0C0';
489
            break;
490
        case "WatchEvent":
491
            label_text = event.getActorName() + " watched " + event.getRepositoryName();
492
            edit_color = '#E60062';
493
            break;
494
    }
495
496
    var no_label = false;
0 ignored issues
show
Unused Code introduced by
The variable no_label seems to be never used. Consider removing it.
Loading history...
497
    var type = event.getType();
498
499
    var abs_size = Math.abs(size);
500
    size = Math.max(Math.sqrt(abs_size) * scale_factor, 3);
501
502
    Math.seedrandom(event.getMessage());
503
    var x = Math.random() * (width - size) + size;
504
    var y = Math.random() * (height - size) + size;
505
506
    var circle_group = svg_area.append('g')
507
        .attr('transform', 'translate(' + x + ', ' + y + ')')
508
        .attr('fill', edit_color)
509
        .style('opacity', starting_opacity);
510
511
    var ring = circle_group.append('circle');
512
    ring.attr({r: size, stroke: 'none'});
513
    ring.transition()
514
        .attr('r', size + ring_radius)
515
        .style('opacity', 0)
516
        .ease(Math.sqrt)
517
        .duration(ring_anim_duration)
518
        .remove();
519
520
    var circle_container = circle_group.append('a');
521
    circle_container.attr('xlink:href', event.getUrl());
522
    circle_container.attr('target', '_blank');
523
    circle_container.attr('fill', svg_text_color);
524
525
    var circle = circle_container.append('circle');
526
    circle.classed(type, true);
527
    circle.attr('r', size)
528
        .attr('fill', edit_color)
529
        .transition()
530
        .duration(max_life)
531
        .style('opacity', 0)
532
        .remove();
533
534
    circle_container.on('mouseover', function() {
535
        circle_container.append('text')
536
            .text(label_text)
0 ignored issues
show
Bug introduced by
The variable label_text seems to not be initialized for all possible execution paths. Are you sure text handles undefined variables?
Loading history...
537
            .classed('label', true)
538
            .attr('text-anchor', 'middle')
539
            .attr('font-size', '0.8em')
540
            .transition()
541
            .delay(1000)
542
            .style('opacity', 0)
543
            .duration(2000)
544
            .each(function() { no_label = true; })
0 ignored issues
show
Unused Code introduced by
The variable no_label seems to be never used. Consider removing it.
Loading history...
545
            .remove();
546
    });
547
548
    var text = circle_container.append('text')
549
        .text(label_text)
0 ignored issues
show
Bug introduced by
The variable label_text seems to not be initialized for all possible execution paths. Are you sure text handles undefined variables?
Loading history...
550
        .classed('article-label', true)
551
        .attr('text-anchor', 'middle')
552
        .attr('font-size', '0.8em')
553
        .transition()
554
        .delay(2000)
555
        .style('opacity', 0)
556
        .duration(5000)
557
        .each(function() { no_label = true; })
0 ignored issues
show
Unused Code introduced by
The variable no_label seems to be never used. Consider removing it.
Loading history...
558
        .remove();
559
560
    // Remove HTML of decayed events
561
    // Keep it less than 50
562
    if($('#area svg g').length > 50){
563
        $('#area svg g:lt(10)').remove();
564
    }
565
}
566