<commit_before>(function(){

    ///// Constants

    var CONST = {
        BOX_SIZE: 25,
        LIGHT_GRAY: '#aaaaaa',
        LIGHTER_GRAY: '#dddddd',
        DOT_SIZE: 1,
        DRAWERS_COUNT: 15,
        DRAW_SPEED: 0.1,
        FILL_COLORS: '#F0E3DF #E3DFF0 #DFEDF0 #DFF0DF'.split(' ')
    };

    ///// Classes

    var Dot = function( x, y ) {
        this.id = 'd-x' + x + 'y' + y;
        this.x = x;
        this.y = y;
    };

    Dot.prototype = {
        draw: function(ctx) {
            var coords = this.coords();

            ctx.fillStyle = CONST.LIGHT_GRAY;
            ctx.fillRect( coords.x, coords.y, CONST.DOT_SIZE, CONST.DOT_SIZE );
            return this;
        },
        coords: function() {
            return {
                x: this.x * CONST.BOX_SIZE,
                y: this.y * CONST.BOX_SIZE
            };
        }
    };

    var Line = function( dot1, dot2 ) {
        this.id = _.uniqueId('l');
        this.dot1 = dot1;
        this.dot2 = dot2;
        this.boxes = [];
        this.drawn = false;
    };

    Line.prototype = {
        draw: function(ctx) {
            var coords1 = this.dot1.coords();
            var coords2 = this.dot2.coords();

            ctx.strokeStyle = CONST.LIGHTER_GRAY;
            ctx.beginPath();
            ctx.moveTo(coords1.x, coords1.y);
            ctx.lineTo(coords2.x, coords2.y);
            ctx.stroke();

            this.drawn = true;
        },

        setPointerToBox: function(box) {
            this.boxes.push(box);
        },

        alertBoxes: function() {
            var len = this.boxes.length;
            while (len--) {
                this.boxes[len].lineDrawn();
            }
        }
    };

    var Box = function( dot1, dot2, dot3, dot4 ) {
        this.id = _.uniqueId('b');
        this.dots = [];

        this.lines = [
            lines.get(dot1, dot2),
            lines.get(dot2, dot3),
            lines.get(dot3, dot4),
            lines.get(dot4, dot1)
        ];

        this.lines = _.compact(this.lines);
        if (this.lines.length !== 4) {
            return;
        }

        // set pointers on the lines back to this box
        // and setup the dots array
        for (var i = 0, len = this.lines.length; i < len; i++) {
            this.lines[i].setPointerToBox(this);
            this.dots.push(this.lines[i].dot1);
            this.dots.push(this.lines[i].dot2);
        }

        this.dots = _.uniq(this.dots);
    };

    Box.prototype = {
        // returns the upper LH dot of the box
        getOriginDot: function() {
            var originDot;
            var len = this.dots.length;
            while (len--) {
                var dot = this.dots[len];
                originDot = originDot || dot;
                if (dot.x < originDot.x || dot.y < originDot.y) {
                    originDot = dot;
                }
            }
            return originDot;
        },

        checkDrawnLines: function() {
            var len = this.lines.length;
            while (len--) {
                if (!this.lines[len].drawn) { return false; }
            }
            return true;
        },

        fill: function(ctx) {
            /// get the upper LH dot
            var dot = this.getOriginDot();
            var coords = dot.coords();
            ctx.beginPath();
            ctx.rect(coords.x, coords.y, CONST.BOX_SIZE, CONST.BOX_SIZE);
            ctx.fillStyle = random(CONST.FILL_COLORS);
            ctx.fill();
        },

        lineDrawn: function() {
            if (this.checkDrawnLines()) {
                this.fill(DOTS);
            }
        }
    };

    ///// Dots Collection

    var dots = (function(){

        var _dots = {};
        var _length = 0;
        var _dots_array = [];

        function add( dot ) {
            if (!dot) { return; }
            if (typeof dot.x !== 'number' || typeof dot.y !== 'number') { return; }

            var x = 'x' + dot.x;
            var y = 'y' + dot.y;

            _dots[x] = _dots[x] || {};
            _dots[x][y] = dot;

            _dots_array.push(dot);

            _length += 1;
        }

        function get( x, y ) {

            if (typeof x !== 'number' || typeof y !== 'number') {
                return _dots_array;
            }

            x = 'x' + x;
            y = 'y' + y;

            return _dots[x] && _dots[x][y];
        }

        function length() {
            return _length;
        }

        // returns two neighbors (the neighbor below and to the right)
        function getNeighborsOf(dot) {
            var neighbors = [];
            neighbors.push( get(dot.x + 1, dot.y) );
            neighbors.push( get(dot.x, dot.y + 1) );
            return neighbors;
        }

        // returns all four neighbors)
        function getAllNeighborsOf(dot) {
            var neighbors = [];
            neighbors.push( get(dot.x + 1, dot.y) );
            neighbors.push( get(dot.x, dot.y + 1) );
            neighbors.push( get(dot.x - 1, dot.y) );
            neighbors.push( get(dot.x, dot.y - 1) );
            return neighbors;
        }

        // with 'dot' as the upper LH corner, get the next 3 dots that make up the box
        function getFourCorners(dot) {
            var corners = [
                dot,
                get( dot.x + 1, dot.y ),
                get( dot.x + 1, dot.y + 1 ),
                get( dot.x, dot.y + 1)
            ];
            return _.compact(corners);
        }

        function reset() {
            _dots = {};
            _length = 0;
            _dots_array = [];
        }

        return {
            add: add,
            get: get,
            length: length,
            getNeighborsOf: getNeighborsOf,
            getAllNeighborsOf: getAllNeighborsOf,
            getFourCorners: getFourCorners,
            reset: reset
        };
    })();

    ///// Lines Collection

    var lines = (function(){

        var _lines = {};
        var _length = 0;
        var _lines_array = [];

        function add( line ) {
            var dot1 = line.dot1;
            var dot2 = line.dot2;

            if (!dot1 || !dot2) { return; }

            _lines[dot1.id] = _lines[dot1.id] || {};
            _lines[dot1.id][dot2.id] = line;

            _lines_array.push(line);

            _length += 1;
        }

        // doesn't matter what order dot1 and dot2 are passed in
        function get( dot1, dot2 ) {

            if (!dot1 || !dot2) {
                return _lines_array;
            }

            if (_lines[dot1.id] && _lines[dot1.id][dot2.id]) {
                return _lines[dot1.id][dot2.id];
            } else {
                return _lines[dot2.id] && _lines[dot2.id][dot1.id];
            }

        }

        function length() {
            return _length;
        }

        function reset() {
            _lines = {};
            _length = 0;
            _lines_array = [];
        }

        return {
            add: add,
            get: get,
            length: length,
            reset: reset
        };
    })();

    ///// Drawers Collection

    var drawers = (function(){

        var _drawers = [];
        var _lines = [];

        function create( x, y ) {
            // if x and y are coords, then get the dot from the collection
            // otherwise, assume that x is a dot
            var dot = (typeof x === 'number' && typeof y === 'number') ? dots.get(x, y) : x;

            var drawer = new Drawer( dot );
            _drawers.push( drawer );

        }

        // check to see if the line passed in is already in the lines array
        function checkLines(line) {
            if (!line || !line.id) return false;
            for (var i = 0, len = _lines.length; i < len; i++) {
                if (line.id === _lines[i].id) return true;
            }
            return false;
        }

        function get() {
            return _drawers;
        }

        function removeDrawer( drawer ) {
            var i = _.indexOf(_drawers, drawer);
            _drawers.splice( i, 1);
        }

        function getAlive() {
            return _.where(_drawers, { dead: false });
        }

        function reset() {
            _drawers = [];
            _lines = [];
        }

        ///// Drawer Class

        var Animator = function(dot1, dot2, line, drawer) {
            this.drawer = drawer;
            this.line = line;
            this.destDot = dot2;
            this.next = dot1.coords();
            this.coords2 = dot2.coords();
            this.cur = {};
            this.complete = false;
        };

        Animator.prototype = {
            update: function() {
                if (this.complete) return;

                this.cur = {
                    x: this.next.x,
                    y: this.next.y
                };

                var dx = (this.coords2.x - this.cur.x) * CONST.DRAW_SPEED;
                var dy = (this.coords2.y - this.cur.y) * CONST.DRAW_SPEED;

                if (abs(dx) < 1 && abs(dy) < 1) {
                    this.next = this.coords2;
                    this.draw(DOTS);
                    this.drawer.completedAnimation();
                    return;
                }

                this.next = {
                    x: this.cur.x + dx,
                    y: this.cur.y + dy
                };

                this.draw(DOTS);
            },

            draw: function(ctx) {

                ctx.strokeStyle = CONST.LIGHTER_GRAY;
                ctx.beginPath();
                ctx.moveTo(this.cur.x, this.cur.y);
                ctx.lineTo(this.next.x, this.next.y);
                ctx.stroke();

            }
        };

        var Drawer = function( startingDot ) {
            this.location = startingDot;
            this.dead = false;
            this.animating = false;
            this.id = _.uniqueId();
        };

        Drawer.prototype = {
            drawToNeighbor: function() {
                if (this.dead) return;

                if (this.animator) {
                    this.animator.update();
                    return;
                }

                var current = this.location;

                var neighbors = dots.getAllNeighborsOf(current);

                var someLines = _.map(neighbors, function(dot){
                    if (!dot) return false;
                    var line = lines.get(dot, current);
                    if (!line) return false;
                    if (checkLines(line)) return false;
                    return line;
                });

                someLines = _.compact(someLines);

                if (!someLines.length) {
                    return this.remove();
                }

                var i = random(someLines.length) | 0;
                var line = someLines[i];

                _lines.push(line);

                var destDot = (line.dot1 === this.location) ? line.dot2 : line.dot1;
                this.animator = new Animator(this.location, destDot, line, this);

            },
            completedAnimation: function() {
                this.location = this.animator.destDot;
                this.animator.line.drawn = true;
                this.animator.line.alertBoxes();
                this.animator = null;
            },
            remove: function() {
                this.dead = true;
                // removeDrawer(this);
            }
        };

        return {
            create: create,
            get: get,
            reset: reset,
            getAlive: getAlive
        };
    })();

    var boxes = [];

    ///// Start Up

    var DOTS = Sketch.create({
        container: document.getElementById( 'container' ),
        autostart: false,
        autoclear: false
    });

    DOTS.setup = function() {

        ///// build the dots

        var x_limit = ceil(DOTS.width / CONST.BOX_SIZE);
        var y_limit = ceil(DOTS.height / CONST.BOX_SIZE);

        for (var x = 0; x < x_limit; x++) {
            for (var y = 0; y < y_limit; y++) {
                dots.add( new Dot( x, y ) );
            }
        }

        ///// build the lines

        var allDots = dots.get();
        for (var i = 0, leng = allDots.length; i < leng; i++) {

            var dot = allDots[i];
            var neighbors = dots.getNeighborsOf( dot );

            lines.add( new Line(dot, neighbors[0]) );
            lines.add( new Line(dot, neighbors[1]) );

        }

        ///// build the boxes
        for (var p = 0; p < leng; p++) {
            var ds = dots.getFourCorners( allDots[p] );
            if (ds.length !== 4) { continue; }
            boxes.push(new Box( ds[0], ds[1], ds[2], ds[3] ) );
        }

        ///// start some drawers
        for (var k = 0; k < CONST.DRAWERS_COUNT; k++) {
            var d = random(allDots);
            drawers.create( d.x, d.y );
        }

    };

    DOTS.update = function() {
        if (!drawers.getAlive().length) {
            DOTS.reset();
        }
    };

    DOTS.draw = function() {

        var allDots = dots.get();
        var leng = allDots.length;
        while (leng--) {
            allDots[leng].draw( DOTS );
        }

        var allDrawers = drawers.get();
        for (var i = 0, len = allDrawers.length; i < len; i++) {
            allDrawers[i].drawToNeighbor();
        }

    };

    DOTS.reset = function() {
        DOTS.stop();
        dots.reset();
        lines.reset();
        drawers.reset();
        boxes = [];
        DOTS.clear();
        DOTS.setup();
        DOTS.start();
    };

    ////// Setup dat.GUI

    var gui = new dat.GUI();
    gui.add(CONST, 'DRAWERS_COUNT', 1, 150).step(1).onFinishChange( changeHandler );
    gui.add(CONST, 'BOX_SIZE', 5, 80).step(1).onFinishChange( changeHandler );
    gui.add(CONST, 'DRAW_SPEED', 0.05, 1).step(0.01);
    gui.add(DOTS, 'reset');

    function changeHandler(val) {
        DOTS.reset();
    }

    ///// Exports

    window.DOTS = DOTS;
    window.dots = dots;
    window.lines = lines;
    window.drawers = drawers;

})();<commit_msg>better easing and color control<commit_after>(function(){

    ///// Constants

    var CONST = {
        BOX_SIZE: 25,
        LIGHT_GRAY: '#aaaaaa',
        LIGHTER_GRAY: '#dddddd',
        DOT_SIZE: 1,
        DRAWERS_COUNT: 15,
        DRAW_SPEED: 0.1,
        MULTI: '#F0E3DF #E3DFF0 #DFEDF0 #DFF0DF'.split(' '),
        GRAYSCALE: '#d8d8d8 #e0e0e0 #e8e8e8 #f0f0f0'.split(' '),
        MONOBLUE: 'rgba(115,129,158,0.6) rgba(115,129,158,0.45) rgba(115,129,158,0.3) rgba(115,129,158,0.1)'.split(' ')
    };

    ///// Classes

    var Dot = function( x, y ) {
        this.id = 'd-x' + x + 'y' + y;
        this.x = x;
        this.y = y;
    };

    Dot.prototype = {
        draw: function(ctx) {
            var coords = this.coords();

            ctx.fillStyle = CONST.LIGHT_GRAY;
            ctx.fillRect( coords.x, coords.y, CONST.DOT_SIZE, CONST.DOT_SIZE );
            return this;
        },
        coords: function() {
            return {
                x: this.x * CONST.BOX_SIZE,
                y: this.y * CONST.BOX_SIZE
            };
        }
    };

    var Line = function( dot1, dot2 ) {
        this.id = _.uniqueId('l');
        this.dot1 = dot1;
        this.dot2 = dot2;
        this.boxes = [];
        this.drawn = false;
    };

    Line.prototype = {
        draw: function(ctx) {
            var coords1 = this.dot1.coords();
            var coords2 = this.dot2.coords();

            ctx.strokeStyle = CONST.LIGHTER_GRAY;
            ctx.beginPath();
            ctx.moveTo(coords1.x, coords1.y);
            ctx.lineTo(coords2.x, coords2.y);
            ctx.stroke();

            this.drawn = true;
        },

        setPointerToBox: function(box) {
            this.boxes.push(box);
        },

        alertBoxes: function() {
            var len = this.boxes.length;
            while (len--) {
                this.boxes[len].lineDrawn();
            }
        }
    };

    var Box = function( dot1, dot2, dot3, dot4 ) {
        this.id = _.uniqueId('b');
        this.dots = [];

        this.lines = [
            lines.get(dot1, dot2),
            lines.get(dot2, dot3),
            lines.get(dot3, dot4),
            lines.get(dot4, dot1)
        ];

        this.lines = _.compact(this.lines);
        if (this.lines.length !== 4) {
            return;
        }

        // set pointers on the lines back to this box
        // and setup the dots array
        for (var i = 0, len = this.lines.length; i < len; i++) {
            this.lines[i].setPointerToBox(this);
            this.dots.push(this.lines[i].dot1);
            this.dots.push(this.lines[i].dot2);
        }

        this.dots = _.uniq(this.dots);
    };

    Box.prototype = {
        // returns the upper LH dot of the box
        getOriginDot: function() {
            var originDot;
            var len = this.dots.length;
            while (len--) {
                var dot = this.dots[len];
                originDot = originDot || dot;
                if (dot.x < originDot.x || dot.y < originDot.y) {
                    originDot = dot;
                }
            }
            return originDot;
        },

        checkDrawnLines: function() {
            var len = this.lines.length;
            while (len--) {
                if (!this.lines[len].drawn) { return false; }
            }
            return true;
        },

        fill: function(ctx) {
            /// get the upper LH dot
            var dot = this.getOriginDot();
            var coords = dot.coords();
            ctx.beginPath();
            ctx.rect(coords.x, coords.y, CONST.BOX_SIZE, CONST.BOX_SIZE);
            ctx.fillStyle = random(DOTS.FILL_COLORS);
            ctx.fill();
        },

        lineDrawn: function() {
            if (this.checkDrawnLines()) {
                this.fill(DOTS);
            }
        }
    };

    ///// Dots Collection

    var dots = (function(){

        var _dots = {};
        var _length = 0;
        var _dots_array = [];

        function add( dot ) {
            if (!dot) { return; }
            if (typeof dot.x !== 'number' || typeof dot.y !== 'number') { return; }

            var x = 'x' + dot.x;
            var y = 'y' + dot.y;

            _dots[x] = _dots[x] || {};
            _dots[x][y] = dot;

            _dots_array.push(dot);

            _length += 1;
        }

        function get( x, y ) {

            if (typeof x !== 'number' || typeof y !== 'number') {
                return _dots_array;
            }

            x = 'x' + x;
            y = 'y' + y;

            return _dots[x] && _dots[x][y];
        }

        function length() {
            return _length;
        }

        // returns two neighbors (the neighbor below and to the right)
        function getNeighborsOf(dot) {
            var neighbors = [];
            neighbors.push( get(dot.x + 1, dot.y) );
            neighbors.push( get(dot.x, dot.y + 1) );
            return neighbors;
        }

        // returns all four neighbors)
        function getAllNeighborsOf(dot) {
            var neighbors = [];
            neighbors.push( get(dot.x + 1, dot.y) );
            neighbors.push( get(dot.x, dot.y + 1) );
            neighbors.push( get(dot.x - 1, dot.y) );
            neighbors.push( get(dot.x, dot.y - 1) );
            return neighbors;
        }

        // with 'dot' as the upper LH corner, get the next 3 dots that make up the box
        function getFourCorners(dot) {
            var corners = [
                dot,
                get( dot.x + 1, dot.y ),
                get( dot.x + 1, dot.y + 1 ),
                get( dot.x, dot.y + 1)
            ];
            return _.compact(corners);
        }

        function reset() {
            _dots = {};
            _length = 0;
            _dots_array = [];
        }

        return {
            add: add,
            get: get,
            length: length,
            getNeighborsOf: getNeighborsOf,
            getAllNeighborsOf: getAllNeighborsOf,
            getFourCorners: getFourCorners,
            reset: reset
        };
    })();

    ///// Lines Collection

    var lines = (function(){

        var _lines = {};
        var _length = 0;
        var _lines_array = [];

        function add( line ) {
            var dot1 = line.dot1;
            var dot2 = line.dot2;

            if (!dot1 || !dot2) { return; }

            _lines[dot1.id] = _lines[dot1.id] || {};
            _lines[dot1.id][dot2.id] = line;

            _lines_array.push(line);

            _length += 1;
        }

        // doesn't matter what order dot1 and dot2 are passed in
        function get( dot1, dot2 ) {

            if (!dot1 || !dot2) {
                return _lines_array;
            }

            if (_lines[dot1.id] && _lines[dot1.id][dot2.id]) {
                return _lines[dot1.id][dot2.id];
            } else {
                return _lines[dot2.id] && _lines[dot2.id][dot1.id];
            }

        }

        function length() {
            return _length;
        }

        function reset() {
            _lines = {};
            _length = 0;
            _lines_array = [];
        }

        return {
            add: add,
            get: get,
            length: length,
            reset: reset
        };
    })();

    ///// Drawers Collection

    var drawers = (function(){

        var _drawers = [];
        var _lines = [];

        function create( x, y ) {
            // if x and y are coords, then get the dot from the collection
            // otherwise, assume that x is a dot
            var dot = (typeof x === 'number' && typeof y === 'number') ? dots.get(x, y) : x;

            var drawer = new Drawer( dot );
            _drawers.push( drawer );

        }

        // check to see if the line passed in is already in the lines array
        function checkLines(line) {
            if (!line || !line.id) return false;
            for (var i = 0, len = _lines.length; i < len; i++) {
                if (line.id === _lines[i].id) return true;
            }
            return false;
        }

        function get() {
            return _drawers;
        }

        function removeDrawer( drawer ) {
            var i = _.indexOf(_drawers, drawer);
            _drawers.splice( i, 1);
        }

        function getAlive() {
            return _.where(_drawers, { dead: false });
        }

        function reset() {
            _drawers = [];
            _lines = [];
        }

        ///// Drawer Class

        var Animator = function(dot1, dot2, line, drawer) {
            this.drawer = drawer;
            this.line = line;
            this.destDot = dot2;
            this.next = dot1.coords();
            this.coords2 = dot2.coords();
            this.cur = {};
            this.complete = false;
        };

        Animator.prototype = {
            update: function() {
                if (this.complete) return;

                this.cur = {
                    x: this.next.x,
                    y: this.next.y
                };

                var dx = (this.coords2.x - this.cur.x) * CONST.DRAW_SPEED;
                var dy = (this.coords2.y - this.cur.y) * CONST.DRAW_SPEED;

                if (abs(dx) < 0.05 && abs(dy) < 0.05) {
                    this.next = this.coords2;
                    this.draw(DOTS);
                    this.drawer.completedAnimation();
                    return;
                }

                this.next = {
                    x: this.cur.x + dx,
                    y: this.cur.y + dy
                };

                this.draw(DOTS);
            },

            draw: function(ctx) {

                ctx.strokeStyle = CONST.LIGHTER_GRAY;
                ctx.beginPath();
                ctx.moveTo(this.cur.x, this.cur.y);
                ctx.lineTo(this.next.x, this.next.y);
                ctx.stroke();

            }
        };

        var Drawer = function( startingDot ) {
            this.location = startingDot;
            this.dead = false;
            this.animating = false;
            this.id = _.uniqueId();
        };

        Drawer.prototype = {
            drawToNeighbor: function() {
                if (this.dead) return;

                if (this.animator) {
                    this.animator.update();
                    return;
                }

                var current = this.location;

                var neighbors = dots.getAllNeighborsOf(current);

                var someLines = _.map(neighbors, function(dot){
                    if (!dot) return false;
                    var line = lines.get(dot, current);
                    if (!line) return false;
                    if (checkLines(line)) return false;
                    return line;
                });

                someLines = _.compact(someLines);

                if (!someLines.length) {
                    return this.remove();
                }

                var i = random(someLines.length) | 0;
                var line = someLines[i];

                _lines.push(line);

                var destDot = (line.dot1 === this.location) ? line.dot2 : line.dot1;
                this.animator = new Animator(this.location, destDot, line, this);

            },
            completedAnimation: function() {
                this.location = this.animator.destDot;
                this.animator.line.drawn = true;
                this.animator.line.alertBoxes();
                this.animator = null;
            },
            remove: function() {
                this.dead = true;
                // removeDrawer(this);
            }
        };

        return {
            create: create,
            get: get,
            reset: reset,
            getAlive: getAlive
        };
    })();

    var boxes = [];

    ///// Start Up

    var DOTS = Sketch.create({
        container: document.getElementById( 'container' ),
        autostart: false,
        autoclear: false
    });

    DOTS.setup = function() {

        ///// build the dots

        var x_limit = ceil(DOTS.width / CONST.BOX_SIZE);
        var y_limit = ceil(DOTS.height / CONST.BOX_SIZE);

        for (var x = 0; x < x_limit; x++) {
            for (var y = 0; y < y_limit; y++) {
                dots.add( new Dot( x, y ) );
            }
        }

        ///// build the lines

        var allDots = dots.get();
        for (var i = 0, leng = allDots.length; i < leng; i++) {

            var dot = allDots[i];
            var neighbors = dots.getNeighborsOf( dot );

            lines.add( new Line(dot, neighbors[0]) );
            lines.add( new Line(dot, neighbors[1]) );

        }

        ///// build the boxes
        for (var p = 0; p < leng; p++) {
            var ds = dots.getFourCorners( allDots[p] );
            if (ds.length !== 4) { continue; }
            boxes.push(new Box( ds[0], ds[1], ds[2], ds[3] ) );
        }

        ///// start some drawers
        for (var k = 0; k < CONST.DRAWERS_COUNT; k++) {
            var d = random(allDots);
            drawers.create( d.x, d.y );
        }

    };

    DOTS.update = function() {
        if (!drawers.getAlive().length) {
            DOTS.reset();
        }
    };

    DOTS.draw = function() {

        var allDots = dots.get();
        var leng = allDots.length;
        while (leng--) {
            allDots[leng].draw( DOTS );
        }

        var allDrawers = drawers.get();
        for (var i = 0, len = allDrawers.length; i < len; i++) {
            allDrawers[i].drawToNeighbor();
        }

    };

    DOTS.reset = function() {
        DOTS.stop();
        dots.reset();
        lines.reset();
        drawers.reset();
        boxes = [];
        DOTS.clear();
        DOTS.setup();
        DOTS.start();
    };

    DOTS.FILL_COLORS = CONST.MONOBLUE;

    ////// Setup dat.GUI

    var gui = new dat.GUI();
    gui.add(CONST, 'DRAWERS_COUNT', 1, 150).step(1).onFinishChange( changeHandler );
    gui.add(CONST, 'BOX_SIZE', 5, 80).step(1).onFinishChange( changeHandler );
    gui.add(CONST, 'DRAW_SPEED', 0.05, 1).step(0.01);
    gui.add(DOTS, 'FILL_COLORS', { MonoBlue: 'MONOBLUE', Grayscale: 'GRAYSCALE', Multi: 'MULTI' }).onFinishChange( changeColor );
    gui.add(DOTS, 'reset');

    function changeHandler(val) {
        DOTS.reset();
    }
    function changeColor(val) {
        DOTS.FILL_COLORS = CONST[val];
    }
    ///// Exports

    window.DOTS = DOTS;
    window.dots = dots;
    window.lines = lines;
    window.drawers = drawers;

})();<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var _ = require('lodash');
var Model = require('./model');

var init = function() {
  var api = new RestAPI();

  /**
   * The main function. Wraps {@link RestAPI#setup}.
   *
   * @global
   * @see RestAPI#setup
   */
  var restifier = module.exports = function() {
    return api.setup.apply(api, Array.prototype.slice.call(arguments, 0));
  };

  /**
   * Factory function to create a new {@link RestAPI}.
   *
   * @name restifier.api
   * @global
   * @see RestAPI
   *
   * @returns RestAPI A new RestAPI.
   */
  restifier.api = function() {
    return new RestAPI();
  };

  restifier.reset = init;

  // Bind all RestAPI functions to the restifier object
  _.forEach(RestAPI.prototype, function(method, name) {
    if (typeof method !== 'function') {
      return;
    }
    restifier[name] = _.bind(method, api);
  });

  // Expose the RestAPI instance
  restifier.instance = api;
};

/**
 * Represents a RESTful API powered by Restifier.
 *
 * @class
 */
function RestAPI() {
  this.models = {};
}

/**
 * Gateway function that can add model(s) or return initialization
 * middleware depending on the arguments passed to it.
 *
 * @returns {Model|Function} A model or middleware depending on the arguments.
 * * `setup()` - Returns `initialize()`
 * * `setup(mong)` - Returns `model(mong)`
 * * `setup(mong1, mong2)` - Returns `modelsMiddleware(mong1, mong2)`
 */
RestAPI.prototype.setup = function() {
  var args = Array.prototype.slice.call(arguments, 0);
  if (args.length > 1) {
    return this.modelsMiddleware(args);
  }

  if (args.length === 0 || !args[0].schema) {
    return this.initialize();
  }
  return this.model(args[0]);
};

/**
 * Initialization middleware.
 *
 * @returns {Function} Express middleware
 */
RestAPI.prototype.initialize = function() {
  return require('res-error')({
    log: false
  });
};

/**
 * Should be called after the app has been created.
 *
 * @returns {Function} Express middleware
 */
RestAPI.prototype.finish = function() {
  return function(req, res, next) {
    return res.error(404, 'Path not found.');
  };
};

/**
 * Adds a model to this RestAPI.
 *
 * @param {mongoose.Model} mong The mongoose model
 */
RestAPI.prototype.model = function(mong) {
  var m = new Model(this, mong);
  this.models[mong.modelName] = m;
  return m;
};

/**
 * Adds multiple models to this RestAPI.
 *
 * @param {mongoose.Model[]} mongs The mongoose models
 */
RestAPI.prototype.addModels = function(mongs) {
  return _.map(mongs, function(mong) {
    return this.model(mong);
  }, this);
};

/**
 * Creates a middleware out of multiple models.
 *
 * @param {mongoose.Model[]} mongs The mongoose models
 */
RestAPI.prototype.modelsMiddleware = function(mongs) {
  var router = express.Router();
  _.forEach(this.addModels(mongs), function(model) {
    model.serve(router);
  });
  return router;
};

/**
 * Creates middleware that encompasses all registered models.
 * This is equivalent to calling `model.middleware()` for each
 * individual model, plus calling `restifier.initialize()` and
 * `restifier.finish()`.
 *
 * @returns {Router} Returns an Express router containing all middlewares.
 */
RestAPI.prototype.middleware = function() {
  var router = express.Router();
  router.use(this.initialize());
  _.forEach(this.models, function(model) {
    router.use(model.middleware());
    _.forEach(model.submodels, function(submodel) {
      router.use(submodel.middleware());
    });
  });
  router.use(this.finish());
  return router;
};

init();
<commit_msg>Move init function down<commit_after>'use strict';

var express = require('express');
var _ = require('lodash');
var Model = require('./model');

/**
 * Represents a RESTful API powered by Restifier.
 *
 * @class
 */
function RestAPI() {
  this.models = {};
}

/**
 * Gateway function that can add model(s) or return initialization
 * middleware depending on the arguments passed to it.
 *
 * @returns {Model|Function} A model or middleware depending on the arguments.
 * * `setup()` - Returns `initialize()`
 * * `setup(mong)` - Returns `model(mong)`
 * * `setup(mong1, mong2)` - Returns `modelsMiddleware(mong1, mong2)`
 */
RestAPI.prototype.setup = function() {
  var args = Array.prototype.slice.call(arguments, 0);
  if (args.length > 1) {
    return this.modelsMiddleware(args);
  }

  if (args.length === 0 || !args[0].schema) {
    return this.initialize();
  }
  return this.model(args[0]);
};

/**
 * Initialization middleware.
 *
 * @returns {Function} Express middleware
 */
RestAPI.prototype.initialize = function() {
  return require('res-error')({
    log: false
  });
};

/**
 * Should be called after the app has been created.
 *
 * @returns {Function} Express middleware
 */
RestAPI.prototype.finish = function() {
  return function(req, res, next) {
    return res.error(404, 'Path not found.');
  };
};

/**
 * Adds a model to this RestAPI.
 *
 * @param {mongoose.Model} mong The mongoose model
 */
RestAPI.prototype.model = function(mong) {
  var m = new Model(this, mong);
  this.models[mong.modelName] = m;
  return m;
};

/**
 * Adds multiple models to this RestAPI.
 *
 * @param {mongoose.Model[]} mongs The mongoose models
 */
RestAPI.prototype.addModels = function(mongs) {
  return _.map(mongs, function(mong) {
    return this.model(mong);
  }, this);
};

/**
 * Creates a middleware out of multiple models.
 *
 * @param {mongoose.Model[]} mongs The mongoose models
 */
RestAPI.prototype.modelsMiddleware = function(mongs) {
  var router = express.Router();
  _.forEach(this.addModels(mongs), function(model) {
    model.serve(router);
  });
  return router;
};

/**
 * Creates middleware that encompasses all registered models.
 * This is equivalent to calling `model.middleware()` for each
 * individual model, plus calling `restifier.initialize()` and
 * `restifier.finish()`.
 *
 * @returns {Router} Returns an Express router containing all middlewares.
 */
RestAPI.prototype.middleware = function() {
  var router = express.Router();
  router.use(this.initialize());
  _.forEach(this.models, function(model) {
    router.use(model.middleware());
    _.forEach(model.submodels, function(submodel) {
      router.use(submodel.middleware());
    });
  });
  router.use(this.finish());
  return router;
};

var init = function() {
  var api = new RestAPI();

  /**
   * The main function. Wraps {@link RestAPI#setup}.
   *
   * @global
   * @see RestAPI#setup
   */
  var restifier = module.exports = function() {
    return api.setup.apply(api, Array.prototype.slice.call(arguments, 0));
  };

  /**
   * Factory function to create a new {@link RestAPI}.
   *
   * @name restifier.api
   * @global
   * @see RestAPI
   *
   * @returns RestAPI A new RestAPI.
   */
  restifier.api = function() {
    return new RestAPI();
  };

  restifier.reset = init;

  // Bind all RestAPI functions to the restifier object
  _.forEach(RestAPI.prototype, function(method, name) {
    if (typeof method !== 'function') {
      return;
    }
    restifier[name] = _.bind(method, api);
  });

  // Expose the RestAPI instance
  restifier.instance = api;
};

init();
<|endoftext|>


<commit_before>var bl = require('bl'),
	crypto = require('crypto'),
	express = require('express'),
	request = require('request');

var app = express(),
	projects = {},
	workID = 0;

var Log = new require('./utils').Log(),
	Strings = require('./utils').Strings,
	Packager = require('./packager');

app.listen(process.env.PORT || 5000);

app.get('/', function(req, res){
	res.redirect('https://github.com/p3lim/addon-packager-proxy/wiki/Setup');
});

var regexParam = function(name, fn){
	return function(req, res, next, val){
		var captures;
		if(captures = fn.exec(String(val))){
			req.params[name] = captures[0];
			next();
		} else
			next('route');
	}
}

var fetchAddonList = function(){
	request({
		url: 'https://api.github.com/gists/' + process.env.GIST_ID,
		json: true,
		headers: {
			'User-Agent': 'addon-packager-proxy'
		}
	}, function(err, res, data){
		if(err)
			return Log.error(Strings.CONNECTION_ERROR.replace('%s', res.request.uri.href));

		if(!data.files)
			return Log.error(Strings.GIST_NOT_FOUND.replace('%s', process.env.GIST_ID));

		var file = data.files['addons.json'];
		if(!file)
			return Log.error(Strings.GIST_FILE_NOT_FOUND);

		var obj;
		try {
			obj = JSON.parse(file.content);
		} catch(err){
			return Log.error(Strings.GIST_SYNTAX_ERROR);
		}

		for(var index in obj)
			projects[obj[index].repo] = obj[index];

		Log.info(Strings.GIST_SUCCESSFUL);
	});
}

app.param('repo', regexParam('repo', /[\d\w\.-]+/));
app.param('tag', regexParam('tag', /.+/));

app.get('/updatelist', function(req, res){
	fetchAddonList();
	res.Send(Strings.FORCED_GIST_UPDATE_MESSAGE);
	Log.info(Strings.FORCED_GIST_UPDATE_MESSAGE);
});

app.get('/force/:repo/:tag', function(req, res){
	var name = req.params.repo;
	var details = projects[name];
	if(!details){
		res.status(400).send(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
		return Log.info(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
	}

	var tag = req.params.tag;
	res.send(Strings.FORCED_CHECK_MESSAGE.replace('%s', name).replace('%s', tag));
	Log.info(Strings.FORCED_CHECK_MESSAGE.replace('%s', name).replace('%s', tag));

	details.tag = tag;
	new Packager(details, ++workID, true);
});

app.post('/', function(req, res, next){
	if(!req.headers['x-github-delivery']){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_DELIVERY);
	}

	var signature = req.headers['x-hub-signature'],
		event = req.headers['x-github-event'];

	if(!signature){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_SECRET);
	}

	if(!event){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_EVENT);
	}

	req.pipe(bl(function(err, data){
		if(err){
			res.status(500).end();
			return Log.error(Strings.ERROR_MESSAGE.replace('%s', 'Webhook').replace('%s', err.message));
		}

		if(!signatureMatch(signature, data)){
			res.status(401).end();
			return Log.error(Strings.WEBHOOK_SIGN_MISMATCH);
		}

		try {
			res.payload = JSON.parse(data.toString());
		} catch(err){
			res.status(400).end();
			return Log.error(Strings.WEBHOOK_SYNTAX_ERROR);
		}

		res.event = event;

		next();
	}));
}, function(req, res){
	if(res.event === 'ping'){
		res.status(200).end();
		return Log.info(Strings.WEBHOOK_PING_MESSAGE.replace('%s', res.payload.zen));
	}

	if(res.event !== 'create'){
		res.status(204).end();
		return;
	}

	if(res.payload.ref_type !== 'tag'){
		res.status(204).end();
		return Log.info(Strings.WEBHOOK_REF_MISMATCH.replace('%s', res.payload.ref_type));
	}

	var name = res.payload.repository.name;
	var details = projects[name];
	if(!details){
		res.status(204).end();
		return Log.info(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
	}

	Log.info(Strings.WEBHOOK_RECEIVED_MESSAGE.replace('%s', name).replace('%s', res.payload.ref));

	details.tag = res.payload.ref;
	new Packager(details, ++workID);

	res.status(202).end();
});

function signatureMatch(signature, data){
	var computed = 'sha1=' + crypto.createHmac('sha1', process.env.SECRET_KEY).update(data).digest('hex');
	if(computed === signature)
		return true;
	else {
		Log.info(Strings.SIGN_PROVIDED.replace('%s', signature));
		Log.info(Strings.SIGN_COMPUTED.replace('%s', computed));
	}
}

fetchAddonList();
<commit_msg>Fix typo<commit_after>var bl = require('bl'),
	crypto = require('crypto'),
	express = require('express'),
	request = require('request');

var app = express(),
	projects = {},
	workID = 0;

var Log = new require('./utils').Log(),
	Strings = require('./utils').Strings,
	Packager = require('./packager');

app.listen(process.env.PORT || 5000);

app.get('/', function(req, res){
	res.redirect('https://github.com/p3lim/addon-packager-proxy/wiki/Setup');
});

var regexParam = function(name, fn){
	return function(req, res, next, val){
		var captures;
		if(captures = fn.exec(String(val))){
			req.params[name] = captures[0];
			next();
		} else
			next('route');
	}
}

var fetchAddonList = function(){
	request({
		url: 'https://api.github.com/gists/' + process.env.GIST_ID,
		json: true,
		headers: {
			'User-Agent': 'addon-packager-proxy'
		}
	}, function(err, res, data){
		if(err)
			return Log.error(Strings.CONNECTION_ERROR.replace('%s', res.request.uri.href));

		if(!data.files)
			return Log.error(Strings.GIST_NOT_FOUND.replace('%s', process.env.GIST_ID));

		var file = data.files['addons.json'];
		if(!file)
			return Log.error(Strings.GIST_FILE_NOT_FOUND);

		var obj;
		try {
			obj = JSON.parse(file.content);
		} catch(err){
			return Log.error(Strings.GIST_SYNTAX_ERROR);
		}

		for(var index in obj)
			projects[obj[index].repo] = obj[index];

		Log.info(Strings.GIST_SUCCESSFUL);
	});
}

app.param('repo', regexParam('repo', /[\d\w\.-]+/));
app.param('tag', regexParam('tag', /.+/));

app.get('/updatelist', function(req, res){
	fetchAddonList();
	res.send(Strings.FORCED_GIST_UPDATE_MESSAGE);
	Log.info(Strings.FORCED_GIST_UPDATE_MESSAGE);
});

app.get('/force/:repo/:tag', function(req, res){
	var name = req.params.repo;
	var details = projects[name];
	if(!details){
		res.status(400).send(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
		return Log.info(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
	}

	var tag = req.params.tag;
	res.send(Strings.FORCED_CHECK_MESSAGE.replace('%s', name).replace('%s', tag));
	Log.info(Strings.FORCED_CHECK_MESSAGE.replace('%s', name).replace('%s', tag));

	details.tag = tag;
	new Packager(details, ++workID, true);
});

app.post('/', function(req, res, next){
	if(!req.headers['x-github-delivery']){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_DELIVERY);
	}

	var signature = req.headers['x-hub-signature'],
		event = req.headers['x-github-event'];

	if(!signature){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_SECRET);
	}

	if(!event){
		res.status(400).end();
		return Log.error(Strings.WEBHOOK_NO_EVENT);
	}

	req.pipe(bl(function(err, data){
		if(err){
			res.status(500).end();
			return Log.error(Strings.ERROR_MESSAGE.replace('%s', 'Webhook').replace('%s', err.message));
		}

		if(!signatureMatch(signature, data)){
			res.status(401).end();
			return Log.error(Strings.WEBHOOK_SIGN_MISMATCH);
		}

		try {
			res.payload = JSON.parse(data.toString());
		} catch(err){
			res.status(400).end();
			return Log.error(Strings.WEBHOOK_SYNTAX_ERROR);
		}

		res.event = event;

		next();
	}));
}, function(req, res){
	if(res.event === 'ping'){
		res.status(200).end();
		return Log.info(Strings.WEBHOOK_PING_MESSAGE.replace('%s', res.payload.zen));
	}

	if(res.event !== 'create'){
		res.status(204).end();
		return;
	}

	if(res.payload.ref_type !== 'tag'){
		res.status(204).end();
		return Log.info(Strings.WEBHOOK_REF_MISMATCH.replace('%s', res.payload.ref_type));
	}

	var name = res.payload.repository.name;
	var details = projects[name];
	if(!details){
		res.status(204).end();
		return Log.info(Strings.WEBHOOK_REPO_MISMATCH.replace('%s', name));
	}

	Log.info(Strings.WEBHOOK_RECEIVED_MESSAGE.replace('%s', name).replace('%s', res.payload.ref));

	details.tag = res.payload.ref;
	new Packager(details, ++workID);

	res.status(202).end();
});

function signatureMatch(signature, data){
	var computed = 'sha1=' + crypto.createHmac('sha1', process.env.SECRET_KEY).update(data).digest('hex');
	if(computed === signature)
		return true;
	else {
		Log.info(Strings.SIGN_PROVIDED.replace('%s', signature));
		Log.info(Strings.SIGN_COMPUTED.replace('%s', computed));
	}
}

fetchAddonList();
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', mess<commit_msg>Who you calling a fool?<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', messa<|endoftext|>


<commit_before>pjax_config_page("/home", function() {
    return {
        onLoad: function() {
            $('#btn_sign_in').attr('href', Login.login_url());
            $('.link-to-binary-home').attr('href', page.url.url_for('home', '', true));
        }
    };
});

pjax_config_page("/404", function() {
    return {
        onLoad: function() {
            $('.contact a').attr('href', page.url.url_for('contact', '', true));
        }
    };
});

pjax_config_page("/terms-and-conditions", function() {
    return {
        onLoad: function() {
            var hash;
            function updateTab() {
                hash = /^#(risk|legal|order)-tab$/.test(window.location.hash) ? window.location.hash : '#legal-tab';
                //remove active class and hide all content
                $('#legal-menu li').removeClass('active a-active');
                $('.menu-has-sub-item div.toggle-content').addClass('invisible');
                //add active class to the right tab and show expected content
                $(hash).addClass('active')
                       .find('a').addClass('a-active');
                $(hash + '-content').removeClass('invisible');
            }
            $(window).on('hashchange', function() {
                updateTab();
            });
            updateTab();
            $('.content-tab-container').removeClass('invisible');
        }
    };
});

pjax_config_page("/contract-specifications", function() {
    return {
        onLoad: function() {
            var hash;
            function updateTab() {
                hash = /^#(volatility|forex)-tab$/.test(window.location.hash) ? window.location.hash : '#volatility-tab';
                //remove active class and hide all content
                $('#spec-menu li').removeClass('active a-active');
                $('.menu-has-sub-item div.toggle-content').addClass('invisible');
                //add active class to the right tab and show expected content
                $(hash).addClass('active')
                       .find('a').addClass('a-active');
                $(hash + '-content').removeClass('invisible');
            }
            $(window).on('hashchange', function() {
                updateTab();
            });
            updateTab();
            $('.content-tab-container').removeClass('invisible');
        }
    };
});
<commit_msg>Fix jumping up on tab click<commit_after>pjax_config_page("/home", function() {
    return {
        onLoad: function() {
            $('#btn_sign_in').attr('href', Login.login_url());
            $('.link-to-binary-home').attr('href', page.url.url_for('home', '', true));
        }
    };
});

pjax_config_page("/404", function() {
    return {
        onLoad: function() {
            $('.contact a').attr('href', page.url.url_for('contact', '', true));
        }
    };
});

pjax_config_page("/terms-and-conditions", function() {
    return {
        onLoad: function() {
            var hash;
            function updateTab() {
                hash = /^#(risk|legal|order)-tab$/.test(window.location.hash) ? window.location.hash : '#legal-tab';
                //remove active class and hide all content
                $('#legal-menu li').removeClass('active a-active');
                $('.menu-has-sub-item div.toggle-content').addClass('invisible');
                //add active class to the right tab and show expected content
                $(hash).addClass('active')
                       .find('a').addClass('a-active');
                $(hash + '-content').removeClass('invisible');
            }
            $(window).on('hashchange', function() {
                updateTab();
            });
            $('#legal-menu li').click(function(e) {
                e.preventDefault();
                window.history.pushState(null, null, '#' + $(this).attr('id'));
                updateTab();
            });
            updateTab();
            $('.content-tab-container').removeClass('invisible');
        }
    };
});

pjax_config_page("/contract-specifications", function() {
    return {
        onLoad: function() {
            var hash;
            function updateTab() {
                hash = /^#(volatility|forex)-tab$/.test(window.location.hash) ? window.location.hash : '#volatility-tab';
                //remove active class and hide all content
                $('#spec-menu li').removeClass('active a-active');
                $('.menu-has-sub-item div.toggle-content').addClass('invisible');
                //add active class to the right tab and show expected content
                $(hash).addClass('active')
                       .find('a').addClass('a-active');
                $(hash + '-content').removeClass('invisible');
            }
            $(window).on('hashchange', function() {
                updateTab();
            });
            $('#spec-menu li').click(function(e) {
                e.preventDefault();
                window.history.pushState(null, null, '#' + $(this).attr('id'));
                updateTab();
            });
            updateTab();
            $('.content-tab-container').removeClass('invisible');
        }
    };
});
<|endoftext|>


<commit_before>var template = require('../lib/uri-template'),
    expect = require("expect.js");

function createTestContext(c) {
    return function (t, r) {
        expect(template(t)(c)).to.eql(r);
    };
}

describe('uri-template', function () {
    describe('Level 1', function () {
        var assert = createTestContext({
                'var': 'value',
                'some.value': 'some',
                'some_value': 'value',
                'Some%20Thing': 'hello',
                'foo': 'bar',
                'hello': 'Hello World!',
                'bool': false,
                'toString': 'string',
                'number': 42,
                'float': 3.14,
                'undef': undefined,
                'null': null,
                'chars': 'šöäŸœñê€£¥‡ÑÒÓÔÕÖ×ØÙÚàáâãäåæçÿü'
            });

        it('empty string', function () {
            assert('', '');
        });

        it('encodes non expressions correctly', function () {
            assert('hello/world', 'hello/world');
            assert('Hello World!/{foo}', 'Hello%20World!/bar');
            assert(':/?#[]@!$&()*+,;=\'', ':/?#[]@!$&()*+,;=\'');
            assert('%20', '%20');
            assert('%xyz', '%25xyz');
            assert('%', '%25');
        });

        it('expand plain ASCII strings', function () {
            assert('{var}', 'value');
        });

        it('expand non-ASCII strings', function () {
            assert('{chars}', '%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF%C3%BC');
        });

        it('expand expressions with dot and underscore', function () {
            assert('{some.value}', 'some');
            assert('{some_value}', 'value');
        });

        it('expand expressions with encoding', function () {
            assert('{Some%20Thing}', 'hello');
        });

        it('expand expressions with reserved JavaScript names', function () {
            assert('{toString}', 'string');
        });

        it('expand variables that are not strings', function () {
            assert('{number}', '42');
            assert('{float}', '3.14');
            assert('{bool}', 'false');
        });

        it('expand variables that are undefined or null', function () {
            assert('{undef}', '');
            assert('{null}', '');
        });

        it('expand multiple values', function () {
            assert('{var}/{foo}', 'value/bar');
        });

        it('escape invalid characters correctly', function () {
            assert('{hello}', 'Hello%20World!');
        });
    });

    describe('Level 2', function () {
        var assert = createTestContext({
                'var': 'value',
                'hello': 'Hello World!',
                'path': '/foo/bar'
            });

        it('reserved expansion of basic strings', function () {
            assert('{+var}', 'value');
            assert('{+hello}', 'Hello%20World!');
        });

        it('preserves paths', function() {
            assert('{+path}/here', '/foo/bar/here');
            assert('here?ref={+path}', 'here?ref=/foo/bar');
        });
    });

    describe('Level 3', function () {
        var assert = createTestContext({
               'var' : 'value',
               'hello' : 'Hello World!',
               'empty' : '',
               'path' : '/foo/bar',
               'x' : '1024',
               'y' : '768'
            });

        it('variables without an operator', function () {
            assert('map?{x,y}', 'map?1024,768');
            assert('{x,hello,y}', '1024,Hello%20World!,768');
        });

        it('variables with the reserved expansion operator', function () {
            assert('{+x,hello,y}', '1024,Hello%20World!,768');
            assert('{+path,x}/here', '/foo/bar,1024/here');
        });

        it('variables with the fragment expansion operator', function () {
            assert('{#x,hello,y}', '#1024,Hello%20World!,768');
            assert('{#path,x}/here', '#/foo/bar,1024/here');
        });

        it('variables with the dot operator', function () {
            assert('X{.var}', 'X.value');
            assert('X{.x,y}', 'X.1024.768');
        });

        it('variables with the path operator', function () {
            assert('{/var}', '/value');
            assert('{/var,x}/here', '/value/1024/here');
        });

        it('variables with the parameter operator', function () {
            assert('{;x,y}', ';x=1024;y=768');
            assert('{;x,y,empty}', ';x=1024;y=768;empty');
        });

        it('variables with the query operator', function () {
            assert('{?x,y}', '?x=1024&y=768');
            assert('{?x,y,empty}', '?x=1024&y=768&empty=');
        });

        it('variables with the query continuation operator', function () {
            assert('?fixed=yes{&x}', '?fixed=yes&x=1024');
            assert('{&x,y,empty}', '&x=1024&y=768&empty=');
        });
    });

    describe('Level 4', function () {
        var assert = createTestContext({
                'var': 'value',
                'hello': 'Hello World!',
                'path': '/foo/bar',
                'list': ['red', 'green', 'blue'],
                'keys': {
                    'semi': ';',
                    'dot': '.',
                    'comma': ','
                },
                'number': 2133
            });

        it('variable modifiers prefix', function () {
            assert('{var:3}', 'val');
            assert('{var:30}', 'value');
            assert('{+path:6}/here', '/foo/b/here');
            assert('{#path:6}/here', '#/foo/b/here');
            assert('X{.var:3}', 'X.val');
            assert('{/var:1,var}', '/v/value');
            assert('{;hello:5}', ';hello=Hello');
            assert('{?var:3}', '?var=val');
            assert('{&var:3}', '&var=val');
        });

        it('variable modifier prefix converted to string', function () {
            assert('{number:3}', '213');
        });

        it('variable list expansion', function () {
            assert('{list}', 'red,green,blue');
            assert('{+list}', 'red,green,blue');
            assert('{#list}', '#red,green,blue');
            assert('{/list}', '/red,green,blue');
            assert('{;list}', ';list=red,green,blue');
            assert('{.list}', '.red,green,blue');
            assert('{?list}', '?list=red,green,blue');
            assert('{&list}', '&list=red,green,blue');
        });

        it('variable associative array expansion', function () {
            assert('{keys}', 'semi,%3B,dot,.,comma,%2C');
            assert('{keys*}', 'semi=%3B,dot=.,comma=%2C');
            assert('{+keys}', 'semi,;,dot,.,comma,,');
            assert('{#keys}', '#semi,;,dot,.,comma,,');
            assert('{.keys}', '.semi,%3B,dot,.,comma,%2C');
            assert('{/keys}', '/semi,%3B,dot,.,comma,%2C');
            assert('{;keys}', ';keys=semi,%3B,dot,.,comma,%2C');
            assert('{?keys}', '?keys=semi,%3B,dot,.,comma,%2C');
            assert('{&keys}', '&keys=semi,%3B,dot,.,comma,%2C');
        });

        it('variable list explode', function () {
            assert('{list*}', 'red,green,blue');
            assert('{+list*}', 'red,green,blue');
            assert('{#list*}', '#red,green,blue');
            assert('{/list*}', '/red/green/blue');
            assert('{;list*}', ';list=red;list=green;list=blue');
            assert('{.list*}', '.red.green.blue');
            assert('{?list*}', '?list=red&list=green&list=blue');
            assert('{&list*}', '&list=red&list=green&list=blue');

            assert('{/list*,path:4}', '/red/green/blue/%2Ffoo');
        });

        it('variable associative array explode', function () {
            assert('{+keys*}', 'semi=;,dot=.,comma=,');
            assert('{#keys*}', '#semi=;,dot=.,comma=,');
            assert('{/keys*}', '/semi=%3B/dot=./comma=%2C');
            assert('{;keys*}', ';semi=%3B;dot=.;comma=%2C');
            assert('{?keys*}', '?semi=%3B&dot=.&comma=%2C');
            assert('{&keys*}', '&semi=%3B&dot=.&comma=%2C')
        });
    });
});
<commit_msg>Added tests for expanding empty objects and arrays.<commit_after>var template = require('../lib/uri-template'),
    expect = require("expect.js");

function createTestContext(c) {
    return function (t, r) {
        expect(template(t)(c)).to.eql(r);
    };
}

describe('uri-template', function () {
    describe('Level 1', function () {
        var assert = createTestContext({
                'var': 'value',
                'some.value': 'some',
                'some_value': 'value',
                'Some%20Thing': 'hello',
                'foo': 'bar',
                'hello': 'Hello World!',
                'bool': false,
                'toString': 'string',
                'number': 42,
                'float': 3.14,
                'undef': undefined,
                'null': null,
                'chars': 'šöäŸœñê€£¥‡ÑÒÓÔÕÖ×ØÙÚàáâãäåæçÿü'
            });

        it('empty string', function () {
            assert('', '');
        });

        it('encodes non expressions correctly', function () {
            assert('hello/world', 'hello/world');
            assert('Hello World!/{foo}', 'Hello%20World!/bar');
            assert(':/?#[]@!$&()*+,;=\'', ':/?#[]@!$&()*+,;=\'');
            assert('%20', '%20');
            assert('%xyz', '%25xyz');
            assert('%', '%25');
        });

        it('expand plain ASCII strings', function () {
            assert('{var}', 'value');
        });

        it('expand non-ASCII strings', function () {
            assert('{chars}', '%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF%C3%BC');
        });

        it('expand expressions with dot and underscore', function () {
            assert('{some.value}', 'some');
            assert('{some_value}', 'value');
        });

        it('expand expressions with encoding', function () {
            assert('{Some%20Thing}', 'hello');
        });

        it('expand expressions with reserved JavaScript names', function () {
            assert('{toString}', 'string');
        });

        it('expand variables that are not strings', function () {
            assert('{number}', '42');
            assert('{float}', '3.14');
            assert('{bool}', 'false');
        });

        it('expand variables that are undefined or null', function () {
            assert('{undef}', '');
            assert('{null}', '');
        });

        it('expand multiple values', function () {
            assert('{var}/{foo}', 'value/bar');
        });

        it('escape invalid characters correctly', function () {
            assert('{hello}', 'Hello%20World!');
        });
    });

    describe('Level 2', function () {
        var assert = createTestContext({
                'var': 'value',
                'hello': 'Hello World!',
                'path': '/foo/bar'
            });

        it('reserved expansion of basic strings', function () {
            assert('{+var}', 'value');
            assert('{+hello}', 'Hello%20World!');
        });

        it('preserves paths', function() {
            assert('{+path}/here', '/foo/bar/here');
            assert('here?ref={+path}', 'here?ref=/foo/bar');
        });
    });

    describe('Level 3', function () {
        var assert = createTestContext({
               'var' : 'value',
               'hello' : 'Hello World!',
               'empty' : '',
               'path' : '/foo/bar',
               'x' : '1024',
               'y' : '768'
            });

        it('variables without an operator', function () {
            assert('map?{x,y}', 'map?1024,768');
            assert('{x,hello,y}', '1024,Hello%20World!,768');
        });

        it('variables with the reserved expansion operator', function () {
            assert('{+x,hello,y}', '1024,Hello%20World!,768');
            assert('{+path,x}/here', '/foo/bar,1024/here');
        });

        it('variables with the fragment expansion operator', function () {
            assert('{#x,hello,y}', '#1024,Hello%20World!,768');
            assert('{#path,x}/here', '#/foo/bar,1024/here');
        });

        it('variables with the dot operator', function () {
            assert('X{.var}', 'X.value');
            assert('X{.x,y}', 'X.1024.768');
        });

        it('variables with the path operator', function () {
            assert('{/var}', '/value');
            assert('{/var,x}/here', '/value/1024/here');
        });

        it('variables with the parameter operator', function () {
            assert('{;x,y}', ';x=1024;y=768');
            assert('{;x,y,empty}', ';x=1024;y=768;empty');
        });

        it('variables with the query operator', function () {
            assert('{?x,y}', '?x=1024&y=768');
            assert('{?x,y,empty}', '?x=1024&y=768&empty=');
        });

        it('variables with the query continuation operator', function () {
            assert('?fixed=yes{&x}', '?fixed=yes&x=1024');
            assert('{&x,y,empty}', '&x=1024&y=768&empty=');
        });
    });

    describe('Level 4', function () {
        var assert = createTestContext({
                'var': 'value',
                'hello': 'Hello World!',
                'path': '/foo/bar',
                'list': ['red', 'green', 'blue'],
                'keys': {
                    'semi': ';',
                    'dot': '.',
                    'comma': ','
                },
                "chars": {
                    'ü': 'ü'
                },
                'number': 2133,
                'emptylist': [],
                'emptyobject': {}
            });

        it('variable empty list', function () {
            assert('{/emptylist}', '');
            assert('{/emptylist*}', '');
            assert('{?emptylist}', '?emptylist=');
            assert('{?emptylist*}', '');
        });

        it('variable empty object', function () {
            assert('{/emptyobject}', '');
            assert('{/emptyobject*}', '');
            assert('{?emptyobject}', '?emptyobject=');
            assert('{?emptyobject*}', '');
        });

        it('variable modifiers prefix', function () {
            assert('{var:3}', 'val');
            assert('{var:30}', 'value');
            assert('{+path:6}/here', '/foo/b/here');
            assert('{#path:6}/here', '#/foo/b/here');
            assert('X{.var:3}', 'X.val');
            assert('{/var:1,var}', '/v/value');
            assert('{;hello:5}', ';hello=Hello');
            assert('{?var:3}', '?var=val');
            assert('{&var:3}', '&var=val');
        });

        it('variable modifier prefix converted to string', function () {
            assert('{number:3}', '213');
        });

        it('variable list expansion', function () {
            assert('{list}', 'red,green,blue');
            assert('{+list}', 'red,green,blue');
            assert('{#list}', '#red,green,blue');
            assert('{/list}', '/red,green,blue');
            assert('{;list}', ';list=red,green,blue');
            assert('{.list}', '.red,green,blue');
            assert('{?list}', '?list=red,green,blue');
            assert('{&list}', '&list=red,green,blue');
        });

        it('variable associative array expansion', function () {
            assert('{keys}', 'semi,%3B,dot,.,comma,%2C');
            assert('{keys*}', 'semi=%3B,dot=.,comma=%2C');
            assert('{+keys}', 'semi,;,dot,.,comma,,');
            assert('{#keys}', '#semi,;,dot,.,comma,,');
            assert('{.keys}', '.semi,%3B,dot,.,comma,%2C');
            assert('{/keys}', '/semi,%3B,dot,.,comma,%2C');
            assert('{;keys}', ';keys=semi,%3B,dot,.,comma,%2C');
            assert('{?keys}', '?keys=semi,%3B,dot,.,comma,%2C');
            assert('{&keys}', '&keys=semi,%3B,dot,.,comma,%2C');
        });

        it('variable list explode', function () {
            assert('{list*}', 'red,green,blue');
            assert('{+list*}', 'red,green,blue');
            assert('{#list*}', '#red,green,blue');
            assert('{/list*}', '/red/green/blue');
            assert('{;list*}', ';list=red;list=green;list=blue');
            assert('{.list*}', '.red.green.blue');
            assert('{?list*}', '?list=red&list=green&list=blue');
            assert('{&list*}', '&list=red&list=green&list=blue');

            assert('{/list*,path:4}', '/red/green/blue/%2Ffoo');
        });

        it('variable associative array explode', function () {
            assert('{+keys*}', 'semi=;,dot=.,comma=,');
            assert('{#keys*}', '#semi=;,dot=.,comma=,');
            assert('{/keys*}', '/semi=%3B/dot=./comma=%2C');
            assert('{;keys*}', ';semi=%3B;dot=.;comma=%2C');
            assert('{?keys*}', '?semi=%3B&dot=.&comma=%2C');
            assert('{&keys*}', '&semi=%3B&dot=.&comma=%2C')
        });
    });
});
<|endoftext|>


<commit_before>/* This module will use one of the path generators in the
   svg directory, to render a svg.
*/
var Api = require(__dirname + '/baseModule.js');
Api._cache = {}

var D3PathGenerator = require(__dirname + '/svg/d3PathGenerator.js');

var cheerio = require('cheerio');

module.exports = function(ApiParams) {

  var api = new Api("svg", ApiParams);

  api.get = function(callback) {
    var self = this;
    this.datasetConfig = this.apiParams.config.datasets[this.apiParams.dataset];
    this.getCallback = callback;

    //Use the first recommended projection for this dataset, if none given
    this.projection = this.parameters["projection"] || this.parameters["svg_proj"]
                     || this.datasetConfig.recommendedProjections[0]
    this.width = this.parameters["width"] || this.parameters["svg_width"]
    this.height = this.parameters["height"] || this.parameters["svg_height"]
    this.lang = this.parameters["svg_lang"] || null
    this.variant = this.parameters["svg_variant"] || null

    self.cacheKey = self.apiParams.date + self.apiParams.dataset + self.projection + self.width + self.height + this.parameters["svg_props"] + this.lang + this.variant
    if (self.cacheKey in Api._cache){
      self._callback(null, Api._cache[self.cacheKey], self.getCallback)
      return
    }

    /* call geo module */
    var geo = require(__dirname + '/geo')(ApiParams)
    geo.parameters["geo_type"] = "geojson"
    geo.parameters["geo_props"] = this.parameters["svg_props"]
    geo.parameters["geo_lang"] = this.lang
    geo.parameters["geo_variant"] = this.variant
    geo.parameters["geo_scale"] = "s"

    geo.get(function createSvg(err, geojson){

      self.geojson = geojson
//      console.log(geojson.features[0].geometry.coordinates)

      if ( D3PathGenerator().canConvertTo(self.projection) ){
        var pathGenerator = D3PathGenerator(geojson, self.projection, self.apiParams.dataset,
                                {width: self.width,
                                height: self.height,
                                bbox: self.datasetConfig.bbox})
      } else {
        self.apiParams.res.status(501).send('Sorry, no SVG path generator was found for that projection.')
        return
      }

      pathGenerator.getPaths(function(error, paths){
        Api._cache[self.cacheKey] = paths
        self._callback(null, paths, self.getCallback)
      })

    });

  }
  return api
}<commit_msg>round svg dimension for better caching<commit_after>/* This module will use one of the path generators in the
   svg directory, to render a svg.
*/
var Api = require(__dirname + '/baseModule.js');
Api._cache = {}

var D3PathGenerator = require(__dirname + '/svg/d3PathGenerator.js');

var cheerio = require('cheerio');

module.exports = function(ApiParams) {

  var api = new Api("svg", ApiParams);

  api.get = function(callback) {
    var self = this;
    this.datasetConfig = this.apiParams.config.datasets[this.apiParams.dataset];
    this.getCallback = callback;

    //Use the first recommended projection for this dataset, if none given
    this.projection = this.parameters["projection"] || this.parameters["svg_proj"]
                     || this.datasetConfig.recommendedProjections[0]
    this.width = this.parameters["width"] || this.parameters["svg_width"]
    this.height = this.parameters["height"] || this.parameters["svg_height"]
    this.lang = this.parameters["svg_lang"] || null
    this.variant = this.parameters["svg_variant"] || null

    /* Round up dimension for a better chance of caching */
    this.width = Math.ceil(this.width / 20.0) * 20;
    this.height = Math.ceil(this.height / 20.0) * 20;

    self.cacheKey = self.apiParams.date + self.apiParams.dataset + self.projection + self.width + self.height + this.parameters["svg_props"] + this.lang + this.variant
    if (self.cacheKey in Api._cache){
      self._callback(null, Api._cache[self.cacheKey], self.getCallback)
      return
    }

    /* call geo module */
    var geo = require(__dirname + '/geo')(ApiParams)
    geo.parameters["geo_type"] = "geojson"
    geo.parameters["geo_props"] = this.parameters["svg_props"]
    geo.parameters["geo_lang"] = this.lang
    geo.parameters["geo_variant"] = this.variant
    geo.parameters["geo_scale"] = "s"

    geo.get(function createSvg(err, geojson){

      self.geojson = geojson
//      console.log(geojson.features[0].geometry.coordinates)

      if ( D3PathGenerator().canConvertTo(self.projection) ){
        var pathGenerator = D3PathGenerator(geojson, self.projection, self.apiParams.dataset,
                                {width: self.width,
                                height: self.height,
                                bbox: self.datasetConfig.bbox})
      } else {
        self.apiParams.res.status(501).send('Sorry, no SVG path generator was found for that projection.')
        return
      }

      pathGenerator.getPaths(function(error, paths){
        Api._cache[self.cacheKey] = paths
        self._callback(null, paths, self.getCallback)
      })

    });

  }
  return api
}<|endoftext|>


<commit_before>/* Task Description */
/*
 * Create a module for a Telerik Academy course
 * The course has a title and presentations
 * Each presentation also has a title
 * There is a homework for each presentation
 * There is a set of students listed for the course
 * Each student has firstname, lastname and an ID
 * IDs must be unique integer numbers which are at least 1
 * Each student can submit a homework for each presentation in the course
 * Create method init
 * Accepts a string - course title
 * Accepts an array of strings - presentation titles
 * Throws if there is an invalid title
 * Titles do not start or end with spaces
 * Titles do not have consecutive spaces
 * Titles have at least one character
 * Throws if there are no presentations
 * Create method addStudent which lists a student for the course
 * Accepts a string in the format 'Firstname Lastname'
 * Throws if any of the names are not valid
 * Names start with an upper case letter
 * All other symbols in the name (if any) are lowercase letters
 * Generates a unique student ID and returns it
 * Create method getAllStudents that returns an array of students in the format:
 * {firstname: 'string', lastname: 'string', id: StudentID}
 * Create method submitHomework
 * Accepts studentID and homeworkID
 * homeworkID 1 is for the first presentation
 * homeworkID 2 is for the second one
 * ...
 * Throws if any of the IDs are invalid
 * Create method pushExamResults
 * Accepts an array of items in the format {StudentID: ..., Score: ...}
 * StudentIDs which are not listed get 0 points
 * Throw if there is an invalid StudentID
 * Throw if same StudentID is given more than once ( he tried to cheat (: )
 * Throw if Score is not a number
 * Create method getTopStudents which returns an array of the top 10 performing students
 * Array must be sorted from best to worst
 * If there are less than 10, return them all
 * The final score that is used to calculate the top performing students is done as follows:
 * 75% of the exam result
 * 25% the submitted homework (count of submitted homeworks / count of all homeworks) for the course
 */

function solve() {

    var Course = {

        init: function(title, presentations) {

            this.presentations = presentations;
            this.students = [];
            this.ID = 0;

            if (title == '' || title == ' ' || title == undefined || title == null) {
                throw 'title cannot be empty or you know....';
            }

            for (let i = 0; i < presentations.length; i += 1) {
                if (presentations[i] == '' || presentations[i] == ' ' ||
                    presentations[i == undefined || presentations[i] == null]) {
                    throw 'exeption';
                }

                for (let j = 0; j < presentations[i].length; j += 1) {
                    if (presentations[i][j] == ' ' && presentations[i][j + 1] == ' ') {
                        throw 'consecutive space';
                    }
                }
            }

            for (let i = 1; i < title.length - 1; i += 1) {
                if (title[i] == ' ' && title[i + 1] == ' ') {
                    throw 'title does not contain consecutive space';
                }
            }

            if (title[0] == ' ' || title[title.length - 1] == ' ') {
                throw 'titles do not start or end with space';
            }

            if (title.length < 1) {
                throw 'title must contains atleast 1 char';
            }

            if (presentations.length == 0) {
                throw 'there must be presantations!';
            }

            return this;
        },
        addStudent: function(name) {

            var names = name.split(' ');

            if (names.length != 2) {
                throw 'invalid input';
            }

            this.ID += 1;

            var sID = this.ID,
                firstName = names[0],
                secondName = names[1];

            if (firstName[0] != firstName[0].toUpperCase()) {
                throw 'invalid name';
            }

            if (secondName[0] != secondName[0].toUpperCase()) {
                throw 'invalid name';
            }

            let fNameSub = firstName.substr(1, firstName.length),
                sNameSub = secondName.substr(1, secondName.length);

            if (fNameSub != fNameSub.toLowerCase() || sNameSub != sNameSub.toLowerCase()) {
                throw 'invalid name';
            }

            var student = {
                firstname: firstName,
                lastname: secondName,
                id: sID
            };

            this.students.push(student);

            return sID;
        },
        getAllStudents: function() {
            return this.students;
        },
        submitHomework: function(studentID, homeworkID) {

            function isInt(value) {
                var x = parseFloat(value);
                return !isNaN(value) && (x | 0) === x;
            }

            let studentsCount = this.students.length,
                presentationsCount = this.presentations.length;

            if (homeworkID > presentationsCount) {
                throw 'invalid ID';
            }

            if (studentID > studentsCount) {
                throw 'invalid ID';
            }

            if (homeworkID > presentationsCount) {
                throw 'invalid ID';
            }

            if (studentID < 1 || homeworkID < 1) {
                throw 'invalid ID';
            }

            if (!isInt(studentID)) {
                throw 'invalid ID';
            }

            if (!isInt(homeworkID)) {
                throw 'invalid ID';
            }

        },
        pushExamResults: function(results) {

            if (!(results instanceof Array)) {
                throw 'invalid input';
            }

            let idsArray = [];

            for (r of results) {
                if (r.StudentID < 1 || isNaN(r.score) ||
                    isNaN(r.StudentID) || r.StudentID > this.students.length
                ) {
                    throw 'invalid';
                }

                idsArray.push(r.StudentID);
            }

            for (let i = 0; i <= idsArray.length - 1; i += 1) {
                for (let j = i + 1; j < idsArray.length; j += 1) {
                    if (idsArray[j] == idsArray[i]) {
                        throw 'cheater allert';
                    }
                }
            }

        },
        getTopStudents: function() {}
    };

    return Course;
}

// let course = solve();
// course.init('CSharp', ['Presentation1', 'Presentation2']);
// course.addStudent('Pesho Peshov');
// course.addStudent('Evg Nest');
// course.addStudent('Ili St');
// console.log(course.getAllStudents());
// course.submitHomework(1, 1);
module.exports = solve;<commit_msg>ModelsAndPaters<commit_after>/* Task Description */
/*
 * Create a module for a Telerik Academy course
 * The course has a title and presentations
 * Each presentation also has a title
 * There is a homework for each presentation
 * There is a set of students listed for the course
 * Each student has firstname, lastname and an ID
 * IDs must be unique integer numbers which are at least 1
 * Each student can submit a homework for each presentation in the course
 * Create method init
 * Accepts a string - course title
 * Accepts an array of strings - presentation titles
 * Throws if there is an invalid title
 * Titles do not start or end with spaces
 * Titles do not have consecutive spaces
 * Titles have at least one character
 * Throws if there are no presentations
 * Create method addStudent which lists a student for the course
 * Accepts a string in the format 'Firstname Lastname'
 * Throws if any of the names are not valid
 * Names start with an upper case letter
 * All other symbols in the name (if any) are lowercase letters
 * Generates a unique student ID and returns it
 * Create method getAllStudents that returns an array of students in the format:
 * {firstname: 'string', lastname: 'string', id: StudentID}
 * Create method submitHomework
 * Accepts studentID and homeworkID
 * homeworkID 1 is for the first presentation
 * homeworkID 2 is for the second one
 * ...
 * Throws if any of the IDs are invalid
 * Create method pushExamResults
 * Accepts an array of items in the format {StudentID: ..., Score: ...}
 * StudentIDs which are not listed get 0 points
 * Throw if there is an invalid StudentID
 * Throw if same StudentID is given more than once ( he tried to cheat (: )
 * Throw if Score is not a number
 * Create method getTopStudents which returns an array of the top 10 performing students
 * Array must be sorted from best to worst
 * If there are less than 10, return them all
 * The final score that is used to calculate the top performing students is done as follows:
 * 75% of the exam result
 * 25% the submitted homework (count of submitted homeworks / count of all homeworks) for the course
 */

function solve() {

    var Course = {

        init: function(title, presentations) {

            this.presentations = presentations;
            this.students = [];
            this.ID = 0;

            if (title == '' || title == ' ' || title == undefined || title == null) {
                throw 'title cannot be empty or you know....';
            }

            for (let i = 0; i < presentations.length; i += 1) {
                if (presentations[i] == '' || presentations[i] == ' ' ||
                    presentations[i == undefined || presentations[i] == null]) {
                    throw 'exeption';
                }

                for (let j = 0; j < presentations[i].length; j += 1) {
                    if (presentations[i][j] == ' ' && presentations[i][j + 1] == ' ') {
                        throw 'consecutive space';
                    }
                }
            }

            for (let i = 1; i < title.length - 1; i += 1) {
                if (title[i] == ' ' && title[i + 1] == ' ') {
                    throw 'title does not contain consecutive space';
                }
            }

            if (title[0] == ' ' || title[title.length - 1] == ' ') {
                throw 'titles do not start or end with space';
            }

            if (title.length < 1) {
                throw 'title must contains atleast 1 char';
            }

            if (presentations.length == 0) {
                throw 'there must be presantations!';
            }

            return this;
        },
        addStudent: function(name) {

            var names = name.split(' ');

            if (names.length != 2) {
                throw 'invalid input';
            }

            this.ID += 1;

            var sID = this.ID,
                firstName = names[0],
                secondName = names[1];

            if (firstName[0] != firstName[0].toUpperCase()) {
                throw 'invalid name';
            }

            if (secondName[0] != secondName[0].toUpperCase()) {
                throw 'invalid name';
            }

            let fNameSub = firstName.substr(1, firstName.length),
                sNameSub = secondName.substr(1, secondName.length);

            if (fNameSub != fNameSub.toLowerCase() || sNameSub != sNameSub.toLowerCase()) {
                throw 'invalid name';
            }

            var student = {
                firstname: firstName,
                lastname: secondName,
                id: sID
            };

            this.students.push(student);

            return sID;
        },
        getAllStudents: function() {
            return this.students;
        },
        submitHomework: function(studentID, homeworkID) {

            function isInt(value) {
                var x = parseFloat(value);
                return !isNaN(value) && (x | 0) === x;
            }

            let studentsCount = this.students.length,
                presentationsCount = this.presentations.length;

            if (homeworkID > presentationsCount) {
                throw 'invalid ID';
            }

            if (studentID > studentsCount) {
                throw 'invalid ID';
            }

            if (homeworkID > presentationsCount) {
                throw 'invalid ID';
            }

            if (studentID < 1 || homeworkID < 1) {
                throw 'invalid ID';
            }

            if (!isInt(studentID)) {
                throw 'invalid ID';
            }

            if (!isInt(homeworkID)) {
                throw 'invalid ID';
            }

        },
        pushExamResults: function(results) {

            if (!(results instanceof Array)) {
                throw 'invalid input';
            }

            let idsArray = [];

            for (r of results) {
                if (r.StudentID < 1 || isNaN(r.score) ||
                    isNaN(r.StudentID) || r.StudentID > this.students.length
                ) {
                    throw 'invalid';
                }

                idsArray.push(r.StudentID);
            }

            for (let i = 0; i <= idsArray.length - 1; i += 1) {
                for (let j = i + 1; j < idsArray.length; j += 1) {
                    if (idsArray[j] == idsArray[i]) {
                        throw 'cheater allert';
                    }
                }
            }

        },
        getTopStudents: function() {}
    };

    return Course;
}
module.exports = solve;<|endoftext|>


<commit_before>'use strict';
const l10nFile = __dirname + '/../l10n/commands/drop.yml';
const l10n = require('../src/l10n')(l10nFile);
const CommandUtil = require('../src/command_util').CommandUtil;
const util = require('util');

exports.command = (rooms, items, players, npcs, Commands) => {
  return (args, player, isDead) => {
    const room = rooms.getAt(player.getLocation());

    args = args.toLowerCase();

    if (args === 'all') {
      dropAll();
      return;
    }

    let item = CommandUtil.findItemInInventory(args, player, true);

    if (!item) {
      return player.sayL10n(l10n, 'ITEM_NOT_FOUND');
    }

    if (item.isEquipped()) {
      item = CommandUtil.findItemInInventory('2.' + args, player, true) || item;
      if (item.isEquipped()) {
        return player.sayL10n(l10n, 'ITEM_WORN');
      }
    }

    drop(item);

    function dropAll() {
      const items = player.getInventory()
        .filter(item => !item.isEquipped());
      if (!items.length && !isDead) { return player.say('You have nothing to drop.'); }
      items.forEach(item => drop(item));
    }

    function drop(item) {
      let playerName = player.getName();

      if (item.isEquipped()) {
        return player.sayL10n(l10n, 'ITEM_WORN');
      }

      players.eachIf(
        p => CommandUtil.inSameRoom(p, player),
        p => p.sayL10n(l10n, 'OTHER_DROPS', playerName, item.getShortDesc(p.getLocale()))
      );

      let itemName = item.getShortDesc('en');
      if (!isDead) {
        player.sayL10n(l10n, 'ITEM_DROP', itemName, false);
        room.getNpcs().forEach( id => {
          let npc = npcs.get(id);
          npc.emit('playerDropItem', room, rooms, player, players, npc, npcs, item);
        });
      }
      util.log(playerName + " drops " + itemName + " at " + room.getLocation() + ".");

      player.removeItem(item);
      room.addItem(item.getUuid());
      item.setInventory(null);
      item.setRoom(room.getLocation());
    }
  };
};
<commit_msg>Fix whitespace<commit_after>'use strict';
const l10nFile = __dirname + '/../l10n/commands/drop.yml';
const l10n = require('../src/l10n')(l10nFile);
const CommandUtil = require('../src/command_util').CommandUtil;
const util = require('util');

exports.command = (rooms, items, players, npcs, Commands) => {
  return (args, player, isDead) => {
    const room = rooms.getAt(player.getLocation());

    args = args.toLowerCase();

    if (args === 'all') {
      dropAll();
      return;
    }

    let item = CommandUtil.findItemInInventory(args, player, true);

    if (!item) {
      return player.sayL10n(l10n, 'ITEM_NOT_FOUND');
    }

    if (item.isEquipped()) {
      item = CommandUtil.findItemInInventory('2.' + args, player, true) || item;
      if (item.isEquipped()) {
        return player.sayL10n(l10n, 'ITEM_WORN');
      }
    }

    drop(item);

    function dropAll() {
      const items = player.getInventory()
        .filter(item => !item.isEquipped());
      if (!items.length && !isDead) { return player.say('You have nothing to drop.'); }
      items.forEach(item => drop(item));
    }

    function drop(item) {
      let playerName = player.getName();

      if (item.isEquipped()) {
        return player.sayL10n(l10n, 'ITEM_WORN');
      }

      players.eachIf(
        p => CommandUtil.inSameRoom(p, player),
        p => p.sayL10n(l10n, 'OTHER_DROPS', playerName, item.getShortDesc(p.getLocale()))
      );

      let itemName = item.getShortDesc('en');
      if (!isDead) {
        player.sayL10n(l10n, 'ITEM_DROP', itemName, false);
        room.getNpcs().forEach( id => {
          let npc = npcs.get(id);
          npc.emit('playerDropItem', room, rooms, player, players, npc, npcs, item);
        });
      }
      util.log(playerName + " drops " + itemName + " at " + room.getLocation() + ".");

      player.removeItem(item);
      room.addItem(item.getUuid());
      item.setInventory(null);
      item.setRoom(room.getLocation());
    }
  };
};
<|endoftext|>


<commit_before>var $ = function(selector) {
  return [].slice.call(document.querySelectorAll(selector))
};

var slider = new Slider({
  width: 540,
  height: 400,
  sliders: [{
    tag: 'div',
    className: 'm-slider-item snake-box',
    content: 'snake',
    fn: snake
  }, {
    tag: 'div',
    className: 'm-cube',
    content: 'cube',
    fn: animationCube
  }]
});
<commit_msg>Update index.js<commit_after>var $ = function(selector) {
  return [].slice.call(document.querySelectorAll(selector))
};

var slider = new Slider({
  width: 540,
  height: 400,
  sliders: [{
    tag: 'div',
    className: 'm-slider-item snake-box',
    content: 'snake',
    fn: snake
  }, {
    tag: 'div',
    className: 'm-slider-item m-cube',
    content: 'cube',
    fn: animationCube
  }]
});
<|endoftext|>