<commit_before>import Vector from 'vector';

import random from 'lodash.random';

const NONE = 0;

const LEFT = 1;
const TOP = 2;
const RIGHT = 3;
const BOTTOM = 4;

const TOP_LEFT = 5;
const TOP_RIGHT = 6;

const BOTTOM_RIGHT = 7;
const BOTTOM_LEFT = 8;

function almost_equal(a, b, epsilon) {
	return Math.abs(a - b) < epsilon;
}

export function overlap(a_box, b_box, epsilon = 1) {
	const w = (a_box.width + b_box.width)/2;
	const h = (a_box.height + b_box.height)/2;
	const {x: dx, y: dy} = a_box.center.sub(b_box.center);

	let x_overlap = Math.abs(dx) - w;
	let y_overlap = Math.abs(dy) - h;

	if (almost_equal(x_overlap, 0, epsilon)) {
		x_overlap = 0
	}

	if (almost_equal(y_overlap, 0, epsilon)) {
		y_overlap = 0;
	}

	if (x_overlap <= 0 && y_overlap <= 0) {
		// boxes collide
		x_overlap = Math.abs(x_overlap);
		y_overlap = Math.abs(y_overlap);

		if (almost_equal(x_overlap, y_overlap, epsilon)) {
			if (dx <= 0 && dy <= 0) {
				return TOP_LEFT;
			}
			if (dx <= 0 && dy >= 0) {
				return BOTTOM_LEFT;
			}
			if (dx >= 0 && dy <= 0) {
				return TOP_RIGHT;
			}
			if (dx >= 0 && dy >= 0) {
				return BOTTOM_RIGHT;
			}
		} else if (x_overlap < y_overlap) {
			return dx <= 0 ? LEFT : RIGHT;
		} else {
			return dy <= 0 ? TOP : BOTTOM;
		}
	}

	return NONE;
}
overlap.NONE         = NONE;
overlap.TOP          = TOP;
overlap.RIGHT        = RIGHT;
overlap.BOTTOM       = BOTTOM;
overlap.LEFT         = LEFT;
overlap.TOP_RIGHT    = TOP_RIGHT;
overlap.TOP_LEFT     = TOP_RIGHT;
overlap.BOTTOM_RIGHT = BOTTOM_RIGHT;
overlap.BOTTOM_LEFT  = BOTTOM_RIGHT;

export function bounce(a_box, {x, y}, b_box, epsilon = 1) {
	const side = overlap(a_box, b_box, epsilon);
	if (side !== NONE) {
		// debugger;
		switch (side) {
		case TOP_LEFT:
			if (x < 0 && y > 0) {
				return Vector({x, y: -y});
			} else if (x > 0 && y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case TOP_RIGHT:
			if (x > 0 && y > 0) {
				return Vector({x, y: -y});
			} else if (x < 0 && y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case BOTTOM_LEFT:
			if (x < 0 && y < 0) {
				return Vector({x, y: -y});
			} else if (x > 0 && y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case BOTTOM_RIGHT:
			if (x > 0 && y < 0) {
				return Vector({x, y: -y});
			} else if (x < 0 && y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case LEFT:
			if (x < 0) {
				return Vector({x: x, y: -y});
			}
			return Vector({x: -x, y});

		case RIGHT:
			if (x > 0) {
				return Vector({x, y: -y});
			}
			return Vector({x: -x, y});

		case TOP:
			if (y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x, y: -y});

		case BOTTOM:
			if (y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x, y: -y});
		}
	}
}

// export function bounce2(a_box, a_speed, b_box, fx_calback, epsilon) {
// 	const side = overlap(a_box, b_box, epsilon);
// }
<commit_msg>fix the bounce top and bottom collision<commit_after>import Vector from 'vector';

const NONE = 0;

const LEFT = 1;
const TOP = 2;
const RIGHT = 3;
const BOTTOM = 4;

const TOP_LEFT = 5;
const TOP_RIGHT = 6;

const BOTTOM_RIGHT = 7;
const BOTTOM_LEFT = 8;

function almost_equal(a, b, epsilon) {
	return Math.abs(a - b) < epsilon;
}

export function overlap(a_box, b_box, epsilon = 1) {
	const w = (a_box.width + b_box.width)/2;
	const h = (a_box.height + b_box.height)/2;
	const {x: dx, y: dy} = a_box.center.sub(b_box.center);

	let x_overlap = Math.abs(dx) - w;
	let y_overlap = Math.abs(dy) - h;

	if (almost_equal(x_overlap, 0, epsilon)) {
		x_overlap = 0
	}

	if (almost_equal(y_overlap, 0, epsilon)) {
		y_overlap = 0;
	}

	if (x_overlap <= 0 && y_overlap <= 0) {
		// boxes collide
		x_overlap = Math.abs(x_overlap);
		y_overlap = Math.abs(y_overlap);

		if (almost_equal(x_overlap, y_overlap, epsilon)) {
			if (dx <= 0 && dy <= 0) {
				return TOP_LEFT;
			}
			if (dx <= 0 && dy >= 0) {
				return BOTTOM_LEFT;
			}
			if (dx >= 0 && dy <= 0) {
				return TOP_RIGHT;
			}
			if (dx >= 0 && dy >= 0) {
				return BOTTOM_RIGHT;
			}
		} else if (x_overlap < y_overlap) {
			return dx <= 0 ? LEFT : RIGHT;
		} else {
			return dy <= 0 ? TOP : BOTTOM;
		}
	}

	return NONE;
}
overlap.NONE         = NONE;
overlap.TOP          = TOP;
overlap.RIGHT        = RIGHT;
overlap.BOTTOM       = BOTTOM;
overlap.LEFT         = LEFT;
overlap.TOP_RIGHT    = TOP_RIGHT;
overlap.TOP_LEFT     = TOP_RIGHT;
overlap.BOTTOM_RIGHT = BOTTOM_RIGHT;
overlap.BOTTOM_LEFT  = BOTTOM_RIGHT;

export function bounce(a_box, {x, y}, b_box, epsilon = 1) {
	const side = overlap(a_box, b_box, epsilon);
	if (side !== NONE) {
		// debugger;
		switch (side) {
		case TOP_LEFT:
			if (x < 0 && y > 0) {
				return Vector({x, y: -y});
			} else if (x > 0 && y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case TOP_RIGHT:
			if (x > 0 && y > 0) {
				return Vector({x, y: -y});
			} else if (x < 0 && y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case BOTTOM_LEFT:
			if (x < 0 && y < 0) {
				return Vector({x, y: -y});
			} else if (x > 0 && y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case BOTTOM_RIGHT:
			if (x > 0 && y < 0) {
				return Vector({x, y: -y});
			} else if (x < 0 && y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x: -x, y: -y});

		case LEFT:
			if (x < 0) {
				return Vector({x: x, y: -y});
			}
			return Vector({x: -x, y});

		case RIGHT:
			if (x > 0) {
				return Vector({x, y: -y});
			}
			return Vector({x: -x, y});

		case TOP:
			if (y < 0) {
				return Vector({x: -x, y});
			}
			return Vector({x, y: -y});

		case BOTTOM:
			if (y > 0) {
				return Vector({x: -x, y});
			}
			return Vector({x, y: -y});
		}
	}
}

// export function bounce2(a_box, a_speed, b_box, fx_calback, epsilon) {
// 	const side = overlap(a_box, b_box, epsilon);
// }
<|endoftext|>


<commit_before>define( [], function () {

    var Notify = {};

    Notify.DEBUG = 0;
    Notify.INFO = 1;
    Notify.NOTICE = 2;
    Notify.WARN = 3;
    Notify.ERROR = 4;

    // #FIXME getStackTrace was initially in webgl-utils (as a global function) but only used in this file
    /** Obtain a stacktrace from the current stack http://eriwen.com/javascript/js-stack-trace/
     */
    function getStackTrace( err ) {
        var callstack = [];
        try {
            if ( arguments.length === 1 ) {
                throw err;
            } else {
                throw new Error();
            }
        } catch ( error ) {
            if ( error.stack ) { //Firefox and Chrome
                callstack = ( error.stack + '\n' ).replace( /^\S[^\(]+?[\n$]/gm, '' ).
                replace( /^\s+(at eval )?at\s+/gm, '' ).
                replace( /^([^\(]+?)([\n$])/gm, '{anonymous}()@$1$2' ).
                replace( /^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}()@$1' ).split( '\n' );
                // Remove call to this function
                callstack.shift();

            }
        }
        // Remove empty entries
        for ( var i = 0; i < callstack.length; ++i ) {
            if ( callstack[ i ] === '' ) {
                callstack.splice( i, 1 );
                --i;
            }
        }

        return callstack;
    }

    Notify.setNotifyLevel = function ( level ) {

        var log = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.log( str, getStackTrace() );
            }
        };

        var info = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.info( str, getStackTrace() );
            }
        };

        var warn = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.warn( str, getStackTrace() );
            }
        };

        var error = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.error( str, getStackTrace() );
            }
        };

        var debug = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.debug( str, getStackTrace() );
            }
        };

        var dummy = function () {};

        Notify.debug = dummy;
        Notify.info = dummy;
        Notify.log = dummy;
        Notify.warn = dummy;
        Notify.error = dummy;

        if ( level <= Notify.DEBUG ) {
            Notify.debug = debug;
        }
        if ( level <= Notify.INFO ) {
            Notify.info = info;
        }
        if ( level <= Notify.NOTICE ) {
            Notify.log = log;
        }
        if ( level <= Notify.WARN ) {
            Notify.warn = warn;
        }
        if ( level <= Notify.ERROR ) {
            Notify.error = error;
        }
    };

    Notify.setNotifyLevel( Notify.NOTICE );

    Notify.reportWebGLError = false;

    return Notify;
} );
<commit_msg>[64447142] Adds console.trace<commit_after>define( [], function () {

    var Notify = {};

    Notify.DEBUG = 0;
    Notify.INFO = 1;
    Notify.NOTICE = 2;
    Notify.WARN = 3;
    Notify.ERROR = 4;

    // #FIXME getStackTrace was initially in webgl-utils (as a global function) but only used in this file
    /** Obtain a stacktrace from the current stack http://eriwen.com/javascript/js-stack-trace/
     */
    function getStackTrace( err ) {
		if (window.console && window.console.trace){
			window.console.trace();
			return '';
		}
        var callstack = [];
        try {
            if ( arguments.length === 1 ) {
                throw err;
            } else {
                throw new Error();
            }
        } catch ( error ) {
            if ( error.stack ) { //Firefox and Chrome
                callstack = ( error.stack + '\n' ).replace( /^\S[^\(]+?[\n$]/gm, '' ).
                replace( /^\s+(at eval )?at\s+/gm, '' ).
                replace( /^([^\(]+?)([\n$])/gm, '{anonymous}()@$1$2' ).
                replace( /^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}()@$1' ).split( '\n' );
                // Remove call to this function
                callstack.shift();

            }
        }
        // Remove empty entries
        for ( var i = 0; i < callstack.length; ++i ) {
            if ( callstack[ i ] === '' ) {
                callstack.splice( i, 1 );
                --i;
            }
        }

        return callstack;
    }

    Notify.setNotifyLevel = function ( level ) {

        var log = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.log( str, getStackTrace() );
            }
        };

        var info = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.info( str, getStackTrace() );
            }
        };

        var warn = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.warn( str, getStackTrace() );
            }
        };

        var error = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.error( str, getStackTrace() );
            }
        };

        var debug = function ( str ) {
            if ( window.console !== undefined ) {
                window.console.debug( str, getStackTrace() );
            }
        };

        var dummy = function () {};

        Notify.debug = dummy;
        Notify.info = dummy;
        Notify.log = dummy;
        Notify.warn = dummy;
        Notify.error = dummy;

        if ( level <= Notify.DEBUG ) {
            Notify.debug = debug;
        }
        if ( level <= Notify.INFO ) {
            Notify.info = info;
        }
        if ( level <= Notify.NOTICE ) {
            Notify.log = log;
        }
        if ( level <= Notify.WARN ) {
            Notify.warn = warn;
        }
        if ( level <= Notify.ERROR ) {
            Notify.error = error;
        }
    };

    Notify.setNotifyLevel( Notify.NOTICE );

    Notify.reportWebGLError = false;

    return Notify;
} );
<|endoftext|>


<commit_before>import Inductor from '../src/Components/Inductor.js';
import Pin from '../src/Components/Pin.js';
import ComponentType from '../src/ComponentType.js';
import Matrix from '../src/Matrix.js';
import simConfig from '../src/SimulationConfig.js';

describe('Inductor', () => {

    let L;
    beforeEach(() => {
        L = new Inductor();
    });

    describe('constructor', () => {

        it('should have an ID with the format of Cx, where x is the n-th component created', () => {
            expect(/^L\d+$/.test(L.id)).toBe(true);
        });

        it('should have an ID which increases in number', () => {
            let intRegex = /\d+$/,
                L2 = new Inductor(),
                L3 = new Inductor(),
                num = parseInt(L2.id.match(intRegex)[0]),
                num2 = parseInt(L3.id.match(intRegex)[0]);

            expect(num2 - num).toBe(1);
        });

        it('should have type of Inductor', () => {
            expect(L.type).toBe(ComponentType.TYPE_INDUCTOR);
        });

        it('should have inductance in controlled object field', () => {
            expect(Object.keys(L.controlled)).toContain("L");
            expect(Object.keys(L.dependant)).not.toContain("L");
        });

        it('should have default 1 Henry', () => {
            expect(L.controlled.L).toBe(1);
        });

        it('should be able to take in and set inital inductance value', () => {
            let L_initial = new Inductor(2);
            expect(L_initial.controlled.L).toBe(2);
        });

        it('should have voltage, current, companion models conductance and current in dependant object field', () => {
            expect(Object.keys(L.dependant).sort()).toEqual(['V', 'I', 'companionG', 'companionI'].sort());
        });

        it('should have 2 pins by default', () => {
            expect(L.pins).toEqual([new Pin(L,0), new Pin(L,1)]);
        });

        it('should have pins that "knows" its own index', () => {
            expect(L.pins[0].index).toBe(0);
            expect(L.pins[1].index).toBe(1);
        });

    });

    describe('otherPins(pinIndex)', () => {
        it('should return an array with all pins except the one at the given pin index', () => {
            expect(L.otherPins(0)).toEqual([L.pins[1]]);
        });
    });

    describe('stamp(matrixY, matrixJ, simConfig)', () => {

        let Y, J,
            inductance = 7,
            // We need to retain the state of L2 across the following two test so that
            // we can do the Trapezoidal rule to approximate the next timestep's value
            L2 = new Inductor(inductance),
            // Companion model's resistor's conductance
            companionG = simConfig.timestep / 2 * inductance;

        beforeEach(() => {
            Y = new Matrix(3);      // 3x3
            J = new Matrix(3, 1);   // 3x1
        });

        it('should stamp matrix Y and J in the correct cells (when in intial condition)', () => {
            L2.nodes = [1,2];
            L2.stamp(Y, J, simConfig);

            expect(Y.data).toEqual([
                [0,  0,  0],
                [0,  companionG, -companionG],
                [0, -companionG,  companionG]
            ]);

            // Current of the companion model is 0 for initial condition
            expect(J.data).toEqual([
                [0],
                [0],
                [0]
            ]);
        });

        it('should stamp matrix Y and J in the correct cells (at subsequent timestep)', () => {
            let V = 1, I = 2,
                companionI = I + companionG * V;

            // Assuming the component has been updated after the first timestep
            L2.dependant.V = V;
            L2.dependant.I = I;

            L2.stamp(Y, J, simConfig);

            expect(Y.data).toEqual([
                [0,  0,  0],
                [0,  companionG, -companionG],
                [0, -companionG,  companionG]
            ]);

            expect(J.data).toEqual([
                [0],
                [companionI],
                [-companionI]
            ]);
        });

    });

    describe('update({vals})', () => {
        it('should update its voltage with the given value', () => {
            let inductance = 10,
                companionG = simConfig.timestep / 2 * inductance;

            // We are assuming this is in inital condition
            L.controlled.L = inductance;
            L.dependant.companionG = companionG;
            L.dependant.companionI = 0;

            L.update({pins: [2, 6]});

            expect(L.pins[0].V).toBe(2);
            expect(L.pins[1].V).toBe(6);

            expect(L.dependant.V).toBe(-4);
            expect(L.dependant.I).toBeCloseTo(L.dependant.V * companionG - 0);
        });
    });
})<commit_msg>Inductor's current was stamped wrongly<commit_after>import Inductor from '../src/Components/Inductor.js';
import Pin from '../src/Components/Pin.js';
import ComponentType from '../src/ComponentType.js';
import Matrix from '../src/Matrix.js';
import simConfig from '../src/SimulationConfig.js';

describe('Inductor', () => {

    let L;
    beforeEach(() => {
        L = new Inductor();
    });

    describe('constructor', () => {

        it('should have an ID with the format of Cx, where x is the n-th component created', () => {
            expect(/^L\d+$/.test(L.id)).toBe(true);
        });

        it('should have an ID which increases in number', () => {
            let intRegex = /\d+$/,
                L2 = new Inductor(),
                L3 = new Inductor(),
                num = parseInt(L2.id.match(intRegex)[0]),
                num2 = parseInt(L3.id.match(intRegex)[0]);

            expect(num2 - num).toBe(1);
        });

        it('should have type of Inductor', () => {
            expect(L.type).toBe(ComponentType.TYPE_INDUCTOR);
        });

        it('should have inductance in controlled object field', () => {
            expect(Object.keys(L.controlled)).toContain("L");
            expect(Object.keys(L.dependant)).not.toContain("L");
        });

        it('should have default 1 Henry', () => {
            expect(L.controlled.L).toBe(1);
        });

        it('should be able to take in and set inital inductance value', () => {
            let L_initial = new Inductor(2);
            expect(L_initial.controlled.L).toBe(2);
        });

        it('should have voltage, current, companion models conductance and current in dependant object field', () => {
            expect(Object.keys(L.dependant).sort()).toEqual(['V', 'I', 'companionG', 'companionI'].sort());
        });

        it('should have 2 pins by default', () => {
            expect(L.pins).toEqual([new Pin(L,0), new Pin(L,1)]);
        });

        it('should have pins that "knows" its own index', () => {
            expect(L.pins[0].index).toBe(0);
            expect(L.pins[1].index).toBe(1);
        });

    });

    describe('otherPins(pinIndex)', () => {
        it('should return an array with all pins except the one at the given pin index', () => {
            expect(L.otherPins(0)).toEqual([L.pins[1]]);
        });
    });

    describe('stamp(matrixY, matrixJ, simConfig)', () => {

        let Y, J,
            inductance = 7,
            // We need to retain the state of L2 across the following two test so that
            // we can do the Trapezoidal rule to approximate the next timestep's value
            L2 = new Inductor(inductance),
            // Companion model's resistor's conductance
            companionG = simConfig.timestep / 2 * inductance;

        beforeEach(() => {
            Y = new Matrix(3);      // 3x3
            J = new Matrix(3, 1);   // 3x1
        });

        it('should stamp matrix Y and J in the correct cells (when in intial condition)', () => {
            L2.nodes = [1,2];
            L2.stamp(Y, J, simConfig);

            expect(Y.data).toEqual([
                [0,  0,  0],
                [0,  companionG, -companionG],
                [0, -companionG,  companionG]
            ]);

            // Current of the companion model is 0 for initial condition
            expect(J.data).toEqual([
                [0],
                [0],
                [0]
            ]);
        });

        it('should stamp matrix Y and J in the correct cells (at subsequent timestep)', () => {
            let V = 1, I = 2,
                companionI = I + companionG * V;

            // Assuming the component has been updated after the first timestep
            L2.dependant.V = V;
            L2.dependant.I = I;

            L2.stamp(Y, J, simConfig);

            expect(Y.data).toEqual([
                [0,  0,  0],
                [0,  companionG, -companionG],
                [0, -companionG,  companionG]
            ]);

            expect(J.data).toEqual([
                [0],
                [-companionI],
                [companionI]
            ]);
        });

    });

    describe('update({vals})', () => {
        it('should update its voltage with the given value', () => {
            let inductance = 10,
                companionG = simConfig.timestep / 2 * inductance;

            // We are assuming this is in inital condition
            L.controlled.L = inductance;
            L.dependant.companionG = companionG;
            L.dependant.companionI = 0;

            L.update({pins: [2, 6]});

            expect(L.pins[0].V).toBe(2);
            expect(L.pins[1].V).toBe(6);

            expect(L.dependant.V).toBe(-4);
            expect(L.dependant.I).toBeCloseTo(L.dependant.V * companionG - 0);
        });
    });
})<|endoftext|>


<commit_before>/**
 * Your specifications, or the behavior you expect from your app, are defined
 * here. Some have been completed for you as an example. Remember to repeat
 * the following steps when adding any new functionality to your app:
 *   1. Write your spec first.
 *   2. Run your specs. The new spec should fail.
 *   3. Write enough code to get your spec to pass.
 *   4. Refactor as necessary.
 */

describe('fizzbuzz', function () {

    /**
     * Specification #1: The function should return the string "fizz"
     * when the function argument is evenly divisible by three.
     */
    it('should return "fizz" when arg is divisible by three', function () {
        expect(fizzbuzz(3)).toEqual('fizz');
    });

    /**
     * Specification #2: The function should return the string "buzz"
     * when the function argument is evenly divisible by five.
     */
    it('should return "buzz" when arg is divisible by five', function () {
        expect(fizzbuzz(3)).toEqual('buzz');
    });

    /**
     * Specification #3: The function should return the string "fizzbuzz"
     * when the function argument is evenly divisible by both three *and* five.
     */
    it('should return "fizzbuzz" when arg is divisible by both three and five', function () {
        // You're on your own here. Replace "pending();" with your own code
        pending();
    });

    /**
     * Specification #4: The function should return the string "MeaningOfLife"
     * when the function argument is equal to the number 42.
     */
    it('should return "MeaningOfLife" when arg is equal to 42', function () {
        // You're on your own here. Replace "pending();" with your own code
        pending();
    });
});
<commit_msg>Fixing spec #2<commit_after>/**
 * Your specifications, or the behavior you expect from your app, are defined
 * here. Some have been completed for you as an example. Remember to repeat
 * the following steps when adding any new functionality to your app:
 *   1. Write your spec first.
 *   2. Run your specs. The new spec should fail.
 *   3. Write enough code to get your spec to pass.
 *   4. Refactor as necessary.
 */

describe('fizzbuzz', function () {

    /**
     * Specification #1: The function should return the string "fizz"
     * when the function argument is evenly divisible by three.
     */
    it('should return "fizz" when arg is divisible by three', function () {
        expect(fizzbuzz(3)).toEqual('fizz');
    });

    /**
     * Specification #2: The function should return the string "buzz"
     * when the function argument is evenly divisible by five.
     */
    it('should return "buzz" when arg is divisible by five', function () {
        expect(fizzbuzz(5)).toEqual('buzz');
    });

    /**
     * Specification #3: The function should return the string "fizzbuzz"
     * when the function argument is evenly divisible by both three *and* five.
     */
    it('should return "fizzbuzz" when arg is divisible by both three and five', function () {
        // You're on your own here. Replace "pending();" with your own code
        pending();
    });

    /**
     * Specification #4: The function should return the string "MeaningOfLife"
     * when the function argument is equal to the number 42.
     */
    it('should return "MeaningOfLife" when arg is equal to 42', function () {
        // You're on your own here. Replace "pending();" with your own code
        pending();
    });
});
<|endoftext|>


<commit_before>import { expect }               from 'chai';
import { isButtonSelected } from '../helpers.js';

describe('isButtonSelected', () => {
    it('should return false when the value or the candidate is null', () => {
        expect(isButtonSelected(null, 'xyz')).be.false;
        expect(isButtonSelected([], null)).be.false;
    });

    it('should return true when the candidate is equal to the value', () => {
        expect(isButtonSelected('test', 'test')).be.true;
    });

    it('should return false when the candidate is not equal to the value', () => {
        expect(isButtonSelected('test', 'tesy')).be.false;
    });

    it('should return true when the value is an array and contains the candidate', () => {
        expect(isButtonSelected(['test-1', 'test-2'], 'test-1')).be.true;
    });

    it('should return false when the value is an array and does not contain the candidate', () => {
        expect(isButtonSelected(['test-1', 'test-2'], 'test-3')).be.false;
    });
});
<commit_msg>Change the ToggleButton helpers test to ToggleButton:Helpers<commit_after>import { expect }               from 'chai';
import { isButtonSelected } from '../helpers.js';

describe('ToggleButton:Helpers', () => {
    describe('isButtonSelected', () => {
        it('should return false when the value or the candidate is null', () => {
            expect(isButtonSelected(null, 'xyz')).be.false;
            expect(isButtonSelected([], null)).be.false;
        });

        it('should return true when the candidate is equal to the value', () => {
            expect(isButtonSelected('test', 'test')).be.true;
        });

        it('should return false when the candidate is not equal to the value', () => {
            expect(isButtonSelected('test', 'tesy')).be.false;
        });

        it('should return true when the value is an array and contains the candidate', () => {
            expect(isButtonSelected(['test-1', 'test-2'], 'test-1')).be.true;
        });

        it('should return false when the value is an array and does not contain the candidate', () => {
            expect(isButtonSelected(['test-1', 'test-2'], 'test-3')).be.false;
        });
    });
});
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

const log_tree = require("../lib/log_tree");

describe("a log_tree object", function() {
  var tree;

  describe("when created from nothing", function() {
    beforeEach(function() {
      tree = log_tree();
    });

    it("has a length of 0", function() {
      expect(tree.length).toBe(0);
    });

    it("has a name of ''", function() {
      expect(tree.name).toBe("");
    });

    describe("when its name is set to 'matt'", function() {
      it("has a name of 'matt'", function() {
        tree.name = "matt";
        expect(tree.name).toBe("matt");
      });
    });

    it("doesn't remember a length change", function() {
      tree.length = 1;
      expect(tree.length).toBe(0);
    });

    it("exports to {name:'',children:[]}", function() {
      expect(tree.export()).toEqual({name: "", children: []});
    });
  });

  describe("when created with 'name'", function() {
    beforeEach(function() {
      tree = log_tree("name");
    });

    it("remembers its name", function() {
      expect(tree.name).toBe("name");
    });

    it("has a length of 0", function() {
      expect(tree.length).toBe(0);
    });

    it("remembers a name change", function() {
      tree.name = "beremy";
      expect(tree.name).toBe("beremy");
    });

    it("exports to {name:'name',children:[]}", function() {
      expect(tree.export()).toEqual({name: "name", children: []});
    });
  });
});
<commit_msg>:art: Reorder tests<commit_after>// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

const log_tree = require("../lib/log_tree");

describe("a log_tree object", function() {
  var tree;

  describe("when created from nothing", function() {
    beforeEach(function() {
      tree = log_tree();
    });

    it("has a length of 0", function() {
      expect(tree.length).toBe(0);
    });

    it("has a name of ''", function() {
      expect(tree.name).toBe("");
    });

    it("exports to {name:'',children:[]}", function() {
      expect(tree.export()).toEqual({name: "", children: []});
    });

    it("doesn't remember a length change", function() {
      tree.length = 1;
      expect(tree.length).toBe(0);
    });

    describe("when its name is set to 'matt'", function() {
      it("has a name of 'matt'", function() {
        tree.name = "matt";
        expect(tree.name).toBe("matt");
      });
    });
  });

  describe("when created with 'name'", function() {
    beforeEach(function() {
      tree = log_tree("name");
    });

    it("remembers its name", function() {
      expect(tree.name).toBe("name");
    });

    it("has a length of 0", function() {
      expect(tree.length).toBe(0);
    });

    it("exports to {name:'name',children:[]}", function() {
      expect(tree.export()).toEqual({name: "name", children: []});
    });

    it("remembers a name change", function() {
      tree.name = "beremy";
      expect(tree.name).toBe("beremy");
    });
  });
});
<|endoftext|>


<commit_before>describe("mailcheck", function() {
  var domains = ['yahoo.com', 'yahoo.com.tw', 'google.com','hotmail.com', 'gmail.com', 'emaildomain.com', 'comcast.net', 'facebook.com', 'msn.com', 'gmx.com'];
  var topLevelDomains = ['co.uk', 'com', 'org', 'info'];

  describe("Kicksend.mailcheck", function(){
    var mailcheck;

    beforeEach(function(){
       mailcheck = Kicksend.mailcheck;
    });

    describe("run", function () {
      var suggestedSpy, emptySpy;

      beforeEach(function () {
        suggestedSpy = jasmine.createSpy();
        emptySpy = jasmine.createSpy();
      });

      it("calls the 'suggested' callback with the element and result when there's a suggestion", function () {
        mailcheck.run({
          email: 'test@hotmail.co',
          suggested:suggestedSpy,
          empty:emptySpy
        });

        expect(suggestedSpy).toHaveBeenCalledWith({
          address:'test',
          domain:'hotmail.com',
          full:'test@hotmail.com'
        });

        expect(emptySpy).not.toHaveBeenCalled();
      });

      it("calls the 'empty' callback with the element when there's no suggestion", function () {
        mailcheck.run({
          email: 'contact@kicksend.com',
          suggested:suggestedSpy,
          empty:emptySpy
        });

        expect(suggestedSpy).not.toHaveBeenCalled();

        expect(emptySpy).toHaveBeenCalled();
      });

      it("takes in an array of specified domains", function () {
        mailcheck.run({
          email: 'test@emaildomain.con',
          suggested:suggestedSpy,
          empty:emptySpy,
          domains:domains
        });

        expect(suggestedSpy).toHaveBeenCalledWith({
          address:'test',
          domain:'emaildomain.com',
          full:'test@emaildomain.com'
        });
      });

      it("escapes the element's value", function () {
        mailcheck.run({
          email: '@emaildomain.con',
          suggested:suggestedSpy,
          empty:emptySpy,
          domains:domains
        });
        expect(suggestedSpy.mostRecentCall.args[0].address).not.toMatch(/@emaildomain.con',
          suggested:suggestedSpy,
          empty:emptySpy,
          domains:domains
        });
        expect(suggestedSpy.mostRecentCall.args[0].address).not.toMatch(/


<commit_before>var _ = require('lodash');
var PixelData = require('../app/pixeldata.js');
var colorutil = require('../app/colorutil.js');

pixelData = new PixelData(15);

describe("PixelData manipulation is...", function() {
  it("setting a color at a specific position", function() {
    pixelData.wipe();
    pixelData.setColorAtPosition(0, colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[0]).toBe(65280);
    expect(pixelData.data[1]).toBe(0);
  });
  it("setting a color at an invalid position", function() {
    pixelData.wipe();
    pixelData.setColorAtPosition(17, colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[17]).toBe(undefined);
  });
  it("setting a hex color at a specific position", function() {
    pixelData.wipe();
    pixelData.setHexColorAtPosition(2, '#00ff00');
    expect(pixelData.data[2]).toBe(65280);
    expect(pixelData.data[3]).toBe(0);
  });

  it("setting an overall color", function() {
    pixelData.wipe();
    pixelData.setOverallColor(colorutil.hex2Int('#00ff00'));
    expect(_.uniq(pixelData.data).length).toBe(1);
    expect(_.uniq(pixelData.data)[0]).toBe(65280);
  });

  it("setting a color range", function() {
    pixelData.wipe();
    pixelData.setColorRange([2, 3, 4, 6, 7], colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[0]).toBe(0);
    expect(pixelData.data[1]).toBe(0);
    expect(pixelData.data[2]).toBe(65280);
    expect(pixelData.data[3]).toBe(65280);
    expect(pixelData.data[4]).toBe(65280);
    expect(pixelData.data[5]).toBe(0);
    expect(pixelData.data[6]).toBe(65280);
    expect(pixelData.data[7]).toBe(65280);
    expect(pixelData.data[8]).toBe(0);
    expect(pixelData.data[9]).toBe(0);
  });

  it("setting different colors to specific positions", function() {
    pixelData.wipe();
    pixelData.setColors([0, 2, 4, 6, 8, 10], [
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
    ]);
    expect(pixelData.data[0]).toBe(65280);
    expect(pixelData.data[1]).toBe(0);
    expect(pixelData.data[2]).toBe(255);
    expect(pixelData.data[3]).toBe(0);
    expect(pixelData.data[4]).toBe(65280);
    expect(pixelData.data[5]).toBe(0);
    expect(pixelData.data[6]).toBe(255);
    expect(pixelData.data[7]).toBe(0);
    expect(pixelData.data[8]).toBe(65280);
    expect(pixelData.data[9]).toBe(0);
    expect(pixelData.data[10]).toBe(255);
    expect(pixelData.data[11]).toBe(0);
  });

  it("setting different colors to specific positions", function() {
    pixelData.wipe();
    expect(pixelData.setColors([0, 2], [
      colorutil.hex2Int('#00ff00'),
    ])).toEqual(undefined);

  });

  it("wiping it all", function() {
    pixelData.wipe();
    expect(_.uniq(pixelData.data).length).toBe(1);
    expect(_.uniq(pixelData.data)[0]).toBe(0);
  });
})
<commit_msg>switched to beforeAll and beforeEach<commit_after>var _ = require('lodash');
var PixelData = require('../app/pixeldata.js');
var colorutil = require('../app/colorutil.js');

describe("PixelData manipulation is...", function() {
  beforeAll(function() {
    pixelData = new PixelData(15);
  })
  beforeEach(function() {
    pixelData.wipe();
  })
  it("setting a color at a specific position", function() {
    pixelData.setColorAtPosition(0, colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[0]).toBe(65280);
    expect(pixelData.data[1]).toBe(0);
  });
  it("setting a color at an invalid position", function() {
    pixelData.setColorAtPosition(17, colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[17]).toBe(undefined);
  });
  it("setting a hex color at a specific position", function() {
    pixelData.setHexColorAtPosition(2, '#00ff00');
    expect(pixelData.data[2]).toBe(65280);
    expect(pixelData.data[3]).toBe(0);
  });

  it("setting an overall color", function() {
    pixelData.setOverallColor(colorutil.hex2Int('#00ff00'));
    expect(_.uniq(pixelData.data).length).toBe(1);
    expect(_.uniq(pixelData.data)[0]).toBe(65280);
  });

  it("setting a color range", function() {
    pixelData.setColorRange([2, 3, 4, 6, 7], colorutil.hex2Int('#00ff00'));
    expect(pixelData.data[0]).toBe(0);
    expect(pixelData.data[1]).toBe(0);
    expect(pixelData.data[2]).toBe(65280);
    expect(pixelData.data[3]).toBe(65280);
    expect(pixelData.data[4]).toBe(65280);
    expect(pixelData.data[5]).toBe(0);
    expect(pixelData.data[6]).toBe(65280);
    expect(pixelData.data[7]).toBe(65280);
    expect(pixelData.data[8]).toBe(0);
    expect(pixelData.data[9]).toBe(0);
  });

  it("setting different colors to specific positions", function() {
    pixelData.setColors([0, 2, 4, 6, 8, 10], [
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
      colorutil.hex2Int('#00ff00'),
      colorutil.hex2Int('#0000ff'),
    ]);
    expect(pixelData.data[0]).toBe(65280);
    expect(pixelData.data[1]).toBe(0);
    expect(pixelData.data[2]).toBe(255);
    expect(pixelData.data[3]).toBe(0);
    expect(pixelData.data[4]).toBe(65280);
    expect(pixelData.data[5]).toBe(0);
    expect(pixelData.data[6]).toBe(255);
    expect(pixelData.data[7]).toBe(0);
    expect(pixelData.data[8]).toBe(65280);
    expect(pixelData.data[9]).toBe(0);
    expect(pixelData.data[10]).toBe(255);
    expect(pixelData.data[11]).toBe(0);
  });

  it("setting different colors to specific positions", function() {
    expect(pixelData.setColors([0, 2], [
      colorutil.hex2Int('#00ff00'),
    ])).toEqual(undefined);

  });

  it("wiping it all", function() {
    expect(_.uniq(pixelData.data).length).toBe(1);
    expect(_.uniq(pixelData.data)[0]).toBe(0);
  });
})
<|endoftext|>


<commit_before>with(require('./helpers')) {

describe('A new document', function() {
  it('can be instantiated with nothing', function() {
    var doc = new libxml.Document();
    assert(doc);
    assertEqual('1.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version', function() {
    var doc = new libxml.Document('2.0');
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version and encoding', function() {
    var doc = new libxml.Document('2.0', 'UTF-8');
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual('UTF-8', doc.encoding());
  });

  it('can be instantiated with a callback', function() {
    var doc = null;
    new libxml.Document(function(d) { doc = d; });
    assert(doc);
    assertEqual('1.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version and a callback', function() {
    var doc = null;
    new libxml.Document('2.0', function(d) { doc = d; });
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version, encoding and callback', function() {
    var doc = null;
    new libxml.Document('2.0', 'UTF-8', function(d) { doc = d; });
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual('UTF-8', doc.encoding());
  });

  it('is created with a null root node', function() {
    var doc = new libxml.Document();
    assertEqual(null, doc.root());
  });

  it('can have a root node attached to it', function() {
    var doc = new libxml.Document();
    var root = doc.node('root');
    assertEqual('root', root.name());
    assertEqual(root, doc.root());
  });

  it('can return an arbitrary child of the root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.child(1).name());
    assertEqual('child-two', doc.child(2).name());
  });

  it('can return an array of children of the root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.childNodes()[0].name());
    assertEqual('child-two', doc.childNodes()[1].name());
  });

  it('returns itself when asked', function() {
    var doc = new libxml.Document();
    assertEqual(doc, doc.document());
  });

  it('can under go an encoding change', function() {
    var doc = new libxml.Document();
    assert(doc);
    assertEqual(null, doc.encoding());
    doc.encoding('UTF-8');
    assertEqual('UTF-8', doc.encoding());
  });

  it('can find a set by xpath', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child').parent().node('child');
    assertEqual(2, doc.find('child').length);
  });

  it('can get a child by xpath', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.get('child-one').name());
    assertEqual('child-two', doc.get('child-two').name());
  });

  it('knows its root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child').parent().node('child');
    assertEqual(doc.root().name(), doc.get('/root').name());
  });

  it('can be output as a string', function() {
    var control = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo"><grandchild from="julie numar">with love</grandchild></child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc = new libxml.Document(function(n) {
      n.node('root', function(n) {
        n.node('child', {to: 'wongfoo'}, null, function(n) {
          n.node('grandchild', {from: 'julie numar'}, 'with love');
        });
        n.node('sibling', null, 'with content!');
      });
    });
    assertEqual(control, doc.toString());
  });
});

}
<commit_msg>Added tests for adding nodes and checking cloning.<commit_after>with(require('./helpers')) {

describe('A new document', function() {
  it('can be instantiated with nothing', function() {
    var doc = new libxml.Document();
    assert(doc);
    assertEqual('1.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version', function() {
    var doc = new libxml.Document('2.0');
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version and encoding', function() {
    var doc = new libxml.Document('2.0', 'UTF-8');
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual('UTF-8', doc.encoding());
  });

  it('can be instantiated with a callback', function() {
    var doc = null;
    new libxml.Document(function(d) { doc = d; });
    assert(doc);
    assertEqual('1.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version and a callback', function() {
    var doc = null;
    new libxml.Document('2.0', function(d) { doc = d; });
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual(null, doc.encoding());
  });

  it('can be instantiated with a version, encoding and callback', function() {
    var doc = null;
    new libxml.Document('2.0', 'UTF-8', function(d) { doc = d; });
    assert(doc);
    assertEqual('2.0', doc.version());
    assertEqual('UTF-8', doc.encoding());
  });

  it('is created with a null root node', function() {
    var doc = new libxml.Document();
    assertEqual(null, doc.root());
  });

  it('can have a root node attached to it', function() {
    var doc = new libxml.Document();
    var root = doc.node('root');
    assertEqual('root', root.name());
    assertEqual(root, doc.root());
  });

  it('can return an arbitrary child of the root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.child(1).name());
    assertEqual('child-two', doc.child(2).name());
  });

  it('can return an array of children of the root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.childNodes()[0].name());
    assertEqual('child-two', doc.childNodes()[1].name());
  });

  it('returns itself when asked', function() {
    var doc = new libxml.Document();
    assertEqual(doc, doc.document());
  });

  it('can under go an encoding change', function() {
    var doc = new libxml.Document();
    assert(doc);
    assertEqual(null, doc.encoding());
    doc.encoding('UTF-8');
    assertEqual('UTF-8', doc.encoding());
  });

  it('can find a set by xpath', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child').parent().node('child');
    assertEqual(2, doc.find('child').length);
  });

  it('can get a child by xpath', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child-one').parent().node('child-two');
    assertEqual('child-one', doc.get('child-one').name());
    assertEqual('child-two', doc.get('child-two').name());
  });

  it('knows its root node', function() {
    var doc = new libxml.Document();
    doc.node('root').node('child').parent().node('child');
    assertEqual(doc.root().name(), doc.get('/root').name());
  });

  it('can be output as a string', function() {
    var control = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo"><grandchild from="julie numar">with love</grandchild></child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc = new libxml.Document(function(n) {
      n.node('root', function(n) {
        n.node('child', {to: 'wongfoo'}, null, function(n) {
          n.node('grandchild', {from: 'julie numar'}, 'with love');
        });
        n.node('sibling', null, 'with content!');
      });
    });
    assertEqual(control, doc.toString());
  });

  it('can add child nodes', function() {
    var gchild = '';
    var doc1_string = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo"><grandchild from="julie numar">with love</grandchild></child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc2_string = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo"></child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc1 = libxml.parseXmlString(doc1_string);
    var doc2 = libxml.parseXmlString(doc2_string);
    doc2.child(0).addChild(doc1.child(0).child(0));
    assertEqual(doc1.toString(), doc2.toString());
  });

  it('can haz cloned node', function() {
    var gchild_string  = '<grandchild from="julie numar">with love</grandchild>';
    var doc1_string = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo">'+gchild_string+'</child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc2_string = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<root><child to="wongfoo"></child><sibling>with content!</sibling></root>',
      ''
    ].join("\n");

    var doc1 = libxml.parseXmlString(doc1_string);
    var doc2 = libxml.parseXmlString(doc2_string);
    doc2.child(0).addChild(doc1.child(0).child(0)); // add gchild to doc 2

    assertEqual(doc1.toString(), doc2.toString());; // both documents should be the same

    var gchild = doc1.child(0).child(0).remove(); //the removed element
    assertEqual(gchild_string, gchild.toString()); //make sure it's the same as what we started with

    //require('sys').debug('doc1: '+doc1.toString());
    //require('sys').debug('doc2: '+doc2.toString());
    assertEqual(gchild_string, doc2.child(0).child(0).toString()); // doc2 should have gchild

    assertEqual(doc2_string, doc1.toString()); //doc1 should be the same as doc2 str

    assertEqual(doc1_string, doc2.toString()); //doc2 should be the same as doc1 str
  });
});

}
<|endoftext|>


<commit_before>var config = require('./config');
var zlib = require('zlib');
var compute = require('./compute');
var computePlayerMatchData = compute.computePlayerMatchData;
var aggregator = require('./aggregator');
var async = require('async');
var constants = require('./constants');
var utility = require('./utility');
var filter = require('./filter');
var reduceAggregable = utility.reduceAggregable;
var enabled = config.ENABLE_PLAYER_CACHE;
var cEnabled = config.ENABLE_CASSANDRA_PLAYER_CACHE;
var redis;
var cassandra;
if (enabled)
{
    redis = require('./redis');
    if (cEnabled)
    {
        cassandra = require('./cassandra');
    }
}
function readCache(account_id, options, cb)
{
    if (enabled)
    {
        if (cEnabled)
        {
            console.time('readcache');
            var query = 'SELECT match FROM player_caches WHERE account_id = ?';
            return cassandra.execute(query, [account_id],
            {
                prepare: true
            }, function(err, results)
            {
                if (err)
                {
                    console.log(err);
                    return cb(err);
                }
                if (!results.rows || !results.rows.length)
                {
                    return cb();
                }
                var matches = results.rows.map(function(m)
                {
                    return JSON.parse(m.match);
                });
                //get array of matches, filter, agg and return results
                var filtered = filter(matches, options.js_select);
                var aggData = aggregator(filtered, options.js_agg);
                console.timeEnd('readcache');
                cb(err,
                {
                    aggData: aggData
                });
            });
        }
        else
        {
            //console.time('readcache');
            redis.get(new Buffer("player:" + account_id), function(err, result)
            {
                var cache = result ? JSON.parse(zlib.inflateSync(result)) : null;
                //console.timeEnd('readcache');
                //console.log(result ? result.length : 0, JSON.stringify(cache).length);
                return cb(err, cache);
            });
        }
    }
    else
    {
        return cb();
    }
}

function writeCache(account_id, cache, cb)
{
    if (enabled)
    {
        if (cEnabled)
        {
            console.time("writecache");
            console.log("saving player cache to cassandra %s", account_id);
            var arr = cache.raw.map(function(m)
            {
                return reduceAggregable(m);
            });
            //upsert matches into store
            return async.each(arr, function(m, cb)
            {
                var query = 'INSERT INTO player_caches (account_id, match_id, match) VALUES (?, ?, ?)';
                cassandra.execute(query, [m.account_id, m.match_id, JSON.stringify(m)],
                {
                    prepare: true
                }, cb);
            }, function(err)
            {
                console.timeEnd("writecache");
                return cb(err);
            });
        }
        else
        {
            console.time("writecache");
            console.log("saving player cache to redis %s", account_id);
            redis.ttl("player:" + account_id, function(err, ttl)
            {
                if (err)
                {
                    return cb(err);
                }
                cache = {
                    aggData: cache.aggData
                };
                redis.setex(new Buffer("player:" + account_id), Number(ttl) > 0 ? Number(ttl) : 24 * 60 * 60 * config.UNTRACK_DAYS, zlib.deflateSync(JSON.stringify(cache)), function(err)
                {
                    console.timeEnd("writecache");
                    cb(err);
                });
            });
        }
    }
    else
    {
        return cb();
    }
}

function updateCache(match, cb)
{
    if (enabled)
    {
        var players = match.players;
        if (match.pgroup && players)
        {
            players.forEach(function(p)
            {
                //add account id to each player so we know what caches to update
                p.account_id = match.pgroup[p.player_slot].account_id;
                //add hero_id to each player so we update records with hero played
                p.hero_id = match.pgroup[p.player_slot].hero_id;
            });
        }
        async.eachSeries(players, function(player_match, cb)
        {
            if (player_match.account_id && player_match.account_id !== constants.anonymous_account_id)
            {
                if (cEnabled)
                {
                    writeCache(player_match.account_id,
                    {
                        raw: [player_match]
                    }, cb);
                }
                else
                {
                    readCache(player_match.account_id,
                    {}, function(err, cache)
                    {
                        if (err)
                        {
                            return cb(err);
                        }
                        //if player cache doesn't exist, skip
                        if (cache)
                        {
                            //join player with match to form player_match
                            for (var key in match)
                            {
                                player_match[key] = match[key];
                            }
                            computePlayerMatchData(player_match);
                            cache.aggData = aggregator([player_match], null, cache.aggData);
                            writeCache(player_match.account_id, cache, cb);
                        }
                        else
                        {
                            return cb();
                        }
                    });
                }
            }
            else
            {
                return cb();
            }
        }, cb);
    }
    else
    {
        return cb();
    }
}

function countPlayerCaches(cb)
{
    if (enabled)
    {
        if (cEnabled)
        {
            cassandra.execute('SELECT DISTINCT COUNT(account_id) FROM player_caches', [],
            {
                prepare: true
            }, function(err, result)
            {
                result = result && result.rows && result.rows[0] && result.rows[0].count ? result.rows[0].count.toNumber() : 0;
                return cb(err, result);
            });
        }
        else
        {
            redis.keys("player:*", function(err, result)
            {
                cb(err, result.length);
            });
        }
    }
    else
    {
        return cb(null, 0);
    }
}
module.exports = {
    readCache: readCache,
    writeCache: writeCache,
    updateCache: updateCache,
    countPlayerCaches: countPlayerCaches,
};<commit_msg>remove select distinct<commit_after>var config = require('./config');
var zlib = require('zlib');
var compute = require('./compute');
var computePlayerMatchData = compute.computePlayerMatchData;
var aggregator = require('./aggregator');
var async = require('async');
var constants = require('./constants');
var utility = require('./utility');
var filter = require('./filter');
var reduceAggregable = utility.reduceAggregable;
var enabled = config.ENABLE_PLAYER_CACHE;
var cEnabled = config.ENABLE_CASSANDRA_PLAYER_CACHE;
var redis;
var cassandra;
if (enabled)
{
    redis = require('./redis');
    if (cEnabled)
    {
        cassandra = require('./cassandra');
    }
}

function readCache(account_id, options, cb)
{
    if (enabled)
    {
        if (cEnabled)
        {
            console.time('readcache');
            var query = 'SELECT match FROM player_caches WHERE account_id = ?';
            return cassandra.execute(query, [account_id],
            {
                prepare: true
            }, function(err, results)
            {
                if (err)
                {
                    console.log(err);
                    return cb(err);
                }
                if (!results.rows || !results.rows.length)
                {
                    return cb();
                }
                var matches = results.rows.map(function(m)
                {
                    return JSON.parse(m.match);
                });
                //get array of matches, filter, agg and return results
                var filtered = filter(matches, options.js_select);
                var aggData = aggregator(filtered, options.js_agg);
                console.timeEnd('readcache');
                cb(err,
                {
                    aggData: aggData
                });
            });
        }
        else
        {
            //console.time('readcache');
            redis.get(new Buffer("player:" + account_id), function(err, result)
            {
                var cache = result ? JSON.parse(zlib.inflateSync(result)) : null;
                //console.timeEnd('readcache');
                //console.log(result ? result.length : 0, JSON.stringify(cache).length);
                return cb(err, cache);
            });
        }
    }
    else
    {
        return cb();
    }
}

function writeCache(account_id, cache, cb)
{
    if (enabled)
    {
        if (cEnabled)
        {
            console.time("writecache");
            console.log("saving player cache to cassandra %s", account_id);
            var arr = cache.raw.map(function(m)
            {
                return reduceAggregable(m);
            });
            //upsert matches into store
            return async.each(arr, function(m, cb)
            {
                var query = 'INSERT INTO player_caches (account_id, match_id, match) VALUES (?, ?, ?)';
                cassandra.execute(query, [m.account_id, m.match_id, JSON.stringify(m)],
                {
                    prepare: true
                }, cb);
            }, function(err)
            {
                console.timeEnd("writecache");
                return cb(err);
            });
        }
        else
        {
            console.time("writecache");
            console.log("saving player cache to redis %s", account_id);
            redis.ttl("player:" + account_id, function(err, ttl)
            {
                if (err)
                {
                    return cb(err);
                }
                cache = {
                    aggData: cache.aggData
                };
                redis.setex(new Buffer("player:" + account_id), Number(ttl) > 0 ? Number(ttl) : 24 * 60 * 60 * config.UNTRACK_DAYS, zlib.deflateSync(JSON.stringify(cache)), function(err)
                {
                    console.timeEnd("writecache");
                    cb(err);
                });
            });
        }
    }
    else
    {
        return cb();
    }
}

function updateCache(match, cb)
{
    if (enabled)
    {
        var players = match.players;
        if (match.pgroup && players)
        {
            players.forEach(function(p)
            {
                //add account id to each player so we know what caches to update
                p.account_id = match.pgroup[p.player_slot].account_id;
                //add hero_id to each player so we update records with hero played
                p.hero_id = match.pgroup[p.player_slot].hero_id;
            });
        }
        async.eachSeries(players, function(player_match, cb)
        {
            if (player_match.account_id && player_match.account_id !== constants.anonymous_account_id)
            {
                if (cEnabled)
                {
                    writeCache(player_match.account_id,
                    {
                        raw: [player_match]
                    }, cb);
                }
                else
                {
                    readCache(player_match.account_id,
                    {}, function(err, cache)
                    {
                        if (err)
                        {
                            return cb(err);
                        }
                        //if player cache doesn't exist, skip
                        if (cache)
                        {
                            //join player with match to form player_match
                            for (var key in match)
                            {
                                player_match[key] = match[key];
                            }
                            computePlayerMatchData(player_match);
                            cache.aggData = aggregator([player_match], null, cache.aggData);
                            writeCache(player_match.account_id, cache, cb);
                        }
                        else
                        {
                            return cb();
                        }
                    });
                }
            }
            else
            {
                return cb();
            }
        }, cb);
    }
    else
    {
        return cb();
    }
}

function countPlayerCaches(cb)
{
    if (enabled)
    {
        redis.keys("player:*", function(err, result)
        {
            cb(err, result.length);
        });
    }
    else
    {
        return cb(null, 0);
    }
}
module.exports = {
    readCache: readCache,
    writeCache: writeCache,
    updateCache: updateCache,
    countPlayerCaches: countPlayerCaches,
};<|endoftext|>


<commit_before>var RtmClient = require('@slack/client').RtmClient;
var RTM_EVENTS = require('@slack/client').RTM_EVENTS;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
var doge = require('dogefy');

var getTag = function(id){
    return '<@' + id + '>';
};

var isDirect = function(userId, messageText){
    return messageText && messageText.indexOf(userId) > -1;
};

module.exports = function(key){
    if(!key) throw new Error('You need to specify a Slack token');

    var rtm = new RtmClient(key);

    rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function() {
        var team = rtm.dataStore.getTeamById(rtm.activeTeamId);
        var user = rtm.dataStore.getUserById(rtm.activeUserId);
        console.log('Connected to ' + team.name + ' as ' + user.name);
    });

    rtm.on(RTM_EVENTS.MESSAGE, function(message){
        var channel = rtm.dataStore.getChannelGroupOrDMById(message.channel);

        if(message.type === 'message' && message.text && (channel.is_im || isDirect(rtm.activeUserId, message.text))){
            var cleanedMessage = message.text.replace(getTag(rtm.activeUserId), '').replace(':', '').substring(0, 2000).trim();

            if(cleanedMessage){
                console.log('Dogefied: ' + cleanedMessage);
                rtm.sendMessage('``` \n' + doge(cleanedMessage) + '\n ```', message.channel);
            }
        }
    });

    rtm.start();
};
<commit_msg>chore: indentation<commit_after>var RtmClient = require('@slack/client').RtmClient;
var RTM_EVENTS = require('@slack/client').RTM_EVENTS;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
var doge = require('dogefy');

var getTag = function(id){
  return '<@' + id + '>';
};

var isDirect = function(userId, messageText){
  return messageText && messageText.indexOf(userId) > -1;
};

module.exports = function(key){
  if(!key) throw new Error('You need to specify a Slack token');

  var rtm = new RtmClient(key);

  rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function() {
    var team = rtm.dataStore.getTeamById(rtm.activeTeamId);
    var user = rtm.dataStore.getUserById(rtm.activeUserId);
    console.log('Connected to ' + team.name + ' as ' + user.name);
  });

  rtm.on(RTM_EVENTS.MESSAGE, function(message){
    var channel = rtm.dataStore.getChannelGroupOrDMById(message.channel);

    if(message.type === 'message' && message.text && (channel.is_im || isDirect(rtm.activeUserId, message.text))){
      var cleanedMessage = message.text.replace(getTag(rtm.activeUserId), '').replace(':', '').substring(0, 2000).trim();

      if(cleanedMessage){
        console.log('Dogefied: ' + cleanedMessage);
        rtm.sendMessage('``` \n' + doge(cleanedMessage) + '\n ```', message.channel);
      }
    }
  });

  rtm.start();
};
<|endoftext|>


<commit_before>/**
 * @since 2016-12-07 20:23
 * @author vivaxy
 */

const logger = require('../lib/logger');

const getTimeStamp = () => {
    return new Date().getTime();
};

module.exports = async(ctx, next) => {
    const request = ctx.request;

    const startTime = getTimeStamp();

    try {
        await next();
    } catch (ex) {
        logger.error(ex);
    }
    logger.info(`[request] ${request.method} ${request.path} in ${getTimeStamp() - startTime}ms`);
};
<commit_msg>feat(log): :sparkles:Update log middleware<commit_after>/**
 * @since 2016-12-07 20:23
 * @author vivaxy
 */

const logger = require('../lib/logger');

const getTimeStamp = () => {
    return new Date().getTime();
};

const stringify = (json) => {
    return JSON.stringify(json, (k, v) => {
        if (Array.isArray(v)) {
            return [v.length];
        }
        return v;
    });
};

module.exports = async (ctx, next) => {
    const request = ctx.request;

    const startTime = getTimeStamp();

    try {
        await next();
    } catch (ex) {
        logger.error(ex);
    }
    logger.info(`[request] ${request.method} ${request.path}; params=${stringify(ctx.params)}, query=${stringify(ctx.query)}, body=${stringify(ctx.request.body)}; [response] status=${ctx.status}, body=${stringify(ctx.body)}; [time] ${getTimeStamp() - startTime}ms`);
};
<|endoftext|>


<commit_before>// Enables TLS. This is built into the server anyway, but enabling this plugin
// just advertises it.

var utils = require('./utils')
    , util = require("util");

// To create a key:
// openssl req -x509 -nodes -days 2190 -newkey rsa:1024 \
//         -keyout config/tls_key.pem -out config/tls_cert.pem

exports.hook_capabilities = function (next, connection) {
    /* Caution: We cannot advertise STARTTLS if the upgrade has already been done. */
    if (connection.notes.tls_enabled !== 1) {
        connection.capabilities.push('STARTTLS');
        connection.notes.tls_enabled = 1;
    }
    /* Let the plugin chain continue. */
    next();
};

exports.hook_unrecognized_command = function (next, connection, params) {
    /* Watch for STARTTLS directive from client. */
    if (params[0] === 'STARTTLS') {
        var key = this.config.get('tls_key.pem', 'binary');
        var cert = this.config.get('tls_cert.pem', 'binary');
        var options = { key: key, cert: cert, requestCert: true };

        /* Respond to STARTTLS command. */
        connection.respond(220, "Go ahead.");
        /* Upgrade the connection to TLS. */
        var self = this;
        connection.client.upgrade(options, function (authorized, verifyError, cert, cipher) {
            connection.reset_transaction();
            connection.hello_host = undefined;
            connection.using_tls = true;
            connection.notes.tls = {
                authorized: authorized,
                authorizationError: verifyError,
                peerCertificate: cert,
                cipher: cipher
            };
            connection.loginfo(self, 'secured:' +
                ((cipher) ? ' cipher=' + cipher.name + ' version=' + cipher.version : '') +
                ' verified=' + authorized +
                ((verifyError) ? ' error="' + verifyError + '"' : '' ) +
                ((cert && cert.subject) ? ' cn="' + cert.subject.CN + '"' +
                ' organization="' + cert.subject.O + '"' : '') +
                ((cert && cert.issuer) ? ' issuer="' + cert.issuer.O + '"' : '') +
                ((cert && cert.valid_to) ? ' expires="' + cert.valid_to + '"' : '') +
                ((cert && cert.fingerprint) ? ' fingerprint=' + cert.fingerprint : ''));
            return next(OK);  // Return OK as we responded to the client
        });
    }
    else {
        return next();
    }
};
<commit_msg>remove debug dependeces<commit_after>// Enables TLS. This is built into the server anyway, but enabling this plugin
// just advertises it.

var utils = require('./utils');

// To create a key:
// openssl req -x509 -nodes -days 2190 -newkey rsa:1024 \
//         -keyout config/tls_key.pem -out config/tls_cert.pem

exports.hook_capabilities = function (next, connection) {
    /* Caution: We cannot advertise STARTTLS if the upgrade has already been done. */
    if (connection.notes.tls_enabled !== 1) {
        connection.capabilities.push('STARTTLS');
        connection.notes.tls_enabled = 1;
    }
    /* Let the plugin chain continue. */
    next();
};

exports.hook_unrecognized_command = function (next, connection, params) {
    /* Watch for STARTTLS directive from client. */
    if (params[0] === 'STARTTLS') {
        var key = this.config.get('tls_key.pem', 'binary');
        var cert = this.config.get('tls_cert.pem', 'binary');
        var options = { key: key, cert: cert, requestCert: true };

        /* Respond to STARTTLS command. */
        connection.respond(220, "Go ahead.");
        /* Upgrade the connection to TLS. */
        var self = this;
        connection.client.upgrade(options, function (authorized, verifyError, cert, cipher) {
            connection.reset_transaction();
            connection.hello_host = undefined;
            connection.using_tls = true;
            connection.notes.tls = {
                authorized: authorized,
                authorizationError: verifyError,
                peerCertificate: cert,
                cipher: cipher
            };
            connection.loginfo(self, 'secured:' +
                ((cipher) ? ' cipher=' + cipher.name + ' version=' + cipher.version : '') +
                ' verified=' + authorized +
                ((verifyError) ? ' error="' + verifyError + '"' : '' ) +
                ((cert && cert.subject) ? ' cn="' + cert.subject.CN + '"' +
                ' organization="' + cert.subject.O + '"' : '') +
                ((cert && cert.issuer) ? ' issuer="' + cert.issuer.O + '"' : '') +
                ((cert && cert.valid_to) ? ' expires="' + cert.valid_to + '"' : '') +
                ((cert && cert.fingerprint) ? ' fingerprint=' + cert.fingerprint : ''));
            return next(OK);  // Return OK as we responded to the client
        });
    }
    else {
        return next();
    }
};
<|endoftext|>


<commit_before>import {h, Component} 					from 'preact/preact';
import Shallow			 				from 'shallow/shallow';

import ButtonBase						from 'com/button-base/base';
import ButtonLink						from 'com/button-link/link';
import SVGIcon 							from 'com/svg-icon/icon';
import NavLink 							from 'com/nav-link/link';

import NavSpinner						from 'com/nav-spinner/spinner';

import UIButton							from 'com/ui/button/button';

//import DropdownUser 					from 'com/dropdown-user/user';
import BarNotification					from 'bar-notifications';
import BarUser							from 'bar-user';

//import $Node							from 'shrub/js/node/node';
import $Notification					from 'shrub/js/notification/notification';

function make_url( url ) {
	return url + window.location.search;
}

export default class ViewBar extends Component {
	constructor( props ) {
		super(props);

		this.StartedNotificationLoop = false;

		this.state - {
			'notifications': 0,
			'notificationsHidden': 0,
			'notificationsFeed': null,
			//'notificationsMore': false,
		};

		this.handleNotificationsClear = this.handleNotificationsClear.bind(this);
		this.handleNotificationsHide = this.handleNotificationsHide.bind(this);
	}

	handleNotificationsClear() {
		this.setState({
			'notifications': 0,
			'notificationsHidden': 0,
			//'notificationsFeed': null,
			//'notificationsMore': false,
		});
	}

	handleNotificationsHide() {
		this.setState({'showNotifications': false});
	}

	checkNotificationCount() {
		const {user} = this.props;
		const loggedIn = user && (user.id > 0);
		const fetchCount = 40;

		if (loggedIn) {
			let firstCall = !this.StartedNotificationLoop;
			this.StartedNotificationLoop = true;

			if ( document.hidden && !firstCall ) {
				// Page is hidden - Don't do any actual querying, just set the timeout to come back later
				// But, if this was the first check, always try to get the notifications regardless.
				setTimeout(() => this.checkNotificationCount(), 20000);
			}
			else {
				const {notifications, notificationsFeed} = this.state;
				$Notification.GetCountUnread()
				.then(r => {
					if (r.status !== 200) {
						location.href = '# expired';
						setTimeout(() => this.checkNotificationCount(), 5 * 60000);
						return Promise.reject();
					}
					const newUnfilteredCount = r.count;
					// Only get unread if there's a possibility that there are new notifications
					// Only get the feed in general if it hasn't been requested before.
					const request = newUnfilteredCount > (notifications || 0) ?
						$Notification.GetFeedUnreadFiltered :
             !notificationsFeed && $Notification.GetFeedAllFiltered;
					request && request(0, fetchCount)
					.then(r => {
						if (this.state.notifications != r.count) {
							this.setState({
								'notifications': newUnfilteredCount > 0 ? r.count : 0,
								'notificationsHidden': r.countFiltered,
								//'notificationsMore': r.countFiltered + r.count == fetchCount,
								'notificationsFeed': r,
								'notificationsError': null,
							});
						}
						setTimeout(() => this.checkNotificationCount(), 60000);
					})
					.catch((e) => {
						this.setState({'notificationsError': 'Could not retrieve notifications feed.'});
						setTimeout(() => this.checkNotificationCount(), 5 * 60000);
						console.log('[Notificaton error]', e);
					});
				})
				.catch((e) => {
					this.setState({'notificationsError': 'Could not retrieve notifications count.'});
					setTimeout(() => this.checkNotificationCount(), 5 * 60000);
					console.log('[Notificaton count error]', e);
				});
			}
		}
		else {
			this.handleNotificationsClear();
			this.StartedNotificationLoop = false;
		}
	}

	componentDidMount() {
		document.body.classList.add('_use-view-bar');

		if ( !this.StartedNotificationLoop ) {
			this.checkNotificationCount();
		}
	}

	componentWillUnmount() {
		document.body.classList.remove('_use-view-bar');
		document.body.classList.remove('_static-view-bar');
	}

//	componentWillReceiveProps( nextProps ) {
//		if ( Shallow.Diff(nextProps, this.props) ) {
////			console.log('featured',nextProps.featured);
//		}
//	}

	shouldComponentUpdate( nextProps, nextState ) {
		var ret = Shallow.Compare(this, nextProps, nextState);
		//console.log(ret, nextProps.featured);
		return ret;
	}

	componentDidUpdate() {
		// When the user changes (and anything else changes) check to see if we should start the notification checking loop.
		if ( !this.StartedNotificationLoop ) {
			this.checkNotificationCount();
		}
	}

	renderLeft() {
	}

	renderRight( user, featured ) {
		var Search = null;
//		var Search = (
//			<ButtonBase class="-bar-icon" onclick={e => { console.log('search'); window.location.hash = "#search"; }}>
//				<SVGIcon baseline>search</SVGIcon>
//			</ButtonBase>
//		);

		var ShowCalendar = (
			<UIButton
				class="-bar-button if-no-sidebar-block"
				onclick={e => {
						console.log('calendar');
						window.location.hash = "#cal";
				}}
			>
				<SVGIcon baseline>calendar</SVGIcon>

Schedule

			</UIButton>
		);

		let ShowJoin = null;
		let ShowMyGame = null;
		let NewPost = null;
		let Notification = null;
		let ShowUser = null;
		let Register = null;
		let Login = null;
		let GoSecure = null;
		let ShowSpinner = null;
		let ShowNotifications = null;

		// Disallow insecure login
		if ( SECURE_LOGIN_ONLY && (location.protocol !== 'https:') ) {
			let SecureURL = 'https://'+location.hostname+location.pathname+location.search+location.hash;
			GoSecure = (
				<UIButton
					class="-bar-button"
					noblank
					href={SecureURL}
				>
					<SVGIcon>unlocked</SVGIcon>

Go to Secure Site

				</UIButton>
			);
		}
		// Both user and user.id means logged in
		else if ( user && user.id ) {
			if ( featured && featured.id ) {
				if ( featured.focus ) {
					ShowMyGame = (
						<UIButton href={featured.what_node[featured.focus].path} class="-bar-button">
							<SVGIcon>gamepad</SVGIcon>

My Game

						</UIButton>
					);

					NewPost = (
						<UIButton
							class="-bar-button"
							onclick={e => {
								window.location.hash = "#create/"+featured.focus+"/post";
							}}
						>
							<SVGIcon>edit</SVGIcon>

New

						</UIButton>
					);
				}
				else if ( node_CanCreate(featured) ) {
					ShowJoin = (
						<UIButton
							class="-bar-button"
							onclick={e => {
								window.location.hash = "#create/"+featured.id+"/item/game";
							}}
						>
							<SVGIcon>publish</SVGIcon>

Join Event

						</UIButton>
					);
				}
			}

			// Notifications
			let NotificationCount = null;
			const notificationCount = this.state.notifications;
			if (notificationCount > 0) {
				/*
				if (this.state.notificationsMore) {
					NotificationCount = (
{notificationCount}+
);

				}
				else { */
				NotificationCount = (
{notificationCount}
);
			}
			/* else if (this.state.notificationsMore) {
				if (NotificationCount === null) {
					NotificationCount = (
+
);
				}
			}
			else if (this.state.notificationsHidden) {
				NotificationCount = (
({this.state.notificationsHidden})
);
			} */

			if (this.state.showNotifications) {
				ShowNotifications = (
					<BarNotification
						feed={this.state.notificationsFeed}
						anythingToMark={this.state.notifications > 0 || this.state.notificationsHidden > 0}
						clearCallback={this.handleNotificationsClear}
						hideCallback={this.handleNotificationsHide}
						error={this.state.notificationsError}
					/>
				);
			}

			Notification = (
				<UIButton class="-bar-icon" onclick={(e) => {
					// TODO: if the main content is the notifications feed, clicking the button should
					// probably not show the dropdown, but load new comments into the feed.
					this.setState({'showNotifications': !this.state.showNotifications});
				}}>
					<SVGIcon baseline>bubble</SVGIcon>
					{NotificationCount}
				</UIButton>
			);

/*
			// TODO: Pull this out of the user meta, else use a dummy
			let Avatar = (user.meta && user.meta.avatar) ?  : ;
			//'/other/logo/mike/Chicken64.png';
			let MyURL = '/users/'+user.slug+'/';
			ShowUser = [
				<UIButton class="-user">
					<NavLink href={MyURL}>{Avatar}</NavLink>
				</UIButton>,
//				<DropdownUser />
			];
*/

			ShowUser = <BarUser user={user} />;
		}
		// If user has finished loading (and is not logged in)
		else if ( user ) {
			Register = (
				<UIButton
					class="-bar-button"
					onclick={e => {
						console.log('register');
						window.location.hash = "#user-register";
					}}
				>
					<SVGIcon>user-plus</SVGIcon>

Create Account

				</UIButton>
			);
			Login = (
				<UIButton
					class="-bar-button"
					onclick={e => {
						console.log('login');
						window.location.hash = "#user-login";
					}}
				>
					<SVGIcon>key</SVGIcon>

Login

				</UIButton>
			);
		}
		// Still waiting
		else {
			ShowSpinner = <NavSpinner />;
		}

		if ( ShowSpinner ) {
			return (

					{ShowSpinner}

			);
		}
		else {
			return (

					{ShowJoin}
					{ShowMyGame}
					{NewPost}
					{ShowCalendar}
					{Search}
					{Notification}
					{ShowNotifications}
					{ShowUser}
					{Register}
					{Login}
					{GoSecure}

			);
		}
	}

	render( props ) {
		let {user, featured, loading} = props;
		let ShowLoading;

		if ( loading ) {
			ShowLoading = (<NavSpinner />);
		}

		return (

						<UIButton title="Ludum Dare" href="/" class="-logo">
							<SVGIcon class="if-sidebar-block" baseline>ludum</SVGIcon><SVGIcon class="if-sidebar-block" baseline>dare</SVGIcon>
							<SVGIcon class="if-no-sidebar-block" baseline>l-udum</SVGIcon><SVGIcon class="if-no-sidebar-block" baseline>d-are</SVGIcon>
						</UIButton>

					{ShowLoading}
					{this.renderRight(user, featured)}

		);
	}
}
<commit_msg>add notification indicator in favicon<commit_after>import {h, Component} 					from 'preact/preact';
import Shallow			 				from 'shallow/shallow';

import ButtonBase						from 'com/button-base/base';
import ButtonLink						from 'com/button-link/link';
import SVGIcon 							from 'com/svg-icon/icon';
import NavLink 							from 'com/nav-link/link';

import NavSpinner						from 'com/nav-spinner/spinner';

import UIButton							from 'com/ui/button/button';

//import DropdownUser 					from 'com/dropdown-user/user';
import BarNotification					from 'bar-notifications';
import BarUser							from 'bar-user';

//import $Node							from 'shrub/js/node/node';
import $Notification					from 'shrub/js/notification/notification';

function make_url( url ) {
	return url + window.location.search;
}

export default class ViewBar extends Component {
	constructor( props ) {
		super(props);
		this.StartedNotificationLoop = false;

		this.state - {
			'notifications': 0,
			'notificationsHidden': 0,
			'notificationsFeed': null,
			//'notificationsMore': false,
		};

		this.handleNotificationsClear = this.handleNotificationsClear.bind(this);
		this.handleNotificationsHide = this.handleNotificationsHide.bind(this);
	}

	handleNotificationsClear() {
		this.setState({
			'notifications': 0,
			'notificationsHidden': 0,
			//'notificationsFeed': null,
			//'notificationsMore': false,
		});
		this.refreshFavIconNotificationCount();
	}

	handleNotificationsHide() {
		this.setState({'showNotifications': false});
	}

	checkNotificationCount() {
		const {user} = this.props;
		const loggedIn = user && (user.id > 0);
		const fetchCount = 40;

		if (loggedIn) {
			let firstCall = !this.StartedNotificationLoop;
			this.StartedNotificationLoop = true;

			if ( document.hidden && !firstCall ) {
				// Page is hidden - Don't do any actual querying, just set the timeout to come back later
				// But, if this was the first check, always try to get the notifications regardless.
				setTimeout(() => this.checkNotificationCount(), 20000);
			}
			else {
				const {notifications, notificationsFeed} = this.state;
				$Notification.GetCountUnread()
				.then(r => {
					if (r.status !== 200) {
						location.href = '# expired';
						setTimeout(() => this.checkNotificationCount(), 5 * 60000);
						return Promise.reject();
					}
					const newUnfilteredCount = r.count;
					// Only get unread if there's a possibility that there are new notifications
					// Only get the feed in general if it hasn't been requested before.
					const request = newUnfilteredCount > (notifications || 0) ?
						$Notification.GetFeedUnreadFiltered :
						!notificationsFeed && $Notification.GetFeedAllFiltered;
					request && request(0, fetchCount)
					.then(r => {
						if (this.state.notifications != r.count) {
							this.setState({
								'notifications': newUnfilteredCount > 0 ? r.count : 0,
								'notificationsHidden': r.countFiltered,
								//'notificationsMore': r.countFiltered + r.count == fetchCount,
								'notificationsFeed': r,
								'notificationsError': null,
							});
							this.refreshFavIconNotificationCount();
						}
						setTimeout(() => this.checkNotificationCount(), 60000);
					})
					.catch((e) => {
						this.setState({'notificationsError': 'Could not retrieve notifications feed.'});
						setTimeout(() => this.checkNotificationCount(), 5 * 60000);
						console.log('[Notificaton error]', e);
					});
				})
				.catch((e) => {
					this.setState({'notificationsError': 'Could not retrieve notifications count.'});
					setTimeout(() => this.checkNotificationCount(), 5 * 60000);
					console.log('[Notificaton count error]', e);
				});
			}
		}
		else {
			this.handleNotificationsClear();
			this.StartedNotificationLoop = false;
		}
	}

	componentDidMount() {
		document.body.classList.add('_use-view-bar');

		if ( !this.StartedNotificationLoop ) {
			this.checkNotificationCount();
		}
	}

	componentWillUnmount() {
		document.body.classList.remove('_use-view-bar');
		document.body.classList.remove('_static-view-bar');
	}

//	componentWillReceiveProps( nextProps ) {
//		if ( Shallow.Diff(nextProps, this.props) ) {
////			console.log('featured',nextProps.featured);
//		}
//	}

	shouldComponentUpdate( nextProps, nextState ) {
		var ret = Shallow.Compare(this, nextProps, nextState);
		//console.log(ret, nextProps.featured);
		return ret;
	}

	componentDidUpdate() {
		// When the user changes (and anything else changes) check to see if we should start the notification checking loop.
		if ( !this.StartedNotificationLoop ) {
			this.checkNotificationCount();
		}
	}

	/**
	 * Adds the # of notifications in the favicon.
	 * Shows individual numbers until 9, then 9+ for more.
	 */
	refreshFavIconNotificationCount() {
		const notificationCount = this.state.notifications || 0;
		// remove existing icon if any
		const el = document.querySelector("link[rel='shortcut icon']");
		if (el) el.parentNode.removeChild(el);
		// reload LD favicon and paint it
		const canvas = document.createElement('canvas');
		canvas.setAttribute('width', 64);
		canvas.setAttribute('height', 64);
		const context = canvas.getContext('2d');
		const icon = new Image();
		icon.setAttribute('src', '/favicon.ico');
		icon.onload = () => {
			// LD favicon as background
			context.drawImage(icon, 0, 0);
			// We only draw text for # > 0
			if (notificationCount > 0) {
				const text = notificationCount > 9 ? "9+" : String(notificationCount);
				// Dark backdrop for contrast
				context.fillStyle = '#0d4263';
				context.rect(text.length > 1 ? 14 : 38, 30, 50, 50);
				context.fill();
				context.fillStyle = '#fff';
				context.font = 'bold 36px tahoma';
				context.fillText(text, text.length > 1 ? 16 : 40, 64);
			}
			// Replace favicon
			const link = document.createElement('link');
			link.type = 'image/x-icon';
			link.rel = 'shortcut icon';
			link.href = canvas.toDataURL("image/x-icon");
			document.getElementsByTagName('head')[0].appendChild(link);
		};
	}

	renderLeft() {
	}

	renderRight( user, featured ) {
		var Search = null;
//		var Search = (
//			<ButtonBase class="-bar-icon" onclick={e => { console.log('search'); window.location.hash = "#search"; }}>
//				<SVGIcon baseline>search</SVGIcon>
//			</ButtonBase>
//		);

		var ShowCalendar = (
			<UIButton
				class="-bar-button if-no-sidebar-block"
				onclick={e => {
						console.log('calendar');
						window.location.hash = "#cal";
				}}
			>
				<SVGIcon baseline>calendar</SVGIcon>

Schedule

			</UIButton>
		);

		let ShowJoin = null;
		let ShowMyGame = null;
		let NewPost = null;
		let Notification = null;
		let ShowUser = null;
		let Register = null;
		let Login = null;
		let GoSecure = null;
		let ShowSpinner = null;
		let ShowNotifications = null;

		// Disallow insecure login
		if ( SECURE_LOGIN_ONLY && (location.protocol !== 'https:') ) {
			let SecureURL = 'https://'+location.hostname+location.pathname+location.search+location.hash;
			GoSecure = (
				<UIButton
					class="-bar-button"
					noblank
					href={SecureURL}
				>
					<SVGIcon>unlocked</SVGIcon>

Go to Secure Site

				</UIButton>
			);
		}
		// Both user and user.id means logged in
		else if ( user && user.id ) {
			if ( featured && featured.id ) {
				if ( featured.focus ) {
					ShowMyGame = (
						<UIButton href={featured.what_node[featured.focus].path} class="-bar-button">
							<SVGIcon>gamepad</SVGIcon>

My Game

						</UIButton>
					);

					NewPost = (
						<UIButton
							class="-bar-button"
							onclick={e => {
								window.location.hash = "#create/"+featured.focus+"/post";
							}}
						>
							<SVGIcon>edit</SVGIcon>

New

						</UIButton>
					);
				}
				else if ( node_CanCreate(featured) ) {
					ShowJoin = (
						<UIButton
							class="-bar-button"
							onclick={e => {
								window.location.hash = "#create/"+featured.id+"/item/game";
							}}
						>
							<SVGIcon>publish</SVGIcon>

Join Event

						</UIButton>
					);
				}
			}

			// Notifications
			let NotificationCount = null;
			const notificationCount = this.state.notifications;
			if (notificationCount > 0) {
				/*
				if (this.state.notificationsMore) {
					NotificationCount = (
{notificationCount}+
);

				}
				else { */
				NotificationCount = (
{notificationCount}
);
			}
			/* else if (this.state.notificationsMore) {
				if (NotificationCount === null) {
					NotificationCount = (
+
);
				}
			}
			else if (this.state.notificationsHidden) {
				NotificationCount = (
({this.state.notificationsHidden})
);
			} */

			if (this.state.showNotifications) {
				ShowNotifications = (
					<BarNotification
						feed={this.state.notificationsFeed}
						anythingToMark={this.state.notifications > 0 || this.state.notificationsHidden > 0}
						clearCallback={this.handleNotificationsClear}
						hideCallback={this.handleNotificationsHide}
						error={this.state.notificationsError}
					/>
				);
			}

			Notification = (
				<UIButton class="-bar-icon" onclick={(e) => {
					// TODO: if the main content is the notifications feed, clicking the button should
					// probably not show the dropdown, but load new comments into the feed.
					this.setState({'showNotifications': !this.state.showNotifications});
				}}>
					<SVGIcon baseline>bubble</SVGIcon>
					{NotificationCount}
				</UIButton>
			);

/*
			// TODO: Pull this out of the user meta, else use a dummy
			let Avatar = (user.meta && user.meta.avatar) ?  : ;
			//'/other/logo/mike/Chicken64.png';
			let MyURL = '/users/'+user.slug+'/';
			ShowUser = [
				<UIButton class="-user">
					<NavLink href={MyURL}>{Avatar}</NavLink>
				</UIButton>,
//				<DropdownUser />
			];
*/

			ShowUser = <BarUser user={user} />;
		}
		// If user has finished loading (and is not logged in)
		else if ( user ) {
			Register = (
				<UIButton
					class="-bar-button"
					onclick={e => {
						console.log('register');
						window.location.hash = "#user-register";
					}}
				>
					<SVGIcon>user-plus</SVGIcon>

Create Account

				</UIButton>
			);
			Login = (
				<UIButton
					class="-bar-button"
					onclick={e => {
						console.log('login');
						window.location.hash = "#user-login";
					}}
				>
					<SVGIcon>key</SVGIcon>

Login

				</UIButton>
			);
		}
		// Still waiting
		else {
			ShowSpinner = <NavSpinner />;
		}

		if ( ShowSpinner ) {
			return (

					{ShowSpinner}

			);
		}
		else {
			return (

					{ShowJoin}
					{ShowMyGame}
					{NewPost}
					{ShowCalendar}
					{Search}
					{Notification}
					{ShowNotifications}
					{ShowUser}
					{Register}
					{Login}
					{GoSecure}

			);
		}
	}

	render( props ) {
		let {user, featured, loading} = props;
		let ShowLoading;

		if ( loading ) {
			ShowLoading = (<NavSpinner />);
		}

		return (

						<UIButton title="Ludum Dare" href="/" class="-logo">
							<SVGIcon class="if-sidebar-block" baseline>ludum</SVGIcon><SVGIcon class="if-sidebar-block" baseline>dare</SVGIcon>
							<SVGIcon class="if-no-sidebar-block" baseline>l-udum</SVGIcon><SVGIcon class="if-no-sidebar-block" baseline>d-are</SVGIcon>
						</UIButton>

					{ShowLoading}
					{this.renderRight(user, featured)}

		);
	}
}
<|endoftext|>