<commit_before>
function setup_ajax_logging(elm) {
    var count = 0;

    function update(msg) {
        elm.text(count + ' outstanding requests. ' + msg);
    }

    $(document).ajaxSend(function (event, jqxhr, settings) {
        count++;
        update('Fetching ' + settings.url);
    });

    $(document).ajaxComplete(function (event, jqxhr, settings) {
        count--;
        update('Retrieved ' + settings.url);
    });
}

function log() {
    var p = $('<p>');
    var now = new Date();
    p.append((now.getHours() < 10 ? '0' : '') + now.getHours(), ':',
             (now.getMinutes() < 10 ? '0' : '') + now.getMinutes(), ':',
             (now.getSeconds() < 10 ? '0' : '') + now.getSeconds(), ':');

    for (var i = 0; i < arguments.length; i++) {
        p.append(' ' + arguments[i]);
    }

    var l = $('#log');
    l.append(p);

    var pos = p.position();
    var diff = pos.top + p.height() - l.height();

    if (diff > 0) {
        l.scrollTop(l.scrollTop() + diff);
    }
}

function swift_url() {
    var path = window.location.pathname;
    var parts = path.split('/');
    while (parts.length > 3) {
        parts.pop();
    }
    return parts.join('/');
}

function list_objects(container, opts, success) {
    var param = $.param(opts);
    var url = swift_url() + '/' + container + '?' + param;
    return $.getJSON(url, success);
}

function list_containers(opts, success) {
    var param = $.param(opts);
    var url = swift_url() + '/?' + param;
    return $.getJSON(url, success);
}

function load_videos(container, opts, success) {
    list_objects(container, opts, function (data, status, xhr) {
        var count = xhr.getResponseHeader('X-Container-Object-Count');
        if (count) {
            $('#count').text(count);
        }
        if (data.length == 0) {
            return (success || $.noop)({videos: []}, true, true);
        } else {
            var first = data[0].name;
            var last = data[data.length - 1].name;
            var prev = list_objects(container, {limit: 1, end_marker: first});
            var next = list_objects(container, {limit: 1, marker: last});

            videos = $.map(data, function (obj) {
                var path = container + '/' + encodeURIComponent(obj.name);
                return {
                    name: obj.name,
                    src: swift_url() + '/' + path
                };
            });
            $.when(prev, next).then(function (a_prev, a_next) {
                var first = a_prev[0].length == 0;
                var last = a_next[0].length == 0;
                return (success || $.noop)({videos: videos}, first, last);
            });
        }
    });
}

function page_videos(element, direction) {
    var videos = element.find('.video');
    var opts = {limit: 6, marker: null, end_marker: null};
    if (videos.length > 0) {
        if (direction == 'prev') {
            var first_video = videos[0];
            opts.end_marker = $(first_video).data('name');
        } else {
            var last_video = videos[videos.length - 1];
            opts.marker = $(last_video).data('name');
        }
    }

    load_videos(element.data('container'), opts, function (videos, first, last) {
        log('Loaded', videos.videos.length, 'videos');
        var template = element.data('template');
        var html = template(videos);
        element.html(html);
        load_video_data(element);
        element.data('prev')[first ? 'addClass' : 'removeClass']('disabled');
        element.data('next')[last ? 'addClass' : 'removeClass']('disabled');
    });
}

function show_video(elm) {
    $('#player > video').attr('src', $(elm).data('src'));
    $('#player').fadeIn();
    $('#dimmer').fadeIn();
}

function update_job_input(base_job, container, name) {
    var job = JSON.parse(JSON.stringify(base_job));  // clone job
    var path = 'swift://~/' + container + '/' + name;
    var devices = job[0].file_list;
    for (i = 0; i < devices.length; i++) {
        if (devices[i].device == "input") {
            devices[i].path = path;
            return job;
        }
    }
}

function loop_dots(next) {
    var duration = 200;
    var dots = $(this);
    dots.children().each(function (i, dot) {
        dots.queue(function (next) {
            $(dot).fadeIn();
            next();
        });
        dots.delay(duration);
    });
    dots.fadeOut();
    dots.delay(duration);
    dots.queue(function (next) {
        dots.children().hide();
        dots.show();
        next();
    });
    dots.queue(loop_dots);
    next();
}

function start_loading_animation(elm) {
    var dots = elm.children('.dots');
    for (i = 0; i < 3; i++) {
        dots.append($('<span>').text('.').hide());
    }
    dots.queue(loop_dots);
}

function stop_loading_animation(elm) {
    elm.children('.dots').finish();
    elm.fadeOut();
}

$.ajaxTransport("blob", function(options, originalOptions, jqXHR){
    if (window.FormData) {
        return {
            send: function(headers, completeCallback){
                var xhr = new XMLHttpRequest();
                xhr.addEventListener('load', function () {
                    var res = {};
                    res[options.dataType] = xhr.response;
                    completeCallback(xhr.status, xhr.statusText, res,
                                     xhr.getAllResponseHeaders());
                });
                xhr.open(options.type, options.url, options.async);
                xhr.responseType = options.dataType;
	        for (var key in headers) {
                    xhr.setRequestHeader(key, headers[key]);
                }
                xhr.send(options.data);
            },
            abort: function () {
                jqXHR.abort();
            }
        };
    }
});

function blob_execute(job, success) {
    var headers = {'X-Zerovm-Execute': '1.0'};
    return $.ajax({
        'mgtest': 123,
        'type': 'POST',
        'url': swift_url(),
        'data': JSON.stringify(job),
        'headers': headers,
        'cache': false,
        'success': success,
        'contentType': 'application/json',
        'dataType': 'blob'
    });
}

function load_video_data(elm) {
    var client = new ZeroCloudClient();
    var opts = {version: "0.0", swiftUrl: swift_url()};
    var meta = swift_url() + '/video-browser/extract-meta/extract-meta.json';
    var thumb = swift_url() + '/video-browser/extract-thumbnail/extract-thumbnail.json';
    var prefix = swift_url() + '/' + elm.data('container');
    var container = elm.data('container');

    client.auth(opts, function () {
        var meta_job = $.getJSON(meta);
        var thumb_job = $.getJSON(thumb);

        elm.find('.video').each(function (i, video) {
            var name = $(video).data('name');
            var title = $(video).children('.title');
            var loading = $(video).find('.loading');
            start_loading_animation(loading);

            var ajax_opts = {method: 'HEAD', cache: false};
            var q = $.ajax(prefix + '/' + name, ajax_opts);

            q.then(function (data, status, xhr) {
                log('Swift - loaded metadata for', name);
                var text = xhr.getResponseHeader('X-Object-Meta-Title');
                if (text) {
                    log('Found title for', name, 'in Swift');
                    title.text(text);
                    title.addClass('updated');
                } else {
                    meta_job.then(function (base_job) {
                        job = update_job_input(base_job, container, name);
                        log('Loading title for', name, 'with ZeroVM');
                        client.execute(job, function (result) {
                            result = ini_parse(result);
                            if (result.title) {
                                title.text(result.title);
                                title.addClass('updated');
                                log('ZeroVM - extracted title for', name);
                            }
                        });
                    });
                }

                var thumbUrl = xhr.getResponseHeader('X-Object-Meta-Thumbnail');
                if (thumbUrl) {
                    $(video).css('background-image', 'url(' + thumbUrl + ')');
                    stop_loading_animation(loading);
                    log('Swift - loaded thumbnail URL for', name);
                } else {
                    thumb_job.then(function (base_job) {
                        return update_job_input(base_job, container, name);
                    }).then(blob_execute).then(function (blob) {
                        var url = URL.createObjectURL(blob);
                        $(video).css('background-image', 'url("' + url + '")');
                        stop_loading_animation(loading);
                        log('ZeroVM - extracted thumbnail for', name);
                    });
                }
            });
        });
    });
}

function ini_parse(data) {
    var result = {};
    var section = null;
    $.each(data.split('\n'), function (i, line) {
        if (!line || line.charAt(0) == ';')
            return true;
        if (line.charAt(0) == '[') {
            section = line.substr(1, line.length - 2);
            return true;
        }
        var keyvalue = line.split('=', 2);
        var key = keyvalue[0];
        if (section)
            key = section + '.' + key;
        result[key] = keyvalue[1];
    });
    return result;
}
<commit_msg>Allow calling load_video_data multiple times<commit_after>
function setup_ajax_logging(elm) {
    var count = 0;

    function update(msg) {
        elm.text(count + ' outstanding requests. ' + msg);
    }

    $(document).ajaxSend(function (event, jqxhr, settings) {
        count++;
        update('Fetching ' + settings.url);
    });

    $(document).ajaxComplete(function (event, jqxhr, settings) {
        count--;
        update('Retrieved ' + settings.url);
    });
}

function log() {
    var p = $('<p>');
    var now = new Date();
    p.append((now.getHours() < 10 ? '0' : '') + now.getHours(), ':',
             (now.getMinutes() < 10 ? '0' : '') + now.getMinutes(), ':',
             (now.getSeconds() < 10 ? '0' : '') + now.getSeconds(), ':');

    for (var i = 0; i < arguments.length; i++) {
        p.append(' ' + arguments[i]);
    }

    var l = $('#log');
    l.append(p);

    var pos = p.position();
    var diff = pos.top + p.height() - l.height();

    if (diff > 0) {
        l.scrollTop(l.scrollTop() + diff);
    }
}

function swift_url() {
    var path = window.location.pathname;
    var parts = path.split('/');
    while (parts.length > 3) {
        parts.pop();
    }
    return parts.join('/');
}

function list_objects(container, opts, success) {
    var param = $.param(opts);
    var url = swift_url() + '/' + container + '?' + param;
    return $.getJSON(url, success);
}

function list_containers(opts, success) {
    var param = $.param(opts);
    var url = swift_url() + '/?' + param;
    return $.getJSON(url, success);
}

function load_videos(container, opts, success) {
    list_objects(container, opts, function (data, status, xhr) {
        var count = xhr.getResponseHeader('X-Container-Object-Count');
        if (count) {
            $('#count').text(count);
        }
        if (data.length == 0) {
            return (success || $.noop)({videos: []}, true, true);
        } else {
            var first = data[0].name;
            var last = data[data.length - 1].name;
            var prev = list_objects(container, {limit: 1, end_marker: first});
            var next = list_objects(container, {limit: 1, marker: last});

            videos = $.map(data, function (obj) {
                var path = container + '/' + encodeURIComponent(obj.name);
                return {
                    name: obj.name,
                    src: swift_url() + '/' + path
                };
            });
            $.when(prev, next).then(function (a_prev, a_next) {
                var first = a_prev[0].length == 0;
                var last = a_next[0].length == 0;
                return (success || $.noop)({videos: videos}, first, last);
            });
        }
    });
}

function page_videos(element, direction) {
    var videos = element.find('.video');
    var opts = {limit: 6, marker: null, end_marker: null};
    if (videos.length > 0) {
        if (direction == 'prev') {
            var first_video = videos[0];
            opts.end_marker = $(first_video).data('name');
        } else {
            var last_video = videos[videos.length - 1];
            opts.marker = $(last_video).data('name');
        }
    }

    load_videos(element.data('container'), opts, function (videos, first, last) {
        log('Loaded', videos.videos.length, 'videos');
        var template = element.data('template');
        var html = template(videos);
        element.html(html);
        load_video_data(element);
        element.data('prev')[first ? 'addClass' : 'removeClass']('disabled');
        element.data('next')[last ? 'addClass' : 'removeClass']('disabled');
    });
}

function show_video(elm) {
    $('#player > video').attr('src', $(elm).data('src'));
    $('#player').fadeIn();
    $('#dimmer').fadeIn();
}

function update_job_input(base_job, container, name) {
    var job = JSON.parse(JSON.stringify(base_job));  // clone job
    var path = 'swift://~/' + container + '/' + name;
    var devices = job[0].file_list;
    for (i = 0; i < devices.length; i++) {
        if (devices[i].device == "input") {
            devices[i].path = path;
            return job;
        }
    }
}

function loop_dots(next) {
    var duration = 200;
    var dots = $(this);
    dots.children().each(function (i, dot) {
        dots.queue(function (next) {
            $(dot).fadeIn();
            next();
        });
        dots.delay(duration);
    });
    dots.fadeOut();
    dots.delay(duration);
    dots.queue(function (next) {
        dots.children().hide();
        dots.show();
        next();
    });
    dots.queue(loop_dots);
    next();
}

function start_loading_animation(elm) {
    var dots = elm.children('.dots');
    while (dots.children().length < 3) {
        dots.append($('<span>').text('.').hide());
    }
    dots.queue(loop_dots);
    elm.fadeIn();
}

function stop_loading_animation(elm) {
    elm.children('.dots').finish();
    elm.fadeOut();
}

$.ajaxTransport("blob", function(options, originalOptions, jqXHR){
    if (window.FormData) {
        return {
            send: function(headers, completeCallback){
                var xhr = new XMLHttpRequest();
                xhr.addEventListener('load', function () {
                    var res = {};
                    res[options.dataType] = xhr.response;
                    completeCallback(xhr.status, xhr.statusText, res,
                                     xhr.getAllResponseHeaders());
                });
                xhr.open(options.type, options.url, options.async);
                xhr.responseType = options.dataType;
	        for (var key in headers) {
                    xhr.setRequestHeader(key, headers[key]);
                }
                xhr.send(options.data);
            },
            abort: function () {
                jqXHR.abort();
            }
        };
    }
});

function blob_execute(job, success) {
    var headers = {'X-Zerovm-Execute': '1.0'};
    return $.ajax({
        'mgtest': 123,
        'type': 'POST',
        'url': swift_url(),
        'data': JSON.stringify(job),
        'headers': headers,
        'cache': false,
        'success': success,
        'contentType': 'application/json',
        'dataType': 'blob'
    });
}

function load_video_data(elm) {
    var client = new ZeroCloudClient();
    var opts = {version: "0.0", swiftUrl: swift_url()};
    var meta = swift_url() + '/video-browser/extract-meta/extract-meta.json';
    var thumb = swift_url() + '/video-browser/extract-thumbnail/extract-thumbnail.json';
    var prefix = swift_url() + '/' + elm.data('container');
    var container = elm.data('container');

    client.auth(opts, function () {
        var meta_job = $.getJSON(meta);
        var thumb_job = $.getJSON(thumb);

        elm.find('.video').each(function (i, video) {
            var name = $(video).data('name');
            var title = $(video).children('.title');
            var loading = $(video).find('.loading');
            start_loading_animation(loading);

            var ajax_opts = {method: 'HEAD', cache: false};
            var q = $.ajax(prefix + '/' + name, ajax_opts);

            q.then(function (data, status, xhr) {
                log('Swift - loaded metadata for', name);
                var text = xhr.getResponseHeader('X-Object-Meta-Title');
                if (text) {
                    log('Found title for', name, 'in Swift');
                    title.text(text);
                    title.addClass('updated');
                } else {
                    meta_job.then(function (base_job) {
                        job = update_job_input(base_job, container, name);
                        log('Loading title for', name, 'with ZeroVM');
                        client.execute(job, function (result) {
                            result = ini_parse(result);
                            if (result.title) {
                                title.text(result.title);
                                title.addClass('updated');
                                log('ZeroVM - extracted title for', name);
                            }
                        });
                    });
                }

                var thumbUrl = xhr.getResponseHeader('X-Object-Meta-Thumbnail');
                if (thumbUrl) {
                    $(video).css('background-image', 'url(' + thumbUrl + ')');
                    stop_loading_animation(loading);
                    log('Swift - loaded thumbnail URL for', name);
                } else {
                    thumb_job.then(function (base_job) {
                        return update_job_input(base_job, container, name);
                    }).then(blob_execute).then(function (blob) {
                        var url = URL.createObjectURL(blob);
                        $(video).css('background-image', 'url("' + url + '")');
                        stop_loading_animation(loading);
                        log('ZeroVM - extracted thumbnail for', name);
                    });
                }
            });
        });
    });
}

function ini_parse(data) {
    var result = {};
    var section = null;
    $.each(data.split('\n'), function (i, line) {
        if (!line || line.charAt(0) == ';')
            return true;
        if (line.charAt(0) == '[') {
            section = line.substr(1, line.length - 2);
            return true;
        }
        var keyvalue = line.split('=', 2);
        var key = keyvalue[0];
        if (section)
            key = section + '.' + key;
        result[key] = keyvalue[1];
    });
    return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Microsoft Open Technologies (Shanghai) Co. Ltd.  All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

(function ($, oh) {
    'use strict';

    var hackathon_name = oh.comm.getCurrentHackathon();
    var def_expid = 0;

    function pageload() {
        def_expid = $('[data-experiment]').data('experiment') || 0;
        if (def_expid) {
            getExperiment()
        } else {
            getTemplate();
        }
        teamMember();
        hacakthonStat();
    }

    function teamMember() {
//        oh.api.team.member.list.get({header: {hackathon_name: hackathon_name}}, function (data) {
//            // todo 'Response team member'
//            if (data.error) {
//
//            } else {
//
//            }
//            console.log(data);
//        });
    }

    function hacakthonStat() {
        oh.api.hackathon.stat.get({
            header: {hackathon_name: hackathon_name}
        }, function (data) {
            $('#online').text(data.online);
            $('#total').text(data.total);
            //setTimeout(hacakthonStat(), 600000)
        });
    }

    function getTemplate() {
        oh.api.hackathon.template.get({header: {hackathon_name: hackathon_name}}, function (data) {
            if (data.error) {
                showErrorMsg(data);
            } else {
                if (data.length > 0) {
                    def_expid = data[0].id;
                    postTemplate(data[0].name);
                } else {
                    showErrorMsg({
                        error: {
                            code: 404,
                            friendly_message: '没有模板'
                        }
                    });
                }
            }
        });
    }

    function postTemplate(name) {
        oh.api.user.experiment.post({
            body: {template_name: name, hackathon_name: hackathon_name}
        }, function (data) {
            loadExperiment(data);
        });
    }

    function showErrorMsg(data) {
        $('#load').hide();
        var errorbox = $('#error').hide();
        if (data.error.code) {
            errorbox.find('.code').text(data.error.code);
        }
        if (data.error.friendly_message) {
            errorbox.find('.message').text(data.error.friendly_message);
        }
        errorbox.show();
    }

    function getExperiment() {
        oh.api.user.experiment.get({query: {id: def_expid}}, function (data) {
            loadExperiment(data);
        });
    }

    function loadExperiment(data) {
        var tmpe = '
\

\
                            \
                                \
                            \

{name}
\

\

';

        if (data.status == 2) {
            var dockers = []
            for (var i in data.remote_servers) {
                dockers.push({
                    purl: "",
                    imgUrl: data.remote_servers[i].name == 'cloud_eclipse' ? '/static/pic/idehub.png' : '/static/pic/dseries.png',
                    name: data.remote_servers[i].name,
                    surl: data.remote_servers[i].name == 'cloud_eclipse' ? data.remote_servers[i].url + window.location.origin : data.remote_servers[i].url + "&oh=" + $.cookie('token')
                })
                $('.hackathon-nav').append(tmpe.format(dockers[i]));
            }
            heartbeat(def_expid);
        } else if (data.status == 1) {
            setTimeout(getExperiment, 60000);
        } else {
            showErrorMsg(data);
        }
    }

    function bindEvent() {
        var work_center = $('.center').on('mouseover', 'iframe', function (e) {
            $(this).focus();
        });
        var hnav = $('.hackathon-nav').on('click', 'a.vm-box', function (e) {
            hnav.find('.vm-box').removeClass('active')
            var a = $(this).addClass('active');
            var url = a.data('url');
            var token = a.data('token');
            var name = a.attr('id')
            var ifrem = work_center.find('#' + name);
            work_center.find('iframe').addClass('invisible');
            if (ifrem.length > 0) {
                ifrem.removeClass('invisible');
            } else {
                ifrem = $('').attr({
                    src: url,
                    id: name,
                    width: '100%',
                    height: '100%',
                    frameborder: 'no',
                    marginwidth: '0',
                    scrolling: 'no'
                }).appendTo(work_center)
            }
        });

        var smallbtn = $('

')
            .click(function (e) {
                e.preventDefault();
                $('iframe[class!="invisible"]').removeClass('work-full');
                smallbtn.hide();
            }).appendTo('body');

        var fullbtn = $('#workfull').click(function (e) {
            e.preventDefault();
            $('iframe[class!="invisible"]').addClass('work-full');
            $('.smallscreen').show();
        });
    }

    function heartbeat(id) {
        oh.api.user.experiment.put({
            body: {id: id}
        }, function (data) {
            if (data.error) {
                // todo 'heartbeat error'
            } else {
                window.setTimeout(function(){
                        heartbeat(id)
                    }, 300000)
                }
            }
        });
    }

    function init() {
        pageload();
        bindEvent();
    }

    function endCountdown() {
        var timerTmpe = '{day}天{hour}小时{minute}分钟{second}秒';

        function show_time() {
            var timing = {day: 0, hour: 0, minute: 0, second: 0, distance: 0};
            this.time_server += 1000
            timing.distance = this.time_end - this.time_server;
            if (timing.distance > 0) {
                timing.day = Math.floor(timing.distance / 86400000)
                timing.distance -= timing.day * 86400000;
                timing.hour = Math.floor(timing.distance / 3600000)
                timing.distance -= timing.hour * 3600000;
                timing.minute = Math.floor(timing.distance / 60000)
                timing.distance -= timing.minute * 60000;
                timing.second = Math.floor(timing.distance / 1000)
                if (timing.day == 0) {
                    timing.day = null
                }
                if (timing.hour == 0 && timing.day == null) {
                    timing.hour = null
                }
                if (timing.minute == 0 && timing.hour == null) {
                    timing.minute = null
                }
                if (timing.second == 0 && timing.minute == null) {
                    timing.second = null
                }
                return timing;
            } else {
                return null;
            }
        }

        function showCountDown(countDown) {
            var timing = show_time.apply(countDown);
            if (!timing) {
                $('#timer').text('本次活动已结束，非常感谢您的参与。')
                clearInterval(stop);
            } else {
                $('#end_timer').text(timerTmpe.format(timing))
            }
        }

        var countDown = {
            time_server: new Date().getTime(),
            time_end: $('#end_timer').data('endtiem')
        }
        showCountDown(countDown);
        var stop = setInterval(function () {
            showCountDown(countDown);
        }, 1000);
    }

    $(function () {
        init();
        endCountdown();
    })
})(window.jQuery, window.oh);<commit_msg>remove duplicate '}'<commit_after>/*
 * Copyright (c) Microsoft Open Technologies (Shanghai) Co. Ltd.  All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

(function ($, oh) {
    'use strict';

    var hackathon_name = oh.comm.getCurrentHackathon();
    var def_expid = 0;

    function pageload() {
        def_expid = $('[data-experiment]').data('experiment') || 0;
        if (def_expid) {
            getExperiment()
        } else {
            getTemplate();
        }
        teamMember();
        hacakthonStat();
    }

    function teamMember() {
//        oh.api.team.member.list.get({header: {hackathon_name: hackathon_name}}, function (data) {
//            // todo 'Response team member'
//            if (data.error) {
//
//            } else {
//
//            }
//            console.log(data);
//        });
    }

    function hacakthonStat() {
        oh.api.hackathon.stat.get({
            header: {hackathon_name: hackathon_name}
        }, function (data) {
            $('#online').text(data.online);
            $('#total').text(data.total);
            //setTimeout(hacakthonStat(), 600000)
        });
    }

    function getTemplate() {
        oh.api.hackathon.template.get({header: {hackathon_name: hackathon_name}}, function (data) {
            if (data.error) {
                showErrorMsg(data);
            } else {
                if (data.length > 0) {
                    def_expid = data[0].id;
                    postTemplate(data[0].name);
                } else {
                    showErrorMsg({
                        error: {
                            code: 404,
                            friendly_message: '没有模板'
                        }
                    });
                }
            }
        });
    }

    function postTemplate(name) {
        oh.api.user.experiment.post({
            body: {template_name: name, hackathon_name: hackathon_name}
        }, function (data) {
            loadExperiment(data);
        });
    }

    function showErrorMsg(data) {
        $('#load').hide();
        var errorbox = $('#error').hide();
        if (data.error.code) {
            errorbox.find('.code').text(data.error.code);
        }
        if (data.error.friendly_message) {
            errorbox.find('.message').text(data.error.friendly_message);
        }
        errorbox.show();
    }

    function getExperiment() {
        oh.api.user.experiment.get({query: {id: def_expid}}, function (data) {
            loadExperiment(data);
        });
    }

    function loadExperiment(data) {
        var tmpe = '
\

\
                            \
                                \
                            \

{name}
\

\

';

        if (data.status == 2) {
            var dockers = []
            for (var i in data.remote_servers) {
                dockers.push({
                    purl: "",
                    imgUrl: data.remote_servers[i].name == 'cloud_eclipse' ? '/static/pic/idehub.png' : '/static/pic/dseries.png',
                    name: data.remote_servers[i].name,
                    surl: data.remote_servers[i].name == 'cloud_eclipse' ? data.remote_servers[i].url + window.location.origin : data.remote_servers[i].url + "&oh=" + $.cookie('token')
                })
                $('.hackathon-nav').append(tmpe.format(dockers[i]));
            }
            heartbeat(def_expid);
        } else if (data.status == 1) {
            setTimeout(getExperiment, 60000);
        } else {
            showErrorMsg(data);
        }
    }

    function bindEvent() {
        var work_center = $('.center').on('mouseover', 'iframe', function (e) {
            $(this).focus();
        });
        var hnav = $('.hackathon-nav').on('click', 'a.vm-box', function (e) {
            hnav.find('.vm-box').removeClass('active')
            var a = $(this).addClass('active');
            var url = a.data('url');
            var token = a.data('token');
            var name = a.attr('id')
            var ifrem = work_center.find('#' + name);
            work_center.find('iframe').addClass('invisible');
            if (ifrem.length > 0) {
                ifrem.removeClass('invisible');
            } else {
                ifrem = $('').attr({
                    src: url,
                    id: name,
                    width: '100%',
                    height: '100%',
                    frameborder: 'no',
                    marginwidth: '0',
                    scrolling: 'no'
                }).appendTo(work_center)
            }
        });

        var smallbtn = $('

')
            .click(function (e) {
                e.preventDefault();
                $('iframe[class!="invisible"]').removeClass('work-full');
                smallbtn.hide();
            }).appendTo('body');

        var fullbtn = $('#workfull').click(function (e) {
            e.preventDefault();
            $('iframe[class!="invisible"]').addClass('work-full');
            $('.smallscreen').show();
        });
    }

    function heartbeat(id) {
        oh.api.user.experiment.put({
            body: {id: id}
        }, function (data) {
            if (data.error) {
                // todo 'heartbeat error'
            } else {
                window.setTimeout(function(){
                        heartbeat(id)
                    }, 300000)
            }
        });
    }

    function init() {
        pageload();
        bindEvent();
    }

    function endCountdown() {
        var timerTmpe = '{day}天{hour}小时{minute}分钟{second}秒';

        function show_time() {
            var timing = {day: 0, hour: 0, minute: 0, second: 0, distance: 0};
            this.time_server += 1000
            timing.distance = this.time_end - this.time_server;
            if (timing.distance > 0) {
                timing.day = Math.floor(timing.distance / 86400000)
                timing.distance -= timing.day * 86400000;
                timing.hour = Math.floor(timing.distance / 3600000)
                timing.distance -= timing.hour * 3600000;
                timing.minute = Math.floor(timing.distance / 60000)
                timing.distance -= timing.minute * 60000;
                timing.second = Math.floor(timing.distance / 1000)
                if (timing.day == 0) {
                    timing.day = null
                }
                if (timing.hour == 0 && timing.day == null) {
                    timing.hour = null
                }
                if (timing.minute == 0 && timing.hour == null) {
                    timing.minute = null
                }
                if (timing.second == 0 && timing.minute == null) {
                    timing.second = null
                }
                return timing;
            } else {
                return null;
            }
        }

        function showCountDown(countDown) {
            var timing = show_time.apply(countDown);
            if (!timing) {
                $('#timer').text('本次活动已结束，非常感谢您的参与。')
                clearInterval(stop);
            } else {
                $('#end_timer').text(timerTmpe.format(timing))
            }
        }

        var countDown = {
            time_server: new Date().getTime(),
            time_end: $('#end_timer').data('endtiem')
        }
        showCountDown(countDown);
        var stop = setInterval(function () {
            showCountDown(countDown);
        }, 1000);
    }

    $(function () {
        init();
        endCountdown();
    })
})(window.jQuery, window.oh);<|endoftext|>


<commit_before>var update = (function() {

//Width and height
var width = '300',
    height = '300',
    radius = Math.min(width, height) / 2,
    color = d3.scale.category20(),
    cpus,
    mems,
    arc,
    svg,
    g,
    lastData,
    shouldUpdate = true,
    path,
    vizPieCPU = d3.layout.pie()
                .sort(null)
                .value(function(d) { return d; });
    vizPieMem = d3.layout.pie()
                .sort(null)
                .value(function(d) { return d; });

var svgCPU,
    svgMem,
    arcCPU,
    arcMem,
    gCPU,
    gMem;

/**
 * Initial setup for d3 elements
 */
function setup(jsonData) {
    var jsonData = BrowserUtils.getProcesses();
    cpus = [];
    mems = [];
    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            cpus.push(jsonData[item].cpu);
            mems.push(jsonData[item].memory);
        }
    }
    console.log("INSIDE SETUP:", mems);
    //Create SVG element
    svgCPU = d3.select("#cpuContainer").append("svg")
        .attr({
            height: height,
            width: width
        })
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .attr("class","svgCPU")

    svgMem = d3.select("#memContainer").append("svg")
        .attr({
            height: height,
            width: width
        })
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .attr("class","svgMem")

    arcCPU = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    arcMem = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    gCPU = svgCPU.selectAll(".arc")
        .data(vizPieCPU(cpus))
        .enter().append("path");
        // .attr("class", "arc");

    gMem = svgMem.selectAll(".arc")
        .data(vizPieMem(mems))
        .enter().append("path");
        // .attr("class", "arc");

    // // Add loading text.
    gCPU.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("Loading...");
}

/**
 * Creates and returns a handler to close a tab
 * @param id    the tabId
 * @return      handler to close the relevant tab
 */
function closeTab(id) {
    return function(evt) {
        chrome.tabs.remove(id || someTabIds.pop());
    }
}

/**
 * Returns the first element in an array matching the
 * input property/value pair
 * @param array      the array in question
 * @param prop       the property name
 * @param val        the value of the property to match
 */
function getArrayEltByProp(array, prop, val) {
    var i;
    for(i=0;i<array.length;i++) {
        if(array[i][prop] === val) {
            return array[i];
        }
    }
    return null;
}

/**
 * Creates and returns a click handler that creates
 * a menu with additional information about the selected
 * process
 * @param id             the id of the selected process
 * @param processList    the list of all processes
 * @return               hover handler
 */
function createProcessMenu(id, processList, container) {
    return function(evt) {
        shouldUpdate = false;
        evt.stopPropagation();
        $('#procMenu').remove();
        $('#lettuceWrap').on('click', function() {
            $('#procMenu').remove();
            shouldUpdate = true;
        });
        var left = evt.clientX,
            top = evt.clientY,
            menu = $(document.createElement('div')),
            nameDiv = $(document.createElement('div')),
            memDiv = $(document.createElement('div')),
            cpuDiv = $(document.createElement('div')),
            removeTabButton,
            process,
            name,
            mem,
            cpu;
        container = container || $('#lettuceWrap');
        menu.attr('id', 'procMenu');
        menu.css({
            position: 'absolute',
            left: left,
            top: top,
            background: 'rgba(255,100,0,0.5)'
        })
        container.append(menu);
        process = getArrayEltByProp(processList, 'id', id);
        mem = process.memory;
        cpu = process.cpu;
        if(process && process.info && process.info.type === 'tab') {
            removeTabButton = $(document.createElement('button'));
            removeTabButton.attr({
                type: 'button'
            });
            removeTabButton.text('close tab');
            removeTabButton.on('click', function(evt) {
                shouldUpdate = true;
                closeTab(process.info.tabid)(evt);
            });
            menu.append(removeTabButton);
            name = process.info.title;
        } else {
            name = process.info.type;
        }
        nameDiv.text(name);
        memDiv.text(mem);
        cpuDiv.text(cpu);
        menu.append(nameDiv);
        menu.append(memDiv);
        menu.append(cpuDiv);

    }
}

/**
 * Filters list of processes to reflect current filter settings
 * @param jsonData     the list of processes to filter
 * @return             the filtered list
 */
function filterProcesses(jsonData) {
    var filter = $('#filterSelect').val().toLowerCase().replace(/ /g,''),
        ret = [],
        type,
        i;
    for(i=0;i<jsonData.length;i++) {
        // debugger;
        type = jsonData[i].info.type;
        if(filter === 'all' || (type === 'tab' &&  filter==='tabsonly') || (type !== 'tab' && filter==='notabs')){
            ret.push(jsonData[i]);
        }
    }
    return ret;
}

/**
 * Update the d3 elements
 * @param jsonData    an array of processes
 */
function displayData(jsonData) {

    if(!shouldUpdate) {
        return;
    }
    $('#cpuContainer').empty(); // Clear
    $('#memContainer').empty(); // Clear

    jsonData = filterProcesses(jsonData);
    cpus = [];
    mems = [];
    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            cpus.push(jsonData[item].cpu);
            mems.push(jsonData[item].memory);
        }
    }

    var totalCPU = 0;
    var totalMem = 0;

    for(var i=0, len=cpus.length; i<len; i++){
        totalCPU += cpus[i];  //Iterate over your first array and then grab the second element add the values up
    }
    if (totalCPU === 0) {
        return;
    }
    for(var i=0, len=mems.length; i<len; i++){
        totalMem += mems[i];  //Iterate over your first array and then grab the second element add the values up
    }
    if (totalMem === 0) {
        return;
    }

    $('#loading').empty(); // Clear

    // For the most relevant names to display on the chart
    var dummyCPUS = cpus.slice(0);
    var dummyMems = mems.slice(0);
    maxCPUVals = [];
    maxMemVals = [];

    for(var i=0;i<4;i++) {
        var maxCPUVal = Math.max.apply(Math, dummyCPUS);
        maxCPUVals.push(maxCPUVal);

        var maxMemVal = Math.max.apply(Math, dummyMems);
        maxMemVals.push(maxMemVal);

        var indexCPU = dummyCPUS.indexOf(maxCPUVal);
        var indexMem = dummyMems.indexOf(maxMemVal);

        if (indexCPU > -1) {
            dummyCPUS.splice(indexCPU, 1);
        }
        if (indexMem > -1) {
            dummyMems.splice(indexMem, 1);
        }
    }

    namesCPU = []
    namesMem = []

    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            // Determine title to display
            if (maxMemVals.indexOf(jsonData[item].memory) === -1) {
                // Not one of the bigger processes w.r.t memory, so set its title to a blank string
                namesMem.push("");
            } else {
                // one of max vals, get real name
                if (jsonData[item].info.type == "tab") {

                    if (jsonData[item].info.title.length >= 10) {
                        var url = jsonData[item].info.url
                        title = url.match(/[^w]\w+\.{1}/g)

                        if (title == null) {
                            namesMem.push(jsonData[item].info.title.slice(1,10))
                        }
                        else {
                            var matchNum = 0;
                            if (title[matchNum].match(/www/g)) {
                                matchNum += 1
                            }
                            if (title[matchNum][0].match(/\w/g)){
                                // first char is alpha, so slice from there
                                finalTitle = title[matchNum].slice(0,-1);
                                namesMem.push(finalTitle);
                            }
                            else {
                                finalTitle = title[matchNum].slice(1,-1);
                                namesMem.push(finalTitle);
                            }

                        }
                    }
                    else {
                        namesMem.push(jsonData[item].info.title);
                    }
                }
                else {
                    namesMem.push(jsonData[item].info.type);
                }
            }
            if (maxCPUVals.indexOf(jsonData[item].cpu) === -1) {
                // Not one of the bigger processes w.r.t. cpu, so set its title to a blank string
                namesCPU.push("");
                continue;
            } else {
                // one of max vals, get real name
                if (jsonData[item].info.type == "tab") {

                    if (jsonData[item].info.title.length >= 10) {
                        var url = jsonData[item].info.url
                        title = url.match(/[^w]\w+\.{1}/g)

                        if (title == null) {
                            namesCPU.push(jsonData[item].info.title.slice(1,10))
                        }
                        else {
                            var matchNum = 0;
                            if (title[matchNum].match(/www/g)) {
                                matchNum += 1
                            }
                            if (title[matchNum][0].match(/\w/g)){
                                // first char is alpha, so slice from there
                                finalTitle = title[matchNum].slice(0,-1);
                                namesCPU.push(finalTitle);
                            }
                            else {
                                finalTitle = title[matchNum].slice(1,-1);
                                namesCPU.push(finalTitle);
                            }
                        }
                    }
                    else {
                        namesCPU.push(jsonData[item].info.title);
                    }
                }
                else {
                    namesCPU.push(jsonData[item].info.type);
                }
            }
        }
    }

    // Define svg canvas
    svgCPU = d3.select("#cpuContainer").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

    // Define svg canvas
    svgMem = d3.select("#memContainer").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

    arcCPU = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    arcMem = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    pathCPU = svgCPU.datum(cpus).selectAll("path")
                          .data(vizPieCPU)
                          .attr("d", arc)

    pathMem = svgMem.datum(mems).selectAll("path")
                          .data(vizPieMem)
                          .attr("d", arc)

    // Defines arcs
    gCPU = svgCPU.selectAll(".arc")
        .data(vizPieCPU(cpus))
        .enter().append("g")
        .attr("class", "arc")
        .style("stroke-width", 4);

    gMem = svgMem.selectAll(".arc")
        .data(vizPieMem(mems))
        .enter().append("g")
        .attr("class", "arc")
        .style("stroke-width", 4);

    console.log(arcCPU);
    // Draws and colors
    gCPU.append("path")
      .attr("d", arcCPU)
      .style("fill", function(d, i) { return color(i); });

    // Draws and colors
    gMem.append("path")
      .attr("d", arcMem)
      .style("fill", function(d, i) { return color(i); });

    svgCPU.selectAll('path').each(function(d, i) {
        $(this).attr('id', jsonData[i].id)
        $(this).on('click', createProcessMenu(parseInt($(this).attr('id'), 10), jsonData));
    });

    svgMem.selectAll('path').each(function(d, i) {
        // debugger;
        $(this).attr('id', jsonData[i].id)
        $(this).on('click', createProcessMenu(parseInt($(this).attr('id'), 10), jsonData));
    });

    gCPU.append("text")
      .attr("transform", function(d) { return "translate(" + arcCPU.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .style("font-size","8px")
      .data(namesCPU)
      .text(function(d, i) {return d; });

    gMem.append("text")
      .attr("transform", function(d) { return "translate(" + arcMem.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .style("font-size","8px")
      .data(namesMem)
      .text(function(d, i) {return d; });

    gCPU.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("CPU Usage");

    gMem.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("Memory Usage");

   }

return {
    displayData: displayData,
    setup:  setup
};

})();
<commit_msg>adding dough class<commit_after>var update = (function() {

//Width and height
var width = '300',
    height = '300',
    radius = Math.min(width, height) / 2,
    color = d3.scale.category20(),
    cpus,
    mems,
    arc,
    svg,
    g,
    lastData,
    shouldUpdate = true,
    path,
    vizPieCPU = d3.layout.pie()
                .sort(null)
                .value(function(d) { return d; });
    vizPieMem = d3.layout.pie()
                .sort(null)
                .value(function(d) { return d; });

var svgCPU,
    svgMem,
    arcCPU,
    arcMem,
    gCPU,
    gMem;

/**
 * Initial setup for d3 elements
 */
function setup(jsonData) {
    var jsonData = BrowserUtils.getProcesses();
    cpus = [];
    mems = [];
    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            cpus.push(jsonData[item].cpu);
            mems.push(jsonData[item].memory);
        }
    }
    //Create SVG element
    svgCPU = d3.select("#cpuContainer").append("svg")
        .attr({
            height: height,
            width: width
        })
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .attr("class","svgCPU")

    svgMem = d3.select("#memContainer").append("svg")
        .attr({
            height: height,
            width: width
        })
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
        .attr("class","svgMem")

    arcCPU = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    arcMem = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    gCPU = svgCPU.selectAll(".arc")
        .data(vizPieCPU(cpus))
        .enter().append("path");
        // .attr("class", "arc");

    gMem = svgMem.selectAll(".arc")
        .data(vizPieMem(mems))
        .enter().append("path");
        // .attr("class", "arc");

    // // Add loading text.
    gCPU.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("Loading...");
}

/**
 * Creates and returns a handler to close a tab
 * @param id    the tabId
 * @return      handler to close the relevant tab
 */
function closeTab(id) {
    return function(evt) {
        chrome.tabs.remove(id || someTabIds.pop());
    }
}

/**
 * Returns the first element in an array matching the
 * input property/value pair
 * @param array      the array in question
 * @param prop       the property name
 * @param val        the value of the property to match
 */
function getArrayEltByProp(array, prop, val) {
    var i;
    for(i=0;i<array.length;i++) {
        if(array[i][prop] === val) {
            return array[i];
        }
    }
    return null;
}

/**
 * Creates and returns a click handler that creates
 * a menu with additional information about the selected
 * process
 * @param id             the id of the selected process
 * @param processList    the list of all processes
 * @return               hover handler
 */
function createProcessMenu(id, processList, container) {
    return function(evt) {
        shouldUpdate = false;
        evt.stopPropagation();
        $('#procMenu').remove();
        $('#lettuceWrap').on('click', function() {
            $('#procMenu').remove();
            shouldUpdate = true;
        });
        var left = evt.clientX,
            top = evt.clientY,
            menu = $(document.createElement('div')),
            nameDiv = $(document.createElement('div')),
            memDiv = $(document.createElement('div')),
            cpuDiv = $(document.createElement('div')),
            removeTabButton,
            process,
            name,
            mem,
            cpu;
        container = container || $('#lettuceWrap');
        menu.attr('id', 'procMenu');
        menu.css({
            position: 'absolute',
            left: left,
            top: top,
            background: 'rgba(255,100,0,0.5)'
        })
        container.append(menu);
        process = getArrayEltByProp(processList, 'id', id);
        mem = process.memory;
        cpu = process.cpu;
        if(process && process.info && process.info.type === 'tab') {
            removeTabButton = $(document.createElement('button'));
            removeTabButton.attr({
                type: 'button'
            });
            removeTabButton.text('close tab');
            removeTabButton.on('click', function(evt) {
                shouldUpdate = true;
                closeTab(process.info.tabid)(evt);
            });
            menu.append(removeTabButton);
            name = process.info.title;
        } else {
            name = process.info.type;
        }
        nameDiv.text(name);
        memDiv.text(mem);
        cpuDiv.text(cpu);
        menu.append(nameDiv);
        menu.append(memDiv);
        menu.append(cpuDiv);

    }
}

/**
 * Filters list of processes to reflect current filter settings
 * @param jsonData     the list of processes to filter
 * @return             the filtered list
 */
function filterProcesses(jsonData) {
    var filter = $('#filterSelect').val().toLowerCase().replace(/ /g,''),
        ret = [],
        type,
        i;
    for(i=0;i<jsonData.length;i++) {
        // debugger;
        type = jsonData[i].info.type;
        if(filter === 'all' || (type === 'tab' &&  filter==='tabsonly') || (type !== 'tab' && filter==='notabs')){
            ret.push(jsonData[i]);
        }
    }
    return ret;
}

/**
 * Update the d3 elements
 * @param jsonData    an array of processes
 */
function displayData(jsonData) {

    if(!shouldUpdate) {
        return;
    }
    $('#cpuContainer').empty(); // Clear
    $('#memContainer').empty(); // Clear

    jsonData = filterProcesses(jsonData);
    cpus = [];
    mems = [];
    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            cpus.push(jsonData[item].cpu);
            mems.push(jsonData[item].memory);
        }
    }

    var totalCPU = 0;
    var totalMem = 0;

    for(var i=0, len=cpus.length; i<len; i++){
        totalCPU += cpus[i];  //Iterate over your first array and then grab the second element add the values up
    }
    if (totalCPU === 0) {
        return;
    }
    for(var i=0, len=mems.length; i<len; i++){
        totalMem += mems[i];  //Iterate over your first array and then grab the second element add the values up
    }
    if (totalMem === 0) {
        return;
    }

    $('#loading').empty(); // Clear

    // For the most relevant names to display on the chart
    var dummyCPUS = cpus.slice(0);
    var dummyMems = mems.slice(0);
    maxCPUVals = [];
    maxMemVals = [];

    for(var i=0;i<4;i++) {
        var maxCPUVal = Math.max.apply(Math, dummyCPUS);
        maxCPUVals.push(maxCPUVal);

        var maxMemVal = Math.max.apply(Math, dummyMems);
        maxMemVals.push(maxMemVal);

        var indexCPU = dummyCPUS.indexOf(maxCPUVal);
        var indexMem = dummyMems.indexOf(maxMemVal);

        if (indexCPU > -1) {
            dummyCPUS.splice(indexCPU, 1);
        }
        if (indexMem > -1) {
            dummyMems.splice(indexMem, 1);
        }
    }

    namesCPU = []
    namesMem = []

    for (item in jsonData) {
        if(jsonData.hasOwnProperty(item)) {
            // Determine title to display
            if (maxMemVals.indexOf(jsonData[item].memory) === -1) {
                // Not one of the bigger processes w.r.t memory, so set its title to a blank string
                namesMem.push("");
            } else {
                // one of max vals, get real name
                if (jsonData[item].info.type == "tab") {

                    if (jsonData[item].info.title.length >= 10) {
                        var url = jsonData[item].info.url
                        title = url.match(/[^w]\w+\.{1}/g)

                        if (title == null) {
                            namesMem.push(jsonData[item].info.title.slice(1,10))
                        }
                        else {
                            var matchNum = 0;
                            if (title[matchNum].match(/www/g)) {
                                matchNum += 1
                            }
                            if (title[matchNum][0].match(/\w/g)){
                                // first char is alpha, so slice from there
                                finalTitle = title[matchNum].slice(0,-1);
                                namesMem.push(finalTitle);
                            }
                            else {
                                finalTitle = title[matchNum].slice(1,-1);
                                namesMem.push(finalTitle);
                            }

                        }
                    }
                    else {
                        namesMem.push(jsonData[item].info.title);
                    }
                }
                else {
                    namesMem.push(jsonData[item].info.type);
                }
            }
            if (maxCPUVals.indexOf(jsonData[item].cpu) === -1) {
                // Not one of the bigger processes w.r.t. cpu, so set its title to a blank string
                namesCPU.push("");
                continue;
            } else {
                // one of max vals, get real name
                if (jsonData[item].info.type == "tab") {

                    if (jsonData[item].info.title.length >= 10) {
                        var url = jsonData[item].info.url
                        title = url.match(/[^w]\w+\.{1}/g)

                        if (title == null) {
                            namesCPU.push(jsonData[item].info.title.slice(1,10))
                        }
                        else {
                            var matchNum = 0;
                            if (title[matchNum].match(/www/g)) {
                                matchNum += 1
                            }
                            if (title[matchNum][0].match(/\w/g)){
                                // first char is alpha, so slice from there
                                finalTitle = title[matchNum].slice(0,-1);
                                namesCPU.push(finalTitle);
                            }
                            else {
                                finalTitle = title[matchNum].slice(1,-1);
                                namesCPU.push(finalTitle);
                            }
                        }
                    }
                    else {
                        namesCPU.push(jsonData[item].info.title);
                    }
                }
                else {
                    namesCPU.push(jsonData[item].info.type);
                }
            }
        }
    }

    // Define svg canvas
    svgCPU = d3.select("#cpuContainer").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

    // Define svg canvas
    svgMem = d3.select("#memContainer").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

    arcCPU = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    arcMem = d3.svg.arc()
        .innerRadius(radius - 50)
        .outerRadius(radius);

    pathCPU = svgCPU.datum(cpus).selectAll("path")
                          .data(vizPieCPU)
                          .attr("d", arc)

    pathMem = svgMem.datum(mems).selectAll("path")
                          .data(vizPieMem)
                          .attr("d", arc)

    // Defines arcs
    gCPU = svgCPU.selectAll(".arc")
        .data(vizPieCPU(cpus))
        .enter().append("g")
        .attr("class", "arc")
        .style("stroke-width", 4);

    gMem = svgMem.selectAll(".arc")
        .data(vizPieMem(mems))
        .enter().append("g")
        .attr("class", "arc")
        .style("stroke-width", 4);

    // Draws and colors
    gCPU.append("path")
      .attr("d", arcCPU)
      .attr("class", "dough")
      .style("fill", function(d, i) { return color(i); });

    // Draws and colors
    gMem.append("path")
      .attr("d", arcMem)
      .attr("class", "dough")
      .style("fill", function(d, i) { return color(i); });

    svgCPU.selectAll('path').each(function(d, i) {
        $(this).attr('id', jsonData[i].id)
        $(this).on('click', createProcessMenu(parseInt($(this).attr('id'), 10), jsonData));
    });

    svgMem.selectAll('path').each(function(d, i) {
        // debugger;
        $(this).attr('id', jsonData[i].id)
        $(this).on('click', createProcessMenu(parseInt($(this).attr('id'), 10), jsonData));
    });

    gCPU.append("text")
      .attr("transform", function(d) { return "translate(" + arcCPU.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .style("font-size","8px")
      .data(namesCPU)
      .text(function(d, i) {return d; });

    gMem.append("text")
      .attr("transform", function(d) { return "translate(" + arcMem.centroid(d) + ")"; })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .style("font-size","8px")
      .data(namesMem)
      .text(function(d, i) {return d; });

    gCPU.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("CPU Usage");

    gMem.append("text")
        .style("text-anchor", "middle")
        .style("font-size","24px")
        .text("Memory Usage");

   }

return {
    displayData: displayData,
    setup:  setup
};

})();
<|endoftext|>


<commit_before>jIRCs.prototype.irc_PING = function(prefix, args) {
    this.send('PONG',args);
};

jIRCs.prototype.irc_NICK = function(prefix, args) {
    var oldNick = this.getNick(prefix),
        newNick = args.pop();
    if(oldNick == this.nickname) {
        this.nickname = newNick;
    }
    this.forEach(this.channels, function(c, channel) {
        if(c.names && oldNick in c.names) {
            this.renderLine(channel, channel, oldNick + ' is now known as ' + newNick);
            c.names[newNick] = c.names[oldNick];
            delete(c.names[oldNick]);
        }
    }, this);
    this.forEach(this.displays, function(disobj) {
        this.render(disobj);
    }, this);
};

jIRCs.prototype.irc_JOIN = function(prefix, args) {
    var channel = args.pop().toLowerCase();
    if(prefix != this.nickname) {
        //this.renderLine(channel, channel, prefix + " joined " + channel);
    } else {
        this.renderLine(channel, channel, "You have joined " + channel);
    }
    if(!this.channels[channel].names) {
        this.channels[channel].names = {};
    }
    this.channels[channel].names[prefix] = "";
    if (!this.channels[channel].modes) {
        this.channels[channel].modes = {};
        this.send('MODE', [channel]); // Get the initial modes because the server doesn't send them by default
    }
    this.forEach(this.displays, function(disobj) {
        if(channel.charAt(0) == "#" && prefix == this.nickname) {
            this.activateChan(channel, disobj);
        }
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_PART = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var reason = args.pop();
    if(this.getNick(prefix) == this.nickname) {
        this.destroyChan(channel);
    } else {
        //this.renderLine(channel, channel, prefix + " left " + channel + " [" + reason + "]");
        delete(this.channels[channel].names[prefix]);
        this.forEach(this.displays, function(disobj) {
            if(disobj.viewing == channel) {
                this.render(disobj);
            }
        }, this);
    }
};

jIRCs.prototype.irc_QUIT = function(prefix, args) {
    var reason = args.pop();
    this.forEach(this.channels, function(c, channel) {
        if(channel == 'Status') {
            return;
        }
        if(c.names && prefix in c.names) {
            //this.renderLine(channel, channel, prefix + ' quit (' + reason + ')');
            delete(c.names[prefix]);
        }
    }, this);
    if(this.getNick(prefix) == this.nickname) {
        // Let ondisconnect handle cleanup
    } else {
        this.forEach(this.displays, function(disobj) {
            this.render(disobj);
        }, this);
    }
};

jIRCs.prototype.irc_PRIVMSG = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var message = args.pop();
    //account for private messages
    if (channel == this.nickname.toLowerCase()) {
        channel = prefix.toLowerCase();
    }
    if (channel.charAt(0) in this.statusSymbols) {
        prefix += ":" + channel; // give a visible indication that the message isn't for the whole channel
        channel = channel.substr(1); // trim the status char off so the message gets displayed to the correct channel
    }
    if(message.charAt(0) == '\u0001') {
        message = message.split('\u0001')[1];
        if(message.substr(0,6).toUpperCase() == 'ACTION') {
            message = prefix + message.substr(6);
            prefix = '';
            this.renderLine(channel, prefix, message);
        } else {
            args = message.split(' ');
            var method = 'ctcp_' + args.shift().toUpperCase();
            console.log("<<<<<< " + method + "('" + channel + "'," + JSON.stringify(args) + ")");
            if(method in this) {
                this[method](channel, args);
            }
        }
    } else {
        this.renderLine(channel, "<"+prefix+">", message);
    }
    if(prefix == "BidServ") {
        var cleaned = message.replace("\u0001","").replace("\u0002","").replace("\u00034","").replace("\u000F","").replace("\u0016","").replace("\u001D","").replace("\u001F","");
        var parts = cleaned.split(" ");
        console.debug(
            cleaned,
            parts,
            parts.slice(0,2).join(" "),
            parts.slice(0,3).join(" "),
            ~cleaned.indexOf("has the high bid of"),
            ~cleaned.indexOf("New highest bid is by"),
            parts.slice(0,1).join(" ") == "Auction for" && ~cleaned.indexOf("cancelled"),
            parts[0] == "Sold!"
        );
        if(parts.slice(0,2).join(" ") == "Starting Auction") {
            var id = parts[4].slice(1,-1);
            var name = parts.slice(5,-4).join(" ").slice(1,-2);
            this.auctionStart(id,name);
        } else if(parts.slice(0,3).join(" ") == "Beginning bidding at") {
            var starting = parts[3];
            this.auctionBid(starting,"Nobody");
        } else if(~cleaned.indexOf("has the high bid of")) { // ~ abuses two's complement notation to make -1 false, and everything else true
            var index = 0;
            while(index < parts.length - 5) {
                if(parts[index+1] == "has" && parts[index+2] == "the" && parts[index+3] == "high" && parts[index+4] == "bid" && parts[index+5] == "of")
                    break;
                index++;
            }
            var bidder = parts[index];
            var bid = parts[index + 6];
            this.auctionBid(bid,bidder);
        } else if(~cleaned.indexOf("New highest bid is by")) {
            parts = cleaned.substr(cleaned.indexOf("New highest bid is by")).split(" ");
            var bidder = parts[5];
            var bid = parts[7];
            this.auctionBid(bid,bidder);
        } else if(parts.slice(0,2).join(" ") == "Auction for" && ~cleaned.indexOf("cancelled")) {
            this.auctionStop();
        } else if(parts[0] == "Sold!") {
            this.auctionStop();
        }
    }
};

jIRCs.prototype.irc_NOTICE = function(prefix, args) {
    var nick = '\u2013 ' + this.getNick(prefix);
    var message = args.pop();
    var dest = args.shift().toLowerCase(); // It'll only be used if it's a channel name, anyway
    if (this.chantypes.indexOf(dest.charAt(0)) !== -1 || this.chantypes.indexOf(dest.charAt(1)) !== -1) { // There may or may not be a channel status in the parameter
        nick += ":" + dest + ' \u2013'; // Give a visible indication that the message is a channel notice
        if (dest.charAt(0) in this.statusSymbols) { // it's not going directly to all of a channel
            dest = dest.substr(1); // display it in the correct window
        }
        this.renderLine(dest, nick, message);
    } else {
        nick += ' \u2013'; // \u2013 is an en-dash
        this.forEach(this.displays, function(disobj) {
            this.renderLine(disobj.viewing, nick, message, disobj);
        }, this);
    }
    if(this.getNick(prefix) == "NickServ") {
        if(message.slice(0,33) == "You are now identified. Welcome, ") {
            this.setAccount(message.slice(33,-1));
        } else if(message.slice(0,21) == "You are now logged out") {
            this.setAccount(false);
        }
    }
};

jIRCs.prototype.irc_MODE = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var modes = args.shift().split('');
    if (channel == this.nickname.toLowerCase()) { // handle user modes here
        var adding = true;
        this.forEach(modes, function(mode) {
            switch (mode) {
                case '+':
                    adding = true;
                    break;
                case '-':
                    adding = false;
                    break;
                default:
                    if (adding) {
                        this.userModes.push(mode);
                    } else {
                        var modePos = this.userModes.indexOf(mode);
                        if (modePos != -1) {
                            this.userModes.splice(modePos, 1);
                        }
                    }
            }
        }, this);
    } else {
        // At this point, what's left in args is the parameter list
        this.parseModes(channel, modes, args); // handle the channel modes
    }
};

jIRCs.prototype.irc_CAP = function(prefix, args) {
    // :server CAP dest subcommand :capability list
    if (args[1] == "LS") {
        var supportedCaps = args[2].split(' ');
        if (supportedCaps.indexOf("multi-prefix") != -1) {
            this.send("CAP", ["REQ", ":multi-prefix"]);
        } else if (!this.registered) {
            this.send("CAP", ["END"]);
        }
    } else if (args[1] == "ACK" && !this.registered) {
        this.send("CAP", ["END"]);
    }
}

jIRCs.prototype.irc_001 = function(prefix, args) {
    this.registered = true;
}

jIRCs.prototype.irc_005 = function(prefix, args) {
    var server = args.shift();
    var message = args.pop();
    this.forEach(args, function(arg) {
        if(arg.substr(0,7).toUpperCase() == 'PREFIX=') {
            var modes = arg.substr(8).split(')'); // exclude the open paren, split close paren
            var symbols = modes[1].split('');
            var letters = modes[0].split('');
            this.statuses = this.zip(symbols.concat(letters), letters.concat(symbols));
            this.statusOrder = letters;
            this.statusSymbols = this.zip(symbols, symbols);
            this.statuses[''] = '';
            this.statusOrder.push('');
        }
        if (arg.substr(0, 10) == 'CHANMODES=') {
            var modes = arg.substr(10); // get all the channel modes
            var groups = modes.split(',');
            this.forEach(groups, function(group, groupNum) {
                this.forEach(group, function(mode) {
                    this.chanModes[mode] = groupNum; // map modes to their group index for easy lookup
                }, this);
            }, this);
        }
        if (arg.substr(0, 10) == 'CHANTYPES=') {
            this.chantypes = arg.substr(10).split('');
        }
    }, this);
};

jIRCs.prototype.irc_324 = function(prefix, args) {
    args.shift(); // discard our nick; it's not useful
    var channel = args.shift().toLowerCase();
    var modes = args.shift().split('');
    // At this point, what's left in args (if anything) is the mode parameter list
    this.channels[channel].modes = {}; // Reset the channel modes list as 324 is all of the channel's current modes
    this.parseModes(channel, modes, args);
};

jIRCs.prototype.irc_353 = function(prefix, args) {
    var channel = args[2].toLowerCase();
    if (!this.channels[channel].moreNames) {
        this.channels[channel].names = {};
        this.channels[channel].moreNames = true;
    }
    var names = args[3].split(' '); // Strip the colon and split the names out
    this.forEach(names, function(name) {
        var statusList = '';
        while (name.charAt(0) in this.statusSymbols) {
            statusList += name.charAt(0);
            name = name.substr(1);
        }
        this.channels[channel].names[name] = statusList;
    }, this);
};

jIRCs.prototype.irc_366 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    this.channels[channel].moreNames = false;
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_332 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.message = args[2];
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_333 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.creator = args[2];
    this.channels[channel].topic.time = new Date(args[3] * 1000);
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_TOPIC = function(prefix, args) {
    var channel = args[0].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.creator = prefix;
    this.channels[channel].topic.time = new Date();
    this.channels[channel].topic.message = args[1];
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_433 = function(prefix, args) {
    this.nickname += "_";
    this.send('NICK',[this.nickname]);
};

jIRCs.prototype.irc_unknown = function(prefix, args) {
    this.renderLine("Status", prefix, args.join(" "));
};
<commit_msg>fix the slicing. Again<commit_after>jIRCs.prototype.irc_PING = function(prefix, args) {
    this.send('PONG',args);
};

jIRCs.prototype.irc_NICK = function(prefix, args) {
    var oldNick = this.getNick(prefix),
        newNick = args.pop();
    if(oldNick == this.nickname) {
        this.nickname = newNick;
    }
    this.forEach(this.channels, function(c, channel) {
        if(c.names && oldNick in c.names) {
            this.renderLine(channel, channel, oldNick + ' is now known as ' + newNick);
            c.names[newNick] = c.names[oldNick];
            delete(c.names[oldNick]);
        }
    }, this);
    this.forEach(this.displays, function(disobj) {
        this.render(disobj);
    }, this);
};

jIRCs.prototype.irc_JOIN = function(prefix, args) {
    var channel = args.pop().toLowerCase();
    if(prefix != this.nickname) {
        //this.renderLine(channel, channel, prefix + " joined " + channel);
    } else {
        this.renderLine(channel, channel, "You have joined " + channel);
    }
    if(!this.channels[channel].names) {
        this.channels[channel].names = {};
    }
    this.channels[channel].names[prefix] = "";
    if (!this.channels[channel].modes) {
        this.channels[channel].modes = {};
        this.send('MODE', [channel]); // Get the initial modes because the server doesn't send them by default
    }
    this.forEach(this.displays, function(disobj) {
        if(channel.charAt(0) == "#" && prefix == this.nickname) {
            this.activateChan(channel, disobj);
        }
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_PART = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var reason = args.pop();
    if(this.getNick(prefix) == this.nickname) {
        this.destroyChan(channel);
    } else {
        //this.renderLine(channel, channel, prefix + " left " + channel + " [" + reason + "]");
        delete(this.channels[channel].names[prefix]);
        this.forEach(this.displays, function(disobj) {
            if(disobj.viewing == channel) {
                this.render(disobj);
            }
        }, this);
    }
};

jIRCs.prototype.irc_QUIT = function(prefix, args) {
    var reason = args.pop();
    this.forEach(this.channels, function(c, channel) {
        if(channel == 'Status') {
            return;
        }
        if(c.names && prefix in c.names) {
            //this.renderLine(channel, channel, prefix + ' quit (' + reason + ')');
            delete(c.names[prefix]);
        }
    }, this);
    if(this.getNick(prefix) == this.nickname) {
        // Let ondisconnect handle cleanup
    } else {
        this.forEach(this.displays, function(disobj) {
            this.render(disobj);
        }, this);
    }
};

jIRCs.prototype.irc_PRIVMSG = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var message = args.pop();
    //account for private messages
    if (channel == this.nickname.toLowerCase()) {
        channel = prefix.toLowerCase();
    }
    if (channel.charAt(0) in this.statusSymbols) {
        prefix += ":" + channel; // give a visible indication that the message isn't for the whole channel
        channel = channel.substr(1); // trim the status char off so the message gets displayed to the correct channel
    }
    if(message.charAt(0) == '\u0001') {
        message = message.split('\u0001')[1];
        if(message.substr(0,6).toUpperCase() == 'ACTION') {
            message = prefix + message.substr(6);
            prefix = '';
            this.renderLine(channel, prefix, message);
        } else {
            args = message.split(' ');
            var method = 'ctcp_' + args.shift().toUpperCase();
            console.log("<<<<<< " + method + "('" + channel + "'," + JSON.stringify(args) + ")");
            if(method in this) {
                this[method](channel, args);
            }
        }
    } else {
        this.renderLine(channel, "<"+prefix+">", message);
    }
    if(prefix == "BidServ") {
        var cleaned = message.replace("\u0001","").replace("\u0002","").replace("\u00034","").replace("\u000F","").replace("\u0016","").replace("\u001D","").replace("\u001F","");
        var parts = cleaned.split(" ");
        console.debug(
            cleaned,
            parts,
            parts.slice(0,2).join(" "),
            parts.slice(0,3).join(" "),
            ~cleaned.indexOf("has the high bid of"),
            ~cleaned.indexOf("New highest bid is by"),
            parts.slice(0,1).join(" ") == "Auction for" && ~cleaned.indexOf("cancelled"),
            parts[0] == "Sold!"
        );
        if(parts.slice(0,2).join(" ") == "Starting Auction") {
            var id = parts[4].slice(1,-1);
            var name = parts.slice(5,-4).join(" ").slice(1,-2);
            this.auctionStart(id,name);
        } else if(parts.slice(0,3).join(" ") == "Beginning bidding at") {
            var starting = parts[3];
            this.auctionBid(starting,"Nobody");
        } else if(~cleaned.indexOf("has the high bid of")) { // ~ abuses two's complement notation to make -1 false, and everything else true
            var index = 0;
            while(index < parts.length - 5) {
                if(parts[index+1] == "has" && parts[index+2] == "the" && parts[index+3] == "high" && parts[index+4] == "bid" && parts[index+5] == "of")
                    break;
                index++;
            }
            var bidder = parts[index];
            var bid = parts[index + 6];
            this.auctionBid(bid,bidder);
        } else if(~cleaned.indexOf("New highest bid is by")) {
            parts = cleaned.substr(cleaned.indexOf("New highest bid is by")).split(" ");
            var bidder = parts[5];
            var bid = parts[7];
            this.auctionBid(bid,bidder);
        } else if(parts.slice(0,2).join(" ") == "Auction for" && ~cleaned.indexOf("cancelled")) {
            this.auctionStop();
        } else if(parts[0] == "Sold!") {
            this.auctionStop();
        }
    }
};

jIRCs.prototype.irc_NOTICE = function(prefix, args) {
    var nick = '\u2013 ' + this.getNick(prefix);
    var message = args.pop();
    var dest = args.shift().toLowerCase(); // It'll only be used if it's a channel name, anyway
    if (this.chantypes.indexOf(dest.charAt(0)) !== -1 || this.chantypes.indexOf(dest.charAt(1)) !== -1) { // There may or may not be a channel status in the parameter
        nick += ":" + dest + ' \u2013'; // Give a visible indication that the message is a channel notice
        if (dest.charAt(0) in this.statusSymbols) { // it's not going directly to all of a channel
            dest = dest.substr(1); // display it in the correct window
        }
        this.renderLine(dest, nick, message);
    } else {
        nick += ' \u2013'; // \u2013 is an en-dash
        this.forEach(this.displays, function(disobj) {
            this.renderLine(disobj.viewing, nick, message, disobj);
        }, this);
    }
    if(this.getNick(prefix) == "NickServ") {
        if(message.slice(0,33) == "You are now identified. Welcome, ") {
            this.setAccount(message.slice(33,-1));
        } else if(message.slice(0,22) == "You are now logged out") {
            this.setAccount(false);
        }
    }
};

jIRCs.prototype.irc_MODE = function(prefix, args) {
    var channel = args.shift().toLowerCase();
    var modes = args.shift().split('');
    if (channel == this.nickname.toLowerCase()) { // handle user modes here
        var adding = true;
        this.forEach(modes, function(mode) {
            switch (mode) {
                case '+':
                    adding = true;
                    break;
                case '-':
                    adding = false;
                    break;
                default:
                    if (adding) {
                        this.userModes.push(mode);
                    } else {
                        var modePos = this.userModes.indexOf(mode);
                        if (modePos != -1) {
                            this.userModes.splice(modePos, 1);
                        }
                    }
            }
        }, this);
    } else {
        // At this point, what's left in args is the parameter list
        this.parseModes(channel, modes, args); // handle the channel modes
    }
};

jIRCs.prototype.irc_CAP = function(prefix, args) {
    // :server CAP dest subcommand :capability list
    if (args[1] == "LS") {
        var supportedCaps = args[2].split(' ');
        if (supportedCaps.indexOf("multi-prefix") != -1) {
            this.send("CAP", ["REQ", ":multi-prefix"]);
        } else if (!this.registered) {
            this.send("CAP", ["END"]);
        }
    } else if (args[1] == "ACK" && !this.registered) {
        this.send("CAP", ["END"]);
    }
}

jIRCs.prototype.irc_001 = function(prefix, args) {
    this.registered = true;
}

jIRCs.prototype.irc_005 = function(prefix, args) {
    var server = args.shift();
    var message = args.pop();
    this.forEach(args, function(arg) {
        if(arg.substr(0,7).toUpperCase() == 'PREFIX=') {
            var modes = arg.substr(8).split(')'); // exclude the open paren, split close paren
            var symbols = modes[1].split('');
            var letters = modes[0].split('');
            this.statuses = this.zip(symbols.concat(letters), letters.concat(symbols));
            this.statusOrder = letters;
            this.statusSymbols = this.zip(symbols, symbols);
            this.statuses[''] = '';
            this.statusOrder.push('');
        }
        if (arg.substr(0, 10) == 'CHANMODES=') {
            var modes = arg.substr(10); // get all the channel modes
            var groups = modes.split(',');
            this.forEach(groups, function(group, groupNum) {
                this.forEach(group, function(mode) {
                    this.chanModes[mode] = groupNum; // map modes to their group index for easy lookup
                }, this);
            }, this);
        }
        if (arg.substr(0, 10) == 'CHANTYPES=') {
            this.chantypes = arg.substr(10).split('');
        }
    }, this);
};

jIRCs.prototype.irc_324 = function(prefix, args) {
    args.shift(); // discard our nick; it's not useful
    var channel = args.shift().toLowerCase();
    var modes = args.shift().split('');
    // At this point, what's left in args (if anything) is the mode parameter list
    this.channels[channel].modes = {}; // Reset the channel modes list as 324 is all of the channel's current modes
    this.parseModes(channel, modes, args);
};

jIRCs.prototype.irc_353 = function(prefix, args) {
    var channel = args[2].toLowerCase();
    if (!this.channels[channel].moreNames) {
        this.channels[channel].names = {};
        this.channels[channel].moreNames = true;
    }
    var names = args[3].split(' '); // Strip the colon and split the names out
    this.forEach(names, function(name) {
        var statusList = '';
        while (name.charAt(0) in this.statusSymbols) {
            statusList += name.charAt(0);
            name = name.substr(1);
        }
        this.channels[channel].names[name] = statusList;
    }, this);
};

jIRCs.prototype.irc_366 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    this.channels[channel].moreNames = false;
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_332 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.message = args[2];
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_333 = function(prefix, args) {
    var channel = args[1].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.creator = args[2];
    this.channels[channel].topic.time = new Date(args[3] * 1000);
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_TOPIC = function(prefix, args) {
    var channel = args[0].toLowerCase();
    if(!this.channels[channel].topic) {
        this.channels[channel].topic = {};
    }
    this.channels[channel].topic.creator = prefix;
    this.channels[channel].topic.time = new Date();
    this.channels[channel].topic.message = args[1];
    this.forEach(this.displays, function(disobj) {
        if(disobj.viewing == channel) {
            this.render(disobj);
        }
    }, this);
};

jIRCs.prototype.irc_433 = function(prefix, args) {
    this.nickname += "_";
    this.send('NICK',[this.nickname]);
};

jIRCs.prototype.irc_unknown = function(prefix, args) {
    this.renderLine("Status", prefix, args.join(" "));
};
<|endoftext|>


<commit_before>const util = require('util')
const AWS = require('aws-sdk')

const switches = [0, 1, 2, 3]
const buildQueryParams = (devID) => ({
  TableName: 'devices',
  Key: {
    device_name: devID
  }
})

const buildMessagesParams = (devID, payload) => {
    let fields = payload['payload_fields']
    let newItem = {
        message_id: `${devID}-${Date.now()}`,
        device_name: devID,
        counter: payload['counter'],
        status: fields['status'],
        battery: fields['battery'],
        battery_percentage: fields['battery_percentage']
    };

    for (let i of switches) {
        let key = 'switch' + i
        let value = fields[key]
        newItem[key] = value
    }

    return [{ PutRequest: { Item: newItem } }]
}

const buildNewDeviceParams = (devID, payload) => {
    let fields = payload['payload_fields']
    let newItem = {
        device_name: devID,
        first_seen: Date.now(),
        first_battery_value: fields['battery'],
        hardware_serial: payload['hardware_serial']
    }

    for (let i of switches) {
        let key = 'switch' + i
        let keyLast = 'last_switch' + i
        let value = fields[key]

        newItem[key] = value
        newItem[keyLast] = value
    }

    return [{ PutRequest: { Item: newItem } }]
}

const buildUpdateDeviceParams = (devID, payload, existingItem) => {
    let fields = payload['payload_fields']

    for (let i of switches) {
        let key = 'switch' + i
        let keyLast = 'last_switch' + i
        let value = fields[key]

        // status=1 means first transmission since power up
        // If status=0 and there's a previous key, we have two possibilities
        if (fields['status'] == 0 && keyLast in existingItem) {
            if (value > existingItem[keyLast]) {
                // The value is greater than the last one, so, we need to add
                // the difference between last and current
                existingItem[key] += (value - existingItem[keyLast])
            } else if (value < existingItem[keyLast]) {
                // Or the value is smaller than the last one, because the
                // counter rolled over 255. We need to add 255-last + current.
                existingItem[key] += (255 - existingItem[keyLast] + value)
            }
        } else {
            existingItem[key] += value
        }

        // Then store the unmodified payload value as `last seen`
        existingItem[keyLast] = fields[key]
    }

    return [{
        PutRequest: {
            Item: existingItem
        }
    }]
}

const store = async(devID, payload) => {
    // Only store port 1 messages
    if (payload['port'] !== 1) {
        return;
    }

    let documentClient = new AWS.DynamoDB.DocumentClient({
        region: process.env.AWS_REGION
    });

    try {
        let data = await documentClient.get(buildQueryParams(devID)).promise()
        let writeParams = {
            'RequestItems': {
                'messages': buildMessagesParams(devID, payload)
            }
        }

        if (data && data['Item']) {
            console.log(`Updating values of device ${devID}`)
            writeParams['RequestItems']['devices'] = buildUpdateDeviceParams(devID, payload, data['Item'])
        } else {
            console.log(`Recording device ${devID} for the first time`)
            writeParams['RequestItems']['devices'] = buildNewDeviceParams(devID, payload)
        }

        let result = await documentClient.batchWrite(writeParams).promise()
        console.log(`Storage operation completed.`)
        console.log(result);
    } catch (err) {
        console.error(err)
    }
}

module.exports = {
    store
}
<commit_msg>Modify database structure and fix linter issues<commit_after>const util = require('util')
const AWS = require('aws-sdk')

const switches = [0, 1, 2, 3]
const defaultSwitchKey = 'switch%d'
const lastSwitchKey = 'last_switch_%d'
const cumulativeSwitchKey = 'cumulative_switch_%d'

const copySwitchValues = (source, target, {sourceKeyFormat = defaultSwitchKey, targetKeyFormat = defaultSwitchKey} = {}) => {
  for (let i of switches) {
    let keySource = util.format(sourceKeyFormat, i)
    let keyTarget = util.format(targetKeyFormat, i)

    target[keyTarget] = source[keySource]
  }
}

const buildQueryParams = (devID) => ({
  TableName: 'devices',
  Key: {
    device_name: devID
  }
})

const buildMessagesParams = (devID, payload) => {
  let fields = payload['payload_fields']
  let newItem = {
    device_name: devID,
    datetime: new Date().toISOString(),
    counter: payload['counter'],
    status: fields['status'],
    battery: fields['battery'],
    battery_percentage: fields['battery_percentage']
  }

  copySwitchValues(fields, newItem)
  copySwitchValues(fields, newItem, { sourceKeyFormat: cumulativeSwitchKey, targetKeyFormat: cumulativeSwitchKey })

  return [{ PutRequest: { Item: newItem } }]
}

const buildNewDeviceParams = (devID, payload) => {
  let fields = payload['payload_fields']
  let newItem = {
    device_name: devID,
    first_seen: new Date().toISOString(),
    last_seen: new Date().toISOString(),
    first_battery_value: fields['battery'],
    hardware_serial: payload['hardware_serial']
  }

  copySwitchValues(fields, newItem)
  copySwitchValues(fields, newItem, { targetKeyFormat: lastSwitchKey })

  return [{ PutRequest: { Item: newItem } }]
}

const buildUpdateDeviceParams = (devID, payload, existingItem) => {
  let fields = payload['payload_fields']

  existingItem['last_seen'] = new Date().toISOString()

  for (let i of switches) {
    let key = util.format(defaultSwitchKey, i)
    let keyLast = util.format(lastSwitchKey, i)
    let cumulativeKey = util.format(cumulativeSwitchKey, i)
    let value = fields[key]

    existingItem[key] += value
    existingItem[keyLast] = fields[cumulativeKey]
  }

  return [{
    PutRequest: {
      Item: existingItem
    }
  }]
}

const calculateAggregates = function (devID, payload, existingItem) {
  let fields = payload['payload_fields']

  // First copy all switch values to cumulative fields
  copySwitchValues(fields, fields, { targetKeyFormat: cumulativeSwitchKey })

  // And now update switch fields to contain non-aggregated values
  if (existingItem) {
    for (let i of switches) {
      let key = util.format(defaultSwitchKey, i)
      let keyLast = util.format(lastSwitchKey, i)
      let value = fields[key]

      // Status=1 means first transmission since power up, we move to next
      if (fields['status'] === 1) continue
      console.log(`Updating ${key} from previous ${existingItem[keyLast]} using transmitted value ${value}...`)

      // If status=0 and there's a previous key, we have two possibilities
      if (value >= existingItem[keyLast]) {
        // The value is greater (or equals) than the last one, so
        // the non-aggregated count is the difference between current and last
        fields[key] = value - existingItem[keyLast]
        console.log(`...by adding the diff: ${fields[key]}`)
      } else if (value < existingItem[keyLast]) {
        // If the value is smaller than the last one, because the
        // counter rolled over 255. We need to add 256 - last + current
        fields[key] = (256 - existingItem[keyLast] + value)
        console.log(`...after rollover to: ${fields[key]}`)
      }
    }
  }
}

const store = async (devID, payload) => {
  // Only store port 1 messages
  if (payload['port'] !== 1) {
    return
  }

  let documentClient = new AWS.DynamoDB.DocumentClient({
    region: process.env.AWS_REGION
  })

  try {
    let data = await documentClient.get(buildQueryParams(devID)).promise()
    let existingItem = data ? data['Item'] : null
    calculateAggregates(devID, payload, existingItem)

    let writeParams = {
      'RequestItems': {
        'messages': buildMessagesParams(devID, payload)
      }
    }

    if (existingItem) {
      console.log(`Updating values of device ${devID}`)
      writeParams['RequestItems']['devices'] = buildUpdateDeviceParams(devID, payload, existingItem)
    } else {
      console.log(`Recording device ${devID} for the first time`)
      writeParams['RequestItems']['devices'] = buildNewDeviceParams(devID, payload)
    }

    let result = await documentClient.batchWrite(writeParams).promise()
    console.log(`Storage operation completed.`)
    console.log(result)
  } catch (err) {
    console.error(err)
  }
}

module.exports = {
  store
}
<|endoftext|>