<commit_before>var ToolTypeEnum = {
  RADIO: 1,
  RADIOLIST: 2,
  BUTTON: 3,
  CHECK: 4,
  SLIDE: 5,
  HELP: 6
};
Object.freeze(ToolTypeEnum);

class ToolBarItem {
  /**
   * Create a ToolBarItem that can be any type listed in ToolTypeEnum.
   * @param {string|String[]} name
   * @param {string} id
   * @param {string} img popover image.
   * @param {number|ToolTypeEnum} type any type listed in ToolTypeEnum.
   * @param {ToolBarItem[]|undefined} content the list of items in RADIOLIST.
   * @param {function|undefined} action the action that triggers on BUTTON click.
   * @param {number|undefined} min the minimum value in SLIDE.
   * @param {number|undefined} max the maximum value in SLIDE.
   * @param {number|undefined} step the step size in SLIDE.
   * @param {number|undefined} value the current value in SLIDE.
   */
  constructor(name, id, img, type, content, action, min, max, step, value) {
    this.name = name;
    this.id = id;
    this.img = img;

    //@param {string|number} description popover description or z-index for RADIOLIST.
    this.description = "";//description;

    //Warning: Dirty code below.
    if (this.name == "Mirrors")
      this.description = 4;
    else if (this.name == "Glasses")
      this.description = 3;
    else if (this.name == "Point Source")
      this.description = 6;
    else if (this.name == "Blockers")
      this.description = 7;
    else if (this.name == "Samples")
      this.description = 5;
    else
      this.description = getMsg(this.id + "_popover");

    this.type = type;
    this.selected = "";
    this.content = content;
    if (this.type == ToolTypeEnum.RADIOLIST) {
      for (var i = 0; i < content.length; i++) {
        this.selected = ko.observable(content[i].name);
        break;
      }
    } else if (this.type == ToolTypeEnum.CHECK) {
      this.selected = ko.observable(false);
    } else if (this.type == ToolTypeEnum.BUTTON) {
      this.action = action;
    } else if (this.type == ToolTypeEnum.SLIDE) {
      this.min = ko.observable(min);
      this.max = ko.observable(max);
      this.step = ko.observable(step);
      this.value = ko.observable(value);
    }
    else if (this.type == ToolTypeEnum.HELP) {
      this.selected = ko.observable(true);
    }
    //console.log(this);
  }
  getTitle() {
    return "" + this.getLocaleName() + "";
  }
  getLocaleName() {
    return getMsg(this.id);
  }
  getContent() {
    var image = "";
    if (this.img != undefined)
      image = "";
    return image + "" + this.description + "";
  }
}

class ToolBarGroup {
  /**
   * Creates a ToolBarGroup that results in a new toolgroup row in toolbar.
   * @param {string} title
   * @param {ToolBarItem[]} tools
   * @constructor
   */
  constructor(title, tools) {
    this.title = title;
    this.tools = tools;
    for (var i = 0; i < tools.length; i++) {
      this.selected = ko.observable(tools[i].name);
      break;
    }
  }
  getLocaleName() {
    return getMsg(this.title);
  }
}
<commit_msg>Fix z-index issue (#53)<commit_after>var ToolTypeEnum = {
  RADIO: 1,
  RADIOLIST: 2,
  BUTTON: 3,
  CHECK: 4,
  SLIDE: 5,
  HELP: 6
};
Object.freeze(ToolTypeEnum);

class ToolBarItem {
  /**
   * Create a ToolBarItem that can be any type listed in ToolTypeEnum.
   * @param {string|String[]} name
   * @param {string} id
   * @param {string} img popover image.
   * @param {number|ToolTypeEnum} type any type listed in ToolTypeEnum.
   * @param {ToolBarItem[]|undefined} content the list of items in RADIOLIST.
   * @param {function|undefined} action the action that triggers on BUTTON click.
   * @param {number|undefined} min the minimum value in SLIDE.
   * @param {number|undefined} max the maximum value in SLIDE.
   * @param {number|undefined} step the step size in SLIDE.
   * @param {number|undefined} value the current value in SLIDE.
   */
  constructor(name, id, img, type, content, action, min, max, step, value) {
    this.name = name;
    this.id = id;
    this.img = img;

    //@param {string|number} description popover description or z-index for RADIOLIST.
    this.description = "";//description;

    // Currently, a hack is used to make the RADIOLIST dropdown menu appear
    // above other toolbar buttons. This hack requires setting the
    // `description` of the RADIOLIST to represent its z-index. This
    // value should monotonically decrease for each RADIOLIST
    // (from left to right, top to bottom).
    //
    // This works because a higher z-index button will always appear above a
    // lower z-index one, and a button will never be covered by a dropdown menu
    // of another RADIOLIST button at its right or below it. Therefore, the
    // z-index of a button must be higher than all buttons at its right or
    // below.
    //
    // The current approach is far from ideal. A better approach is to make
    // the buttons in the dropdown menu to have higher z-indices than normal
    // buttons. However, this is currently not possible due to unknown reasons.
    //
    // TL;DR: For each RADIOLIST button, its `description` must be set to a
    //        value higher than all RADIOLIST buttons at its right or below.
    //        This value should be updated whenever a new RADIOLIST button is
    //        added or reordered.
    if (this.name == "Glasses")
      this.description = 3;
    else if (this.name == "Mirrors")
      this.description = 4;
    else if (this.name == "Blockers")
      this.description = 5;
    else if (this.name == "Point Source")
      this.description = 6;
    else if (this.name == "Samples")
      this.description = 7;
    else
      this.description = getMsg(this.id + "_popover");

    this.type = type;
    this.selected = "";
    this.content = content;
    if (this.type == ToolTypeEnum.RADIOLIST) {
      for (var i = 0; i < content.length; i++) {
        this.selected = ko.observable(content[i].name);
        break;
      }
    } else if (this.type == ToolTypeEnum.CHECK) {
      this.selected = ko.observable(false);
    } else if (this.type == ToolTypeEnum.BUTTON) {
      this.action = action;
    } else if (this.type == ToolTypeEnum.SLIDE) {
      this.min = ko.observable(min);
      this.max = ko.observable(max);
      this.step = ko.observable(step);
      this.value = ko.observable(value);
    }
    else if (this.type == ToolTypeEnum.HELP) {
      this.selected = ko.observable(true);
    }
    //console.log(this);
  }
  getTitle() {
    return "" + this.getLocaleName() + "";
  }
  getLocaleName() {
    return getMsg(this.id);
  }
  getContent() {
    var image = "";
    if (this.img != undefined)
      image = "";
    return image + "" + this.description + "";
  }
}

class ToolBarGroup {
  /**
   * Creates a ToolBarGroup that results in a new toolgroup row in toolbar.
   * @param {string} title
   * @param {ToolBarItem[]} tools
   * @constructor
   */
  constructor(title, tools) {
    this.title = title;
    this.tools = tools;
    for (var i = 0; i < tools.length; i++) {
      this.selected = ko.observable(tools[i].name);
      break;
    }
  }
  getLocaleName() {
    return getMsg(this.title);
  }
}
<|endoftext|>


<commit_before>'use strict';
$(document).ready(function() {

  $('#filter-company').selectize({
      plugins: ['remove_button'],
      sortField: 'text'
  });

  $('#filter-fund').selectize({
      plugins: ['remove_button'],
      sortField: 'text'
  });

  $('[data-toggle=popover]').popover({
    html: true,
    trigger: 'hover'
  });

  $('[data-toggle=tooltip]').tooltip({
    html: true,
    trigger: 'hover'
  });

  var visited = $.cookie('visited'); // create the cookie
  if (visited == 'yes') {
      return false; // second page load, cookie is active so do nothing
  } else {
      $('#howToSearchModal').modal();; // first page load, launch modal
  };
  // assign cookie's value and expiration time
  $.cookie('visited', 'yes', {
      expires: 7 // the number of days the cookie will be effective
  });

});

/* This functions makes the scrollbar fixed to the top as scrolling down */
$(document).ready(function () {
  var menu = $('.sort-menu');
  var origOffsetY = menu.offset().top;

  function scroll() {
      if ($(window).scrollTop() >= origOffsetY) {
          $('.sort-menu').addClass('navbar-fixed-top');
          $('.content').addClass('menu-padding');
      } else {
          $('.sort-menu').removeClass('navbar-fixed-top');
          $('.content').removeClass('menu-padding');
      }
  }
  document.onscroll = scroll;
});
<commit_msg>cookie duration changed to one day<commit_after>'use strict';
$(document).ready(function() {

  $('#filter-company').selectize({
      plugins: ['remove_button'],
      sortField: 'text'
  });

  $('#filter-fund').selectize({
      plugins: ['remove_button'],
      sortField: 'text'
  });

  $('[data-toggle=popover]').popover({
    html: true,
    trigger: 'hover'
  });

  $('[data-toggle=tooltip]').tooltip({
    html: true,
    trigger: 'hover'
  });

  var visited = $.cookie('visited'); // create the cookie
  if (visited == 'yes') {
      return false; // second page load, cookie is active so do nothing
  } else {
      $('#howToSearchModal').modal();; // first page load, launch modal
  };
  // assign cookie's value and expiration time
  $.cookie('visited', 'yes', {
      expires: 1 // the number of days the cookie will be effective
  });

});

/* This functions makes the scrollbar fixed to the top as scrolling down */
$(document).ready(function () {
  var menu = $('.sort-menu');
  var origOffsetY = menu.offset().top;

  function scroll() {
      if ($(window).scrollTop() >= origOffsetY) {
          $('.sort-menu').addClass('navbar-fixed-top');
          $('.content').addClass('menu-padding');
      } else {
          $('.sort-menu').removeClass('navbar-fixed-top');
          $('.content').removeClass('menu-padding');
      }
  }
  document.onscroll = scroll;
});
<|endoftext|>


<commit_before>// Import the Mongoose module.
var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

// Set the data types, properties and default values to our Schema.
var SpeakerSchema   = new Schema({
    name:           { type: String, default: '' },
    company:        { type: String, default: '' },
    title:          { type: String, default: '' },
    description:    { type: String, default: '' },
    picture:        { type: String, default: '' },
    schedule:       { type: String, default: '' },
    createdOn:      { type: Date,   default: Date.now}
});
module.exports = mongoose.model('Speaker', SpeakerSchema);<commit_msg>Changed default for name<commit_after>// Import the Mongoose module.
var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

// Set the data types, properties and default values to our Schema.
var SpeakerSchema   = new Schema({
    name:           { type: String, default: 'Fred' },
    company:        { type: String, default: '' },
    title:          { type: String, default: '' },
    description:    { type: String, default: '' },
    picture:        { type: String, default: '' },
    schedule:       { type: String, default: '' },
    createdOn:      { type: Date,   default: Date.now}
});
module.exports = mongoose.model('Speaker', SpeakerSchema);<|endoftext|>


<commit_before>(function(){
/**
 * IX.State is simple state-machine utilities:{
	toggle(origStat, newStat) : if newStat give, return newStat, otherwise return !origStat
 * }
 *
 * IX.IManager is a Class to deal with key/value safely. It provide:
 * @Methods :{
	isRegistered(key) : check if key exist;
	register(key, value) : set the key mapped to value
	unregister(key) : clear the key's value
	get(key) : get the value mapped by key,
	clear() : clear all key/value;
 * }
 *
 * IX.IList is a Class to deal with Array easily. It provide:
 * @Methods : {
	isEmpty() : check if list is empty
	isLast(k) : check if k is last element in list
	getList() : return whole list
	getSize() : return the length of list
	indexOf(key) : return the index of key in list
	remove(idx) : remove the element in list idx position
	tryRemove(key): try remove key from list if existed
	append(key) : remove existed key and append key to last position in list
	tryAdd(key) : append key only if it is inexisted in list
	insertBefore(key, dstKey) : remove key if existed and insert it before dstkey, or append it if dstKey not existed
	clear() : clean all list
 * }
 *
 * IX.I1ToNManager is a Class to deal with special key/value which one key mapped to many values. It provide:
 * @Methods : {
  	@Methods(IX.IManager)

  	getKeys() : get all key in sequence in store
	hasValue(key) : check if any value is mapped by key
	put(k, v) : map k to v
	remove(k, v) : unmap v by k
	clear() : clear store
 * }
 *
 * IX.IListManager will manage key/value store with ordered key list. It provide:
 * @Methods : {
  	@Methods(IX.IManager)

  	register(key, value) : @Override append the key to the last of list
	unregister(key) :  @Override remove the entry for key from store
	isEmpty() : check if store is empty
	getSize() : get the size of store
	hasKey(key) : check if key is in store
	isLastKey(key) : check if key is the last in store
	getKeys() : get all key in sequence in store
	getByKeys(keys) :  get all values mapped by keys
	getAll() : get all values in store
	iterate(fn) :  for each value, iterate to execure fn(value, key)
	getFirst() : get the first meaningful value

	append(key) :  only append key to store's key list, will not changed value
	insertBefore(key, dstKey) : only for key, same as IX.IList.insertBefore,
	remove(key) : same as unregister, remove entry and value by key.
	clear() : clear the store
 * }
 *
 * IX.IPagedManager will manage key/value store with ordered key list in paged info.
 * params :
	newInstFn : function(item){return itemModel;} // to create model for item
	instHT : null or instance of IX.IListManager  // if null, will create HT of IListManager
	dataCaller : function({pageNo, pageSize}, cbFn({total, items: [item]})) // dynamic load data for paged data
 * @Methods : {
	get : function(id){return itemModel;},
	getFirst : function(){return firstItemModel;},
	// getSize : function(){return sizeInHT;},
	getTotal : function(){return total;},

	load : load(pageNo, pageSize, cbFn([itemModel]), lazyLoad)
	putData : function({total, items}, startPos),
	addItems : function(itemIds){} // only change total and clear page info;
	removeItems : function(itemIds){}, // remove itemModels in HT, change total and clear page info;
	// iterate : function(fn), // iterate all itemModels in HT,
	clear : function(){ids = [];} // clear page info;
 * }
 *
 * IX.formatDataStore is an utilities handle with JSON data , for example
 * if convert JSON like :
 *  {
  		type : "array"/"json", [option; default :"json"]
 *		1: for array:
  		fields :["name1", "name2", ...],
  		items:[ [value1, value2, ...], ...]
 * 		2: for json:
  		items : [{name1: value1, name2: value2},...]
 *  } to Array like :
 *  [{name1: value1, name2: value2},...]
 *
 */
IX.State = {
	toggle :function(origStat, newStat){
		return (newStat===undefined)?!origStat : newStat;
	}
};

IX.IManager = function(){
	var _ht = {};
	return {
		isRegistered : function(name){
			return (name in _ht) && (_ht[name]);
		},
		register: function(name, obj) {
			_ht[name] = obj;
		},
		unregister : function(name){
			_ht[name] = null;
		},
		get: function(name){
			return (name in _ht)?_ht[name]: null;
		},
		clear : function() {
			_ht = {};
		}
	};
};

var _IXArrayIndexOf =  IX.Array.indexOf;
IX.IList = function(){
	var _keyList = [];

	function indexOfFn(key) {
		return key ? _IXArrayIndexOf(_keyList, function(item) {
			return item == key;
		}) : -1;
	}
	function removeFn(idx) {
		if (idx >= 0 && idx<_keyList.length)
			_keyList = _keyList.slice(0, idx).concat(_keyList.slice(idx+1));
	}
	function appendFn(key){
		if (!_keyList || _keyList.length === 0)
			_keyList = [key];
		else {
			var idx = indexOfFn(key);
			removeFn(idx);
			_keyList.push(key);
		}
	}
	function insertBefore(key, dstKey) {
		// find the dstKey, if not exist, append current key to the end of list.
		var dstIdx = indexOfFn(dstKey);
		if (dstIdx == -1) {
			appendFn(key);
			return;
		}
		// find the key, if current key is before dstKey, do nothing.
		var idx = indexOfFn(key);
		if (idx != -1 && dstIdx - idx == 1)
			return;
		// else remove the existed record and insert it before dstKey.
		if (idx >= 0) {
			removeFn(idx);
			dstIdx = indexOfFn(dstKey);
		}
		_keyList = _keyList.slice(0, dstIdx).concat([key], _keyList.slice(idx));
	}
	return {
		isEmpty :function(){return _keyList.length===0;},
		isLast : function(k){return _keyList.length>0 && k==_keyList[_keyList.length-1];},
		getList : function(){return _keyList;},
		getSize: function(){return _keyList.length;},
		indexOf : indexOfFn,
		remove : removeFn,
		tryRemove : function(key){removeFn(indexOfFn(key));},
		append : appendFn,
		tryAdd :function(key){
			if (!_keyList || _keyList.length === 0)
				_keyList = [key];
			else if (indexOfFn(key) <0)
				_keyList.push(key);
		},
		insertBefore : insertBefore,
		clear : function(){
			_keyList = [];
		}
	};
};
IX.I1ToNManager = function(eqFn) {
	var _eqFn = IX.isFn(eqFn)?eqFn : function(item, value){return item==value;};
	var _mgr = new IX.IManager();
	var _list = [];

	var hasEntryFn = function(key) {
		var list = _mgr.get(key);
		return list && list.length>0;
	};
	var indexOfFn = function(arr, value) {
		return _IXArrayIndexOf(arr, function(item){return _eqFn(item, value);});
	};

	return IX.inherit(_mgr, {
		hasValue :hasEntryFn,
		put : function(k, v) {
			if (!hasEntryFn(k)) {
				_mgr.register(k, [v]);
				_list.push(k);
				return;
			}
			var list = _mgr.get(k);
			if (indexOfFn(list, v)==-1)
				_mgr.register(k, list.concat(v));
		},
		remove : function(k, v){
			var list = _mgr.get(k);
			var idx = indexOfFn(list, v);
			if (idx < 0)
				return;
			_mgr.register(k, IX.Array.splice(list, idx));
			if (list.length === 1)
				_list = IX.Array.remove(_list, k);
		},
		getKeys : function(){return _list;},
		clear : function(){
			_mgr.clear();
			_list = [];
		}
	});
};
IX.IListManager = function() {
	var _super = new IX.IManager();
	var _list = new IX.IList();

	var registerFn = function(key, obj) {
		_super.register(key, obj);
		var idx = _list.indexOf(key);
		if (obj) {
			if (idx == -1)
				_list.append(key);
		} else
			_list.remove(idx);
	};
	var listFn = function(keys) {
		return IX.map(keys, function(item) {return _super.get(item);});
	};
	return IX.inherit(_super, {
		// register should not change the sequence of key.
		register : registerFn,
		unregister : function(key){registerFn(key);},
		isEmpty :function(){return _list.isEmpty();},
		getSize : function(){return _list.getSize();},
		hasKey : _super.isRegistered,
		isLastKey : function(key){return _list.isLast(key);},
		getKeys : function() {return _list.getList();},
		getByKeys : function(keys){return listFn(keys);},
		getAll : function() {return listFn(_list.getList());},
		iterate: function(fn){IX.iterate(_list.getList(), function(item){fn(_super.get(item), item);}); },
		getFirst : function() {
			var arr = _list.getList();
			if (!arr || arr.length === 0)
				return null;
			var len = arr.length;
			for (var i = 0; i < len; i++) {
				var inst = _super.get(arr[i]);
				if (inst)
					return inst;
			}
			return null;
		},
		// only for key. append will remove existed record in keyList and append it to the end
		append : _list.append,
		insertBefore : _list.insertBefore,
		remove : function(key) {registerFn(key);},

		clear : function(){
			_super.clear();
			_list.clear();
		}
	});
};

IX.IPagedManager = function(newInstFn, instHT, dataCaller){
	var total = null;
	var ids = [];
	var ht = instHT ? instHT :(new IX.IListManager());

	function _add(pos, item){
		var model = newInstFn(item);
		var id = model.getId();
		ids[pos] = id;
		ht.register(id, model);
		return model;
	}
	function putData(data , startPos){
		if ("total" in data)
			 total = data.total;
		var pos = startPos || 0;
		return IX.map(data.items, function(item, idx){
			return _add(pos + idx, item);
		});
	}
	function load(pageNo, pageSize, cbFn, lazyLoad){
		var startPos = pageNo * pageSize;
		if (lazyLoad){
			var _ids = [];
			var _num = total === null? 0 : Math.min(pageSize, total - startPos);
			for(var i=0; i<_num; i++) {
				var id = ids[startPos + i];
				if (IX.isEmpty(id)) break;
				_ids.push(id);
			}
			if (_num > 0 && _ids.length == _num)
				return cbFn(ht.getByKeys(_ids));
		}
		dataCaller({
			pageNo : pageNo,
			pageSize : pageSize
		}, function(result) {
			cbFn(putData(result, startPos));
		});
	}
	function resetTotal(_total){
		total = _total;
		ids = [];
	}
	return {
		get : ht.get,
		getFirst : ht.getFirst,
		//getSize : ht.getSize,
		getTotal : function(){return total;},

		load : load,
		putData : putData,
		addItems : function(itemIds){
			resetTotal(total + itemIds.length);
		},
		removeItems : function(itemIds){
			IX.iterate(itemIds, function(itemId){
				ht.unregister(itemId);
			});
			resetTotal(total - itemIds.length);
		},
		//iterate : ht.iterate,

		clear : function(){ids = [];}
	};
};

IX.formatDataStore = function(data){
	var _items = $XP(data, "items", []);
	if (_items.length>0 && $XP(data, "type", "json")!="json"){
		var _fields = $XP(data, "fields", []);
		_items =  IX.map(_items, function(row){
			return IX.loop(_fields, {}, function(acc, col, idx){
				acc[col] = IX.isArray(row)?row[idx]:row[col];
				return acc;
			});
		});
	}

	return IX.map(_items, function(item){
		var id = $XP(item, "id");
		if (IX.isEmpty(id))
			item.id = IX.id();
		return item;
	});
};
})();
<commit_msg>extend IX.IListManager.iterate(fn)<commit_after>(function(){
/**
 * IX.State is simple state-machine utilities:{
	toggle(origStat, newStat) : if newStat give, return newStat, otherwise return !origStat
 * }
 *
 * IX.IManager is a Class to deal with key/value safely. It provide:
 * @Methods :{
	isRegistered(key) : check if key exist;
	register(key, value) : set the key mapped to value
	unregister(key) : clear the key's value
	get(key) : get the value mapped by key,
	clear() : clear all key/value;
 * }
 *
 * IX.IList is a Class to deal with Array easily. It provide:
 * @Methods : {
	isEmpty() : check if list is empty
	isLast(k) : check if k is last element in list
	getList() : return whole list
	getSize() : return the length of list
	indexOf(key) : return the index of key in list
	remove(idx) : remove the element in list idx position
	tryRemove(key): try remove key from list if existed
	append(key) : remove existed key and append key to last position in list
	tryAdd(key) : append key only if it is inexisted in list
	insertBefore(key, dstKey) : remove key if existed and insert it before dstkey, or append it if dstKey not existed
	clear() : clean all list
 * }
 *
 * IX.I1ToNManager is a Class to deal with special key/value which one key mapped to many values. It provide:
 * @Methods : {
  	@Methods(IX.IManager)

  	getKeys() : get all key in sequence in store
	hasValue(key) : check if any value is mapped by key
	put(k, v) : map k to v
	remove(k, v) : unmap v by k
	clear() : clear store
 * }
 *
 * IX.IListManager will manage key/value store with ordered key list. It provide:
 * @Methods : {
  	@Methods(IX.IManager)

  	register(key, value) : @Override append the key to the last of list
	unregister(key) :  @Override remove the entry for key from store
	isEmpty() : check if store is empty
	getSize() : get the size of store
	hasKey(key) : check if key is in store
	isLastKey(key) : check if key is the last in store
	getKeys() : get all key in sequence in store
	getByKeys(keys) :  get all values mapped by keys
	getAll() : get all values in store
	iterate(fn) :  for each value, iterate to execure fn(value, key, idx)
	getFirst() : get the first meaningful value

	append(key) :  only append key to store's key list, will not changed value
	insertBefore(key, dstKey) : only for key, same as IX.IList.insertBefore,
	remove(key) : same as unregister, remove entry and value by key.
	clear() : clear the store
 * }
 *
 * IX.IPagedManager will manage key/value store with ordered key list in paged info.
 * params :
	newInstFn : function(item){return itemModel;} // to create model for item
	instHT : null or instance of IX.IListManager  // if null, will create HT of IListManager
	dataCaller : function({pageNo, pageSize}, cbFn({total, items: [item]})) // dynamic load data for paged data
 * @Methods : {
	get : function(id){return itemModel;},
	getFirst : function(){return firstItemModel;},
	// getSize : function(){return sizeInHT;},
	getTotal : function(){return total;},

	load : load(pageNo, pageSize, cbFn([itemModel]), lazyLoad)
	putData : function({total, items}, startPos),
	addItems : function(itemIds){} // only change total and clear page info;
	removeItems : function(itemIds){}, // remove itemModels in HT, change total and clear page info;
	// iterate : function(fn), // iterate all itemModels in HT,
	clear : function(){ids = [];} // clear page info;
 * }
 *
 * IX.formatDataStore is an utilities handle with JSON data , for example
 * if convert JSON like :
 *  {
  		type : "array"/"json", [option; default :"json"]
 *		1: for array:
  		fields :["name1", "name2", ...],
  		items:[ [value1, value2, ...], ...]
 * 		2: for json:
  		items : [{name1: value1, name2: value2},...]
 *  } to Array like :
 *  [{name1: value1, name2: value2},...]
 *
 */
IX.State = {
	toggle :function(origStat, newStat){
		return (newStat===undefined)?!origStat : newStat;
	}
};

IX.IManager = function(){
	var _ht = {};
	return {
		isRegistered : function(name){
			return (name in _ht) && (_ht[name]);
		},
		register: function(name, obj) {
			_ht[name] = obj;
		},
		unregister : function(name){
			_ht[name] = null;
		},
		get: function(name){
			return (name in _ht)?_ht[name]: null;
		},
		clear : function() {
			_ht = {};
		}
	};
};

var _IXArrayIndexOf =  IX.Array.indexOf;
IX.IList = function(){
	var _keyList = [];

	function indexOfFn(key) {
		return key ? _IXArrayIndexOf(_keyList, function(item) {
			return item == key;
		}) : -1;
	}
	function removeFn(idx) {
		if (idx >= 0 && idx<_keyList.length)
			_keyList = _keyList.slice(0, idx).concat(_keyList.slice(idx+1));
	}
	function appendFn(key){
		if (!_keyList || _keyList.length === 0)
			_keyList = [key];
		else {
			var idx = indexOfFn(key);
			removeFn(idx);
			_keyList.push(key);
		}
	}
	function insertBefore(key, dstKey) {
		// find the dstKey, if not exist, append current key to the end of list.
		var dstIdx = indexOfFn(dstKey);
		if (dstIdx == -1) {
			appendFn(key);
			return;
		}
		// find the key, if current key is before dstKey, do nothing.
		var idx = indexOfFn(key);
		if (idx != -1 && dstIdx - idx == 1)
			return;
		// else remove the existed record and insert it before dstKey.
		if (idx >= 0) {
			removeFn(idx);
			dstIdx = indexOfFn(dstKey);
		}
		_keyList = _keyList.slice(0, dstIdx).concat([key], _keyList.slice(idx));
	}
	return {
		isEmpty :function(){return _keyList.length===0;},
		isLast : function(k){return _keyList.length>0 && k==_keyList[_keyList.length-1];},
		getList : function(){return _keyList;},
		getSize: function(){return _keyList.length;},
		indexOf : indexOfFn,
		remove : removeFn,
		tryRemove : function(key){removeFn(indexOfFn(key));},
		append : appendFn,
		tryAdd :function(key){
			if (!_keyList || _keyList.length === 0)
				_keyList = [key];
			else if (indexOfFn(key) <0)
				_keyList.push(key);
		},
		insertBefore : insertBefore,
		clear : function(){
			_keyList = [];
		}
	};
};
IX.I1ToNManager = function(eqFn) {
	var _eqFn = IX.isFn(eqFn)?eqFn : function(item, value){return item==value;};
	var _mgr = new IX.IManager();
	var _list = [];

	var hasEntryFn = function(key) {
		var list = _mgr.get(key);
		return list && list.length>0;
	};
	var indexOfFn = function(arr, value) {
		return _IXArrayIndexOf(arr, function(item){return _eqFn(item, value);});
	};

	return IX.inherit(_mgr, {
		hasValue :hasEntryFn,
		put : function(k, v) {
			if (!hasEntryFn(k)) {
				_mgr.register(k, [v]);
				_list.push(k);
				return;
			}
			var list = _mgr.get(k);
			if (indexOfFn(list, v)==-1)
				_mgr.register(k, list.concat(v));
		},
		remove : function(k, v){
			var list = _mgr.get(k);
			var idx = indexOfFn(list, v);
			if (idx < 0)
				return;
			_mgr.register(k, IX.Array.splice(list, idx));
			if (list.length === 1)
				_list = IX.Array.remove(_list, k);
		},
		getKeys : function(){return _list;},
		clear : function(){
			_mgr.clear();
			_list = [];
		}
	});
};
IX.IListManager = function() {
	var _super = new IX.IManager();
	var _list = new IX.IList();

	var registerFn = function(key, obj) {
		_super.register(key, obj);
		var idx = _list.indexOf(key);
		if (obj) {
			if (idx == -1)
				_list.append(key);
		} else
			_list.remove(idx);
	};
	var listFn = function(keys) {
		return IX.map(keys, function(item) {return _super.get(item);});
	};
	return IX.inherit(_super, {
		// register should not change the sequence of key.
		register : registerFn,
		unregister : function(key){registerFn(key);},
		isEmpty :function(){return _list.isEmpty();},
		getSize : function(){return _list.getSize();},
		hasKey : _super.isRegistered,
		isLastKey : function(key){return _list.isLast(key);},
		getKeys : function() {return _list.getList();},
		getByKeys : function(keys){return listFn(keys);},
		getAll : function() {return listFn(_list.getList());},
		iterate: function(fn){IX.iterate(_list.getList(), function(item, idx){fn(_super.get(item), item, idx);}); },
		getFirst : function() {
			var arr = _list.getList();
			if (!arr || arr.length === 0)
				return null;
			var len = arr.length;
			for (var i = 0; i < len; i++) {
				var inst = _super.get(arr[i]);
				if (inst)
					return inst;
			}
			return null;
		},
		// only for key. append will remove existed record in keyList and append it to the end
		append : _list.append,
		insertBefore : _list.insertBefore,
		remove : function(key) {registerFn(key);},

		clear : function(){
			_super.clear();
			_list.clear();
		}
	});
};

IX.IPagedManager = function(newInstFn, instHT, dataCaller){
	var total = null;
	var ids = [];
	var ht = instHT ? instHT :(new IX.IListManager());

	function _add(pos, item){
		var model = newInstFn(item);
		var id = model.getId();
		ids[pos] = id;
		ht.register(id, model);
		return model;
	}
	function putData(data , startPos){
		if ("total" in data)
			 total = data.total;
		var pos = startPos || 0;
		return IX.map(data.items, function(item, idx){
			return _add(pos + idx, item);
		});
	}
	function load(pageNo, pageSize, cbFn, lazyLoad){
		var startPos = pageNo * pageSize;
		if (lazyLoad){
			var _ids = [];
			var _num = total === null? 0 : Math.min(pageSize, total - startPos);
			for(var i=0; i<_num; i++) {
				var id = ids[startPos + i];
				if (IX.isEmpty(id)) break;
				_ids.push(id);
			}
			if (_num > 0 && _ids.length == _num)
				return cbFn(ht.getByKeys(_ids));
		}
		dataCaller({
			pageNo : pageNo,
			pageSize : pageSize
		}, function(result) {
			cbFn(putData(result, startPos));
		});
	}
	function resetTotal(_total){
		total = _total;
		ids = [];
	}
	return {
		get : ht.get,
		getFirst : ht.getFirst,
		//getSize : ht.getSize,
		getTotal : function(){return total;},

		load : load,
		putData : putData,
		addItems : function(itemIds){
			resetTotal(total + itemIds.length);
		},
		removeItems : function(itemIds){
			IX.iterate(itemIds, function(itemId){
				ht.unregister(itemId);
			});
			resetTotal(total - itemIds.length);
		},
		//iterate : ht.iterate,

		clear : function(){ids = [];}
	};
};

IX.formatDataStore = function(data){
	var _items = $XP(data, "items", []);
	if (_items.length>0 && $XP(data, "type", "json")!="json"){
		var _fields = $XP(data, "fields", []);
		_items =  IX.map(_items, function(row){
			return IX.loop(_fields, {}, function(acc, col, idx){
				acc[col] = IX.isArray(row)?row[idx]:row[col];
				return acc;
			});
		});
	}

	return IX.map(_items, function(item){
		var id = $XP(item, "id");
		if (IX.isEmpty(id))
			item.id = IX.id();
		return item;
	});
};
})();
<|endoftext|>


<commit_before>require('angular');
Howl = require('howler');    // for sounds (if you need them)
Nodule = require('nodule');  // for nodule helpers

var app = angular.module('asteroid-mining', []);

app.directive("asteroidMining", function() {
    return {
        restrict: 'E',
        templateUrl: "/ng-modules/asteroidMining/asteroidMining.html"
    };
});

app.controller("asteroidMiningController", ['data', '$scope', '$rootScope', function(data, $scope, $rootScope) {
    var vm = this;
    vm.nodule = new Nodule($rootScope, 'asteroid-mining', function(){
      vm.game = new Phaser.Game(800, 600, Phaser.CANVAS, 'asteroid-mining-content', {
        preload: vm.preload,
        create: vm.create,
        update: vm.update,
        render: vm.render
      });
    });

    vm.bulletTime = 0;

    vm.preload = function() {

      // vm.game.load.image('a1', '/assets/sprites/asteroids/0.png');
      // vm.game.load.image('a2', '/assets/sprites/asteroids/1.png');
      vm.game.load.image('a3', '/assets/sprites/asteroids/p0.png');
      vm.game.load.image('space', '/assets/backgrounds/milky_way_bg.png');
      vm.game.load.image('bullet', 'http://examples.phaser.io/assets/games/asteroids/bullets.png');
      vm.game.load.image('ship', '/assets/sprites/ship-nothrust.png');

    }

    vm.create = function() {
      var w=vm.game.width;
      var h=vm.game.height;
      var rnd=vm.game.rnd.integerInRange.bind(vm.game.rnd);

      //  This will run in Canvas mode, so let's gain a little speed and display
      vm.game.renderer.clearBeforeRender = false;
      vm.game.renderer.roundPixels = true;

      //  We need arcade physics
      vm.game.physics.startSystem(Phaser.Physics.ARCADE);

      //  A spacey background
      vm.game.add.tileSprite(0, 0, vm.game.width, vm.game.height, 'space');

      //  Our ships bullets
      vm.bullets = vm.game.add.group();
      vm.bullets.enableBody = true;
      vm.bullets.physicsBodyType = Phaser.Physics.ARCADE;

      //  All 40 of them
      vm.bullets.createMultiple(40, 'bullet');
      vm.bullets.setAll('anchor.x', 0.5);
      vm.bullets.setAll('anchor.y', 0.5);

      //  Our player ship
      vm.sprite = vm.game.add.sprite(
        rnd(w/10.0, w/3.0),
        rnd(h/10.0, h*9/10.0),
        'ship');
      vm.sprite.anchor.set(3.0/5.0, 0.5);
      vm.sprite.scale.set(0.25, 0.25);
      vm.game.physics.enable(vm.sprite, Phaser.Physics.ARCADE);
      vm.sprite.body.maxVelocity.set(200);
      vm.sprite.rotation = vm.game.physics.arcade.moveToXY(vm.sprite, w,
        rnd(h/10.0, h*9/10.00),
        rnd(w/60.0, w/90.0));

      // the asteroid
      vm.asteroid = vm.game.add.sprite(
        rnd(w*2/3.0, w*9/10.0),
        rnd(h/10.0, h*9/10.0),
        'a3');
      vm.asteroid.anchor.set(0.5, 0.5);
      vm.asteroid.scale.set(0.5, 0.5);
      vm.asteroid.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
      vm.game.physics.enable(vm.asteroid, Phaser.Physics.ARCADE);
      vm.game.physics.arcade.moveToXY(vm.asteroid, 0,
        rnd(h/10.0, h*9/10.00),
        rnd(w/60.0, w/90.0));

      // asteroids
      vm.asteroids = vm.game.add.group();
      // vm.asteroids.enableBody = true;
      // vm.asteroids.physicsBodyType = Phaser.Physics.ARCADE;
      // vm.createAsteroids();

      //  Game input
      vm.cursors = vm.game.input.keyboard.createCursorKeys();
      vm.game.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR ]);
    }

    vm.update = function() {
      if (vm.cursors.up.isDown) {
          vm.game.physics.arcade.accelerationFromRotation(vm.sprite.rotation, 200, vm.sprite.body.acceleration);
      } else {
          vm.sprite.body.acceleration.set(0);
      }

      if (vm.cursors.left.isDown) {
          vm.sprite.body.angularVelocity = -100;
      } else if (vm.cursors.right.isDown) {
          vm.sprite.body.angularVelocity = 100;
      } else {
          vm.sprite.body.angularVelocity = 0;
      }

      if (vm.game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {
          vm.fireBullet();
      }

      vm.screenWrap(vm.sprite);

      // vm.bullets.forEachExists(vm.screenWrap, this);

      (function (item) {
          item.angle += item.rotateAngle;
          vm.screenWrap(item);
      })(vm.asteroid);

      vm.game.physics.arcade.overlap(vm.bullets, vm.asteroids, null, function(bullet, asteroid){
          if (!bullet.alive || !asteroid.alive) return;
          bullet.kill();
          asteroid.kill();
      });
    }

    vm.createAsteroids = function() {
        for (var enemyIndex = 0; enemyIndex < 5; enemyIndex++) {
            var indexEntry = vm.game.rnd.integerInRange(0, 3),
                x, y;
            switch (indexEntry) {
                case 0:
                {
                    x = vm.game.world.randomX;
                    y = 0;
                }
                    break;
                case 1:
                {
                    x = vm.game.width;
                    y = vm.game.world.randomY;
                }
                    break;
                case 2:
                {
                    x = vm.game.world.randomX;
                    y = vm.game.height;
                }
                    break;
                case 3:
                {
                    x = 0;
                    y = vm.game.world.randomY;
                }
                    break;
            }

            var enemy = vm.asteroids.create(x, y, "a3");
            enemy.scale = { x: 0.5, y: 0.5 };
            enemy.moveX = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.moveX == 0) {
                enemy.moveX = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.moveY = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.moveY == 0) {
                enemy.moveY = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.rotateAngle == 0) {
                enemy.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.asteroidSize = 2;

            vm.asteroids.add(enemy);
            vm.game.physics.enable(enemy, Phaser.Physics.ARCADE);
        }

        vm.asteroids.setAll("anchor.x", 0.5);
        vm.asteroids.setAll("anchor.y", 0.5);
    }

    vm.fireBullet = function() {

        if (vm.game.time.now > vm.bulletTime)
        {
            var bullet = vm.bullets.getFirstExists(false);

            if (bullet)
            {
                var pos = vm.sprite.toGlobal(vm.sprite.anchor);
                bullet.reset(pos.x, pos.y);
                bullet.lifespan = 2000;
                bullet.rotation = vm.sprite.rotation;
                vm.game.physics.arcade.velocityFromRotation(vm.sprite.rotation, 400, bullet.body.velocity);
                vm.bulletTime = vm.game.time.now + 250;
            }
        }
    }

    vm.screenWrap = function(sprite) {

        if (sprite.x < 0)
        {
            sprite.x = vm.game.width;
        }
        else if (sprite.x > vm.game.width)
        {
            sprite.x = 0;
        }

        if (sprite.y < 0)
        {
            sprite.y = vm.game.height;
        }
        else if (sprite.y > vm.game.height)
        {
            sprite.y = 0;
        }

    }

    vm.render = function() {

    }
}]);

module.exports = angular.module('asteroid-mining').name;
<commit_msg>bullets produce asteroid fragments which are caught by the ship<commit_after>require('angular');
Howl = require('howler');    // for sounds (if you need them)
Nodule = require('nodule');  // for nodule helpers

var app = angular.module('asteroid-mining', []);

app.directive("asteroidMining", function() {
    return {
        restrict: 'E',
        templateUrl: "/ng-modules/asteroidMining/asteroidMining.html"
    };
});

app.controller("asteroidMiningController", ['data', '$scope', '$rootScope', function(data, $scope, $rootScope) {
    var vm = this;
    vm.nodule = new Nodule($rootScope, 'asteroid-mining', function(){
      vm.game = new Phaser.Game(800, 600, Phaser.CANVAS, 'asteroid-mining-content', {
        preload: vm.preload,
        create: vm.create,
        update: vm.update,
        render: vm.render
      });
    });

    vm.bulletTime = 0;

    vm.preload = function() {

      // vm.game.load.image('a1', '/assets/sprites/asteroids/0.png');
      // vm.game.load.image('a2', '/assets/sprites/asteroids/1.png');
      vm.game.load.image('a3', '/assets/sprites/asteroids/p0.png');
      vm.game.load.image('space', '/assets/backgrounds/milky_way_bg.png');
      vm.game.load.image('bullet', 'http://examples.phaser.io/assets/games/asteroids/bullets.png');
      vm.game.load.image('ship', '/assets/sprites/ship-nothrust.png');

    }

    vm.create = function() {
      var w=vm.game.width;
      var h=vm.game.height;
      var rnd=vm.game.rnd.integerInRange.bind(vm.game.rnd);

      //  This will run in Canvas mode, so let's gain a little speed and display
      vm.game.renderer.clearBeforeRender = false;
      vm.game.renderer.roundPixels = true;

      //  We need arcade physics
      vm.game.physics.startSystem(Phaser.Physics.ARCADE);

      //  A spacey background
      vm.game.add.tileSprite(0, 0, vm.game.width, vm.game.height, 'space');

      //  Our ships bullets
      vm.bullets = vm.game.add.group();
      vm.bullets.enableBody = true;
      vm.bullets.physicsBodyType = Phaser.Physics.ARCADE;
      vm.bullets.createMultiple(40, 'bullet');
      vm.bullets.setAll('anchor.x', 0.5);
      vm.bullets.setAll('anchor.y', 0.5);

      // our asteroid particles
      vm.parts = vm.game.add.group();
      vm.parts.enableBody = true;
      vm.parts.physicsBodyType = Phaser.Physics.ARCADE;
      vm.parts.createMultiple(60, 'a3');
      vm.parts.setAll('anchor.x', 0.5);
      vm.parts.setAll('anchor.y', 0.5);
      vm.parts.setAll('scale.x', 0.05);
      vm.parts.setAll('scale.y', 0.05);

      //  Our player ship
      vm.sprite = vm.game.add.sprite(
        rnd(w/10.0, w/3.0),
        rnd(h/10.0, h*9/10.0),
        'ship');
      vm.sprite.anchor.set(3.0/5.0, 0.5);
      vm.sprite.scale.set(0.25, 0.25);
      vm.game.physics.enable(vm.sprite, Phaser.Physics.ARCADE);
      vm.sprite.body.maxVelocity.set(200);
      vm.sprite.rotation = vm.game.physics.arcade.moveToXY(vm.sprite, w,
        rnd(h/10.0, h*9/10.00),
        rnd(w/60.0, w/90.0));

      // the asteroid
      vm.asteroid = vm.game.add.sprite(
        rnd(w*2/3.0, w*9/10.0),
        rnd(h/10.0, h*9/10.0),
        'a3');
      vm.asteroid.anchor.set(0.5, 0.5);
      vm.asteroid.scale.set(0.5, 0.5);
      vm.asteroid.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
      vm.game.physics.enable(vm.asteroid, Phaser.Physics.ARCADE);
      vm.game.physics.arcade.moveToXY(vm.asteroid, 0,
        rnd(h/10.0, h*9/10.00),
        rnd(w/60.0, w/90.0));

      // asteroids
      vm.asteroids = vm.game.add.group();
      // vm.asteroids.enableBody = true;
      // vm.asteroids.physicsBodyType = Phaser.Physics.ARCADE;
      // vm.createAsteroids();

      //  Game input
      vm.cursors = vm.game.input.keyboard.createCursorKeys();
      vm.game.input.keyboard.addKeyCapture([ Phaser.Keyboard.SPACEBAR ]);
    }

    vm.update = function() {
      if (vm.cursors.up.isDown) {
          vm.game.physics.arcade.accelerationFromRotation(vm.sprite.rotation, 200, vm.sprite.body.acceleration);
      } else {
          vm.sprite.body.acceleration.set(0);
      }

      if (vm.cursors.left.isDown) {
          vm.sprite.body.angularVelocity = -100;
      } else if (vm.cursors.right.isDown) {
          vm.sprite.body.angularVelocity = 100;
      } else {
          vm.sprite.body.angularVelocity = 0;
      }

      if (vm.game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {
          vm.fireBullet();
      }

      // TODO check for out of screen
      if (vm.screenKill(vm.sprite)) {
          alert('You broke out of orbit!');
      }

      // vm.bullets.forEachExists(vm.screenKill, this);

      vm.parts.forEachExists(vm.screenKill, this);

      (function (item) {
          item.angle += item.rotateAngle;
          // TODO: check for out of screen
          if (vm.screenKill(item)) {
            alert('The asteroid excaped!');
          };
      })(vm.asteroid);

      vm.game.physics.arcade.overlap(vm.bullets, vm.asteroids, null, function(bullet, asteroid){
          if (!bullet.alive || !asteroid.alive) return;
          bullet.kill();
          asteroid.kill();
      });

      vm.game.physics.arcade.overlap(vm.bullets, vm.asteroid, null, function(asteroid, bullet) {
          if (!bullet.alive) return;

          var projectile = vm.parts.getFirstExists(false);
          if (projectile) {
              projectile.reset(bullet.x, bullet.y);
              projectile.rotation = Phaser.Math.reverseAngle(bullet.rotation);
              vm.game.physics.arcade.velocityFromRotation(projectile.rotation, 200, projectile.body.velocity);
          }

          bullet.kill();
      });

      vm.game.physics.arcade.overlap(vm.parts, vm.sprite, null, function(sprite, projectile) {
          if (!projectile.alive) return;

          alert('you cought a part of the asteroid!');

          projectile.kill();
      });
    }

    vm.createAsteroids = function() {
        for (var enemyIndex = 0; enemyIndex < 5; enemyIndex++) {
            var indexEntry = vm.game.rnd.integerInRange(0, 3),
                x, y;
            switch (indexEntry) {
                case 0:
                {
                    x = vm.game.world.randomX;
                    y = 0;
                }
                    break;
                case 1:
                {
                    x = vm.game.width;
                    y = vm.game.world.randomY;
                }
                    break;
                case 2:
                {
                    x = vm.game.world.randomX;
                    y = vm.game.height;
                }
                    break;
                case 3:
                {
                    x = 0;
                    y = vm.game.world.randomY;
                }
                    break;
            }

            var enemy = vm.asteroids.create(x, y, "a3");
            enemy.scale = { x: 0.5, y: 0.5 };
            enemy.moveX = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.moveX == 0) {
                enemy.moveX = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.moveY = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.moveY == 0) {
                enemy.moveY = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
            while (enemy.rotateAngle == 0) {
                enemy.rotateAngle = vm.game.rnd.integerInRange(-2, 2);
            }
            enemy.asteroidSize = 2;

            vm.asteroids.add(enemy);
            vm.game.physics.enable(enemy, Phaser.Physics.ARCADE);
        }

        vm.asteroids.setAll("anchor.x", 0.5);
        vm.asteroids.setAll("anchor.y", 0.5);
    }

    vm.fireBullet = function() {

        if (vm.game.time.now > vm.bulletTime)
        {
            var bullet = vm.bullets.getFirstExists(false);

            if (bullet)
            {
                var pos = vm.sprite.toGlobal(vm.sprite.anchor);
                bullet.reset(pos.x, pos.y);
                bullet.lifespan = 2000;
                bullet.rotation = vm.sprite.rotation;
                vm.game.physics.arcade.velocityFromRotation(vm.sprite.rotation, 400, bullet.body.velocity);
                vm.bulletTime = vm.game.time.now + 250;
            }
        }
    }

    vm.screenKill = function(sprite) {
        var wrap = false;

        if (sprite.x < 0) {
            sprite.x = vm.game.width;
            wrap = true;
        } else if (sprite.x > vm.game.width) {
            sprite.x = 0;
            wrap = true;
        }

        if (sprite.y < 0) {
            sprite.y = vm.game.height;
            wrap = true;
        } else if (sprite.y > vm.game.height) {
            sprite.y = 0;
            wrap = true;
        }
        if (wrap) sprite.kill();
        return wrap;
    }

    vm.render = function() {
      // vm.game.debug.spriteInfo(vm.sprite, 32, 32);
      // vm.game.debug.spriteInfo(vm.asteroid, 32, 132);
      // vm.game.debug.text('ship.velocity: ' + vm.sprite.body.velocity, 32, 250);
      // vm.game.debug.text('aster.velocity: ' + vm.asteroid.body.velocity, 32, 300);
    }
}]);

module.exports = angular.module('asteroid-mining').name;
<|endoftext|>


<commit_before>"use strict";

const u = require("./UtilFunctions.js"),
	ID = require("./ID.js"),
	Finger = require("./Finger.js");

class Node{
	constructor(chord){
		this.id = chord.id;
		this.chord = chord;
		this.finger = [];
		this.predecessor = this;

		//Create Finger Table
		for(var i=0; i<chord.config.idWidth; i++)
			this.finger[i] = new Finger(this, i);
	}

	clean () {
		this.predecessor = this;

		//Wipe the finger table
		for(var i=0; i<this.finger.length; i++)
			this.finger[i].node = this;
	}

	setFinger(index, node){
		//Set the node, and then check further indices to see if this node is a better fit.
		//Improvement over std chord.
		do {
			this.finger[index++].node = node;
		} while(index<this.finger.length
			&& ID.inRightOpenBound(node.id, this.finger[index].start, this.finger[index].node.id));
	}

	removeFinger(id){
		//Scan right to left for a block of fingers represented by this id.
		//Replace them all with the node found immediately to the right of the block.
		//If last element was removed, replace with self.
		//Improvement over std chord.

		let index = this.finger.length - 1,
			replace,
			last = index;

		while(index >=0){
			replace = (index === this.finger.length-1) ? this : this.finger[index+1].node;

			while(index >=0 && ID.compare(id, this.finger[index].node.id) === 0){
				last = index;
				this.finger[index].node = replace;

				index--;
			}

			index--;
		}

		return last;
	}

	preserveFingerInvariant(){
		//We can observe that the largest value for any node in the finger table is our predecessor.
		//This property is required for correctness of the system to hold.

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

			if(this.predecessor && ID.inLeftOpenBound(finger.node.id, this.id, this.predecessor.id))
				finger.node = this.predecessor;

		};
	}

	getSuccessor(){
		return new Promise((resolve, reject) => {
			resolve(this.finger[0].node)
		});
	}

	setSuccessor(val){
		return new Promise((resolve, reject) => {
			let end = () => {
				this.setFinger(0, val);
				this.chord.statemachine.set_successor(val);
				resolve(val);
			}

			if(!val.isConnected || val.isConnected())
				end();
			else {
				this.chord.nodeOverRing(ID.coerceString(val.id), val)
					.then(
						() => end()
					)
			}

		});
	}

	getPredecessor(){
		return new Promise((resolve, reject) => {
			resolve(this.predecessor)
		});
	}

	setPredecessor(val){
		return new Promise((resolve, reject) => {
			this.predecessor = val;

			this.preserveFingerInvariant();

			this.chord.statemachine.set_predecessor(val);

			resolve(val);
		});
	}

	closestPrecedingFinger(id){
		return new Promise( resolve => {
			for (var i = this.finger.length - 1; i >= 0; i--) {
				if(ID.inOpenBound(this.finger[i].node.id, this.id, id)){
					resolve(this.finger[i].node);
					break;
				}
			}
			resolve(this);
		} );
	}

	findSuccessor(id){
		return this.findPredecessor(id)
			.then( nPrime => { return nPrime.getSuccessor() } )
	}

	findPredecessor(id){
		return new Promise( (resolve, reject) => {
			let nPrime = this;

			let condUpd = () => {
				nPrime.getSuccessor()
					.then(
						succ => {
							if (!ID.inLeftOpenBound(id, nPrime.id, succ.id)) {
								nPrime.closestPrecedingFinger(id)
									.then(
										newPrime => {
											nPrime = newPrime;
											condUpd();
										},
										rea => reject(rea)
									)
							} else {
								resolve(nPrime);
							}
						},
						rea => reject(rea)
					)
				};

			condUpd();
		} )
	}

	//Stabilization methods
	stableJoin(knownNode){
		let succ;

		return this.setPredecessor(null)
			.then(
				() => {
					this.chord.server.connect = true;
					return knownNode.findSuccessor(this.id);
				}
			)
			.then(
				foundSucc => {
					succ = foundSucc;
					return this.chord.nodeOverRing(ID.coerceString(succ.id), succ);
				}
			)
			.then(
				conn => {
					return this.setSuccessor(succ);
				}
			);
	}

	//periodically verify n's immediate successor
	//and tell the successor about n.
	stabilize(){
		let oSucc;

		// if(this.chord.state === "disconnected" || this.chord.state === "external")
		// 	return;

		u.log(this.chord, `ME:`);
		u.log(this.chord, this.id.idString);

		return this.getSuccessor()
			.then(succ => {
				oSucc = succ;
				u.log(this.chord, `MY SUCCESSOR:`);
				u.log(this.chord, succ.id.idString);
				return succ.getPredecessor();
			})
			.then(pred => {
				u.log(this.chord, `MY SUCCESSOR'S PREDECESSOR:`);
				u.log(this.chord, (pred) ? pred.id.idString : pred);

				if(pred){
					u.log(this.chord, `x: ${ID.coerceString(pred.id)}`);
					u.log(this.chord, `LB: ${ID.coerceString(this.id)}`);
					u.log(this.chord, `UB: ${ID.coerceString(oSucc.id)}`);
					u.log(this.chord, `x in (UB, LB): ${ID.inOpenBound(pred.id, this.id, oSucc.id)}`);
				}

				if(pred && ID.inOpenBound(pred.id, this.id, oSucc.id)) {
					u.log(this.chord, `NEW SUCCESSOR FOUND`);
					oSucc = pred;
					return this.setSuccessor(pred);
				} else {
					return Promise.resolve();
				}
			})
			.then(
				res => {
					u.log(this.chord, `NOTIFYING SUCCESSOR ABOUT:`);
					u.log(this.chord, this.id.idString);

					return oSucc.notify(this);
				}
			)

	}

	notify(nPrime){
		u.log(this.chord, `NOTIFIED BY:`);
		u.log(this.chord, ID.coerceString(nPrime.id));

		if(this.predecessor === null || ID.inOpenBound(nPrime.id, this.predecessor.id, this.id))
			return this.setPredecessor(nPrime);

		return Promise.resolve();
	}

	fixFingers(){
		let i = Math.floor(Math.random() * (this.finger.length-1) + 1);
		//this.finger[i].node = this.findSuccessor(this.finger[i].start);

		if(this.chord.state === "disconnected" || this.chord.state === "external")
			return;

		return this.findSuccessor(this.finger[i].start)
			.then(
				succ => this.setFinger(i, succ)//this.finger[i].node = succ
			)
	}

	//Custom

	message(msg){
		u.log(this.chord, `Received message at the local node for ${msg.dest}: ${msg.data}
			I am ${this.id.idString}`);

		u.log(this.chord, `!!! STATE: ${this.chord.state} !!!`)

		if(this.chord.state === "external" && ID.compare(msg.dest, this.id)!== 0) {
			let nodeIdList = Object.getOwnPropertyNames(this.chord.directNodes),
				chosen;

			if(nodeIdList.length === 0) {
				//Something went badly wrong, and the state machine got stuck.
				//Help it out a little?
				this.chord.statemachine.handle("disconnect_all");
			} else if(this.chord.server.node && this.chord.server.node.isConnected()){
				chosen = this.chord.server.node;
			} else {
				chosen = this.chord.directNodes[nodeIdList[0]];
			}

			if(chosen) {
				chosen.message(this.chord.messageCore.makeProxyMessage(msg, chosen.id))
			}

		} else if (this.chord.state === "partial" && ID.compare(msg.dest, this.id)!== 0 ) {
			this.getSuccessor()
				.then(
					successor => successor.message(this.chord.messageCore.makeProxyMessage(msg, successor.id))
				)
		} else if (!msg.bypass && (ID.compare(this.id, msg.dest)===0 || ID.inLeftOpenBound(msg.dest, this.predecessor.id, this.id))){
			//Pass to appropriate handler - this is our message.
			this.chord.messageCore.handleMessage(msg);
		} else {
			//Pass along the chain to a responsible node.
			this.closestPrecedingFinger(msg.dest)
			.then(
				dest => {
					if(dest===this){
						//Successor is likely inaccurate - the earlier checks determined that
						//the message was NOT for us.
						//Send to successor, it may know better.
						this.finger[0].node.message(msg);
					} else {
						dest.message(msg);
					}
				}
			)
		}
	}

	unlinkClient(idString){
		if(this.chord.config.isServer && this.chord.directNodes[idString]){
			// delete this.chord.directNodes[idString];
			return true;
		}

		return false;
	}
}

module.exports = Node;
<commit_msg>[Chord] Fix for msg routing - unaware of new state.<commit_after>"use strict";

const u = require("./UtilFunctions.js"),
	ID = require("./ID.js"),
	Finger = require("./Finger.js");

class Node{
	constructor(chord){
		this.id = chord.id;
		this.chord = chord;
		this.finger = [];
		this.predecessor = this;

		//Create Finger Table
		for(var i=0; i<chord.config.idWidth; i++)
			this.finger[i] = new Finger(this, i);
	}

	clean () {
		this.predecessor = this;

		//Wipe the finger table
		for(var i=0; i<this.finger.length; i++)
			this.finger[i].node = this;
	}

	setFinger(index, node){
		//Set the node, and then check further indices to see if this node is a better fit.
		//Improvement over std chord.
		do {
			this.finger[index++].node = node;
		} while(index<this.finger.length
			&& ID.inRightOpenBound(node.id, this.finger[index].start, this.finger[index].node.id));
	}

	removeFinger(id){
		//Scan right to left for a block of fingers represented by this id.
		//Replace them all with the node found immediately to the right of the block.
		//If last element was removed, replace with self.
		//Improvement over std chord.

		let index = this.finger.length - 1,
			replace,
			last = index;

		while(index >=0){
			replace = (index === this.finger.length-1) ? this : this.finger[index+1].node;

			while(index >=0 && ID.compare(id, this.finger[index].node.id) === 0){
				last = index;
				this.finger[index].node = replace;

				index--;
			}

			index--;
		}

		return last;
	}

	preserveFingerInvariant(){
		//We can observe that the largest value for any node in the finger table is our predecessor.
		//This property is required for correctness of the system to hold.

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

			if(this.predecessor && ID.inLeftOpenBound(finger.node.id, this.id, this.predecessor.id))
				finger.node = this.predecessor;

		};
	}

	getSuccessor(){
		return new Promise((resolve, reject) => {
			resolve(this.finger[0].node)
		});
	}

	setSuccessor(val){
		return new Promise((resolve, reject) => {
			let end = () => {
				this.setFinger(0, val);
				this.chord.statemachine.set_successor(val);
				resolve(val);
			}

			if(!val.isConnected || val.isConnected())
				end();
			else {
				this.chord.nodeOverRing(ID.coerceString(val.id), val)
					.then(
						() => end()
					)
			}

		});
	}

	getPredecessor(){
		return new Promise((resolve, reject) => {
			resolve(this.predecessor)
		});
	}

	setPredecessor(val){
		return new Promise((resolve, reject) => {
			this.predecessor = val;

			this.preserveFingerInvariant();

			this.chord.statemachine.set_predecessor(val);

			resolve(val);
		});
	}

	closestPrecedingFinger(id){
		return new Promise( resolve => {
			for (var i = this.finger.length - 1; i >= 0; i--) {
				if(ID.inOpenBound(this.finger[i].node.id, this.id, id)){
					resolve(this.finger[i].node);
					break;
				}
			}
			resolve(this);
		} );
	}

	findSuccessor(id){
		return this.findPredecessor(id)
			.then( nPrime => { return nPrime.getSuccessor() } )
	}

	findPredecessor(id){
		return new Promise( (resolve, reject) => {
			let nPrime = this;

			let condUpd = () => {
				nPrime.getSuccessor()
					.then(
						succ => {
							if (!ID.inLeftOpenBound(id, nPrime.id, succ.id)) {
								nPrime.closestPrecedingFinger(id)
									.then(
										newPrime => {
											nPrime = newPrime;
											condUpd();
										},
										rea => reject(rea)
									)
							} else {
								resolve(nPrime);
							}
						},
						rea => reject(rea)
					)
				};

			condUpd();
		} )
	}

	//Stabilization methods
	stableJoin(knownNode){
		let succ;

		return this.setPredecessor(null)
			.then(
				() => {
					this.chord.server.connect = true;
					return knownNode.findSuccessor(this.id);
				}
			)
			.then(
				foundSucc => {
					succ = foundSucc;
					return this.chord.nodeOverRing(ID.coerceString(succ.id), succ);
				}
			)
			.then(
				conn => {
					return this.setSuccessor(succ);
				}
			);
	}

	//periodically verify n's immediate successor
	//and tell the successor about n.
	stabilize(){
		let oSucc;

		// if(this.chord.state === "disconnected" || this.chord.state === "external")
		// 	return;

		u.log(this.chord, `ME:`);
		u.log(this.chord, this.id.idString);

		return this.getSuccessor()
			.then(succ => {
				oSucc = succ;
				u.log(this.chord, `MY SUCCESSOR:`);
				u.log(this.chord, succ.id.idString);
				return succ.getPredecessor();
			})
			.then(pred => {
				u.log(this.chord, `MY SUCCESSOR'S PREDECESSOR:`);
				u.log(this.chord, (pred) ? pred.id.idString : pred);

				if(pred){
					u.log(this.chord, `x: ${ID.coerceString(pred.id)}`);
					u.log(this.chord, `LB: ${ID.coerceString(this.id)}`);
					u.log(this.chord, `UB: ${ID.coerceString(oSucc.id)}`);
					u.log(this.chord, `x in (UB, LB): ${ID.inOpenBound(pred.id, this.id, oSucc.id)}`);
				}

				if(pred && ID.inOpenBound(pred.id, this.id, oSucc.id)) {
					u.log(this.chord, `NEW SUCCESSOR FOUND`);
					oSucc = pred;
					return this.setSuccessor(pred);
				} else {
					return Promise.resolve();
				}
			})
			.then(
				res => {
					u.log(this.chord, `NOTIFYING SUCCESSOR ABOUT:`);
					u.log(this.chord, this.id.idString);

					return oSucc.notify(this);
				}
			)

	}

	notify(nPrime){
		u.log(this.chord, `NOTIFIED BY:`);
		u.log(this.chord, ID.coerceString(nPrime.id));

		if(this.predecessor === null || ID.inOpenBound(nPrime.id, this.predecessor.id, this.id))
			return this.setPredecessor(nPrime);

		return Promise.resolve();
	}

	fixFingers(){
		let i = Math.floor(Math.random() * (this.finger.length-1) + 1);
		//this.finger[i].node = this.findSuccessor(this.finger[i].start);

		if(this.chord.state === "disconnected" || this.chord.state === "external")
			return;

		return this.findSuccessor(this.finger[i].start)
			.then(
				succ => this.setFinger(i, succ)//this.finger[i].node = succ
			)
	}

	//Custom

	message(msg){
		u.log(this.chord, `Received message at the local node for ${msg.dest}: ${msg.data}
			I am ${this.id.idString}`);

		u.log(this.chord, `!!! STATE: ${this.chord.state} !!!`)

		if(this.chord.state.substr(0,8) === "external" && ID.compare(msg.dest, this.id)!== 0) {
			let nodeIdList = Object.getOwnPropertyNames(this.chord.directNodes),
				chosen;

			if(nodeIdList.length === 0) {
				//Something went badly wrong, and the state machine got stuck.
				//Help it out a little?
				this.chord.statemachine.handle("disconnect_all");
			} else if(this.chord.server.node && this.chord.server.node.isConnected()){
				chosen = this.chord.server.node;
			} else {
				chosen = this.chord.directNodes[nodeIdList[0]];
			}

			if(chosen) {
				chosen.message(this.chord.messageCore.makeProxyMessage(msg, chosen.id))
			}

		} else if (this.chord.state === "partial" && ID.compare(msg.dest, this.id)!== 0 ) {
			this.getSuccessor()
				.then(
					successor => successor.message(this.chord.messageCore.makeProxyMessage(msg, successor.id))
				)
		} else if (!msg.bypass && (ID.compare(this.id, msg.dest)===0 || ID.inLeftOpenBound(msg.dest, this.predecessor.id, this.id))){
			//Pass to appropriate handler - this is our message.
			this.chord.messageCore.handleMessage(msg);
		} else {
			//Pass along the chain to a responsible node.
			this.closestPrecedingFinger(msg.dest)
			.then(
				dest => {
					if(dest===this){
						//Successor is likely inaccurate - the earlier checks determined that
						//the message was NOT for us.
						//Send to successor, it may know better.
						this.finger[0].node.message(msg);
					} else {
						dest.message(msg);
					}
				}
			)
		}
	}

	unlinkClient(idString){
		if(this.chord.config.isServer && this.chord.directNodes[idString]){
			// delete this.chord.directNodes[idString];
			return true;
		}

		return false;
	}
}

module.exports = Node;
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2016 Mailvelope GmbH
 * Licensed under the GNU Affero General Public License version 3
 */

import React from 'react';
import PropTypes from 'prop-types';
import * as l10n from '../../../lib/l10n';
import moment from 'moment';
import {KeyringOptions} from '../KeyringOptions';
import DatePicker from './DatePicker';

l10n.register([
  'keygrid_algorithm',
  'keygrid_default_label',
  'key_gen_key_size',
  'key_gen_experimental',
  'key_gen_expiration',
  'key_gen_future_default',
  'keygrid_key_not_expire'
]);

export default function AdvKeyGenOptions({value: {keyAlgo, keySize, keyExpirationTime}, onChange, disabled}) {
  const handleDateChange = moment => onChange({target: {id: 'keyExpirationTime', value: moment}});
  const keyAlgos = [
    <option value="rsa" key={0}>RSA</option>,
    <option value="ecc" key={1}>{`ECC - Curve25519 (${l10n.map.key_gen_experimental})`}</option>
  ];
  const gpgKeyAlgos = [
    <option value="default" key={0}>{l10n.map.keygrid_default_label}</option>,
    <option value="future-default" key={1}>{`${l10n.map.key_gen_future_default} (${l10n.map.key_gen_experimental})`}</option>
  ];
  return (

        {l10n.map.keygrid_algorithm}
        <select id="keyAlgo" value={keyAlgo} onChange={onChange} className="custom-select" disabled={disabled}>
          <KeyringOptions.Consumer>
            {options => options.gnupg ? gpgKeyAlgos : keyAlgos}
          </KeyringOptions.Consumer>
        </select>

      <div className={`form-group ${keyAlgo === 'rsa' ? '' : 'hide'}`}>
        {l10n.map.key_gen_key_size} (Bit)
        <select id="keySize" value={keySize} onChange={onChange} className="custom-select" disabled={disabled}>
          <option value="2048">2048 Bit</option>
          <option value="4096">4096 Bit</option>
        </select>

        {l10n.map.key_gen_expiration}
        <DatePicker id="keyExpirationTime" value={keyExpirationTime} onChange={handleDateChange} placeholder={l10n.map.keygrid_key_not_expire} minDate={moment().add({days: 1})} maxDate={moment('2080-12-31')} disabled={disabled} />

  );
}

AdvKeyGenOptions.propTypes = {
  value: PropTypes.object.isRequired,
  onChange: PropTypes.func.isRequired,
  disabled: PropTypes.bool
};
<commit_msg>Fix remove bit length select for ECC algo and GnuPG usage<commit_after>/**
 * Copyright (C) 2016 Mailvelope GmbH
 * Licensed under the GNU Affero General Public License version 3
 */

import React from 'react';
import PropTypes from 'prop-types';
import * as l10n from '../../../lib/l10n';
import moment from 'moment';
import {KeyringOptions} from '../KeyringOptions';
import DatePicker from './DatePicker';

l10n.register([
  'keygrid_algorithm',
  'keygrid_default_label',
  'key_gen_key_size',
  'key_gen_experimental',
  'key_gen_expiration',
  'key_gen_future_default',
  'keygrid_key_not_expire'
]);

export default function AdvKeyGenOptions({value: {keyAlgo, keySize, keyExpirationTime}, onChange, disabled}) {
  const context = React.useContext(KeyringOptions);
  const handleDateChange = moment => onChange({target: {id: 'keyExpirationTime', value: moment}});
  const keyAlgos = [
    <option value="rsa" key={0}>RSA</option>,
    <option value="ecc" key={1}>{`ECC - Curve25519 (${l10n.map.key_gen_experimental})`}</option>
  ];
  const gpgKeyAlgos = [
    <option value="default" key={0}>{l10n.map.keygrid_default_label}</option>,
    <option value="future-default" key={1}>{`${l10n.map.key_gen_future_default} (${l10n.map.key_gen_experimental})`}</option>
  ];
  return (

        {l10n.map.keygrid_algorithm}
        <select id="keyAlgo" value={keyAlgo} onChange={onChange} className="custom-select" disabled={disabled}>
          {context.gnupg ? gpgKeyAlgos : keyAlgos}
        </select>

      <div className={`form-group ${(keyAlgo === 'rsa' && !context.gnupg) ? '' : 'd-none'}`}>
        {l10n.map.key_gen_key_size} (Bit)
        <select id="keySize" value={keySize} onChange={onChange} className="custom-select" disabled={disabled}>
          <option value="2048">2048 Bit</option>
          <option value="4096">4096 Bit</option>
        </select>

        {l10n.map.key_gen_expiration}
        <DatePicker id="keyExpirationTime" value={keyExpirationTime} onChange={handleDateChange} placeholder={l10n.map.keygrid_key_not_expire} minDate={moment().add({days: 1})} maxDate={moment('2080-12-31')} disabled={disabled} />

  );
}

AdvKeyGenOptions.propTypes = {
  value: PropTypes.object.isRequired,
  onChange: PropTypes.func.isRequired,
  disabled: PropTypes.bool
};
<|endoftext|>


<commit_before>/*jslint white:true */
/*global chrome */

(function ( http ) {

    'use strict';

    var dnt_header = { name: 'DNT', value: '1' },
        filter = { urls: [ '<all_urls>' ] },
        info = [ 'requestHeaders', 'blocking' ];

    function doNotTrack( r ) {
        console.log( r );
        r.requestHeaders.push( dnt_header );
        return { requestHeaders: r.requestHeaders };
    }

    http.onBeforeSendHeaders.addListener( doNotTrack, filter, info );

}( chrome.webRequest ));
<commit_msg>drop debug statement<commit_after>//    ____    __  __  ______
//   /\  _`\ /\ \/\ \/\__  _\
//   \ \ \/\ \ \ `\\ \/_/\ \/
//    \ \ \ \ \ \ , ` \ \ \ \
//     \ \ \_\ \ \ \`\ \ \ \ \
//      \ \____/\ \_\ \_\ \ \_\
//       \/___/  \/_/\/_/  \/_/
//
// DNT :: Do Not Track Extension for Chrome
// Copyright (c) 2012 Ori Livneh. BSD License.

/*jslint white:true */
/*global chrome */

(function ( http ) {

    'use strict';

    var dnt_header = { name: 'DNT', value: '1' },
        filter = { urls: [ '<all_urls>' ] },
        info = [ 'requestHeaders', 'blocking' ];

    function doNotTrack( r ) {
        r.requestHeaders.push( dnt_header );
        return { requestHeaders: r.requestHeaders };
    }

    http.onBeforeSendHeaders.addListener( doNotTrack, filter, info );

}( chrome.webRequest ));
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var coffee = require('gulp-coffee');
var gutil = require('gulp-util');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var shell = require('gulp-shell');
var rename = require("gulp-rename");
var jsoncovToLcov = require('json2lcov');
var fs = require('fs');
var del = require('del');

gulp.task('watch', function() {
  gulp.start('sass')
  gulp.watch('./scss/**/*.scss', ['sass']);
  gulp.watch('./src/*.coffee', ['coffee']);
  gulp.watch('./test/src/*.coffee', ['test-coffee']);
});

gulp.task('default', function() {
  gulp.start('sass', 'coffee', 'test-coffee', 'compress', 'test', 'coverage', 'clean');
});

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('./css'));
});

gulp.task('concat', function() {
  return gulp.src(['./src/NovelManager.coffee','./src/InputManager.coffee','./src/Parser.coffee','./src/InventoryManager.coffee','./src/LanguageManager.coffee','./src/SceneManager.coffee','./src/SoundManager.coffee','./src/TextPrinter.coffee','./src/UI.coffee','./src/Util.coffee','./src/Init.coffee'])
    .pipe(concat('novel.coffee'))
    .pipe(gulp.dest('./'));
});

gulp.task('test-concat', function() {
  return gulp.src(['./test/src/Init.coffee','./test/src/Parser-test.coffee','./test/src/InventoryManager-test.coffee','./test/src/Util-test.coffee'])
    .pipe(concat('test.coffee'))
    .pipe(gulp.dest('./test'));
});

gulp.task('coffee', ['concat'], function() {
  return gulp.src('./novel.coffee')
    .pipe(coffee({bare: true}).on('error', gutil.log))
    .pipe(gulp.dest('./'));
});

gulp.task('test-coffee', ['test-concat'], function() {
  return gulp.src('./test/test.coffee')
    .pipe(coffee({bare: true}).on('error', gutil.log))
    .pipe(gulp.dest('./test'));
});

gulp.task('compress', ['coffee'], function() {
  return gulp.src('./novel.js')
    .pipe(uglify())
    .pipe(rename('novel.min.js'))
    .pipe(gulp.dest('./'));
});

gulp.task('test', ['coffee','test-coffee'], shell.task([
  'jscover ./ cov',
  'mocha-phantomjs cov/test/index.html -R json-cov > report.json',
]))

gulp.task('coverage', ['test'], function() {
  var json = JSON.parse(fs.readFileSync('report.json','utf8'));
  fs.writeFileSync('coverage.lcov',jsoncovToLcov(json))
});

gulp.task('clean', function() {
  return del([
    'report.json'
  ]);
});
<commit_msg>Fixed code coverage<commit_after>'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var coffee = require('gulp-coffee');
var gutil = require('gulp-util');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var shell = require('gulp-shell');
var rename = require("gulp-rename");
var jsoncovToLcov = require('json2lcov');
var fs = require('fs');
var del = require('del');

gulp.task('watch', function() {
  gulp.start('sass')
  gulp.watch('./scss/**/*.scss', ['sass']);
  gulp.watch('./src/*.coffee', ['coffee']);
  gulp.watch('./test/src/*.coffee', ['test-coffee']);
});

gulp.task('default', function() {
  gulp.start('sass', 'coffee', 'test-coffee', 'compress', 'test', 'coverage', 'clean');
});

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('./css'));
});

gulp.task('concat', function() {
  return gulp.src(['./src/NovelManager.coffee','./src/InputManager.coffee','./src/Parser.coffee','./src/InventoryManager.coffee','./src/LanguageManager.coffee','./src/SceneManager.coffee','./src/SoundManager.coffee','./src/TextPrinter.coffee','./src/UI.coffee','./src/Util.coffee','./src/Init.coffee'])
    .pipe(concat('novel.coffee'))
    .pipe(gulp.dest('./'));
});

gulp.task('test-concat', function() {
  return gulp.src(['./test/src/Init.coffee','./test/src/Parser-test.coffee','./test/src/InventoryManager-test.coffee','./test/src/Util-test.coffee'])
    .pipe(concat('test.coffee'))
    .pipe(gulp.dest('./test'));
});

gulp.task('coffee', ['concat'], function() {
  return gulp.src('./novel.coffee')
    .pipe(coffee({bare: true}).on('error', gutil.log))
    .pipe(gulp.dest('./'));
});

gulp.task('test-coffee', ['test-concat'], function() {
  return gulp.src('./test/test.coffee')
    .pipe(coffee({bare: true}).on('error', gutil.log))
    .pipe(gulp.dest('./test'));
});

gulp.task('compress', ['coffee'], function() {
  return gulp.src('./novel.js')
    .pipe(uglify())
    .pipe(rename('novel.min.js'))
    .pipe(gulp.dest('./'));
});

gulp.task('test', ['coffee','test-coffee'], shell.task([
  'jscover ./ cov',
  'mocha-phantomjs cov/test/index.html -R json-cov > report.json',
]));

gulp.task('coverage', ['test'], function() {
  var json = JSON.parse(fs.readFileSync('report.json','utf8'));
  delete json.files[1];
  fs.writeFileSync('coverage.lcov',jsoncovToLcov(json))
});

gulp.task('clean', function() {
  return del([
    'report.json'
  ]);
});
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { HSK1 } from '../../imports/api/hsk1.js';
import { getPaginationSize } from '../main.js';

import '../../imports/html5up-forty/elements.html';

function generateQuestion(caller,popselected,accordingToQuestion){
  return;
  var voc = caller.voc.get();
  var noOfWords = caller.noOfVoc.get();
  var level = Session.get('level');
  var page = Session.get('page');
  var pagination = Session.get('pagination');

  if(!page){
    page = 0;
  }
  if(noOfWords == 0
    || level != caller.level.get()
    || page != caller.page.get()
    || pagination != caller.pagination.get()
  ){
    if(level){

      var query = {};
      query["level"] = level;

      var options = {};
      options.sort = {};
      options.sort.pinyinlowercase = 1;
      options.limit = getPaginationSize();
      options.skip = getPaginationSize() * page;

      var temp = HSK1.find(query,options);
      voc = [];

      var knownWords = amplify.store()["hsklibrary"+level];
      if(!knownWords){knownWords={};}
      var counter = 0;
      temp.forEach(function(ele){
        counter += 1;
        var doaddtheword = false;
        //the particular word has never been quizzed, so quiz it
        var temp_cur = knownWords[ele.simp];
        if(!temp_cur){
          doaddtheword = true;
          ele.grade = initialLevelOfCorrectlyAnsweredVariable;
          ele.gradepinyin = initialLevelOfCorrectlyAnsweredVariable;
        }else{
          if(temp_cur.grade>0||temp_cur.gradepinyin>0){
            //the grade of the word is not 0, so quiz it.
            doaddtheword = true;
            ele.grade = temp_cur.grade;
            ele.gradepinyin = temp_cur.gradepinyin;
          }
        }

        if(doaddtheword){
          voc.push(ele);
        }

      });

      caller.noOfVoc.set(counter);

      //voc = temp.fetch();
      Session.set("currentVoc",undefined);
      caller.answers.set([]);
      caller.voc.set(voc);
      caller.level.set(level);
      caller.page.set(page);
      caller.pagination.set(pagination);

    }
  };

  var result = Session.get("currentVoc");
  if(voc&&voc.length>0){
    if(popselected&&result){
      //we already have a variable, no need to reset it
    }else{
        //first select a vocabel that is not in amplify but in voc
        //second from a list of vocabel with the highest level in pinyin or translation
        //go down level by level
        var setOfVocabulary = [];
        var currentStatusTemp = amplify.store()["hsklibrary"+level];
        if(!currentStatusTemp){
          currentStatusTemp={};
        }
        var currentStatus ={};
        var highestlevelPinyin = 0;
        var highestlevelTranslation = 0;
        if(!accordingToQuestion){
          for(var j=0;j<voc.length;j++){
            if(currentStatusTemp[voc[j].simp]){
              currentStatus[voc[j].simp] = currentStatusTemp[voc[j].simp];
            }else{
              setOfVocabulary.push(voc[j])
            }
          }
          if(setOfVocabulary.length>0){

          }else{

            for(var  element in currentStatus){
              highestlevelTranslation = Math.max(currentStatus[element].grade,highestlevelTranslation);
              highestlevelPinyin = Math.max(currentStatus[element].gradepinyin,highestlevelPinyin);
            }
            if(highestlevelTranslation>highestlevelPinyin){
              highestlevelPinyin = numberOfLevels+1;
            }else if(highestlevelTranslation<highestlevelPinyin){
              highestlevelTranslation = numberOfLevels+1;
            }

            for(var element in currentStatus){
              if(currentStatus[element].grade==highestlevelTranslation||
                currentStatus[element].gradepinyin==highestlevelPinyin
              ){
                for(var j=0;j<voc.length;j++){
                  if(currentStatus[element] && currentStatus[element].simp == voc[j].simp){
                      setOfVocabulary.push(voc[j]);
                  }
                }
              }
            }

          }
        }else{
          var query = {};
          query["level"] = level;

          var options = {};
          options.sort = {};
          options.sort.pinyinlowercase = 1;
          options.limit = getPaginationSize();
          options.skip = getPaginationSize() * page;

          var temp = HSK1.find(query,options);
          voc = temp.fetch();
          for(var i = 0;i<voc.length;i++){
            if(accordingToQuestion && accordingToQuestion.simp==voc[i].simp){

            }else{
                setOfVocabulary.push(voc[i]);
            }

          }
        }

        voc = setOfVocabulary;

        var selector = (Math.round((Math.random()*(voc.length-1))));
        result = voc[selector];
        if(!result){
          console.log("Error");
        }
        var temporary_result = undefined;
        if(result){
          temporary_result = currentStatus[result.simp];
          if(temporary_result){
            result = temporary_result;
          }
        }

        if(result){
          result.second = result.pinyin;
          result.first = result.simp;
          if(popselected){
            var temp = caller.voc.get();
            if(temp){
                //temp.splice(selector,1);
                caller.voc.set(temp);
                /*check if either pinyin or translation should be tested*/
                var what = undefined;
                what = pinyin_static;
                if(result.gradepinyin == 0){
                  what = translation_static;
                }else if(result.gradepinyin < result.grade){
                  what = translation_static;
                }else if(result.gradepinyin == result.grade){
                  var randomized = Math.round(Math.random());
                  if(randomized==1){
                    what = translation_static;
                  }
                }

                caller.pinyinOrTranslation.set(what);

                Session.set("currentVoc",result);
                caller.answers.set([]);
                generateAnswers(caller);
            }
          }
      }
    }

  }

  return result;
}

const numberOfPossibleAnswers = 4;
export const initialLevelOfCorrectlyAnsweredVariable = 4;
const numberOfLevels = 9;
const translation_static = "translation";
const pinyin_static = "pinyin";

function generateAnswers(caller,pinyinOrTranslation){
  var options = Math.min(numberOfPossibleAnswers,caller.voc.get().length+1);
  var result = caller.answers.get();
  if(result==undefined||result.length==0/*&&caller.voc.get().length>0*/){
    var correct = Session.get("currentVoc");

    if(correct){
      result = [];
      resultSimpArray = [];
      var correctposition = Math.round(Math.random()*(options-1));
      for(var i = 0;i<options;i++){
        if(i==correctposition){
          result[i] = correct;
          if(result[i]){
            result[i].correct = true;
          }

        }else{
          var counterForChange = 0;
          result[i] = generateQuestion(caller,false,correct);
          while(resultSimpArray.indexOf(result[i].simp)>-1&&counterForChange<5){
            result[i] = generateQuestion(caller,false,correct);
            counterForChange++;
          }
          if(result[i]){
              result[i].correct = false;
          }

        }
        if(result[i]==undefined){

        }else{
          resultSimpArray.push(result[i].simp);
          if(caller.pinyinOrTranslation.get()==translation_static){
              result[i].text = result[i].translation;
          }else{
            result[i].text = result[i].pinyin;
          }

        }

      }
    }else{

    }
    caller.answers.set(result);

  }
  return result;
}

Template.quiz.onCreated(function(){
  this.voc = new ReactiveVar([]);
  this.answers = new ReactiveVar([]);
  this.noOfVoc = new ReactiveVar(0);
  this.level = new ReactiveVar(null);
  this.lastanswer = new ReactiveVar(-1);
  this.pinyinOrTranslation = new ReactiveVar(undefined);
  this.page = new ReactiveVar(0);
  this.pagination = new ReactiveVar(0);
});

Template.quiz.onRendered(function(){
  var result = generateQuestion(Template.instance(),true);
  generateAnswers(Template.instance());
})

function answered(e,instance){
  //Save in amplify so the hanzi is not quizzed again
  var temp = amplify.store()["hsklibrary"+instance.level.get()];
  if(!temp){temp = {}};
  var temp_cur = temp[Session.get("currentVoc").simp];
  if(!temp_cur){
    temp_cur = Session.get("currentVoc");

  }
  if(temp_cur.grade == undefined){
    temp_cur.grade = initialLevelOfCorrectlyAnsweredVariable;
  }
  if(!temp_cur.gradepinyin == undefined){
    temp_cur.gradepinyin = initialLevelOfCorrectlyAnsweredVariable;
  }
  if(e.currentTarget.getAttribute("correct")){
    //Answer is correct!
    instance.lastanswer.set(1);
    //grade +1
    if(instance.pinyinOrTranslation.get()==translation_static){
        temp_cur.grade -= 1;
    }else{
        temp_cur.gradepinyin -= 1;
    }

  }else{
    //Answer is not correct
    instance.lastanswer.set(0)
    //wrong answer +1 grade;
    if(instance.pinyinOrTranslation.get()==translation_static){
      if(temp_cur.grade<numberOfLevels){
          temp_cur.grade += 1;
      }

    }else{
      if(temp_cur.gradepinyin<numberOfLevels){
          temp_cur.gradepinyin += 1;
      }

    }
  }

  if(temp_cur.grade==0&&temp_cur.gradepinyin==0){
    var temp_voc = instance.voc.get();
    var i = temp_voc.length - 1;
    while(i>= 0){
      if(temp_voc[i].simp==temp_cur.simp){
        temp_voc.splice(i,1);
      }
      i--;
    }

  }

  //restore status in amplify
  temp[temp_cur.simp]=temp_cur;
  amplify.store("hsklibrary"+instance.level.get(),temp);
  Session.set("currentVoc",undefined);
  instance.answers.set([]);
  result = generateQuestion(instance,true);
}

Template.quiz.events({
  'click ul li a.button.special.fit':function(e,a,b){
      var instance = Template.instance()
      setTimeout(function(){answered(e,instance)},200);
  }
});
Template.quiz.helpers({
  gradeofcurrentword(){
    var instance = Template.instance();
    var result = Session.get("currentVoc");
    if(result){
        if(instance.pinyinOrTranslation.get()==translation_static){
          return "Level of Word: "+result.grade+ " ("+translation_static+")";
        }else{
          return "Level of Word: "+result.gradepinyin+ " ("+pinyin_static+")";
        }

    }else{
      return "";
    }

  },
  lastanswer(){
    var instance = Template.instance();
    if(instance.lastanswer.get()==1){
        return "-- Correct";
    }else if(instance.lastanswer.get()==-1){
      return "";
    }
    return "-- Wrong";
  },
  leftover(){
    var instance = Template.instance();
    var result = Session.get("level");
    var level = Session.get("level");
    generateQuestion(instance,true);
    if(HSK1.find({"level":level}).count()>0&&instance.voc.get().length == 0){
      return "No Words left.";
    }
    return "Words left: " +instance.voc.get().length+",";
  },
  levelis(){
    var result = Template.instance().level.get();
    if(!Template.instance().level.get()||Template.instance().level.get()==null||Template.instance().level.get().length==0){
      return "Select a Category above";
    }
    return "Category is: "+Template.instance().level.get()+", ";
  },
  answers(){
    var result = Session.get("level");
    return Template.instance().answers.get();
  },
  first(){
    var instance = Template.instance();
    var level = Session.get("level");
    var result = Session.get("currentVoc");
    var page = Session.get("page");
    var pagination = Session.get("pagination");
    if(result){
        return result.first;
    }else{
      generateQuestion(instance,true);
    }
    return;
  },
  second(){

    var result = Session.get("currentVoc");
    if(result){
        return result.second;
    }
    return;
  },

});
<commit_msg>remove test<commit_after>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { HSK1 } from '../../imports/api/hsk1.js';
import { getPaginationSize } from '../main.js';

import '../../imports/html5up-forty/elements.html';

function generateQuestion(caller,popselected,accordingToQuestion){
  var voc = caller.voc.get();
  var noOfWords = caller.noOfVoc.get();
  var level = Session.get('level');
  var page = Session.get('page');
  var pagination = getPaginationSize();

  if(!level){
    return;
  }
  if(!page){
    page = 0;
  }
  if(!pagination){
    pagination = 10;
  }

  if(noOfWords == 0
    || level != caller.level.get()
    || page != caller.page.get()
    || pagination != caller.pagination.get()
  ){

    /* This retrieves the words from the database */
    var query = {};
    query["level"] = level;

    var options = {};
    options.sort = {};
    options.sort.pinyinlowercase = 1;
    options.limit = getPaginationSize();
    options.skip = getPaginationSize() * page;

    var temp = HSK1.find(query,options);
    voc = [];

    var knownWords = amplify.store()["hsklibrary"+level];
    if(!knownWords){knownWords={};}
    var counter = 0;
    temp.forEach(function(ele){
      counter += 1;
      var doaddtheword = false;
      //the particular word has never been quizzed, so quiz it
      var temp_cur = knownWords[ele.simp];
      if(!temp_cur){
        doaddtheword = true;
        ele.grade = initialLevelOfCorrectlyAnsweredVariable;
        ele.gradepinyin = initialLevelOfCorrectlyAnsweredVariable;
      }else{
        if(temp_cur.grade>0||temp_cur.gradepinyin>0){
          //the grade of the word is not 0, so quiz it.
          doaddtheword = true;
          ele.grade = temp_cur.grade;
          ele.gradepinyin = temp_cur.gradepinyin;
        }
      }

      if(doaddtheword){
        voc.push(ele);
      }

    });

    caller.noOfVoc.set(counter);

    Session.set("currentVoc",undefined);
    caller.answers.set([]);
    caller.voc.set(voc);
    caller.level.set(level);
    caller.page.set(page);
    caller.pagination.set(pagination);
    /*Now we have the words to deal with*/

  };

  var result = Session.get("currentVoc");
  if(voc&&voc.length>0){
    if(popselected&&result){
      //we already have a variable, no need to reset it
    }else{
      //take a possible question, from the not yet answered vocabulary.
      //first select a vocabel that is not in amplify but in voc
      //second from a list of vocabel with the highest level in pinyin or translation
      //go down level by level
      var setOfVocabulary = [];
      var currentStatusTemp = amplify.store()["hsklibrary"+level];
      if(!currentStatusTemp){
        currentStatusTemp={};
      }
      var currentStatus = {};
      var highestlevelPinyin = 0;
      var highestlevelTranslation = 0;
      if(!accordingToQuestion){
        for(var j=0;j<voc.length;j++){
          if(currentStatusTemp[voc[j].simp]){
            currentStatus[voc[j].simp] = currentStatusTemp[voc[j].simp];
          }else{
            setOfVocabulary.push(voc[j])
          }
        }
        if(setOfVocabulary.length>0){

        }else{
          for(var element in currentStatus){
            highestlevelTranslation = Math.max(currentStatus[element].grade,highestlevelTranslation);
            highestlevelPinyin = Math.max(currentStatus[element].gradepinyin,highestlevelPinyin);
          }

          if(highestlevelTranslation>highestlevelPinyin){
            highestlevelPinyin = numberOfLevels+1;
          }else if(highestlevelTranslation<highestlevelPinyin){
            highestlevelTranslation = numberOfLevels+1;
          }

          for(var element in currentStatus){
            if(currentStatus[element].grade==highestlevelTranslation||
              currentStatus[element].gradepinyin==highestlevelPinyin
            ){
              for(var j=0;j<voc.length;j++){
                if(currentStatus[element] && currentStatus[element].simp == voc[j].simp){
                  setOfVocabulary.push(voc[j]);
                }
              }
            }
          }
        }
      }else{
        //fetch an answer from the database;
        var query = {};
        query["level"] = level;
        query["simp"] = {$ne: accordingToQuestion.simp};
        var options = {};
        options.sort = {};
        options.sort.pinyinlowercase = 1;
        options.limit = pagination;
        options.skip = pagination * page;
        setOfVocabulary = HSK1.find(query,options).fetch();
      }

      voc = setOfVocabulary;

      var selector = (Math.round((Math.random()*(voc.length-1))));
      result = voc[selector];
      if(!result){
        console.log("Error");
      }
      var temporary_result = undefined;
      if(result){
        temporary_result = currentStatus[result.simp];
        if(temporary_result){
          result = temporary_result;
        }
      }

      if(result){
        result.second = result.pinyin;
        result.first = result.simp;
        if(popselected){
          var temp = caller.voc.get();
          if(temp){
            caller.voc.set(temp);
            /*check if either pinyin or translation should be tested*/
            var what = undefined;
            what = pinyin_static;
            if(result.gradepinyin == 0){
              what = translation_static;
            }else if(result.gradepinyin < result.grade){
              what = translation_static;
            }else if(result.gradepinyin == result.grade){
              var randomized = Math.round(Math.random());
              if(randomized==1){
                what = translation_static;
              }
            }
            caller.pinyinOrTranslation.set(what);
            Session.set("currentVoc",result);
            caller.answers.set([]);
            generateAnswers(caller);
          }
        }
      }
    }
  }

  return result;
}

const numberOfPossibleAnswers = 4;
export const initialLevelOfCorrectlyAnsweredVariable = 4;
const numberOfLevels = 9;
const translation_static = "translation";
const pinyin_static = "pinyin";

function generateAnswers(caller,pinyinOrTranslation){
  var options = Math.min(numberOfPossibleAnswers,caller.voc.get().length+1);
  var result = caller.answers.get();
  if(result==undefined||result.length==0/*&&caller.voc.get().length>0*/){
    var correct = Session.get("currentVoc");

    if(correct){
      result = [];
      resultSimpArray = [];
      var correctposition = Math.round(Math.random()*(options-1));
      for(var i = 0;i<options;i++){
        if(i==correctposition){
          result[i] = correct;
          if(result[i]){
            result[i].correct = true;
          }

        }else{
          var counterForChange = 0;
          result[i] = generateQuestion(caller,false,correct);
          while(resultSimpArray.indexOf(result[i].simp)>-1&&counterForChange<5){
            result[i] = generateQuestion(caller,false,correct);
            counterForChange++;
          }
          if(result[i]){
              result[i].correct = false;
          }

        }
        if(result[i]==undefined){

        }else{
          resultSimpArray.push(result[i].simp);
          if(caller.pinyinOrTranslation.get()==translation_static){
              result[i].text = result[i].translation;
          }else{
            result[i].text = result[i].pinyin;
          }

        }

      }
    }else{

    }
    caller.answers.set(result);

  }
  return result;
}

Template.quiz.onCreated(function(){
  this.voc = new ReactiveVar([]);
  this.answers = new ReactiveVar([]);
  this.noOfVoc = new ReactiveVar(0);
  this.level = new ReactiveVar(null);
  this.lastanswer = new ReactiveVar(-1);
  this.pinyinOrTranslation = new ReactiveVar(undefined);
  this.page = new ReactiveVar(0);
  this.pagination = new ReactiveVar(0);
});

Template.quiz.onRendered(function(){
  var result = generateQuestion(Template.instance(),true);
  generateAnswers(Template.instance());
})

function answered(e,instance){
  //Save in amplify so the hanzi is not quizzed again
  var temp = amplify.store()["hsklibrary"+instance.level.get()];
  if(!temp){temp = {}};
  var temp_cur = temp[Session.get("currentVoc").simp];
  if(!temp_cur){
    temp_cur = Session.get("currentVoc");

  }
  if(temp_cur.grade == undefined){
    temp_cur.grade = initialLevelOfCorrectlyAnsweredVariable;
  }
  if(!temp_cur.gradepinyin == undefined){
    temp_cur.gradepinyin = initialLevelOfCorrectlyAnsweredVariable;
  }
  if(e.currentTarget.getAttribute("correct")){
    //Answer is correct!
    instance.lastanswer.set(1);
    //grade +1
    if(instance.pinyinOrTranslation.get()==translation_static){
        temp_cur.grade -= 1;
    }else{
        temp_cur.gradepinyin -= 1;
    }

  }else{
    //Answer is not correct
    instance.lastanswer.set(0)
    //wrong answer +1 grade;
    if(instance.pinyinOrTranslation.get()==translation_static){
      if(temp_cur.grade<numberOfLevels){
          temp_cur.grade += 1;
      }

    }else{
      if(temp_cur.gradepinyin<numberOfLevels){
          temp_cur.gradepinyin += 1;
      }

    }
  }

  if(temp_cur.grade==0&&temp_cur.gradepinyin==0){
    var temp_voc = instance.voc.get();
    var i = temp_voc.length - 1;
    while(i>= 0){
      if(temp_voc[i].simp==temp_cur.simp){
        temp_voc.splice(i,1);
      }
      i--;
    }

  }

  //restore status in amplify
  temp[temp_cur.simp]=temp_cur;
  amplify.store("hsklibrary"+instance.level.get(),temp);
  Session.set("currentVoc",undefined);
  instance.answers.set([]);
  result = generateQuestion(instance,true);
}

Template.quiz.events({
  'click ul li a.button.special.fit':function(e,a,b){
      var instance = Template.instance()
      setTimeout(function(){answered(e,instance)},200);
  }
});
Template.quiz.helpers({
  gradeofcurrentword(){
    var instance = Template.instance();
    var result = Session.get("currentVoc");
    if(result){
        if(instance.pinyinOrTranslation.get()==translation_static){
          return "Level of Word: "+result.grade+ " ("+translation_static+")";
        }else{
          return "Level of Word: "+result.gradepinyin+ " ("+pinyin_static+")";
        }

    }else{
      return "";
    }

  },
  lastanswer(){
    var instance = Template.instance();
    if(instance.lastanswer.get()==1){
        return "-- Correct";
    }else if(instance.lastanswer.get()==-1){
      return "";
    }
    return "-- Wrong";
  },
  leftover(){
    var instance = Template.instance();
    var result = Session.get("level");
    var level = Session.get("level");
    generateQuestion(instance,true);
    if(HSK1.find({"level":level}).count()>0&&instance.voc.get().length == 0){
      return "No Words left.";
    }
    return "Words left: " +instance.voc.get().length+",";
  },
  levelis(){
    var result = Template.instance().level.get();
    if(!Template.instance().level.get()||Template.instance().level.get()==null||Template.instance().level.get().length==0){
      return "Select a Category above";
    }
    return "Category is: "+Template.instance().level.get()+", ";
  },
  answers(){
    var result = Session.get("level");
    return Template.instance().answers.get();
  },
  first(){
    var instance = Template.instance();
    var level = Session.get("level");
    var result = Session.get("currentVoc");
    var page = Session.get("page");
    var pagination = Session.get("pagination");
    if(result){
        return result.first;
    }else{
      generateQuestion(instance,true);
    }
    return;
  },
  second(){

    var result = Session.get("currentVoc");
    if(result){
        return result.second;
    }
    return;
  },

});
<|endoftext|>