<commit_before>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2014 Olivier Biot, Jason Oster, Aaron McLeod
 * http://www.melonjs.org
 *
 * a simple debug panel plugin
 * usage : me.plugin.register(debugPanel, "debug");
 *
 * you can then use me.plugin.debug.show() or me.plugin.debug.hide()
 * to show or hide the panel, or press respectively the "S" and "H" keys.
 *
 * note :
 * Heap Memory information is available under Chrome when using
 * the "--enable-memory-info" parameter to launch Chrome
 */

(function($) {

    // ensure that me.debug is defined
    me.debug = me.debug || {};

    var DEBUG_HEIGHT = 70;

    /**
     * @class
     * @public
     * @extends me.plugin.Base
     * @memberOf me
     * @constructor
     */
    debugPanel = me.plugin.Base.extend(
    /** @scope me.debug.Panel.prototype */
    {

        /** @private */
        init : function(showKey, hideKey) {
            // call the super constructor
            this._super(me.plugin.Base, 'init');

            // minimum melonJS version expected
            this.version = "1.1.0";

            // to hold the debug options
            // clickable rect area
            this.area = {};

            // panel position and size
            this.rect = null;

            // for z ordering
            // make it ridiculously high
            this.z = Infinity;

            // visibility flag
            this.visible = false;

            // frame update time in ms
            this.frameUpdateTime = 0;

            // frame draw time in ms
            this.frameDrawTime = 0;

            this.rect = new me.Rect(0, 0, me.video.renderer.getWidth(), DEBUG_HEIGHT);

            // set the object GUID value
            this.GUID = "debug-" + me.utils.createGUID();

            // set the object entity name
            this.name = "me.debugPanel";

            // persistent
            this.isPersistent = true;

            // a floating object
            this.floating = true;

            // renderable
            this.isRenderable = true;

            // always update, even when not visible
            this.alwaysUpdate = true;
            var screenCanvas = me.video.renderer.getScreenCanvas();
            this.canvas = me.video.createCanvas(screenCanvas.width, DEBUG_HEIGHT, true);

            screenCanvas.parentNode.appendChild(this.canvas);
            this.canvas.style.position = 'relative';
            this.context = me.CanvasRenderer.getContext2d(this.canvas);

            // create a default font, with fixed char width
            var s = 20;
            this.mod = 1;
            if(me.game.viewport.width < 500) {
                s = 15;
                this.mod = 0.7;
            }
            this.font = new me.Font('courier', s, 'white');

            // clickable areas
            this.area.renderHitBox = new me.Rect(160,5,15,15);
            this.area.renderVelocity = new me.Rect(165,18,15,15);

            this.area.renderQuadTree = new me.Rect(270,5,15,15);
            this.area.renderCollisionMap = new me.Rect(270,18,15,15);

            // some internal string/length
            this.help_str      = "(s)how/(h)ide";
            this.help_str_len = this.font.measureText(me.video.renderer.getSystemContext(), this.help_str).width;
            this.fps_str_len = this.font.measureText(me.video.renderer.getSystemContext(), "00/00 fps").width;
            this.memoryPositionX = this.font.measureText(me.video.renderer.getSystemContext(), "Draw   : ").width * 2.2 + 610 * this.mod;

            // enable the FPS counter
            me.debug.displayFPS = true;

            // bind the "S" and "H" keys
            me.input.bindKey(showKey || me.input.KEY.S, "show", false, false);
            me.input.bindKey(hideKey || me.input.KEY.H, "hide", false, false);

            // add some keyboard shortcuts
            var self = this;
            this.keyHandler = me.event.subscribe(me.event.KEYDOWN, function (action, keyCode, edge) {
                if (action === "show") {
                    self.show();
                } else if (action === "hide") {
                    self.hide();
                }
            });

            // re-apply panel settings on level changes
            this.levelHandler = me.event.subscribe(me.event.LEVEL_LOADED, function () {
                var layer = me.game.currentLevel.getLayerByName("collision");
                if (layer) {
                    layer.setOpacity((me.debug.renderCollisionMap===true)?1:0);
                }
            });

            // memory heap sample points
            this.samples = [];

            //patch patch patch !
            this.patchSystemFn();
            me.video.onresize(null);
            // make it visible
            this.show();
        },

        /**
         * patch system fn to draw debug information
         */
        patchSystemFn : function() {

            // add a few new debug flag (if not yet defined)
            me.debug.renderHitBox = me.debug.renderHitBox || false;
            me.debug.renderVelocity = me.debug.renderVelocity || false;
            me.debug.renderCollisionMap = me.debug.renderCollisionMap || false;
            me.debug.renderQuadTree = me.debug.renderQuadTree || false;

            var _this = this;

            // patch timer.js
            me.plugin.patch(me.timer, "update", function (time) {
                // call the original me.timer.update function
                this._patched(time);

                // call the FPS counter
                me.timer.countFPS();
            });

            // patch me.game.update
            me.plugin.patch(me.game, 'update', function(time) {
                var frameUpdateStartTime = window.performance.now();

                this._patched(time);

                // calculate the update time
                _this.frameUpdateTime = window.performance.now() - frameUpdateStartTime;
            });

            // patch me.game.draw
            me.plugin.patch(me.game, 'draw', function() {
                var frameDrawStartTime = window.performance.now();

                this._patched();

                // calculate the drawing time
                _this.frameDrawTime = window.performance.now() - frameDrawStartTime;
            });

            // patch sprite.js
            me.plugin.patch(me.Sprite, "draw", function (renderer) {
                // call the original me.Sprite function
                this._patched(renderer);

                // draw the sprite rectangle
                if (me.debug.renderHitBox) {
                    renderer.strokeRect(this.left, this.top, this.width, this.height, "green");
                }
            });

            // patch entities.js
            me.plugin.patch(me.Entity, "draw", function (renderer) {
                // call the original me.game.draw function
                this._patched(renderer);

                // check if debug mode is enabled

                if (me.debug.renderHitBox) {
                    renderer.save();
                    // draw the bounding rect shape
                    this.body.getBounds().draw(renderer, "orange");
                    renderer.translate(this.pos.x, this.pos.y);
                    if (this.body.shapes.length) {
                        // TODO : support multiple shapes
                        this.body.shapes[0].draw(renderer, "red");
                    }
                    renderer.restore();
                }

                if (me.debug.renderVelocity) {
                    // draw entity current velocity
                    var x = ~~(this.pos.x + this.hWidth);
                    var y = ~~(this.pos.y + this.hHeight);
                    // TODO: This will also be tricky for WebGL.
                    var context = renderer.getContext();
                    context.strokeStyle = "blue";
                    context.lineWidth = 1;
                    context.beginPath();
                    context.moveTo(x, y);
                    context.lineTo(
                        x + ~~(this.body.vel.x * this.hWidth),
                        y + ~~(this.body.vel.y * this.hHeight)
                    );
                    context.stroke();
                }
            });

            // resize event to resize our canvas
            me.plugin.patch(me.video, "updateDisplaySize", function (scaleX, scaleY) {
                this._patched(scaleX, scaleY);

                var canvas = me.video.renderer.getScreenCanvas();
                _this.canvas.width = canvas.width;
                _this.canvas.height = DEBUG_HEIGHT;
                _this.canvas.style.top = (-parseInt(canvas.style.height)) + "px";
                _this.canvas.style.width = canvas.style.width;
                _this.canvas.style.height = DEBUG_HEIGHT * scaleY;
                _this.rect.resize(canvas.width, DEBUG_HEIGHT * scaleY);
            });
        },

        /**
         * show the debug panel
         */
        show : function() {
            if (!this.visible) {
                // register a mouse event for the checkboxes
                me.input.registerPointerEvent('pointerdown', this.rect, this.onClick.bind(this), true);
                // add the debug panel to the game world
                me.game.world.addChild(this, Infinity);
                // mark it as visible
                this.visible = true;
            }
        },

        /**
         * hide the debug panel
         */
        hide : function() {
            if (this.visible) {
                // release the mouse event for the checkboxes
                me.input.releasePointerEvent('pointerdown', this.rect);
                // remove the debug panel from the game world
                me.game.world.removeChild(this);
                // mark it as invisible
                this.visible = false;
            }
        },

        /** @private */
        update : function() {
            if (me.input.isKeyPressed('show')) {
                this.show();
            }
            else if (me.input.isKeyPressed('hide')) {
                this.hide();
            }
            return true;
        },

        /**
         * @private
         */
        getBounds : function() {
            return this.rect;
        },

        /** @private */
        onClick : function(e)  {
            // check the clickable areas
            if (this.area.renderHitBox.containsPoint(e.gameX, e.gameY)) {
                me.debug.renderHitBox = !me.debug.renderHitBox;
            }
            else if (this.area.renderCollisionMap.containsPoint(e.gameX, e.gameY)) {
                var layer = me.game.currentLevel.getLayerByName("collision");
                if (layer) {
                    if (layer.getOpacity() === 0) {
                        layer.setOpacity(1);
                        me.debug.renderCollisionMap = true;
                    } else {
                        layer.setOpacity(0);
                        me.debug.renderCollisionMap = false;
                    }
                }
            }
            else if (this.area.renderVelocity.containsPoint(e.gameX, e.gameY)) {
                // does nothing for now, since velocity is
                // rendered together with hitboxes (is a global debug flag required?)
                me.debug.renderVelocity = !me.debug.renderVelocity;
            }
            else if (this.area.renderQuadTree.containsPoint(e.gameX, e.gameY)) {
                me.debug.renderQuadTree = !me.debug.renderQuadTree;
            }
            // force repaint
            me.game.repaint();
        },

        /** @private */
        drawQuadTreeNode : function (node) {
            var bounds = node._bounds;

            // Opacity is based on number of objects in the cell
            renderer.setGlobalAlpha((node.children.length / 16).clamp(0, 0.9));
            renderer.fillRect(Math.abs(bounds.pos.x) + 0.5,
                Math.abs(bounds.pos.y) + 0.5,
                bounds.width,
                bounds.height,
                "red"
            );

            var len = node.nodes.length;

            for(var i = 0; i < len; i++) {
                this.drawQuadTreeNode(renderer, node.nodes[i]);
            }
        },

        /** @private */
        drawQuadTree : function () {
            // save the current globalAlpha value
            var _alpha = this.context.globalAlpha;

            this.context.translate(-me.game.viewport.pos.x, -me.game.viewport.pos.y);

            this.drawQuadTreeNode(me.collision.quadTree.root);

            this.context.translate(me.game.viewport.pos.x, me.game.viewport.pos.y);

            this.context.globalAlpha = _alpha;
        },

        /** @private */
        drawMemoryGraph : function (context, endX) {
            if (window.performance && window.performance.memory) {
                var usedHeap  = Number.prototype.round(window.performance.memory.usedJSHeapSize/1048576, 2);
                var totalHeap =  Number.prototype.round(window.performance.memory.totalJSHeapSize/1048576, 2);
                var len = endX - this.memoryPositionX;

                // remove the first item
                this.samples.shift();
                // add a new sample (25 is the height of the graph)
                this.samples[len] = (usedHeap / totalHeap)  * 25;

                // draw the graph
                for (var x = len; x >= 0; x--) {
                    var where = endX - (len - x);
                    context.beginPath();
                    context.strokeStyle = "lightblue";
                    context.moveTo(where, 30 * this.mod);
                    context.lineTo(where, (30 - (this.samples[x] || 0)) * this.mod);
                    context.stroke();
                }
                // display the current value
                this.font.drawFromContext(context, "Heap : " + usedHeap + '/' + totalHeap + ' MB', this.memoryPositionX, 5 * this.mod);
            } else {
                // Heap Memory information not available
                this.font.drawFromContext(context, "Heap : ??/?? MB", this.memoryPositionX, 5 * this.mod);
            }
        },

        /** @private */
        draw : function(renderer) {
            this.context.save();

            // draw the QuadTree (before the panel)
            if (me.debug.renderQuadTree === true) {
                this.drawQuadTree();
            }

            // draw the panel
            this.context.globalAlpha = 0.5;
            this.context.fillRect(this.rect.left,  this.rect.top,
                             this.rect.width, this.rect.height, "black");
            this.context.globalAlpha = 1.0;

            // # entities / draw
            this.font.drawFromContext(this.context, "#objects : " + me.game.world.children.length, 5 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "#draws   : " + me.game.world.drawCount, 5 * this.mod, 30 * this.mod);

            // debug checkboxes
            this.font.drawFromContext(this.context, "?hitbox   ["+ (me.debug.renderHitBox?"x":" ") +"]",     170 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "?velocity ["+ (me.debug.renderVelocity?"x":" ") +"]",     170 * this.mod, 30 * this.mod);

            this.font.drawFromContext(this.context, "?QuadTree   ["+ (me.debug.renderQuadTree?"x":" ") +"]",    350 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "?col. layer ["+ (me.debug.renderCollisionMap?"x":" ") +"]", 350 * this.mod, 30 * this.mod);

            // draw the update duration
            this.font.drawFromContext(this.context, "Update : " + this.frameUpdateTime.toFixed(2) + " ms", 570 * this.mod, 5 * this.mod);
            // draw the draw duration
            this.font.drawFromContext(this.context, "Draw   : " + (this.frameDrawTime).toFixed(2) + " ms", 570 * this.mod, 30 * this.mod);

            // draw the memory heap usage
            var endX = this.rect.width - 25;
            this.drawMemoryGraph(this.context, endX - this.help_str_len);

            // some help string
            this.font.drawFromContext(this.context, this.help_str, endX - this.help_str_len, 30 * this.mod);

            //fps counter
            var fps_str = "" + me.timer.fps + "/"    + me.sys.fps + " fps";
            this.font.drawFromContext(this.context, fps_str, this.rect.width - this.fps_str_len - 5, 5 * this.mod);

            this.context.restore();

        },

        /** @private */
        onDestroyEvent : function() {
            // hide the panel
            this.hide();
            // unbind keys event
            me.input.unbindKey(me.input.KEY.S);
            me.input.unbindKey(me.input.KEY.H);
            me.event.unsubscribe(this.keyHandler);
            me.event.unsubscribe(this.levelHandler);
        }

    });

    /*---------------------------------------------------------*/
    // END END END
    /*---------------------------------------------------------*/
})(window);
<commit_msg>using pixel density to calculate size drawing. Need to test with high dpi screen.<commit_after>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2014 Olivier Biot, Jason Oster, Aaron McLeod
 * http://www.melonjs.org
 *
 * a simple debug panel plugin
 * usage : me.plugin.register(debugPanel, "debug");
 *
 * you can then use me.plugin.debug.show() or me.plugin.debug.hide()
 * to show or hide the panel, or press respectively the "S" and "H" keys.
 *
 * note :
 * Heap Memory information is available under Chrome when using
 * the "--enable-memory-info" parameter to launch Chrome
 */

(function($) {

    // ensure that me.debug is defined
    me.debug = me.debug || {};

    var DEBUG_HEIGHT = 70;

    /**
     * @class
     * @public
     * @extends me.plugin.Base
     * @memberOf me
     * @constructor
     */
    debugPanel = me.plugin.Base.extend(
    /** @scope me.debug.Panel.prototype */
    {

        /** @private */
        init : function(showKey, hideKey) {
            // call the super constructor
            this._super(me.plugin.Base, 'init');

            // minimum melonJS version expected
            this.version = "1.1.0";

            // to hold the debug options
            // clickable rect area
            this.area = {};

            // panel position and size
            this.rect = null;

            // for z ordering
            // make it ridiculously high
            this.z = Infinity;

            // visibility flag
            this.visible = false;

            // frame update time in ms
            this.frameUpdateTime = 0;

            // frame draw time in ms
            this.frameDrawTime = 0;

            this.rect = new me.Rect(0, 0, me.video.renderer.getWidth(), DEBUG_HEIGHT);

            // set the object GUID value
            this.GUID = "debug-" + me.utils.createGUID();

            // set the object entity name
            this.name = "me.debugPanel";

            // persistent
            this.isPersistent = true;

            // a floating object
            this.floating = true;

            // renderable
            this.isRenderable = true;

            // always update, even when not visible
            this.alwaysUpdate = true;
            var screenCanvas = me.video.renderer.getScreenCanvas();
            this.canvas = me.video.createCanvas(screenCanvas.width, DEBUG_HEIGHT, true);

            screenCanvas.parentNode.appendChild(this.canvas);
            this.canvas.style.position = 'relative';
            this.context = me.CanvasRenderer.getContext2d(this.canvas);

            // create a default font, with fixed char width
            var s = 10;
            this.mod = 1;
            if(me.game.viewport.width < 500) {
                s = 7;
                this.mod = 0.7;
            }
            s *= me.device.getPixelRatio();
            this.mod *= me.device.getPixelRatio();
            this.font = new me.Font('courier', s, 'white');

            // clickable areas
            this.area.renderHitBox = new me.Rect(160,5,15,15);
            this.area.renderVelocity = new me.Rect(165,18,15,15);

            this.area.renderQuadTree = new me.Rect(270,5,15,15);
            this.area.renderCollisionMap = new me.Rect(270,18,15,15);

            // some internal string/length
            this.help_str      = "(s)how/(h)ide";
            this.help_str_len = this.font.measureText(me.video.renderer.getSystemContext(), this.help_str).width;
            this.fps_str_len = this.font.measureText(me.video.renderer.getSystemContext(), "00/00 fps").width;
            this.memoryPositionX = this.font.measureText(me.video.renderer.getSystemContext(), "Draw   : ").width * 2.2 + 300 * this.mod;

            // enable the FPS counter
            me.debug.displayFPS = true;

            // bind the "S" and "H" keys
            me.input.bindKey(showKey || me.input.KEY.S, "show", false, false);
            me.input.bindKey(hideKey || me.input.KEY.H, "hide", false, false);

            // add some keyboard shortcuts
            var self = this;
            this.keyHandler = me.event.subscribe(me.event.KEYDOWN, function (action, keyCode, edge) {
                if (action === "show") {
                    self.show();
                } else if (action === "hide") {
                    self.hide();
                }
            });

            // re-apply panel settings on level changes
            this.levelHandler = me.event.subscribe(me.event.LEVEL_LOADED, function () {
                var layer = me.game.currentLevel.getLayerByName("collision");
                if (layer) {
                    layer.setOpacity((me.debug.renderCollisionMap===true)?1:0);
                }
            });

            // memory heap sample points
            this.samples = [];

            //patch patch patch !
            this.patchSystemFn();
            me.video.onresize(null);
            // make it visible
            this.show();
        },

        /**
         * patch system fn to draw debug information
         */
        patchSystemFn : function() {

            // add a few new debug flag (if not yet defined)
            me.debug.renderHitBox = me.debug.renderHitBox || false;
            me.debug.renderVelocity = me.debug.renderVelocity || false;
            me.debug.renderCollisionMap = me.debug.renderCollisionMap || false;
            me.debug.renderQuadTree = me.debug.renderQuadTree || false;

            var _this = this;

            // patch timer.js
            me.plugin.patch(me.timer, "update", function (time) {
                // call the original me.timer.update function
                this._patched(time);

                // call the FPS counter
                me.timer.countFPS();
            });

            // patch me.game.update
            me.plugin.patch(me.game, 'update', function(time) {
                var frameUpdateStartTime = window.performance.now();

                this._patched(time);

                // calculate the update time
                _this.frameUpdateTime = window.performance.now() - frameUpdateStartTime;
            });

            // patch me.game.draw
            me.plugin.patch(me.game, 'draw', function() {
                var frameDrawStartTime = window.performance.now();

                this._patched();

                // calculate the drawing time
                _this.frameDrawTime = window.performance.now() - frameDrawStartTime;
            });

            // patch sprite.js
            me.plugin.patch(me.Sprite, "draw", function (renderer) {
                // call the original me.Sprite function
                this._patched(renderer);

                // draw the sprite rectangle
                if (me.debug.renderHitBox) {
                    renderer.strokeRect(this.left, this.top, this.width, this.height, "green");
                }
            });

            // patch entities.js
            me.plugin.patch(me.Entity, "draw", function (renderer) {
                // call the original me.game.draw function
                this._patched(renderer);

                // check if debug mode is enabled

                if (me.debug.renderHitBox) {
                    renderer.save();
                    // draw the bounding rect shape
                    this.body.getBounds().draw(renderer, "orange");
                    renderer.translate(this.pos.x, this.pos.y);
                    if (this.body.shapes.length) {
                        // TODO : support multiple shapes
                        this.body.shapes[0].draw(renderer, "red");
                    }
                    renderer.restore();
                }

                if (me.debug.renderVelocity) {
                    // draw entity current velocity
                    var x = ~~(this.pos.x + this.hWidth);
                    var y = ~~(this.pos.y + this.hHeight);
                    // TODO: This will also be tricky for WebGL.
                    var context = renderer.getContext();
                    context.strokeStyle = "blue";
                    context.lineWidth = 1;
                    context.beginPath();
                    context.moveTo(x, y);
                    context.lineTo(
                        x + ~~(this.body.vel.x * this.hWidth),
                        y + ~~(this.body.vel.y * this.hHeight)
                    );
                    context.stroke();
                }
            });

            // resize event to resize our canvas
            me.plugin.patch(me.video, "updateDisplaySize", function (scaleX, scaleY) {
                this._patched(scaleX, scaleY);

                var canvas = me.video.renderer.getScreenCanvas();
                _this.canvas.width = canvas.width;
                _this.canvas.height = DEBUG_HEIGHT;
                _this.canvas.style.top = (-parseInt(canvas.style.height)) + "px";
                _this.canvas.style.width = canvas.style.width;
                _this.canvas.style.height = DEBUG_HEIGHT * scaleY;
                _this.rect.resize(canvas.width, DEBUG_HEIGHT * scaleY);
            });
        },

        /**
         * show the debug panel
         */
        show : function() {
            if (!this.visible) {
                // register a mouse event for the checkboxes
                me.input.registerPointerEvent('pointerdown', this.rect, this.onClick.bind(this), true);
                // add the debug panel to the game world
                me.game.world.addChild(this, Infinity);
                // mark it as visible
                this.visible = true;
            }
        },

        /**
         * hide the debug panel
         */
        hide : function() {
            if (this.visible) {
                // release the mouse event for the checkboxes
                me.input.releasePointerEvent('pointerdown', this.rect);
                // remove the debug panel from the game world
                me.game.world.removeChild(this);
                // mark it as invisible
                this.visible = false;
            }
        },

        /** @private */
        update : function() {
            if (me.input.isKeyPressed('show')) {
                this.show();
            }
            else if (me.input.isKeyPressed('hide')) {
                this.hide();
            }
            return true;
        },

        /**
         * @private
         */
        getBounds : function() {
            return this.rect;
        },

        /** @private */
        onClick : function(e)  {
            // check the clickable areas
            if (this.area.renderHitBox.containsPoint(e.gameX, e.gameY)) {
                me.debug.renderHitBox = !me.debug.renderHitBox;
            }
            else if (this.area.renderCollisionMap.containsPoint(e.gameX, e.gameY)) {
                var layer = me.game.currentLevel.getLayerByName("collision");
                if (layer) {
                    if (layer.getOpacity() === 0) {
                        layer.setOpacity(1);
                        me.debug.renderCollisionMap = true;
                    } else {
                        layer.setOpacity(0);
                        me.debug.renderCollisionMap = false;
                    }
                }
            }
            else if (this.area.renderVelocity.containsPoint(e.gameX, e.gameY)) {
                // does nothing for now, since velocity is
                // rendered together with hitboxes (is a global debug flag required?)
                me.debug.renderVelocity = !me.debug.renderVelocity;
            }
            else if (this.area.renderQuadTree.containsPoint(e.gameX, e.gameY)) {
                me.debug.renderQuadTree = !me.debug.renderQuadTree;
            }
            // force repaint
            me.game.repaint();
        },

        /** @private */
        drawQuadTreeNode : function (renderer, node) {
            var bounds = node._bounds;

            // Opacity is based on number of objects in the cell
            renderer.setGlobalAlpha((node.children.length / 16).clamp(0, 0.9));
            renderer.fillRect(Math.abs(bounds.pos.x) + 0.5,
                Math.abs(bounds.pos.y) + 0.5,
                bounds.width,
                bounds.height,
                "red"
            );

            var len = node.nodes.length;

            for(var i = 0; i < len; i++) {
                this.drawQuadTreeNode(renderer, node.nodes[i]);
            }
        },

        /** @private */
        drawQuadTree : function (renderer) {
            // save the current globalAlpha value
            var _alpha = renderer.globalAlpha();

            renderer.translate(-me.game.viewport.pos.x, -me.game.viewport.pos.y);

            this.drawQuadTreeNode(renderer, me.collision.quadTree.root);

            renderer.translate(me.game.viewport.pos.x, me.game.viewport.pos.y);

            renderer.setGlobalAlpha(_alpha);
        },

        /** @private */
        drawMemoryGraph : function (context, endX) {
            if (window.performance && window.performance.memory) {
                var usedHeap  = Number.prototype.round(window.performance.memory.usedJSHeapSize/1048576, 2);
                var totalHeap =  Number.prototype.round(window.performance.memory.totalJSHeapSize/1048576, 2);
                var len = endX - this.memoryPositionX;

                // remove the first item
                this.samples.shift();
                // add a new sample (25 is the height of the graph)
                this.samples[len] = (usedHeap / totalHeap)  * 25;

                // draw the graph
                for (var x = len; x >= 0; x--) {
                    var where = endX - (len - x);
                    context.beginPath();
                    context.strokeStyle = "lightblue";
                    context.moveTo(where, 30 * this.mod);
                    context.lineTo(where, (30 - (this.samples[x] || 0)) * this.mod);
                    context.stroke();
                }
                // display the current value
                this.font.drawFromContext(context, "Heap : " + usedHeap + '/' + totalHeap + ' MB', this.memoryPositionX, 5 * this.mod);
            } else {
                // Heap Memory information not available
                this.font.drawFromContext(context, "Heap : ??/?? MB", this.memoryPositionX, 5 * this.mod);
            }
        },

        /** @private */
        draw : function(renderer) {
            this.context.save();

            // draw the QuadTree (before the panel)
            if (me.debug.renderQuadTree === true) {
                this.drawQuadTree(renderer);
            }

            // draw the panel
            this.context.globalAlpha = 0.5;
            this.context.fillRect(this.rect.left,  this.rect.top,
                             this.rect.width, this.rect.height, "black");
            this.context.globalAlpha = 1.0;

            // # entities / draw
            this.font.drawFromContext(this.context, "#objects : " + me.game.world.children.length, 5 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "#draws   : " + me.game.world.drawCount, 5 * this.mod, 15 * this.mod);

            // debug checkboxes
            this.font.drawFromContext(this.context, "?hitbox   ["+ (me.debug.renderHitBox?"x":" ") +"]",     85 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "?velocity ["+ (me.debug.renderVelocity?"x":" ") +"]",     85 * this.mod, 15 * this.mod);

            this.font.drawFromContext(this.context, "?QuadTree   ["+ (me.debug.renderQuadTree?"x":" ") +"]",    175 * this.mod, 5 * this.mod);
            this.font.drawFromContext(this.context, "?col. layer ["+ (me.debug.renderCollisionMap?"x":" ") +"]", 175 * this.mod, 15 * this.mod);

            // draw the update duration
            this.font.drawFromContext(this.context, "Update : " + this.frameUpdateTime.toFixed(2) + " ms", 285 * this.mod, 5 * this.mod);
            // draw the draw duration
            this.font.drawFromContext(this.context, "Draw   : " + (this.frameDrawTime).toFixed(2) + " ms", 285 * this.mod, 15 * this.mod);

            // draw the memory heap usage
            var endX = this.rect.width - 25;
            this.drawMemoryGraph(this.context, endX - this.help_str_len);

            // some help string
            this.font.drawFromContext(this.context, this.help_str, endX - this.help_str_len, 15 * this.mod);

            //fps counter
            var fps_str = "" + me.timer.fps + "/"    + me.sys.fps + " fps";
            this.font.drawFromContext(this.context, fps_str, this.rect.width - this.fps_str_len - 5, 5 * this.mod);

            this.context.restore();

        },

        /** @private */
        onDestroyEvent : function() {
            // hide the panel
            this.hide();
            // unbind keys event
            me.input.unbindKey(me.input.KEY.S);
            me.input.unbindKey(me.input.KEY.H);
            me.event.unsubscribe(this.keyHandler);
            me.event.unsubscribe(this.levelHandler);
        }

    });

    /*---------------------------------------------------------*/
    // END END END
    /*---------------------------------------------------------*/
})(window);
<|endoftext|>


<commit_before>/*jshint node: true */
'use strict';

/*
* Name :  MapChartController.js
* Module : UnitTest
* Location : /frontend/test/unit/Controller
*
* History :
* Version       Date        Programmer                  Description
* =================================================================================================
* 0.1.0         2015-05-25  Maria Giovanna Chinellato   Add all attributes and all methods
*
* 0.0.1         2015-05-25  Maria Giovanna Chinellato   Initial code
* =================================================================================================
*
*/

describe('MapChartController', function() {
    /*var scope, $location, $controller;

    beforeEach(angular.mock.module('norris-nrti'));

    beforeEach(inject(function($rootScope, _$controller_, _$location_){
    	$controller = _$controller_
        $location = _$location_;
        scope = $rootScope.$new();

        createController = function() {
            return $controller('MapChartController', {
                '$scope': scope
            });
        };
    }));

    it('should have a method to check if the path is active', function() {
        var controller = createController();
        expect(scope.mapChart).toBeDefined();
    });
});

describe('MapChartController', function(){

	beforeEach(angular.mock.module('norris-nrti'));

	var scope;
	var controller;
	var MapChartFactory;
	//var notify;
	var json = {
			'title' : 'graficonuovo',
			'url' : 'localhost',
			'height' : 400,
			'width' : 400,
			'enabledLegend' : false,
			'horizontalGrid' : false,
			'verticalGrid' : false,
			'legendOnPoint' : false,
			'latitude' : 3,
			'longitude' : 3,
			'scale' : 999,
			'mapType' : 'terrain',
			'zoom' : false,
			'flows' : [{'ID' : '1'},{'ID' : '2'},{'ID' : '3'}]
	};

    describe('listenOnEvent', function(){
		beforeEach(inject(function ($rootScope, $controller, $injector) {
	    	MapChartFactory = $injector.get('MapChartFactory');
	        scope = $rootScope.$new();
	        scope.mapChart = MapChartFactory.build(json);
	        //notify = _notify_;
	        controller = $controller('MapChartController', {    // "lo conosci il MapChartController?" cit. Barney
	        	$scope : scope
	        });
	    }));

	    it ('listenOnEvent works fine', function(){

	    	expect(scope.mapChart).toBeDefined();
			expect(scope.mapChart.getTitle()).toEqual('graficonuovo');
			/*notify.receive('configGraph',{
				'properties' : {
					'title' : 'titolocambiato'
				},
				'data' : data
			});
			expect(scope.mapChart.getTitle()).toEqual('titolocambiato');
			expect(scope.mapChart.getFlowList()[0].flow.getData()[0].value[0]).toEqual(0);
		});
    });

	//describe('socketConnection', function(){

	//});

	describe('listenOnEvent', function(){

		var data = [
			{
				'ID' : '1',
				'records' : [{ 'NorrisRecordID' : '234321', 'value' : [0,1]},{}]
			}
		];

		beforeEach(function(){
			scope.mapChart = MapChartFactory.build(json);
		});

		it ('listenOnEvent works fine', function(){
			controller('MapChartController', {$scope : scope});
			expect(scope.mapChart.getTitle()).toEqual('graficonuovo');
			notify.receive('configGraph',{
				'properties' : {
					'title' : 'titolocambiato'
				},
				'data' : data
			});
			expect(scope.mapChart.getTitle()).toEqual('titolocambiato');
			expect(scope.mapChart.getFlowList()[0].flow.getData()[0].value[0]).toEqual(0);
		});
	});
	*/
});
<commit_msg>fix map chart controller test<commit_after>/*jshint node: true */
'use strict';

/*
* Name :  MapChartController.js
* Module : UnitTest
* Location : /frontend/test/unit/Controller
*
* History :
* Version       Date        Programmer                  Description
* =================================================================================================
* 0.1.0         2015-05-25  Maria Giovanna Chinellato   Add all attributes and all methods
*
* 0.0.1         2015-05-25  Maria Giovanna Chinellato   Initial code
* =================================================================================================
*
*/

describe('MapChartController', function() {
    var scope, $location, $controller;

    beforeEach(angular.mock.module('norris-nrti'));

    beforeEach(inject(function($rootScope, _$controller_, _$location_){
    	$controller = _$controller_;
        $location = _$location_;
        scope = $rootScope.$new();

        createController = function() {
            return $controller('MapChartController', {
                '$scope': scope
            });
        };
    }));

    it('should have a method to check if the path is active', function() {
        var controller = createController();
        expect(scope.mapChart).toBeDefined();
    });
});

/*describe('MapChartController', function(){

	beforeEach(angular.mock.module('norris-nrti'));

	var scope;
	var controller;
	var MapChartFactory;
	//var notify;
	var json = {
			'title' : 'graficonuovo',
			'url' : 'localhost',
			'height' : 400,
			'width' : 400,
			'enabledLegend' : false,
			'horizontalGrid' : false,
			'verticalGrid' : false,
			'legendOnPoint' : false,
			'latitude' : 3,
			'longitude' : 3,
			'scale' : 999,
			'mapType' : 'terrain',
			'zoom' : false,
			'flows' : [{'ID' : '1'},{'ID' : '2'},{'ID' : '3'}]
	};

    describe('listenOnEvent', function(){
		beforeEach(inject(function ($rootScope, $controller, $injector) {
	    	MapChartFactory = $injector.get('MapChartFactory');
	        scope = $rootScope.$new();
	        scope.mapChart = MapChartFactory.build(json);
	        //notify = _notify_;
	        controller = $controller('MapChartController', {    // "lo conosci il MapChartController?" cit. Barney
	        	$scope : scope
	        });
	    }));

	    it ('listenOnEvent works fine', function(){

	    	expect(scope.mapChart).toBeDefined();
			expect(scope.mapChart.getTitle()).toEqual('graficonuovo');
			/*notify.receive('configGraph',{
				'properties' : {
					'title' : 'titolocambiato'
				},
				'data' : data
			});
			expect(scope.mapChart.getTitle()).toEqual('titolocambiato');
			expect(scope.mapChart.getFlowList()[0].flow.getData()[0].value[0]).toEqual(0);
		});
    });

	//describe('socketConnection', function(){

	//});

	describe('listenOnEvent', function(){

		var data = [
			{
				'ID' : '1',
				'records' : [{ 'NorrisRecordID' : '234321', 'value' : [0,1]},{}]
			}
		];

		beforeEach(function(){
			scope.mapChart = MapChartFactory.build(json);
		});

		it ('listenOnEvent works fine', function(){
			controller('MapChartController', {$scope : scope});
			expect(scope.mapChart.getTitle()).toEqual('graficonuovo');
			notify.receive('configGraph',{
				'properties' : {
					'title' : 'titolocambiato'
				},
				'data' : data
			});
			expect(scope.mapChart.getTitle()).toEqual('titolocambiato');
			expect(scope.mapChart.getFlowList()[0].flow.getData()[0].value[0]).toEqual(0);
		});
	});

});*/<|endoftext|>


<commit_before>GCMRC.Page = {
	createLargeMap: function(config) {
		if (!config)
			config = {};

		var divId = config['divId'] || 'openlayers-map';

		var options = {controls: [
//				new OpenLayers.Control.LayerSwitcher()
		]};
		GCMRC.Mapping.maps[divId] = new OpenLayers.Map(divId, options);

		var layersToAdd = [];
		layersToAdd.push(GCMRC.Mapping.layers.esri.esriTopo);
//		[].push.apply(layersToAdd, GCMRC.Mapping.layers.esri.values());
		layersToAdd.push(GCMRC.Mapping.layers.flowlines.allzones);
		layersToAdd.push(GCMRC.Mapping.layers.flowlines.zone8374535);
		layersToAdd.push(GCMRC.Mapping.layers.vector);
		GCMRC.Mapping.maps[divId].addLayers(layersToAdd);

		GCMRC.Stations.values(function(station) {
			if (!station.hidden && station.network === CONFIG.networkName) {
				var sitePoint = new OpenLayers.Geometry.Point(station.lon, station.lat).transform(
						new OpenLayers.Projection("EPSG:4326"),
						GCMRC.Mapping.maps[divId].getProjectionObject()
						);

				var siteFeature = new OpenLayers.Feature.Vector(sitePoint, {
					siteName: station.nwisSite || station.shortName
				});
				GCMRC.Mapping.layers.vector.addFeatures([siteFeature]);
			}
		});

		var resizeToDefault = true;
		if (1 < GCMRC.Mapping.layers.vector.features.length) {
			resizeToDefault = false;
			GCMRC.Mapping.maps[divId].zoomToExtent(GCMRC.Mapping.layers.vector.getDataExtent());
			if (9 < GCMRC.Mapping.maps[divId].zoom) {
				resizeToDefault = true;
			}
		}
		if (resizeToDefault) {
			if ('GCDAMP' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-12499366.619029, 4338225.8756765), 8);
			} else if ('DINO' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-12097598.376886, 4950668.6874257), 9);
			} else if ('BIBE' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-11492369.987008, 3397774.0210003), 9);
			} else {
				LOG.error("Invalid Network Name!");
			}
		}
	},
	reachColoring : [
		"#0967B0",
		"#FF9200",
		"#F30026",
		"#3CDF00",
		"#660AB6",
		"#000000",
		'#FFFFFF'
	],
	addReaches : function($div) {
		var addReachToPage = function(el) {
			var result = [];

			var backgroundColor = '#FFFFFF';
			var linkit = !("09402500" === el.upstreamStation || "09404120" === el.upstreamStation);
			if (this.index < GCMRC.Page.reachColoring.length) {
				backgroundColor = GCMRC.Page.reachColoring[this.index];
				this.index++;
			}

			result.push('
');

			if (linkit) {
				[].push.apply(result, [
				'']);
			}

			[].push.apply(result, [
				'']);

			if (linkit) {
				result.push('');
			}

			result.push('
');

			if (linkit) {
				[].push.apply(result, [
				'']);
			}

			[].push.apply(result, [
				'
',el.reachName,'
']);

			if (linkit) {
				result.push('');
			}

			[].push.apply(result, [
				"(",
				el.upstreamDisplayName,
				" to ",
				el.downstreamDisplayName,
				")",
				'
',
				'
'
			]);

			$div.append(result.join(""));
		};
		GCMRC.Page.reaches.forEach(addReachToPage, {index : 0});
	},
	reaches : [],
	reachLoad : JSL.ResourceLoad(function(el) {
		GCMRC.Page.reaches.push(el);
	})
};<commit_msg>all reaches are linked<commit_after>GCMRC.Page = {
	createLargeMap: function(config) {
		if (!config)
			config = {};

		var divId = config['divId'] || 'openlayers-map';

		var options = {controls: [
//				new OpenLayers.Control.LayerSwitcher()
		]};
		GCMRC.Mapping.maps[divId] = new OpenLayers.Map(divId, options);

		var layersToAdd = [];
		layersToAdd.push(GCMRC.Mapping.layers.esri.esriTopo);
//		[].push.apply(layersToAdd, GCMRC.Mapping.layers.esri.values());
		layersToAdd.push(GCMRC.Mapping.layers.flowlines.allzones);
		layersToAdd.push(GCMRC.Mapping.layers.flowlines.zone8374535);
		layersToAdd.push(GCMRC.Mapping.layers.vector);
		GCMRC.Mapping.maps[divId].addLayers(layersToAdd);

		GCMRC.Stations.values(function(station) {
			if (!station.hidden && station.network === CONFIG.networkName) {
				var sitePoint = new OpenLayers.Geometry.Point(station.lon, station.lat).transform(
						new OpenLayers.Projection("EPSG:4326"),
						GCMRC.Mapping.maps[divId].getProjectionObject()
						);

				var siteFeature = new OpenLayers.Feature.Vector(sitePoint, {
					siteName: station.nwisSite || station.shortName
				});
				GCMRC.Mapping.layers.vector.addFeatures([siteFeature]);
			}
		});

		var resizeToDefault = true;
		if (1 < GCMRC.Mapping.layers.vector.features.length) {
			resizeToDefault = false;
			GCMRC.Mapping.maps[divId].zoomToExtent(GCMRC.Mapping.layers.vector.getDataExtent());
			if (9 < GCMRC.Mapping.maps[divId].zoom) {
				resizeToDefault = true;
			}
		}
		if (resizeToDefault) {
			if ('GCDAMP' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-12499366.619029, 4338225.8756765), 8);
			} else if ('DINO' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-12097598.376886, 4950668.6874257), 9);
			} else if ('BIBE' === CONFIG.networkName) {
				GCMRC.Mapping.maps[divId].moveTo(new OpenLayers.LonLat(-11492369.987008, 3397774.0210003), 9);
			} else {
				LOG.error("Invalid Network Name!");
			}
		}
	},
	reachColoring : [
		"#0967B0",
		"#FF9200",
		"#F30026",
		"#3CDF00",
		"#660AB6",
		"#000000",
		'#FFFFFF'
	],
	addReaches : function($div) {
		var addReachToPage = function(el) {
			var result = [];

			var backgroundColor = '#FFFFFF';
			var linkit = true; //!("09402500" === el.upstreamStation || "09404120" === el.upstreamStation);
			if (this.index < GCMRC.Page.reachColoring.length) {
				backgroundColor = GCMRC.Page.reachColoring[this.index];
				this.index++;
			}

			result.push('
');

			if (linkit) {
				[].push.apply(result, [
				'']);
			}

			[].push.apply(result, [
				'']);

			if (linkit) {
				result.push('');
			}

			result.push('
');

			if (linkit) {
				[].push.apply(result, [
				'']);
			}

			[].push.apply(result, [
				'
',el.reachName,'
']);

			if (linkit) {
				result.push('');
			}

			[].push.apply(result, [
				"(",
				el.upstreamDisplayName,
				" to ",
				el.downstreamDisplayName,
				")",
				'
',
				'
'
			]);

			$div.append(result.join(""));
		};
		GCMRC.Page.reaches.forEach(addReachToPage, {index : 0});
	},
	reaches : [],
	reachLoad : JSL.ResourceLoad(function(el) {
		GCMRC.Page.reaches.push(el);
	})
};<|endoftext|>


<commit_before>(function()
{
    // Set in define().
    let Ordering;

    const configuration = {};

    // Version operations:
    {
        // Creates a new version identifier.
        function create(major, minor = 0, patch = 0, beta = 0)
        {
            return {
                major: major,
                minor: minor,
                patch: patch,
                beta : beta
            };
        }

        // Returns true iff the specified object is a (non-strict) positive integer.
        function is_positive_integer(obj)
        {
            return Number.isInteger(obj) && obj >= 0;
        }
        // Returns true iff the specified object is a valid version identifier.
        function is_valid(obj)
        {
            return (
                is_positive_integer(obj.major) &&
                is_positive_integer(obj.minor) &&
                is_positive_integer(obj.patch) &&
                is_positive_integer(obj.beta)
            );
        }

        // Returns an Ordering relating two version identifiers.
        function compare(a, b)
        {
            const components_a = [a.major, a.minor, a.patch, a.beta],
                  components_b = [b.major, b.minor, b.patch, b.beta];

            for (let i = 0; i < 4; ++i)
            {
                const component_a = components_a[i],
                      component_b = components_b[i];

                if      (component_a > component_b) { return Ordering.Greater; }
                else if (component_a < component_b) { return Ordering.Less;    }
            }
            return Ordering.Equal;
        }

        // Builds a string representation of the specified version identifier.
        function as_string(id, include_patch = true, include_beta = true)
        {
            let result = `${id.major}.${id.minor}`;

            if (include_patch)                { result += `.${id.patch}`; }
            if (include_beta && id.beta > 0)  { result += `b${id.beta}`;  }

            return result;
        }

        configuration.version =
        {
            CURRENT: create(1, 7, 0, 2),
            HAS_RELEASE_NOTES: false,

            create:    create,
            is_valid:  is_valid,
            compare:   compare,
            as_string: as_string
        };
    }
    // Storage layout:
    {
        const version = configuration.version;

        // Enumerates possible tab behaviors.
        const TabBehavior =
        {
            // Redirection to a specified URL.
            Redirect: "redirect",

            // Display of a custom page with user-specified background color and wallpaper image.
            DisplayCustomPage: "display-custom-page"
        };
        configuration.TabBehavior = TabBehavior;

        // Enumerates option-ui themes.
        const Theme =
        {
            Light: "light",
            Dark:  "dark"
        };
        configuration.Theme = Theme;

        // Enumerates (wallpaper) scaling methods.
        const Scaling =
        {
            // Chooses the best method based on the dimensions of the image vs. those of the screen.
            Automatic: "automatic",

            // Tightly fit inside bounds.
            Fit: "fit",

            // Fill bounds.
            Fill: "fill",

            // No scaling.
            None: "none",
        };
        configuration.Scaling = Scaling;

        // Enumerates top site visibility conditions.
        const TopSitesVisibility =
        {
            // Show always.
            Show: "show-always",

            // Show only after the user indicates so.
            ShowOnRequest: "show-on-request",

            // Hide always.
            Hide: "hide-always"
        };
        configuration.TopSitesVisibility = TopSitesVisibility;

        // The default configuration.
        configuration.create_default = function()
        {
            return {
                version: version.create(version.CURRENT.major, version.CURRENT.minor),

                notification:
                {
                    new_features: true
                },
                new_tab:
                {
                    behavior: TabBehavior.DisplayCustomPage,

                    redirect:
                    {
                        url: ""
                    },
                    custom_page:
                    {
                        background:
                        {
                            color: "#2d2d2d",

                            do_animate: true,
                            animation_duration: 0.5
                        },
                        wallpaper:
                        {
                            is_enabled: false,

                            urls: [],

                            scaling: Scaling.Automatic,
                            do_animate: true,
                            animation_duration: 1.5
                        },
                        top_sites:
                        {
                            visibility: TopSitesVisibility.ShowOnRequest
                        }
                    }
                },
                options_ui:
                {
                    theme: Theme.Light
                }
            };
        };
    }
    // Updates:
    {
        const version   = configuration.version;
        const migration =
        {
            "1.4": cfg =>  // migrates 1.4 to 1.5
            {
                cfg.version = version.create(1, 5);

                const page = cfg.new_tab.custom_page;
                const bg   = page.background;
                const wp   = page.wallpaper;

                bg.do_animate         = bg.animation_duration > 0;
                bg.animation_duration = Math.max(bg.animation_duration, 0.1);

                wp.do_animate         = wp.animation_duration > 0;
                wp.animation_duration = Math.max(wp.animation_duration, 0.1);

                cfg.options_ui = { theme: configuration.Theme.Light };
            },
            "1.5": cfg => // migrates 1.5 to 1.6
            {
                cfg.version = version.create(1, 6);

                cfg.new_tab.custom_page.wallpaper.scaling = configuration.Scaling.Fit;
            },
            "1.6": cfg => // migrates 1.6 to 1.7
            {
                cfg.version = version.create(1, 7);

                cfg.new_tab.custom_page.top_sites.visibility =
                    configuration.TopSitesVisibility.ShowOnRequest;
            }
        };
        // Updates the configuration object layout.
        configuration.update = function(cfg)
        {
            let version_string = version.as_string(cfg.version, false, false);
            while (migration.hasOwnProperty(version_string))
            {
                migration[version_string](cfg);
                version_string = version.as_string(cfg.version, false, false);
            }
            cfg.version = version.create(
                version.CURRENT.major,
                version.CURRENT.minor
            );

            return cfg;
        };
    }
    // Read/write:
    {
        // The key to the configuration object in local storage.
        const KEY = "configuration@new-tab-tweaker";

        // Loads the configuration from storage asynchronously (returns a promise).
        //
        // Note: If no configuration object is detected, returns one with default values.
        function load()
        {
            return browser.storage.local.get(KEY).then(item =>
            {
                if (item.hasOwnProperty(KEY)) { return item[KEY];                      }
                else                          { return configuration.create_default(); }
            });
        }
        // Saves a configuration to storage asynchronously (returns a promise).
        function save(cfg)
        {
            const item = {};
            item[KEY] = cfg;

            return browser.storage.local.set(item);
        }

        configuration.storage =
        {
            KEY: KEY,

            load: load,
            save: save
        };
    }

    define(["./ordering"],
    function(ordering)
    {
        Ordering = ordering;

        return configuration;
    });
})();
<commit_msg>add a default wallpaper (Pleiades)<commit_after>(function()
{
    // Set in define().
    let Ordering;

    const configuration = {};

    // Version operations:
    {
        // Creates a new version identifier.
        function create(major, minor = 0, patch = 0, beta = 0)
        {
            return {
                major: major,
                minor: minor,
                patch: patch,
                beta : beta
            };
        }

        // Returns true iff the specified object is a (non-strict) positive integer.
        function is_positive_integer(obj)
        {
            return Number.isInteger(obj) && obj >= 0;
        }
        // Returns true iff the specified object is a valid version identifier.
        function is_valid(obj)
        {
            return (
                is_positive_integer(obj.major) &&
                is_positive_integer(obj.minor) &&
                is_positive_integer(obj.patch) &&
                is_positive_integer(obj.beta)
            );
        }

        // Returns an Ordering relating two version identifiers.
        function compare(a, b)
        {
            const components_a = [a.major, a.minor, a.patch, a.beta],
                  components_b = [b.major, b.minor, b.patch, b.beta];

            for (let i = 0; i < 4; ++i)
            {
                const component_a = components_a[i],
                      component_b = components_b[i];

                if      (component_a > component_b) { return Ordering.Greater; }
                else if (component_a < component_b) { return Ordering.Less;    }
            }
            return Ordering.Equal;
        }

        // Builds a string representation of the specified version identifier.
        function as_string(id, include_patch = true, include_beta = true)
        {
            let result = `${id.major}.${id.minor}`;

            if (include_patch)                { result += `.${id.patch}`; }
            if (include_beta && id.beta > 0)  { result += `b${id.beta}`;  }

            return result;
        }

        configuration.version =
        {
            CURRENT: create(1, 7, 0, 2),
            HAS_RELEASE_NOTES: false,

            create:    create,
            is_valid:  is_valid,
            compare:   compare,
            as_string: as_string
        };
    }
    // Storage layout:
    {
        const version = configuration.version;

        // Enumerates possible tab behaviors.
        const TabBehavior =
        {
            // Redirection to a specified URL.
            Redirect: "redirect",

            // Display of a custom page with user-specified background color and wallpaper image.
            DisplayCustomPage: "display-custom-page"
        };
        configuration.TabBehavior = TabBehavior;

        // Enumerates option-ui themes.
        const Theme =
        {
            Light: "light",
            Dark:  "dark"
        };
        configuration.Theme = Theme;

        // Enumerates (wallpaper) scaling methods.
        const Scaling =
        {
            // Chooses the best method based on the dimensions of the image vs. those of the screen.
            Automatic: "automatic",

            // Tightly fit inside bounds.
            Fit: "fit",

            // Fill bounds.
            Fill: "fill",

            // No scaling.
            None: "none",
        };
        configuration.Scaling = Scaling;

        // Enumerates top site visibility conditions.
        const TopSitesVisibility =
        {
            // Show always.
            Show: "show-always",

            // Show only after the user indicates so.
            ShowOnRequest: "show-on-request",

            // Hide always.
            Hide: "hide-always"
        };
        configuration.TopSitesVisibility = TopSitesVisibility;

        // The default configuration.
        configuration.create_default = function()
        {
            return {
                version: version.create(version.CURRENT.major, version.CURRENT.minor),

                notification:
                {
                    new_features: true
                },
                new_tab:
                {
                    behavior: TabBehavior.DisplayCustomPage,

                    redirect:
                    {
                        url: ""
                    },
                    custom_page:
                    {
                        background:
                        {
                            color: "#2d2d2d",

                            do_animate: true,
                            animation_duration: 0.5
                        },
                        wallpaper:
                        {
                            is_enabled: true,

                            urls: ["https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Pleiades_large.jpg/1280px-Pleiades_large.jpg"],

                            scaling: Scaling.Automatic,
                            do_animate: true,
                            animation_duration: 1.5
                        },
                        top_sites:
                        {
                            visibility: TopSitesVisibility.ShowOnRequest
                        }
                    }
                },
                options_ui:
                {
                    theme: Theme.Light
                }
            };
        };
    }
    // Updates:
    {
        const version   = configuration.version;
        const migration =
        {
            "1.4": cfg =>  // migrates 1.4 to 1.5
            {
                cfg.version = version.create(1, 5);

                const page = cfg.new_tab.custom_page;
                const bg   = page.background;
                const wp   = page.wallpaper;

                bg.do_animate         = bg.animation_duration > 0;
                bg.animation_duration = Math.max(bg.animation_duration, 0.1);

                wp.do_animate         = wp.animation_duration > 0;
                wp.animation_duration = Math.max(wp.animation_duration, 0.1);

                cfg.options_ui = { theme: configuration.Theme.Light };
            },
            "1.5": cfg => // migrates 1.5 to 1.6
            {
                cfg.version = version.create(1, 6);

                cfg.new_tab.custom_page.wallpaper.scaling = configuration.Scaling.Fit;
            },
            "1.6": cfg => // migrates 1.6 to 1.7
            {
                cfg.version = version.create(1, 7);

                cfg.new_tab.custom_page.top_sites.visibility =
                    configuration.TopSitesVisibility.ShowOnRequest;
            }
        };
        // Updates the configuration object layout.
        configuration.update = function(cfg)
        {
            let version_string = version.as_string(cfg.version, false, false);
            while (migration.hasOwnProperty(version_string))
            {
                migration[version_string](cfg);
                version_string = version.as_string(cfg.version, false, false);
            }
            cfg.version = version.create(
                version.CURRENT.major,
                version.CURRENT.minor
            );

            return cfg;
        };
    }
    // Read/write:
    {
        // The key to the configuration object in local storage.
        const KEY = "configuration@new-tab-tweaker";

        // Loads the configuration from storage asynchronously (returns a promise).
        //
        // Note: If no configuration object is detected, returns one with default values.
        function load()
        {
            return browser.storage.local.get(KEY).then(item =>
            {
                if (item.hasOwnProperty(KEY)) { return item[KEY];                      }
                else                          { return configuration.create_default(); }
            });
        }
        // Saves a configuration to storage asynchronously (returns a promise).
        function save(cfg)
        {
            const item = {};
            item[KEY] = cfg;

            return browser.storage.local.set(item);
        }

        configuration.storage =
        {
            KEY: KEY,

            load: load,
            save: save
        };
    }

    define(["./ordering"],
    function(ordering)
    {
        Ordering = ordering;

        return configuration;
    });
})();
<|endoftext|>


<commit_before>(function() {

var json_callback = function(json) {
    var template_url = json['template_url'];
    var d = MochiKit.Async.doSimpleXMLHttpRequest(template_url);
    d.addCallback(function(result) {
      var t = jsontemplate.Template(result.responseText);
      var s = t.expand(json);
      $('search_result').innerHTML = s;
    });
    return d;
};

var json_errback = function(error) {
    log('error when getting find json');
}

var render = function() {
  var d = MochiKit.Async.loadJSONDoc('find');
  d.addCallbacks(json_callback, json_errback);
};

MochiKit.Signal.connect(window, 'onload', render);

})();
<commit_msg>- Add caching of the template rendering.<commit_after>(function() {

var template_cache = {};

var load_template = function(template_url, json, id) {
    var d = MochiKit.Async.doSimpleXMLHttpRequest(template_url);
    d.addCallback(function(result) {
        t = make_template(template_url, result.responseText);
        expand_template(t, json, id);
    });
    return d;
};

var make_template = function(template_url, template_source) {
    var t = jsontemplate.Template(template_source);
    template_cache[template_url] = t;
    return t;
};

var expand_template = function(template, json, id) {
    var s = t.expand(json);
    $(id).innerHTML = s;
};

var json_callback = function(json) {
    var id = 'search_result';
    var template_url = json['template_url'];
    var template = template_cache[template_url];
    if (!isUndefinedOrNull(template)) {
        expand_template(template, json, id);
        return;
    }
    load_template(template_url, json, id);
};

var json_errback = function(error) {
    log('error when getting find json');
};

var render = function() {
  var d = MochiKit.Async.loadJSONDoc('find');
  d.addCallbacks(json_callback, json_errback);
};

MochiKit.Signal.connect(window, 'onload', render);

})();
<|endoftext|>


<commit_before>/**
 * A small plugin for getting the CSV of a categorized chart
 * Based on https://github.com/highslide-software/export-csv
 */
(function (Highcharts) {

    var each = Highcharts.each;
    Highcharts.Chart.prototype.getCSV = function () {
        var columns = [],
            line,
            tempLine,
            csv = "",
            row,
            col,
            options = (this.options.exporting || {}).csv || {},

            // Options
            dateFormat = options.dateFormat || '%Y-%m-%d %H:%M:%S',
            itemDelimiter = options.itemDelimiter || ',', // use ';' for direct import to Excel
            lineDelimiter = options.lineDelimeter || '\n';

        each (this.series, function (series) {
            if (series.options.includeInCSVExport !== false) {
                if (series.xAxis) {
                    var xData = series.xData.slice(),
                        xTitle = 'X values';
                    if (series.xAxis.isDatetimeAxis) {
                        xData = Highcharts.map(xData, function (x) {
                            return Highcharts.dateFormat(dateFormat, x)
                        });
                        xTitle = 'DateTime';
                    } else if (series.xAxis.categories) {
                        xData = Highcharts.map(xData, function (x) {
                            return Highcharts.pick(series.xAxis.categories[x], x);
                        });
                        xTitle = 'Category';
                    }
                    columns.push(xData);
                    columns[columns.length - 1].unshift(xTitle);
                }
                columns.push(series.yData.slice());
                columns[columns.length - 1].unshift(series.name);
            }
        });

        // Transform the columns to CSV
        for (row = 0; row < columns[0].length; row++) {
            line = [];
            for (col = 0; col < columns.length; col++) {
                line.push(columns[col][row]);
            }
            csv += line.join(itemDelimiter) + lineDelimiter;
        }

        return csv;
    };

    if (Highcharts.getOptions().exporting) {
        Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
            text: Highcharts.getOptions().lang.downloadCSV || "Download CSV",
            onclick: function () {
                Highcharts.post('/export/csv/', {
                    csv: this.getCSV()
                });
            }
        });
    }
}(Highcharts));<commit_msg>Fix chart export function<commit_after>/**
 * A small plugin for getting the CSV of a categorized chart
 * Based on https://github.com/highslide-software/export-csv
 */
(function (Highcharts) {

    var each = Highcharts.each;
    Highcharts.Chart.prototype.getCSV = function () {
        var columns = [],
            line,
            tempLine,
            csv = "",
            row,
            col,
            options = (this.options.exporting || {}).csv || {},

            // Options
            dateFormat = options.dateFormat || '%Y-%m-%d %H:%M:%S',
            itemDelimiter = options.itemDelimiter || ',', // use ';' for direct import to Excel
            lineDelimiter = options.lineDelimeter || '\n';

        each (this.series, function (series) {
            if (series.options.includeInCSVExport !== false) {
                if (series.xAxis) {
                    var xData = series.xData.slice(),
                        xTitle = 'X values';
                    if (series.xAxis.isDatetimeAxis) {
                        xData = Highcharts.map(xData, function (x) {
                            return Highcharts.dateFormat(dateFormat, x)
                        });
                        xTitle = 'DateTime';
                    } else if (series.xAxis.categories) {
                        xData = Highcharts.map(xData, function (x) {
                            return Highcharts.pick(series.xAxis.categories[x], x);
                        });
                        xTitle = 'Category';
                    }
                    columns.push(xData);
                    columns[columns.length - 1].unshift(xTitle);
                }
                columns.push(series.yData.slice());
                columns[columns.length - 1].unshift(series.name);
            }
        });

        // Transform the columns to CSV
        for (row = 0; row < columns[0].length; row++) {
            line = [];
            for (col = 0; col < columns.length; col++) {
                line.push(columns[col][row]);
            }
            csv += line.join(itemDelimiter) + lineDelimiter;
        }

        return csv;
    };

    if (Highcharts.getOptions().exporting) {
        Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({
            text: Highcharts.getOptions().lang.downloadCSV || "Download CSV",
            onclick: function () {
                Highcharts.post('api/export/', {
                    csv: this.getCSV()
                });
            }
        });
    }
}(Highcharts));<|endoftext|>


<commit_before>var http = require('http');
var express = require('express');
var sockjs = require('sockjs');
var fs = require('fs');
var Command = require('es_command');
var Transactor = require('transactor');
var EtherSheetService = require('./ethersheet_service');
var createTransactionHandler = require('./transaction_handler');
var formidable = require('formidable');

/*ISISLab code*/
var cookieParser  = require('cookie-parser');
var bodyParser    = require('body-parser');
var cookieSession = require('cookie-session');
var compression   = require('compression');
/*End ISISLab code*/

var ES_CLIENT_PATH= __dirname + '/../node_modules/es_client';
var LAYOUT_PATH = __dirname + '/layouts';

exports.createServer = function(config){

  /***********************************************
   * EtherSheet HTTP Server
   ***********************************************/
  var app = express();
  //improvement preformance
  app.use(compression());

  var http_server = http.createServer(app);

  // Server Settings
  app.set('views',LAYOUT_PATH);
  //app.use(express.logger({ format: ':method :url' }));
  app.use('/es_client',express.static(ES_CLIENT_PATH));
  /*app.use(express.bodyParser());
   app.use(express.cookieParser());*/
  app.use(cookieParser());
  //app.use(bodyParser());
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({extended: true}));
  app.use(cookieSession({secret: 'app_1'}));

  //improvement preformance
  //app.use('view cache', true);

  app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
  });

  /***********************************************
   * EtherSheet DB Client
   ***********************************************/
  var es = new EtherSheetService(config);

  // listen after setup
  es.onConnect(function(err){
    if(err) throw err;
    http_server.listen(config.port, config.host, function(){
      console.log('ethersheet is listening over http on port ' + config.port);
    });
  });

  /**********************************************
   * HTTP Routes
   *********************************************/
    //index
  app.get('/', function(req,res){
    res.render('index.ejs', {introText: config.intro_text});
  });

  //convert sheet to csv
  app.get('/s/:sheetid.csv', function(req,res){
    var sheet_id = String(req.params.sheetid);

    if(!req.cookies || !req.cookies.JSESSIONID == sheet_id){
      console.log('req.cookies', req.cookies);
      res.cookie('JSESSIONID', sheet_id, { maxAge: 900000, httpOnly: false});
      res.redirect("/s/" + sheet_id);
    }

    es.sheetToCSV(sheet_id,function(err, sheet_data){
      //res.header('content-type', 'text/csv');
      //res.render('csv.ejs',{ csv:sheet_data});
      //ISISLab fantasy
      res.header('content-type', 'text/csv; charset=utf-8');
      res.send(sheet_data);
      //End ISISLab fantasy
    });
  });

  //load up the sheet
  app.get('/s/:collection_id', function(req,res){
    var collection_id = String(req.params.collection_id);
    es.getSheetCollection(collection_id,function(err,sheet_data){
      console.log('sheet_data', sheet_data);
      if(err) return res.send(500,String(err));
      res.render('sheet.ejs',{
        channel:collection_id,
        sheet_collection:JSON.stringify(sheet_data)
      });
    });
  });

  //import csv
  app.post('/import/csv', function(req,res){
    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files){
      var csv_path = files.csv_file.path;
      var sheet_id = fields.sheet_id;
      fs.readFile(csv_path, function(err, data){
        es.createSheetFromCSV(sheet_id, data, function(err){
          if(err){
            res.send(500,err.message);
            return;
          }
          res.redirect('back');
          pub_server.refreshClients(sheet_id);
        })
      });
    });
  });

  //Upload image from a cell
  // Post files
  app.post('/upload/image', function(req, res)
  {
    res.setHeader('Content-Type', 'application/json');

    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files)
    {

      var sheet_id = fields.sheet_id;
      var image_name = files.image_file.name;

      fs.readFile(files.image_file.path, function (err, data)
      {
        /// If there's an error
        if(!image_name)
        {
          console.log("There was an error");
          res.send(JSON.stringify({ status: false, massage: "There was an error"}));
        }else{
          var dir     = __dirname +  "/uploads/" + sheet_id;
          //var thumbPath = __dirname + "/uploads/thumbs/" + imageName;
          if (!fs.existsSync(dir)){
            fs.mkdirSync(dir);
          }

          var newPath = dir + "/" + image_name;
          console.log(newPath);

          fs.writeFile(newPath, data, function (err) {
            // let's see it
            console.log("Image uploaded");
            var image_url = req.protocol + "://" + req.headers.host /*+ ":" + config.port*/ + "/images/" + sheet_id + "/" + image_name;
            res.send(JSON.stringify({ status: true, massage: "Image uploaded", image_url: image_url}));
          });
        }
      });

    });
  });

  app.get('/images/:sheet_id/:image', function (req, res) {
    res.sendFile( __dirname +  "/uploads/" +  String(req.params.sheet_id) + "/" +  String(req.params.image));
  });

  app.get('/images/:collection_id', function (req, res) {
    es.

  });

  /***********************************************
   * PubSub Server
   ***********************************************/
  var pub_server = new Transactor();
  var transactionHandler = createTransactionHandler(es);

  pub_server.onTransaction(function(channel,socket,command_string,cb){
    var c = new Command(command_string);

    if(c.getDataType()=='user' && c.getAction()=='addUser'){
      var id = c.getParams()[0].id;
      socket.es_user_id = id;
    }

    transactionHandler(c,cb);
  });

  pub_server.onClose(function(channel,socket){
    var close_msg = {
      type:'user',
      action:'removeUser',
      params:[{
        id: socket.es_user_id
      }]
    };
    var close_command = Command.serialize(close_msg);
    pub_server.broadcast(socket,channel,close_command);
  });
  pub_server.refreshClients = function(sheet_id){
    var refresh_msg = {
      type: 'sheet',
      id: sheet_id,
      action: 'refreshSheet',
      params:[]
    };
    var refresh_command = Command.serialize(refresh_msg);
    console.log('sending refresh command');
    pub_server.broadcast(null,sheet_id,refresh_command);
  };

  /***********************************************
   * Websocket Server
   ***********************************************/
  var ws_server = sockjs.createServer();

  ws_server.installHandlers(http_server,{prefix:'.*/pubsub'});

  ws_server.on('connection', function(socket){
    var channel = socket.pathname.split('/')[1];
    pub_server.addSocket(channel,socket);
  });

  return http_server;
};<commit_msg>Ethersheet server routes updates<commit_after>var http = require('http');
var express = require('express');
var sockjs = require('sockjs');
var fs = require('fs');
var Command = require('es_command');
var Transactor = require('transactor');
var EtherSheetService = require('./ethersheet_service');
var createTransactionHandler = require('./transaction_handler');
var formidable = require('formidable');

/*ISISLab code*/
var cookieParser  = require('cookie-parser');
var bodyParser    = require('body-parser');
var cookieSession = require('cookie-session');
var compression   = require('compression');
/*End ISISLab code*/

var ES_CLIENT_PATH= __dirname + '/../node_modules/es_client';
var LAYOUT_PATH = __dirname + '/layouts';

exports.createServer = function(config){

  /***********************************************
   * EtherSheet HTTP Server
   ***********************************************/
  var app = express();
  //improvement preformance
  app.use(compression());

  var http_server = http.createServer(app);

  // Server Settings
  app.set('views',LAYOUT_PATH);
  //app.use(express.logger({ format: ':method :url' }));
  app.use('/es_client',express.static(ES_CLIENT_PATH));
  /*app.use(express.bodyParser());
   app.use(express.cookieParser());*/
  app.use(cookieParser());
  //app.use(bodyParser());
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({extended: true}));
  app.use(cookieSession({secret: 'app_1'}));

  //improvement preformance
  //app.use('view cache', true);

  app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
  });

  /***********************************************
   * EtherSheet DB Client
   ***********************************************/
  var es = new EtherSheetService(config);

  // listen after setup
  es.onConnect(function(err){
    if(err) throw err;
    http_server.listen(config.port, config.host, function(){
      console.log('ethersheet is listening over http on port ' + config.port);
    });
  });

  /**********************************************
   * HTTP Routes
   *********************************************/
    //index
  app.get('/', function(req,res){
    res.render('index.ejs', {introText: config.intro_text});
  });

  //convert sheet to csv
  app.get('/s/:sheetid.csv', function(req,res){
    var sheet_id = String(req.params.sheetid);

    if(!req.cookies || !req.cookies.JSESSIONID == sheet_id){
      console.log('req.cookies', req.cookies);
      res.cookie('JSESSIONID', sheet_id, { maxAge: 900000, httpOnly: false});
      res.redirect("/s/" + sheet_id);
    }

    es.sheetToCSV(sheet_id,function(err, sheet_data){
      //res.header('content-type', 'text/csv');
      //res.render('csv.ejs',{ csv:sheet_data});
      //ISISLab fantasy
      res.header('content-type', 'text/csv; charset=utf-8');
      res.send(sheet_data);
      //End ISISLab fantasy
    });
  });

  //load up the sheet
  app.get('/s/:collection_id', function(req,res){
    var collection_id = String(req.params.collection_id);
    es.getSheetCollection(collection_id,function(err,sheet_data){
      console.log('sheet_data', sheet_data);
      if(err) return res.send(500,String(err));
      res.render('sheet.ejs',{
        channel:collection_id,
        sheet_collection:JSON.stringify(sheet_data)
      });
    });
  });

  //import csv
  app.post('/import/csv', function(req,res){
    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files){
      var csv_path = files.csv_file.path;
      var sheet_id = fields.sheet_id;
      fs.readFile(csv_path, function(err, data){
        es.createSheetFromCSV(sheet_id, data, function(err){
          if(err){
            res.send(500,err.message);
            return;
          }
          res.redirect('back');
          pub_server.refreshClients(sheet_id);
        })
      });
    });
  });

  //Upload image from a cell
  // Post files
  app.post('/upload/image', function(req, res)
  {
    res.setHeader('Content-Type', 'application/json');

    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files)
    {

      var sheet_id = fields.sheet_id;
      var image_name = files.image_file.name;

      fs.readFile(files.image_file.path, function (err, data)
      {
        /// If there's an error
        if(!image_name)
        {
          console.log("There was an error");
          res.send(JSON.stringify({ status: false, massage: "There was an error"}));
        }else{
          var dir     = __dirname +  "/uploads/" + sheet_id;
          //var thumbPath = __dirname + "/uploads/thumbs/" + imageName;
          if (!fs.existsSync(dir)){
            fs.mkdirSync(dir);
          }

          var newPath = dir + "/" + image_name;
          console.log(newPath);

          fs.writeFile(newPath, data, function (err) {
            // let's see it
            console.log("Image uploaded");
            var image_url = req.protocol + "://" + req.headers.host /*+ ":" + config.port*/ + "/images/" + sheet_id + "/" + image_name;
            res.send(JSON.stringify({ status: true, massage: "Image uploaded", image_url: image_url}));
          });
        }
      });

    });
  });

  app.get('/images/:sheet_id/:image', function (req, res) {
    res.sendFile( __dirname +  "/uploads/" +  String(req.params.sheet_id) + "/" +  String(req.params.image));
  });

  /*app.get('/images/:collection_id', function (req, res) {
    es.

  });*/

  /***********************************************
   * PubSub Server
   ***********************************************/
  var pub_server = new Transactor();
  var transactionHandler = createTransactionHandler(es);

  pub_server.onTransaction(function(channel,socket,command_string,cb){
    var c = new Command(command_string);

    if(c.getDataType()=='user' && c.getAction()=='addUser'){
      var id = c.getParams()[0].id;
      socket.es_user_id = id;
    }

    transactionHandler(c,cb);
  });

  pub_server.onClose(function(channel,socket){
    var close_msg = {
      type:'user',
      action:'removeUser',
      params:[{
        id: socket.es_user_id
      }]
    };
    var close_command = Command.serialize(close_msg);
    pub_server.broadcast(socket,channel,close_command);
  });
  pub_server.refreshClients = function(sheet_id){
    var refresh_msg = {
      type: 'sheet',
      id: sheet_id,
      action: 'refreshSheet',
      params:[]
    };
    var refresh_command = Command.serialize(refresh_msg);
    console.log('sending refresh command');
    pub_server.broadcast(null,sheet_id,refresh_command);
  };

  /***********************************************
   * Websocket Server
   ***********************************************/
  var ws_server = sockjs.createServer();

  ws_server.installHandlers(http_server,{prefix:'.*/pubsub'});

  ws_server.on('connection', function(socket){
    var channel = socket.pathname.split('/')[1];
    pub_server.addSocket(channel,socket);
  });

  return http_server;
};<|endoftext|>


<commit_before>require(["jquery", "codeMirror", "csrfToken", "bsAlert"], function ($, codeMirror, csrfTokenHeader, bsAlert) {
    var codeEditor = codeMirror($("#code-editor")[0], "text/x-csrc");
    var language = $("input[name='language'][checked]").val();
    var submissionId;

    $("input[name='language']").change(function () {
        language = this.value;
        var languageTypes = {"1": "text/x-csrc", "2": "text/x-c++src", "3": "text/x-java"};
        codeEditor.setOption("mode", languageTypes[language]);
    });

    $("#show-more-btn").click(function () {
        $(".hide").attr("class", "problem-section");
        $("#show-more-btn").hide();
    });

    function showLoading() {
        $("#submit-code-button").attr("disabled", "disabled");
        $("#loading-gif").show();
    }

    function hideLoading() {
        $("#submit-code-button").removeAttr("disabled");
        $("#loading-gif").hide();
    }

    function getResultHtml(data) {
        // 0 结果正确 1 运行错误 2 超时 3 超内存 4 编译错误
        // 5 格式错误 6 结果错误 7 系统错误 8 等待判题
        var results = {
            0: {"alert_class": "success", message: "Accepted"},
            1: {"alert_class": "danger", message: "Runtime Error"},
            2: {"alert_class": "warning", message: "Time Limit Exceeded"},
            3: {"alert_class": "warning", message: "Memory Limit Exceeded"},
            4: {"alert_class": "danger", message: "Compile Error"},
            5: {"alert_class": "warning", message: "Format Error"},
            6: {"alert_class": "danger", message: "Wrong Answer"},
            7: {"alert_class": "danger", message: "System Error"},
            8: {"alert_class": "info", message: "Waiting"}
        };

        var html = '
' +
            '
' +
            results[data.result].message +
            '!   ';
        if (!data.result) {
            html += "CPU time: " + data.accepted_answer_info.time + "ms   ";
        }
        html += ('查看详情

');

        return html;
    }

    function getResult() {
        $.ajax({
            url: "/api/submission/?submission_id=" + submissionId,
            method: "get",
            dataType: "json",
            success: function (data) {
                if (!data.code) {
                    // 8是还没有完成判题
                    if (data.data.result == 8) {
                        // 1秒之后重新去获取
                        setTimeout(getResult, 1000);
                    }
                    else {
                        hideLoading();
                        $("#result").html(getResultHtml(data.data));
                    }
                }
                else {
                    bsAlert(data.data);
                    hideLoading();
                }
            }
        })
    }

    $("#submit-code-button").click(function () {
        var problemId = window.location.pathname.split("/")[2];
        var code = codeEditor.getValue();

        showLoading();

        if(!code.trim()){
            bs_alert("请填写代码！");
            hideLoading();
            return false;
        }

        $("#result").html("");

        $.ajax({
            beforeSend: csrfTokenHeader,
            url: "/api/submission/",
            method: "post",
            data: JSON.stringify({
                problem_id: problemId,
                language: language,
                code: codeEditor.getValue()
            }),
            contentType: "application/json",
            success: function (data) {
                if (!data.code) {
                    submissionId = data.data.submission_id;
                    // 获取到id 之后2秒去查询一下判题结果
                    setTimeout(getResult, 2000);
                }
                else {
                    bs_alert(data.data);
                    hideLoading();
                }
            }
        });

    });

    $.ajax({
        url : "/api/user/",
        method: "get",
        dataType: "json",
        success: function(data){
            if(data.code){
                $("#submit-code-button").attr("disabled", "disabled");
                $("#result").html('

请先登录!

');
            }
        }
    })
});
<commit_msg>增加对判题超时的提示<commit_after>require(["jquery", "codeMirror", "csrfToken", "bsAlert"], function ($, codeMirror, csrfTokenHeader, bsAlert) {
    var codeEditor = codeMirror($("#code-editor")[0], "text/x-csrc");
    var language = $("input[name='language'][checked]").val();
    var submissionId;

    $("input[name='language']").change(function () {
        language = this.value;
        var languageTypes = {"1": "text/x-csrc", "2": "text/x-c++src", "3": "text/x-java"};
        codeEditor.setOption("mode", languageTypes[language]);
    });

    $("#show-more-btn").click(function () {
        $(".hide").attr("class", "problem-section");
        $("#show-more-btn").hide();
    });

    function showLoading() {
        $("#submit-code-button").attr("disabled", "disabled");
        $("#loading-gif").show();
    }

    function hideLoading() {
        $("#submit-code-button").removeAttr("disabled");
        $("#loading-gif").hide();
    }

    function getResultHtml(data) {
        // 0 结果正确 1 运行错误 2 超时 3 超内存 4 编译错误
        // 5 格式错误 6 结果错误 7 系统错误 8 等待判题
        var results = {
            0: {"alert_class": "success", message: "Accepted"},
            1: {"alert_class": "danger", message: "Runtime Error"},
            2: {"alert_class": "warning", message: "Time Limit Exceeded"},
            3: {"alert_class": "warning", message: "Memory Limit Exceeded"},
            4: {"alert_class": "danger", message: "Compile Error"},
            5: {"alert_class": "warning", message: "Format Error"},
            6: {"alert_class": "danger", message: "Wrong Answer"},
            7: {"alert_class": "danger", message: "System Error"},
            8: {"alert_class": "info", message: "Waiting"}
        };

        var html = '
' +
            '
' +
            results[data.result].message +
            '!   ';
        if (!data.result) {
            html += "CPU time: " + data.accepted_answer_info.time + "ms   ";
        }
        html += ('查看详情

');

        return html;
    }

    var counter = 0;

    function getResult() {
        if(counter++ > 10){
            hideLoading();
            bsAlert("抱歉，服务器可能出现了故障，请稍后到我的提交列表中查看");
            return;
        }
        $.ajax({
            url: "/api/submission/?submission_id=" + submissionId,
            method: "get",
            dataType: "json",
            success: function (data) {
                if (!data.code) {
                    // 8是还没有完成判题
                    if (data.data.result == 8) {
                        // 1秒之后重新去获取
                        setTimeout(getResult, 1000);
                    }
                    else {
                        hideLoading();
                        $("#result").html(getResultHtml(data.data));
                    }
                }
                else {
                    bsAlert(data.data);
                    hideLoading();
                }
            }
        })
    }

    $("#submit-code-button").click(function () {
        var problemId = window.location.pathname.split("/")[2];
        var code = codeEditor.getValue();

        showLoading();

        if(!code.trim()){
            bsAlert("请填写代码！");
            hideLoading();
            return false;
        }

        $("#result").html("");

        $.ajax({
            beforeSend: csrfTokenHeader,
            url: "/api/submission/",
            method: "post",
            data: JSON.stringify({
                problem_id: problemId,
                language: language,
                code: codeEditor.getValue()
            }),
            contentType: "application/json",
            success: function (data) {
                if (!data.code) {
                    submissionId = data.data.submission_id;
                    // 获取到id 之后2秒去查询一下判题结果
                    setTimeout(getResult, 2000);
                }
                else {
                    bs_alert(data.data);
                    hideLoading();
                }
            }
        });

    });

    $.ajax({
        url : "/api/user/",
        method: "get",
        dataType: "json",
        success: function(data){
            if(data.code){
                $("#submit-code-button").attr("disabled", "disabled");
                $("#result").html('

请先登录!

');
            }
        }
    })
});
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var tape = require( 'tape' );
var floor = require( '@stdlib/math/base/special/floor' );
var randu = require( '@stdlib/math/base/random/randu' );

var dasum;
var opts;

opts = {};
try {
	dasum = require( './../lib/dasum.native.js' );
} catch ( error ) { // eslint-disable-line no-unused-vars
	// Unable to load native addon:
	opts.skip = true;
}

// TESTS //

tape( 'main export is a function', opts, function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof dasum, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function computes the sum of absolute values', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );
	y = dasum( x.length, x, 1 );

	t.strictEqual( y, 15.0, 'returns 15' );
	t.end();
});

tape( 'the function supports an `x` stride', opts, function test( t ) {
	var x;
	var y;
	var N;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );
	N = 3;

	y = dasum( N, x, 2 );

	t.strictEqual( y, 9.0, 'returns 9' );
	t.end();
});

tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `0`', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );

	y = dasum( 0, x, 1 );

	t.strictEqual( y, 0.0, 'returns 0' );
	t.end();
});

tape( 'if provided a `stride` parameter less than or equal to `0`, the function returns `0`', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );

	y = dasum( x.length, x, -1 );

	t.strictEqual( y, 0.0, 'returns 0' );
	t.end();
});

tape( 'the function supports view offsets', opts, function test( t ) {
	var x0;
	var x1;
	var y;
	var N;

	// Initial array...
	x0 = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0, -6.0 ] );

	// Create an offset view...
	x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // begin at 2nd element

	N = floor( x0.length / 2 );

	y = dasum( N, x1, 2 );

	t.strictEqual( y, 12.0, 'returns 12' );
	t.end();
});

tape( 'if the stride equals `1`, the function efficiently sums the absolute values', opts, function test( t ) {
	var sign;
	var x;
	var y;
	var i;

	x = new Float64Array( 100 );
	for ( i = 0; i < x.length; i++ ) {
		sign = randu();
		if ( sign < 0.5 ) {
			sign = -1.0;
		} else {
			sign = 1.0;
		}
		x[ i ] = sign * (i+1);
	}

	y = dasum( x.length, x, 1 );

	// Compare to closed-form formula:
	t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected sum' );

	x = new Float64Array( 240 );
	for ( i = 0; i < x.length; i++ ) {
		sign = randu();
		if ( sign < 0.5 ) {
			sign = -1.0;
		} else {
			sign = 1.0;
		}
		x[ i ] = sign * (i+1);
	}

	y = dasum( x.length, x, 1 );

	// Compare to closed-form formula:
	t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected sum' );

	t.end();
});
<commit_msg>Remove try/catch<commit_after>'use strict';

// MODULES //

var tape = require( 'tape' );
var floor = require( '@stdlib/math/base/special/floor' );
var randu = require( '@stdlib/math/base/random/randu' );
var hasNative = require( './../lib/has_native.js' );

// VARIABLES //

var dasum = ( hasNative ) ? require( './../lib/dasum.native.js' ) : false;
var opts = {
	'skip': !!dasum
};

// TESTS //

tape( 'main export is a function', opts, function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof dasum, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function computes the sum of absolute values', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );
	y = dasum( x.length, x, 1 );

	t.strictEqual( y, 15.0, 'returns 15' );
	t.end();
});

tape( 'the function supports an `x` stride', opts, function test( t ) {
	var x;
	var y;
	var N;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );
	N = 3;

	y = dasum( N, x, 2 );

	t.strictEqual( y, 9.0, 'returns 9' );
	t.end();
});

tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `0`', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );

	y = dasum( 0, x, 1 );

	t.strictEqual( y, 0.0, 'returns 0' );
	t.end();
});

tape( 'if provided a `stride` parameter less than or equal to `0`, the function returns `0`', opts, function test( t ) {
	var x;
	var y;

	x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] );

	y = dasum( x.length, x, -1 );

	t.strictEqual( y, 0.0, 'returns 0' );
	t.end();
});

tape( 'the function supports view offsets', opts, function test( t ) {
	var x0;
	var x1;
	var y;
	var N;

	// Initial array...
	x0 = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0, -6.0 ] );

	// Create an offset view...
	x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // begin at 2nd element

	N = floor( x0.length / 2 );

	y = dasum( N, x1, 2 );

	t.strictEqual( y, 12.0, 'returns 12' );
	t.end();
});

tape( 'if the stride equals `1`, the function efficiently sums the absolute values', opts, function test( t ) {
	var sign;
	var x;
	var y;
	var i;

	x = new Float64Array( 100 );
	for ( i = 0; i < x.length; i++ ) {
		sign = randu();
		if ( sign < 0.5 ) {
			sign = -1.0;
		} else {
			sign = 1.0;
		}
		x[ i ] = sign * (i+1);
	}

	y = dasum( x.length, x, 1 );

	// Compare to closed-form formula:
	t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected sum' );

	x = new Float64Array( 240 );
	for ( i = 0; i < x.length; i++ ) {
		sign = randu();
		if ( sign < 0.5 ) {
			sign = -1.0;
		} else {
			sign = 1.0;
		}
		x[ i ] = sign * (i+1);
	}

	y = dasum( x.length, x, 1 );

	// Compare to closed-form formula:
	t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected sum' );

	t.end();
});
<|endoftext|>