<commit_before>//Version 2.0

//Next up: show unmeetable requirements in red when !validateSetList

//Add more options later
//Alchemy limits, include trashers, exclude alt-vp cards

(function() {
	'use strict';

	//Detect mobile
	if($(window).width() < 800) { //mobile
			mobileWrap();
	}

	$(window).resize(function(){
		if($(window).width() < 800) { //mobile
			mobileWrap();
		} else {
			mobileUnwrap();
		}
	});

	var kingdom = new Kingdom();
	assignEvents();

	//Kingdom class, holds information about which sets to use, requirements for kingdom cards,
	//which cards to use, and information about those cards, and methods for selecting them
	function Kingdom() {
		this.cards = [];
		this.bane = null;
		this.setList = [];

		this.setDistribution = {
			'Base' : 0,
			'Intrigue' : 0,
			'Seaside' : 0,
		 	'Alchemy': 0,
		 	'Prosperity' : 0,
		 	'Cornucopia' : 0,
		 	'Hinterlands' : 0,
		 	'Dark Ages' : 0,
		 	'Guilds' : 0,
		 	'Adventures' : 0,
		 	'Promo' : 0,
		}

		this.requirements = {
			actions: false,
			buys: false,
			cards: false,
			coins: false,
			isTrasher: false,
		}

		this.specReq = {
			moat: false,
		}
	}

	//Main function, called on button click
	Kingdom.prototype.generateKingdom = function() {

		if( anyChecked() ) { //At least one checkbox selected
				this.setList = kingdom.addSetList();

				if(this.validateSetList()) {
					this.chooseCards();

					this.outputKingdom();

				} else { //Sets unable to fulfill requirements
					activateButton(false);
					errorMsg('Sorry, unable to satisfy all the selected options with the selected sets.  Try different sets or different options.');
				}

			} else { //No checkboxes checked
				activateButton(false);
				errorMsg('Please select at least one set.');
			}
	}

	//Add a bane card
	Kingdom.prototype.addBane =function() {
		var bane = getRandom(this.setList);
		kingdom.bane = bane;
	}

	//Add a specific card object to the kingdom
	Kingdom.prototype.addCard = function(card) {
		this.cards.push(card);
		var setName = this.setNameById(card.setID);
		this.setDistribution[setName]++;
		remove(card, this.setList);

	}

	//Adds cards from the user-checked sets to setList object, from which to draw random cards
	Kingdom.prototype.addSetList = function() {
		var self = this;
		var setsToUse = [];

		$('.sets input[type="checkbox"]').not('[value="all"]').each(function(idx, el) {

			if(el.checked) {
				var setName = el.value;

				var set = self.setIdByName(setName);

				setsToUse = setsToUse.concat(self.pullCardsBySet(set));
			}
		});

		return setsToUse;
	}

	//Check if card fulfills unmet requirement
	Kingdom.prototype.checkRequirements = function(card) {

		for(var prop in this.requirements) {

			//If a requirement is true and not yet fulfilled
			if(this.requirements[prop] && !this.hasType(prop)) {

				return(this.fulfillsRequirement(card, prop));
			}
		}
		return true;
	}

	//Choose ten random cards from setlist, test against requirements
	Kingdom.prototype.chooseCards = function() {
		kingdom.cards = [];
		kingdom.bane = null;

		kingdom.resetKingdom();
		kingdom.getRequirements();

		while(kingdom.cards.length < 10) {
			var card = getRandom(this.setList);

			//copy the set list, to whittle down while searching without effecting setlist
			var cardsToSearch = this.setList.slice();

			//Check a card against outstanding requirements
			while(!this.checkRequirements(card)) {
				remove(card, cardsToSearch);
				card = getRandom(cardsToSearch);
			}

			//Add Moat if option selected and attack card in deck
			if(card['isAttack']) {
				if(this.specReq.moat && !this.hasCard('Moat')) {

					//Add moat if there's room
					if(this.cards.length < 9) {
						this.addCard(cardsByName['Moat']);

					} else { //If its the last card and no moat, draw another non-attack
						while(card['isAttack']) {
							card = getRandom(setList);
						}
					}
				}
			}
			this.addCard(card);
		}

		//Require bane
		if(this.hasCard('Young Witch')) {
			this.addBane();
		}

	}

	//Checks if a card meets a given requirement
	Kingdom.prototype.fulfillsRequirement = function(card, type) {
		if(type == 'actions' || type == 'coins' || type == 'cards') {
				if(card[type] > 1) {
					return true;
				}

		} else {
			if(card[type]) {
				console.log(card.name + ' fulfills req ' + type);
				return true;
			}
		}

		return false;
	}

	//Gets kingdom requirements based on checkboxes
	Kingdom.prototype.getRequirements = function() {
		var self = this;
		$('.require input').each(function() {
			if(this.checked) {
				self.requirements[this.value] = true;
			}
		});

		var moat = $('input[value="moat"]');

		if(moat[0].checked) {
			self.specReq.moat = true;
		}
	}

	//Check whether a certain card is present in kingdom.  Takes either string name or object
	Kingdom.prototype.hasCard = function(card) {
		if(card.constructor == String) {
			card = cardsByName[card];
		}

		if(kingdom.cards.indexOf(card) > -1) {
			return true;
		} else {
			return false;
		}
	}

	//Check if a requirement/card type is already present in selected cards
	Kingdom.prototype.hasType = function(type) {

		for(var i = 0; i < this.cards.length; i++) {
			var card = this.cards[i];

			if(this.fulfillsRequirement(card, type)) {
				return true;
			}

		}
		return false;
	}

	//Print kingdom cards/bane card
	Kingdom.prototype.outputKingdom = function() {
		var output = '
Kingdom Cards
';
		for(var i = 0; i < kingdom.cards.length; i++) {
			var card = kingdom.cards[i];
			output += '
' + card.name + '
';
		}

		if(kingdom.bane) {
			output += '
Bane Card
';
			output += '
' + kingdom.bane.name + '
';
		}
		$('.output').empty().append(output);
	}

	Kingdom.prototype.pullCardsBySet = function(set) {
		var cardsInSet = [];

		for(var i = 0; i < cards.length; i++) { //run backwards for speed?
			var card = cards[i];

			if(card.setID == set) {
				cardsInSet.push(card);
			}

			//Cards object has cards in set order, don't loop through whole thing once you've passed your set
			if(card.setID > set) {
				return cardsInSet;
			}
		}
		return cardsInSet;
	}

	Kingdom.prototype.setIdByName = function(name) {
		for(var set in sets) {
			if(sets[set].name.toLowerCase() == name.toLowerCase()) {
				return set;
			}
		}
		return false;
	}

	Kingdom.prototype.setNameById = function(id) {
		for(var set in sets) {
			if(set == id) {
				return sets[set].name;
			}
		}
	}

	//Clears out kingdom requirements and set distrubtion objects in preparation for new kingdom
	Kingdom.prototype.resetKingdom = function() {
		for(var prop in this.requirements) {
			this.requirements[prop] = false;
		}

		for(var prop in this.specReq) {
			this.specReq[prop] = false;
		}

		for(var prop in this.setDistribution) {
			this.setDistribution[prop] = 0;
		}
	}

	//Testing function, logs kingdom requirements and checks if any not met
	Kingdom.prototype.validateDeck = function() {
		for(var prop in this.requirements) {

			if(this.requirements[prop] && !this.hasType(prop)) {
				console.log('requirement true: ', prop);
				console.log('kingdom has type: ', this.hasType(prop));
				console.log('Deck not valid, missing: ', prop);
			}
		}
	}

	//Upcoming: show which requirements can't be fulfilled - push those to array and highlight in dom

	//Check whether the selected sets are capable of fulfilling the selected requirements
	Kingdom.prototype.validateSetList = function() {
		var valid = true;
		var self = this;
		this.resetKingdom();
		this.getRequirements();

		if(self.setList.length < 10) {
			return false;
		}

		//Make array of true requirements
		var reqs = [];
		for(var prop in this.requirements) {
			if(this.requirements[prop]) {
				reqs.push(prop);
			}
		}

		//Return true if, for all requirements, any one card fills that requirement.
		if(reqs.length) {
			valid = reqs.every(function(property){
				return self.setList.some(function(el){

					if( self.fulfillsRequirement(el, property)) {

						return true;
					}

				});
			});
		}
		return valid;

	}

	/*------------------------
	MOBILE FUNCTIONS
	-------------------------*/

	//Wraps labels in div so each appears on own line
	function mobileWrap() {
		$('.sets label, .require label').wrap('

');
	}

	//Unwraps labels when resized from small to large screen
	function mobileUnwrap() {
		$('.sets div label, .require label').unwrap();
	}

	/*------------------------
	DOM INTERACTION/EVENT HANDLING
	-------------------------*/

	//Attaches event handers to checkboxes and button
	function assignEvents() {
		activateButton(true);

		//Check all checkboxes
		$('input[value="all"]').change(function(){
			if(this.checked) {
				$('.sets input').prop('checked', true);
			} else {
				$('.sets input').not('[value="base"]').prop('checked', false);
			}
		});

		//Check if button should be active/inactive
		$('input[type="checkbox"]').change(function() {
			if(!anyChecked()) {
				activateButton(false);

			} else {
				activateButton(true);
			}
		});
	}

	//Assigns generateKingdom to active button
	function assignButton() {
		//clear out attached functions so they dont stack
		$('.get-cards').off();

		$('.get-cards').click(function() {
			kingdom.generateKingdom();
		});
	}

	//Takes true/false to activate/inactive button
	function activateButton(bool) {
		var button = $('button');
		if(bool) {

			//Only clear if going from inactive to active
			if(button.hasClass('inactive')) {
				$('.output').empty();
			}
			button.removeClass('inactive');
			button.addClass('active');

		} else {

			button.addClass('inactive');
			button.removeClass('active');
			button.off();
			errorMsg('Please select at least one set.');
		}
		button[0].disabled = !bool;
		assignButton();
	}

	//Checks that at least one set checkbox is checked
	function anyChecked() {
		var selected = false;

		$('.sets input[type="checkbox"]').each(function() {
			if(this.checked) {
				selected = true;
			}
		});
		return selected;
	}

	/*------------------------
	HELPER FUNCTIONS
	-------------------------*/

	//Get random item from array
	function getRandom(items) {
		var item = items[Math.floor(Math.random() * items.length)];
		return item;
	}

	function remove(el, array) {
		var index = array.indexOf(el);
		if(index > -1) {
			array.splice(index, 1);
		}
	}

	function errorMsg(error) {
		var msg = $('
');
		msg.text(error);
		$('.output').empty().append(msg);
	}

})();<commit_msg>cleaned up console msg<commit_after>//Version 2.0

//Next up: show unmeetable requirements in red when !validateSetList

//Add more options later
//Alchemy limits, include trashers, exclude alt-vp cards

(function() {
	'use strict';

	//Detect mobile
	if($(window).width() < 800) { //mobile
			mobileWrap();
	}

	$(window).resize(function(){
		if($(window).width() < 800) { //mobile
			mobileWrap();
		} else {
			mobileUnwrap();
		}
	});

	var kingdom = new Kingdom();
	assignEvents();

	//Kingdom class, holds information about which sets to use, requirements for kingdom cards,
	//which cards to use, and information about those cards, and methods for selecting them
	function Kingdom() {
		this.cards = [];
		this.bane = null;
		this.setList = [];

		this.setDistribution = {
			'Base' : 0,
			'Intrigue' : 0,
			'Seaside' : 0,
		 	'Alchemy': 0,
		 	'Prosperity' : 0,
		 	'Cornucopia' : 0,
		 	'Hinterlands' : 0,
		 	'Dark Ages' : 0,
		 	'Guilds' : 0,
		 	'Adventures' : 0,
		 	'Promo' : 0,
		}

		this.requirements = {
			actions: false,
			buys: false,
			cards: false,
			coins: false,
			isTrasher: false,
		}

		this.specReq = {
			moat: false,
		}
	}

	//Main function, called on button click
	Kingdom.prototype.generateKingdom = function() {

		if( anyChecked() ) { //At least one checkbox selected
				this.setList = kingdom.addSetList();

				if(this.validateSetList()) {
					this.chooseCards();

					this.outputKingdom();

				} else { //Sets unable to fulfill requirements
					activateButton(false);
					errorMsg('Sorry, unable to satisfy all the selected options with the selected sets.  Try different sets or different options.');
				}

			} else { //No checkboxes checked
				activateButton(false);
				errorMsg('Please select at least one set.');
			}
	}

	//Add a bane card
	Kingdom.prototype.addBane =function() {
		var bane = getRandom(this.setList);
		kingdom.bane = bane;
	}

	//Add a specific card object to the kingdom
	Kingdom.prototype.addCard = function(card) {
		this.cards.push(card);
		var setName = this.setNameById(card.setID);
		this.setDistribution[setName]++;
		remove(card, this.setList);

	}

	//Adds cards from the user-checked sets to setList object, from which to draw random cards
	Kingdom.prototype.addSetList = function() {
		var self = this;
		var setsToUse = [];

		$('.sets input[type="checkbox"]').not('[value="all"]').each(function(idx, el) {

			if(el.checked) {
				var setName = el.value;

				var set = self.setIdByName(setName);

				setsToUse = setsToUse.concat(self.pullCardsBySet(set));
			}
		});

		return setsToUse;
	}

	//Check if card fulfills unmet requirement
	Kingdom.prototype.checkRequirements = function(card) {

		for(var prop in this.requirements) {

			//If a requirement is true and not yet fulfilled
			if(this.requirements[prop] && !this.hasType(prop)) {

				return(this.fulfillsRequirement(card, prop));
			}
		}
		return true;
	}

	//Choose ten random cards from setlist, test against requirements
	Kingdom.prototype.chooseCards = function() {
		kingdom.cards = [];
		kingdom.bane = null;

		kingdom.resetKingdom();
		kingdom.getRequirements();

		while(kingdom.cards.length < 10) {
			var card = getRandom(this.setList);

			//copy the set list, to whittle down while searching without effecting setlist
			var cardsToSearch = this.setList.slice();

			//Check a card against outstanding requirements
			while(!this.checkRequirements(card)) {
				remove(card, cardsToSearch);
				card = getRandom(cardsToSearch);
			}

			//Add Moat if option selected and attack card in deck
			if(card['isAttack']) {
				if(this.specReq.moat && !this.hasCard('Moat')) {

					//Add moat if there's room
					if(this.cards.length < 9) {
						this.addCard(cardsByName['Moat']);

					} else { //If its the last card and no moat, draw another non-attack
						while(card['isAttack']) {
							card = getRandom(setList);
						}
					}
				}
			}
			this.addCard(card);
		}

		//Require bane
		if(this.hasCard('Young Witch')) {
			this.addBane();
		}

	}

	//Checks if a card meets a given requirement
	Kingdom.prototype.fulfillsRequirement = function(card, type) {
		if(type == 'actions' || type == 'coins' || type == 'cards') {
				if(card[type] > 1) {
					return true;
				}

		} else {
			if(card[type]) {
				return true;
			}
		}

		return false;
	}

	//Gets kingdom requirements based on checkboxes
	Kingdom.prototype.getRequirements = function() {
		var self = this;
		$('.require input').each(function() {
			if(this.checked) {
				self.requirements[this.value] = true;
			}
		});

		var moat = $('input[value="moat"]');

		if(moat[0].checked) {
			self.specReq.moat = true;
		}
	}

	//Check whether a certain card is present in kingdom.  Takes either string name or object
	Kingdom.prototype.hasCard = function(card) {
		if(card.constructor == String) {
			card = cardsByName[card];
		}

		if(kingdom.cards.indexOf(card) > -1) {
			return true;
		} else {
			return false;
		}
	}

	//Check if a requirement/card type is already present in selected cards
	Kingdom.prototype.hasType = function(type) {

		for(var i = 0; i < this.cards.length; i++) {
			var card = this.cards[i];

			if(this.fulfillsRequirement(card, type)) {
				return true;
			}

		}
		return false;
	}

	//Print kingdom cards/bane card
	Kingdom.prototype.outputKingdom = function() {
		var output = '
Kingdom Cards
';
		for(var i = 0; i < kingdom.cards.length; i++) {
			var card = kingdom.cards[i];
			output += '
' + card.name + '
';
		}

		if(kingdom.bane) {
			output += '
Bane Card
';
			output += '
' + kingdom.bane.name + '
';
		}
		$('.output').empty().append(output);
	}

	Kingdom.prototype.pullCardsBySet = function(set) {
		var cardsInSet = [];

		for(var i = 0; i < cards.length; i++) { //run backwards for speed?
			var card = cards[i];

			if(card.setID == set) {
				cardsInSet.push(card);
			}

			//Cards object has cards in set order, don't loop through whole thing once you've passed your set
			if(card.setID > set) {
				return cardsInSet;
			}
		}
		return cardsInSet;
	}

	Kingdom.prototype.setIdByName = function(name) {
		for(var set in sets) {
			if(sets[set].name.toLowerCase() == name.toLowerCase()) {
				return set;
			}
		}
		return false;
	}

	Kingdom.prototype.setNameById = function(id) {
		for(var set in sets) {
			if(set == id) {
				return sets[set].name;
			}
		}
	}

	//Clears out kingdom requirements and set distrubtion objects in preparation for new kingdom
	Kingdom.prototype.resetKingdom = function() {
		for(var prop in this.requirements) {
			this.requirements[prop] = false;
		}

		for(var prop in this.specReq) {
			this.specReq[prop] = false;
		}

		for(var prop in this.setDistribution) {
			this.setDistribution[prop] = 0;
		}
	}

	//Testing function, logs kingdom requirements and checks if any not met
	Kingdom.prototype.validateDeck = function() {
		for(var prop in this.requirements) {

			if(this.requirements[prop] && !this.hasType(prop)) {
				console.log('requirement true: ', prop);
				console.log('kingdom has type: ', this.hasType(prop));
				console.log('Deck not valid, missing: ', prop);
			}
		}
	}

	//Upcoming: show which requirements can't be fulfilled - push those to array and highlight in dom

	//Check whether the selected sets are capable of fulfilling the selected requirements
	Kingdom.prototype.validateSetList = function() {
		var valid = true;
		var self = this;
		this.resetKingdom();
		this.getRequirements();

		if(self.setList.length < 10) {
			return false;
		}

		//Make array of true requirements
		var reqs = [];
		for(var prop in this.requirements) {
			if(this.requirements[prop]) {
				reqs.push(prop);
			}
		}

		//Return true if, for all requirements, any one card fills that requirement.
		if(reqs.length) {
			valid = reqs.every(function(property){
				return self.setList.some(function(el){

					if( self.fulfillsRequirement(el, property)) {

						return true;
					}

				});
			});
		}
		return valid;

	}

	/*------------------------
	MOBILE FUNCTIONS
	-------------------------*/

	//Wraps labels in div so each appears on own line
	function mobileWrap() {
		$('.sets label, .require label').wrap('

');
	}

	//Unwraps labels when resized from small to large screen
	function mobileUnwrap() {
		$('.sets div label, .require label').unwrap();
	}

	/*------------------------
	DOM INTERACTION/EVENT HANDLING
	-------------------------*/

	//Attaches event handers to checkboxes and button
	function assignEvents() {
		activateButton(true);

		//Check all checkboxes
		$('input[value="all"]').change(function(){
			if(this.checked) {
				$('.sets input').prop('checked', true);
			} else {
				$('.sets input').not('[value="base"]').prop('checked', false);
			}
		});

		//Check if button should be active/inactive
		$('input[type="checkbox"]').change(function() {
			if(!anyChecked()) {
				activateButton(false);

			} else {
				activateButton(true);
			}
		});
	}

	//Assigns generateKingdom to active button
	function assignButton() {
		//clear out attached functions so they dont stack
		$('.get-cards').off();

		$('.get-cards').click(function() {
			kingdom.generateKingdom();
		});
	}

	//Takes true/false to activate/inactive button
	function activateButton(bool) {
		var button = $('button');
		if(bool) {

			//Only clear if going from inactive to active
			if(button.hasClass('inactive')) {
				$('.output').empty();
			}
			button.removeClass('inactive');
			button.addClass('active');

		} else {

			button.addClass('inactive');
			button.removeClass('active');
			button.off();
			errorMsg('Please select at least one set.');
		}
		button[0].disabled = !bool;
		assignButton();
	}

	//Checks that at least one set checkbox is checked
	function anyChecked() {
		var selected = false;

		$('.sets input[type="checkbox"]').each(function() {
			if(this.checked) {
				selected = true;
			}
		});
		return selected;
	}

	/*------------------------
	HELPER FUNCTIONS
	-------------------------*/

	//Get random item from array
	function getRandom(items) {
		var item = items[Math.floor(Math.random() * items.length)];
		return item;
	}

	function remove(el, array) {
		var index = array.indexOf(el);
		if(index > -1) {
			array.splice(index, 1);
		}
	}

	function errorMsg(error) {
		var msg = $('
');
		msg.text(error);
		$('.output').empty().append(msg);
	}

})();<|endoftext|>


<commit_before>window.Amble = (function(){

    var Amble = {};
    Amble.app = {};

    Amble.Application = function(args){
        var that = this;
        Amble.app = this;

        this.debug = new Amble.Debug();
        this.imgList = [];

        this.resize = typeof args['resize'] === 'boolean' ? args['resize'] : false;

        //wrap this things up
        if(this.resize) {
          window.addEventListener('resize', function(){

            var width = $(camera.context).width();
            var height = $(camera.context).height();

            Amble.app.width = Amble.app.mainCamera.camera.layer.canvas.width = width;
            Amble.app.height = Amble.app.mainCamera.camera.layer.canvas.height = height;

            Amble.app.mainCamera.getComponent('Camera').onresize(Amble.app.mainCamera);

          });
        }

        this.scene = new Amble.Scene();

        if(args['sceneCamera']) {
            this.mainCamera = this.scene.instantiate(args['sceneCamera']);
        }

        if(this.mainCamera) {
          this.width = this.mainCamera.camera.size.x || 800;
          this.height = this.mainCamera.camera.size.y || 600;
        }

        //init all public game loop functions
        var gameLoopFunctionsList = ['preload', 'loaded', 'start', 'preupdate', 'postupdate', 'prerender', 'postrender'];
        for(var i in gameLoopFunctionsList){
            this[gameLoopFunctionsList[i]] = typeof args[gameLoopFunctionsList[i]] === 'function' ? args[gameLoopFunctionsList[i]] : function(){};
        }

        this.paused = false;
        this.pause = function() {
            this.paused = true;
            console.log('pause')
        };

        this.unpause = function() {
            console.log('unpause')
            this.paused = false;
            gameLoop();
        };

        //private game loop functions
        this.update = function(){

            this.mainCamera.camera.update()
            this.scene.update();

            //update all objects on scene
            //priorytet sort?
        };

        this.render = function(){

            var camera = this.mainCamera.camera;
            var linesColor = '#eceff1'

            camera.layer.clear();
            var layer = camera.layer;

            layer.strokeStyle(linesColor).lineWidth(0.5);
            layer.ctx.beginPath();

            var lineSpacing = 200;

            var verticalLinesCount = ((this.width/camera.scale)/lineSpacing) * 2;
            var horizontalLinesCount = ((this.height/camera.scale)/lineSpacing) * 2;
            var startX = Math.floor(camera.position.x - (camera.size.x)/camera.scale) - (camera.position.x - (camera.size.x)/camera.scale) % lineSpacing;
            var startY = Math.floor(camera.position.y - (camera.size.y)/camera.scale) - (camera.position.y - (camera.size.y)/camera.scale) % lineSpacing;

            //vertical lines
            for(var i = -2; i < verticalLinesCount; i++) {
                layer.ctx.moveTo(startX + lineSpacing * i - camera.view.x, camera.position.y - camera.size.y/camera.scale - camera.view.y - lineSpacing);
                layer.ctx.lineTo(startX + lineSpacing * i - camera.view.x, camera.position.y + camera.size.y/camera.scale - camera.view.y);
            }

            //horizonala
            for(var i = -2; i < horizontalLinesCount; i++) {
                layer.ctx.moveTo(camera.position.x - camera.size.x/camera.scale - camera.view.x - lineSpacing * 2, startY + lineSpacing * i - camera.view.y);
                layer.ctx.lineTo(camera.position.x + camera.size.x/camera.scale - camera.view.x, startY + lineSpacing * i - camera.view.y);
            }

            layer.ctx.stroke();

            this.scene.render(camera);

            layer.ctx.save();
            //draw camera viewport (sroke rect)
            layer.strokeStyle(primaryColor);
            layer.lineWidth(1.5)
            var x = -1280/2 - camera.view.x;
            var y = -720/2 - camera.view.y;
            layer.strokeRect(x, y, 1280,  720)

            layer.ctx.restore();

        };

        /* setting loader */
        this.loader = new Amble.Data.Loader();

        var loadingTimer = 0;
        var currentLoadingText = 0;

        var colors = [
            "#8e24aa",
            "#5e35b1",
            "#3949ab",
            "#1e88e5",
            "#039be5",
            "#00acc1",
            "#00897b",
            "#43a047",
            "#7cb342",
            "#c0ca33",
            "#fbc02d",
            "#ff6f00",
            "#e53935",
            "#e91e63"
        ];

        var color = colors[Math.floor(Math.random() * colors.length - 1)];

        this.loadingInterval = setInterval(function(){
            if(that.mainCamera) {
                var x = (that.width - that.width/4) * ((that.loader.successCount + that.loader.errorCount)/that.loader.queue.length);
                var layer = that.mainCamera.camera.layer;
                layer.ctx.save();
                var loading = [
                    "   loading.  ",
                    "   loading.. ",
                    "   loading...",
                ]

                layer.clear('black')
                    .fillStyle(color)
                    .strokeStyle('white')
                    .fillRect(that.width/8, that.height/2 - that.height/16, x, that.height/8)
                    .strokeRect(that.width/8, that.height/2 - that.height/16, (that.width - that.width/4), that.height/8);

                layer.ctx.shadowColor = "white";
                layer.ctx.shadowBlur = 20;

                layer.fillStyle('white');
                layer.ctx.textAlign = 'center';
                layer.ctx.font = "25px Arial";
                var text = parseInt(((that.loader.successCount + that.loader.errorCount)/that.loader.queue.length) * 100) + "%"
                layer.ctx.fillText(text, that.width/2, that.height/2 + 7)

                layer.ctx.font = "20px Arial";
                text = loading[currentLoadingText];
                layer.ctx.fillText(text, that.width/2, 2*that.height/3 + 10)

                loadingTimer += 1/60;
                if(loadingTimer > 1) {
                    loadingTimer = 0;
                    currentLoadingText++;
                    if(currentLoadingText == loading.length) currentLoadingText = 0;
                }
                layer.ctx.restore();
            }
        }, 1000/60);

        /* setting all loading heppens there */
        this.preload();

        /* all loading */
        this.loader.loadAll(function(){

            setTimeout(function(){
                clearInterval(that.loadingInterval);
                Amble.Input._setListeners();

                Amble.app.loader.audioCache = [];
                // that.scene.start();
                that.loaded();

                that.start();
                Amble.Time._lastTime = Date.now()
                gameLoop();

            }, 0);
        })

        function gameLoop(){
            if(!that.paused) {

                var now = Date.now();
                Amble.Time.deltaTime = (now - Amble.Time._lastTime) / 1000.0;

                if(that.mainCamera) {
                    that.preupdate();
                    that.update();
                    that.postupdate();
                    that.render();
                    that.postrender();
                }

                Amble.Time._lastTime = now;
                requestAnimationFrame(gameLoop)
            }
        }
    };

    return Amble;

}());
<commit_msg>removed unnecessary file<commit_after><|endoftext|>


<commit_before>$(document).ready(function() {
	var mouseDown = false;
	var draggingItem = null;
	var lastMouseY = 0;
	var lastMouseX = 0;

	var realtimeArrange = true;

	var dragItems = [];
	var dragTargets = [];
	initList();

	$(".draggable").on("mousedown", function(e) {
		mouseDown = true;
		draggingItem = $.grep(dragItems, function(item){ return item.dragging; })[0];
	});

	$(document).on("mouseup", function() {
		if(draggingItem !== null) {
			var arrangeNeeded = draggingItem.snapTarget !== null && !draggingItem.snapTarget.isEmpty();
			draggingItem.snap();
			if(arrangeNeeded) {
				arrangeList();
			}
			reset();
		}
	});

	$(document).on("mousemove", function(e) {
		if(!mouseDown){ return; }

		if(mouseDown && draggingItem !== null) {
			var directionY = e.pageY < lastMouseY ? "up" : "down";
			var directionX = e.pageX < lastMouseX ? "right" : "left";
			var height = draggingItem.elem.outerHeight();
            var width = draggingItem.elem.outerWidth();
            var left = e.clientX - draggingItem.anchorPoint.left;
            var top = e.clientY - draggingItem.anchorPoint.top;

            // Restrict dragging to a pre-defined area.
            // All the items must be inside a drag_area container for this to work.
            var area = $(".drag_area");
            if(area.length !== 0 && area !== null){
            	var areaBounds = area[0].getBoundingClientRect();
	            if ((left + width) >= areaBounds.right) {
	                left = areaBounds.right - width;
	            }
	            if (left <= areaBounds.left) {
	                left = areaBounds.left;
	            }
	            if(top <= areaBounds.top) {
	            	top = areaBounds.top;
	            }
	            if((top + height) >= areaBounds.bottom) {
	            	top = areaBounds.bottom - height;
	            }

            }

            if(draggingItem.elem.hasClass("sticky") && draggingItem.dragStartPos !== null){
            	var distance = draggingItem.calculateDistance(e.pageX, e.pageY);
            	if(distance >= 70) {
            		draggingItem.dragStartPos = null;
            		draggingItem.move(top, left);
            	}
            } else {
            	draggingItem.move(top, left)
            }

            // Find closest snap position.
            var overlapHandled = false;
            draggingItem.snapTarget = null;
            $(dragItems).each(function() {
            	var item = this.dragTarget.elem;
            	var rect1 = draggingItem.elem[0].getBoundingClientRect();
				var rect2 = item[0].getBoundingClientRect();

				var overlap = !(rect1.right < rect2.left ||
	                rect1.left > rect2.right ||
	                (rect1.bottom - rect1.height / 2) < rect2.top ||
	                (rect1.top + rect1.height / 2) > rect2.bottom);

				if (overlap && !overlapHandled) {
					overlapHandled = true;
					$(item).css("opacity", 1);
					draggingItem.setSnapTarget(this.dragTarget);

					if(realtimeArrange){
						var arrangeNeeded = draggingItem.snapTarget !== null && !draggingItem.snapTarget.isEmpty();
						draggingItem.simulateSnap();
						if(arrangeNeeded) {
							arrangeList();
						}
					}
				} else{
					$(item).css("opacity", 0.2);
				}
            });

            lastMouseY = e.pageY;
            lastMouseX = e.pageX;
		}
	});

	function arrangeList() {
		var moved = false;
		var arrangeDirection = null;
		var startingIndex = 0;
		var emptyIndex = 0;

		$(dragItems).each(function() {
			if($(this).is($(draggingItem))) { return; }

			if(draggingItem.dragTarget.index === this.dragTarget.index) {

				arrangeDirection = this.dragTarget.index < draggingItem.index ? "down" : "up";
				startingIndex = this.dragTarget.index;
				emptyIndex = draggingItem.index;
			}
		});

		$(dragItems).each(function(i) {
			if(!$(this).is($(draggingItem))) {
				var t = this;
				var newIndex = $.extend({}, { index: t.index }).index;
				var indexChanged = false;
				if(arrangeDirection === "up") {
					if(this.index <= startingIndex && this.index > emptyIndex && this.index - 1 >= 0) {
						newIndex--;
						indexChanged = true;
					}
				} else {
					if(this.index >= startingIndex && this.index < emptyIndex && this.index + 1 < dragItems.length) {
						newIndex++;
						indexChanged = true;
					}
				}
				if(indexChanged) {
					var target = $.grep(dragTargets, function(dt) { return dt.index === newIndex; })[0];
					if(target !== undefined){
						this.snapTarget = target;
						this.snap();
					}
				}
			}
			this.index = this.dragTarget.index;
		});
	}

	function initList() {
		var area = $(".drag_area");
		var items = area.find(".draggable");
		if(items.length !== 0) {
			var itemHeight = $(items[0]).outerHeight();
			var itemWidth = $(items[0]).outerWidth();
			var areaBounds = area[0].getBoundingClientRect();
			var parts = areaBounds.height / items.length;
			$.each(items, function(i) {
				var pos = $(this).offset();
				var dragTarget = new DragTarget($("

"), i);
				dragTarget.elem.css({"height": itemHeight, "width": itemWidth, "top": pos.top, "left": pos.left});
				area.prepend(dragTarget.elem);

				var item = new DragItem($(this), dragTarget, i);
				dragItems.push(item);
				dragTargets.push(dragTarget);
			});
		}
	}

	function reset() {
		mouseDown = false;
		draggingItem.reset();
		draggingItem = null;
		$(".drag_target").each(function() {
			$(this).css("opacity", 0);
		});
	}

});

function DragItem(elem, dragTarget, index) {
	this.elem = elem;
	this.dragTarget = dragTarget;
	this.index = index;
	this.startingPos = null;
	this.anchorPoint = null;
	this.dragStartPos = null;
	this.snapTarget = null;
	this.dragging = false;

	var t = this;
	this.elem.on("mousedown", function(e) {
		if(t.elem.hasClass("snapping")){ return; }

		var offset = $(this).offset();
		t.startingPos = offset;
		t.anchorPoint = { top: e.pageY - offset.top, left: e.pageX - offset.left };
		t.dragStartPos = { top: e.pageY, left: e.pageX };
		t.dragging = true;
		t.dragTarget.empty = true;
	});

	DragItem.prototype.move = function(top, left) {
		this.elem.offset({ top: top, left: left });
	};

	DragItem.prototype.snap = function() {
		this.elem.addClass("snapping");

		if(this.snapTarget !== null) {
			this.move(this.snapTarget.elem.offset().top, this.snapTarget.elem.offset().left);
			this.dragTarget = this.snapTarget;
			this.dragTarget.empty = false;
		} else {
			this.move(this.startingPos.top, this.startingPos.left);
		}

		var t = this;
		setTimeout(function(){
			t.elem.removeClass("snapping");
		}, 300);
	};

	// Used for realtime arranging, sets a new dragtarget without actually moving to it.
	DragItem.prototype.simulateSnap = function() {
		if(this.snapTarget !== null) {
			this.dragTarget = this.snapTarget;
			this.dragTarget.empty = false;
		}
	};

	DragItem.prototype.reset = function() {
		this.startingPos = null;
		this.anchorPoint = null;
		this.dragStartPos = null;
		this.dragging = false;
	};

	DragItem.prototype.calculateDistance = function(mouseX, mouseY) {
        return Math.floor(Math.sqrt(Math.pow(mouseX - this.dragStartPos.left, 2) +
        	Math.pow(mouseY - this.dragStartPos.top, 2)));
	};

	DragItem.prototype.setDragging = function(dragging) {
		this.dragging = dragging;
	};

	DragItem.prototype.setSnapTarget = function(target) {
		this.snapTarget = target;
	};

	DragItem.prototype.setStartingPos = function(pos) {
		this.startingPos = pos;
	};
}

function DragTarget(elem, index) {
	this.elem = elem;
	this.index = index;
	this.empty = false;

	DragTarget.prototype.isEmpty = function() {
		return this.empty;
	};
}<commit_msg>fixed a bug with realtime arrange<commit_after>$(document).ready(function() {
	var mouseDown = false;
	var draggingItem = null;
	var lastMouseY = 0;
	var lastMouseX = 0;

	var realtimeArrange = true;

	var dragItems = [];
	var dragTargets = [];
	initList();

	$(".draggable").on("mousedown", function(e) {
		mouseDown = true;
		draggingItem = $.grep(dragItems, function(item){ return item.dragging; })[0];
	});

	$(document).on("mouseup", function() {
		if(draggingItem !== null) {
			var arrangeNeeded = draggingItem.snapTarget !== null && !draggingItem.snapTarget.isEmpty();
			draggingItem.snap();
			if(arrangeNeeded) {
				arrangeList();
			}
			reset();
		}
	});

	$(document).on("mousemove", function(e) {
		if(!mouseDown){ return; }

		if(mouseDown && draggingItem !== null) {
			var directionY = e.pageY < lastMouseY ? "up" : "down";
			var directionX = e.pageX < lastMouseX ? "right" : "left";
			var height = draggingItem.elem.outerHeight();
            var width = draggingItem.elem.outerWidth();
            var left = e.clientX - draggingItem.anchorPoint.left;
            var top = e.clientY - draggingItem.anchorPoint.top;

            // Restrict dragging to a pre-defined area.
            // All the items must be inside a drag_area container for this to work.
            var area = $(".drag_area");
            if(area.length !== 0 && area !== null){
            	var areaBounds = area[0].getBoundingClientRect();
	            if ((left + width) >= areaBounds.right) {
	                left = areaBounds.right - width;
	            }
	            if (left <= areaBounds.left) {
	                left = areaBounds.left;
	            }
	            if(top <= areaBounds.top) {
	            	top = areaBounds.top;
	            }
	            if((top + height) >= areaBounds.bottom) {
	            	top = areaBounds.bottom - height;
	            }

            }

            if(draggingItem.elem.hasClass("sticky") && draggingItem.dragStartPos !== null){
            	var distance = draggingItem.calculateDistance(e.pageX, e.pageY);
            	if(distance >= 70) {
            		draggingItem.dragStartPos = null;
            		draggingItem.move(top, left);
            	}
            } else {
            	draggingItem.move(top, left)
            }

            // Find closest snap position.
            var overlapHandled = false;
            if(!realtimeArrange){
            	draggingItem.snapTarget = null;
            }
            $(dragItems).each(function() {
            	var item = this.dragTarget.elem;
            	var rect1 = draggingItem.elem[0].getBoundingClientRect();
				var rect2 = item[0].getBoundingClientRect();

				var overlap = !(rect1.right < rect2.left ||
	                rect1.left > rect2.right ||
	                (rect1.bottom - rect1.height / 2) < rect2.top ||
	                (rect1.top + rect1.height / 2) > rect2.bottom);

				if (overlap && !overlapHandled) {
					overlapHandled = true;
					$(item).css("opacity", 1);
					draggingItem.setSnapTarget(this.dragTarget);

					if(realtimeArrange){
						var arrangeNeeded = draggingItem.snapTarget !== null && !draggingItem.snapTarget.isEmpty();
						draggingItem.simulateSnap();
						if(arrangeNeeded) {
							arrangeList();
						}
					}
				} else{
					$(item).css("opacity", 0.2);
				}
            });

            lastMouseY = e.pageY;
            lastMouseX = e.pageX;
		}
	});

	function arrangeList() {
		var moved = false;
		var arrangeDirection = null;
		var startingIndex = 0;
		var emptyIndex = 0;

		$(dragItems).each(function() {
			if($(this).is($(draggingItem))) { return; }

			if(draggingItem.dragTarget.index === this.dragTarget.index) {

				arrangeDirection = this.dragTarget.index < draggingItem.index ? "down" : "up";
				startingIndex = this.dragTarget.index;
				emptyIndex = draggingItem.index;
			}
		});

		$(dragItems).each(function(i) {
			if(!$(this).is($(draggingItem))) {
				var t = this;
				var newIndex = $.extend({}, { index: t.index }).index;
				var indexChanged = false;
				if(arrangeDirection === "up") {
					if(this.index <= startingIndex && this.index > emptyIndex && this.index - 1 >= 0) {
						newIndex--;
						indexChanged = true;
					}
				} else {
					if(this.index >= startingIndex && this.index < emptyIndex && this.index + 1 < dragItems.length) {
						newIndex++;
						indexChanged = true;
					}
				}
				if(indexChanged) {
					var target = $.grep(dragTargets, function(dt) { return dt.index === newIndex; })[0];
					if(target !== undefined){
						this.snapTarget = target;
						this.snap();
					}
				}
			}
			this.index = this.dragTarget.index;
		});
	}

	function initList() {
		var area = $(".drag_area");
		var items = area.find(".draggable");
		if(items.length !== 0) {
			var itemHeight = $(items[0]).outerHeight();
			var itemWidth = $(items[0]).outerWidth();
			var areaBounds = area[0].getBoundingClientRect();
			var parts = areaBounds.height / items.length;
			$.each(items, function(i) {
				var pos = $(this).offset();
				var dragTarget = new DragTarget($("

"), i);
				dragTarget.elem.css({"height": itemHeight, "width": itemWidth, "top": pos.top, "left": pos.left});
				area.prepend(dragTarget.elem);

				var item = new DragItem($(this), dragTarget, i);
				dragItems.push(item);
				dragTargets.push(dragTarget);
			});
		}
	}

	function reset() {
		mouseDown = false;
		draggingItem.reset();
		draggingItem = null;
		$(".drag_target").each(function() {
			$(this).css("opacity", 0);
		});
	}

});

function DragItem(elem, dragTarget, index) {
	this.elem = elem;
	this.dragTarget = dragTarget;
	this.index = index;
	this.startingPos = null;
	this.anchorPoint = null;
	this.dragStartPos = null;
	this.snapTarget = null;
	this.dragging = false;

	var t = this;
	this.elem.on("mousedown", function(e) {
		if(t.elem.hasClass("snapping")){ return; }

		var offset = $(this).offset();
		t.startingPos = offset;
		t.anchorPoint = { top: e.pageY - offset.top, left: e.pageX - offset.left };
		t.dragStartPos = { top: e.pageY, left: e.pageX };
		t.dragging = true;
		t.dragTarget.empty = true;
	});

	DragItem.prototype.move = function(top, left) {
		this.elem.offset({ top: top, left: left });
	};

	DragItem.prototype.snap = function() {
		this.elem.addClass("snapping");

		if(this.snapTarget !== null) {
			this.move(this.snapTarget.elem.offset().top, this.snapTarget.elem.offset().left);
			this.dragTarget = this.snapTarget;
			this.dragTarget.empty = false;
		} else {
			this.move(this.startingPos.top, this.startingPos.left);
		}

		var t = this;
		setTimeout(function(){
			t.elem.removeClass("snapping");
		}, 300);
	};

	// Used for realtime arranging, sets a new dragtarget without actually moving to it.
	DragItem.prototype.simulateSnap = function() {
		if(this.snapTarget !== null) {
			this.dragTarget = this.snapTarget;
			this.dragTarget.empty = false;
		}
	};

	DragItem.prototype.reset = function() {
		this.startingPos = null;
		this.anchorPoint = null;
		this.dragStartPos = null;
		this.dragging = false;
	};

	DragItem.prototype.calculateDistance = function(mouseX, mouseY) {
        return Math.floor(Math.sqrt(Math.pow(mouseX - this.dragStartPos.left, 2) +
        	Math.pow(mouseY - this.dragStartPos.top, 2)));
	};

	DragItem.prototype.setDragging = function(dragging) {
		this.dragging = dragging;
	};

	DragItem.prototype.setSnapTarget = function(target) {
		this.snapTarget = target;
	};

	DragItem.prototype.setStartingPos = function(pos) {
		this.startingPos = pos;
	};
}

function DragTarget(elem, index) {
	this.elem = elem;
	this.index = index;
	this.empty = false;

	DragTarget.prototype.isEmpty = function() {
		return this.empty;
	};
}<|endoftext|>


<commit_before>/***
|''Name''|TiddlySpaceErrorHandlers|
|''Description''|Provides useful functionality for a given error message|
|''Version''|0.2.0|
***/
//{{{
var errorhandler = {
	homespace: "frontpage",
	locale: {
		errorCreateSpace: "error creating space.",
		makeTiddlerHeader: "Make Tiddler",
		tiddlerSuggestionsHeader: "Were you looking for one of these tiddlers...?",
		spaceSuggestionsHeader: "Were you looking for one of these spaces...?",
		claimSpace: "create space with this name",
		alternativeTiddlers: "looking for alternative tiddlers...",
		alternativeSpaces: "looking for alternative spaces...",
		creatingLink: "creating space link..."
	},

	init: function(status) {
		if(errorhandler.handlers[status]) {
			errorhandler.handlers[status]();
		}
	},
	handlers: {
		404: function() {
			var domain = window.location.host.split(".");
			var path = window.location.pathname.substr(1, window.location.pathname.length); // remove first "/"
			var space = domain.length > 2 ? domain[0] : errorhandler.homespace;
			var container = $(".spaceSuggestions")[0];
			if(path) {
				var segments = path.split("/");
				var tiddler = segments[segments.length - 1];
				if(tiddler) { // currently only for for tiddler uris
					errorhandler.suggestTiddlers(container, space, tiddler);
				}
			} else {
				errorhandler.createSpaceLink($(".claim-space"), space);
				errorhandler.suggestSpaces(container, space);
			}
		}
	},
	createSpaceLink: function (container, name) {
		$(container).empty(errorhandler.locale.creatingLink);
		$.ajax({url: "/status", dataType: "json",
			success: function(status) {
				if(status.username && status.username != "GUEST") {
					var sh = status["server_host"];
					var newSpaceUri = sh.scheme + "://" + name + "." + sh.host;
					newSpaceUri = sh.port ? newSpaceUri + ":" + sh.port : newSpaceUri;
					var spaceCallback = function() {
						window.location = newSpaceUri;
					};
					$(container).empty();
					$("<input />").attr("type", "button").val(errorhandler.locale.claimSpace).click(function(ev) {
						var host = window.location.protocol + "//" + window.location.host;
						var space = new tiddlyweb.Space(name, host);
						space.create(spaceCallback, function() {
							alert(errorhandler.locale.errorCreateSpace);
						});
						ev.preventDefault();
					}).appendTo(container);
				}
			}
		});
	},
	areSimilar: function(x, y) {
		// TO DO: apply soundex algorithm?
		if(!x || !y) {
			return false;
		} else if(x.indexOf(y) > -1) {
			return true;
		} else if(y.indexOf(x) > -1) {
			return true;
		} else {
			return false;
		}
	},
	createTiddler: function(container, space, title) {
		$.ajax({url: "/status", dataType: "json",
			success: function(status) {
				if(status.username && status.username != "GUEST") {
					$("<h2 />").text(errorhandler.locale.makeTiddlerHeader).appendTo(container);
					container = $("<p />").appendTo(container)[0];
					$("<a />").attr("href", "takenote#tiddler/" + title).
						text("Create tiddler named '" + decodeURIComponent(title) + "'").appendTo(container);
				}
			}
		});
	},
	suggestTiddlers: function(container, space, title) {
		$(container).empty(errorhandler.locale.alternativeTiddlers);
		errorhandler.createTiddler(container, space, title);
		var uri = "/bags/" + space + "_public/tiddlers";
		$.ajax({url: uri, dataType: "text",
			success: function(txt) {
				var tiddlers = txt.split("\n");
				var suggestions = [];
				for(var i = 0; i < tiddlers.length; i++) {
					var thisTitle = tiddlers[i];
					if(errorhandler.areSimilar(title, thisTitle)) {
						suggestions.push(thisTitle);
					}
				}
				if(suggestions.length > 0) {
					$("<h2 />").text(errorhandler.locale.tiddlerSuggestionsHeader).appendTo(container);
					var list = $("<ol />").appendTo(container)[0];
					for(var i = 0; i < suggestions.length; i++) {
						var suggestion = suggestions[i];
						var item = $("<li />").appendTo(list);
						$("<a />").attr("href", "/" + suggestion).text(suggestion).appendTo(item);
					}
				}
			}
		});
	},
	suggestSpaces: function(container, space) {
		$(container).empty(errorhandler.locale.alternativeSpaces);
		$.ajax({url: "/spaces", dataType: "json",
			success: function(spaces) {
				var suggestions = [];
				for(var i = 0; i < spaces.length; i++) {
					var thisSpace = spaces[i];
					if(errorhandler.areSimilar(thisSpace.name, space)) {
						suggestions.push(thisSpace);
					}
				}
				$(container).empty();
				if(suggestions.length > 0) {
					$("<h2 />").text(errorhandler.locale.spaceSuggestionsHeader).appendTo(container);
					var list = $("<ol />").appendTo(container)[0];
					for(var i = 0; i < suggestions.length; i++) {
						var suggestion = suggestions[i];
						var item = $("<li />").appendTo(list);
						var avatar = suggestion.uri + "bags/" + suggestion.name + "_public/tiddlers/SiteIcon";
						$("<img />").attr("src", avatar).appendTo(item).css({width: 48, height: 48});
						$("<a />").attr("href", suggestion.uri).text(suggestion.name).appendTo(item);
					}
				}
			}
		});
	}
};
//}}}
<commit_msg>Refer to takenote by an absolute URL, otherwise the 404 message will then itself 404.<commit_after>/***
|''Name''|TiddlySpaceErrorHandlers|
|''Description''|Provides useful functionality for a given error message|
|''Version''|0.2.0|
***/
//{{{
var errorhandler = {
	homespace: "frontpage",
	locale: {
		errorCreateSpace: "error creating space.",
		makeTiddlerHeader: "Make Tiddler",
		tiddlerSuggestionsHeader: "Were you looking for one of these tiddlers...?",
		spaceSuggestionsHeader: "Were you looking for one of these spaces...?",
		claimSpace: "create space with this name",
		alternativeTiddlers: "looking for alternative tiddlers...",
		alternativeSpaces: "looking for alternative spaces...",
		creatingLink: "creating space link..."
	},

	init: function(status) {
		if(errorhandler.handlers[status]) {
			errorhandler.handlers[status]();
		}
	},
	handlers: {
		404: function() {
			var domain = window.location.host.split(".");
			var path = window.location.pathname.substr(1, window.location.pathname.length); // remove first "/"
			var space = domain.length > 2 ? domain[0] : errorhandler.homespace;
			var container = $(".spaceSuggestions")[0];
			if(path) {
				var segments = path.split("/");
				var tiddler = segments[segments.length - 1];
				if(tiddler) { // currently only for for tiddler uris
					errorhandler.suggestTiddlers(container, space, tiddler);
				}
			} else {
				errorhandler.createSpaceLink($(".claim-space"), space);
				errorhandler.suggestSpaces(container, space);
			}
		}
	},
	createSpaceLink: function (container, name) {
		$(container).empty(errorhandler.locale.creatingLink);
		$.ajax({url: "/status", dataType: "json",
			success: function(status) {
				if(status.username && status.username != "GUEST") {
					var sh = status["server_host"];
					var newSpaceUri = sh.scheme + "://" + name + "." + sh.host;
					newSpaceUri = sh.port ? newSpaceUri + ":" + sh.port : newSpaceUri;
					var spaceCallback = function() {
						window.location = newSpaceUri;
					};
					$(container).empty();
					$("<input />").attr("type", "button").val(errorhandler.locale.claimSpace).click(function(ev) {
						var host = window.location.protocol + "//" + window.location.host;
						var space = new tiddlyweb.Space(name, host);
						space.create(spaceCallback, function() {
							alert(errorhandler.locale.errorCreateSpace);
						});
						ev.preventDefault();
					}).appendTo(container);
				}
			}
		});
	},
	areSimilar: function(x, y) {
		// TO DO: apply soundex algorithm?
		if(!x || !y) {
			return false;
		} else if(x.indexOf(y) > -1) {
			return true;
		} else if(y.indexOf(x) > -1) {
			return true;
		} else {
			return false;
		}
	},
	createTiddler: function(container, space, title) {
		$.ajax({url: "/status", dataType: "json",
			success: function(status) {
				if(status.username && status.username != "GUEST") {
					$("<h2 />").text(errorhandler.locale.makeTiddlerHeader).appendTo(container);
					container = $("<p />").appendTo(container)[0];
					$("<a />").attr("href", "/takenote#tiddler/" + title).
						text("Create tiddler named '" + decodeURIComponent(title) + "'").appendTo(container);
				}
			}
		});
	},
	suggestTiddlers: function(container, space, title) {
		$(container).empty(errorhandler.locale.alternativeTiddlers);
		errorhandler.createTiddler(container, space, title);
		var uri = "/bags/" + space + "_public/tiddlers";
		$.ajax({url: uri, dataType: "text",
			success: function(txt) {
				var tiddlers = txt.split("\n");
				var suggestions = [];
				for(var i = 0; i < tiddlers.length; i++) {
					var thisTitle = tiddlers[i];
					if(errorhandler.areSimilar(title, thisTitle)) {
						suggestions.push(thisTitle);
					}
				}
				if(suggestions.length > 0) {
					$("<h2 />").text(errorhandler.locale.tiddlerSuggestionsHeader).appendTo(container);
					var list = $("<ol />").appendTo(container)[0];
					for(var i = 0; i < suggestions.length; i++) {
						var suggestion = suggestions[i];
						var item = $("<li />").appendTo(list);
						$("<a />").attr("href", "/" + suggestion).text(suggestion).appendTo(item);
					}
				}
			}
		});
	},
	suggestSpaces: function(container, space) {
		$(container).empty(errorhandler.locale.alternativeSpaces);
		$.ajax({url: "/spaces", dataType: "json",
			success: function(spaces) {
				var suggestions = [];
				for(var i = 0; i < spaces.length; i++) {
					var thisSpace = spaces[i];
					if(errorhandler.areSimilar(thisSpace.name, space)) {
						suggestions.push(thisSpace);
					}
				}
				$(container).empty();
				if(suggestions.length > 0) {
					$("<h2 />").text(errorhandler.locale.spaceSuggestionsHeader).appendTo(container);
					var list = $("<ol />").appendTo(container)[0];
					for(var i = 0; i < suggestions.length; i++) {
						var suggestion = suggestions[i];
						var item = $("<li />").appendTo(list);
						var avatar = suggestion.uri + "bags/" + suggestion.name + "_public/tiddlers/SiteIcon";
						$("<img />").attr("src", avatar).appendTo(item).css({width: 48, height: 48});
						$("<a />").attr("href", suggestion.uri).text(suggestion.name).appendTo(item);
					}
				}
			}
		});
	}
};
//}}}
<|endoftext|>


<commit_before>function xkcdSubstitutions(){
	var words = [
		{find: new RegExp('\\bwitnesses\\b', 'gi'), replace: 'these dudes I know'},
		{find: new RegExp('\\ballegedly\\b', 'gi'), replace: 'kinda probably'},
		{find: new RegExp('\\bnew study\\b', 'gi'), replace: 'tumblr post'},
		{find: new RegExp('\\brebuild\\b', 'gi'), replace: 'avenge'},
		{find: new RegExp('\\bspace\\b', 'gi'), replace: 'spaaace'},
		{find: new RegExp('\\bgoogle glass\\b', 'gi'), replace: 'virtual boy'},
		{find: new RegExp('\\bsmartphone\\b', 'gi'), replace: 'Pokédex'},
		{find: new RegExp('\\belectric\\b', 'gi'), replace: 'atomic'},
		{find: new RegExp('\\bsenator\\b', 'gi'), replace: 'elf-lord'},
		{find: new RegExp('\\bcar\\b', 'gi'), replace: 'cat'},
		{find: new RegExp('\\belection\\b', 'gi'), replace: 'eating contest'},
		{find: new RegExp('\\bcongressional leaders\\b', 'gi'), replace: 'river spirits'},
		{find: new RegExp('\\bhomeland security\\b', 'gi'), replace: 'homestar runner'},
		{find: new RegExp('\\bcould not be reached for comment\\b', 'gi'), replace: 'is guilty and everyone knows it'},
        {find: new RegExp('\\bdebate\\b', 'gi'), replace: 'dance-off'},
        {find: new RegExp('\\bself driving\\b', 'gi'), replace: 'uncontrollably swerving'},
        {find: new RegExp('\\bpoll\\b', 'gi'), replace: 'psychic reading'},
        {find: new RegExp('\\bcandidate\\b', 'gi'), replace: 'airbender'},
        {find: new RegExp('\\bdrone\\b', 'gi'), replace: 'dog'},
        {find: new RegExp('\\bvows to\\b', 'gi'), replace: 'probably won\'t'},
        {find: new RegExp('\\bat large\\b', 'gi'), replace: 'very large'},
        {find: new RegExp('\\bsuccessfully\\b', 'gi'), replace: 'suddenly'},
        {find: new RegExp('\\bexpands\\b', 'gi'), replace: 'physically expands'},
        {find: new RegExp('\\b(first|second|third)-degree\\b', 'gi'), replace: 'friggin\' awful'},
        {find: new RegExp('\\ban unknown number\\b', 'gi'), replace: 'like hundreds'},
        {find: new RegExp('\\bfront runner\\b', 'gi'), replace: 'blade runner'},
        {find: new RegExp('\\bglobal\\b', 'gi'), replace: 'spherical'},
        {find: new RegExp('\\byears\\b', 'gi'), replace: 'minutes'},
        {find: new RegExp('\\bminutes\\b', 'gi'), replace: 'years'},
        {find: new RegExp('\\bno indication\\b', 'gi'), replace: 'lots of signs'},
        {find: new RegExp('\\burged restraint by\\b', 'gi'), replace: 'drunkenly egged on'},
        {find: new RegExp('\\bhorsepower\\b', 'gi'), replace: 'tons of horsemeat '},
	];

	var html = document.body.innerHTML;
	for (var i = 0; i < words.length; i++) {
		html = html.replace(words[i].find, words[i].replace);
	}

	return html;
}

document.body.innerHTML=xkcdSubstitutions();
<commit_msg>Inserted real tabs<commit_after>function xkcdSubstitutions(){
	var words = [
		{find: new RegExp('\\bwitnesses\\b', 'gi'), replace: 'these dudes I know'},
		{find: new RegExp('\\ballegedly\\b', 'gi'), replace: 'kinda probably'},
		{find: new RegExp('\\bnew study\\b', 'gi'), replace: 'tumblr post'},
		{find: new RegExp('\\brebuild\\b', 'gi'), replace: 'avenge'},
		{find: new RegExp('\\bspace\\b', 'gi'), replace: 'spaaace'},
		{find: new RegExp('\\bgoogle glass\\b', 'gi'), replace: 'virtual boy'},
		{find: new RegExp('\\bsmartphone\\b', 'gi'), replace: 'Pokédex'},
		{find: new RegExp('\\belectric\\b', 'gi'), replace: 'atomic'},
		{find: new RegExp('\\bsenator\\b', 'gi'), replace: 'elf-lord'},
		{find: new RegExp('\\bcar\\b', 'gi'), replace: 'cat'},
		{find: new RegExp('\\belection\\b', 'gi'), replace: 'eating contest'},
		{find: new RegExp('\\bcongressional leaders\\b', 'gi'), replace: 'river spirits'},
		{find: new RegExp('\\bhomeland security\\b', 'gi'), replace: 'homestar runner'},
		{find: new RegExp('\\bcould not be reached for comment\\b', 'gi'), replace: 'is guilty and everyone knows it'},
		{find: new RegExp('\\bdebate\\b', 'gi'), replace: 'dance-off'},
		{find: new RegExp('\\bself driving\\b', 'gi'), replace: 'uncontrollably swerving'},
		{find: new RegExp('\\bpoll\\b', 'gi'), replace: 'psychic reading'},
		{find: new RegExp('\\bcandidate\\b', 'gi'), replace: 'airbender'},
		{find: new RegExp('\\bdrone\\b', 'gi'), replace: 'dog'},
		{find: new RegExp('\\bvows to\\b', 'gi'), replace: 'probably won\'t'},
		{find: new RegExp('\\bat large\\b', 'gi'), replace: 'very large'},
		{find: new RegExp('\\bsuccessfully\\b', 'gi'), replace: 'suddenly'},
		{find: new RegExp('\\bexpands\\b', 'gi'), replace: 'physically expands'},
		{find: new RegExp('\\b(first|second|third)-degree\\b', 'gi'), replace: 'friggin\' awful'},
		{find: new RegExp('\\ban unknown number\\b', 'gi'), replace: 'like hundreds'},
		{find: new RegExp('\\bfront runner\\b', 'gi'), replace: 'blade runner'},
		{find: new RegExp('\\bglobal\\b', 'gi'), replace: 'spherical'},
		{find: new RegExp('\\byears\\b', 'gi'), replace: 'minutes'},
		{find: new RegExp('\\bminutes\\b', 'gi'), replace: 'years'},
		{find: new RegExp('\\bno indication\\b', 'gi'), replace: 'lots of signs'},
		{find: new RegExp('\\burged restraint by\\b', 'gi'), replace: 'drunkenly egged on'},
		{find: new RegExp('\\bhorsepower\\b', 'gi'), replace: 'tons of horsemeat '},
	];

	var html = document.body.innerHTML;
	for (var i = 0; i < words.length; i++) {
		html = html.replace(words[i].find, words[i].replace);
	}

	return html;
}

document.body.innerHTML=xkcdSubstitutions();
// vim: noet
<|endoftext|>


<commit_before>document.getElementById("v1").innerHTML = "v2.28";
var transformCanvas = document.getElementById('transformCanv');
transformContext = transformCanvas.getContext('2d');
tilesContext = document.getElementById("tileCanv").getContext('2d');
originalPhotoContext = document.getElementById("originalCanv").getContext('2d');

var linesCanvas = document.getElementById('linesCanv');
linesContext = linesCanvas.getContext('2d');
linesContext.fillStyle = "blue";
//tilesContext.fillStyle = "green";
//tilesContext.fillRect(0, 0, linesCanvas.width, linesCanvas.height);
linesContext.fillRect(0, 0, linesCanvas.width, linesCanvas.height);

base_image = new Image();
base_image.src = 'sudoku.png';
base_image.onload = on_load_image;

//---------------------------------------------------------------
function rgb_to_gray(rgb_array)
{
    return 0.299 * rgb_array[0] + 0.587 * rgb_array[1] + 0.114 * rgb_array[2];
}
//---------------------------------------------------------------
function on_load_image()
{
	transformContext.drawImage(base_image, 0, 0);
	originalPhotoContext.drawImage(base_image,0,0);
	var image = transformContext.getImageData(1, 1, 400, 400);
	var data = image.data;
	// for(var i = 0;i<data.length;i+=4){
	// 	var red = data[i];
	// 	var green = data[i+1];
	// 	var blue = data[i+2];

	// 	if(red>240&&green>240&&blue>240){
	// 		data[i] = 255;
	// 		data[i+1] = 255;
	// 		data[i+2] = 255;
	// 	} else {
	// 		data[i] = 0;
	// 		data[i+1] = 0;
	// 		data[i+2] = 0;
	// 	}
	// }
	// transformContext.putImageData(image,0,0);

	var imageData = CannyJS.canny(transformCanvas);
	imageData.drawOn(transformCanv);

	var diagonala = parseInt(Math.sqrt(transformCanvas.height * transformCanvas.height + transformCanvas.width * transformCanvas.width) + 1);

	var accumulator= new Array();

	for (var i=0; i < diagonala; i++){
		accumulator[i] = new Array(180);
	}

	for (var raza = 0; raza < diagonala; raza++){
		for (var theta = 0; theta < 180; theta++){
			accumulator[raza][theta] = 0;
		}
	}

	for (var y = 0; y < transformCanvas.height; y++){
		for (var x = 0; x < transformCanvas.width; x++){
			var culoare = transformContext.getImageData(x, y, 1, 1);
			var data = culoare.data;
			// console.log(data.length);
			if (data[0] > 250 && data[1] > 250 && data[2] > 250){
				for(var theta = 0; theta < 180; theta++){
					var raza = parseInt((x - transformCanvas.width / 2) * Math.cos(theta / 180 * 3.14) + (y - transformCanvas.height / 2) * Math.sin(theta / 180 * 3.14));
					accumulator[raza + diagonala / 2][theta]++;
					// console.log(r+diagonala/2);
				}
			}

		}
	}

	var maxacc = 0;
	for (var r = 0; r < diagonala; r++){
		for (var theta = 0; theta < 180; theta++){
			if (maxacc < accumulator[r][theta]){
				maxacc = accumulator[r][theta];
			}
		}
	}

	// scalez
	for (var r = 0; r < diagonala; r++){
		for (var theta = 0; theta < 180; theta++){
			accumulator[r][theta] = parseInt(accumulator[r][theta] / maxacc * 255);
		}
	}

	//teste verific ce valori am in accumulator.
	// var count = 0;
	// var arrayiu = new Array;
	// for(var i=0;i<diagonala;i++){
	// 	for(var j=0;j<180;j++){
	// 		// arrayiu.push(accumulator[i][j]);
	// 		// console.log(accumulator[i][j]);
	// 	}
	// }

	// niste verificari
	// var uniquearray = [];
	// $.each(arrayiu, function(i,el){
	// 	if($.inArray(el,uniquearray)===-1) uniquearray.push(el);
	// });
	// console.log(uniquearray.sort());

	var vertical = new Array;
	var horizontal = new Array

	var prag = 100;

	var xss=0;
	var yss=0;

	var actualX = new Array;
	var actualY = new Array;

	linesContext.beginPath();
	linesContext.strokeStyle="#FF0000";

	for (var raza = 0; raza < diagonala; raza++){
		for (var theta = 0; theta < 180; theta++){
			if(accumulator[raza][theta] > prag){

				var x1, y1, x2, y2, test2;

				if(theta != 0){
					x1 = 0;
					y1 = Math.floor((raza - diagonala / 2 - (x1 - linesCanvas.width / 2) * Math.cos(theta / 180.0 * 3.14)) / Math.sin(theta / 180.0 * 3.14) + linesCanvas.height / 2);
					if (yss == 0 || yss > 0 && y1 - actualY[yss - 1] > 7){
						actualY[yss] = y1;
						yss++;
					}
					else
						actualY[yss - 1] = y1;
				}
				else {
					x1 = (raza - diagonala / 2) + linesCanvas.width / 2;
					if (xss == 0 || xss > 0 && x1 - actualX[xss - 1] > 7){
						actualX[xss] = x1;
						xss++;
					}
					else
						actualX[xss - 1] = x1;
					y1 = 0;
				}

				if(theta != 0){
					x2 = linesCanvas.width -1;
					y2 = Math.floor((raza - diagonala/2 - (x2 - linesCanvas.width / 2) * Math.cos(theta / 180.0*3.14)) / Math.sin(theta / 180.0*3.14) + linesCanvas.height / 2);
				}
				else {
					x2 = (raza - diagonala / 2) + linesCanvas.width / 2;
					y2 = linesCanvas.height -1;
				}

				linesContext.moveTo(x1, y1);
				linesContext.lineTo(x2, y2);

			}
		}
	}

	linesContext.stroke();

	console.log(actualY);
	console.log(actualX);

	var safety_margin = 6; // ignore pixels closer to margin than this value
	var estimate_cell_size = actualX[1] - actualX[0];

	// create matrix for ANN
	var digit_as_28x28_matrix = [];
	for (var i = 0; i < 28; i++)
		for (var j = 0; j < 28; j++)
			digit_as_28x28_matrix[i * 28 + j] = 0; // fill it with 0

	// take each cell,
	for (var cell_row = 0; cell_row < 9; cell_row++){
		for (var cell_col = 0; cell_col < 9; cell_col++){
			var imgData = originalPhotoContext.getImageData( actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin, estimate_cell_size - 2 * safety_margin, estimate_cell_size - 2 * safety_margin);
			// compute bounding box of digit
			var bbox = {min_row: estimate_cell_size - 2 * safety_margin, min_col: estimate_cell_size - 2 * safety_margin, max_row:0, max_col: 0};
			for (var row = 0; row < estimate_cell_size - 2 * safety_margin; row++)
				for (var col = 0; col < estimate_cell_size - 2 * safety_margin; col++){
					var pixel_color = originalPhotoContext.getImageData(actualX[cell_col] + safety_margin + col, actualY[cell_row] + safety_margin + row, 1, 1);
					if (pixel_color.data[0] < 100 && pixel_color.data[1] < 100 && pixel_color.data[2] < 100){ // black
						if (bbox.min_row > row)
							bbox.min_row = row;
						else
						if (bbox.max_row < row)
							bbox.max_row = row;

						if (bbox.min_col > col)
							bbox.min_col = col;
						else
						if (bbox.max_col < col)
							bbox.max_col = col;
					}
				}
				if (bbox.min_col < bbox.max_col && bbox.min_row < bbox.max_row){// I have a digit there
					// I have the bounding box; now I have to scale the box to 20x20 as in MNIST
					//var imageData = new ImageData(28, 28);

					for (var row = 0; row < 20; row++)
						for (var col = 0; col < 20; col++){
							var original_row = row / 19.0 * (bbox.max_row - bbox.min_row);
							var original_col = col / 19.0 * (bbox.max_col - bbox.min_col);
							var pixel_data = originalPhotoContext.getImageData(actualX[cell_col] + safety_margin + bbox.min_col + original_col, actualY[cell_row] + safety_margin + bbox.min_row + original_row, 1, 1); // I do not like this
							digit_as_28x28_matrix[(row + 4) * 28 + col + 4] = rgb_to_gray(pixel_data.data) / 255.0;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 1] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 2] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 3] = 255;
						}

					// send it to ANN
					var out_last_layer = [];
					var class_index = test_ann(digit_as_28x28_matrix, out_last_layer);
					tilesContext.font = '20px serif';
					tilesContext.strokeText(class_index.toString(), actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin);
					//tilesContext.putImageData(imageData, actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin);
				}
		}
	}
}
<commit_msg>add recognized digits<commit_after>document.getElementById("v1").innerHTML = "v2.29";
var transformCanvas = document.getElementById('transformCanv');
transformContext = transformCanvas.getContext('2d');
tilesContext = document.getElementById("tileCanv").getContext('2d');
originalPhotoContext = document.getElementById("originalCanv").getContext('2d');

var linesCanvas = document.getElementById('linesCanv');
linesContext = linesCanvas.getContext('2d');
linesContext.fillStyle = "blue";
//tilesContext.fillStyle = "green";
//tilesContext.fillRect(0, 0, linesCanvas.width, linesCanvas.height);
linesContext.fillRect(0, 0, linesCanvas.width, linesCanvas.height);

base_image = new Image();
base_image.src = 'sudoku.png';
base_image.onload = on_load_image;

//---------------------------------------------------------------
function rgb_to_gray(rgb_array)
{
    return 0.299 * rgb_array[0] + 0.587 * rgb_array[1] + 0.114 * rgb_array[2];
}
//---------------------------------------------------------------
function on_load_image()
{
	transformContext.drawImage(base_image, 0, 0);
	originalPhotoContext.drawImage(base_image,0,0);
	var image = transformContext.getImageData(1, 1, 400, 400);
	var data = image.data;
	// for(var i = 0;i<data.length;i+=4){
	// 	var red = data[i];
	// 	var green = data[i+1];
	// 	var blue = data[i+2];

	// 	if(red>240&&green>240&&blue>240){
	// 		data[i] = 255;
	// 		data[i+1] = 255;
	// 		data[i+2] = 255;
	// 	} else {
	// 		data[i] = 0;
	// 		data[i+1] = 0;
	// 		data[i+2] = 0;
	// 	}
	// }
	// transformContext.putImageData(image,0,0);

	var imageData = CannyJS.canny(transformCanvas);
	imageData.drawOn(transformCanv);

	var diagonala = parseInt(Math.sqrt(transformCanvas.height * transformCanvas.height + transformCanvas.width * transformCanvas.width) + 1);

	var accumulator= new Array();

	for (var i=0; i < diagonala; i++){
		accumulator[i] = new Array(180);
	}

	for (var raza = 0; raza < diagonala; raza++){
		for (var theta = 0; theta < 180; theta++){
			accumulator[raza][theta] = 0;
		}
	}

	for (var y = 0; y < transformCanvas.height; y++){
		for (var x = 0; x < transformCanvas.width; x++){
			var culoare = transformContext.getImageData(x, y, 1, 1);
			var data = culoare.data;
			// console.log(data.length);
			if (data[0] > 250 && data[1] > 250 && data[2] > 250){
				for(var theta = 0; theta < 180; theta++){
					var raza = parseInt((x - transformCanvas.width / 2) * Math.cos(theta / 180 * 3.14) + (y - transformCanvas.height / 2) * Math.sin(theta / 180 * 3.14));
					accumulator[raza + diagonala / 2][theta]++;
					// console.log(r+diagonala/2);
				}
			}

		}
	}

	var maxacc = 0;
	for (var r = 0; r < diagonala; r++){
		for (var theta = 0; theta < 180; theta++){
			if (maxacc < accumulator[r][theta]){
				maxacc = accumulator[r][theta];
			}
		}
	}

	// scalez
	for (var r = 0; r < diagonala; r++){
		for (var theta = 0; theta < 180; theta++){
			accumulator[r][theta] = parseInt(accumulator[r][theta] / maxacc * 255);
		}
	}

	//teste verific ce valori am in accumulator.
	// var count = 0;
	// var arrayiu = new Array;
	// for(var i=0;i<diagonala;i++){
	// 	for(var j=0;j<180;j++){
	// 		// arrayiu.push(accumulator[i][j]);
	// 		// console.log(accumulator[i][j]);
	// 	}
	// }

	// niste verificari
	// var uniquearray = [];
	// $.each(arrayiu, function(i,el){
	// 	if($.inArray(el,uniquearray)===-1) uniquearray.push(el);
	// });
	// console.log(uniquearray.sort());

	var vertical = new Array;
	var horizontal = new Array

	var prag = 100;

	var xss=0;
	var yss=0;

	var actualX = new Array;
	var actualY = new Array;

	linesContext.beginPath();
	linesContext.strokeStyle="#FF0000";

	for (var raza = 0; raza < diagonala; raza++){
		for (var theta = 0; theta < 180; theta++){
			if(accumulator[raza][theta] > prag){

				var x1, y1, x2, y2, test2;

				if(theta != 0){
					x1 = 0;
					y1 = Math.floor((raza - diagonala / 2 - (x1 - linesCanvas.width / 2) * Math.cos(theta / 180.0 * 3.14)) / Math.sin(theta / 180.0 * 3.14) + linesCanvas.height / 2);
					if (yss == 0 || yss > 0 && y1 - actualY[yss - 1] > 7){
						actualY[yss] = y1;
						yss++;
					}
					else
						actualY[yss - 1] = y1;
				}
				else {
					x1 = (raza - diagonala / 2) + linesCanvas.width / 2;
					if (xss == 0 || xss > 0 && x1 - actualX[xss - 1] > 7){
						actualX[xss] = x1;
						xss++;
					}
					else
						actualX[xss - 1] = x1;
					y1 = 0;
				}

				if(theta != 0){
					x2 = linesCanvas.width -1;
					y2 = Math.floor((raza - diagonala/2 - (x2 - linesCanvas.width / 2) * Math.cos(theta / 180.0*3.14)) / Math.sin(theta / 180.0*3.14) + linesCanvas.height / 2);
				}
				else {
					x2 = (raza - diagonala / 2) + linesCanvas.width / 2;
					y2 = linesCanvas.height -1;
				}

				linesContext.moveTo(x1, y1);
				linesContext.lineTo(x2, y2);

			}
		}
	}

	linesContext.stroke();

	console.log(actualY);
	console.log(actualX);

	var safety_margin = 6; // ignore pixels closer to margin than this value
	var estimate_cell_size = actualX[1] - actualX[0];

	// create matrix for ANN
	var digit_as_28x28_matrix = [];
	for (var i = 0; i < 28; i++)
		for (var j = 0; j < 28; j++)
			digit_as_28x28_matrix[i * 28 + j] = 0; // fill it with 0

	var recognized_digits = [];
	for (var i = 0; i < 9; i++)
		recognized_digits[i] = new Array(9);

	// take each cell,
	for (var cell_row = 0; cell_row < 9; cell_row++){
		for (var cell_col = 0; cell_col < 9; cell_col++){
			var imgData = originalPhotoContext.getImageData( actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin, estimate_cell_size - 2 * safety_margin, estimate_cell_size - 2 * safety_margin);
			// compute bounding box of digit
			var bbox = {min_row: estimate_cell_size - 2 * safety_margin, min_col: estimate_cell_size - 2 * safety_margin, max_row:0, max_col: 0};
			for (var row = 0; row < estimate_cell_size - 2 * safety_margin; row++)
				for (var col = 0; col < estimate_cell_size - 2 * safety_margin; col++){
					var pixel_color = originalPhotoContext.getImageData(actualX[cell_col] + safety_margin + col, actualY[cell_row] + safety_margin + row, 1, 1);
					if (pixel_color.data[0] < 100 && pixel_color.data[1] < 100 && pixel_color.data[2] < 100){ // black
						if (bbox.min_row > row)
							bbox.min_row = row;
						else
						if (bbox.max_row < row)
							bbox.max_row = row;

						if (bbox.min_col > col)
							bbox.min_col = col;
						else
						if (bbox.max_col < col)
							bbox.max_col = col;
					}
				}
				if (bbox.min_col < bbox.max_col && bbox.min_row < bbox.max_row){// I have a digit there
					// I have the bounding box; now I have to scale the box to 20x20 as in MNIST
					//var imageData = new ImageData(28, 28);

					for (var row = 0; row < 20; row++)
						for (var col = 0; col < 20; col++){
							var original_row = row / 19.0 * (bbox.max_row - bbox.min_row);
							var original_col = col / 19.0 * (bbox.max_col - bbox.min_col);
							var pixel_data = originalPhotoContext.getImageData(actualX[cell_col] + safety_margin + bbox.min_col + original_col, actualY[cell_row] + safety_margin + bbox.min_row + original_row, 1, 1); // I do not like this
							digit_as_28x28_matrix[(row + 4) * 28 + col + 4] = rgb_to_gray(pixel_data.data) / 255.0;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 1] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 2] = digit_as_28x28_matrix[(row + 4) * 28 + col + 4] * 255;
							//imageData.data[(row + 4) * 28 * 4 + (col + 4) * 4 + 3] = 255;
						}

					// send it to ANN
					var out_last_layer = [];
					var class_index = test_ann(digit_as_28x28_matrix, out_last_layer);
					recognized_digits[cell_row][cell_col] = class_index;
					tilesContext.font = '20px serif';
					tilesContext.strokeText(class_index.toString(), actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin);

					//tilesContext.putImageData(imageData, actualX[cell_col] + safety_margin, actualY[cell_row] + safety_margin);
				}
				else// no digit found there
				recognized_digits[cell_row][cell_col] = -1;
		}
	}
}
<|endoftext|>


<commit_before>var core = require('../core'),
    DisplayObject = core.DisplayObject,
    _tempMatrix = new core.Matrix();

DisplayObject.prototype._cacheAsBitmap = false;
DisplayObject.prototype._cacheData = false;

// figured theres no point adding ALL the extra variables to prototype.
// this model can hold the information needed. This can also be generated on demand as
// most objects are not cached as bitmaps.
var CacheData = function(){

    this.originalRenderWebGL = null;
    this.originalRenderCanvas = null;

    this.originalUpdateTransform = null;
    this.originalHitTest = null;
    this.originalDestroy = null;
    this.originalMask = null;
    this.originalFilterArea = null;
    this.sprite = null;
};

Object.defineProperties(DisplayObject.prototype, {

    /**
     * Set this to true if you want this display object to be cached as a bitmap.
     * This basically takes a snap shot of the display object as it is at that moment. It can provide a performance benefit for complex static displayObjects.
     * To remove simply set this property to 'false'
     *
     * @member {boolean}
     * @memberof PIXI.DisplayObject#
     */
    cacheAsBitmap: {
        get: function ()
        {
            return this._cacheAsBitmap;
        },
        set: function (value)
        {
            if (this._cacheAsBitmap === value)
            {
                return;
            }

            this._cacheAsBitmap = value;

            var data;

            if (value)
            {

                if(!this._cacheData)
                {
                    this._cacheData = new CacheData();
                }

                data = this._cacheData;

                data.originalRenderWebGL = this.renderWebGL;
                data.originalRenderCanvas = this.renderCanvas;

                data.originalUpdateTransform = this.updateTransform;
                data.originalGetBounds = this.getBounds;

                data.originalDestroy = this.destroy;

                data.originalContainsPoint = this.containsPoint;

                data.originalMask = this._mask;
                data.originalFilterArea = this.filterArea;

                this.renderWebGL = this._renderCachedWebGL;
                this.renderCanvas = this._renderCachedCanvas;

                this.destroy = this._cacheAsBitmapDestroy;

            }
            else
            {
                data = this._cacheData;

                if (data.sprite)
                {
                    this._destroyCachedDisplayObject();
                }

                this.renderWebGL = data.originalRenderWebGL;
                this.renderCanvas = data.originalRenderCanvas;
                this.getBounds = data.originalGetBounds;

                this.destroy = data.originalDestroy;

                this.updateTransform = data.originalUpdateTransform;
                this.containsPoint = data.originalContainsPoint;

                this._mask = data.originalMask;
                this.filterArea = data.originalFilterArea;
            }
        }
    }
});
/**
* Renders a cached version of the sprite with WebGL
*
* @param renderer {PIXI.WebGLRenderer} the WebGL renderer
* @private
*/
DisplayObject.prototype._renderCachedWebGL = function (renderer)
{
    if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
    {
        return;
    }

    this._initCachedDisplayObject( renderer );

    this._cacheData.sprite._transformID = -1;
    this._cacheData.sprite.worldAlpha = this.worldAlpha;
    this._cacheData.sprite._renderWebGL(renderer);
};

/**
* Prepares the WebGL renderer to cache the sprite
*
* @param renderer {PIXI.WebGLRenderer} the WebGL renderer
* @private
*/
DisplayObject.prototype._initCachedDisplayObject = function (renderer)
{
    if(this._cacheData && this._cacheData.sprite)
    {
        return;
    }

    // first we flush anything left in the renderer (otherwise it would get rendered to the cached texture)
    renderer.currentRenderer.flush();
    //this.filters= [];
    // next we find the dimensions of the untransformed object
    // this function also calls updatetransform on all its children as part of the measuring. This means we don't need to update the transform again in this function
    // TODO pass an object to clone too? saves having to create a new one each time!
    var bounds = this.getLocalBounds().clone();

    // add some padding!
    if(this._filters)
    {
        var padding = this._filters[0].padding;
        bounds.x -= padding;
        bounds.y -= padding;

        bounds.width += padding * 2;
        bounds.height += padding * 2;
    }

    // for now we cache the current renderTarget that the webGL renderer is currently using.
    // this could be more elegent..
    var cachedRenderTarget = renderer._activeRenderTarget;
    // We also store the filter stack - I will definitely look to change how this works a little later down the line.
    var stack = renderer.filterManager.filterStack;

    // this renderTexture will be used to store the cached DisplayObject

    var renderTexture = core.RenderTexture.create(bounds.width | 0, bounds.height | 0);

    // need to set //
    var m = _tempMatrix;
    m.tx = -bounds.x;
    m.ty = -bounds.y;

    // reset
    this.transform.worldTransform.identity();

    // set all properties to there original so we can render to a texture
    this.renderWebGL = this._cacheData.originalRenderWebGL;

    renderer.render(this, renderTexture, true, m, true);
    // now restore the state be setting the new properties

    renderer.bindRenderTarget(cachedRenderTarget);

    renderer.filterManager.filterStack = stack;

    this.renderWebGL     = this._renderCachedWebGL;
    this.updateTransform = this.displayObjectUpdateTransform;
    this.getBounds       = this._getCachedBounds;

    this._mask = null;
    this.filterArea = null;

    // create our cached sprite
    var cachedSprite = new core.Sprite(renderTexture);
    cachedSprite.transform.worldTransform = this.transform.worldTransform;
    cachedSprite.anchor.x = -( bounds.x / bounds.width );
    cachedSprite.anchor.y = -( bounds.y / bounds.height );

    this._cacheData.sprite = cachedSprite;

    this.transform._parentID = -1;
    // restore the transform of the cached sprite to avoid the nasty flicker..
    this.updateTransform();

    // map the hit test..
    this.containsPoint = cachedSprite.containsPoint.bind(cachedSprite);
};

/**
* Renders a cached version of the sprite with canvas
*
* @param renderer {PIXI.CanvasRenderer} the Canvas renderer
* @private
*/
DisplayObject.prototype._renderCachedCanvas = function (renderer)
{
    if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
    {
        return;
    }

    this._initCachedDisplayObjectCanvas( renderer );

    this._cacheData.sprite.worldAlpha = this.worldAlpha;

    this._cacheData.sprite.renderCanvas(renderer);
};

//TODO this can be the same as the webGL verison.. will need to do a little tweaking first though..
/**
* Prepares the Canvas renderer to cache the sprite
*
* @param renderer {PIXI.CanvasRenderer} the Canvas renderer
* @private
*/
DisplayObject.prototype._initCachedDisplayObjectCanvas = function (renderer)
{
    if(this._cacheData && this._cacheData.sprite)
    {
        return;
    }

    //get bounds actually transforms the object for us already!
    var bounds = this.getLocalBounds();

    var cachedRenderTarget = renderer.context;

    var renderTexture = new core.RenderTexture.create(bounds.width | 0, bounds.height | 0);

    // need to set //
    var m = _tempMatrix;
    this.transform.worldTransform.copy(m);
    m.invert();

    m.tx -= bounds.x;
    m.ty -= bounds.y;

    //m.append(this.transform.worldTransform.)
     // set all properties to there original so we can render to a texture
    this.renderCanvas = this._cacheData.originalRenderCanvas;

    //renderTexture.render(this, m, true);
    renderer.render(this, renderTexture, true, m, false);

    // now restore the state be setting the new properties
    renderer.context = cachedRenderTarget;

    this.renderCanvas = this._renderCachedCanvas;
    this.updateTransform = this.displayObjectUpdateTransform;
    this.getBounds  = this._getCachedBounds;

    this._mask = null;
    this.filterArea = null;

    // create our cached sprite
    var cachedSprite = new core.Sprite(renderTexture);
    cachedSprite.transform.worldTransform = this.transform.worldTransform;
    cachedSprite.anchor.x = -( bounds.x / bounds.width );
    cachedSprite.anchor.y = -( bounds.y / bounds.height );

    this.updateTransform();

    this._cacheData.sprite = cachedSprite;

    this.containsPoint = cachedSprite.containsPoint.bind(cachedSprite);
};

/**
* Calculates the bounds of the cached sprite
*
* @private
*/
DisplayObject.prototype._getCachedBounds = function ()
{
    this._cacheData.sprite._currentBounds = null;

    return this._cacheData.sprite.getBounds();
};

/**
* Destroys the cached sprite.
*
* @private
*/
DisplayObject.prototype._destroyCachedDisplayObject = function ()
{
    this._cacheData.sprite._texture.destroy(true);
    this._cacheData.sprite = null;
};

DisplayObject.prototype._cacheAsBitmapDestroy = function ()
{
    this.cacheAsBitmap = false;
    this.destroy();
};
<commit_msg>fixes #2883<commit_after>var core = require('../core'),
    DisplayObject = core.DisplayObject,
    _tempMatrix = new core.Matrix();

DisplayObject.prototype._cacheAsBitmap = false;
DisplayObject.prototype._cacheData = false;

// figured theres no point adding ALL the extra variables to prototype.
// this model can hold the information needed. This can also be generated on demand as
// most objects are not cached as bitmaps.
var CacheData = function(){

    this.originalRenderWebGL = null;
    this.originalRenderCanvas = null;

    this.originalUpdateTransform = null;
    this.originalHitTest = null;
    this.originalDestroy = null;
    this.originalMask = null;
    this.originalFilterArea = null;
    this.sprite = null;
};

Object.defineProperties(DisplayObject.prototype, {

    /**
     * Set this to true if you want this display object to be cached as a bitmap.
     * This basically takes a snap shot of the display object as it is at that moment. It can provide a performance benefit for complex static displayObjects.
     * To remove simply set this property to 'false'
     *
     * @member {boolean}
     * @memberof PIXI.DisplayObject#
     */
    cacheAsBitmap: {
        get: function ()
        {
            return this._cacheAsBitmap;
        },
        set: function (value)
        {
            if (this._cacheAsBitmap === value)
            {
                return;
            }

            this._cacheAsBitmap = value;

            var data;

            if (value)
            {

                if(!this._cacheData)
                {
                    this._cacheData = new CacheData();
                }

                data = this._cacheData;

                data.originalRenderWebGL = this.renderWebGL;
                data.originalRenderCanvas = this.renderCanvas;

                data.originalUpdateTransform = this.updateTransform;
                data.originalGetBounds = this.getBounds;

                data.originalDestroy = this.destroy;

                data.originalContainsPoint = this.containsPoint;

                data.originalMask = this._mask;
                data.originalFilterArea = this.filterArea;

                this.renderWebGL = this._renderCachedWebGL;
                this.renderCanvas = this._renderCachedCanvas;

                this.destroy = this._cacheAsBitmapDestroy;

            }
            else
            {
                data = this._cacheData;

                if (data.sprite)
                {
                    this._destroyCachedDisplayObject();
                }

                this.renderWebGL = data.originalRenderWebGL;
                this.renderCanvas = data.originalRenderCanvas;
                this.getBounds = data.originalGetBounds;

                this.destroy = data.originalDestroy;

                this.updateTransform = data.originalUpdateTransform;
                this.containsPoint = data.originalContainsPoint;

                this._mask = data.originalMask;
                this.filterArea = data.originalFilterArea;
            }
        }
    }
});
/**
* Renders a cached version of the sprite with WebGL
*
* @param renderer {PIXI.WebGLRenderer} the WebGL renderer
* @private
*/
DisplayObject.prototype._renderCachedWebGL = function (renderer)
{
    if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
    {
        return;
    }

    this._initCachedDisplayObject( renderer );

    this._cacheData.sprite._transformID = -1;
    this._cacheData.sprite.worldAlpha = this.worldAlpha;
    this._cacheData.sprite._renderWebGL(renderer);
};

/**
* Prepares the WebGL renderer to cache the sprite
*
* @param renderer {PIXI.WebGLRenderer} the WebGL renderer
* @private
*/
DisplayObject.prototype._initCachedDisplayObject = function (renderer)
{
    if(this._cacheData && this._cacheData.sprite)
    {
        return;
    }

    // make sure alpha is set to 1 otherwise it will get rendered as invisible!
    var cacheAlpha = this.alpha;
    this.alpha = 1;

    // first we flush anything left in the renderer (otherwise it would get rendered to the cached texture)
    renderer.currentRenderer.flush();
    //this.filters= [];
    // next we find the dimensions of the untransformed object
    // this function also calls updatetransform on all its children as part of the measuring. This means we don't need to update the transform again in this function
    // TODO pass an object to clone too? saves having to create a new one each time!
    var bounds = this.getLocalBounds().clone();

    // add some padding!
    if(this._filters)
    {
        var padding = this._filters[0].padding;

        bounds.pad(padding);
    }

    // for now we cache the current renderTarget that the webGL renderer is currently using.
    // this could be more elegent..
    var cachedRenderTarget = renderer._activeRenderTarget;
    // We also store the filter stack - I will definitely look to change how this works a little later down the line.
    var stack = renderer.filterManager.filterStack;

    // this renderTexture will be used to store the cached DisplayObject

    var renderTexture = core.RenderTexture.create(bounds.width | 0, bounds.height | 0);

    // need to set //
    var m = _tempMatrix;
    m.tx = -bounds.x;
    m.ty = -bounds.y;

    // reset
    this.transform.worldTransform.identity();

    // set all properties to there original so we can render to a texture
    this.renderWebGL = this._cacheData.originalRenderWebGL;

    renderer.render(this, renderTexture, true, m, true);
    // now restore the state be setting the new properties

    renderer.bindRenderTarget(cachedRenderTarget);

    renderer.filterManager.filterStack = stack;

    this.renderWebGL     = this._renderCachedWebGL;
    this.updateTransform = this.displayObjectUpdateTransform;
    this.getBounds       = this._getCachedBounds;

    this._mask = null;
    this.filterArea = null;

    // create our cached sprite
    var cachedSprite = new core.Sprite(renderTexture);
    cachedSprite.transform.worldTransform = this.transform.worldTransform;
    cachedSprite.anchor.x = -( bounds.x / bounds.width );
    cachedSprite.anchor.y = -( bounds.y / bounds.height );
    cachedSprite.alpha = cacheAlpha;

    this._cacheData.sprite = cachedSprite;

    this.transform._parentID = -1;
    // restore the transform of the cached sprite to avoid the nasty flicker..
    this.updateTransform();

    // map the hit test..
    this.containsPoint = cachedSprite.containsPoint.bind(cachedSprite);
};

/**
* Renders a cached version of the sprite with canvas
*
* @param renderer {PIXI.CanvasRenderer} the Canvas renderer
* @private
*/
DisplayObject.prototype._renderCachedCanvas = function (renderer)
{
    if (!this.visible || this.worldAlpha <= 0 || !this.renderable)
    {
        return;
    }

    this._initCachedDisplayObjectCanvas( renderer );

    this._cacheData.sprite.worldAlpha = this.worldAlpha;

    this._cacheData.sprite.renderCanvas(renderer);
};

//TODO this can be the same as the webGL verison.. will need to do a little tweaking first though..
/**
* Prepares the Canvas renderer to cache the sprite
*
* @param renderer {PIXI.CanvasRenderer} the Canvas renderer
* @private
*/
DisplayObject.prototype._initCachedDisplayObjectCanvas = function (renderer)
{
    if(this._cacheData && this._cacheData.sprite)
    {
        return;
    }

    //get bounds actually transforms the object for us already!
    var bounds = this.getLocalBounds();

    var cachedRenderTarget = renderer.context;

    var renderTexture = new core.RenderTexture.create(bounds.width | 0, bounds.height | 0);

    // need to set //
    var m = _tempMatrix;
    this.transform.worldTransform.copy(m);
    m.invert();

    m.tx -= bounds.x;
    m.ty -= bounds.y;

    //m.append(this.transform.worldTransform.)
     // set all properties to there original so we can render to a texture
    this.renderCanvas = this._cacheData.originalRenderCanvas;

    //renderTexture.render(this, m, true);
    renderer.render(this, renderTexture, true, m, false);

    // now restore the state be setting the new properties
    renderer.context = cachedRenderTarget;

    this.renderCanvas = this._renderCachedCanvas;
    this.updateTransform = this.displayObjectUpdateTransform;
    this.getBounds  = this._getCachedBounds;

    this._mask = null;
    this.filterArea = null;

    // create our cached sprite
    var cachedSprite = new core.Sprite(renderTexture);
    cachedSprite.transform.worldTransform = this.transform.worldTransform;
    cachedSprite.anchor.x = -( bounds.x / bounds.width );
    cachedSprite.anchor.y = -( bounds.y / bounds.height );

    this.updateTransform();

    this._cacheData.sprite = cachedSprite;

    this.containsPoint = cachedSprite.containsPoint.bind(cachedSprite);
};

/**
* Calculates the bounds of the cached sprite
*
* @private
*/
DisplayObject.prototype._getCachedBounds = function ()
{
    this._cacheData.sprite._currentBounds = null;

    return this._cacheData.sprite.getBounds();
};

/**
* Destroys the cached sprite.
*
* @private
*/
DisplayObject.prototype._destroyCachedDisplayObject = function ()
{
    this._cacheData.sprite._texture.destroy(true);
    this._cacheData.sprite = null;
};

DisplayObject.prototype._cacheAsBitmapDestroy = function ()
{
    this.cacheAsBitmap = false;
    this.destroy();
};
<|endoftext|>