<commit_before>/* jshint evil: true */

(function() {

var controllers = { };

/***************
 * DefenseCtrl *
 ***************/

controllers.DefenseCtrl = function($scope, $state, $stateParams) {

    $scope.$watch('query',function() {
        var regex = new RegExp($scope.query || '','i');
        $scope.list = defenses.filter(function(x) { return regex.test(x[0]); });
    });

    $scope.pickDefense = function(defense) {
        $scope.data.defense = defense[3];
        $state.go('^');
    };

    $scope.list = [ ];
    $scope.query = '';

};

/**************
 * PickerCtrl *
 **************/

controllers.PickerCtrl = function($scope, $state, $stateParams) {

    /* * * * * Scope variables * * * * */

    $scope.units = [ ];
    $scope.query = '';
    $scope.recents = JSON.parse(localStorage.getItem('recentUnits')) || [ ];

    $scope.$watch('query',function() { populateList(); },true);

    /* * * * * Scope functions * * * * */

    $scope.pickUnit = function(unitNumber) {
        $scope.data.team[$stateParams.slot] = { unit: units[unitNumber], level: 1, orb: 1 };
        $scope.resetSlot($stateParams.slot,true);
        updateRecent(unitNumber);
        $state.go('^');
    };

    /* * * * * List generation * * * * */

    var generateSearchParameters = function() {
        if (!$scope.query || $scope.query.trim().length < 3) return null;
        var result = { name: [ ] };
        tokens = $scope.query.trim().replace(/\s+/g,' ').split(' ').filter(function(x) { return x.length > 0; });
        tokens.forEach(function(x) {
            var temp = x.match(/^((type|class):(\w+)|(hp|atk|stars|cost|growth|rcv)(>|<|>=|<=|=)(\d+))$/), func;
            if (!temp) {
                result.name.push(x);
            } else if (temp[4] !== undefined) {
                func = new Function('x','return x ' + temp[5].replace(/^=$/,'==') + ' ' + temp[6] + ';');
                result[temp[4]] = func;
            } else {
                func = new Function('x','return /' + temp[3] + '/i.test(x);');
                result[temp[2]] = func;
            }
        });
        if (result.name.length === 0) delete result.name;
        else result.name = new Function('x','return /' + result.name.join(' ') + '/i.test(x);');
        return result;
    };

    var populateList = function() {
        var result, parameters = generateSearchParameters();
        if (parameters === null) return;
        result = units.filter(function(x) { return x !== null && x !== undefined; });
        Object.keys(parameters).forEach(function(key) {
            var unitKey = key.replace(/^(hp|atk|rcv)$/,function(x) { return 'max' + x.toUpperCase(); });
            result = result.filter(function(x) { return parameters[key](x[unitKey]); });
        });
        $scope.units = result;
    };

    /* * * * * Recent list generation * * * * */

    var updateRecent = function(unitNumber) {
        var recentUnits = JSON.parse(JSON.stringify($scope.recents));
        var n = recentUnits.indexOf(unitNumber);
        if (n < 0) recentUnits.unshift(unitNumber);
        else recentUnits = recentUnits.splice(n,1).concat(recentUnits);
        recentUnits = recentUnits.slice(0,14);
        localStorage.setItem('recentUnits',JSON.stringify(recentUnits));
    };

};

/*************
 * SlotsCtrl *
 *************/

controllers.SlotsCtrl = function($scope, $state, $stateParams) {

    /* * * * * Functions * * * * */

    var populateSlots = function(query) {
        var regex = new RegExp(($scope.query || ''),'i'), result = { };
        for (var key in slots) {
            if (regex.test(slots[key].name))
                result[key] = slots[key];
        }
        $scope.slots = result;
    };

    /* * * * * Local variables * * * * */

    var lastSlotName = JSON.parse(localStorage.getItem('lastSlotName')) || '';
    var slots = JSON.parse(localStorage.getItem('slots')) || { };

    /* * * * * Scope variables * * * * */

    $scope.query = '';
    $scope.slots = slots;
    $scope.lastSlot = lastSlotName;
    $scope.overwriting = false;

    $scope.$watch('query',populateSlots);

    $scope.$watch('lastSlot',function(value) {
        if (value)
            $scope.overwriting = slots.hasOwnProperty(value.toLowerCase());
    });

    /* * * * * Scope functions * * * * */

    $scope.teamClick = function(e,slot) {
        if (e.which == 1 && !e.ctrlKey) {
            slot.team.map(function(x,n) {
                $scope.resetSlot(n);
                if (x !== null) $scope.data.team[n] = { unit: units[slot.team[n].unit], level: slot.team[n].level };
            });
            localStorage.setItem('lastSlotName',JSON.stringify(slot.name));
            $state.go('^');
        } else if (e.which == 2 || (e.which == 1 && e.ctrlKey)) {
            delete slots[slot.name];
            delete $scope.slots[slot.name];
            localStorage.setItem('slots',JSON.stringify(slots));
        }
    };

    $scope.saveTeam = function() {
        $scope.$broadcast('$validate');
        var team = $scope.data.team.map(function(x) {
            return !x.unit ? null : { unit : x.unit.number, level: x.level };
        });
        slots[$scope.lastSlot.toLowerCase()] = { name: $scope.lastSlot, team: team };
        localStorage.setItem('slots',JSON.stringify(slots));
        localStorage.setItem('lastSlotName',JSON.stringify($scope.lastSlot));
        $state.go('^');
    };

};

/************
 * ShipCtrl *
 ************/

controllers.ShipCtrl = function($scope, $state) {

    $scope.query = '';
    $scope.list = ships;

    $scope.$watch('query',function() {
        var regex = new RegExp(($scope.query || ''),'i'), result = { };
        for (var key in ships) {
            if (regex.test(key))
                result[key] = ships[key];
        }
        $scope.list = result;
    });

    $scope.getThumbnail = function(ship) {
        if (!ship.thumb) return '';
        return 'background-image: url(http://onepiece-treasurecruise.com/wp-content/uploads/' + ship.thumb + ')';
    };

    $scope.pickShip = function(name) {
        $scope.data.ship.name = name;
        $state.go('^');
    };

};

/*************
 * ResetCtrl *
 *************/

controllers.ResetCtrl = function($scope, $state) {
    $scope.resetStorage = function() {
        localStorage.removeItem('team');
        for (var i=0;i<6;++i) $scope.resetSlot(i);
        $state.go('^');
    };
};

/*****************************
 * Controller initialization *
 *****************************/

for (var key in controllers)
    angular.module('optc')
        .controller(key, controllers[key]);

})();
<commit_msg>fixed growth search<commit_after>/* jshint evil: true */

(function() {

var controllers = { };

/***************
 * DefenseCtrl *
 ***************/

controllers.DefenseCtrl = function($scope, $state, $stateParams) {

    $scope.$watch('query',function() {
        var regex = new RegExp($scope.query || '','i');
        $scope.list = defenses.filter(function(x) { return regex.test(x[0]); });
    });

    $scope.pickDefense = function(defense) {
        $scope.data.defense = defense[3];
        $state.go('^');
    };

    $scope.list = [ ];
    $scope.query = '';

};

/**************
 * PickerCtrl *
 **************/

controllers.PickerCtrl = function($scope, $state, $stateParams) {

    /* * * * * Scope variables * * * * */

    $scope.units = [ ];
    $scope.query = '';
    $scope.recents = JSON.parse(localStorage.getItem('recentUnits')) || [ ];

    $scope.$watch('query',function() { populateList(); },true);

    /* * * * * Scope functions * * * * */

    $scope.pickUnit = function(unitNumber) {
        $scope.data.team[$stateParams.slot] = { unit: units[unitNumber], level: 1, orb: 1 };
        $scope.resetSlot($stateParams.slot,true);
        updateRecent(unitNumber);
        $state.go('^');
    };

    /* * * * * List generation * * * * */

    var generateSearchParameters = function() {
        if (!$scope.query || $scope.query.trim().length < 3) return null;
        var result = { name: [ ] };
        tokens = $scope.query.trim().replace(/\s+/g,' ').split(' ').filter(function(x) { return x.length > 0; });
        tokens.forEach(function(x) {
            var temp = x.match(/^((type|class):(\w+)|(hp|atk|stars|cost|growth|rcv)(>|<|>=|<=|=)([\d.]+))$/), func;
            if (!temp) {
                result.name.push(x);
            } else if (temp[4] !== undefined) {
                func = new Function('x','return x ' + temp[5].replace(/^=$/,'==') + ' ' + temp[6] + ';');
                result[temp[4]] = func;
            } else {
                func = new Function('x','return /' + temp[3] + '/i.test(x);');
                result[temp[2]] = func;
            }
        });
        if (result.name.length === 0) delete result.name;
        else result.name = new Function('x','return /' + result.name.join(' ') + '/i.test(x);');
        return result;
    };

    var populateList = function() {
        var result, parameters = generateSearchParameters();
        if (parameters === null) return;
        result = units.filter(function(x) { return x !== null && x !== undefined; });
        Object.keys(parameters).forEach(function(key) {
            var unitKey = key.replace(/^(hp|atk|rcv)$/,function(x) { return 'max' + x.toUpperCase(); });
            result = result.filter(function(x) { return parameters[key](x[unitKey]); });
        });
        $scope.units = result;
    };

    /* * * * * Recent list generation * * * * */

    var updateRecent = function(unitNumber) {
        var recentUnits = JSON.parse(JSON.stringify($scope.recents));
        var n = recentUnits.indexOf(unitNumber);
        if (n < 0) recentUnits.unshift(unitNumber);
        else recentUnits = recentUnits.splice(n,1).concat(recentUnits);
        recentUnits = recentUnits.slice(0,14);
        localStorage.setItem('recentUnits',JSON.stringify(recentUnits));
    };

};

/*************
 * SlotsCtrl *
 *************/

controllers.SlotsCtrl = function($scope, $state, $stateParams) {

    /* * * * * Functions * * * * */

    var populateSlots = function(query) {
        var regex = new RegExp(($scope.query || ''),'i'), result = { };
        for (var key in slots) {
            if (regex.test(slots[key].name))
                result[key] = slots[key];
        }
        $scope.slots = result;
    };

    /* * * * * Local variables * * * * */

    var lastSlotName = JSON.parse(localStorage.getItem('lastSlotName')) || '';
    var slots = JSON.parse(localStorage.getItem('slots')) || { };

    /* * * * * Scope variables * * * * */

    $scope.query = '';
    $scope.slots = slots;
    $scope.lastSlot = lastSlotName;
    $scope.overwriting = false;

    $scope.$watch('query',populateSlots);

    $scope.$watch('lastSlot',function(value) {
        if (value)
            $scope.overwriting = slots.hasOwnProperty(value.toLowerCase());
    });

    /* * * * * Scope functions * * * * */

    $scope.teamClick = function(e,slot) {
        if (e.which == 1 && !e.ctrlKey) {
            slot.team.map(function(x,n) {
                $scope.resetSlot(n);
                if (x !== null) $scope.data.team[n] = { unit: units[slot.team[n].unit], level: slot.team[n].level };
            });
            localStorage.setItem('lastSlotName',JSON.stringify(slot.name));
            $state.go('^');
        } else if (e.which == 2 || (e.which == 1 && e.ctrlKey)) {
            delete slots[slot.name];
            delete $scope.slots[slot.name];
            localStorage.setItem('slots',JSON.stringify(slots));
        }
    };

    $scope.saveTeam = function() {
        $scope.$broadcast('$validate');
        var team = $scope.data.team.map(function(x) {
            return !x.unit ? null : { unit : x.unit.number, level: x.level };
        });
        slots[$scope.lastSlot.toLowerCase()] = { name: $scope.lastSlot, team: team };
        localStorage.setItem('slots',JSON.stringify(slots));
        localStorage.setItem('lastSlotName',JSON.stringify($scope.lastSlot));
        $state.go('^');
    };

};

/************
 * ShipCtrl *
 ************/

controllers.ShipCtrl = function($scope, $state) {

    $scope.query = '';
    $scope.list = ships;

    $scope.$watch('query',function() {
        var regex = new RegExp(($scope.query || ''),'i'), result = { };
        for (var key in ships) {
            if (regex.test(key))
                result[key] = ships[key];
        }
        $scope.list = result;
    });

    $scope.getThumbnail = function(ship) {
        if (!ship.thumb) return '';
        return 'background-image: url(http://onepiece-treasurecruise.com/wp-content/uploads/' + ship.thumb + ')';
    };

    $scope.pickShip = function(name) {
        $scope.data.ship.name = name;
        $state.go('^');
    };

};

/*************
 * ResetCtrl *
 *************/

controllers.ResetCtrl = function($scope, $state) {
    $scope.resetStorage = function() {
        localStorage.removeItem('team');
        for (var i=0;i<6;++i) $scope.resetSlot(i);
        $state.go('^');
    };
};

/*****************************
 * Controller initialization *
 *****************************/

for (var key in controllers)
    angular.module('optc')
        .controller(key, controllers[key]);

})();
<|endoftext|>


<commit_before>import { EventDispatcher } from '../core/EventDispatcher.js';
import { Texture } from '../textures/Texture.js';
import { LinearFilter } from '../constants.js';
import { Vector4 } from '../math/Vector4.js';

/*
 In options, we can specify:
 * Texture parameters for an auto-generated target texture
 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
*/
class WebGLRenderTarget extends EventDispatcher {

	constructor( width, height, options = {} ) {

		super();

		this.width = width;
		this.height = height;
		this.depth = 1;

		this.scissor = new Vector4( 0, 0, width, height );
		this.scissorTest = false;

		this.viewport = new Vector4( 0, 0, width, height );

		const image = { width: width, height: height, depth: 1 };

		this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
		this.texture.isRenderTargetTexture = true;

		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
		this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null;
		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;

		this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
		this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
		this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;

	}

	setTexture( texture ) {

		texture.image = {
			width: this.width,
			height: this.height,
			depth: this.depth
		};

		this.texture = texture;

	}

	setSize( width, height, depth = 1 ) {

		if ( this.width !== width || this.height !== height || this.depth !== depth ) {

			this.width = width;
			this.height = height;
			this.depth = depth;

			this.texture.image.width = width;
			this.texture.image.height = height;
			this.texture.image.depth = depth;

			this.dispose();

		}

		this.viewport.set( 0, 0, width, height );
		this.scissor.set( 0, 0, width, height );

	}

	clone() {

		return new this.constructor().copy( this );

	}

	copy( source ) {

		this.width = source.width;
		this.height = source.height;
		this.depth = source.depth;

		this.viewport.copy( source.viewport );

		this.texture = source.texture.clone();

		// ensure image object is not shared, see #20328

		this.texture.image = Object.assign( {}, source.texture.image );

		this.depthBuffer = source.depthBuffer;
		this.stencilBuffer = source.stencilBuffer;
		this.depthTexture = source.depthTexture;

		return this;

	}

	dispose() {

		this.dispatchEvent( { type: 'dispose' } );

	}

}

WebGLRenderTarget.prototype.isWebGLRenderTarget = true;

export { WebGLRenderTarget };
<commit_msg>WebGLRenderTarget: Clone depthTexture in copy(). (#23462)<commit_after>import { EventDispatcher } from '../core/EventDispatcher.js';
import { Texture } from '../textures/Texture.js';
import { LinearFilter } from '../constants.js';
import { Vector4 } from '../math/Vector4.js';

/*
 In options, we can specify:
 * Texture parameters for an auto-generated target texture
 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
*/
class WebGLRenderTarget extends EventDispatcher {

	constructor( width, height, options = {} ) {

		super();

		this.width = width;
		this.height = height;
		this.depth = 1;

		this.scissor = new Vector4( 0, 0, width, height );
		this.scissorTest = false;

		this.viewport = new Vector4( 0, 0, width, height );

		const image = { width: width, height: height, depth: 1 };

		this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
		this.texture.isRenderTargetTexture = true;

		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
		this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null;
		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;

		this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
		this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;

		this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;

	}

	setTexture( texture ) {

		texture.image = {
			width: this.width,
			height: this.height,
			depth: this.depth
		};

		this.texture = texture;

	}

	setSize( width, height, depth = 1 ) {

		if ( this.width !== width || this.height !== height || this.depth !== depth ) {

			this.width = width;
			this.height = height;
			this.depth = depth;

			this.texture.image.width = width;
			this.texture.image.height = height;
			this.texture.image.depth = depth;

			this.dispose();

		}

		this.viewport.set( 0, 0, width, height );
		this.scissor.set( 0, 0, width, height );

	}

	clone() {

		return new this.constructor().copy( this );

	}

	copy( source ) {

		this.width = source.width;
		this.height = source.height;
		this.depth = source.depth;

		this.viewport.copy( source.viewport );

		this.texture = source.texture.clone();

		// ensure image object is not shared, see #20328

		this.texture.image = Object.assign( {}, source.texture.image );

		this.depthBuffer = source.depthBuffer;
		this.stencilBuffer = source.stencilBuffer;

		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();

		return this;

	}

	dispose() {

		this.dispatchEvent( { type: 'dispose' } );

	}

}

WebGLRenderTarget.prototype.isWebGLRenderTarget = true;

export { WebGLRenderTarget };
<|endoftext|>


<commit_before>import projections 	from './projections.js';
import {points} 	from './primitiveTypes/points.js';
import {lines} 		from './primitiveTypes/lines.js';

export default function() {

	var ortho           = projections.ortho,
        persp           = projections.persp,
        projection      = ortho,
        origin          = [0, 0],
        scale           = 1,
        distance        = 1,
        alpha           = 0,
        beta            = 0,
        gamma           = 0,
        primitiveType   = 'POINTS',
        primitiveTypes  = {
        POINTS 			: points,
        LINES 			: lines,
        // LINES_LOOP : linesLoop,
        // LINES_STRIP: linesStrip,
        // TRIANGLES : triangles,
        // TRIANGLES_STRIP : trianglesStrip,
        // TRIANGLES_FAN : trianglesFan
		};

    function _3d(data){
        return primitiveTypes[primitiveType](data, projection, alpha, beta, gamma, origin, scale, distance);
    }

    _3d.projection = function(_){
        return arguments.length ? (projection = _, _3d) : projection;
    };

	_3d.origin = function(_){
        return arguments.length ? (origin = _, _3d) : origin;
	};

	_3d.scale = function(_){
        return arguments.length ? (scale = _, _3d) : scale;
	};

	_3d.distance = function(_){
        return arguments.length ? (distance = _, _3d) : distance;
	};

	_3d.rotateZ = function(_){
        return arguments.length ? (alpha = _, _3d) : alpha;
	};

	_3d.rotateY = function(_){
        return arguments.length ? (beta = _, _3d) : beta;
	};

	_3d.rotateX = function(_){
        return arguments.length ? (gamma = _, _3d) : gamma;
	};

	_3d.primitiveType = function(_){
        return arguments.length ? (primitiveType = _, _3d) : primitiveType;
	};

    return _3d;
}
<commit_msg>add tabs as spaces<commit_after>import projections 	from './projections.js';
import {points} 	from './primitiveTypes/points.js';
import {lines} 		from './primitiveTypes/lines.js';

export default function() {

    var ortho           = projections.ortho,
        persp           = projections.persp,
        projection      = ortho,
        origin          = [0, 0],
        scale           = 1,
        distance        = 1,
        alpha           = 0,
        beta            = 0,
        gamma           = 0,
        primitiveType   = 'POINTS',
        primitiveTypes  = {
        POINTS 			: points,
        LINES 			: lines,
        // LINES_LOOP : linesLoop,
        // LINES_STRIP: linesStrip,
        // TRIANGLES : triangles,
        // TRIANGLES_STRIP : trianglesStrip,
        // TRIANGLES_FAN : trianglesFan
		};

    function _3d(data){
        return primitiveTypes[primitiveType](data, projection, alpha, beta, gamma, origin, scale, distance);
    }

    _3d.projection = function(_){
        return arguments.length ? (projection = _, _3d) : projection;
    };

    _3d.origin = function(_){
        return arguments.length ? (origin = _, _3d) : origin;
    };

    _3d.scale = function(_){
        return arguments.length ? (scale = _, _3d) : scale;
    };

    _3d.distance = function(_){
        return arguments.length ? (distance = _, _3d) : distance;
    };

    _3d.rotateZ = function(_){
        return arguments.length ? (alpha = _, _3d) : alpha;
    };

    _3d.rotateY = function(_){
        return arguments.length ? (beta = _, _3d) : beta;
    };

    _3d.rotateX = function(_){
        return arguments.length ? (gamma = _, _3d) : gamma;
    };

    _3d.primitiveType = function(_){
        return arguments.length ? (primitiveType = _, _3d) : primitiveType;
    };

    return _3d;
}
<|endoftext|>


<commit_before>/* eslint-env node */
module.exports = {
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "PhantomJS"
  ],
  "launch_in_dev": [
    "PhantomJS",
    "Chrome"
  ]
};
<commit_msg>remove phantom<commit_after>/* eslint-env node */
module.exports = {
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome"
  ],
  "launch_in_dev": [
    "Chrome"
  ]
};
<|endoftext|>


<commit_before>console.log("starting");
var tape = require("tape");
var chalk = require("chalk");

let errorColor = chalk.red.bold;
let okColor = chalk.green.bold;
var level = 0;

function logger(module, level, message) {
    //if (level < 99) {
    //console.log(module, level, message);
    //}
}
function tablevel() {
    let retval = "";
    for (let i = 0; i < level; i++) {
        retval += "\t";
    }
    return retval;
}
tape.createStream({ objectMode: true }).on('data', (row) => {
    //console.log(JSON.stringify(row));
    if (row.type == "end") {
        console.log();
        level--;
    }
    else if (row.type == "test") {
        level++;
        console.log();
        console.log(tablevel() + "%d. Testing %s", row.id, row.name);
    }
    else {
        if (row.ok) {
            console.log(tablevel() + okColor("%d. \t %s \t %s"), row.id, row.ok, row.name);
            if (row.operator == "throws" && row.actual != undefined) {
                console.log(tablevel() + okColor(" threw: %s"), row.actual);
            }
        }
        else {
            console.log(tablevel() + errorColor("%d. \t %s \t %s"), row.id, row.ok, row.name);
            console.log(tablevel() + errorColor("\t expected: %s actual: %s"),row.expected, row.actual);
        }
    }
    //console.log(JSON.stringify(row))
});
function showObject(tobj) {
    let objstr = JSON.stringify(tobj, null, '\t');
    let showObjectContents = false;
    if (showObjectContents) {
        console.log(objstr);
    }
    else {
        console.log("object size: " + objstr.length);
    }
}

var addon = null;
var aoRelease = null;
var aoDebug = null;

if (addon == null) {
    try {
        addon = require('./build/Release/tester');
    } catch (e) {
        aoRelease = e;
    }
}

if (addon == null) {
    try {
        addon = require('./build/Debug/tester');
    } catch (e) {
        aoDebug = e;
    }
}

//console.log("addon", addon);

if (addon == null) {
    console.log(aoRelease, aoDebug);
}

tape('test function without overload resolution', function (t) {
    t.equal(addon.testfunction_no_overload_resolution(),"testfunction_no_overload_resolution", "function without overload returned true");
    t.end();
});

tape('base_function on base_class', function (t) {
    var bc = new addon.base_class();
    t.ok(bc, "base class created successfully");
    t.ok(bc.base_function(), "function called on base_class");
    t.end();
});

tape('function on derived class', function (t) {
    var dc = new addon.derived_class();
    t.ok(dc, "derived class created successfully");
    t.ok(dc.derived_function(), "function called on derived_class");
    t.end();
});

tape('base_class.base_function  test function on derived class', function (t) {
    var dc = new addon.derived_class();
    t.ok(dc, "derived class created successfully");
    t.ok(dc.base_function(), "base_class.base_function function called on derived_class");
    t.end();
});

var dataTypes = [
    {
        value: 1,
        name: "number"
    }
    , {
        value: 2 ^ 33,
        name: "number"
    }
    , {
        value: true,
        name: "bool"
    }
    , {
        value: false,
        name: "bool"
    }
    , {
        value: "1",
        name: "string"
    }
    , {
        value: "str",
        name: "string"
    }
    , {
        value: new Date(),
        name: "date"
    }
    , {
        value: function () { },
        name: "function"
    }
    , {
        value: new Map(),
        name: "map"
    }
    , {
        value: new Set(),
        name: "set"
    }
    , {
        value: new Buffer(0),
        name: "buffer"
    }
    , {
        value: Promise.resolve(0),
        name: "promise"
    }
    , {
        value: new Proxy({}, {}),
        name: "proxy"
    }
    , {
        value: new RegExp("[a-z]"),
        name: "regexp"
    }
    , {
        value: new addon.base_class(),
        name: "base_class"
    }
    , {
        value: new addon.derived_class(),
        name: "derived_class"
    }
    , {
        value: { "prop1": "val1", "prop2": "val2" },
        name: "struct_A"
    }
    , {
        value: { "prop1": "val1", "prop2": 2 },
        name: "struct_B"
    }
    , {
        value: [],
        name: "array"
    }
     , {
         value: {},
         name: "object"
     }
     , {
         value: null,
         name: "null"
     }
     , {
         value: undefined,
         name: "undefined"
     }
];

tape('function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        t.equal(addon.number_testers(), ".no_parameters", "number_testers no_params");

        for (var dt of dataTypes) {
            t.equal(addon.number_testers(dt.value), "." + dt.name, "number_testers " + dt.name);
        }

        //t.equal(addon.number_testers(1), ".number_testers", "number_testers number");
        //t.equal(addon.number_testers(1), ".number_testers", "number_testers number");
        //t.equal(addon.number_testers(1.1), ".number_testers", "number_testers float");
        //t.equal(addon.number_testers(2 ^ 33), ".number_testers", "number_testers long");
        //
        //t.equal(addon.number_testers("1"), ".string_testers", "number_testers string");
        //
        //t.equal(addon.number_testers(true), ".bool_testers", "number_testers boolean");
        //
        //t.equal(addon.number_testers(new Date()), ".date_testers", "number_testers date");
        //
        //t.equal(addon.number_testers(function () { }), ".function_testers", "number_testers function");
        //
        //t.equal(addon.number_testers(new Buffer(0)), ".buffer_testers", "number_testers buffer");
        //
        //t.equal(addon.number_testers(new Map()), ".map_testers", "number_testers map");
        //
        //t.equal(addon.number_testers(new Set()), ".set_testers", "number_testers set");
        //
        //t.equal(addon.number_testers(Promise.resolve(0)), ".promise_testers", "number_testers promise");
        //
        //t.equal(addon.number_testers(new Proxy({}, {})), ".proxy_testers", "number_testers promise");
        //
        //t.equal(addon.number_testers(new RegExp("[a-z]")), ".regexp_testers", "number_testers regexp");
        //
        //t.equal(addon.number_testers(new addon.base_class()), ".base_class_testers", "number_testers base_class");
        //
        //t.equal(addon.number_testers(new addon.derived_class()), ".derived_class_testers", "number_testers derived_class");
        //
        //t.equal(addon.number_testers({ "prop1": "val1", "prop2": "val2" }), ".struct_A_testers", "number_testers propstruct");
        //

    });
    t.end();
});

//TODO: test member/static functions

tape('member function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        let bc = new addon.base_class();

        t.equal(bc.base_function(), "base_class.base_function.no_parameters_testers", "no_params");

        for (var dt of dataTypes) {
            t.equal(bc.base_function(dt.value), "base_class.base_function." + dt.name, "number_testers " + dt.name);
        }

        //t.equal(bc.base_function(1), "base_class.base_function.number", "number");
        //t.equal(bc.base_function(1), "base_class.base_function.number", "number");
        //t.equal(bc.base_function(1.1), "base_class.base_function.number", "number double");
        //t.equal(bc.base_function(2 ^ 33), "base_class.base_function.number", "number long");
        //t.equal(bc.base_function("1"), "base_class.base_function.string", "string");
        //t.equal(bc.base_function(true), "base_class.base_function.bool", "boolean");
        //t.equal(bc.base_function(new Date()), "base_class.base_function.date", "date");
        //t.equal(bc.base_function(function () { }), "base_class.base_function.function", "function");
        //t.equal(bc.base_function(new Buffer(0)), "base_class.base_function.buffer", "buffer");
        //t.equal(bc.base_function(new Map()), "base_class.base_function.map", "map");
        //t.equal(bc.base_function(new Set()), "base_class.base_function.set", "set");
        //t.equal(bc.base_function(Promise.resolve(0)), "base_class.base_function.promise", "promise");
        //t.equal(bc.base_function(new Proxy({}, {})), "base_class.base_function.proxy", "promise");
        //t.equal(bc.base_function(new RegExp("[a-z]")), "base_class.base_function.regexp", "regexp");
        //t.equal(bc.base_function(new addon.base_class()), "base_class.base_function.base_class", "base_class");
        //t.equal(bc.base_function(new addon.derived_class()), "base_class.base_function.derived_class", "derived_class");
        //t.equal(bc.base_function({ "prop1": "val1", "prop2": "val2" }), "base_class.base_function.struct_A", "propstruct");
        //t.equal(bc.base_function(), "base_class.base_function.no_parameters_testers", "no_params");
    });
    t.end();
});

//TODO: test class inheritance chain calls
//e.g. derived class overload implements function x and base class overload implement function x, which will be called when and on which parameters?
//overload should be across class graph, otherwise no true inheritance will be implemented.
//also, what happens when calling function inherited from base but not overloaded in derived?

tape('derived member function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        let bc = new addon.derived_class();

        t.equal(bc.base_function(), "derived_class.base_function.no_parameters_testers", "no_params");

        for (var dt of dataTypes) {
            t.equal(bc.base_function(dt.value), "derived_class.base_function." + dt.name, "number_testers " + dt.name);
        }

        //t.equal(bc.base_function(1), "derived_class.base_function.number", "number");
        //t.equal(bc.base_function(1), "derived_class.base_function.number", "number");
        //t.equal(bc.base_function(1.1), "derived_class.base_function.number", "number double");
        //t.equal(bc.base_function(2 ^ 33), "derived_class.base_function.number", "number long");
        //t.equal(bc.base_function("1"), "derived_class.base_function.string", "string");
        //t.equal(bc.base_function(true), "derived_class.base_function.bool", "boolean");
        //t.equal(bc.base_function(new Date()), "derived_class.base_function.date", "date");
        //t.equal(bc.base_function(function () { }), "derived_class.base_function.function", "function");
        //t.equal(bc.base_function(new Buffer(0)), "derived_class.base_function.buffer", "buffer");
        //t.equal(bc.base_function(new Map()), "derived_class.base_function.map", "map");
        //t.equal(bc.base_function(new Set()), "derived_class.base_function.set", "set");
        //t.equal(bc.base_function(Promise.resolve(0)), "derived_class.base_function.promise", "promise");
        //t.equal(bc.base_function(new Proxy({}, {})), "derived_class.base_function.proxy", "promise");
        //t.equal(bc.base_function(new RegExp("[a-z]")), "derived_class.base_function.regexp", "regexp");
        //t.equal(bc.base_function(new addon.base_class()), "derived_class.base_function.base_class", "base_class");
        //t.equal(bc.base_function(new addon.derived_class()), "derived_class.base_function.derived_class", "derived_class");
        //t.equal(bc.base_function({ "prop1": "val1", "prop2": "val2" }), "derived_class.base_function.struct_A", "propstruct");

    });
    t.end();
});

//TODO: test structs, succes, fail, multiple
tape('function overload - structs', function (t) {
    t.doesNotThrow(function () {
        t.equal(addon.structs_testers(), "structs_testers.no_parameters", " no parameters")
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }), "structs_testers.struct_A", "struct_A");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }), "structs_testers.struct_B", " struct_B");

        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }, { "prop1": "1", "prop2": "2" }), "structs_testers.struct_A_struct_A", "struct_A struct_A");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }, { "prop1": "1", "prop2": 2 }), "structs_testers.struct_B_struct_B", " struct_B struct_B");

        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }, { "prop1": "1", "prop2": 2 }), "structs_testers.struct_A_struct_B", "struct_A struct_B");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }, { "prop1": "1", "prop2": "2" }), "structs_testers.struct_B_struct_A", " struct_B struct_A");

    });
    t.end();
});

//TODO: test multiple parameters
tape('function overload 2 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {

        for (var dt1 of dataTypes) {
            for (var dt2 of dataTypes) {
                t.equal(addon.number_testers(dt1.value,dt2.value), "." + dt1.name + "." + dt2.name, "number_testers " + dt1.name + " " + dt2.name);
            }
        }

    });
    t.end();
});

//TODO: test parameter defaults
<commit_msg>add test summary, cleanup and fix two parameters overloads.<commit_after>console.log("starting");
var tape = require("tape");
var chalk = require("chalk");

let errorColor = chalk.red.bold;
let okColor = chalk.green.bold;
var level = 0;

function logger(module, level, message) {
    //if (level < 99) {
    //console.log(module, level, message);
    //}
}
function tablevel() {
    let retval = "";
    for (let i = 0; i < level; i++) {
        retval += "\t";
    }
    return retval;
}

var results = {
    passed: 0,
    failed : 0
};

tape.createStream({ objectMode: true }).on('data', (row) => {
    //console.log(JSON.stringify(row));
    if (row.type == "end") {
        console.log();
        level--;
    }
    else if (row.type == "test") {
        level++;
        console.log();
        console.log(tablevel() + "%d. Testing %s", row.id, row.name);
    }
    else {
        if (row.ok) {
            results.passed++;
            console.log(tablevel() + okColor("%d. \t %s \t %s"), row.id, row.ok, row.name);
            if (row.operator == "throws" && row.actual != undefined) {
                console.log(tablevel() + okColor(" threw: %s"), row.actual);
            }
        }
        else {
            results.failed++;
            console.log(tablevel() + errorColor("%d. \t %s \t %s"), row.id, row.ok, row.name);
            console.log(tablevel() + errorColor("\t expected: %s actual: %s"),row.expected, row.actual);
        }
    }
    //console.log(JSON.stringify(row))
});

tape.createStream({ objectMode: true }).on('end', (r) => {
    console.log("passed:", results.passed);
    console.log("failed:", results.failed);
});

function showObject(tobj) {
    let objstr = JSON.stringify(tobj, null, '\t');
    let showObjectContents = false;
    if (showObjectContents) {
        console.log(objstr);
    }
    else {
        console.log("object size: " + objstr.length);
    }
}

var addon = null;
var aoRelease = null;
var aoDebug = null;

if (addon == null) {
    try {
        addon = require('./build/Release/tester');
    } catch (e) {
        aoRelease = e;
    }
}

if (addon == null) {
    try {
        addon = require('./build/Debug/tester');
    } catch (e) {
        aoDebug = e;
    }
}

if (addon == null) {
    console.log(aoRelease, aoDebug);
}

tape('test function without overload resolution', function (t) {
    t.equal(addon.testfunction_no_overload_resolution(),"testfunction_no_overload_resolution", "function without overload returned true");
    t.end();
});

tape('base_function on base_class', function (t) {
    var bc = new addon.base_class();
    t.ok(bc, "base class created successfully");
    t.ok(bc.base_function(), "function called on base_class");
    t.end();
});

tape('function on derived class', function (t) {
    var dc = new addon.derived_class();
    t.ok(dc, "derived class created successfully");
    t.ok(dc.derived_function(), "function called on derived_class");
    t.end();
});

tape('base_class.base_function  test function on derived class', function (t) {
    var dc = new addon.derived_class();
    t.ok(dc, "derived class created successfully");
    t.ok(dc.base_function(), "base_class.base_function function called on derived_class");
    t.end();
});

var dataTypes = [
    {
        value: 1,
        name: "number"
    }
    , {
        value: 2 ^ 33,
        name: "number"
    }
    , {
        value: true,
        name: "bool"
    }
    , {
        value: false,
        name: "bool"
    }
    , {
        value: "1",
        name: "string"
    }
    , {
        value: "str",
        name: "string"
    }
    , {
        value: new Date(),
        name: "date"
    }
    , {
        value: function () { },
        name: "function"
    }
    , {
        value: new Map(),
        name: "map"
    }
    , {
        value: new Set(),
        name: "set"
    }
    , {
        value: new Buffer(0),
        name: "buffer"
    }
    , {
        value: Promise.resolve(0),
        name: "promise"
    }
    , {
        value: new Proxy({}, {}),
        name: "proxy"
    }
    , {
        value: new RegExp("[a-z]"),
        name: "regexp"
    }
    , {
        value: new addon.base_class(),
        name: "base_class"
    }
    , {
        value: new addon.derived_class(),
        name: "derived_class"
    }
    , {
        value: { "prop1": "val1", "prop2": "val2" },
        name: "struct_A"
    }
    , {
        value: { "prop1": "val1", "prop2": 2 },
        name: "struct_B"
    }
    , {
        value: [],
        name: "array"
    }
     , {
         value: {},
         name: "object"
     }
     , {
         value: null,
         name: "null"
     }
     , {
         value: undefined,
         name: "undefined"
     }
];

tape('function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        t.equal(addon.number_testers(), ".no_parameters", "number_testers no_params");

        for (var dt of dataTypes) {
            t.equal(addon.number_testers(dt.value), "." + dt.name, "number_testers " + dt.name);
        }

    });
    t.end();
});

//TODO: test member/static functions

tape('member function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        let bc = new addon.base_class();

        t.equal(bc.base_function(), "base_class.base_function.no_parameters_testers", "no_params");

        for (var dt of dataTypes) {
            t.equal(bc.base_function(dt.value), "base_class.base_function." + dt.name, "number_testers " + dt.name);
        }

    });
    t.end();
});

//TODO: test class inheritance chain calls
//e.g. derived class overload implements function x and base class overload implement function x, which will be called when and on which parameters?
//overload should be across class graph, otherwise no true inheritance will be implemented.
//also, what happens when calling function inherited from base but not overloaded in derived?

tape('derived member function overload 1 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {
        let bc = new addon.derived_class();

        t.equal(bc.base_function(), "derived_class.base_function.no_parameters_testers", "no_params");

        for (var dt of dataTypes) {
            t.equal(bc.base_function(dt.value), "derived_class.base_function." + dt.name, "number_testers " + dt.name);
        }

    });
    t.end();
});

//TODO: test structs, succes, fail, multiple
tape('function overload - structs', function (t) {
    t.doesNotThrow(function () {
        t.equal(addon.structs_testers(), "structs_testers.no_parameters", "no parameters")
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }), "structs_testers.struct_A", "struct_A");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }), "structs_testers.struct_B", "struct_B");

        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }, { "prop1": "1", "prop2": "2" }), "structs_testers.struct_A_struct_A", "struct_A struct_A");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }, { "prop1": "1", "prop2": 2 }), "structs_testers.struct_B_struct_B", "struct_B struct_B");

        t.equal(addon.structs_testers({ "prop1": "1", "prop2": "2" }, { "prop1": "1", "prop2": 2 }), "structs_testers.struct_A_struct_B", "struct_A struct_B");
        t.equal(addon.structs_testers({ "prop1": "1", "prop2": 2 }, { "prop1": "1", "prop2": "2" }), "structs_testers.struct_B_struct_A", "struct_B struct_A");

    });
    t.end();
});

//TODO: test multiple parameters
tape('function overload 2 parameter, no defaults', function (t) {
    t.doesNotThrow(function () {

        for (var dt1 of dataTypes) {
            for (var dt2 of dataTypes) {
                t.equal(addon.two_testers(dt1.value, dt2.value), "." + dt1.name + "." + dt2.name, "number_testers " + dt1.name + " " + dt2.name);
            }
        }

    });
    t.end();
});

//TODO: test parameter defaults
<|endoftext|>


<commit_before>var Phaser = Phaser || {};
var Tetris = Tetris || {};
var _ = _ || {};
var Tetrad = Tetris.Tetrad;

Tetris.COLUMNS = 10;
Tetris.ROWS = 18;
Tetris.TILE_SIZE = 32; // pixels square

function createGameInstance() {
    return new Phaser.Game(Tetris.COLUMNS * Tetris.TILE_SIZE + 4 * Tetris.TILE_SIZE + 5 + 5 + 5,
        Tetris.ROWS * Tetris.TILE_SIZE, Phaser.AUTO, '', {
            preload: preload,
            create: create,
            update: update
        }, true, false);
}

var game = createGameInstance();

function preload() {
    game.load.image('block1', 'blocks/block1.png');
    game.load.image('block2', 'blocks/block2.png');
    game.load.image('block3', 'blocks/block3.png');
    game.load.image('block4', 'blocks/block4.png');
    game.load.image('block5', 'blocks/block5.png');
    game.load.image('block6', 'blocks/block6.png');
    var leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
    leftKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone();
            copy.x -= 1;
            if (!checkCollision(copy))
                Tetris.activeTetrad.x -= 1;
        });
    });
    var rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
    rightKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone();
            copy.x += 1;
            if (!checkCollision(copy))
                Tetris.activeTetrad.x += 1;
        });
    });
    var upKey = game.input.keyboard.addKey(Phaser.Keyboard.UP);
    upKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone().rotateRight();
            if (!checkCollision(copy))
                Tetris.activeTetrad.rotateRight();
            else {
                copy.x--;
                if (!checkCollision(copy)) {
                    Tetris.activeTetrad.x--;
                    Tetris.activeTetrad.rotateRight();
                }
            }
        });
    });
    var downKey = game.input.keyboard.addKey(Phaser.Keyboard.DOWN);
    downKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            Tetris.score++;
            Tetris.counter = Tetris.tickLength + 1;
        });
    });
    Tetris.flashMask = game.add.bitmapData(game.width, game.height);
    Tetris.flashMask.fill(0xFF, 0xFF, 0xFF, 0.8);
    Tetris.gameOverMask = game.add.bitmapData(game.width, game.height);
    Tetris.gameOverMask.fill(0xFF, 0xBB, 0xBB, 0.7);
    Tetris.gameboyMask = game.add.bitmapData(game.width, game.height);
    Tetris.gameboyMask.fill(0x70, 0xCC, 0x70, 0.3);
    Tetris.GUTTER_WIDTH = 5;
    Tetris.gutterTexture = game.add.bitmapData(Tetris.GUTTER_WIDTH, game.height);
    Tetris.gutterTexture.fill(0, 0, 0, 1);
    game.add.image(0, 0, Tetris.gutterTexture);
    game.add.image(Tetris.TILE_SIZE * Tetris.COLUMNS + Tetris.GUTTER_WIDTH, 0, Tetris.gutterTexture);

}

function create() {
    Tetris.field = [];
    for (var i = 0; i < Tetris.ROWS; i++) {
        var row = [];
        for (var j = 0; j < Tetris.COLUMNS; j++)
            row.push(0);
        Tetris.field.push(row);
    }
    Tetris.tickLength = 800; // milliseconds
    Tetris.activeTetrad = new Tetrad().createRandom();
    Tetris.nextTetrad = new Tetrad().createRandom();
    Tetris.counter = 0; // milliseconds
    Tetris.flashCounter = 0;
    Tetris.flashImage = null;
    Tetris.gameOverCounter = 0;
    Tetris.renderBlocks = [];
    Tetris.actionQueue = [];
    Tetris.gameState = 0; // 0 = normal, 1 = flashing, 2 = game over
    Tetris.gameboyImage = game.add.image(0, 0, Tetris.gameboyImage);
    Tetris.linesCompleted = 0;
    Tetris.score = 0;
    Tetris.textStyle = {
        'font': '20px monospace',
        'fill': '#000000',
        'align': 'center'
    };
    Tetris.nextText = game.add.text(0, 0, '', Tetris.textStyle);
    Tetris.scoreText = game.add.text(0, 0, '', Tetris.textStyle);
    Tetris.linesText = game.add.text(0, 0, '', Tetris.textStyle);
}

function update() {
    switch (Tetris.gameState) {
        case 0:
            Tetris.counter += game.time.elapsed;
            if (Tetris.counter > Tetris.tickLength)
                Tetris.actionQueue.push(function() {
                    processTick();
                });
            Tetris.actionQueue.forEach(function(action) {
                action();
            });
            Tetris.actionQueue = [];
            break;
        case 1:
            Tetris.flashCounter += game.time.elapsed;
            switch (Math.floor(Tetris.flashCounter / 100)) {
                case 0:
                    Tetris.flashImage.tint = 0xFFFFFF;
                    break;
                case 1:
                    Tetris.flashImage.tint = 0x80FF80;
                    break;
                case 2:
                    Tetris.flashImage.tint = 0xFFFFFF;
                    break;
                default:
                    break;
            }
            if (Tetris.flashCounter > 300) {
                Tetris.gameState = 0;
                Tetris.flashImage.destroy();
                Tetris.flashImage = null;
            }
            break;
        case 2:
            Tetris.gameOverCounter += game.time.elapsed;
            if (Tetris.gameOverCounter > 2000) {
                game.destroy();
                game = null;
                game = createGameInstance();
            }
            break;
    }
    render();
}

function render() {
    Tetris.nextText.destroy();
    Tetris.nextText = null;
    Tetris.linesText.destroy();
    Tetris.linesText = null;
    Tetris.scoreText.destroy();
    Tetris.scoreText = null;
    Tetris.gameboyImage.destroy();
    Tetris.gameboyImage = null;
    Tetris.renderBlocks.forEach(function(element) {
        element.destroy();
    });
    Tetris.renderBlocks = [];
    for (var row = 0; row < 4; row++)
        for (var col = 0; col < 4; col++)
            if (Tetris.activeTetrad.matrix[row][col])
                Tetris.renderBlocks.push(game.add.image((col + Tetris.activeTetrad.x) * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH, (row + Tetris.activeTetrad.y) * Tetris.TILE_SIZE, Tetris.activeTetrad.block));
    for (var fieldRow = 0; fieldRow < Tetris.ROWS; fieldRow++)
        for (var fieldCol = 0; fieldCol < Tetris.COLUMNS; fieldCol++)
            if (Tetris.field[fieldRow][fieldCol])
                Tetris.renderBlocks.push(game.add.image(fieldCol * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH, fieldRow * Tetris.TILE_SIZE, Tetris.field[fieldRow][fieldCol]));
    var offset = Tetris.COLUMNS * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH * 2 + 5;
    for (var nextRow = 0; nextRow < 4; nextRow++)
        for (var nextCol = 0; nextCol < 4; nextCol++)
            if (Tetris.nextTetrad.matrix[nextRow][nextCol])
                Tetris.renderBlocks.push(game.add.image(offset + Tetris.TILE_SIZE * (nextCol + 1) - 5, Tetris.TILE_SIZE * nextRow + 50, Tetris.nextTetrad.block));
    Tetris.renderBlocks.forEach(function(e) {
        e.scale.x = 4;
        e.scale.y = 4;
    });
    var textCenter = (game.width - offset) / 2 + offset;
    Tetris.nextText = game.add.text(textCenter, 20, "Next:", Tetris.textStyle);
    Tetris.nextText.anchor.set(0.5);
    Tetris.linesText = game.add.text(textCenter, 300, "Lines\ncomplete:\n" + Tetris.linesCompleted, Tetris.textStyle);
    Tetris.linesText.anchor.set(0.5);
    Tetris.scoreText = game.add.text(textCenter, 450, "Score:\n" + Tetris.score, Tetris.textStyle);
    Tetris.scoreText.anchor.set(0.5);
    Tetris.gameboyImage = game.add.image(0, 0, Tetris.gameboyMask);
}

function processTick() {
    Tetris.counter = 0;
    var copy = Tetris.activeTetrad.clone();
    copy.y += 1;
    if (!checkCollision(copy))
        Tetris.activeTetrad.y += 1;
    else {
        for (var row = 0; row < 4; row++)
            for (var col = 0; col < 4; col++)
                if (Tetris.activeTetrad.x + col < 10 && Tetris.activeTetrad.matrix[row][col])
                    Tetris.field[row + Tetris.activeTetrad.y][col + Tetris.activeTetrad.x] = Tetris.activeTetrad.block;
        Tetris.activeTetrad = Tetris.nextTetrad;
        Tetris.nextTetrad = new Tetrad().createRandom();
        if (checkCollision(Tetris.activeTetrad)) {
            game.add.image(0, 0, Tetris.gameOverMask);
            Tetris.gameState = 2;
        }
    }
    var emptyRow = [];
    _(Tetris.COLUMNS).times(function() {
        emptyRow.push(0);
    });
    var linesCompletedThisDrop = 0;
    for (var row = 0; row < Tetris.ROWS; row++) {
        var allFilled = true;
        for (var f = 0; f < Tetris.COLUMNS; f++)
            if (!Tetris.field[row][f]) allFilled = false;
        if (allFilled) {
            linesCompletedThisDrop++;
            Tetris.linesCompleted++;
            Tetris.tickLength--;
            for (var i = row; i > 0; i--)
                Tetris.field[i] = _.cloneDeep(Tetris.field[i - 1]);
            Tetris.field[0] = emptyRow;
            Tetris.gameState = 1;
            Tetris.flashCounter = 0;
            if (Tetris.flashImage === null) Tetris.flashImage = game.add.image(0, 0, Tetris.flashMask);
        }
    }
    Tetris.score += linesCompletedThisDrop * linesCompletedThisDrop * 10;
}

function checkCollision(testTetrad) {
    if (testTetrad.x < 0 || testTetrad.x >= Tetris.COLUMNS) return true;
    if (testTetrad.y + 3 >= Tetris.ROWS) return true;
    for (var row = 0; row < 4; row++)
        for (var col = 0; col < 4; col++)
            if (testTetrad.matrix[row][col] &&
                (
                    Tetris.field[row + testTetrad.y][col + testTetrad.x] ||
                    testTetrad.x + col >= Tetris.COLUMNS
                )
            )
                return true;
    return false;
}<commit_msg>Remove flash effect on line completion.<commit_after>var Phaser = Phaser || {};
var Tetris = Tetris || {};
var _ = _ || {};
var Tetrad = Tetris.Tetrad;

Tetris.COLUMNS = 10;
Tetris.ROWS = 18;
Tetris.TILE_SIZE = 32; // pixels square

function createGameInstance() {
    return new Phaser.Game(Tetris.COLUMNS * Tetris.TILE_SIZE + 4 * Tetris.TILE_SIZE + 5 + 5 + 5,
        Tetris.ROWS * Tetris.TILE_SIZE, Phaser.AUTO, '', {
            preload: preload,
            create: create,
            update: update
        }, true, false);
}

var game = createGameInstance();

function preload() {
    game.load.image('block1', 'blocks/block1.png');
    game.load.image('block2', 'blocks/block2.png');
    game.load.image('block3', 'blocks/block3.png');
    game.load.image('block4', 'blocks/block4.png');
    game.load.image('block5', 'blocks/block5.png');
    game.load.image('block6', 'blocks/block6.png');
    var leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
    leftKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone();
            copy.x -= 1;
            if (!checkCollision(copy))
                Tetris.activeTetrad.x -= 1;
        });
    });
    var rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
    rightKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone();
            copy.x += 1;
            if (!checkCollision(copy))
                Tetris.activeTetrad.x += 1;
        });
    });
    var upKey = game.input.keyboard.addKey(Phaser.Keyboard.UP);
    upKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            var copy = Tetris.activeTetrad.clone().rotateRight();
            if (!checkCollision(copy))
                Tetris.activeTetrad.rotateRight();
            else {
                copy.x--;
                if (!checkCollision(copy)) {
                    Tetris.activeTetrad.x--;
                    Tetris.activeTetrad.rotateRight();
                }
            }
        });
    });
    var downKey = game.input.keyboard.addKey(Phaser.Keyboard.DOWN);
    downKey.onDown.add(function() {
        Tetris.actionQueue.push(function() {
            Tetris.score++;
            Tetris.counter = Tetris.tickLength + 1;
        });
    });
    Tetris.gameOverMask = game.add.bitmapData(game.width, game.height);
    Tetris.gameOverMask.fill(0xFF, 0xBB, 0xBB, 0.7);
    Tetris.gameboyMask = game.add.bitmapData(game.width, game.height);
    Tetris.gameboyMask.fill(0x70, 0xCC, 0x70, 0.3);
    Tetris.GUTTER_WIDTH = 5;
    Tetris.gutterTexture = game.add.bitmapData(Tetris.GUTTER_WIDTH, game.height);
    Tetris.gutterTexture.fill(0, 0, 0, 1);
    game.add.image(0, 0, Tetris.gutterTexture);
    game.add.image(Tetris.TILE_SIZE * Tetris.COLUMNS + Tetris.GUTTER_WIDTH, 0, Tetris.gutterTexture);

}

function create() {
    Tetris.field = [];
    for (var i = 0; i < Tetris.ROWS; i++) {
        var row = [];
        for (var j = 0; j < Tetris.COLUMNS; j++)
            row.push(0);
        Tetris.field.push(row);
    }
    Tetris.tickLength = 800; // milliseconds
    Tetris.activeTetrad = new Tetrad().createRandom();
    Tetris.nextTetrad = new Tetrad().createRandom();
    Tetris.counter = 0; // milliseconds
    Tetris.gameOverCounter = 0;
    Tetris.renderBlocks = [];
    Tetris.actionQueue = [];
    Tetris.gameState = 0; // 0 = normal, 1 = flashing, 2 = game over
    Tetris.gameboyImage = game.add.image(0, 0, Tetris.gameboyImage);
    Tetris.linesCompleted = 0;
    Tetris.score = 0;
    Tetris.textStyle = {
        'font': '20px monospace',
        'fill': '#000000',
        'align': 'center'
    };
    Tetris.nextText = game.add.text(0, 0, '', Tetris.textStyle);
    Tetris.scoreText = game.add.text(0, 0, '', Tetris.textStyle);
    Tetris.linesText = game.add.text(0, 0, '', Tetris.textStyle);
}

function update() {
    switch (Tetris.gameState) {
        case 0:
            Tetris.counter += game.time.elapsed;
            if (Tetris.counter > Tetris.tickLength)
                Tetris.actionQueue.push(function() {
                    processTick();
                });
            Tetris.actionQueue.forEach(function(action) {
                action();
            });
            Tetris.actionQueue = [];
            break;
        case 2:
            Tetris.gameOverCounter += game.time.elapsed;
            if (Tetris.gameOverCounter > 2000) {
                game.destroy();
                game = null;
                game = createGameInstance();
            }
            break;
    }
    render();
}

function render() {
    Tetris.nextText.destroy();
    Tetris.nextText = null;
    Tetris.linesText.destroy();
    Tetris.linesText = null;
    Tetris.scoreText.destroy();
    Tetris.scoreText = null;
    Tetris.gameboyImage.destroy();
    Tetris.gameboyImage = null;
    Tetris.renderBlocks.forEach(function(element) {
        element.destroy();
    });
    Tetris.renderBlocks = [];
    for (var row = 0; row < 4; row++)
        for (var col = 0; col < 4; col++)
            if (Tetris.activeTetrad.matrix[row][col])
                Tetris.renderBlocks.push(game.add.image((col + Tetris.activeTetrad.x) * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH, (row + Tetris.activeTetrad.y) * Tetris.TILE_SIZE, Tetris.activeTetrad.block));
    for (var fieldRow = 0; fieldRow < Tetris.ROWS; fieldRow++)
        for (var fieldCol = 0; fieldCol < Tetris.COLUMNS; fieldCol++)
            if (Tetris.field[fieldRow][fieldCol])
                Tetris.renderBlocks.push(game.add.image(fieldCol * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH, fieldRow * Tetris.TILE_SIZE, Tetris.field[fieldRow][fieldCol]));
    var offset = Tetris.COLUMNS * Tetris.TILE_SIZE + Tetris.GUTTER_WIDTH * 2 + 5;
    for (var nextRow = 0; nextRow < 4; nextRow++)
        for (var nextCol = 0; nextCol < 4; nextCol++)
            if (Tetris.nextTetrad.matrix[nextRow][nextCol])
                Tetris.renderBlocks.push(game.add.image(offset + Tetris.TILE_SIZE * (nextCol + 1) - 5, Tetris.TILE_SIZE * nextRow + 50, Tetris.nextTetrad.block));
    Tetris.renderBlocks.forEach(function(e) {
        e.scale.x = 4;
        e.scale.y = 4;
    });
    var textCenter = (game.width - offset) / 2 + offset;
    Tetris.nextText = game.add.text(textCenter, 20, "Next:", Tetris.textStyle);
    Tetris.nextText.anchor.set(0.5);
    Tetris.linesText = game.add.text(textCenter, 300, "Lines\ncomplete:\n" + Tetris.linesCompleted, Tetris.textStyle);
    Tetris.linesText.anchor.set(0.5);
    Tetris.scoreText = game.add.text(textCenter, 450, "Score:\n" + Tetris.score, Tetris.textStyle);
    Tetris.scoreText.anchor.set(0.5);
    Tetris.gameboyImage = game.add.image(0, 0, Tetris.gameboyMask);
}

function processTick() {
    Tetris.counter = 0;
    var copy = Tetris.activeTetrad.clone();
    copy.y += 1;
    if (!checkCollision(copy))
        Tetris.activeTetrad.y += 1;
    else {
        for (var row = 0; row < 4; row++)
            for (var col = 0; col < 4; col++)
                if (Tetris.activeTetrad.x + col < 10 && Tetris.activeTetrad.matrix[row][col])
                    Tetris.field[row + Tetris.activeTetrad.y][col + Tetris.activeTetrad.x] = Tetris.activeTetrad.block;
        Tetris.activeTetrad = Tetris.nextTetrad;
        Tetris.nextTetrad = new Tetrad().createRandom();
        if (checkCollision(Tetris.activeTetrad)) {
            game.add.image(0, 0, Tetris.gameOverMask);
            Tetris.gameState = 2;
        }
    }
    var emptyRow = [];
    _(Tetris.COLUMNS).times(function() {
        emptyRow.push(0);
    });
    var linesCompletedThisDrop = 0;
    for (var row = 0; row < Tetris.ROWS; row++) {
        var allFilled = true;
        for (var f = 0; f < Tetris.COLUMNS; f++)
            if (!Tetris.field[row][f]) allFilled = false;
        if (allFilled) {
            linesCompletedThisDrop++;
            Tetris.linesCompleted++;
            Tetris.tickLength--;
            for (var i = row; i > 0; i--)
                Tetris.field[i] = _.cloneDeep(Tetris.field[i - 1]);
            Tetris.field[0] = emptyRow;
        }
    }
    Tetris.score += linesCompletedThisDrop * linesCompletedThisDrop * 10;
}

function checkCollision(testTetrad) {
    if (testTetrad.x < 0 || testTetrad.x >= Tetris.COLUMNS) return true;
    if (testTetrad.y + 3 >= Tetris.ROWS) return true;
    for (var row = 0; row < 4; row++)
        for (var col = 0; col < 4; col++)
            if (testTetrad.matrix[row][col] &&
                (
                    Tetris.field[row + testTetrad.y][col + testTetrad.x] ||
                    testTetrad.x + col >= Tetris.COLUMNS
                )
            )
                return true;
    return false;
}<|endoftext|>


<commit_before>var canvas;
var ctx;
var block_size = 30;
var blocks_x = 10;
var blocks_y = 20;
var world = {"width": blocks_x * block_size, "height": blocks_y * block_size};
var tetrii = {"I": [[0, 0], [0, 1], [0, 2], [0, 3]],
              "T": [[0, 0], [-1, 0], [1, 0], [0, -1]],
              "Z": [[0, 0], [-1, -1], [0, -1], [1, 0]],
              "S": [[0, 0], [-1, 0], [0, -1], [1, -1]],
              "J": [[0, 0], [-1, -1], [-1, 0], [1, 0]],
              "L": [[0, 0], [-1, 0], [1, 0], [1, -1]],
              "O": [[0, 0], [0, 1], [1, 0], [1, 1]]};
var tcolors = {"I": 1, "T": 2, "Z": 3, "S": 4, "J": 5, "L": 6, "O": 7};
var colors = {1: "#12c6bb", 2: "#63009b", 3: "#aa0f11", 4: "green", 5: "#0d37e5",
              6: "#e9850e", 7: "#d5cf12"};
var corners = [[-1, -1], [1, -1], [1, 1], [-1, 1]];
var sides = [[0, -1], [1, 0], [0, 1], [-1, 0]];

var freq = 1.;
var tetris;
var matrix;
var points = 0;
var bag_counter = 0;
var current_bag = ["I", "T", "Z", "S", "J", "L", "O"];
var next_bag = ["I", "T", "Z", "S", "J", "L", "O"];
current_bag = shuffle(current_bag);
next_bag = shuffle(next_bag);
var next_tetris;
var total_cleared = 0;
var fps = 60.;
var fps_counter = 0;
var dropping = false;

window.onload = function() {
    init();
    canvas = document.getElementById("canvas");
    canvas.width = world.width*2;
    canvas.height = world.height;
    ctx = canvas.getContext("2d");

    setInterval(update, 1000./fps);
    //setInterval(heartbeat, 1000./freq);

    document.addEventListener("keydown", keyDown);

}

function update(){

  draw_canvas();

  draw_matrix();

  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    if (tetris.y + pos[1] + 1 > blocks_y){
      tetris.y -= 1;
    }
  }

  draw_tetris();
  draw_next_tetris();
  //draw_grid();
  draw_points();
  if (fps_counter>=fps){
    heartbeat();
    fps_counter = 0;
  }
  //alert(fps_counter);
  fps_counter += freq;
}

function init(){
  new_tetris();
  matrix = zeros([blocks_y, blocks_x]);
  myAudio = new Audio('sounds/Tetristitle.m4a');
  myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
  }, false);
  myAudio.volume = 0.5;
  myAudio.play();
}

function draw_canvas(){
  ctx.lineWidth = '5';
  ctx.fillStyle = 'black';
  ctx.strokeStyle = 'white';
  ctx.fillRect(0, 0, canvas.width/2, canvas.height);
  ctx.fillStyle = 'white';
  ctx.fillRect(canvas.width/2, 0, canvas.width, canvas.height);
}
function draw_tetris(){
  var c = tetris_color();
  ctx.fillStyle = c;
  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    draw_block(tetris.x + pos[0], tetris.y + pos[1]);
  }
}

function draw_next_tetris(){
  var c = colors[tcolors[next_tetris.id]];
  ctx.fillStyle = c;
  var positions = next_tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    draw_block(14 + pos[0], 15 + pos[1]);
  }
}

function draw_points(){
  var p = points.toString();
  ctx.font = "20px Arial";
  ctx.fillStyle = 'black';
  ctx.fillText("Points:",world.width + 100,50);
  ctx.fillText(p,world.width + 100,100);
  ctx.fillText("Cleared lines:",world.width + 100,200);
  ctx.fillText(total_cleared,world.width + 100,250);
  ctx.fillText("Level:",world.width + 100,300);
  ctx.fillText(freq,world.width + 100,350);
}

function draw_grid(){
  ctx.strokeStyle = '#4c4a4a';
  ctx.lineWidth=2;
  ctx.moveTo(0,0);
  ctx.lineTo(world.width,0);
  ctx.moveTo(1,0);
  ctx.lineTo(1,world.height);
  ctx.moveTo(0,world.height-1);
  ctx.lineTo(world.width,world.height-1);
  ctx.moveTo(world.width-1,0);
  ctx.lineTo(world.width-1,world.height);
  /*for (var i=0; i<blocks_x; i++){
    ctx.moveTo(i * block_size,0);
    ctx.lineTo(i * block_size,world.height);
  }
  for (var i=0; i<blocks_y; i++){
    ctx.moveTo(0, i * block_size);
    ctx.lineTo(world.width, i * block_size);
  }*/
  ctx.stroke();
}

function draw_block(x, y){
  ctx.fillRect(x * block_size, y * block_size, block_size, block_size);
}

function heartbeat(){
  if(dropping) {
      return;
  }
  var future_pos_y = tetris.y + 1;
  if (collision_detected(tetris.x, future_pos_y)){
    tetris_dies();
  } else {
    tetris.y = future_pos_y;
  }

}

function full_line_detection(){
  var completed_lines = [];
  for (var i=0; i<blocks_y; i++){
    var complete = true;
    for (var j=0; j<blocks_x; j++){
      if (matrix[i][j] == 0){
        complete = false;
        break;
      }
    }
    if (complete){
      completed_lines.push(i);
    }
  }

  var new_matrix = [];
  for (var i=0;i<completed_lines.length; i++){
    new_matrix.push(zeros([blocks_x]));
  }
  for (var i=0; i<blocks_y; i++){
    if (completed_lines.indexOf(i) == -1){
      new_matrix.push(matrix[i]);
    }
  }
  matrix = new_matrix;
  add_points(completed_lines.length);
  total_cleared += completed_lines.length;
  freq = Math.floor(total_cleared/10) + 1;
  if (completed_lines.length == 4){
    var snd = new Audio("sounds/TetrisforJeff2.m4a");
    snd.volume=.6;
    snd.play();
  }
  if (completed_lines.length == 3){
    var snd = new Audio("sounds/Tetris2.m4a");
    snd.volume=1.;
    snd.play();
  }
  if (completed_lines.length == 1){
    var snd = new Audio("sounds/TetrisG.m4a");
    snd.volume=.6;
    snd.play();
  }
  if (completed_lines.length == 2){
    var snd = new Audio("sounds/TetrisG.m4a");
    snd.volume=.6;
    snd.play();
    snd.play();
  }
  //alert(freq);
}

function add_points(n_lines){
  points += n_lines * n_lines * 100 * freq;
}

function tetris_dies(){
  add_to_matrix();
  full_line_detection();
  new_tetris();
  var snd = new Audio("sounds/Tetris1.m4a");
  snd.volume=.5;
  snd.play();
}

function new_tetris(){
  if (bag_counter == 5){
    next_bag = shuffle(next_bag);
  }
  if (bag_counter == 7){
    //alert("switch to next bag");
    for (var i=0; i<7;i++){
      current_bag[i] = next_bag[i];
    }

    bag_counter = 0;
  }
  if (bag_counter < 6){
    nb = current_bag[bag_counter+1];
    var npos = tetrii[nb];
    next_tetris = {"id": nb, "x": 5, "y": -1, "pos": npos, "o": 0};
  } else {
    nb = next_bag[0];
    var npos = tetrii[nb];
    next_tetris = {"id": nb, "x": 5, "y": -1, "pos": npos, "o": 0};
  }

  b = current_bag[bag_counter];
  bag_counter += 1;
  var pos = tetrii[b];
  tetris = {"id": b, "x": 5, "y": -1, "pos": pos, "o": 0};
  console.log("New tetris", tetris);
}

function collision_detected(x, y, rot){
  //var positions = tetris.pos;
  var positions_new;
  var positions_rot;
  if (rot){
    positions_new = rotated(tetris.pos);

  } else{
    positions_new = tetris.pos;
  }
  for (var i=0; i<4; i++){
    var pos_new = positions_new[i];
    if (y + pos_new[1] >= blocks_y){
      return true;
    }
    if (x + pos_new[0] >= blocks_x || x + pos_new[0] < 0){
      return true;
    }
  }
  if (matrix_collision(x, y, positions_new)){
    return true;
  }
  return false;
}

function rotated(pos){
  //return pos;
  var tet;
  var new_pos;
  if (tetris.id=="O"){
    return pos;
  }
  if (tetris.id=="I"){
    if (pos[0][0] == 0 && pos[0][1] == 0){
      new_pos = [[-1, 1], [0, 1], [1, 1], [2, 1]];
    }
    else if (pos[0][0] == -1 && pos[0][1] == 1){
      new_pos = [[1, 0], [1, 1], [1, 2], [1, 3]];
    }
    else if (pos[0][0] == 1 && pos[0][1] ==  0){
      new_pos = [[-1, 2], [0, 2], [1, 2], [2, 2]];
    }
    else if (pos[0][0] == -1 && pos[0][1] == 2){
      new_pos = [[0, 0], [0, 1], [0, 2], [0, 3]];
    }
    return new_pos;
  }
  var pos_new = zeros([4, 2]);
  for (var i=1; i<4; i++){
    for (var j=0; j<4; j++){
      if (pos[i][0] == sides[j][0] && pos[i][1] == sides[j][1]){
        pos_new[i] = sides[(j+1)%4];
      }
      if (pos[i][0] == corners[j][0] && pos[i][1] == corners[j][1]){
        pos_new[i] = corners[(j+1)%4];
      }
    }
  }
  return pos_new;

}

function rotate(){
  //alert(tetris.pos);
  var new_pos = rotated(tetris.pos);
  tetris.pos = new_pos;
  //alert(tetris.pos);
}

function keyDown(evt){
  var future_pos_x = tetris.x;
  var future_pos_y = tetris.y;
  var rot = false;
  switch (evt.keyCode) {
    case 37:
      future_pos_x = tetris.x - 1;
      break;
    case 39:
      future_pos_x = tetris.x + 1;
      break;
    case 40:
      future_pos_y = tetris.y + 1;
      break;
    case 38:

      rot = true;
      //alert(tetris.o);
      break;
    case 32:
      console.log("dropping");
      dropping = true;
      drop_tetris();
      tetris_dies();
      dropping = false;
      console.log("dropping ended");
      return;

  }
  if (collision_detected(future_pos_x, future_pos_y, rot)){
    if (evt.keyCode == 40){
      tetris_dies();
    }
  } else {
    tetris.y = future_pos_y;
    tetris.x = future_pos_x;
    if (rot==true){
      rotate();
    }

  }
}

function drop_tetris() {
    var future_pos_x = tetris.x;
    var future_pos_y = tetris.y;
    while(!collision_detected(future_pos_x, future_pos_y, 0)){
        future_pos_y += 1;
        console.log(future_pos_y);
    }
    tetris.y = future_pos_y - 1;
    console.log("after collision checking in drop");
    console.log(tetris.y);
}

function zeros(dimensions) {
    var array = [];

    for (var i = 0; i < dimensions[0]; ++i) {
        array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
    }

    return array;
}

function add_to_matrix(){
  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    matrix[tetris.y + pos[1]][tetris.x + pos[0]] = tcolors[tetris.id];
  }
}

function tetris_color(){
  return colors[tcolors[tetris.id]];
}

function draw_matrix(){
  for (var i=0; i<blocks_y; i++){
    for (var j=0; j<blocks_x; j++){
      if (matrix[i][j] > 0){
        ctx.fillStyle = colors[matrix[i][j]];
        draw_block(j, i);
      }
    }
  }
}

function matrix_collision(x, y, pos_new){
  var positions = pos_new;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    var ix = x + pos[0];
    var iy = y + pos[1];
    if (iy < blocks_y && ix < blocks_x && ix >= 0 && iy >= 0){
      if (matrix[iy][ix] > 0){
        return true;
      }
    }
  }
  return false;
}

function shuffle(a) {
  var j, x, i;
  for (i = a.length; i; i--) {
    j = Math.floor(Math.random() * i);
    x = a[i - 1];
    a[i - 1] = a[j];
    a[j] = x;
  }
  return a;
}
<commit_msg>added speed increase and changed to 2<commit_after>var canvas;
var ctx;
var block_size = 30;
var blocks_x = 10;
var blocks_y = 20;
var world = {"width": blocks_x * block_size, "height": blocks_y * block_size};
var tetrii = {"I": [[0, 0], [0, 1], [0, 2], [0, 3]],
              "T": [[0, 0], [-1, 0], [1, 0], [0, -1]],
              "Z": [[0, 0], [-1, -1], [0, -1], [1, 0]],
              "S": [[0, 0], [-1, 0], [0, -1], [1, -1]],
              "J": [[0, 0], [-1, -1], [-1, 0], [1, 0]],
              "L": [[0, 0], [-1, 0], [1, 0], [1, -1]],
              "O": [[0, 0], [0, 1], [1, 0], [1, 1]]};
var tcolors = {"I": 1, "T": 2, "Z": 3, "S": 4, "J": 5, "L": 6, "O": 7};
var colors = {1: "#12c6bb", 2: "#63009b", 3: "#aa0f11", 4: "green", 5: "#0d37e5",
              6: "#e9850e", 7: "#d5cf12"};
var corners = [[-1, -1], [1, -1], [1, 1], [-1, 1]];
var sides = [[0, -1], [1, 0], [0, 1], [-1, 0]];

var freq = 1.;
var increase = 2.;
var tetris;
var matrix;
var points = 0;
var bag_counter = 0;
var current_bag = ["I", "T", "Z", "S", "J", "L", "O"];
var next_bag = ["I", "T", "Z", "S", "J", "L", "O"];
current_bag = shuffle(current_bag);
next_bag = shuffle(next_bag);
var next_tetris;
var total_cleared = 0;
var fps = 60.;
var fps_counter = 0;
var dropping = false;

window.onload = function() {
    init();
    canvas = document.getElementById("canvas");
    canvas.width = world.width*2;
    canvas.height = world.height;
    ctx = canvas.getContext("2d");

    setInterval(update, 1000./fps);
    //setInterval(heartbeat, 1000./freq);

    document.addEventListener("keydown", keyDown);

}

function update(){

  draw_canvas();

  draw_matrix();

  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    if (tetris.y + pos[1] + 1 > blocks_y){
      tetris.y -= 1;
    }
  }

  draw_tetris();
  draw_next_tetris();
  //draw_grid();
  draw_points();
  if (fps_counter>=fps){
    heartbeat();
    fps_counter = 0;
  }
  //alert(fps_counter);
  fps_counter += freq;
}

function init(){
  new_tetris();
  matrix = zeros([blocks_y, blocks_x]);
  myAudio = new Audio('sounds/Tetristitle.m4a');
  myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
  }, false);
  myAudio.volume = 0.5;
  myAudio.play();
}

function draw_canvas(){
  ctx.lineWidth = '5';
  ctx.fillStyle = 'black';
  ctx.strokeStyle = 'white';
  ctx.fillRect(0, 0, canvas.width/2, canvas.height);
  ctx.fillStyle = 'white';
  ctx.fillRect(canvas.width/2, 0, canvas.width, canvas.height);
}
function draw_tetris(){
  var c = tetris_color();
  ctx.fillStyle = c;
  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    draw_block(tetris.x + pos[0], tetris.y + pos[1]);
  }
}

function draw_next_tetris(){
  var c = colors[tcolors[next_tetris.id]];
  ctx.fillStyle = c;
  var positions = next_tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    draw_block(14 + pos[0], 15 + pos[1]);
  }
}

function draw_points(){
  var p = points.toString();
  ctx.font = "20px Arial";
  ctx.fillStyle = 'black';
  ctx.fillText("Points:",world.width + 100,50);
  ctx.fillText(p,world.width + 100,100);
  ctx.fillText("Cleared lines:",world.width + 100,200);
  ctx.fillText(total_cleared,world.width + 100,250);
  ctx.fillText("Level:",world.width + 100,300);
  ctx.fillText(freq,world.width + 100,350);
}

function draw_grid(){
  ctx.strokeStyle = '#4c4a4a';
  ctx.lineWidth=2;
  ctx.moveTo(0,0);
  ctx.lineTo(world.width,0);
  ctx.moveTo(1,0);
  ctx.lineTo(1,world.height);
  ctx.moveTo(0,world.height-1);
  ctx.lineTo(world.width,world.height-1);
  ctx.moveTo(world.width-1,0);
  ctx.lineTo(world.width-1,world.height);
  /*for (var i=0; i<blocks_x; i++){
    ctx.moveTo(i * block_size,0);
    ctx.lineTo(i * block_size,world.height);
  }
  for (var i=0; i<blocks_y; i++){
    ctx.moveTo(0, i * block_size);
    ctx.lineTo(world.width, i * block_size);
  }*/
  ctx.stroke();
}

function draw_block(x, y){
  ctx.fillRect(x * block_size, y * block_size, block_size, block_size);
}

function heartbeat(){
  if(dropping) {
      return;
  }
  var future_pos_y = tetris.y + 1;
  if (collision_detected(tetris.x, future_pos_y)){
    tetris_dies();
  } else {
    tetris.y = future_pos_y;
  }

}

function full_line_detection(){
  var completed_lines = [];
  for (var i=0; i<blocks_y; i++){
    var complete = true;
    for (var j=0; j<blocks_x; j++){
      if (matrix[i][j] == 0){
        complete = false;
        break;
      }
    }
    if (complete){
      completed_lines.push(i);
    }
  }

  var new_matrix = [];
  for (var i=0;i<completed_lines.length; i++){
    new_matrix.push(zeros([blocks_x]));
  }
  for (var i=0; i<blocks_y; i++){
    if (completed_lines.indexOf(i) == -1){
      new_matrix.push(matrix[i]);
    }
  }
  matrix = new_matrix;
  add_points(completed_lines.length);
  total_cleared += completed_lines.length;
  freq = Math.floor(total_cleared/10) + increase;
  if (completed_lines.length == 4){
    var snd = new Audio("sounds/TetrisforJeff2.m4a");
    snd.volume=.6;
    snd.play();
  }
  if (completed_lines.length == 3){
    var snd = new Audio("sounds/Tetris2.m4a");
    snd.volume=1.;
    snd.play();
  }
  if (completed_lines.length == 1){
    var snd = new Audio("sounds/TetrisG.m4a");
    snd.volume=.6;
    snd.play();
  }
  if (completed_lines.length == 2){
    var snd = new Audio("sounds/TetrisG.m4a");
    snd.volume=.6;
    snd.play();
    snd.play();
  }
  //alert(freq);
}

function add_points(n_lines){
  points += n_lines * n_lines * 100 * freq;
}

function tetris_dies(){
  add_to_matrix();
  full_line_detection();
  new_tetris();
  var snd = new Audio("sounds/Tetris1.m4a");
  snd.volume=.5;
  snd.play();
}

function new_tetris(){
  if (bag_counter == 5){
    next_bag = shuffle(next_bag);
  }
  if (bag_counter == 7){
    //alert("switch to next bag");
    for (var i=0; i<7;i++){
      current_bag[i] = next_bag[i];
    }

    bag_counter = 0;
  }
  if (bag_counter < 6){
    nb = current_bag[bag_counter+1];
    var npos = tetrii[nb];
    next_tetris = {"id": nb, "x": 5, "y": -1, "pos": npos, "o": 0};
  } else {
    nb = next_bag[0];
    var npos = tetrii[nb];
    next_tetris = {"id": nb, "x": 5, "y": -1, "pos": npos, "o": 0};
  }

  b = current_bag[bag_counter];
  bag_counter += 1;
  var pos = tetrii[b];
  tetris = {"id": b, "x": 5, "y": -1, "pos": pos, "o": 0};
  console.log("New tetris", tetris);
}

function collision_detected(x, y, rot){
  //var positions = tetris.pos;
  var positions_new;
  var positions_rot;
  if (rot){
    positions_new = rotated(tetris.pos);

  } else{
    positions_new = tetris.pos;
  }
  for (var i=0; i<4; i++){
    var pos_new = positions_new[i];
    if (y + pos_new[1] >= blocks_y){
      return true;
    }
    if (x + pos_new[0] >= blocks_x || x + pos_new[0] < 0){
      return true;
    }
  }
  if (matrix_collision(x, y, positions_new)){
    return true;
  }
  return false;
}

function rotated(pos){
  //return pos;
  var tet;
  var new_pos;
  if (tetris.id=="O"){
    return pos;
  }
  if (tetris.id=="I"){
    if (pos[0][0] == 0 && pos[0][1] == 0){
      new_pos = [[-1, 1], [0, 1], [1, 1], [2, 1]];
    }
    else if (pos[0][0] == -1 && pos[0][1] == 1){
      new_pos = [[1, 0], [1, 1], [1, 2], [1, 3]];
    }
    else if (pos[0][0] == 1 && pos[0][1] ==  0){
      new_pos = [[-1, 2], [0, 2], [1, 2], [2, 2]];
    }
    else if (pos[0][0] == -1 && pos[0][1] == 2){
      new_pos = [[0, 0], [0, 1], [0, 2], [0, 3]];
    }
    return new_pos;
  }
  var pos_new = zeros([4, 2]);
  for (var i=1; i<4; i++){
    for (var j=0; j<4; j++){
      if (pos[i][0] == sides[j][0] && pos[i][1] == sides[j][1]){
        pos_new[i] = sides[(j+1)%4];
      }
      if (pos[i][0] == corners[j][0] && pos[i][1] == corners[j][1]){
        pos_new[i] = corners[(j+1)%4];
      }
    }
  }
  return pos_new;

}

function rotate(){
  //alert(tetris.pos);
  var new_pos = rotated(tetris.pos);
  tetris.pos = new_pos;
  //alert(tetris.pos);
}

function keyDown(evt){
  var future_pos_x = tetris.x;
  var future_pos_y = tetris.y;
  var rot = false;
  switch (evt.keyCode) {
    case 37:
      future_pos_x = tetris.x - 1;
      break;
    case 39:
      future_pos_x = tetris.x + 1;
      break;
    case 40:
      future_pos_y = tetris.y + 1;
      break;
    case 38:

      rot = true;
      //alert(tetris.o);
      break;
    case 32:
      console.log("dropping");
      dropping = true;
      drop_tetris();
      tetris_dies();
      dropping = false;
      console.log("dropping ended");
      return;

  }
  if (collision_detected(future_pos_x, future_pos_y, rot)){
    if (evt.keyCode == 40){
      tetris_dies();
    }
  } else {
    tetris.y = future_pos_y;
    tetris.x = future_pos_x;
    if (rot==true){
      rotate();
    }

  }
}

function drop_tetris() {
    var future_pos_x = tetris.x;
    var future_pos_y = tetris.y;
    while(!collision_detected(future_pos_x, future_pos_y, 0)){
        future_pos_y += 1;
        console.log(future_pos_y);
    }
    tetris.y = future_pos_y - 1;
    console.log("after collision checking in drop");
    console.log(tetris.y);
}

function zeros(dimensions) {
    var array = [];

    for (var i = 0; i < dimensions[0]; ++i) {
        array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
    }

    return array;
}

function add_to_matrix(){
  var positions = tetris.pos;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    matrix[tetris.y + pos[1]][tetris.x + pos[0]] = tcolors[tetris.id];
  }
}

function tetris_color(){
  return colors[tcolors[tetris.id]];
}

function draw_matrix(){
  for (var i=0; i<blocks_y; i++){
    for (var j=0; j<blocks_x; j++){
      if (matrix[i][j] > 0){
        ctx.fillStyle = colors[matrix[i][j]];
        draw_block(j, i);
      }
    }
  }
}

function matrix_collision(x, y, pos_new){
  var positions = pos_new;
  for (var i=0; i<4; i++){
    var pos = positions[i];
    var ix = x + pos[0];
    var iy = y + pos[1];
    if (iy < blocks_y && ix < blocks_x && ix >= 0 && iy >= 0){
      if (matrix[iy][ix] > 0){
        return true;
      }
    }
  }
  return false;
}

function shuffle(a) {
  var j, x, i;
  for (i = a.length; i; i--) {
    j = Math.floor(Math.random() * i);
    x = a[i - 1];
    a[i - 1] = a[j];
    a[j] = x;
  }
  return a;
}
<|endoftext|>


<commit_before>/**
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
**/

var number = __inherit(object, "int");

var __py2js_number = number;

number.PY$_isnumeric_ = true;

number.PY$__repr__ = number.PY$__str__;

number.PY$__eq__ = function (other) {
    if (typeof(other) === "number") {
        return bool(this._obj === other);
    }
    if (other.PY$__class__ !== this.PY$__class__)
        return False;
    return bool(this._obj === other._obj);
};

number.toString = function () {
    return js(this.PY$__str__());
};

number._js_ = function () {
    return this._obj;
};

number.PY$__bool__ = function() {
    return py_builtins.bool(this._obj);
};

number.PY$__pos__ = function() {
    return this.PY$__class__(+this._obj);
};

number.PY$__neg__ = function() {
    return this.PY$__class__(-this._obj);
};

number.PY$__nonzero__ = function() {
    return py_builtins.bool(this._obj != 0);
};

number.PY$__gt__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj > x._obj);
};

number.PY$__lt__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj < x._obj);
};

number.PY$__ge__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj >= x._obj);
};

number.PY$__le__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj <= x._obj);
};

number.PY$__mul__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot multiply number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj * x._obj);
    else
        return x.PY$__class__(this._obj * x._obj);
};

number.PY$__add__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot add number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj + x._obj);
    else
        return x.PY$__class__(this._obj + x._obj);
};

number.PY$__div__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot divide number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj / x._obj);
    else
        return x.PY$__class__(this._obj / x._obj);
};

number.PY$__sub__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot subtract number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj - x._obj);
    else
        return x.PY$__class__(this._obj - x._obj);
};

number.PY$__pow__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot exponentiate number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(Math.pow(this._obj, x._obj));
    else
        return x.PY$__class__(Math.pow(this._obj, x._obj));
};

number.PY$__imul__      = number.PY$__mul__;
number.PY$__iadd__      = number.PY$__add__;
number.PY$__idiv__      = number.PY$__div__;
number.PY$__isub__      = number.PY$__sub__;
number.PY$__ipow__      = number.PY$__pow__;
<commit_msg> + Added $PY.number<commit_after>/**
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
**/

var number = __inherit(object, "int");

$PY.number = number;

number.PY$_isnumeric_ = true;

number.PY$__repr__ = number.PY$__str__;

number.PY$__eq__ = function (other) {
    if (typeof(other) === "number") {
        return bool(this._obj === other);
    }
    if (other.PY$__class__ !== this.PY$__class__)
        return False;
    return bool(this._obj === other._obj);
};

number.toString = function () {
    return js(this.PY$__str__());
};

number._js_ = function () {
    return this._obj;
};

number.PY$__bool__ = function() {
    return py_builtins.bool(this._obj);
};

number.PY$__pos__ = function() {
    return this.PY$__class__(+this._obj);
};

number.PY$__neg__ = function() {
    return this.PY$__class__(-this._obj);
};

number.PY$__nonzero__ = function() {
    return py_builtins.bool(this._obj != 0);
};

number.PY$__gt__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj > x._obj);
};

number.PY$__lt__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj < x._obj);
};

number.PY$__ge__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj >= x._obj);
};

number.PY$__le__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot compare number and non-number");
    return py_builtins.bool(this._obj <= x._obj);
};

number.PY$__mul__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot multiply number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj * x._obj);
    else
        return x.PY$__class__(this._obj * x._obj);
};

number.PY$__add__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot add number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj + x._obj);
    else
        return x.PY$__class__(this._obj + x._obj);
};

number.PY$__div__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot divide number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj / x._obj);
    else
        return x.PY$__class__(this._obj / x._obj);
};

number.PY$__sub__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot subtract number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(this._obj - x._obj);
    else
        return x.PY$__class__(this._obj - x._obj);
};

number.PY$__pow__ = function(x) {
    if (!x.PY$_isnumeric_)
        throw py_builtins.TypeError("Cannot exponentiate number and non-number");
    if (this.PY$_isnumeric_float || (! x.PY$_isnumeric_float))
        return this.PY$__class__(Math.pow(this._obj, x._obj));
    else
        return x.PY$__class__(Math.pow(this._obj, x._obj));
};

number.PY$__imul__      = number.PY$__mul__;
number.PY$__iadd__      = number.PY$__add__;
number.PY$__idiv__      = number.PY$__div__;
number.PY$__isub__      = number.PY$__sub__;
number.PY$__ipow__      = number.PY$__pow__;
<|endoftext|>


<commit_before>/***
   Copyright 2013 Teun Duynstee

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
firstBy = (function() {
    function makeCompareFunction(f, direction){
      if(typeof(f)!="function"){
        var prop = f;
        // make unary function
        f = function(v1){return v1[prop];}
      }
      if(f.length === 1) {
        // f is a unary function mapping a single item to its sort score
        var uf = f;
        f = function(v1,v2) {return uf(v1) < uf(v2) ? -1 : uf(v1) > uf(v2) ? 1 : 0;}
      }
      if(direction === -1)return function(v1,v2){return -f(v1,v2)};
      return f;
    }
    /* mixin for the `thenBy` property */
    function extend(f, d) {
      f=makeCompareFunction(f, d);
      f.thenBy = tb;
      return f;
    }

    /* adds a secondary compare function to the target function (`this` context)
       which is applied in case the first one returns 0 (equal)
       returns a new compare function, which has a `thenBy` method as well */
    function tb(y, d) {
        var x = this;
        y = makeCompareFunction(y, d);
        return extend(function(a, b) {
            return x(a,b) || y(a,b);
        });
    }
    return extend;
})();
<commit_msg>Allow for undefined properties<commit_after>/***
   Copyright 2013 Teun Duynstee

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
firstBy = (function() {
    function makeCompareFunction(f, direction){
      if(typeof(f)!="function"){
        var prop = f;
        // make unary function
        f = function(v1){return !!v1[prop] ? v1[prop] : "";}
      }
      if(f.length === 1) {
        // f is a unary function mapping a single item to its sort score
        var uf = f;
        f = function(v1,v2) {return uf(v1) < uf(v2) ? -1 : uf(v1) > uf(v2) ? 1 : 0;}
      }
      if(direction === -1)return function(v1,v2){return -f(v1,v2)};
      return f;
    }
    /* mixin for the `thenBy` property */
    function extend(f, d) {
      f=makeCompareFunction(f, d);
      f.thenBy = tb;
      return f;
    }

    /* adds a secondary compare function to the target function (`this` context)
       which is applied in case the first one returns 0 (equal)
       returns a new compare function, which has a `thenBy` method as well */
    function tb(y, d) {
        var x = this;
        y = makeCompareFunction(y, d);
        return extend(function(a, b) {
            return x(a,b) || y(a,b);
        });
    }
    return extend;
})();
<|endoftext|>


<commit_before>/*********************************************/
/*           Simple Thermometer              */
/*                                           */
/* Press button once. If temperature is 25C  */
/* then the RED LED will flash twice and the */
/* GREEN LED will flash 5 times.             */
/*********************************************/

function flashRED() {
  digitalWrite(LED1, 1);
  setTimeout(function() {
    digitalWrite(LED1,0);
  }, 100);
}

function flashGREEN() {
  digitalWrite(LED2, 1);
  setTimeout(function() {
    digitalWrite(LED2,0);
  }, 100);
}

function flashBLUE() {
  digitalWrite(LED3, 1);
  setTimeout(function() {
    digitalWrite(LED3,0);
  }, 100);
}

var digits = [0, 0];
setInterval(function() {
  if(digitalRead(BTN)) {
    temp = E.getTemperature();
    console.log('temp: ' + temp);
    digits = parseInt(temp).toString(10).split("").map(Number);
    console.log(digits);
  }

  if(digits[0]>0) {
    console.log("flashRED");
    flashRED();
  }

  if(digits[0] <= 0) {
   if(digits[1]>0) {
     console.log("flashGREEN");
     flashGREEN();
     digits[1]--;
   }
  }

  digits[0]--;

}, 800);
<commit_msg>Updated to handle negative value temperatures<commit_after>/*********************************************/
/*           Simple Thermometer              */
/*                                           */
/* Press button once. If temperature is 25C  */
/* then the RED LED will flash twice and the */
/* GREEN LED will flash 5 times.             */
/* If temperature is -25C the BLUE LED will  */
/* flash once, the RED LED will flash twice  */
/* and the GREEN LED will flash 5 times.     */
/*********************************************/

function flashRED() {
  digitalWrite(LED1, 1);
  setTimeout(function() {
    digitalWrite(LED1,0);
  }, 100);
}

function flashGREEN() {
  digitalWrite(LED2, 1);
  setTimeout(function() {
    digitalWrite(LED2,0);
  }, 100);
}

function flashBLUE() {
  digitalWrite(LED3, 1);
  setTimeout(function() {
    digitalWrite(LED3,0);
  }, 100);
}

var digits = [0, 0];
var negative = false;
setInterval(function() {
  if(digitalRead(BTN)) {
    temp = E.getTemperature();
    console.log("temperature: " + temp);
    /* check if negative temp exists */
    negative = temp<0 || false;
    temp = Math.abs(temp);
    digits = parseInt(temp).toString(10).split("").map(Number);
    /* always make sure the `digits` array is of length 2 */
    if(digits.length===1) {
      digits.unshift(0);
    }
    console.log(digits);
  }

  if(negative) {
    console.log("flashBLUE");
    flashBLUE();
    negative = false;
  } else {
    if(digits[0]>0) {
      console.log("flashRED");
      flashRED();
    }
    if(digits[0] <= 0) {
     if(digits[1]>0) {
       console.log("flashGREEN");
       flashGREEN();
       digits[1]--;
     }
    }
    digits[0]--;
  }
}, 800);
<|endoftext|>