<commit_before>const supertest = require('supertest'),
      should = require('should'),
      crypto = require('crypto'),
      path = require('path');

const app = require(path.resolve('./app')),
      dbHandle = require(path.resolve('./test/handleDatabase'));

const agent = supertest.agent(app);

describe('/users/:username/avatar', function () {

  let dbData;

  function beforeEachPopulate(data) {
    // put pre-data into database
    beforeEach(async function () {
      // create data in database
      dbData = await dbHandle.fill(data);
    });

    afterEach(async function () {
      await dbHandle.clear();
    });
  }

  let loggedUser, otherUser;

  beforeEachPopulate({
    users: 2, // how many users to make
    verifiedUsers: [0, 1] // which  users to make verified
  });

  beforeEach(function () {
    [loggedUser, otherUser] = dbData.users;
  });

  describe('GET', function () {

    context('logged', function () {

      context(':username exists', function () {

        it('[nothing uploaded] responds with 200 and a default identicon (identicon.js)', async function () {
          const response = await agent
            .get(`/users/${otherUser.username}/avatar`)
            .set('Content-Type', 'application/vnd.api+json')
            .auth(loggedUser.username, loggedUser.password)
            .expect(200)
            .expect('Content-Type', /^application\/vnd\.api\+json/);

          // the request returns a json:
          // {
          //    data: {
          //      type: 'user-avatars'
          //      id: username
          //      attributes: {
          //        format,
          //        base64
          //      }
          //    }
          // }
          // check the proper format attribute

          should(response).have.propertyByPath('body', 'data', 'type').eql('user-avatars');
          should(response).have.propertyByPath('body', 'data', 'id').eql('user1');
          should(response).have.propertyByPath('body', 'data', 'attributes', 'format').eql('png');
          should(response).have.propertyByPath('body', 'data', 'attributes', 'base64');

          // compare hash of the base64 image representation
          const data = response.body.data.attributes.base64;
          const hash = crypto.createHash('sha256').update(data).digest('hex');

          should(hash).equal('e4bc10f78c8e645c9fe170c46534e3593f8230cb295f283c0ad2846b64914f12');

        });

        it('[png uploaded] responds with 200 and a png image');

        it('[jpeg uploaded] responds with 200 and a jpeg image');

      });

      context(':username doesn\'t exist', function () {

        it('responds with 404', async function () {
          await agent
            .get('/users/nonexistent-user/avatar')
            .set('Content-Type', 'application/vnd.api+json')
            .auth(loggedUser.username, loggedUser.password)
            .expect(404)
            .expect('Content-Type', /^application\/vnd\.api\+json/);
        });

      });
    });

    context('not logged', function () {

      it('responds with 403', async function () {
        await agent
          .get('/users/nonexistent-user/avatar')
          .set('Content-Type', 'application/vnd.api+json')
          .expect(403)
          .expect('Content-Type', /^application\/vnd\.api\+json/);
      });

    });
  });

  describe('PATCH', function () {

    context('logged as :username', function () {

      context('good data type (png, jpeg)', function () {

        it('[png] responds with 200 and saves the image');

        it('[jpeg] responds with 200 and saves the image');

        it('crops and resizes the image to square 512x512px before saving');

        it('gets rid of any previous avatar of the user');

      });

      context('bad data type', function () {

        it('responds with 400 bad data');

      });
    });

    context('not logged as :username', function () {

      it('responds with 403');

    });

  });

  describe('DELETE', function () {

    context('logged as :username', function () {

      it('[data on server] responds with 204 and deletes the avatar from server');

      it('[no user image] responds with 204');

    });

    context('not logged as :username', function () {

      it('responds with 403');

    });

  });
});
<commit_msg>change user.username.avatar hash code - updated library<commit_after>const supertest = require('supertest'),
      should = require('should'),
      crypto = require('crypto'),
      path = require('path');

const app = require(path.resolve('./app')),
      dbHandle = require(path.resolve('./test/handleDatabase'));

const agent = supertest.agent(app);

describe('/users/:username/avatar', function () {

  let dbData;

  function beforeEachPopulate(data) {
    // put pre-data into database
    beforeEach(async function () {
      // create data in database
      dbData = await dbHandle.fill(data);
    });

    afterEach(async function () {
      await dbHandle.clear();
    });
  }

  let loggedUser, otherUser;

  beforeEachPopulate({
    users: 2, // how many users to make
    verifiedUsers: [0, 1] // which  users to make verified
  });

  beforeEach(function () {
    [loggedUser, otherUser] = dbData.users;
  });

  describe('GET', function () {

    context('logged', function () {

      context(':username exists', function () {

        it('[nothing uploaded] responds with 200 and a default identicon (identicon.js)', async function () {
          const response = await agent
            .get(`/users/${otherUser.username}/avatar`)
            .set('Content-Type', 'application/vnd.api+json')
            .auth(loggedUser.username, loggedUser.password)
            .expect(200)
            .expect('Content-Type', /^application\/vnd\.api\+json/);

          // the request returns a json:
          // {
          //    data: {
          //      type: 'user-avatars'
          //      id: username
          //      attributes: {
          //        format,
          //        base64
          //      }
          //    }
          // }
          // check the proper format attribute

          should(response).have.propertyByPath('body', 'data', 'type').eql('user-avatars');
          should(response).have.propertyByPath('body', 'data', 'id').eql('user1');
          should(response).have.propertyByPath('body', 'data', 'attributes', 'format').eql('png');
          should(response).have.propertyByPath('body', 'data', 'attributes', 'base64');

          // compare hash of the base64 image representation
          const data = response.body.data.attributes.base64;
          const hash = crypto.createHash('sha256').update(data).digest('hex');

          should(hash).equal('7d76d24aee7faf11a3494ae91b577d94cbb5320cec1b2fd04187fff1197915bb');

        });

        it('[png uploaded] responds with 200 and a png image');

        it('[jpeg uploaded] responds with 200 and a jpeg image');

      });

      context(':username doesn\'t exist', function () {

        it('responds with 404', async function () {
          await agent
            .get('/users/nonexistent-user/avatar')
            .set('Content-Type', 'application/vnd.api+json')
            .auth(loggedUser.username, loggedUser.password)
            .expect(404)
            .expect('Content-Type', /^application\/vnd\.api\+json/);
        });

      });
    });

    context('not logged', function () {

      it('responds with 403', async function () {
        await agent
          .get('/users/nonexistent-user/avatar')
          .set('Content-Type', 'application/vnd.api+json')
          .expect(403)
          .expect('Content-Type', /^application\/vnd\.api\+json/);
      });

    });
  });

  describe('PATCH', function () {

    context('logged as :username', function () {

      context('good data type (png, jpeg)', function () {

        it('[png] responds with 200 and saves the image');

        it('[jpeg] responds with 200 and saves the image');

        it('crops and resizes the image to square 512x512px before saving');

        it('gets rid of any previous avatar of the user');

      });

      context('bad data type', function () {

        it('responds with 400 bad data');

      });
    });

    context('not logged as :username', function () {

      it('responds with 403');

    });

  });

  describe('DELETE', function () {

    context('logged as :username', function () {

      it('[data on server] responds with 204 and deletes the avatar from server');

      it('[no user image] responds with 204');

    });

    context('not logged as :username', function () {

      it('responds with 403');

    });

  });
});
<|endoftext|>


<commit_before>const $ = require('jquery');

var assARRAY = ['grunt','grunt','shirt','towel','jesus','jorge','jesus','girly','gushy','tanks'];

var lingo = new Lingo();
var mysteryWord = lingo.generateMysteryWord(assARRAY);
var mysteryWordArray = lingo.generateWordArray(mysteryWord);

function mysteryRow(){
  return "
"+mysteryWordArray[0]+"	"+mysteryWordArray[1]+"	"+mysteryWordArray[2]+"	"+mysteryWordArray[3]+"	"+mysteryWordArray[4]+"
";
}

$('.input-tile').before(mysteryRow());
function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
    });
  });
  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };
  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };
  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };
  Lingo.prototype.countCharacterOccurences = function(wordArray, character){
    var countChar = 0;
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character){
        countChar++;
      }
    }
    return countChar;
  };
  Lingo.prototype.decrementCharacterOccurences = function(countChar){
    countChar--;
    return countChar;
  };

var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) { nextInput.focus(); }
  }
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getUserWordArray(){
    var userWordArray = guess.map(function(){
       return this.value;
    }).get();
    return userWordArray;
  }
  function newWordRow(){
    var userWordArray = getUserWordArray();
    var colorArray = checkUserGuess(userWordArray,mysteryWordArray);
    var orangeArray = [];
    var newRow = "
"+userWordArray[0]+"	"+userWordArray[1]+"	"+userWordArray[2]+"	"+userWordArray[3]+"	"+userWordArray[4]+"
";
    for (var i = 0; i < colorArray.length; i++) {
      if (colorArray[i] === 'orange'){
        orangeArray.push("");
      }
      if (orangeArray.length === 5) {
        correctGuess();
      }
    }
    if (isGameOver() === true && orangeArray.length !== 5){
      $('.mystery-word').html('You should have guessed:  '+mysteryWord+'. Better luck next time!');
      setTimeout( function(){
        location.replace("end.html");
      }, 3000);
    }
    return newRow;
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
    clearInputRow();
    swapRow();
    removeRow();
    $('#one').focus();
  }
  function correctGuess(){
    // var scoreUpOne = (function() {
    //   var score = 0;
    //   return function() {return score+=1;};
    // })();
    // $('#current-score').text(scoreUpOne);
    // store(scoreUpOne);
    setTimeout(location.reload.bind(location), 600); }
    if (event.which === 13) {
      isRowFilled();
      prependRow();
      $.done();
  }
});

$('input').keydown(function(){ // DELETE KEY NOT PERFECT
  if (event.which === 8) {
    var lastInput = guess.get(guess.index(this)-1);
    if ($('#column-last').val() === '') { lastInput.focus(); }
  }
});
function removeRow() {
  $('tr:last').remove();
}
function isLetter(event){
  if (event.which >= 97 && event.which <= 122 ) {
    return true;
  }
}

$('input').bind('keypress', function (event) {
    var regex = new RegExp("^[a-zA-Z]+$");
    var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
    if (!regex.test(key)) {
       event.preventDefault();
       return false;
    }
});

function isRowFilled(event) {
  if ($('#column-last').val().length < 1 )
    { $(event.keyCode === 13);
        return false;
    }
}

function checkUserGuess(userWordArray, mysteryWordArray){
  var colorArray = [];
  for (var i = 0; i < userWordArray.length; i++) {
    var lingo = new Lingo();
    if (userWordArray[i] === mysteryWordArray[i]) {
      colorArray.push('orange');
    } else if (lingo.checkWordArrayForLetter(mysteryWordArray, userWordArray[i])){
      colorArray.push('yellow');
    } else {
      colorArray.push('none');
    }
  }
  return colorArray;
}
// var store = function(score){
//     localStorage.setItem('userScore', JSON.stringify(score));
// };
function isGameOver(){
    var addedRowsCount = $('.added-row').length;
    if (addedRowsCount === 5){
      return true;
    } else { return false; }
}
}
module.exports = Lingo;
<commit_msg>renamed vulgar array<commit_after>const $ = require('jquery');

var mysteryWordARRAY = ['grunt','grunt','shirt','towel','jesus','jorge','jesus','girly','gushy','tanks'];

var lingo = new Lingo();
var mysteryWord = lingo.generateMysteryWord(mysteryWordARRAY);
var mysteryWordArray = lingo.generateWordArray(mysteryWord);

function mysteryRow(){
  return "
"+mysteryWordArray[0]+"	"+mysteryWordArray[1]+"	"+mysteryWordArray[2]+"	"+mysteryWordArray[3]+"	"+mysteryWordArray[4]+"
";
}

$('.input-tile').before(mysteryRow());
function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
    });
  });
  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };
  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };
  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };
  Lingo.prototype.countCharacterOccurences = function(wordArray, character){
    var countChar = 0;
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character){
        countChar++;
      }
    }
    return countChar;
  };
  Lingo.prototype.decrementCharacterOccurences = function(countChar){
    countChar--;
    return countChar;
  };

var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) { nextInput.focus(); }
  }
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getUserWordArray(){
    var userWordArray = guess.map(function(){
       return this.value;
    }).get();
    return userWordArray;
  }
  function newWordRow(){
    var userWordArray = getUserWordArray();
    var colorArray = checkUserGuess(userWordArray,mysteryWordArray);
    var orangeArray = [];
    var newRow = "
"+userWordArray[0]+"	"+userWordArray[1]+"	"+userWordArray[2]+"	"+userWordArray[3]+"	"+userWordArray[4]+"
";
    for (var i = 0; i < colorArray.length; i++) {
      if (colorArray[i] === 'orange'){
        orangeArray.push("");
      }
      if (orangeArray.length === 5) {
        correctGuess();
      }
    }
    if (isGameOver() === true && orangeArray.length !== 5){
      $('.mystery-word').html('You should have guessed:  '+mysteryWord+'. Better luck next time!');
      setTimeout( function(){
        location.replace("end.html");
      }, 3000);
    }
    return newRow;
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
    clearInputRow();
    swapRow();
    removeRow();
    $('#one').focus();
  }
  function correctGuess(){
    // var scoreUpOne = (function() {
    //   var score = 0;
    //   return function() {return score+=1;};
    // })();
    // $('#current-score').text(scoreUpOne);
    // store(scoreUpOne);
    setTimeout(location.reload.bind(location), 600); }
    if (event.which === 13) {
      isRowFilled();
      prependRow();
      $.done();
  }
});

$('input').keydown(function(){ // DELETE KEY NOT PERFECT
  if (event.which === 8) {
    var lastInput = guess.get(guess.index(this)-1);
    if ($('#column-last').val() === '') { lastInput.focus(); }
  }
});
function removeRow() {
  $('tr:last').remove();
}
function isLetter(event){
  if (event.which >= 97 && event.which <= 122 ) {
    return true;
  }
}

$('input').bind('keypress', function (event) {
    var regex = new RegExp("^[a-zA-Z]+$");
    var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
    if (!regex.test(key)) {
       event.preventDefault();
       return false;
    }
});

function isRowFilled(event) {
  if ($('#column-last').val().length < 1 )
    { $(event.keyCode === 13);
        return false;
    }
}

function checkUserGuess(userWordArray, mysteryWordArray){
  var colorArray = [];
  for (var i = 0; i < userWordArray.length; i++) {
    var lingo = new Lingo();
    if (userWordArray[i] === mysteryWordArray[i]) {
      colorArray.push('orange');
    } else if (lingo.checkWordArrayForLetter(mysteryWordArray, userWordArray[i])){
      colorArray.push('yellow');
    } else {
      colorArray.push('none');
    }
  }
  return colorArray;
}
// var store = function(score){
//     localStorage.setItem('userScore', JSON.stringify(score));
// };
function isGameOver(){
    var addedRowsCount = $('.added-row').length;
    if (addedRowsCount === 5){
      return true;
    } else { return false; }
}
}
module.exports = Lingo;
<|endoftext|>


<commit_before>/**
 * Parsed resources (snippets, abbreviations, variables, etc.) for Emmet.
 * Contains convenient method to get access for snippets with respect of
 * inheritance. Also provides ability to store data in different vocabularies
 * ('system' and 'user') for fast and safe resource update
 * @author Sergey Chikuyonok (serge.che@gmail.com)
 * @link http://chikuyonok.ru
 *
 * XXX This module is over-complicated, should provide better implementation
 *
 * @param {Function} require
 * @param {Underscore} _
 */
emmet.define('resources', function(require, _) {
	var VOC_SYSTEM = 'system';
	var VOC_USER = 'user';

	/** Regular expression for XML tag matching */
	var reTag = /^<(\w+\:?[\w\-]*)((?:\s+[\w\:\-]+\s*=\s*(['"]).*?\3)*)\s*(\/?)>/;

	var systemSettings = {};
	var userSettings = {};

	/** @type HandlerList List of registered abbreviation resolvers */
	var resolvers = require('handlerList').create();

	/**
	 * Check if specified resource is parsed by Emmet
	 * @param {Object} obj
	 * @return {Boolean}
	 */
	function isParsed(obj) {
		return obj && obj.__emmet_parsed__;
	}

	/**
	 * Marks object as parsed by Emmet
	 * @param {Object}
	 */
	function setParsed(obj) {
		obj.__emmet_parsed__ = true;
	}

	/**
	 * Returns resource vocabulary by its name
	 * @param {String} name Vocabulary name ('system' or 'user')
	 */
	function getVocabulary(name) {
		return name == VOC_SYSTEM ? systemSettings : userSettings;
	}

	/**
	 * Helper function that transforms string into hash
	 * @return {Object}
	 */
	function stringToHash(str){
		var obj = {}, items = str.split(",");
		for ( var i = 0; i < items.length; i++ )
			obj[ items[i] ] = true;
		return obj;
	}

	/**
	 * Creates resource inheritance chain for lookups
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name
	 * @return {Array}
	 */
	function createResourceChain(vocabulary, syntax, name) {
		var voc = getVocabulary(vocabulary),
			result = [],
			resource = null;

		if (voc && syntax in voc) {
			resource = voc[syntax];
			if (name in resource)
				result.push(resource[name]);
		}

		// get inheritance definition
		// in case of user-defined vocabulary, resource dependency
		// may be defined in system vocabulary only, so we have to correctly
		// handle this case
		var chain_source = null;
		if (resource && 'extends' in resource)
			chain_source = resource;
		else if (vocabulary == VOC_USER && syntax in systemSettings
			&& 'extends' in systemSettings[syntax] )
			chain_source = systemSettings[syntax];

		if (chain_source) {
			if (!isParsed(chain_source['extends'])) {
				var ar = chain_source['extends'].split(',');
				var utils = require('utils');
				for (var i = 0; i < ar.length; i++)
					ar[i] = utils.trim(ar[i]);
				chain_source['extends'] = ar;
				setParsed(chain_source['extends']);
			}

			// find resource in ancestors
			for (var i = 0; i < chain_source['extends'].length; i++) {
				var type = chain_source['extends'][i];
				if (voc[type] && voc[type][name])
					result.push(voc[type][name]);
			}
		}

		return result;
	}

	/**
	 * Get resource collection from settings vocbulary for specified syntax.
	 * It follows inheritance chain if resource wasn't directly found in
	 * syntax settings
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name
	 */
	function getSubset(vocabulary, syntax, name) {
		var chain = createResourceChain(vocabulary, syntax, name);
		return chain[0];
	}

	/**
	 * Normalizes caret plceholder in passed text: replaces | character with
	 * default caret placeholder
	 * @param {String} text
	 * @returns {String}
	 */
	function normalizeCaretPlaceholder(text) {
		var utils = require('utils');
		return utils.replaceUnescapedSymbol(text, '|', utils.getCaretPlaceholder());
	}

	/**
	 * Returns parsed item located in specified vocabulary by its syntax and
	 * name
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name ('abbreviation', 'snippet')
	 * @param {String} item Abbreviation or snippet name
	 * @return {Object}
	 */
	function getParsedItem(vocabulary, syntax, name, item) {
		var chain = createResourceChain(vocabulary, syntax, name);
		var result = null, res;
		var elements = require('elements');

		for (var i = 0, il = chain.length; i < il; i++) {
			res = chain[i];
			if (item in res) {
				if (!isParsed(res[item])) {
					var value = normalizeCaretPlaceholder(res[item]);
					switch(name) {
						case 'abbreviations':
							res[item] = parseAbbreviation(item, value);
							res[item].__ref = value;
							break;
						case 'snippets':
							res[item] = elements.create('snippet', value);
							break;
					}

					setParsed(res[item]);
				}

				result = res[item];
				break;
			}
		}

		return result;
	}

	function parseItem(name, value, type) {
		var value = normalizeCaretPlaceholder(value);

		if (type == 'snippets') {
			return elements.create('snippet', value);
		}

		if (type == 'abbreviations') {
			return parseAbbreviation(name, value);
		}
	}

	/**
	 * Parses single abbreviation
	 * @param {String} key Abbreviation name
	 * @param {String} value Abbreviation value
	 * @return {Object}
	 */
	function parseAbbreviation(key, value) {
		key = require('utils').trim(key);
		var elements = require('elements');
		var m;
		if (m = reTag.exec(value)) {
			return elements.create('element', m[1], m[2], m[4] == '/');
		} else {
			// assume it's reference to another abbreviation
			return elements.create('reference', value);
		}
	}

	return {
		/**
		 * Sets new unparsed data for specified settings vocabulary
		 * @param {Object} data
		 * @param {String} type Vocabulary type ('system' or 'user')
		 * @memberOf resources
		 */
		setVocabulary: function(data, type) {
			if (type == VOC_SYSTEM)
				systemSettings = data;
			else
				userSettings = data;
		},

		/**
		 * Get data from specified vocabulary. Can contain parsed entities
		 * @param {String} name Vocabulary type ('system' or 'user')
		 * @return {Object}
		 */
		getVocabulary: getVocabulary,

		/**
		 * Returns resource value from data set with respect of inheritance
		 * @param {String} syntax Resource syntax (html, css, ...)
		 * @param {String} name Resource name ('snippets' or 'abbreviation')
		 * @param {String} item Resource item name
		 * @return {Object}
		 */
		getResource: function(syntax, name, item) {
			return getParsedItem(VOC_USER, syntax, name, item)
				|| getParsedItem(VOC_SYSTEM, syntax, name, item);
		},

		/**
		 * Returns abbreviation value from data set
		 * @param {String} type Resource type (html, css, ...)
		 * @param {String} name Abbreviation name
		 * @return {Object}
		 */
		getAbbreviation: function(type, name) {
			name = name || '';
			return this.getResource(type, 'abbreviations', name)
				|| this.getResource(type, 'abbreviations', name.replace(/\-/g, ':'));
		},

		/**
		 * Returns snippet value from data set
		 * @param {String} type Resource type (html, css, ...)
		 * @param {String} name Snippet name
		 * @return {Object}
		 */
		getSnippet: function(type, name) {
			name = name || '';
			return this.getResource(type, 'snippets', name)
				|| this.getResource(type, 'snippets', name.replace(/\-/g, ':'));
		},

		/**
		 * Returns resource (abbreviation, snippet, etc.) matched for passed
		 * abbreviation
		 * @param {TreeNode} node
		 * @param {String} syntax
		 * @returns {Object}
		 */
		getMatchedResource: function(node, syntax) {
			return resolvers.exec(null, _.toArray(arguments))
				|| this.getAbbreviation(syntax, node.name())
				|| this.getSnippet(syntax, node.name());
		},

		/**
		 * Returns variable value
		 * @return {String}
		 */
		getVariable: function(name) {
			return getSubset(VOC_USER, 'variables', name)
				|| getSubset(VOC_SYSTEM, 'variables', name);
		},

		/**
		 * Store runtime variable in user storage
		 * @param {String} name Variable name
		 * @param {String} value Variable value
		 */
		setVariable: function(name, value){
			var voc = getVocabulary('user') || {};
			if (!('variables' in voc))
				voc.variables = {};

			voc.variables[name] = value;
			this.setVocabulary(voc, 'user');
		},

		/**
		 * Returns resource subset from settings vocabulary
		 * @param {String} syntax Syntax name
		 * @param {String} name Resource name
		 * @return {Object}
		 */
		getSubset: function(syntax, name) {
			return getSubset(VOC_USER, syntax, name)
				|| getSubset(VOC_SYSTEM, syntax, name);
		},

		/**
		 * Check if there are resources for specified syntax
		 * @param {String} syntax
		 * @return {Boolean}
		 */
		hasSyntax: function(syntax) {
			return syntax in getVocabulary(VOC_USER)
				|| syntax in getVocabulary(VOC_SYSTEM);
		},

		/**
		 * Registers new abbreviation resolver.
		 * @param {Function} fn Abbreviation resolver which will receive
		 * abbreviation as first argument and should return parsed abbreviation
		 * object if abbreviation has handled successfully, null
		 * otherwise
		 * @param {Object} options Options list as described in
		 * {@link HandlerList#add()} method
		 */
		addResolver: function(fn, options) {
			resolvers.add(fn, options);
		},

		removeResolver: function(fn) {
			resolvers.remove(fn);
		},

		findItem: function(syntax, name, memo) {
			memo = memo || [];

			var data = require('utils').deepMerge({}, systemSettings[syntax], userSettings[syntax]);
			console.log('searching in', data);

			var matchedItem = null;
			_.find(['snippets', 'abbreviations'], function(sectionName) {
				if (sectionName in data && name in data[sectionName]) {
					return matchedItem = parseItem(name, data[sectionName][name], sectionName);
				}
			});

			memo.push(syntax);

			if (!matchedItem && data['extends'] && !_.include(memo, data['extends'])) {
				// try to find item in parent syntax section
				return this.findItem(data['extends'], name, memo);
			}

			return matchedItem;
		}

	};
});<commit_msg>Working on new resource manager<commit_after>/**
 * Parsed resources (snippets, abbreviations, variables, etc.) for Emmet.
 * Contains convenient method to get access for snippets with respect of
 * inheritance. Also provides ability to store data in different vocabularies
 * ('system' and 'user') for fast and safe resource update
 * @author Sergey Chikuyonok (serge.che@gmail.com)
 * @link http://chikuyonok.ru
 *
 * XXX This module is over-complicated, should provide better implementation
 *
 * @param {Function} require
 * @param {Underscore} _
 */
emmet.define('resources', function(require, _) {
	var VOC_SYSTEM = 'system';
	var VOC_USER = 'user';

	var cache = {};

	/** Regular expression for XML tag matching */
	var reTag = /^<(\w+\:?[\w\-]*)((?:\s+[\w\:\-]+\s*=\s*(['"]).*?\3)*)\s*(\/?)>/;

	var systemSettings = {};
	var userSettings = {};

	/** @type HandlerList List of registered abbreviation resolvers */
	var resolvers = require('handlerList').create();

	/**
	 * Check if specified resource is parsed by Emmet
	 * @param {Object} obj
	 * @return {Boolean}
	 */
	function isParsed(obj) {
		return obj && obj.__emmet_parsed__;
	}

	/**
	 * Marks object as parsed by Emmet
	 * @param {Object}
	 */
	function setParsed(obj) {
		obj.__emmet_parsed__ = true;
	}

	/**
	 * Returns resource vocabulary by its name
	 * @param {String} name Vocabulary name ('system' or 'user')
	 */
	function getVocabulary(name) {
		return name == VOC_SYSTEM ? systemSettings : userSettings;
	}

	/**
	 * Helper function that transforms string into hash
	 * @return {Object}
	 */
	function stringToHash(str){
		var obj = {}, items = str.split(",");
		for ( var i = 0; i < items.length; i++ )
			obj[ items[i] ] = true;
		return obj;
	}

	/**
	 * Creates resource inheritance chain for lookups
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name
	 * @return {Array}
	 */
	function createResourceChain(vocabulary, syntax, name) {
		var voc = getVocabulary(vocabulary),
			result = [],
			resource = null;

		if (voc && syntax in voc) {
			resource = voc[syntax];
			if (name in resource)
				result.push(resource[name]);
		}

		// get inheritance definition
		// in case of user-defined vocabulary, resource dependency
		// may be defined in system vocabulary only, so we have to correctly
		// handle this case
		var chain_source = null;
		if (resource && 'extends' in resource)
			chain_source = resource;
		else if (vocabulary == VOC_USER && syntax in systemSettings
			&& 'extends' in systemSettings[syntax] )
			chain_source = systemSettings[syntax];

		if (chain_source) {
			if (!isParsed(chain_source['extends'])) {
				var ar = chain_source['extends'].split(',');
				var utils = require('utils');
				for (var i = 0; i < ar.length; i++)
					ar[i] = utils.trim(ar[i]);
				chain_source['extends'] = ar;
				setParsed(chain_source['extends']);
			}

			// find resource in ancestors
			for (var i = 0; i < chain_source['extends'].length; i++) {
				var type = chain_source['extends'][i];
				if (voc[type] && voc[type][name])
					result.push(voc[type][name]);
			}
		}

		return result;
	}

	/**
	 * Get resource collection from settings vocbulary for specified syntax.
	 * It follows inheritance chain if resource wasn't directly found in
	 * syntax settings
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name
	 */
	function getSubset(vocabulary, syntax, name) {
		var chain = createResourceChain(vocabulary, syntax, name);
		return chain[0];
	}

	/**
	 * Normalizes caret plceholder in passed text: replaces | character with
	 * default caret placeholder
	 * @param {String} text
	 * @returns {String}
	 */
	function normalizeCaretPlaceholder(text) {
		var utils = require('utils');
		return utils.replaceUnescapedSymbol(text, '|', utils.getCaretPlaceholder());
	}

	/**
	 * Returns parsed item located in specified vocabulary by its syntax and
	 * name
	 * @param {String} vocabulary Resource vocabulary
	 * @param {String} syntax Syntax name
	 * @param {String} name Resource name ('abbreviation', 'snippet')
	 * @param {String} item Abbreviation or snippet name
	 * @return {Object}
	 */
	function getParsedItem(vocabulary, syntax, name, item) {
		var chain = createResourceChain(vocabulary, syntax, name);
		var result = null, res;
		var elements = require('elements');

		for (var i = 0, il = chain.length; i < il; i++) {
			res = chain[i];
			if (item in res) {
				if (!isParsed(res[item])) {
					var value = normalizeCaretPlaceholder(res[item]);
					switch(name) {
						case 'abbreviations':
							res[item] = parseAbbreviation(item, value);
							res[item].__ref = value;
							break;
						case 'snippets':
							res[item] = elements.create('snippet', value);
							break;
					}

					setParsed(res[item]);
				}

				result = res[item];
				break;
			}
		}

		return result;
	}

	function parseItem(name, value, type) {
		value = normalizeCaretPlaceholder(value);

		if (type == 'snippets') {
			return elements.create('snippet', value);
		}

		if (type == 'abbreviations') {
			return parseAbbreviation(name, value);
		}
	}

	/**
	 * Parses single abbreviation
	 * @param {String} key Abbreviation name
	 * @param {String} value Abbreviation value
	 * @return {Object}
	 */
	function parseAbbreviation(key, value) {
		key = require('utils').trim(key);
		var elements = require('elements');
		var m;
		if (m = reTag.exec(value)) {
			return elements.create('element', m[1], m[2], m[4] == '/');
		} else {
			// assume it's reference to another abbreviation
			return elements.create('reference', value);
		}
	}

	return {
		/**
		 * Sets new unparsed data for specified settings vocabulary
		 * @param {Object} data
		 * @param {String} type Vocabulary type ('system' or 'user')
		 * @memberOf resources
		 */
		setVocabulary: function(data, type) {
			cache = {};
			if (type == VOC_SYSTEM)
				systemSettings = data;
			else
				userSettings = data;
		},

		/**
		 * Get data from specified vocabulary. Can contain parsed entities
		 * @param {String} name Vocabulary type ('system' or 'user')
		 * @return {Object}
		 */
		getVocabulary: getVocabulary,

		/**
		 * Returns resource value from data set with respect of inheritance
		 * @param {String} syntax Resource syntax (html, css, ...)
		 * @param {String} name Resource name ('snippets' or 'abbreviation')
		 * @param {String} item Resource item name
		 * @return {Object}
		 */
		getResource: function(syntax, name, item) {
			return getParsedItem(VOC_USER, syntax, name, item)
				|| getParsedItem(VOC_SYSTEM, syntax, name, item);
		},

		/**
		 * Returns abbreviation value from data set
		 * @param {String} type Resource type (html, css, ...)
		 * @param {String} name Abbreviation name
		 * @return {Object}
		 */
		getAbbreviation: function(type, name) {
			name = name || '';
			return this.getResource(type, 'abbreviations', name)
				|| this.getResource(type, 'abbreviations', name.replace(/\-/g, ':'));
		},

		/**
		 * Returns snippet value from data set
		 * @param {String} type Resource type (html, css, ...)
		 * @param {String} name Snippet name
		 * @return {Object}
		 */
		getSnippet: function(type, name) {
			name = name || '';
			return this.getResource(type, 'snippets', name)
				|| this.getResource(type, 'snippets', name.replace(/\-/g, ':'));
		},

		/**
		 * Returns resource (abbreviation, snippet, etc.) matched for passed
		 * abbreviation
		 * @param {TreeNode} node
		 * @param {String} syntax
		 * @returns {Object}
		 */
		getMatchedResource: function(node, syntax) {
			return resolvers.exec(null, _.toArray(arguments))
				|| this.getAbbreviation(syntax, node.name())
				|| this.getSnippet(syntax, node.name());
		},

		/**
		 * Returns variable value
		 * @return {String}
		 */
		getVariable: function(name) {
			return getSubset(VOC_USER, 'variables', name)
				|| getSubset(VOC_SYSTEM, 'variables', name);
		},

		/**
		 * Store runtime variable in user storage
		 * @param {String} name Variable name
		 * @param {String} value Variable value
		 */
		setVariable: function(name, value){
			var voc = getVocabulary('user') || {};
			if (!('variables' in voc))
				voc.variables = {};

			voc.variables[name] = value;
			this.setVocabulary(voc, 'user');
		},

		/**
		 * Returns resource subset from settings vocabulary
		 * @param {String} syntax Syntax name
		 * @param {String} name Resource name
		 * @return {Object}
		 */
		getSubset: function(syntax, name) {
			return getSubset(VOC_USER, syntax, name)
				|| getSubset(VOC_SYSTEM, syntax, name);
		},

		/**
		 * Check if there are resources for specified syntax
		 * @param {String} syntax
		 * @return {Boolean}
		 */
		hasSyntax: function(syntax) {
			return syntax in getVocabulary(VOC_USER)
				|| syntax in getVocabulary(VOC_SYSTEM);
		},

		/**
		 * Registers new abbreviation resolver.
		 * @param {Function} fn Abbreviation resolver which will receive
		 * abbreviation as first argument and should return parsed abbreviation
		 * object if abbreviation has handled successfully, null
		 * otherwise
		 * @param {Object} options Options list as described in
		 * {@link HandlerList#add()} method
		 */
		addResolver: function(fn, options) {
			resolvers.add(fn, options);
		},

		removeResolver: function(fn) {
			resolvers.remove(fn);
		},

		getSection: function(name) {
			if (!name)
				return null;

			if (!(name in cache)) {
				cache[name] = require('utils').deepMerge({}, systemSettings[name], userSettings[name]);
			}

			var data = cache[name], subsections = _.rest(arguments), key;
			while (data && (key = subsections.shift())) {
				if (key in data) {
					data = data[key];
				} else {
					return null;
				}
			}

			return data;
		},

		findItem: function(topSection, subsection) {
			var data = this.getSection(topSection);
			while (data) {
				if (subsection in data)
					return data[subsection];

				data = this.getSection(data['extends']);
			}
		},

		findSnippet: function(syntax, name, memo) {
			memo = memo || [];

			var data = this.getSection(syntax), matchedItem = null;
			_.find(['snippets', 'abbreviations'], function(sectionName) {
				var data = this.getSection(syntax, sectionName);
				if (data) {
					return matchedItem = parseItem(name, data[name], sectionName);
				}
			}, this);

			memo.push(syntax);
			if (!matchedItem && data['extends'] && !_.include(memo, data['extends'])) {
				// try to find item in parent syntax section
				return this.findSnippet(data['extends'], name, memo);
			}

			return matchedItem;
		}

	};
});<|endoftext|>


<commit_before>var Frog = require('../lib/frog');
var Car = require('../lib/car');
var Bus = require('../lib/bus');
var Bike = require('../lib/bike');
var Zone = require('../lib/zone');
var Pad = require('../lib/pad');
var Troncycle = require('../lib/troncycle');

var levelCompleteScreen = document.getElementById('level-complete');
var gameLostScreen = document.getElementById('game-lost');
var gameWonScreen = document.getElementById('game-complete');
var frogFinalLife = document.getElementById('final-life');
var frogSecondLife = document.getElementById('second-life');
var frogFirstLife = document.getElementById('first-life');
var zeroImg = document.getElementById('zero-img');

var canvas = document.getElementById('world');
var ctx = canvas.getContext('2d');
var game = new Game();
var frog = new Frog();

//GAME
function Game() {
var startZone = new Zone();
var midZone = new Zone(5, 245, 590, 10);
var endZone = new Zone(5,5);

var pads = [];
  var spotBottomX = 310;
  var spotTopX = 70;
  for (var i = 0; i < 5; i++) {
  if (i < 1) {
    pads.push(new Pad(spotBottomX));
    } else {
    pads.push(new Pad(spotTopX, 30));
    spotTopX += 160;
  }
}

var bikes = [];
  var firstBikeX = 250;
  var nextBikeX = 240;
  var thirdBikeX = 10;
  for (var j = 0; j < 7; j++) {
  if (j < 2) {
    bikes.push(new Bike(firstBikeX));
    firstBikeX -= 290;
  } else if (j < 5){
    bikes.push(new Bike(nextBikeX, 192));
    nextBikeX -= 120;
    } else {
    bikes.push(new Bike(thirdBikeX, 63));
    thirdBikeX += 190;
  }
}

var buses = [];
  var firstBusX = 540;
  var secondBusX = 40;
  for (var k = 0; k < 5; k++) {
    if (k < 2) {
      buses.push(new Bus(firstBusX));
   firstBusX -= 240;
    } else {
   buses.push(new Bus(secondBusX, 148));
   secondBusX += 320;
  }
}

var cars = [];
var firstCarsX = 400;
var secondCarsX = 200;
for (var l = 0; l < 6; l++) {
  if (l < 3) {
    cars.push(new Car(firstCarsX));
    firstCarsX -= 255;
  } else {
    cars.push(new Car(secondCarsX, 103));
  } secondCarsX += 240;
}

var vehicleArray = [];
  for(var m = 0; m < cars.length; m++) {
  vehicleArray.push(cars[m]);
  }
  for(var n = 0; n < buses.length; n++) {
  vehicleArray.push(buses[n]);
  }
  for(var o = 0; o < bikes.length; o++) {
  vehicleArray.push(bikes[o]);
}

var troncycles = [];
  var firstTronX = 70;
  var secondTronX = 20;
  var thirdTronX = 330;
  var fourthTronX = 350;
  var fifthTronX = 200;
  var sixthTronX = 200;
  var seventhTronX = 190;
  for (var p = 0; p < 26; p++) {
    if (p < 4) {
      troncycles.push(new Troncycle(firstTronX, 370));
      firstTronX -= 180;
    } else if (p < 8){
      troncycles.push(new Troncycle(secondTronX, 330));
      secondTronX += 240;
    } else if (p < 11){
      troncycles.push(new Troncycle(thirdTronX, 280));
      thirdTronX -= 150;
    } else if (p < 15){
      troncycles.push(new Troncycle(fourthTronX, 195));
      fourthTronX += 160;
    } else if (p < 18){
      troncycles.push(new Troncycle(fifthTronX, 150));
      fifthTronX -= 290;
    } else if (p < 21){
      troncycles.push(new Troncycle(sixthTronX, 110));
      sixthTronX += 280;
    } else{
      troncycles.push(new Troncycle(seventhTronX, 70));
      seventhTronX -= 170;
    }
  }

// var troncycleOne = new Troncycle();
// var troncycleEight = new Troncycle(200, 370);
// var troncycleFifteen = new Troncycle(50, 370);
// var troncycleTwo = new Troncycle(400, 330);
// var troncycleNine = new Troncycle(200, 330);
// var troncycleSixteen = new Troncycle(580, 330);
// var troncycleThree = new Troncycle(300, 280);
// var troncycleTen = new Troncycle(150, 280);
// var troncycleSeventeen = new Troncycle(420, 280);
// var troncycleFour = new Troncycle(200, 195);
// var troncycleEleven = new Troncycle(40, 195);
// var troncycleEightteen = new Troncycle(290, 195);
// var troncycleFive = new Troncycle(390, 150);
// var troncycleTwelve = new Troncycle(500, 150);
// var troncycleNineteen = new Troncycle(100, 150);
// var troncycleSix = new Troncycle(300, 110);
// var troncycleThirteen = new Troncycle(20, 110);
// var troncycleTwenty = new Troncycle(420, 110);
// var troncycleSeven = new Troncycle(90, 70);
// var troncycleFourteen = new Troncycle(500, 70);
// var troncycleTwentyOne = new Troncycle(200, 70);

// var cycles = [];
// cycles.push(troncycleOne, troncycleTwo, troncycleThree, troncycleFour, troncycleFive, troncycleSix, troncycleSeven, troncycleEight, troncycleNine, troncycleTen, troncycleEleven,  troncycleTwelve,  troncycleThirteen, troncycleFourteen, troncycleFifteen, troncycleSixteen, troncycleSeventeen, troncycleEightteen, troncycleNineteen, troncycleTwenty, troncycleTwentyOne);
//
// var cyclesMoveRight = [];
// cyclesMoveRight.push(troncycleOne, troncycleThree, troncycleFive, troncycleSeven, troncycleEight, troncycleTen,  troncycleTwelve, troncycleFourteen, troncycleFifteen, troncycleSeventeen, troncycleNineteen, troncycleTwentyOne);
//
// var cyclesMoveLeft = [];
// cyclesMoveLeft.push(troncycleTwo, troncycleFour, troncycleSix, troncycleNine, troncycleEleven,  troncycleThirteen, troncycleSixteen, troncycleEightteen, troncycleTwenty);

var cycleArray = [];
  for (var q = 0; q < troncycles.length; q++){
    cycleArray.push(troncycles[q])
  }

var water = [];
water.push(startZone, endZone);

var bottomLanes = [];
bottomLanes.push(cars[0], cars[1], cars[2], buses[0], buses[1], bikes[0], bikes[1]);

var topLanes = [];
topLanes.push(cars[3], cars[4], buses[2], buses[3], bikes[2], bikes[3], bikes[4]);

var topLaneDifferent = [];
topLaneDifferent.push(bikes[5], bikes[6]);

//GAME FUNCTIONS
  this.animate = function() {
    if(frog.level === 1) {
      this.levelOne();
    } else if(frog.level === 2) {
      this.levelTwo();
    } else if (frog.level === 3) {
      this.levelThree();
    }
  };
  this.levelOne = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    bottomLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRight();
    });
    topLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    topLaneDifferent.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeftFast();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    vehicleArray.forEach(function(vehicle) {
      frog.detectCollision(vehicle, gameLostScreen);
    });
  };
  this.levelTwo = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    bottomLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRightFast();
    });
    topLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeftFast();
    });
    topLaneDifferent.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    vehicleArray.forEach(function(vehicle) {
      frog.detectCollision(vehicle, gameLostScreen);
    });
  };
  this.levelThree = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    cyclesMoveRight.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRight();
    });
    cyclesMoveLeft.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    cycles.forEach(function(cycle) {
      frog.detectCollision(cycle, gameLostScreen);
    });
  };
}

document.addEventListener('keydown', function(event) {
  if (event.keyCode === 37) {
    frog.moveLeft(canvas);
  }
  if (event.keyCode === 38) {
    frog.moveUp(canvas);
  }
  if (event.keyCode === 39) {
    frog.moveRight(canvas);
  }
  if (event.keyCode === 40) {
    frog.moveDown(canvas);
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13 && frog.lives === 0) {
    gameLostScreen.style.display='none';
    frog.lives = 3;
    frog.level = 1;
    zeroImg.classList.add('hide');
    frogFirstLife.classList.remove('hide');
    frogSecondLife.classList.remove('hide');
    frogFinalLife.classList.remove('hide');
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13 && frog.level === 4) {
    gameWonScreen.style.display='none';
    frog.lives = 3;
    frog.level = 1;
    frogFirstLife.classList.remove('hide');
    frogSecondLife.classList.remove('hide');
    frogFinalLife.classList.remove('hide');
  }
});

document.addEventListener('keydown', function(event) {
  if (event.which === 38 && frog.lives <= 0) {
    frog.lives = 0;
    frog.x = 310;
    frog.y = 470;
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13) {
    levelCompleteScreen.style.display='none';
    frog.canMove = true;
  }
});

function checkForFrogLives() {
  if (frog.lives === 0) {
    frog.canMove = false;
  }
}

module.exports = Game;
<commit_msg>creates cyclesMoveRight array and pushes necessary cycles<commit_after>var Frog = require('../lib/frog');
var Car = require('../lib/car');
var Bus = require('../lib/bus');
var Bike = require('../lib/bike');
var Zone = require('../lib/zone');
var Pad = require('../lib/pad');
var Troncycle = require('../lib/troncycle');

var levelCompleteScreen = document.getElementById('level-complete');
var gameLostScreen = document.getElementById('game-lost');
var gameWonScreen = document.getElementById('game-complete');
var frogFinalLife = document.getElementById('final-life');
var frogSecondLife = document.getElementById('second-life');
var frogFirstLife = document.getElementById('first-life');
var zeroImg = document.getElementById('zero-img');

var canvas = document.getElementById('world');
var ctx = canvas.getContext('2d');
var game = new Game();
var frog = new Frog();

//GAME
function Game() {
var startZone = new Zone();
var midZone = new Zone(5, 245, 590, 10);
var endZone = new Zone(5,5);

var pads = [];
  var spotBottomX = 310;
  var spotTopX = 70;
  for (var i = 0; i < 5; i++) {
  if (i < 1) {
    pads.push(new Pad(spotBottomX));
    } else {
    pads.push(new Pad(spotTopX, 30));
    spotTopX += 160;
  }
}

var bikes = [];
  var firstBikeX = 250;
  var nextBikeX = 240;
  var thirdBikeX = 10;
  for (var j = 0; j < 7; j++) {
  if (j < 2) {
    bikes.push(new Bike(firstBikeX));
    firstBikeX -= 290;
  } else if (j < 5){
    bikes.push(new Bike(nextBikeX, 192));
    nextBikeX -= 120;
    } else {
    bikes.push(new Bike(thirdBikeX, 63));
    thirdBikeX += 190;
  }
}

var buses = [];
  var firstBusX = 540;
  var secondBusX = 40;
  for (var k = 0; k < 5; k++) {
    if (k < 2) {
      buses.push(new Bus(firstBusX));
   firstBusX -= 240;
    } else {
   buses.push(new Bus(secondBusX, 148));
   secondBusX += 320;
  }
}

var cars = [];
var firstCarsX = 400;
var secondCarsX = 200;
for (var l = 0; l < 6; l++) {
  if (l < 3) {
    cars.push(new Car(firstCarsX));
    firstCarsX -= 255;
  } else {
    cars.push(new Car(secondCarsX, 103));
  } secondCarsX += 240;
}

var vehicleArray = [];
  for(var m = 0; m < cars.length; m++) {
  vehicleArray.push(cars[m]);
  }
  for(var n = 0; n < buses.length; n++) {
  vehicleArray.push(buses[n]);
  }
  for(var o = 0; o < bikes.length; o++) {
  vehicleArray.push(bikes[o]);
}

var troncycles = [];
  var firstTronX = 70;
  var secondTronX = 20;
  var thirdTronX = 330;
  var fourthTronX = 350;
  var fifthTronX = 200;
  var sixthTronX = 200;
  var seventhTronX = 190;
  for (var p = 0; p < 26; p++) {
    if (p < 4) {
      troncycles.push(new Troncycle(firstTronX, 370));
      firstTronX -= 180;
    } else if (p < 8){
      troncycles.push(new Troncycle(secondTronX, 330));
      secondTronX += 240;
    } else if (p < 11){
      troncycles.push(new Troncycle(thirdTronX, 280));
      thirdTronX -= 150;
    } else if (p < 15){
      troncycles.push(new Troncycle(fourthTronX, 195));
      fourthTronX += 160;
    } else if (p < 18){
      troncycles.push(new Troncycle(fifthTronX, 150));
      fifthTronX -= 290;
    } else if (p < 21){
      troncycles.push(new Troncycle(sixthTronX, 110));
      sixthTronX += 280;
    } else{
      troncycles.push(new Troncycle(seventhTronX, 70));
      seventhTronX -= 170;
    }
  }

// var troncycleOne = new Troncycle();
// var troncycleEight = new Troncycle(200, 370);
// var troncycleFifteen = new Troncycle(50, 370);
// var troncycleTwo = new Troncycle(400, 330);
// var troncycleNine = new Troncycle(200, 330);
// var troncycleSixteen = new Troncycle(580, 330);
// var troncycleThree = new Troncycle(300, 280);
// var troncycleTen = new Troncycle(150, 280);
// var troncycleSeventeen = new Troncycle(420, 280);
// var troncycleFour = new Troncycle(200, 195);
// var troncycleEleven = new Troncycle(40, 195);
// var troncycleEightteen = new Troncycle(290, 195);
// var troncycleFive = new Troncycle(390, 150);
// var troncycleTwelve = new Troncycle(500, 150);
// var troncycleNineteen = new Troncycle(100, 150);
// var troncycleSix = new Troncycle(300, 110);
// var troncycleThirteen = new Troncycle(20, 110);
// var troncycleTwenty = new Troncycle(420, 110);
// var troncycleSeven = new Troncycle(90, 70);
// var troncycleFourteen = new Troncycle(500, 70);
// var troncycleTwentyOne = new Troncycle(200, 70);

// var cycles = [];
// cycles.push(troncycleOne, troncycleTwo, troncycleThree, troncycleFour, troncycleFive, troncycleSix, troncycleSeven, troncycleEight, troncycleNine, troncycleTen, troncycleEleven,  troncycleTwelve,  troncycleThirteen, troncycleFourteen, troncycleFifteen, troncycleSixteen, troncycleSeventeen, troncycleEightteen, troncycleNineteen, troncycleTwenty, troncycleTwentyOne);
//
// var cyclesMoveRight = [];
// cyclesMoveRight.push(troncycleOne, troncycleThree, troncycleFive, troncycleSeven, troncycleEight, troncycleTen,  troncycleTwelve, troncycleFourteen, troncycleFifteen, troncycleSeventeen, troncycleNineteen, troncycleTwentyOne);
//
// var cyclesMoveLeft = [];
// cyclesMoveLeft.push(troncycleTwo, troncycleFour, troncycleSix, troncycleNine, troncycleEleven,  troncycleThirteen, troncycleSixteen, troncycleEightteen, troncycleTwenty);

var cycleArray = [];
  for (var q = 0; q < troncycles.length; q++){
    cycleArray.push(troncycles[q])
  }

var water = [];
water.push(startZone, endZone);

var bottomLanes = [];
bottomLanes.push(cars[0], cars[1], cars[2], buses[0], buses[1], bikes[0], bikes[1]);

var topLanes = [];
topLanes.push(cars[3], cars[4], buses[2], buses[3], bikes[2], bikes[3], bikes[4]);

var topLaneDifferent = [];
topLaneDifferent.push(bikes[5], bikes[6]);

var cyclesMoveRight = [];
cyclesMoveRight.push(troncycles[0], troncycles[1], troncycles[2], troncycles[3], troncycles[8], troncycles[9], troncycles[10], troncycles[15], troncycles[16], troncycles[17], troncycles[21], troncycles[22], troncycles[23], troncycles[24]);

//GAME FUNCTIONS
  this.animate = function() {
    if(frog.level === 1) {
      this.levelOne();
    } else if(frog.level === 2) {
      this.levelTwo();
    } else if (frog.level === 3) {
      this.levelThree();
    }
  };
  this.levelOne = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    bottomLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRight();
    });
    topLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    topLaneDifferent.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeftFast();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    vehicleArray.forEach(function(vehicle) {
      frog.detectCollision(vehicle, gameLostScreen);
    });
  };
  this.levelTwo = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    bottomLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRightFast();
    });
    topLanes.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeftFast();
    });
    topLaneDifferent.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    vehicleArray.forEach(function(vehicle) {
      frog.detectCollision(vehicle, gameLostScreen);
    });
  };
  this.levelThree = function() {
    water.forEach(function(area) {
      area.draw(ctx);
    });
    midZone.drawCenterLine(ctx);
    pads.forEach(function(pad) {
      pad.draw(ctx);
    });
    cyclesMoveRight.forEach(function(obstacle) {
      obstacle.draw(ctx).moveRight();
    });
    cyclesMoveLeft.forEach(function(obstacle) {
      obstacle.draw(ctx).moveLeft();
    });
    frog.draw(ctx);
    frog.winner(levelCompleteScreen, gameWonScreen);
    frog.drowns(gameLostScreen);
    frog.livesDisplay(frogFirstLife, frogSecondLife, frogFinalLife, zeroImg);
    cycles.forEach(function(cycle) {
      frog.detectCollision(cycle, gameLostScreen);
    });
  };
}

document.addEventListener('keydown', function(event) {
  if (event.keyCode === 37) {
    frog.moveLeft(canvas);
  }
  if (event.keyCode === 38) {
    frog.moveUp(canvas);
  }
  if (event.keyCode === 39) {
    frog.moveRight(canvas);
  }
  if (event.keyCode === 40) {
    frog.moveDown(canvas);
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13 && frog.lives === 0) {
    gameLostScreen.style.display='none';
    frog.lives = 3;
    frog.level = 1;
    zeroImg.classList.add('hide');
    frogFirstLife.classList.remove('hide');
    frogSecondLife.classList.remove('hide');
    frogFinalLife.classList.remove('hide');
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13 && frog.level === 4) {
    gameWonScreen.style.display='none';
    frog.lives = 3;
    frog.level = 1;
    frogFirstLife.classList.remove('hide');
    frogSecondLife.classList.remove('hide');
    frogFinalLife.classList.remove('hide');
  }
});

document.addEventListener('keydown', function(event) {
  if (event.which === 38 && frog.lives <= 0) {
    frog.lives = 0;
    frog.x = 310;
    frog.y = 470;
  }
});

document.addEventListener('keyup', function(event) {
  if (event.which === 13) {
    levelCompleteScreen.style.display='none';
    frog.canMove = true;
  }
});

function checkForFrogLives() {
  if (frog.lives === 0) {
    frog.canMove = false;
  }
}

module.exports = Game;
<|endoftext|>


<commit_before>'use strict';

/* CI Test mode - script which purpose is to test if CI enviroment is working
 * properly by running one simple test for android and ios native layer and
 * node layer.
 */

const fs = require('fs-extra-promise');

var setUpFunctions = {

  updateUnitTestConfig: () => {
    const locationOfUnitTestConfig = '../../TestServer/UnitTestConfig.js';

    let originalContent = fs.readFileSync(locationOfUnitTestConfig);
    let newContent = originalContent.toString().replace(/numDevices: -?[0-9]/g, 'numDevices: -1');

    if (originalContent === newContent) {
      throw new Error('Replace function with regex didn\'t worked properly!');
    }

    fs.writeFileSync(locationOfUnitTestConfig, newContent);
  },

  updateThaliTestSuiteFunction: () => {
    const locationOfAndroidBeforeCompile = '../../../scripts/android/before_compile.js';

    let originalContent = fs.readFileSync(locationOfAndroidBeforeCompile);
    let newContent = originalContent.toString().replace('Test.java', 'CITest');

    fs.writeFileSync(locationOfAndroidBeforeCompile, newContent, 'utf-8');
  },

  copyCINativeTestClass: () => {
    const path = '../../../scripts/android/before_compile.js';

    let originalContent = fs.readFileSync(path);
    let oldFunc = 'var i, testClassName;';
    let newFunc = oldFunc + '\nfs.copySync(appRoot + \'/plugins/org.thaliproject.p2p/src/android/test/io/jxcore/node/CITestClass.java\', appRoot + \'/platforms/android/src/io/jxcore/node/CITestClass.java\');';
    let newContent = originalContent.toString().replace(oldFunc, newFunc);

    fs.writeFileSync(path, newContent);
  },

  updateRunTestsToRunOnlyOneNodeTest: () => {
    const locationOfRunTests = './runTests.js';

    let originalContent = fs.readFileSync(locationOfRunTests);
    let newContent = originalContent.toString().replace('fileName.indexOf(\'test\') === 0)', 'fileName.indexOf(\'CITest\') === 0)');

    fs.writeFileSync(locationOfRunTests, newContent);
  },

  copyCINodeTestClass: () => {
    fs.renameSync('bv_tests/disabled/CITestClass.js', 'bv_tests/CITestClass.js');
  },

  emptyAlliOSTestFilesButOne: (pathParam) => {
    let path;

    path = pathParam || '../../../lib/ios/ThaliCore/ThaliCoreTests';

    if (path === '../../../lib/ios/ThaliCore/ThaliCoreTests') {
      if (!fs.existsSync(path + '/SimpleTestCase.swift')) {
        throw new Error('SimpleTestCase test file was not found!');
      }
    }

    const filesArray = fs.readdirSync(path);
    let currentFilePath, i;

    for (i = 0; i < filesArray.length; i++) {
      if (filesArray[i].indexOf('SimpleTestCase') === -1) {
        currentFilePath = path + '/' + filesArray[i].toString();
        if (!fs.lstatSync(currentFilePath).isDirectory()) {
          fs.writeFileSync(currentFilePath, '');
        } else {
          setUpFunctions.emptyAlliOSTestFilesButOne(currentFilePath);
        }
      }
    }
  },
};

function runFunctionAndCheckFailures(func, errStr) {
  try {
    func();
  } catch (e) {
    console.log(e);
    console.log(errStr);
    process.exit(-1);
  }
}

for (let name in setUpFunctions) {
  if (setUpFunctions.hasOwnProperty(name)) {
    runFunctionAndCheckFailures(setUpFunctions[name], name);
  }
}

process.exit(0);
<commit_msg>Fixed swiftlint issue<commit_after>'use strict';

/* CI Test mode - script which purpose is to test if CI enviroment is working
 * properly by running one simple test for android and ios native layer and
 * node layer.
 */

const fs = require('fs-extra-promise');

var setUpFunctions = {

  updateUnitTestConfig: () => {
    const locationOfUnitTestConfig = '../../TestServer/UnitTestConfig.js';

    let originalContent = fs.readFileSync(locationOfUnitTestConfig);
    let newContent = originalContent.toString().replace(/numDevices: -?[0-9]/g, 'numDevices: -1');

    if (originalContent === newContent) {
      throw new Error('Replace function with regex didn\'t worked properly!');
    }

    fs.writeFileSync(locationOfUnitTestConfig, newContent);
  },

  updateThaliTestSuiteFunction: () => {
    const locationOfAndroidBeforeCompile = '../../../scripts/android/before_compile.js';

    let originalContent = fs.readFileSync(locationOfAndroidBeforeCompile);
    let newContent = originalContent.toString().replace('Test.java', 'CITest');

    fs.writeFileSync(locationOfAndroidBeforeCompile, newContent, 'utf-8');
  },

  copyCINativeTestClass: () => {
    const path = '../../../scripts/android/before_compile.js';

    let originalContent = fs.readFileSync(path);
    let oldFunc = 'var i, testClassName;';
    let newFunc = oldFunc + '\nfs.copySync(appRoot + \'/plugins/org.thaliproject.p2p/src/android/test/io/jxcore/node/CITestClass.java\', appRoot + \'/platforms/android/src/io/jxcore/node/CITestClass.java\');';
    let newContent = originalContent.toString().replace(oldFunc, newFunc);

    fs.writeFileSync(path, newContent);
  },

  updateRunTestsToRunOnlyOneNodeTest: () => {
    const locationOfRunTests = './runTests.js';

    let originalContent = fs.readFileSync(locationOfRunTests);
    let newContent = originalContent.toString().replace('fileName.indexOf(\'test\') === 0)', 'fileName.indexOf(\'CITest\') === 0)');

    fs.writeFileSync(locationOfRunTests, newContent);
  },

  copyCINodeTestClass: () => {
    fs.renameSync('bv_tests/disabled/CITestClass.js', 'bv_tests/CITestClass.js');
  },

  emptyAlliOSTestFilesButOne: (pathParam) => {
    let path;

    path = pathParam || '../../../lib/ios/ThaliCore/ThaliCoreTests';

    if (path === '../../../lib/ios/ThaliCore/ThaliCoreTests') {
      if (!fs.existsSync(path + '/SimpleTestCase.swift')) {
        throw new Error('SimpleTestCase test file was not found!');
      }
    }

    const filesArray = fs.readdirSync(path);
    let currentFilePath, i;

    for (i = 0; i < filesArray.length; i++) {
      if (filesArray[i].indexOf('SimpleTestCase') === -1) {
        currentFilePath = path + '/' + filesArray[i].toString();
        if (!fs.lstatSync(currentFilePath).isDirectory()) {
          fs.writeFileSync(currentFilePath, 'import Foundation\n');
        } else {
          setUpFunctions.emptyAlliOSTestFilesButOne(currentFilePath);
        }
      }
    }
  },
};

function runFunctionAndCheckFailures(func, errStr) {
  try {
    func();
  } catch (e) {
    console.log(e);
    console.log(errStr);
    process.exit(-1);
  }
}

for (let name in setUpFunctions) {
  if (setUpFunctions.hasOwnProperty(name)) {
    runFunctionAndCheckFailures(setUpFunctions[name], name);
  }
}

process.exit(0);
<|endoftext|>


<commit_before>var e = module.exports = {};
const winston = require('winston');
const moment = require('moment-timezone');
const path = require('path');
const wconfig = require('winston/lib/winston/config');

const levels = {
    killme: 0,
    error: 1,
    warn: 2,
    command: 3,
    init: 4,
    output: 5,
    irc: 6,
    website: 7,
    music: 8,
    info: 9,
    shard: 10,
    verbose: 11,
    debug: 12,
    silly: 13
};

const colors = {
    error: 'red',
    killme: 'red',
    warn: 'yellow',
    info: 'green',
    verbose: 'cyan',
    debug: 'grey',
    silly: 'magenta',
    command: 'blue',
    website: 'cyan',
    music: 'cyan',
    init: 'green',
    output: 'magenta',
    irc: 'yellow',
    shard: 'yellow',
    timestamp: 'grey',
    bold: 'bold'
};

var debug;

e.init = () => {
    debug = config.general.isbeta;
    var maxLength = 0;
    for (let key in levels) {
        if (key.length > maxLength) {
            maxLength = key.length;
        }
    }
    var logger = e.logger = new(winston.Logger)({
        levels: levels,
        colors: colors,
        level: 'debug',
        exitOnError: false,
        transports: [
            new(winston.transports.Console)({
                prettyPrint: true,
                colorize: true,
                name: 'general',
                silent: false,
                handleExceptions: true,
                stderrLevels: ['error', 'warn'],
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.

                    if (options.level == 'shard') {
                        let message = options.message.split(' ');
                        let level = pad('[' + options.level.toUpperCase() + message[0] + ']', maxLength + 2);
                        message = message.slice(1).join(' ');
                        return wconfig.colorize('timestamp', options.timestamp()) + wconfig.colorize(options.level, level) + ' ' +
                            (options.level == 'error' && options.meta && options.meta.stack ? (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) : (undefined !== message ? message : '') +
                                (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                    }
                    return wconfig.colorize('timestamp', options.timestamp()) + wconfig.colorize(options.level, pad('[' + options.level.toUpperCase() + ']', maxLength + 2)) + ' ' +
                        (options.level == 'error' && options.meta && options.meta.stack ? (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) : (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            }),
            new(winston.transports.File)({
                name: 'file-general',
                filename: path.join(__dirname, 'logs', 'generallogs.log'),
                maxsize: 10000000,
                prettyPrint: true,
                colorize: true,
                json: false,
                silent: false,
                handleExceptions: true,
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.
                    return options.timestamp() + '[' + options.level.toUpperCase() + '] ' +
                        (options.level == 'error' && options.meta && options.meta.stack ?
                            (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) :
                            (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ?
                                '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            }),
            new(winston.transports.File)({
                name: 'file-error',
                filename: path.join(__dirname, 'logs', 'errorlogs.log'),
                maxsize: 10000000,
                prettyPrint: true,
                colorize: true,
                level: 'error',
                silent: false,
                handleExceptions: true,
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.
                    return options.timestamp() + '[' + options.level.toUpperCase() + '] ' +
                        (options.level == 'error' && options.meta && options.meta.stack ?
                            (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) :
                            (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ?
                                '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            })
        ]
    });
    logger.level = debug ? 'debug' : 'info';

    logger.toggleDebug = function() {
        logger.level = debug ? 'info' : 'debug';
        debug = !debug;
        return debug;
    };
    global.logger = logger;
    return logger;
};

function pad(value, length) {
    return (value.toString().length < length) ? pad(' ' + value, length) : value;
};<commit_msg>fixed logging order<commit_after>var e = module.exports = {};
const winston = require('winston');
const moment = require('moment-timezone');
const path = require('path');
const wconfig = require('winston/lib/winston/config');

const levels = {
    killme: 0,
    error: 1,
    warn: 2,
    command: 3,
    init: 4,
    output: 5,
    irc: 6,
    website: 7,
    music: 8,
    shard: 9,
    info: 10,
    verbose: 11,
    debug: 12,
    silly: 13
};

const colors = {
    error: 'red',
    killme: 'red',
    warn: 'yellow',
    info: 'green',
    verbose: 'cyan',
    debug: 'grey',
    silly: 'magenta',
    command: 'blue',
    website: 'cyan',
    music: 'cyan',
    init: 'green',
    output: 'magenta',
    irc: 'yellow',
    shard: 'yellow',
    timestamp: 'grey',
    bold: 'bold'
};

var debug;

e.init = () => {
    debug = config.general.isbeta;
    var maxLength = 0;
    for (let key in levels) {
        if (key.length > maxLength) {
            maxLength = key.length;
        }
    }
    var logger = e.logger = new(winston.Logger)({
        levels: levels,
        colors: colors,
        level: 'debug',
        exitOnError: false,
        transports: [
            new(winston.transports.Console)({
                prettyPrint: true,
                colorize: true,
                name: 'general',
                silent: false,
                handleExceptions: true,
                stderrLevels: ['error', 'warn'],
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.

                    if (options.level == 'shard') {
                        let message = options.message.split(' ');
                        let level = pad('[' + options.level.toUpperCase() + message[0] + ']', maxLength + 2);
                        message = message.slice(1).join(' ');
                        return wconfig.colorize('timestamp', options.timestamp()) + wconfig.colorize(options.level, level) + ' ' +
                            (options.level == 'error' && options.meta && options.meta.stack ? (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) : (undefined !== message ? message : '') +
                                (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                    }
                    return wconfig.colorize('timestamp', options.timestamp()) + wconfig.colorize(options.level, pad('[' + options.level.toUpperCase() + ']', maxLength + 2)) + ' ' +
                        (options.level == 'error' && options.meta && options.meta.stack ? (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) : (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            }),
            new(winston.transports.File)({
                name: 'file-general',
                filename: path.join(__dirname, 'logs', 'generallogs.log'),
                maxsize: 10000000,
                prettyPrint: true,
                colorize: true,
                json: false,
                silent: false,
                handleExceptions: true,
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.
                    return options.timestamp() + '[' + options.level.toUpperCase() + '] ' +
                        (options.level == 'error' && options.meta && options.meta.stack ?
                            (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) :
                            (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ?
                                '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            }),
            new(winston.transports.File)({
                name: 'file-error',
                filename: path.join(__dirname, 'logs', 'errorlogs.log'),
                maxsize: 10000000,
                prettyPrint: true,
                colorize: true,
                level: 'error',
                silent: false,
                handleExceptions: true,
                timestamp: () => {
                    return `[${moment().tz('Canada/Mountain').format('MM/DD HH:mm:ss')}]`;
                },
                formatter: options => {
                    // Return string will be passed to logger.
                    return options.timestamp() + '[' + options.level.toUpperCase() + '] ' +
                        (options.level == 'error' && options.meta && options.meta.stack ?
                            (options.meta.stack.join ? options.meta.stack.join('\n') : options.meta.stack) :
                            (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ?
                                '\n\t' + JSON.stringify(options.meta, null, 2) : ''));
                }
            })
        ]
    });
    logger.level = debug ? 'debug' : 'info';

    logger.toggleDebug = function() {
        logger.level = debug ? 'info' : 'debug';
        debug = !debug;
        return debug;
    };
    global.logger = logger;
    return logger;
};

function pad(value, length) {
    return (value.toString().length < length) ? pad(' ' + value, length) : value;
};<|endoftext|>


<commit_before>var voxel = require('voxel')
var voxelMesh = require('voxel-mesh')
var interact = require('interact')
var Detector = require('./detector')
var THREE = require('three')
var Stats = require('./stats')
var PlayerControls = require('./player-controls.js')
var requestAnimationFrame = require('raf')
var inherits = require('inherits')
var EventEmitter = require('events').EventEmitter

module.exports = Game

function Game(opts) {
  if (!(this instanceof Game)) return new Game(opts)
  var self = this
  if (!opts) opts = {}

  if (opts.generate) {
    this.generateVoxelChunk = function(low, high) {
      return voxel.generate(low, high, opts.generate)
    }
  } else this.generateVoxelChunk = opts.generateVoxelChunk

  this.texturePath = opts.texturePath || '/textures/'
  this.cubeSize = opts.cubeSize || 25
  this.chunkSize = opts.chunkSize || 32
  this.chunkDistance = opts.chunkDistance || 2
  this.startingPosition = opts.startingPosition || new THREE.Vector3(35,1024,35)
  this.worldOrigin = opts.worldOrigin || new THREE.Vector3(0,0,0)
  if (opts.renderCallback) this.renderCallback = opts.renderCallback

  this.material = this.loadTextures([ 'grass', 'grass_dirt', 'brick' ])
  this.height = window.innerHeight
  this.width = window.innerWidth
  this.scene = scene = new THREE.Scene()
  this.camera = this.createCamera(scene)
  this.renderer = this.createRenderer()
  this.controls = this.createControls()
  this.addLights(this.scene)
  this.moveToPosition(this.startingPosition)
  this.voxels = voxel(this)
  this.voxels.generateMissingChunks(this.worldOrigin)
  Object.keys(this.voxels.chunks).map(function(chunkIndex) {
    self.showChunk(self.voxels.chunks[chunkIndex])
  })
  this.addStats()
  window.addEventListener('resize', this.onWindowResize.bind(this), false)
  window.addEventListener('mousedown', this.onMouseDown.bind(this), false)
  window.addEventListener('mouseup', this.onMouseUp.bind(this), false)
  requestAnimationFrame(window).on('data', this.tick.bind(this))
}

inherits(Game, EventEmitter)

Game.prototype.setupPointerLock = function(element) {
  var self = this
  element = element || document.body
  if (typeof element !== 'object') element = document.querySelector(element)
  var pointer = this.pointer = interact(document.body)
  if (!pointer.pointerAvailable()) this.pointerLockDisabled = true
  pointer.on('attain', function(movements) {
    self.controls.enabled = true
    movements.pipe(self.controls)
  })
  pointer.on('release', function() {
    self.controls.enabled = false
  })
  pointer.on('error', function() {
    // user denied pointer lock OR it's not available
    self.pointerLockDisabled = true
    console.error('pointerlock error')
  })
}

Game.prototype.requestPointerLock = function(element) {
  if (!this.pointer) this.setupPointerLock(element)
  this.pointer.request()
}

Game.prototype.moveToPosition = function(position) {
  var pos = this.controls.yawObject.position
  pos.x = position.x
  pos.y = position.y
  pos.z = position.z
}

Game.prototype.onWindowResize = function() {
  this.camera.aspect = window.innerWidth / window.innerHeight
  this.camera.updateProjectionMatrix()
  this.renderer.setSize( window.innerWidth, window.innerHeight )
}

Game.prototype.addMarker = function(position) {
  var geometry = new THREE.SphereGeometry( 1, 4, 4 );
  var material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
  var mesh = new THREE.Mesh( geometry, material );
  mesh.position.copy(position)
  this.scene.add(mesh)
}

Game.prototype.onMouseDown = function(e) {
  var intersection = this.raycast()
  if (intersection) this.emit('mousedown', intersection, e)
}

Game.prototype.onMouseUp = function(e) {
  var intersection = this.raycast()
  if (intersection) this.emit('mouseup', intersection, e)
}

Game.prototype.intersectAllMeshes = function(start, direction) {
  var self = this
  var meshes = []
  Object.keys(self.voxels.meshes).map(function(key) {
    meshes.push(self.voxels.meshes[key].surfaceMesh)
  })
  var d = direction.subSelf(start).normalize()
  var ray = new THREE.Raycaster(start, d)
  var intersections = ray.intersectObjects( meshes )
  if (intersections.length === 0) return false
  var intersection = intersections[0]
  var p = new THREE.Vector3()
  p.copy(intersection.point)
  p.x += d.x
  p.y += d.y
  p.z += d.z
  return p
}

Game.prototype.raycast = function() {
  var start = this.controls.yawObject.position.clone()
  var direction = this.camera.matrixWorld.multiplyVector3(new THREE.Vector3(0,0,-1))
  var intersects = this.intersectAllMeshes(start, direction)
  return intersects
}

Game.prototype.loadTextures = function(names) {
  var self = this;
  return new THREE.MeshFaceMaterial(names.map(function (name) {
    var tex = THREE.ImageUtils.loadTexture(self.texturePath + name + ".png")
    tex.magFilter = THREE.NearestFilter
    tex.minFilter = THREE.LinearMipMapLinearFilter

    return new THREE.MeshLambertMaterial({
      map: tex,
      ambient: 0xbbbbbb
    })
  }))
}

Game.prototype.createCamera = function() {
  var camera;
  camera = new THREE.PerspectiveCamera(60, this.width / this.height, 1, 10000)
  camera.lookAt(new THREE.Vector3(0, 0, 0))
  this.scene.add(camera)
  return camera
}

Game.prototype.createControls = function() {
  var controls = new PlayerControls(this.camera)
  this.scene.add( controls.yawObject )
  return controls
}

Game.prototype.createRenderer = function() {
  if( Detector.webgl ){
    this.renderer = new THREE.WebGLRenderer({
      antialias: true
    })
  } else {
    this.renderer = new THREE.CanvasRenderer()
  }
  this.renderer.setSize(this.width, this.height)
  this.renderer.setClearColorHex(0xBFD1E5, 1.0)
  this.renderer.clear()
  this.element = this.renderer.domElement
  return this.renderer
}

Game.prototype.appendTo = function (element) {
  if (typeof element === 'object') {
    element.appendChild(this.element)
  }
  else {
    document.querySelector(element).appendChild(this.element)
  }
}

Game.prototype.addStats = function() {
  stats = new Stats()
  stats.domElement.style.position  = 'absolute'
  stats.domElement.style.bottom  = '0px'
  document.body.appendChild( stats.domElement )
}

Game.prototype.cameraRotation = function() {
  var xAngle = this.controls.pitchObject.rotation.x
  var yAngle = this.controls.yawObject.rotation.y
  return {x: xAngle, y: yAngle}
}

Game.prototype.getCollisions = function(position, checker) {
  var self = this
  var p = position.clone()
  var w = self.cubeSize / 4 // width of player cube
  var h = self.cubeSize * 1.5 // height of player cube

  var vertices = {
    bottom: [
      new THREE.Vector3(p.x - w, p.y - h, p.z - w),
      new THREE.Vector3(p.x - w, p.y - h, p.z + w),
      new THREE.Vector3(p.x + w, p.y - h, p.z - w),
      new THREE.Vector3(p.x + w, p.y - h, p.z + w)
    ],
    middle: [
      new THREE.Vector3(p.x - w, p.y - h / 2, p.z - w),
      new THREE.Vector3(p.x - w, p.y - h / 2, p.z + w),
      new THREE.Vector3(p.x + w, p.y - h / 2, p.z - w),
      new THREE.Vector3(p.x + w, p.y - h / 2, p.z + w)
    ],
    top: [
      new THREE.Vector3(p.x - w, p.y, p.z - w),
      new THREE.Vector3(p.x - w, p.y, p.z + w),
      new THREE.Vector3(p.x + w, p.y, p.z - w),
      new THREE.Vector3(p.x + w, p.y, p.z + w)
    ],
  }

  return {
    bottom: vertices.bottom.map(check).filter(Boolean),
    middle: vertices.middle.map(check).filter(Boolean),
    top: vertices.top.map(check).filter(Boolean)
  }

  function check(vertex) {
    if (checker) return checker(vertex) && vertex
    return self.voxels.voxelAtPosition(vertex) && vertex
  }
}

Game.prototype.addLights = function(scene) {
  var ambientLight, directionalLight
  ambientLight = new THREE.AmbientLight(0xaaaaaa)
  scene.add(ambientLight)
  var light	= new THREE.DirectionalLight( 0xffffff )
  light.position.set( Math.random(), Math.random(), Math.random() ).normalize()
  scene.add( light )
};

Game.prototype.currentMesh = function() {
  var cid = this.voxels.chunkAtPosition(this.controls.yawObject.position).join('|')
  return this.voxels.meshes[cid]
}

Game.prototype.createBlock = function(pos, val) {
  var self = this
  var direction = self.camera.matrixWorld.multiplyVector3(new THREE.Vector3(0,0,-1))
  var start = self.controls.yawObject.position.clone()
  var d = direction.subSelf(start).normalize()

  var p = new THREE.Vector3()
  p.copy(pos)
  p.x -= 1.1 * d.x
  p.y -= 1.1 * d.y
  p.z -= 1.1 * d.z
  var block = self.getBlock(p)
  if (block) return false

  var vidx = self.voxels.voxelIndex(p)
  var c = self.voxels.chunkAtPosition(p)
  var ckey = c.join('|')
  var chunk = self.voxels.chunks[ckey]
  if (!chunk) return false

  var collisions = self.getCollisions(self.controls.yawObject.position, check)
  if (collisions.top.length) return false
  if (collisions.middle.length) return false
  if (collisions.bottom.length) return false

  chunk.voxels[vidx] = val
  this.showChunk(this.voxels.chunks[c.join('|')])
  return true

  function check(v) { return vidx === self.voxels.voxelIndex(v) }
}

Game.prototype.setBlock = function(pos, val) {
  var hitVoxel = this.voxels.voxelAtPosition(pos, val)
  var c = this.voxels.chunkAtPosition(pos)
  this.showChunk(this.voxels.chunks[c.join('|')])
}

Game.prototype.getBlock = function(pos) {
  return this.voxels.voxelAtPosition(pos)
}

Game.prototype.showChunk = function(chunk) {
  var chunkIndex = chunk.position.join('|')
  var bounds = this.voxels.getBounds.apply(this.voxels, chunk.position)
  var cubeSize = this.cubeSize
  var scale = new THREE.Vector3(cubeSize, cubeSize, cubeSize)
  var mesh = voxelMesh(chunk, scale)
  this.voxels.chunks[chunkIndex] = chunk
  if (this.voxels.meshes[chunkIndex]) this.scene.remove(this.voxels.meshes[chunkIndex].surfaceMesh)
  this.voxels.meshes[chunkIndex] = mesh
  mesh.createSurfaceMesh(this.material)
  mesh.setPosition(bounds[0][0] * cubeSize, bounds[0][1] * cubeSize, bounds[0][2] * cubeSize)
  mesh.addToScene(this.scene)
  this.applyTextures(mesh.geometry)
  return mesh
}

Game.prototype.applyTextures = function (geom) {
  var self = this;

  var vmap = []
  for (var i = 0; i < geom.vertices.length; i += 4) {
    vmap.push([
      geom.vertices[i+0],
      geom.vertices[i+1],
      geom.vertices[i+2],
      geom.vertices[i+3]
    ])
  }

  geom.faces.forEach(function (face, ix) {
    if (Math.abs(face.normal.y) === 1) {
      face.materialIndex = 0
    }
    else {
      face.materialIndex = 1
    }
  })
}

Game.prototype.tick = function(dt) {
  var self = this
  this.controls.tick(dt, function () {
    var collisions = self.getCollisions(this.yawObject.position)

    if (collisions.middle.length || collisions.top.length) {
      this.yawObject.translateX(-this.velocity.x)
      this.yawObject.translateY(-this.velocity.y)
      this.yawObject.translateZ(-this.velocity.z)
      this.velocity.x *= -1
      this.velocity.z *= -1
      this.velocity.y = Math.min(0, this.velocity.y)
    }

    if (collisions.bottom.length) {
      this.gravityEnabled = false
      this.velocity.y = Math.max(0, this.velocity.y)
    }
    else {
      this.gravityEnabled = true
    }
  })
  if (this.renderCallback) this.renderCallback.call(this)
  this.renderer.render(this.scene, this.camera)
  stats.update()
}
<commit_msg>textures now based on voxel data<commit_after>var voxel = require('voxel')
var voxelMesh = require('voxel-mesh')
var interact = require('interact')
var Detector = require('./detector')
var THREE = require('three')
var Stats = require('./stats')
var PlayerControls = require('./player-controls.js')
var requestAnimationFrame = require('raf')
var inherits = require('inherits')
var EventEmitter = require('events').EventEmitter

module.exports = Game

function Game(opts) {
  if (!(this instanceof Game)) return new Game(opts)
  var self = this
  if (!opts) opts = {}

  if (opts.generate) {
    this.generateVoxelChunk = function(low, high) {
      return voxel.generate(low, high, opts.generate)
    }
  } else this.generateVoxelChunk = opts.generateVoxelChunk

  this.texturePath = opts.texturePath || '/textures/'
  this.cubeSize = opts.cubeSize || 25
  this.chunkSize = opts.chunkSize || 32
  this.chunkDistance = opts.chunkDistance || 2
  this.startingPosition = opts.startingPosition || new THREE.Vector3(35,1024,35)
  this.worldOrigin = opts.worldOrigin || new THREE.Vector3(0,0,0)
  if (opts.renderCallback) this.renderCallback = opts.renderCallback

  this.materials = opts.materials || [ 'grass' ]
  this.material = this.loadTextures(this.materials)

  this.height = window.innerHeight
  this.width = window.innerWidth
  this.scene = scene = new THREE.Scene()
  this.camera = this.createCamera(scene)
  this.renderer = this.createRenderer()
  this.controls = this.createControls()
  this.addLights(this.scene)
  this.moveToPosition(this.startingPosition)
  this.voxels = voxel(this)
  this.voxels.generateMissingChunks(this.worldOrigin)
  Object.keys(this.voxels.chunks).map(function(chunkIndex) {
    self.showChunk(self.voxels.chunks[chunkIndex])
  })
  this.addStats()
  window.addEventListener('resize', this.onWindowResize.bind(this), false)
  window.addEventListener('mousedown', this.onMouseDown.bind(this), false)
  window.addEventListener('mouseup', this.onMouseUp.bind(this), false)
  requestAnimationFrame(window).on('data', this.tick.bind(this))
}

inherits(Game, EventEmitter)

Game.prototype.setupPointerLock = function(element) {
  var self = this
  element = element || document.body
  if (typeof element !== 'object') element = document.querySelector(element)
  var pointer = this.pointer = interact(document.body)
  if (!pointer.pointerAvailable()) this.pointerLockDisabled = true
  pointer.on('attain', function(movements) {
    self.controls.enabled = true
    movements.pipe(self.controls)
  })
  pointer.on('release', function() {
    self.controls.enabled = false
  })
  pointer.on('error', function() {
    // user denied pointer lock OR it's not available
    self.pointerLockDisabled = true
    console.error('pointerlock error')
  })
}

Game.prototype.requestPointerLock = function(element) {
  if (!this.pointer) this.setupPointerLock(element)
  this.pointer.request()
}

Game.prototype.moveToPosition = function(position) {
  var pos = this.controls.yawObject.position
  pos.x = position.x
  pos.y = position.y
  pos.z = position.z
}

Game.prototype.onWindowResize = function() {
  this.camera.aspect = window.innerWidth / window.innerHeight
  this.camera.updateProjectionMatrix()
  this.renderer.setSize( window.innerWidth, window.innerHeight )
}

Game.prototype.addMarker = function(position) {
  var geometry = new THREE.SphereGeometry( 1, 4, 4 );
  var material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
  var mesh = new THREE.Mesh( geometry, material );
  mesh.position.copy(position)
  this.scene.add(mesh)
}

Game.prototype.onMouseDown = function(e) {
  var intersection = this.raycast()
  if (intersection) this.emit('mousedown', intersection, e)
}

Game.prototype.onMouseUp = function(e) {
  var intersection = this.raycast()
  if (intersection) this.emit('mouseup', intersection, e)
}

Game.prototype.intersectAllMeshes = function(start, direction) {
  var self = this
  var meshes = []
  Object.keys(self.voxels.meshes).map(function(key) {
    meshes.push(self.voxels.meshes[key].surfaceMesh)
  })
  var d = direction.subSelf(start).normalize()
  var ray = new THREE.Raycaster(start, d)
  var intersections = ray.intersectObjects( meshes )
  if (intersections.length === 0) return false
  var intersection = intersections[0]
  var p = new THREE.Vector3()
  p.copy(intersection.point)
  p.x += d.x
  p.y += d.y
  p.z += d.z
  return p
}

Game.prototype.raycast = function() {
  var start = this.controls.yawObject.position.clone()
  var direction = this.camera.matrixWorld.multiplyVector3(new THREE.Vector3(0,0,-1))
  var intersects = this.intersectAllMeshes(start, direction)
  return intersects
}

Game.prototype.loadTextures = function(names) {
  var self = this
  return new THREE.MeshFaceMaterial(names.map(function (name) {
    var tex = THREE.ImageUtils.loadTexture(self.texturePath + name + ".png")
    tex.magFilter = THREE.NearestFilter
    tex.minFilter = THREE.LinearMipMapLinearFilter

    return new THREE.MeshLambertMaterial({
      map: tex,
      ambient: 0xbbbbbb
    })
  }))
}

Game.prototype.createCamera = function() {
  var camera;
  camera = new THREE.PerspectiveCamera(60, this.width / this.height, 1, 10000)
  camera.lookAt(new THREE.Vector3(0, 0, 0))
  this.scene.add(camera)
  return camera
}

Game.prototype.createControls = function() {
  var controls = new PlayerControls(this.camera)
  this.scene.add( controls.yawObject )
  return controls
}

Game.prototype.createRenderer = function() {
  if( Detector.webgl ){
    this.renderer = new THREE.WebGLRenderer({
      antialias: true
    })
  } else {
    this.renderer = new THREE.CanvasRenderer()
  }
  this.renderer.setSize(this.width, this.height)
  this.renderer.setClearColorHex(0xBFD1E5, 1.0)
  this.renderer.clear()
  this.element = this.renderer.domElement
  return this.renderer
}

Game.prototype.appendTo = function (element) {
  if (typeof element === 'object') {
    element.appendChild(this.element)
  }
  else {
    document.querySelector(element).appendChild(this.element)
  }
}

Game.prototype.addStats = function() {
  stats = new Stats()
  stats.domElement.style.position  = 'absolute'
  stats.domElement.style.bottom  = '0px'
  document.body.appendChild( stats.domElement )
}

Game.prototype.cameraRotation = function() {
  var xAngle = this.controls.pitchObject.rotation.x
  var yAngle = this.controls.yawObject.rotation.y
  return {x: xAngle, y: yAngle}
}

Game.prototype.getCollisions = function(position, checker) {
  var self = this
  var p = position.clone()
  var w = self.cubeSize / 4 // width of player cube
  var h = self.cubeSize * 1.5 // height of player cube

  var vertices = {
    bottom: [
      new THREE.Vector3(p.x - w, p.y - h, p.z - w),
      new THREE.Vector3(p.x - w, p.y - h, p.z + w),
      new THREE.Vector3(p.x + w, p.y - h, p.z - w),
      new THREE.Vector3(p.x + w, p.y - h, p.z + w)
    ],
    middle: [
      new THREE.Vector3(p.x - w, p.y - h / 2, p.z - w),
      new THREE.Vector3(p.x - w, p.y - h / 2, p.z + w),
      new THREE.Vector3(p.x + w, p.y - h / 2, p.z - w),
      new THREE.Vector3(p.x + w, p.y - h / 2, p.z + w)
    ],
    top: [
      new THREE.Vector3(p.x - w, p.y, p.z - w),
      new THREE.Vector3(p.x - w, p.y, p.z + w),
      new THREE.Vector3(p.x + w, p.y, p.z - w),
      new THREE.Vector3(p.x + w, p.y, p.z + w)
    ],
  }

  return {
    bottom: vertices.bottom.map(check).filter(Boolean),
    middle: vertices.middle.map(check).filter(Boolean),
    top: vertices.top.map(check).filter(Boolean)
  }

  function check(vertex) {
    if (checker) return checker(vertex) && vertex
    return self.voxels.voxelAtPosition(vertex) && vertex
  }
}

Game.prototype.addLights = function(scene) {
  var ambientLight, directionalLight
  ambientLight = new THREE.AmbientLight(0xaaaaaa)
  scene.add(ambientLight)
  var light	= new THREE.DirectionalLight( 0xffffff )
  light.position.set( Math.random(), Math.random(), Math.random() ).normalize()
  scene.add( light )
};

Game.prototype.currentMesh = function() {
  var cid = this.voxels.chunkAtPosition(this.controls.yawObject.position).join('|')
  return this.voxels.meshes[cid]
}

Game.prototype.createBlock = function(pos, val) {
  var self = this
  var direction = self.camera.matrixWorld.multiplyVector3(new THREE.Vector3(0,0,-1))
  var start = self.controls.yawObject.position.clone()
  var d = direction.subSelf(start).normalize()

  var p = new THREE.Vector3()
  p.copy(pos)
  p.x -= 1.1 * d.x
  p.y -= 1.1 * d.y
  p.z -= 1.1 * d.z
  var block = self.getBlock(p)
  if (block) return false

  var vidx = self.voxels.voxelIndex(p)
  var c = self.voxels.chunkAtPosition(p)
  var ckey = c.join('|')
  var chunk = self.voxels.chunks[ckey]
  if (!chunk) return false

  var collisions = self.getCollisions(self.controls.yawObject.position, check)
  if (collisions.top.length) return false
  if (collisions.middle.length) return false
  if (collisions.bottom.length) return false

  chunk.voxels[vidx] = val
  this.showChunk(this.voxels.chunks[c.join('|')])
  return true

  function check(v) { return vidx === self.voxels.voxelIndex(v) }
}

Game.prototype.setBlock = function(pos, val) {
  var hitVoxel = this.voxels.voxelAtPosition(pos, val)
  var c = this.voxels.chunkAtPosition(pos)
  this.showChunk(this.voxels.chunks[c.join('|')])
}

Game.prototype.getBlock = function(pos) {
  return this.voxels.voxelAtPosition(pos)
}

Game.prototype.showChunk = function(chunk) {
  var chunkIndex = chunk.position.join('|')
  var bounds = this.voxels.getBounds.apply(this.voxels, chunk.position)
  var cubeSize = this.cubeSize
  var scale = new THREE.Vector3(cubeSize, cubeSize, cubeSize)
  var mesh = voxelMesh(chunk, scale)
  this.voxels.chunks[chunkIndex] = chunk
  if (this.voxels.meshes[chunkIndex]) this.scene.remove(this.voxels.meshes[chunkIndex].surfaceMesh)
  this.voxels.meshes[chunkIndex] = mesh
  mesh.createSurfaceMesh(this.material)
  mesh.setPosition(bounds[0][0] * cubeSize, bounds[0][1] * cubeSize, bounds[0][2] * cubeSize)
  mesh.addToScene(this.scene)
  this.applyTextures(mesh.geometry)
  return mesh
}

Game.prototype.applyTextures = function (geom) {
  var self = this;

  geom.faces.forEach(function (face, ix) {
    var c = face.vertexColors[0]
    var index = Math.floor(c.b*255 + c.g*255*255 + c.r*255*255*255)
    face.materialIndex = index % self.materials.length
  })
}

Game.prototype.tick = function(dt) {
  var self = this
  this.controls.tick(dt, function () {
    var collisions = self.getCollisions(this.yawObject.position)

    if (collisions.middle.length || collisions.top.length) {
      this.yawObject.translateX(-this.velocity.x)
      this.yawObject.translateY(-this.velocity.y)
      this.yawObject.translateZ(-this.velocity.z)
      this.velocity.x *= -1
      this.velocity.z *= -1
      this.velocity.y = Math.min(0, this.velocity.y)
    }

    if (collisions.bottom.length) {
      this.gravityEnabled = false
      this.velocity.y = Math.max(0, this.velocity.y)
    }
    else {
      this.gravityEnabled = true
    }
  })
  if (this.renderCallback) this.renderCallback.call(this)
  this.renderer.render(this.scene, this.camera)
  stats.update()
}
<|endoftext|>