<commit_before>define(['underscore'], function(_) {

    var BASE_MAP_SIZE = 200;

    var module = {};

    var exp = {},
        map = {};

    var ADD = '+', SUBTRACT = '-', MULTIPLY = '*', DIVIDE = '/';
    var operatorPrecedence = {};

    // Create a map of the operator precedence
    _.each([DIVIDE, MULTIPLY, ADD, SUBTRACT], function(o, i) {
        operatorPrecedence[o] = i + 1;
    });

    // A simple class system
    var klass = function(base, ctor) {
        if(arguments.length === 1) {
            ctor = base;
            base = Object;
        }

        ctor.prototype = new base();

        return function() {
            var result = Object.create(ctor.prototype);
            ctor.apply(result, arguments);
            return result;
        };
    };

    // The base expression from which all others are derived
    exp.base = klass(function() {
        this.build = function() { throw 'Must override'; }
    });

    var def = function(val, d) {
        return (val !== undefined) ? val : d;
    };

    exp.buildParams = klass(function(opts) {
        var self = this;

        this.coerce = def(opts.coerce, false);
        this.isRoot = def(opts.isRoot, false);
        this.depth = def(opts.depth, 0);
        this.isBinaryOperand = def(opts.isBinaryOperand, false);
        this.isLeftOperand = def(opts.isLeftOperand, false);
        this.parentOperator = def(opts.parentOperator, null);

        this.createChild = function(opts) {
            opts.depth = def(opts.depth, self.depth + 1);
            opts.isBinaryOperand = def(opts.isBinaryOperand, self.isBinaryOperand);
            return exp.buildParams(opts);
        };
    });

    exp.buildResult = klass(function() {
        var self = this;

        this.type = null;
        this.numeric = null;
        this.symbolic = '';
        this.strategy = '';
        this.leafiness = 0;
        this.isAtomic = false;
        this.isAssociative = true;
        this.operatorPrecedence = 0;
        this.containsConcat = false;
        this.hasParenthesis = false;
    });

    // A unit expression, either 0 or 1, created by coercing
    // an array literal between Array, Number and Boolean types.
    // All expression trees are comprised of at least one unit expression.
    exp.unit = klass(exp.base, function(val) {
        this.getType = function() { return 'unit'; }
        this.build = function(params) {
            if(val === 0 || val === 1) {
                var s;
                if(val === 0) { s = '+[]'; }
                if(val === 1) { s = params.coerce ? '+!+[]' : '!+[]'; }

                var result = exp.buildResult();
                result.type = 'unit';
                result.symbolic = s;
                result.strategy = 'unit_' + val;
                result.numeric = val;
                result.isAtomic = true;

                return result;
            }
            throw 'Invalid Unit';
        };
    });

    // A binary expression which supports addition, subtraction, multiplication and division.
    // Most of the power of the efficiency of the number system is derived from these binary expressions.
    exp.binary = klass(exp.base, function(left, op, right) {

        var self = this;

        var myPrecedence = operatorPrecedence[op];
        var myAssociativity = (op === ADD || op === MULTIPLY);

        var doesNeedParenthesis = function(expr, params, result) {
            // If the operand is truly atomic, it won't need any parenthesis
            if(result.isAtomic) {
                return false;
            }

            // Parenthesis are required if our operation is not associative,
            // or the operation at the root of the sub-tree is not associative,
            // or our operator precedence will change the meaning of the expression.
            return  !myAssociativity
                    || !result.isAssociative
                    || myPrecedence < result.operatorPrecedence;
        };

        var evaluateNumeric = function(leftOperand, rightOperand) {
            if(op === ADD)          return leftOperand + rightOperand;
            if(op === SUBTRACT)     return leftOperand - rightOperand;
            if(op === MULTIPLY)     return leftOperand * rightOperand;
            if(op === DIVIDE)       return leftOperand / rightOperand;
        };

        var makeChildParams = function(params, isLeft) {
            // Only the left operand needs to be explicitly coerced to a number,
            // and only addition (as it can be confused with concatenation).
            var shouldCoerce = isLeft && params.coerce && op === ADD;

            return params.createChild({
                coerce: shouldCoerce,
                isBinaryOperand: true,
                isLeftOperand: isLeft,
                parentOperator: op
            });
        };

        this.build = function(params) {

            var binaryResult = exp.buildResult();

            // Map each operand if necessary
            var leftExpr = (typeof left === 'number') ? exp.map(left) : left,
                rightExpr = (typeof left === 'number') ? exp.map(right) : right;

            // Create child parameters for each sub-expression
            var leftParams = makeChildParams(params, true),
                rightParams = makeChildParams(params, false);

            // Build each sub-expression
            var leftResult = leftExpr.build(leftParams),
                rightResult = rightExpr.build(rightParams);

            // Determine if each sub-expression requires parenthesis.
            var leftRequiresParenthesis = doesNeedParenthesis(leftExpr, leftParams, leftResult);
            var rightRequiresParenthesis = doesNeedParenthesis(rightExpr, rightParams, rightResult);

            if(leftResult.type === 'unit' && rightResult.type === 'concat' && op === ADD) {
                leftRequiresParenthesis = true;
            }

            // Apply parenthesis if necessary
            if(leftRequiresParenthesis && !leftResult.hasParenthesis) {
                leftResult.symbolic = '(' + leftResult.symbolic + ')';
            }

            if(rightRequiresParenthesis && !rightResult.hasParenthesis) {
                rightResult.symbolic = '(' + rightResult.symbolic + ')';
            }

            binaryResult.numeric = evaluateNumeric(leftResult.numeric, rightResult.numeric);
            binaryResult.strategy = String(leftResult.numeric) + op + String(rightResult.numeric);
            binaryResult.symbolic = leftResult.symbolic + op + rightResult.symbolic;
            binaryResult.operatorPrecedence = myPrecedence;
            binaryResult.isAssociative = myAssociativity;
            binaryResult.containsConcat = leftResult.containsConcat || rightResult.containsConcat;
            binaryResult.leafiness = 1 + Math.max(leftResult.leafiness, rightResult.leafiness);

            return binaryResult;
        };
    });

    // The concat expression abuses coercion between Arrays and Strings, and Strings to numbers.
    // It is a little known fact that single element arrays can be coerced to strings (e.g., ['a'] + 'b' == 'ab').
    // We can use this to form numbers one decimal digit at a time (e.g., [1]+[0]+[0] == '100')
    // It is an excellent general case, capable of representing any number, provided that it has at least two digits.
    // It is also an efficient representation in many cases, although it's complexity does scale linearly with
    // the number of decimal digits in the number.
    exp.concat = klass(exp.base, function(val) {

        this.build = function(params) {

            var digits = String(val).split(''),
                parts = [],
                result = exp.buildResult(),
                childParams,
                symbolic,
                i;

            for(i = 0; i < digits.length; i++) {
                childParams = params.createChild({ coerce: true });
                parts.push( exp.map( Number(digits[i]) ).build(childParams) );
            }

            // Build the symbolic representation
            symbolic = _.map(parts, function(r) { return '[' + r.symbolic + ']'; });
            symbolic = '(' + symbolic.join('+') + ')';
            if(params.coerce) {
                symbolic = '+' + symbolic;
            }

            result.type = 'concat';
            result.symbolic = symbolic;
            result.numeric = val;
            result.strategy = 'concat_' + val;
            result.leafiness = 1 + _.reduce(parts, function(max, r) { return Math.max(r.leafiness, max); }, 0);
            result.containsConcat = true;
            result.isAssociative = params.isCoerced === false && params.parentOperator !== ADD;
            result.hasParenthesis = params.isLeftOperand;
            result.isAtomic = result.hasParenthesis;

            return result;
        };
    });

    // An expression proxy. The expression will be lazily initialised once any method is called.
    exp.lazy = klass(exp.base, function(val) {
        var memo = null;
        var init = function() {
            !map[val] && exp.chooseBest(val);
            memo = map[val];
        };
        this.build = function(params) { init(); return memo.build(params); };
    });

    // Get the expression for a value from the map, or return a lazily initialised proxy if it doesn't exist.
    exp.map = function(val) {
        return map[val] || exp.lazy(val);
    };

    exp.chooseBest = function(value, options) {

        var defaults = {
            maxPasses: 5,
            skipLarger: false,
            missingFilter: function(v) { return v <= 10000; }
        };

        options = _.extend({}, defaults, options);

        var missingMapping = [];

        var pass = function(val) {

            var winner = null, smallest = Number.POSITIVE_INFINITY, count = 0;
            var trySolution = function(expr) {
                var built = expr.build(exp.buildParams({ coerce: true })),
                    len = built.symbolic.length;

                if(len < smallest) {
                    smallest = len;
                    winner = { name: built.strategy, expr: expr };
                }

                count++;
            };

            trySolution(exp.concat(val));

            var isCandidate = function(n) {
                n = +n;
                if(n < 0 || Math.floor(n) !== Math.ceil(n)) {
                    return false;
                }

                return true;
            };

            var expand = function(val) {
                var existing = map[val];
                if(existing) {
                    return existing;
                }

                missingMapping.push(val);
                return exp.concat(val);
            }

            var i, a, b;

            var max = Math.min(Math.ceil(val / 2), BASE_MAP_SIZE);
            for(i = 1; i <= max; i++) {
                a = i;
                // val = a + b
                b = val - a;
                if(isCandidate(b)) {
                    // Sometimes the coercion is more efficient by swapping the operands
                    trySolution(exp.binary(expand(a), ADD, expand(b)));
                    trySolution(exp.binary(expand(b), ADD, expand(a)));
                }
            }

            max = Math.ceil(Math.sqrt(val));
            for(i = 1; i <= max; i++) {
                a = i;
                // val = a * b
                b = val / a;
                if(isCandidate(b)) {
                    trySolution(exp.binary(expand(a), MULTIPLY, expand(b)));
                }
            }

            if(!options.skipLarger) {
                max = val + BASE_MAP_SIZE;
                for(i = val + 1; i <= max; i++) {
                    a = i;
                    // val = a - b
                    b = -(val - a);
                    if(isCandidate(b)) {
                        trySolution(exp.binary(expand(a), SUBTRACT, expand(b)));
                    }
                }

                max = BASE_MAP_SIZE;
                for(i = 2; i <= max; i++) {
                    b = i;
                    // val = a / b
                    a = val * b;
                    if(isCandidate(b)) {
                        trySolution(exp.binary(expand(a), DIVIDE, expand(b)));
                    }
                }
            }

            return winner.expr;
        };

        for(var i = 0; i < options.maxPasses; i++) {
            map[value] = pass(value);
            missingMapping = _.uniq(_.filter(missingMapping, options.missingFilter));

            if(missingMapping.length === 0) {
                break;
            }

            var temp;
            missingMapping = [];
            _.each(temp, function(v) {
                map[v] = pass(v);
            });
        }

        return { missing: missingMapping };
    };

    var isInitialised = false;

    var initialiseMap = function() {
        if(isInitialised) { return };
        isInitialised = true;

        map[0] = exp.unit(0);
        map[1] = exp.unit(1);
        map[2] = exp.binary(1, ADD, 1);
        map[3] = exp.binary(1, ADD, 2);
        map[4] = exp.binary(2, ADD, 2);
        map[5] = exp.binary(10, DIVIDE, 2);
        map[6] = exp.binary(3, MULTIPLY, 2);
        map[7] = exp.binary(10, SUBTRACT, 3);
        map[8] = exp.binary(10, SUBTRACT, 2);
        map[9] = exp.binary(10, SUBTRACT, 1);
        map[10] = exp.concat(10);

        // Start by filling out the base map in a strictly incrementing fashion,
        // ignoring any candidates involving larger numbers.
        for(var i = 11; i <= BASE_MAP_SIZE; i++) {
            exp.chooseBest(i, { maxPasses: 1, skipLarger: true });
        }

        // Perform a second pass, this time considering larger candidates
        for(var i = 11; i <= BASE_MAP_SIZE; i++) {
            exp.chooseBest(i, { maxPasses: 1 });
        }

    };

    module.getSymbolic = function(val) {
        initialiseMap();

        var result = exp.map(val).build(exp.buildParams({ coerce: true })),
            symbolic = result.symbolic,
            validator = new Function('return (' + symbolic + ');');

        if(validator() !== val) {
            throw 'Symbolic representation did not match expected value.';
        }

        console.log(result.strategy);

        return symbolic;
    };

    module.test = function() {
        initialiseMap();

        var pad = function(direction, input, width) {
            input = String(input);
            while(input.length < width) {
                input = (direction === 'left') ? (' ' + input) : (input + ' ');
            }
            return input;
        };
        var padLeft = _.partial(pad, 'left');
        var padRight = _.partial(pad, 'right');

        var total = 0;
        for(var i = 0; i <= BASE_MAP_SIZE; i++) {
            var result = exp.map(i).build(exp.buildParams({ coerce: true }));
            var symbolic = result.symbolic;
            var validator = new Function('return (' + symbolic + ');');
            var evaluated = validator();
            total += symbolic.length;

            var strategy = result.strategy;

            var info = padLeft(i, 3) + '=' + padRight(evaluated, 3) + ' ' + padLeft(symbolic.length, 2) + 'chars. ' + padRight(strategy, 11) + ' ' + symbolic;

            if((i === evaluated)) {
                console.log(info);
            } else {
                console.log('FAIL ' + info);
            }
        }
        console.log('TOTAL: ' + total + ' chars.');
    };

    return module;
});<commit_msg>Added shift operators<commit_after>define(['underscore'], function(_) {

    var BASE_MAP_SIZE = 200;

    var module = {};

    var exp = {},
        map = {};

    var ADD = '+', SUBTRACT = '-', MULTIPLY = '*', DIVIDE = '/', LSHIFT = '<<', RSHIFT = '>>';
    var operatorPrecedence = {};

    // Create a map of the operator precedence
    _.each([DIVIDE, MULTIPLY, ADD, SUBTRACT, LSHIFT, RSHIFT], function(o, i) {
        operatorPrecedence[o] = i + 1;
    });

    // A simple class system
    var klass = function(base, ctor) {
        if(arguments.length === 1) {
            ctor = base;
            base = Object;
        }

        ctor.prototype = new base();

        return function() {
            var result = Object.create(ctor.prototype);
            ctor.apply(result, arguments);
            return result;
        };
    };

    // The base expression from which all others are derived
    exp.base = klass(function() {
        this.build = function() { throw 'Must override'; }
    });

    var def = function(val, d) {
        return (val !== undefined) ? val : d;
    };

    exp.buildParams = klass(function(opts) {
        var self = this;

        this.coerce = def(opts.coerce, false);
        this.isRoot = def(opts.isRoot, false);
        this.depth = def(opts.depth, 0);
        this.isBinaryOperand = def(opts.isBinaryOperand, false);
        this.isLeftOperand = def(opts.isLeftOperand, false);
        this.parentOperator = def(opts.parentOperator, null);

        this.createChild = function(opts) {
            opts.depth = def(opts.depth, self.depth + 1);
            opts.isBinaryOperand = def(opts.isBinaryOperand, self.isBinaryOperand);
            return exp.buildParams(opts);
        };
    });

    exp.buildResult = klass(function() {
        var self = this;

        this.type = null;
        this.numeric = null;
        this.symbolic = '';
        this.strategy = '';
        this.leafiness = 0;
        this.isAtomic = false;
        this.isAssociative = true;
        this.operatorPrecedence = 0;
        this.containsConcat = false;
        this.hasParenthesis = false;
    });

    // A unit expression, either 0 or 1, created by coercing
    // an array literal between Array, Number and Boolean types.
    // All expression trees are comprised of at least one unit expression.
    exp.unit = klass(exp.base, function(val) {
        this.getType = function() { return 'unit'; }
        this.build = function(params) {
            if(val === 0 || val === 1) {
                var s;
                if(val === 0) { s = '+[]'; }
                if(val === 1) { s = params.coerce ? '+!+[]' : '!+[]'; }

                var result = exp.buildResult();
                result.type = 'unit';
                result.symbolic = s;
                result.strategy = 'unit_' + val;
                result.numeric = val;
                result.isAtomic = true;

                return result;
            }
            throw 'Invalid Unit';
        };
    });

    // A binary expression which supports addition, subtraction, multiplication and division.
    // Most of the power of the efficiency of the number system is derived from these binary expressions.
    exp.binary = klass(exp.base, function(left, op, right) {

        var self = this;

        var myPrecedence = operatorPrecedence[op];
        var myAssociativity = (op === ADD || op === MULTIPLY);

        var doesNeedParenthesis = function(expr, params, result) {
            // If the operand is truly atomic, it won't need any parenthesis
            if(result.isAtomic) {
                return false;
            }

            // Parenthesis are required if our operation is not associative,
            // or the operation at the root of the sub-tree is not associative,
            // or our operator precedence will change the meaning of the expression.
            return  !myAssociativity
                    || !result.isAssociative
                    || myPrecedence < result.operatorPrecedence;
        };

        var evaluateNumeric = function(leftOperand, rightOperand) {
            if(op === ADD)          return leftOperand + rightOperand;
            if(op === SUBTRACT)     return leftOperand - rightOperand;
            if(op === MULTIPLY)     return leftOperand * rightOperand;
            if(op === DIVIDE)       return leftOperand / rightOperand;
            if(op === LSHIFT)       return leftOperand << rightOperand;
            if(op === RSHIFT)       return leftOperand >> rightOperand;
        };

        var makeChildParams = function(params, isLeft) {
            // Only the left operand needs to be explicitly coerced to a number,
            // and only addition (as it can be confused with concatenation).
            var shouldCoerce = isLeft && params.coerce && op === ADD;

            return params.createChild({
                coerce: shouldCoerce,
                isBinaryOperand: true,
                isLeftOperand: isLeft,
                parentOperator: op
            });
        };

        this.build = function(params) {

            var binaryResult = exp.buildResult();

            // Map each operand if necessary
            var leftExpr = (typeof left === 'number') ? exp.map(left) : left,
                rightExpr = (typeof left === 'number') ? exp.map(right) : right;

            // Create child parameters for each sub-expression
            var leftParams = makeChildParams(params, true),
                rightParams = makeChildParams(params, false);

            // Build each sub-expression
            var leftResult = leftExpr.build(leftParams),
                rightResult = rightExpr.build(rightParams);

            // Determine if each sub-expression requires parenthesis.
            var leftRequiresParenthesis = doesNeedParenthesis(leftExpr, leftParams, leftResult);
            var rightRequiresParenthesis = doesNeedParenthesis(rightExpr, rightParams, rightResult);

            if(leftResult.type === 'unit' && rightResult.type === 'concat' && op === ADD) {
                leftRequiresParenthesis = true;
            }

            // Apply parenthesis if necessary
            if(leftRequiresParenthesis && !leftResult.hasParenthesis) {
                leftResult.symbolic = '(' + leftResult.symbolic + ')';
            }

            if(rightRequiresParenthesis && !rightResult.hasParenthesis) {
                rightResult.symbolic = '(' + rightResult.symbolic + ')';
            }

            binaryResult.numeric = evaluateNumeric(leftResult.numeric, rightResult.numeric);
            binaryResult.strategy = String(leftResult.numeric) + op + String(rightResult.numeric);
            binaryResult.symbolic = leftResult.symbolic + op + rightResult.symbolic;
            binaryResult.operatorPrecedence = myPrecedence;
            binaryResult.isAssociative = myAssociativity;
            binaryResult.containsConcat = leftResult.containsConcat || rightResult.containsConcat;
            binaryResult.leafiness = 1 + Math.max(leftResult.leafiness, rightResult.leafiness);

            return binaryResult;
        };
    });

    // The concat expression abuses coercion between Arrays and Strings, and Strings to numbers.
    // It is a little known fact that single element arrays can be coerced to strings (e.g., ['a'] + 'b' == 'ab').
    // We can use this to form numbers one decimal digit at a time (e.g., [1]+[0]+[0] == '100')
    // It is an excellent general case, capable of representing any number, provided that it has at least two digits.
    // It is also an efficient representation in many cases, although it's complexity does scale linearly with
    // the number of decimal digits in the number.
    exp.concat = klass(exp.base, function(val) {

        this.build = function(params) {

            var digits = String(val).split(''),
                parts = [],
                result = exp.buildResult(),
                childParams,
                symbolic,
                i;

            for(i = 0; i < digits.length; i++) {
                childParams = params.createChild({ coerce: true });
                parts.push( exp.map( Number(digits[i]) ).build(childParams) );
            }

            // Build the symbolic representation
            symbolic = _.map(parts, function(r) { return '[' + r.symbolic + ']'; });
            symbolic = '(' + symbolic.join('+') + ')';
            if(params.coerce) {
                symbolic = '+' + symbolic;
            }

            result.type = 'concat';
            result.symbolic = symbolic;
            result.numeric = val;
            result.strategy = 'concat_' + val;
            result.leafiness = 1 + _.reduce(parts, function(max, r) { return Math.max(r.leafiness, max); }, 0);
            result.containsConcat = true;
            result.isAssociative = params.isCoerced === false && params.parentOperator !== ADD;
            result.hasParenthesis = params.isLeftOperand;
            result.isAtomic = result.hasParenthesis;

            return result;
        };
    });

    // An expression proxy. The expression will be lazily initialised once any method is called.
    exp.lazy = klass(exp.base, function(val) {
        var memo = null;
        var init = function() {
            !map[val] && exp.chooseBest(val);
            memo = map[val];
        };
        this.build = function(params) { init(); return memo.build(params); };
    });

    // Get the expression for a value from the map, or return a lazily initialised proxy if it doesn't exist.
    exp.map = function(val) {
        return map[val] || exp.lazy(val);
    };

    exp.chooseBest = function(value, options) {

        var defaults = {
            maxPasses: 5,
            skipLarger: false,
            missingFilter: function(v) { return v <= 10000; }
        };

        options = _.extend({}, defaults, options);

        var missingMapping = [];

        var pass = function(val) {

            var winner = null, smallest = Number.POSITIVE_INFINITY, count = 0;
            var trySolution = function(expr) {
                var built = expr.build(exp.buildParams({ coerce: true })),
                    len = built.symbolic.length;

                if(len < smallest) {
                    smallest = len;
                    winner = { name: built.strategy, expr: expr };
                }

                count++;
            };

            trySolution(exp.concat(val));

            var isCandidate = function(n) {
                n = +n;
                if(n < 0 || Math.floor(n) !== Math.ceil(n)) {
                    return false;
                }

                return true;
            };

            var expand = function(val) {
                var existing = map[val];
                if(existing) {
                    return existing;
                }

                missingMapping.push(val);
                return exp.concat(val);
            }

            var i, a, b;

            var max = Math.min(Math.ceil(val / 2), BASE_MAP_SIZE);
            for(i = 1; i <= max; i++) {
                a = i;
                // val = a + b
                b = val - a;
                if(isCandidate(b)) {
                    // Sometimes the coercion is more efficient by swapping the operands
                    trySolution(exp.binary(expand(a), ADD, expand(b)));
                    trySolution(exp.binary(expand(b), ADD, expand(a)));
                }
            }

            max = Math.ceil(Math.sqrt(val));
            for(i = 1; i <= max; i++) {
                a = i;
                // val = a * b
                b = val / a;
                if(isCandidate(b)) {
                    trySolution(exp.binary(expand(a), MULTIPLY, expand(b)));

                    // val = a << b
                    b = Math.log(b)/Math.log(2);
                    if(isCandidate(b)) {
                        trySolution(exp.binary(expand(a), LSHIFT, expand(b)));
                    }

                    // Multiplications are commutative but shifts are not
                    // val = b << a
                    b = val / a;
                    a = Math.log(a)/Math.log(2);
                    if(isCandidate(a)) {
                       trySolution(exp.binary(expand(b), LSHIFT, expand(a)));
                    }
                }
            }

            if(!options.skipLarger) {
                max = val + BASE_MAP_SIZE;
                for(i = val + 1; i <= max; i++) {
                    a = i;
                    // val = a - b
                    b = -(val - a);
                    if(isCandidate(b)) {
                        trySolution(exp.binary(expand(a), SUBTRACT, expand(b)));
                    }
                }

                max = BASE_MAP_SIZE;
                for(i = 2; i <= max; i++) {
                    b = i;
                    // val = a / b
                    a = val * b;
                    trySolution(exp.binary(expand(a), DIVIDE, expand(b)));

                    // val = a >> b
                    b = Math.log(b)/Math.log(2);
                    if(isCandidate(b)) {
                        trySolution(exp.binary(expand(a), RSHIFT, expand(b)));
                    }
                }
            }

            return winner.expr;
        };

        for(var i = 0; i < options.maxPasses; i++) {
            map[value] = pass(value);
            missingMapping = _.uniq(_.filter(missingMapping, options.missingFilter));

            if(missingMapping.length === 0) {
                break;
            }

            var temp;
            missingMapping = [];
            _.each(temp, function(v) {
                map[v] = pass(v);
            });
        }

        return { missing: missingMapping };
    };

    var isInitialised = false;

    var initialiseMap = function() {
        if(isInitialised) { return };
        isInitialised = true;

        map[0] = exp.unit(0);
        map[1] = exp.unit(1);
        map[2] = exp.binary(1, ADD, 1);
        map[3] = exp.binary(1, ADD, 2);
        map[4] = exp.binary(2, ADD, 2);
        map[5] = exp.binary(10, RSHIFT, 1);
        map[6] = exp.binary(3, LSHIFT, 1);
        map[7] = exp.binary(10, SUBTRACT, 3);
        map[8] = exp.binary(10, SUBTRACT, 2);
        map[9] = exp.binary(10, SUBTRACT, 1);
        map[10] = exp.concat(10);

        // Start by filling out the base map in a strictly incrementing fashion,
        // ignoring any candidates involving larger numbers.
        for(var i = 11; i <= BASE_MAP_SIZE; i++) {
            exp.chooseBest(i, { maxPasses: 1, skipLarger: true });
        }

        // Perform a second pass, this time considering larger candidates
        for(var i = 11; i <= BASE_MAP_SIZE; i++) {
            exp.chooseBest(i, { maxPasses: 1 });
        }

    };

    module.getSymbolic = function(val) {
        initialiseMap();

        var result = exp.map(val).build(exp.buildParams({ coerce: true })),
            symbolic = result.symbolic,
            validator = new Function('return (' + symbolic + ');');

        if(validator() !== val) {
            throw 'Symbolic representation did not match expected value.';
        }

        console.log(result.strategy);

        return symbolic;
    };

    module.test = function() {
        var testStart = new Date();
        initialiseMap();

        var pad = function(direction, input, width) {
            input = String(input);
            while(input.length < width) {
                input = (direction === 'left') ? (' ' + input) : (input + ' ');
            }
            return input;
        };
        var padLeft = _.partial(pad, 'left');
        var padRight = _.partial(pad, 'right');

        var total = 0;
        for(var i = 0; i <= BASE_MAP_SIZE; i++) {
            var result = exp.map(i).build(exp.buildParams({ coerce: true }));
            var symbolic = result.symbolic;
            var validator = new Function('return (' + symbolic + ');');
            var evaluated = validator();
            total += symbolic.length;

            var strategy = result.strategy;

            var info = padLeft(i, 3) + '=' + padRight(evaluated, 3) + ' ' + padLeft(symbolic.length, 2) + 'chars. ' + padRight(strategy, 11) + ' ' + symbolic;

            if((i === evaluated)) {
                console.log(info);
            } else {
                console.log('FAIL ' + info);
            }
        }
        console.log('TOTAL: ' + total + ' chars.');

        var testTime = new Date().getTime() - testStart.getTime();
        console.log('Test Time: ' + testTime + 'ms');
    };

    return module;
});<|endoftext|>


<commit_before>var text = []; //"content of text here";
var delay = 50;
var currentWord = 0;
var currentChar = 1;
var destination = "[set in call to type]";
var dest = null;

console.log("testing - 1");

function type() {
    if (document.getElementById) {
        dest = document.getElementById(destination);
        if (dest) {
            dest.innerHTML = text[currentWord].substr(0, currentChar);
            ++currentChar;
            if (currentChar > text[currentWord].length) {

                setTimeout("unType()", 2500);

                currentChar = 1;
                if (++currentWord === text.length) {
                    currentWord = 0;
                }

            }
            else
                setTimeout("type()", delay);
        }
    }
}

function unType() {
    console.log("unType()");
    dest.innerHTML = text[currentWord].substr(0, currentChar - 2);

    if (currentChar === 1)
        type();
}

function startTyping(textParam, delayParam, destinationParam) {
    text = textParam;
    delay = delayParam;
    currentChar = 1;
    destination = destinationParam;
    type();
}

startTyping(["Software Developer", "University of Texas Student", "Entrepreneur"], 50, "messages");<commit_msg>changed version number<commit_after>var text = []; //"content of text here";
var delay = 50;
var currentWord = 0;
var currentChar = 1;
var destination = "[set in call to type]";
var dest = null;

console.log("testing - 2");

function type() {
    if (document.getElementById) {
        dest = document.getElementById(destination);
        if (dest) {
            dest.innerHTML = text[currentWord].substr(0, currentChar);
            ++currentChar;
            if (currentChar > text[currentWord].length) {

                setTimeout("unType()", 2500);

                currentChar = 1;
                if (++currentWord === text.length) {
                    currentWord = 0;
                }

            }
            else
                setTimeout("type()", delay);
        }
    }
}

function unType() {
    console.log("unType()");
    dest.innerHTML = text[currentWord].substr(0, currentChar - 2);

    if (currentChar === 1)
        type();
}

function startTyping(textParam, delayParam, destinationParam) {
    text = textParam;
    delay = delayParam;
    currentChar = 1;
    destination = destinationParam;
    type();
}

startTyping(["Software Developer", "University of Texas Student", "Entrepreneur"], 50, "messages");<|endoftext|>


<commit_before>var map = new BMap.Map("jjz-map");
var point = new BMap.Point(116.400244, 39.92556);
map.centerAndZoom(point, 12);

map.addControl(new BMap.NavigationControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT }));// 添加平移缩放控件
map.addControl(new BMap.ScaleControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT }));// 添加比例尺控件
map.addControl(new BMap.MapTypeControl());//添加地图类型控件
map.enableScrollWheelZoom();//启用滚轮放大缩小
map.disable3DBuilding();// 禁用地图的3D楼块展现功能

var ctrl = new BMapLib.TrafficControl();
map.addControl(ctrl);
ctrl.setAnchor(BMAP_ANCHOR_TOP_LEFT);
// ctrl.showTraffic() // 显示实时路况，暂不默认开启

// 添加定位控件
var geolocationControl = new BMap.GeolocationControl();
map.addControl(geolocationControl);

geolocationControl.addEventListener("locationSuccess", function (e) {
    // 定位成功事件
    var address = '';
    address += e.addressComponent.province;
    address += e.addressComponent.city;
    address += e.addressComponent.district;
    address += e.addressComponent.street;
    address += e.addressComponent.streetNumber;
    console.log("当前定位地址为：" + address);
    var point1 = new BMap.Point(e.point.lng, e.point.lat);// 创建点坐标(经度,纬度)
    var mk = new BMap.Marker(point1);// 创建标注
    map.addOverlay(mk);// 将标注添加到地图中
    mk.enableDragging();//可拖拽 disableDragging（不可拖拽）
    mk.setAnimation(BMAP_ANIMATION_BOUNCE);//跳动的动画
    map.panTo(point1);//移动
});

geolocationControl.addEventListener("locationError", function (e) {
    // 定位失败事件
    alert(e.message);
});

var polyline = new BMap.Polyline([new BMap.Point(116.385871, 39.955059), new BMap.Point(116.436734, 39.95575), new BMap.Point(116.438925, 39.955197), new BMap.Point(116.440264, 39.953427), new BMap.Point(116.441548, 39.920012), new BMap.Point(116.442141, 39.916927), new BMap.Point(116.44277, 39.907588), new BMap.Point(116.444782, 39.905623), new BMap.Point(116.450603, 39.903714), new BMap.Point(116.452813, 39.884186), new BMap.Point(116.450549, 39.877763), new BMap.Point(116.447926, 39.876296), new BMap.Point(116.424391, 39.877293), new BMap.Point(116.421265, 39.878539), new BMap.Point(116.390291, 39.877348), new BMap.Point(116.373223, 39.875549), new BMap.Point(116.365103, 39.874164), new BMap.Point(116.357198, 39.874386), new BMap.Point(116.355329, 39.876241), new BMap.Point(116.355976, 39.881307), new BMap.Point(116.355221, 39.902344), new BMap.Point(116.356946, 39.903838), new BMap.Point(116.362551, 39.904641), new BMap.Point(116.36336, 39.905969), new BMap.Point(116.363216, 39.917923), new BMap.Point(116.362048, 39.948297), new BMap.Point(116.364258, 39.950164), new BMap.Point(116.378865, 39.954658), new BMap.Point(116.385898, 39.955073)], {
        strokeColor: "red",
        strokeWeight: 3,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.468336, 39.914022), new BMap.Point(116.441495, 39.914506), new BMap.Point(116.424382, 39.914402), new BMap.Point(116.398035, 39.913752), new BMap.Point(116.363019, 39.912929), new BMap.Point(116.316801, 39.91351)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.412686, 39.930619), new BMap.Point(116.41318, 39.919327), new BMap.Point(116.413072, 39.914291)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.409717, 39.914188), new BMap.Point(116.408909, 39.929796)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.413054, 39.914184), new BMap.Point(116.413198, 39.907121)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.41786, 39.914267), new BMap.Point(116.418157, 39.907253)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.405746, 39.914039), new BMap.Point(116.406097, 39.906671)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.402504, 39.906464), new BMap.Point(116.402072, 39.913894)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.398066, 39.913756), new BMap.Point(116.398255, 39.909709), new BMap.Point(116.398048, 39.909349), new BMap.Point(116.398174, 39.906734)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.398264, 39.909705), new BMap.Point(116.399485, 39.909152), new BMap.Point(116.40236, 39.909248)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线

// 添加点击事件侦听
function addClickHandler(marker, title, content) {
        marker.addEventListener("click",
        function(e) {
                displayInfo(title, content, e)
        });
}
if (typeof(points) != 'undefined') {
        // 在地图中输出坐标点
        for (var i = 0,
        n = points.length; i < n; i++) {
                var point = new BMap.Point(points[i].pointx, points[i].pointy);
                addMarker(point, points[i].pathname);
        }
}
// 添加覆盖物
function addMarker(point, title, content) {
        var marker = new BMap.Marker(point);
        var label = new BMap.Label(title, {
                offset: new BMap.Size(20, -10)
        });
        label.setStyle({
                display: "none"
        });
        if (points[i].biaozhu == "1") {
                marker = new BMap.Marker(point, {
                        icon: new BMap.Icon(blue_icon, new BMap.Size(20, 25)),
                        offset: new BMap.Size(0, -10)
                }); //创建对象
        } else {
                marker = new BMap.Marker(point, {
                        icon: new BMap.Icon(red_icon, new BMap.Size(20, 25)),
                        offset: new BMap.Size(0, -10)
                });
        }
        marker.setLabel(label);
        marker.addEventListener("mouseover",
        function() {
                label.setStyle({ //给label设置样式，任意的CSS都是可以的
                        display: "block"
                });
        });
        marker.addEventListener("mouseout",
        function() {
                label.setStyle({ //给label设置样式，任意的CSS都是可以的
                        display: "none"
                });
        });
        map.addOverlay(marker);
        var opts = {
                title: points[i].title
        };
        var infoWindow = new BMap.InfoWindow(points[i].pathname + '
查看街景     ', opts); // 创建信息窗口对象，引号里可以书写任意的html语句。
        marker.addEventListener("click",
        function() {
                map.openInfoWindow(infoWindow, point); //开启信息窗口
        });
}
<commit_msg>Add console log for mouse click coordinates.<commit_after>var map = new BMap.Map("jjz-map");
var point = new BMap.Point(116.400244, 39.92556);
map.centerAndZoom(point, 12);

map.addControl(new BMap.NavigationControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT }));// 添加平移缩放控件
map.addControl(new BMap.ScaleControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT }));// 添加比例尺控件
map.addControl(new BMap.MapTypeControl());//添加地图类型控件
map.enableScrollWheelZoom();//启用滚轮放大缩小
map.disable3DBuilding();// 禁用地图的3D楼块展现功能

var ctrl = new BMapLib.TrafficControl();
map.addControl(ctrl);
ctrl.setAnchor(BMAP_ANCHOR_TOP_LEFT);
// ctrl.showTraffic() // 显示实时路况，暂不默认开启

// 添加定位控件
var geolocationControl = new BMap.GeolocationControl();
map.addControl(geolocationControl);

geolocationControl.addEventListener("locationSuccess", function (e) {
    // 定位成功事件
    var address = '';
    address += e.addressComponent.province;
    address += e.addressComponent.city;
    address += e.addressComponent.district;
    address += e.addressComponent.street;
    address += e.addressComponent.streetNumber;
    console.log("当前定位地址为：" + address);
    var point1 = new BMap.Point(e.point.lng, e.point.lat);// 创建点坐标(经度,纬度)
    var mk = new BMap.Marker(point1);// 创建标注
    map.addOverlay(mk);// 将标注添加到地图中
    mk.enableDragging();//可拖拽 disableDragging（不可拖拽）
    mk.setAnimation(BMAP_ANIMATION_BOUNCE);//跳动的动画
    map.panTo(point1);//移动
});

geolocationControl.addEventListener("locationError", function (e) {
    // 定位失败事件
    alert(e.message);
});

var polyline = new BMap.Polyline([new BMap.Point(116.385871, 39.955059), new BMap.Point(116.436734, 39.95575), new BMap.Point(116.438925, 39.955197), new BMap.Point(116.440264, 39.953427), new BMap.Point(116.441548, 39.920012), new BMap.Point(116.442141, 39.916927), new BMap.Point(116.44277, 39.907588), new BMap.Point(116.444782, 39.905623), new BMap.Point(116.450603, 39.903714), new BMap.Point(116.452813, 39.884186), new BMap.Point(116.450549, 39.877763), new BMap.Point(116.447926, 39.876296), new BMap.Point(116.424391, 39.877293), new BMap.Point(116.421265, 39.878539), new BMap.Point(116.390291, 39.877348), new BMap.Point(116.373223, 39.875549), new BMap.Point(116.365103, 39.874164), new BMap.Point(116.357198, 39.874386), new BMap.Point(116.355329, 39.876241), new BMap.Point(116.355976, 39.881307), new BMap.Point(116.355221, 39.902344), new BMap.Point(116.356946, 39.903838), new BMap.Point(116.362551, 39.904641), new BMap.Point(116.36336, 39.905969), new BMap.Point(116.363216, 39.917923), new BMap.Point(116.362048, 39.948297), new BMap.Point(116.364258, 39.950164), new BMap.Point(116.378865, 39.954658), new BMap.Point(116.385898, 39.955073)], {
        strokeColor: "red",
        strokeWeight: 3,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.468336, 39.914022), new BMap.Point(116.441495, 39.914506), new BMap.Point(116.424382, 39.914402), new BMap.Point(116.398035, 39.913752), new BMap.Point(116.363019, 39.912929), new BMap.Point(116.316801, 39.91351)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.412686, 39.930619), new BMap.Point(116.41318, 39.919327), new BMap.Point(116.413072, 39.914291)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.409717, 39.914188), new BMap.Point(116.408909, 39.929796)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.413054, 39.914184), new BMap.Point(116.413198, 39.907121)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.41786, 39.914267), new BMap.Point(116.418157, 39.907253)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.405746, 39.914039), new BMap.Point(116.406097, 39.906671)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.402504, 39.906464), new BMap.Point(116.402072, 39.913894)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.398066, 39.913756), new BMap.Point(116.398255, 39.909709), new BMap.Point(116.398048, 39.909349), new BMap.Point(116.398174, 39.906734)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线
var polyline = new BMap.Polyline([new BMap.Point(116.398264, 39.909705), new BMap.Point(116.399485, 39.909152), new BMap.Point(116.40236, 39.909248)], {
        strokeColor: "red",
        strokeWeight: 5,
        strokeOpacity: 0.0
});
map.addOverlay(polyline); //增加折线

// 添加点击事件侦听
function addClickHandler(marker, title, content) {
        marker.addEventListener("click",
        function(e) {
                displayInfo(title, content, e)
        });
}
if (typeof(points) != 'undefined') {
        // 在地图中输出坐标点
        for (var i = 0,
        n = points.length; i < n; i++) {
                var point = new BMap.Point(points[i].pointx, points[i].pointy);
                addMarker(point, points[i].pathname);
        }
}
// 添加覆盖物
function addMarker(point, title, content) {
        var marker = new BMap.Marker(point);
        var label = new BMap.Label(title, {
                offset: new BMap.Size(20, -10)
        });
        label.setStyle({
                display: "none"
        });
        if (points[i].biaozhu == "1") {
                marker = new BMap.Marker(point, {
                        icon: new BMap.Icon(blue_icon, new BMap.Size(20, 25)),
                        offset: new BMap.Size(0, -10)
                }); //创建对象
        } else {
                marker = new BMap.Marker(point, {
                        icon: new BMap.Icon(red_icon, new BMap.Size(20, 25)),
                        offset: new BMap.Size(0, -10)
                });
        }
        marker.setLabel(label);
        marker.addEventListener("mouseover",
        function() {
                label.setStyle({ //给label设置样式，任意的CSS都是可以的
                        display: "block"
                });
        });
        marker.addEventListener("mouseout",
        function() {
                label.setStyle({ //给label设置样式，任意的CSS都是可以的
                        display: "none"
                });
        });
        map.addOverlay(marker);
        var opts = {
                title: points[i].title
        };
        var infoWindow = new BMap.InfoWindow(points[i].pathname + '
查看街景     ', opts); // 创建信息窗口对象，引号里可以书写任意的html语句。
        marker.addEventListener("click",
        function() {
                map.openInfoWindow(infoWindow, point); //开启信息窗口
        });
}

// 显示坐标
function showPoint(e)
{
        console.log(e.point.lng + ", " + e.point.lat);
}
map.addEventListener("click", showPoint);
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { AuthenticationError, ExchangeError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitstamp extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitstamp',
            'name': 'Bitstamp',
            'countries': 'GB',
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'CORS': true,
                'fetchOrder': true,
                'withdraw': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27786377-8c8ab57e-5fe9-11e7-8ea4-2b05b6bcceec.jpg',
                'api': 'https://www.bitstamp.net/api',
                'www': 'https://www.bitstamp.net',
                'doc': 'https://www.bitstamp.net/api',
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                'uid': true,
            },
            'api': {
                'public': {
                    'get': [
                        'order_book/{pair}/',
                        'ticker_hour/{pair}/',
                        'ticker/{pair}/',
                        'transactions/{pair}/',
                        'trading-pairs-info/',
                    ],
                },
                'private': {
                    'post': [
                        'balance/',
                        'balance/{pair}/',
                        'bch_withdrawal/',
                        'bch_address/',
                        'user_transactions/',
                        'user_transactions/{pair}/',
                        'open_orders/all/',
                        'open_orders/{pair}/',
                        'order_status/',
                        'cancel_order/',
                        'buy/{pair}/',
                        'buy/market/{pair}/',
                        'sell/{pair}/',
                        'sell/market/{pair}/',
                        'ltc_withdrawal/',
                        'ltc_address/',
                        'eth_withdrawal/',
                        'eth_address/',
                        'xrp_withdrawal/',
                        'xrp_address/',
                        'transfer-to-main/',
                        'transfer-from-main/',
                        'withdrawal/open/',
                        'withdrawal/status/',
                        'withdrawal/cancel/',
                        'liquidation_address/new/',
                        'liquidation_address/info/',
                    ],
                },
                'v1': {
                    'post': [
                        'bitcoin_deposit_address/',
                        'unconfirmed_btc/',
                        'bitcoin_withdrawal/',
                        'ripple_withdrawal/',
                        'ripple_address/',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': true,
                    'percentage': true,
                    'taker': 0.25 / 100,
                    'maker': 0.25 / 100,
                    'tiers': {
                        'taker': [
                            [0, 0.25 / 100],
                            [20000, 0.24 / 100],
                            [100000, 0.22 / 100],
                            [400000, 0.20 / 100],
                            [600000, 0.15 / 100],
                            [1000000, 0.14 / 100],
                            [2000000, 0.13 / 100],
                            [4000000, 0.12 / 100],
                            [20000000, 0.11 / 100],
                            [20000001, 0.10 / 100],
                        ],
                        'maker': [
                            [0, 0.25 / 100],
                            [20000, 0.24 / 100],
                            [100000, 0.22 / 100],
                            [400000, 0.20 / 100],
                            [600000, 0.15 / 100],
                            [1000000, 0.14 / 100],
                            [2000000, 0.13 / 100],
                            [4000000, 0.12 / 100],
                            [20000000, 0.11 / 100],
                            [20000001, 0.10 / 100],
                        ],
                    },
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0,
                        'BCH': 0,
                        'LTC': 0,
                        'ETH': 0,
                        'XRP': 0,
                        'USD': 25,
                        'EUR': 0.90,
                    },
                    'deposit': {
                        'BTC': 0,
                        'BCH': 0,
                        'LTC': 0,
                        'ETH': 0,
                        'XRP': 0,
                        'USD': 25,
                        'EUR': 0,
                    },
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetTradingPairsInfo ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let symbol = market['name'];
            let [ base, quote ] = symbol.split ('/');
            let baseId = base.toLowerCase ();
            let quoteId = quote.toLowerCase ();
            let symbolId = baseId + '_' + quoteId;
            let id = market['url_symbol'];
            let precision = {
                'amount': market['base_decimals'],
                'price': market['counter_decimals'],
            };
            let [ cost, currency ] = market['minimum_order'].split (' ');
            let active = (market['trading'] === 'Enabled');
            let lot = Math.pow (10, -precision['amount']);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'symbolId': symbolId,
                'info': market,
                'lot': lot,
                'active': active,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': lot,
                        'max': undefined,
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': undefined,
                    },
                    'cost': {
                        'min': parseFloat (cost),
                        'max': undefined,
                    },
                },
            });
        }
        return result;
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetOrderBookPair (this.extend ({
            'pair': this.marketId (symbol),
        }, params));
        let timestamp = parseInt (orderbook['timestamp']) * 1000;
        return this.parseOrderBook (orderbook, timestamp);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let ticker = await this.publicGetTickerPair (this.extend ({
            'pair': this.marketId (symbol),
        }, params));
        let timestamp = parseInt (ticker['timestamp']) * 1000;
        let vwap = parseFloat (ticker['vwap']);
        let baseVolume = parseFloat (ticker['volume']);
        let quoteVolume = baseVolume * vwap;
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (ticker['high']),
            'low': parseFloat (ticker['low']),
            'bid': parseFloat (ticker['bid']),
            'ask': parseFloat (ticker['ask']),
            'vwap': vwap,
            'open': parseFloat (ticker['open']),
            'close': undefined,
            'first': undefined,
            'last': parseFloat (ticker['last']),
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let timestamp = undefined;
        if ('date' in trade) {
            timestamp = parseInt (trade['date']) * 1000;
        } else if ('datetime' in trade) {
            timestamp = this.parse8601 (trade['datetime']);
        }
        let side = (trade['type'] === '0') ? 'buy' : 'sell';
        let order = undefined;
        if ('order_id' in trade)
            order = trade['order_id'].toString ();
        if ('currency_pair' in trade) {
            let marketId = trade['currency_pair'];
            if (marketId in this.markets_by_id)
                market = this.markets_by_id[marketId];
        }
        let price = this.safeFloat (trade, 'price');
        price = this.safeFloat (trade, market['symbolId'], price);
        let amount = this.safeFloat (trade, 'amount');
        amount = this.safeFloat (trade, market['baseId'], amount);
        let id = this.safeValue (trade, 'tid');
        id = this.safeValue (trade, 'id', id);
        if (id)
            id = id.toString ();
        return {
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'order': order,
            'type': undefined,
            'side': side,
            'price': parseFloat (price),
            'amount': parseFloat (amount),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetTransactionsPair (this.extend ({
            'pair': market['id'],
            'time': 'minute',
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balance = await this.privatePostBalance ();
        let result = { 'info': balance };
        let currencies = Object.keys (this.currencies);
        for (let i = 0; i < currencies.length; i++) {
            let currency = currencies[i];
            let lowercase = currency.toLowerCase ();
            let total = lowercase + '_balance';
            let free = lowercase + '_available';
            let used = lowercase + '_reserved';
            let account = this.account ();
            if (free in balance)
                account['free'] = parseFloat (balance[free]);
            if (used in balance)
                account['used'] = parseFloat (balance[used]);
            if (total in balance)
                account['total'] = parseFloat (balance[total]);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let method = 'privatePost' + this.capitalize (side);
        let order = {
            'pair': this.marketId (symbol),
            'amount': amount,
        };
        if (type === 'market')
            method += 'Market';
        else
            order['price'] = price;
        method += 'Pair';
        let response = await this[method] (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostCancelOrder ({ 'id': id });
    }

    parseOrderStatus (order) {
        if ((order['status'] === 'Queue') || (order['status'] === 'Open'))
            return 'open';
        if (order['status'] === 'Finished')
            return 'closed';
        return order['status'];
    }

    async fetchOrderStatus (id, symbol = undefined) {
        await this.loadMarkets ();
        let response = await this.privatePostOrderStatus ({ 'id': id });
        return this.parseOrderStatus (response);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        let method = 'privatePostUserTransactions';
        if (symbol) {
            market = this.market (symbol);
            request['pair'] = market['id'];
            method += 'Pair';
        }
        let response = await this[method] (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostOrderStatus ({ 'id': id });
    }

    getCurrencyName (code) {
        if (code === 'BTC')
            return 'bitcoin';
        return code.toLowerCase ();
    }

    isFiat (code) {
        if (code === 'USD')
            return true;
        if (code === 'EUR')
            return true;
        return false;
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        let isFiat = this.isFiat (code);
        if (isFiat)
            throw new ExchangeError (this.id + ' fiat withdraw() for ' + code + ' is not implemented yet');
        let name = this.getCurrencyName (code);
        let request = {
            'amount': amount,
            'address': address,
        };
        let v1 = (code === 'BTC');
        let method = v1 ? 'v1' : 'private'; // v1 or v2
        method += 'Post' + this.capitalize (name) + 'Withdrawal';
        let query = params;
        if (code === 'XRP') {
            let tag = this.safeString (params, 'destination_tag');
            if (tag) {
                request['destination_tag'] = tag;
                query = this.omit (params, 'destination_tag');
            } else {
                throw new ExchangeError (this.id + ' withdraw() requires a destination_tag param for ' + code);
            }
        }
        let response = await this[method] (this.extend (request, query));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/';
        if (api !== 'v1')
            url += this.version + '/';
        url += this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let auth = nonce + this.uid + this.apiKey;
            let signature = this.encode (this.hmac (this.encode (auth), this.encode (this.secret)));
            query = this.extend ({
                'key': this.apiKey,
                'signature': signature.toUpperCase (),
                'nonce': nonce,
            }, query);
            body = this.urlencode (query);
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let status = this.safeString (response, 'status');
            if (status === 'error') {
                let code = this.safeString (response, 'code');
                if (typeof code !== 'undefined') {
                    if (code === 'API0005')
                        throw new AuthenticationError (this.id + ' invalid signature, use the uid for the main account if you have subaccounts');
                }
                throw new ExchangeError (this.id + ' ' + this.json (response));
            }
        }
    }
}
<commit_msg>Bitstamp parse trade fix<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { AuthenticationError, ExchangeError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitstamp extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitstamp',
            'name': 'Bitstamp',
            'countries': 'GB',
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'CORS': true,
                'fetchOrder': true,
                'withdraw': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/27786377-8c8ab57e-5fe9-11e7-8ea4-2b05b6bcceec.jpg',
                'api': 'https://www.bitstamp.net/api',
                'www': 'https://www.bitstamp.net',
                'doc': 'https://www.bitstamp.net/api',
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                'uid': true,
            },
            'api': {
                'public': {
                    'get': [
                        'order_book/{pair}/',
                        'ticker_hour/{pair}/',
                        'ticker/{pair}/',
                        'transactions/{pair}/',
                        'trading-pairs-info/',
                    ],
                },
                'private': {
                    'post': [
                        'balance/',
                        'balance/{pair}/',
                        'bch_withdrawal/',
                        'bch_address/',
                        'user_transactions/',
                        'user_transactions/{pair}/',
                        'open_orders/all/',
                        'open_orders/{pair}/',
                        'order_status/',
                        'cancel_order/',
                        'buy/{pair}/',
                        'buy/market/{pair}/',
                        'sell/{pair}/',
                        'sell/market/{pair}/',
                        'ltc_withdrawal/',
                        'ltc_address/',
                        'eth_withdrawal/',
                        'eth_address/',
                        'xrp_withdrawal/',
                        'xrp_address/',
                        'transfer-to-main/',
                        'transfer-from-main/',
                        'withdrawal/open/',
                        'withdrawal/status/',
                        'withdrawal/cancel/',
                        'liquidation_address/new/',
                        'liquidation_address/info/',
                    ],
                },
                'v1': {
                    'post': [
                        'bitcoin_deposit_address/',
                        'unconfirmed_btc/',
                        'bitcoin_withdrawal/',
                        'ripple_withdrawal/',
                        'ripple_address/',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': true,
                    'percentage': true,
                    'taker': 0.25 / 100,
                    'maker': 0.25 / 100,
                    'tiers': {
                        'taker': [
                            [0, 0.25 / 100],
                            [20000, 0.24 / 100],
                            [100000, 0.22 / 100],
                            [400000, 0.20 / 100],
                            [600000, 0.15 / 100],
                            [1000000, 0.14 / 100],
                            [2000000, 0.13 / 100],
                            [4000000, 0.12 / 100],
                            [20000000, 0.11 / 100],
                            [20000001, 0.10 / 100],
                        ],
                        'maker': [
                            [0, 0.25 / 100],
                            [20000, 0.24 / 100],
                            [100000, 0.22 / 100],
                            [400000, 0.20 / 100],
                            [600000, 0.15 / 100],
                            [1000000, 0.14 / 100],
                            [2000000, 0.13 / 100],
                            [4000000, 0.12 / 100],
                            [20000000, 0.11 / 100],
                            [20000001, 0.10 / 100],
                        ],
                    },
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0,
                        'BCH': 0,
                        'LTC': 0,
                        'ETH': 0,
                        'XRP': 0,
                        'USD': 25,
                        'EUR': 0.90,
                    },
                    'deposit': {
                        'BTC': 0,
                        'BCH': 0,
                        'LTC': 0,
                        'ETH': 0,
                        'XRP': 0,
                        'USD': 25,
                        'EUR': 0,
                    },
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetTradingPairsInfo ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let symbol = market['name'];
            let [ base, quote ] = symbol.split ('/');
            let baseId = base.toLowerCase ();
            let quoteId = quote.toLowerCase ();
            let symbolId = baseId + '_' + quoteId;
            let id = market['url_symbol'];
            let precision = {
                'amount': market['base_decimals'],
                'price': market['counter_decimals'],
            };
            let [ cost, currency ] = market['minimum_order'].split (' ');
            let active = (market['trading'] === 'Enabled');
            let lot = Math.pow (10, -precision['amount']);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'symbolId': symbolId,
                'info': market,
                'lot': lot,
                'active': active,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': lot,
                        'max': undefined,
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': undefined,
                    },
                    'cost': {
                        'min': parseFloat (cost),
                        'max': undefined,
                    },
                },
            });
        }
        return result;
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetOrderBookPair (this.extend ({
            'pair': this.marketId (symbol),
        }, params));
        let timestamp = parseInt (orderbook['timestamp']) * 1000;
        return this.parseOrderBook (orderbook, timestamp);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let ticker = await this.publicGetTickerPair (this.extend ({
            'pair': this.marketId (symbol),
        }, params));
        let timestamp = parseInt (ticker['timestamp']) * 1000;
        let vwap = parseFloat (ticker['vwap']);
        let baseVolume = parseFloat (ticker['volume']);
        let quoteVolume = baseVolume * vwap;
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': parseFloat (ticker['high']),
            'low': parseFloat (ticker['low']),
            'bid': parseFloat (ticker['bid']),
            'ask': parseFloat (ticker['ask']),
            'vwap': vwap,
            'open': parseFloat (ticker['open']),
            'close': undefined,
            'first': undefined,
            'last': parseFloat (ticker['last']),
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let timestamp = undefined;
        if ('date' in trade) {
            timestamp = parseInt (trade['date']) * 1000;
        } else if ('datetime' in trade) {
            timestamp = this.parse8601 (trade['datetime']);
        }
        let side = (trade['type'] === '0') ? 'buy' : 'sell';
        let order = undefined;
        if ('order_id' in trade)
            order = trade['order_id'].toString ();

        let ids = Object.keys (currencies);
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            if (id.split('_') == 2):
                let candidate_sym = id.replace('_', '');
                if (candidate_sym in this.markets_by_id) {
                    market = this.markets_by_id[marketId];
                }
        }

        let price = this.safeFloat (trade, 'price');
        price = this.safeFloat (trade, market['symbolId'], price);
        let amount = this.safeFloat (trade, 'amount');
        amount = this.safeFloat (trade, market['baseId'], amount);
        let id = this.safeValue (trade, 'tid');
        id = this.safeValue (trade, 'id', id);
        if (id)
            id = id.toString ();
        return {
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'order': order,
            'type': undefined,
            'side': side,
            'price': parseFloat (price),
            'amount': parseFloat (amount),
            'fee': {
                'cost': parseFloat(trade['fee']),
                'currency': marker['quote'],
            }
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetTransactionsPair (this.extend ({
            'pair': market['id'],
            'time': 'minute',
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balance = await this.privatePostBalance ();
        let result = { 'info': balance };
        let currencies = Object.keys (this.currencies);
        for (let i = 0; i < currencies.length; i++) {
            let currency = currencies[i];
            let lowercase = currency.toLowerCase ();
            let total = lowercase + '_balance';
            let free = lowercase + '_available';
            let used = lowercase + '_reserved';
            let account = this.account ();
            if (free in balance)
                account['free'] = parseFloat (balance[free]);
            if (used in balance)
                account['used'] = parseFloat (balance[used]);
            if (total in balance)
                account['total'] = parseFloat (balance[total]);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let method = 'privatePost' + this.capitalize (side);
        let order = {
            'pair': this.marketId (symbol),
            'amount': amount,
        };
        if (type === 'market')
            method += 'Market';
        else
            order['price'] = price;
        method += 'Pair';
        let response = await this[method] (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostCancelOrder ({ 'id': id });
    }

    parseOrderStatus (order) {
        if ((order['status'] === 'Queue') || (order['status'] === 'Open'))
            return 'open';
        if (order['status'] === 'Finished')
            return 'closed';
        return order['status'];
    }

    async fetchOrderStatus (id, symbol = undefined) {
        await this.loadMarkets ();
        let response = await this.privatePostOrderStatus ({ 'id': id });
        return this.parseOrderStatus (response);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        let method = 'privatePostUserTransactions';
        if (symbol) {
            market = this.market (symbol);
            request['pair'] = market['id'];
            method += 'Pair';
        }
        let response = await this[method] (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostOrderStatus ({ 'id': id });
    }

    getCurrencyName (code) {
        if (code === 'BTC')
            return 'bitcoin';
        return code.toLowerCase ();
    }

    isFiat (code) {
        if (code === 'USD')
            return true;
        if (code === 'EUR')
            return true;
        return false;
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        let isFiat = this.isFiat (code);
        if (isFiat)
            throw new ExchangeError (this.id + ' fiat withdraw() for ' + code + ' is not implemented yet');
        let name = this.getCurrencyName (code);
        let request = {
            'amount': amount,
            'address': address,
        };
        let v1 = (code === 'BTC');
        let method = v1 ? 'v1' : 'private'; // v1 or v2
        method += 'Post' + this.capitalize (name) + 'Withdrawal';
        let query = params;
        if (code === 'XRP') {
            let tag = this.safeString (params, 'destination_tag');
            if (tag) {
                request['destination_tag'] = tag;
                query = this.omit (params, 'destination_tag');
            } else {
                throw new ExchangeError (this.id + ' withdraw() requires a destination_tag param for ' + code);
            }
        }
        let response = await this[method] (this.extend (request, query));
        return {
            'info': response,
            'id': response['id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/';
        if (api !== 'v1')
            url += this.version + '/';
        url += this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let auth = nonce + this.uid + this.apiKey;
            let signature = this.encode (this.hmac (this.encode (auth), this.encode (this.secret)));
            query = this.extend ({
                'key': this.apiKey,
                'signature': signature.toUpperCase (),
                'nonce': nonce,
            }, query);
            body = this.urlencode (query);
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let status = this.safeString (response, 'status');
            if (status === 'error') {
                let code = this.safeString (response, 'code');
                if (typeof code !== 'undefined') {
                    if (code === 'API0005')
                        throw new AuthenticationError (this.id + ' invalid signature, use the uid for the main account if you have subaccounts');
                }
                throw new ExchangeError (this.id + ' ' + this.json (response));
            }
        }
    }
}
<|endoftext|>


<commit_before>var game = new Phaser.Game(
	480, 320, Phaser.AUTO, null, {
	preload: preload,
	create: create,
	update: update
});

var ball;

var paddle;

var bricks;
var newBrick;
var brickInfo;

var scoreText;
var score = 0;

function preload() {
	game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
	game.scale.pageAlignHorizontally = true;
	game.scale.pageAlignVertically = true;
	game.stage.backgroundColor = '#eee';
	game.load.image('ball', './img/ball.png');
	game.load.image('paddle', './img/paddle.png');
	game.load.image('brick', './img/brick.png');
}

function create() {
	game.physics.startSystem(Phaser.Physics.ARCADE);
	ball = game.add.sprite(50, 50, 'ball');
	game.physics.enable(ball, Phaser.Physics.ARCADE);
	ball.body.collideWorldBounds = true;
	ball.body.bounce.set(1);
	ball.body.velocity.set(150, -150);
	game.physics.arcade.checkCollision.down = false;
	ball.checkWorldBounds = true;
	ball.events.onOutOfBounds.add(function(){
		alert('Game over!');
		location.reload();
	}, this);
	paddle = game.add.sprite(game.world.width*0.5, game.world.height-5, 'paddle');
	paddle.anchor.set(0.5,1);
	game.physics.enable(paddle, Phaser.Physics.ARCADE);
	paddle.body.immovable = true;
	initBricks();
	scoreText = game.add.text(5, 5, 'Points: 0', { font: '18px Arial', fill: '#0095DD' });
}

function update() {
	ball.x += 1;
	ball.y += 1;
	game.physics.arcade.collide(ball, paddle);
	game.physics.arcade.collide(ball, bricks, ballHitBrick);
	paddle.x = game.input.x || game.world.width*0.5;
}

function initBricks() {
    brickInfo = {
        width: 50,
        height: 20,
        count: {
            row: 7,
            col: 3
        },
        offset: {
            top: 50,
            left: 60
        },
        padding: 10
	};
	bricks = game.add.group();

	for (c = 0; c < brickInfo.count.col; c++) {
		for(r = 0; r < brickInfo.count.row; r++) {
			var brickX = (r * (brickInfo.width + brickInfo.padding)) + brickInfo.offset.left;
			var brickY = (c * (brickInfo.height + brickInfo.padding)) + brickInfo.offset.top;
			newBrick = game.add.sprite(brickX, brickY, 'brick');
			game.physics.enable(newBrick, Phaser.Physics.ARCADE);
			newBrick.body.immovable = true;
			newBrick.anchor.set(0.5);
			bricks.add(newBrick);
		}
	}
}

function ballHitBrick(ball, brick) {
	brick.kill();
	score += 10;
    scoreText.setText('Points: '+score);
}<commit_msg>added win condition, just an alert for now<commit_after>var game = new Phaser.Game(
	480, 320, Phaser.AUTO, null, {
	preload: preload,
	create: create,
	update: update
});

var ball;

var paddle;

var bricks;
var newBrick;
var brickInfo;

var scoreText;
var score = 0;

function preload() {
	game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
	game.scale.pageAlignHorizontally = true;
	game.scale.pageAlignVertically = true;
	game.stage.backgroundColor = '#eee';
	game.load.image('ball', './img/ball.png');
	game.load.image('paddle', './img/paddle.png');
	game.load.image('brick', './img/brick.png');
}

function create() {
	game.physics.startSystem(Phaser.Physics.ARCADE);
	ball = game.add.sprite(50, 50, 'ball');
	game.physics.enable(ball, Phaser.Physics.ARCADE);
	ball.body.collideWorldBounds = true;
	ball.body.bounce.set(1);
	ball.body.velocity.set(150, -150);
	game.physics.arcade.checkCollision.down = false;
	ball.checkWorldBounds = true;
	ball.events.onOutOfBounds.add(function(){
		alert('Game over!');
		location.reload();
	}, this);
	paddle = game.add.sprite(game.world.width*0.5, game.world.height-5, 'paddle');
	paddle.anchor.set(0.5,1);
	game.physics.enable(paddle, Phaser.Physics.ARCADE);
	paddle.body.immovable = true;
	initBricks();
	scoreText = game.add.text(5, 5, 'Points: 0', { font: '18px Arial', fill: '#0095DD' });
}

function update() {
	ball.x += 1;
	ball.y += 1;
	game.physics.arcade.collide(ball, paddle);
	game.physics.arcade.collide(ball, bricks, ballHitBrick);
	paddle.x = game.input.x || game.world.width*0.5;
}

function initBricks() {
    brickInfo = {
        width: 50,
        height: 20,
        count: {
            row: 7,
            col: 3
        },
        offset: {
            top: 50,
            left: 60
        },
        padding: 10
	};
	bricks = game.add.group();

	for (c = 0; c < brickInfo.count.col; c++) {
		for(r = 0; r < brickInfo.count.row; r++) {
			var brickX = (r * (brickInfo.width + brickInfo.padding)) + brickInfo.offset.left;
			var brickY = (c * (brickInfo.height + brickInfo.padding)) + brickInfo.offset.top;
			newBrick = game.add.sprite(brickX, brickY, 'brick');
			game.physics.enable(newBrick, Phaser.Physics.ARCADE);
			newBrick.body.immovable = true;
			newBrick.anchor.set(0.5);
			bricks.add(newBrick);
		}
	}
}

function ballHitBrick(ball, brick) {
	brick.kill();
	score += 10;
	scoreText.setText('Points: '+score);

	var count_alive = 0;
    for (i = 0; i < bricks.children.length; i++) {
    	if (bricks.children[i].alive == true) {
        	count_alive++;
    	}
    }
    if (count_alive == 0) {
    	alert('You won the game, congratulations!');
    	location.reload();
    }
}<|endoftext|>


<commit_before>$(document).ready(function(){
$('.responsive-3').slick({
  arrows: false,
  dots: true,
  infinite: true,
  speed: 300,
  slidesToShow: 3,
  slidesToScroll: 1,
  touchThreshold: 20,
  responsive: [
    {
      breakpoint: 1024,
      settings: {
        slidesToShow: 3,
        slidesToScroll: 1,
        infinite: true,
        dots: true
      }
    },
    {
      breakpoint: 900,
      settings: {
        slidesToShow: 2,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 480,
      settings: {
        slidesToShow: 1,
        slidesToScroll: 1
      }
    }
  ]
});

$('.responsive-4').slick({
  arrows: false,
  dots: true,
  infinite: true,
  speed: 300,
  slidesToShow: 4,
  slidesToScroll: 1,
  touchThreshold: 20,
  responsive: [
    {
      breakpoint: 1024,
      settings: {
        slidesToShow: 4,
        slidesToScroll: 1,
        infinite: true,
        dots: true
      }
    },
    {
      breakpoint: 991,
      settings: {
        slidesToShow: 3,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 768,
      settings: {
        slidesToShow: 2,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 486,
      settings: {
        slidesToShow: 1,
        slidesToScroll: 1
      }
    }
  ]
});
});

function setSlideVisibility() {
  //Find the visible slides i.e. where aria-hidden="false"
  var visibleSlides = $('.slick-slide[aria-hidden="false"]');
  //Make sure all of the visible slides have an opacity of 1
  $(visibleSlides).each(function() {
    $(this).css('opacity', 1);
  });
  //Set the opacity of the first and last partial slides.
  $(visibleSlides).first().prev().css('opacity', 0);
  $(visibleSlides).last().next().css('opacity', 0);
}

$(setSlideVisibility());

$('.slider').on('beforeChange', function() {
  $('.slick-slide').each(function() {
  	$(this).css('opacity', 1);
  });
});

$('.slider').on('afterChange', function() {
  setSlideVisibility();
});
<commit_msg>Create carousel.js<commit_after>$(document).ready(function(){
$('.responsive-3').slick({
  centerMode: true,
  arrows: false,
  dots: true,
  infinite: true,
  speed: 300,
  slidesToShow: 3,
  slidesToScroll: 1,
  touchThreshold: 20,
  responsive: [
    {
      breakpoint: 1024,
      settings: {
        centerMode: true,
        slidesToShow: 3,
        slidesToScroll: 1,
        infinite: true,
        dots: true
      }
    },
    {
      breakpoint: 900,
      settings: {
        centerMode: true,
        slidesToShow: 2,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 480,
      settings: {
        centerMode: true,
        slidesToShow: 1,
        slidesToScroll: 1
      }
    }
  ]
});

$('.responsive-4').slick({
  arrows: false,
  dots: true,
  infinite: true,
  speed: 300,
  slidesToShow: 4,
  slidesToScroll: 1,
  touchThreshold: 20,
  responsive: [
    {
      breakpoint: 1024,
      settings: {
        slidesToShow: 4,
        slidesToScroll: 1,
        infinite: true,
        dots: true
      }
    },
    {
      breakpoint: 991,
      settings: {
        slidesToShow: 3,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 768,
      settings: {
        slidesToShow: 2,
        slidesToScroll: 1
      }
    },
    {
      breakpoint: 486,
      settings: {
        slidesToShow: 1,
        slidesToScroll: 1
      }
    }
  ]
});

function setSlideVisibility() {
  //Find the visible slides i.e. where aria-hidden="false"
  var visibleSlides = $('.slick-slide[aria-hidden="false"]');
  //Make sure all of the visible slides have an opacity of 1
  $(visibleSlides).each(function() {
    $(this).css('opacity', 1);
  });
  //Set the opacity of the first and last partial slides.
  $(visibleSlides).first().prev().css('opacity', 0);
  $(visibleSlides).last().next().css('opacity', 0);
}

$(setSlideVisibility());

$('.slider').on('beforeChange', function() {
  $('.slick-slide').each(function() {
  	$(this).css('opacity', 1);
  });
});

$('.slider').on('afterChange', function() {
  setSlideVisibility();
});

});
<|endoftext|>


<commit_before><commit_msg>Playing around with express<commit_after>var express = require("express");
var app = express();
<|endoftext|>