0) {
- UI.showUpdateValue("#update-data", -cost);
- UI.showUpdateValue("#update-reputation", item.state.reputation);
- }
- };
- vs.showInfo = function (r) {
- UI.showModal(r.name, r.getInfo());
- UI.showLevels(r.state.level);
- };
- }]);
+ };
- app.controller('DetectorController', ['$scope', 'game', 'detector', function ($scope, game, detector) {
+
+ function DetectorController($scope, game, detector, lab) {
var vm = this;
vm.elements = detector.elements;
vm.dropOptions = {
@@ -137,12 +140,12 @@ var app = (function () {
vm.onDrop = function (event, ui) {
var result = detector.onDrop(event, ui, game);
if (result)
- game.lab.observe(result);
+ lab.observe(result);
};
vm.click = function () {
- game.lab.clickDetector();
+ lab.clickDetector();
detector.addEvent();
- UI.showUpdateValue("#update-data", game.lab.state.detector);
+ UI.showUpdateValue("#update-data", lab.state.detector);
game.elements.addKnownToStore();
return false;
};
@@ -152,100 +155,135 @@ var app = (function () {
};
vm.clearAll = function () {
detector.clearAll(game);
- }
- }]);
+ };
+ };
+ DetectorController.$inject = ['$scope', 'game', 'detector', 'lab'];
+ app.controller('DetectorController', DetectorController);
- app.controller('LabController', ['$interval', 'game', 'detector', function ($interval, game, detector) {
- this.lab = game.lab;
- this.showDetectorInfo = function () {
- if (!this._detectorInfo) {
- this._detectorInfo = Helpers.loadFile('html/detector.html');
+
+ function LabController($interval, game, detector, lab) {
+ // todo give workers instead of game
+ var vm = this;
+ vm.lab = lab;
+ vm.showDetectorInfo = function () {
+ if (!vm._detectorInfo) {
+ vm._detectorInfo = Helpers.loadFile('html/detector.html');
}
- UI.showModal('Detector', this._detectorInfo);
+ UI.showModal('Detector', vm._detectorInfo);
};
$interval(function () { // one tick
- var grant = game.lab.getGrant();
+ var grant = lab.getGrant();
UI.showUpdateValue("#update-funding", grant);
var sum = 0;
for (var i = 0; i < game.workers.length; i++) {
sum += game.workers[i].state.hired * game.workers[i].state.rate;
}
if (sum > 0) {
- game.lab.acquireData(sum);
+ lab.acquireData(sum);
UI.showUpdateValue("#update-data", sum);
detector.addEventExternal(game.workers.map(function (w) {
return w.state.hired;
}).reduce(function (a, b) {
- return a + b
+ return a + b;
}, 0));
}
}, 1000);
- }]);
+ };
+ LabController.$inject = ['$interval', 'game', 'detector', 'lab'];
+ app.controller('LabController', LabController);
- app.controller('ObservationsController', ['$scope', 'game', function ($scope, game) {
+
+ function ObservationsController($scope, game, lab) {
var vm = this;
- vm.observations = game.lab.state.observations;
+ vm.observations = lab.state.observations;
vm.gridOptions = {
enableFiltering: true,
- columnDefs: [
- { field: 'inputs', filter:{}, visible:true},
- { field: 'reactants', visible:false},
- { field: 'results', visible:true, sort: { direction: 'asc' }},
- { field: 'catalysts', visible:false},
- { field: 'conditions', visible:false},
- ],
+ columnDefs: [{
+ field: 'inputs',
+ filter: {},
+ visible: true
+ }, {
+ field: 'reactants',
+ visible: false
+ }, {
+ field: 'results',
+ visible: true,
+ sort: {
+ direction: 'asc'
+ }
+ }, {
+ field: 'catalysts',
+ visible: false
+ }, {
+ field: 'conditions',
+ visible: false
+ }, ],
data: vm.observations
};
- }]);
+ };
+ ObservationsController.$inject = ['$scope', 'game', 'lab'];
+ app.controller('ObservationsController', ObservationsController);
- app.controller('UpgradesController', ['$scope', 'game', function ($scope, game) {
- this.upgrades = game.upgrades;
- this.isVisible = function (upgrade) {
- return upgrade.isVisible(game.lab, game.allObjects);
+ function UpgradesController($scope, game, lab) {
+ var vm = this;
+ vm.upgrades = game.upgrades;
+ vm.isVisible = function (upgrade) {
+ return upgrade.isVisible(lab, game.allObjects);
};
- this.isAvailable = function (upgrade) {
- return upgrade.isAvailable(game.lab, game.allObjects);
+ vm.isAvailable = function (upgrade) {
+ return upgrade.isAvailable(lab, game.allObjects);
};
- this.upgrade = function (upgrade) {
- if (upgrade.buy(game.lab, game.allObjects)) {
+ vm.upgrade = function (upgrade) {
+ if (upgrade.buy(lab, game.allObjects)) {
UI.showUpdateValue("#update-funding", upgrade.cost);
}
- }
- }]);
+ };
+ };
+ UpgradesController.$inject = ['$scope', 'game', 'lab'];
+ app.controller('UpgradesController', UpgradesController);
- app.controller('AchievementsController', function ($scope, game) {
- $scope.achievements = game.achievements;
- $scope.progress = function () {
+ function AchievementsController($scope, game, lab) {
+ var vm = this;
+ vm.achievements = game.achievements;
+ vm.progress = function () {
return game.achievements.filter(function (a) {
- return a.validate(game.lab, game.allObjects, game.lastSaved);
+ return a.validate(lab, game.allObjects, game.lastSaved);
}).length;
};
- });
+ };
+ AchievementsController.$inject = ['$scope', 'game', 'lab'];
+ app.controller('AchievementsController', AchievementsController);
- app.controller('SaveController', ['$scope', '$interval', 'game', function ($scope, $interval, game) {
+ function SaveController($scope, $interval, $window, game, lab) {
+ var vm = this;
game.lastSaved = new Date().getTime();
- $scope.lastSaved = game.lastSaved;
- $scope.saveNow = function () {
+ vm.lastSaved = game.lastSaved;
+ vm.saveNow = function () {
var saveTime = new Date().getTime();
- game.lab.state.time += saveTime - game.lastSaved;
+ lab.state.time += saveTime - game.lastSaved;
game.save();
game.lastSaved = saveTime;
- $scope.lastSaved = game.lastSaved;
+ vm.lastSaved = game.lastSaved;
};
- $scope.restart = function () {
- if (window.confirm(
+ vm.restart = function () {
+ if ($window.confirm(
'Do you really want to restart the game? All progress will be lost.'
)) {
ObjectStorage.clear();
- window.location.reload(true);
+ $window.location.reload(true);
}
};
- $interval($scope.saveNow, 10000);
- }]);
+ $interval(vm.saveNow, 10000);
+ };
+ SaveController.$inject = ['$scope', '$interval', '$window', 'game', 'lab'];
+ app.controller('SaveController', SaveController);
- app.controller('StatsController', ['$scope', 'game', function ($scope, game) {
- $scope.lab = game.lab;
- }]);
+ function StatsController($scope, lab) {
+ var vm = this;
+ vm.lab = lab;
+ };
+ StatsController.$inject = ['$scope', 'lab'];
+ app.controller('StatsController', StatsController);
analytics.init();
analytics.sendScreen(analytics.screens.main);
diff --git a/js/detector/detector.js b/js/detector/detector.js
index ca789db..97282ba 100644
--- a/js/detector/detector.js
+++ b/js/detector/detector.js
@@ -6,8 +6,8 @@ var Detector = function(){
return {
core:
{
- canvas: null,
- ctx: null
+ // canvas: null,
+ // ctx: null
},
//
// events:
@@ -19,8 +19,8 @@ var Detector = function(){
flame:
{
- canvas: null,
- ctx: null
+ // canvas: null,
+ // ctx: null
},
elements: new GameObjects.ElementStores(),
@@ -39,15 +39,15 @@ var Detector = function(){
init: function(baseSize,element)
{
// get canvas
- this.core.canvas = document.getElementById('detector-core');
- if (!this.core.canvas) {
- this.core.canvas=$('');
- $(element).append(this.core.canvas);
- }
- this.core.ctx = this.core.canvas.getContext('2d');
-
- this.flame.canvas = document.getElementById('detector-flame');
- this.flame.ctx = this.flame.canvas.getContext('2d');
+ // this.core.canvas = document.getElementById('detector-core');
+ // if (!this.core.canvas) {
+ // this.core.canvas=$('');
+ // $(element).append(this.core.canvas);
+ // }
+ // this.core.ctx = this.core.canvas.getContext('2d');
+ //
+ // this.flame.canvas = document.getElementById('detector-flame');
+ // this.flame.ctx = this.flame.canvas.getContext('2d');
this.initBubbles();
this.initFlame();
@@ -130,8 +130,8 @@ var Detector = function(){
},
/** Clear an element back to element Store **/
- storeElementByHashKey: function(hashKey,game){
- var i = this.elements.findIndexByHashKey(hashKey);
+ storeElementBy: function(qObject,game){
+ var i = _.findIndex(this.elements,qObject);
var removedElement = this.elements.splice(i,1)[0];
return game.elements.get(removedElement.key).state.amount+=1;
},
@@ -139,7 +139,7 @@ var Detector = function(){
clearAll: function(game){
var hashKeys = this.elements.map(function(e){return e.$$hashKey;});
for (var i = 0; i < hashKeys.length; i++) {
- this.storeElementByHashKey(hashKeys[i], game);
+ this.storeElementBy({'$$hashKey': hashKeys[i]}, game);
}
},
@@ -231,7 +231,8 @@ var Detector = function(){
for (var i = 0; i < reactants.length; i++) {
// get the uuid from inputs
var ingredient = inputs.filter(function(e){return e.key===reactants[i];})[0];
- this.elements.findIndexByHashKey(ingredient.uuid);
+ var j = _.findIndex(this.elements,{uuid:ingredient.uuid});
+ var removed = this.elements.slice(j,1);
}
// TODO use angular effects to remove in puff of fade
diff --git a/js/game.js b/js/game.js
index 979954e..912b27a 100644
--- a/js/game.js
+++ b/js/game.js
@@ -5,19 +5,20 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
'use strict';
var Game = function () {
- this.lab = new GameObjects.Lab();
+ // this.lab = new GameObjects.Lab();
this.elements = null;
this.workers = null;
this.upgrades = null;
this.achievements = null;
this.allObjects = {
- lab: this.lab
+ // lab: this.lab
};
this.loaded = false;
this.rules = null;
};
- Game.prototype.load = function () {
+ Game.prototype.load = function ($http, $q) {
+ var self = this;
if (this.loaded) {
return;
}
@@ -27,50 +28,94 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
// make it work with Angular. If you know a way, let me know, and I'll
// give you a beer. - Kevin
this.elements = Helpers.loadFile('json/elements.json');
- this.workers = Helpers.loadFile('json/workers.json');
- this.upgrades = Helpers.loadFile('json/upgrades.json');
- this.achievements = Helpers.loadFile('json/achievements.json');
- this.keywords = Helpers.loadFile('json/keywords.json');
+ this.workers = Helpers.loadFile('/json/workers.json');
+ this.upgrades = Helpers.loadFile('./json/upgrades.json');
+ this.achievements = Helpers.loadFile('./json/achievements.json');
+ this.keywords = Helpers.loadFile('./json/keywords.json');
- // Turn JSON files into actual game objects and fill map of all objects
- var _this = this;
- var makeGameObject = function (type, object) {
- // It's okay to define this function here since load is only called
- // once anyway...
- var o = new type(object);
- _this.allObjects[o.key] = o;
- return o;
- };
- this.elements = this.elements.slice(0,20).map(
- function (r) {
- return makeGameObject(GameObjects.ElementStore, r);
- });
- this.workers = this.workers.map(
- function (w) {
- return makeGameObject(GameObjects.Worker, w);
- });
- this.upgrades = this.upgrades.map(
- function (u) {
- return makeGameObject(GameObjects.Upgrade, u);
- });
- this.achievements = this.achievements.map(
- function (a) {
- return makeGameObject(GameObjects.Achievement, a);
- });
- // Load states from local store
- for (var key in this.allObjects) {
- var o = this.allObjects[key];
- o.loadState(ObjectStorage.load(key));
- }
+ // function successCallback(response) {
+ // return angular.fromJson(response.data);
+ // }
+ //
+ // function errorCallback(response) {
+ // return console.error('Could not get url', response.statusText, response);
+ // }
+ // return $q.all(
+ // $http.get('json/elements.json', {
+ // transformResponse: angular.fromJson
+ // })
+ // .then(function (response) {
+ // return self.elements = response.data;
+ // }),
+ // $http.get('json/workers.json', {
+ // transformResponse: angular.fromJson
+ // })
+ // .then(function (response) {
+ // return self.workers = response.data;
+ // }),
+ // $http.get('json/upgrades.json', {
+ // transformResponse: angular.fromJson
+ // })
+ // .then(
+ // function (response) {
+ // return self.upgrades = response.data;
+ // }),
+ // $http.get('json/achievements.json', {
+ // transformResponse: angular.fromJson
+ // })
+ // .then(
+ // function (response) {
+ // return self.achievements = response.data;
+ // }),
+ // $http.get('json/keywords.json', {
+ // transformResponse: angular.fromJson
+ // })
+ // .then(
+ // function (response) {
+ // return self.keywords = response.data;
+ // })
+ // ).then(function () {
- // put elements in extended array with utility methods
- this.elementStore = new GameObjects.ElementStores();
- this.elementStore.push.apply(this.elementStore, this.elements);
- this.elements = this.elementStore;
+ // Turn JSON files into actual game objects and fill map of all objects
+ var makeGameObject = function (type, object) {
+ // It's okay to define this function here since load is only called
+ // once anyway...
+ var o = new type(object);
+ self.allObjects[o.key] = o;
+ return o;
+ };
+ self.elements = self.elements.slice(0, 20).map(
+ function (r) {
+ return makeGameObject(GameObjects.ElementStore, r);
+ });
+ self.workers = self.workers.map(
+ function (w) {
+ return makeGameObject(GameObjects.Worker, w);
+ });
+ self.upgrades = self.upgrades.map(
+ function (u) {
+ return makeGameObject(GameObjects.Upgrade, u);
+ });
+ self.achievements = self.achievements.map(
+ function (a) {
+ return makeGameObject(GameObjects.Achievement, a);
+ });
+ // Load states from local store
+ for (var key in self.allObjects) {
+ var o = self.allObjects[key];
+ o.loadState(ObjectStorage.load(key));
+ }
- this.rules = this.generateRules();
+ // put elements in extended array with utility methods
+ self.elementStore = new GameObjects.ElementStores();
+ self.elementStore.push.apply(self.elementStore, self.elements);
+ self.elements = self.elementStore;
- this.loaded = true;
+ self.rules = self.generateRules();
+
+ self.loaded = true;
+ return self;
+ // });
};
/** Generate rules between runes **/
diff --git a/js/helpers.js b/js/helpers.js
index f2ba604..a903ba4 100644
--- a/js/helpers.js
+++ b/js/helpers.js
@@ -2,95 +2,102 @@
* Define some useful helpers that are used throughout the game.
*/
var Helpers = (function () {
- 'use strict';
- /** Load a file (usually JSON).
- */
- var loadFile = function (filename) {
- var res;
- $.ajax({
- async: false,
- url : filename,
- success : function(data) {
- res = data;
- }
- });
- return res;
- };
+ 'use strict';
+ /** Load a file (usually JSON).
+ */
+ var loadFile = function (filename) {
+ var res;
+ $.ajax({
+ async: false,
+ url: filename,
+ success: function (data) {
+ res = data;
+ }
+ });
+ return res;
+ };
- var makeGameObject = function(type, object) {
- // It's okay to define this function here since load is only called
- // once anyway...
- var o = new type(object);
- _this.allObjects[o.key] = o;
- return o;
- };
+ /** Format a number with proper postfix.
+ */
+ var formatNumberPostfix = function (number) {
+ if (typeof number !== "number") {
+ return 0;
+ }
- /** Format a number with proper postfix.
- */
- var formatNumberPostfix = function (number) {
- if (typeof number !== "number") {
- return 0;
+ var prefixes = [{
+ magnitude: 1e24,
+ label: 'Y'
+ }, {
+ magnitude: 1e21,
+ label: 'Z'
+ }, {
+ magnitude: 1e18,
+ label: 'E'
+ }, {
+ magnitude: 1e15,
+ label: 'P'
+ }, {
+ magnitude: 1e12,
+ label: 'T'
+ }, {
+ magnitude: 1e9,
+ label: 'B'
+ }, {
+ magnitude: 1e6,
+ label: 'M'
+ }, {
+ magnitude: 1e3,
+ label: 'k'
+ }];
+
+ var abs = Math.abs(number);
+ for (var i = 0; i < prefixes.length; i++) {
+ if (abs >= prefixes[i].magnitude) {
+ return (number / prefixes[i].magnitude).toFixed(1) + prefixes[i].label;
+ }
+ }
+ return number;
}
- var prefixes = [
- { magnitude: 1e24, label: 'Y' },
- { magnitude: 1e21, label: 'Z' },
- { magnitude: 1e18, label: 'E' },
- { magnitude: 1e15, label: 'P' },
- { magnitude: 1e12, label: 'T' },
- { magnitude: 1e9, label: 'B' },
- { magnitude: 1e6, label: 'M' },
- { magnitude: 1e3, label: 'k' }
- ];
+ var formatTime = function (msec) {
+ var totals = Math.ceil(msec / 1000);
+ var days = Math.floor(totals / (24 * 60 * 60));
+ var hours = Math.floor((totals % (24 * 60 * 60)) / (60 * 60));
+ var totalmin = (totals % (24 * 60 * 60)) % (60 * 60);
+ var mins = Math.floor(totalmin / 60);
+ var secs = totalmin % 60;
- var abs = Math.abs(number);
- for (var i = 0; i < prefixes.length; i++) {
- if (abs >= prefixes[i].magnitude) {
- return (number / prefixes[i].magnitude).toFixed(1) + prefixes[i].label;
- }
- }
- return number;
- }
+ var str = [];
+ if (days > 0) {
+ str.push(days + ' day' + (days % 100 == 1 ? '' : 's'));
+ }
+ if (hours > 0) {
+ str.push(hours + ' h');
+ }
+ if (mins > 0) {
+ str.push(mins + ' min');
+ }
+ if (secs > 0) {
+ str.push(secs + ' s');
+ }
- var formatTime = function (msec) {
- var totals = Math.ceil(msec / 1000);
- var days = Math.floor(totals / (24 * 60 * 60));
- var hours = Math.floor((totals % (24 * 60 * 60)) / (60 * 60));
- var totalmin = (totals % (24 * 60 * 60)) % (60 * 60);
- var mins = Math.floor(totalmin / 60);
- var secs = totalmin % 60;
+ return str.join(', ');
+ };
- var str = [];
- if (days > 0) {
- str.push(days + ' day' + (days % 100 == 1 ? '' : 's'));
- }
- if (hours > 0) {
- str.push(hours + ' h');
- }
- if (mins > 0) {
- str.push(mins + ' min');
- }
- if (secs > 0) {
- str.push(secs + ' s');
- }
+ var saveVersion = '1.0';
+ var validateSaveVersion = function () {
+ var ver = ObjectStorage.load('saveVersion');
+ if (typeof ver === 'undefined' || ver != saveVersion) {
+ ObjectStorage.clear();
+ ObjectStorage.save('saveVersion', saveVersion);
+ }
+ };
- return str.join(', ');
- };
-
- var saveVersion = '1.0';
- var validateSaveVersion = function () {
- var ver = ObjectStorage.load('saveVersion');
- if (typeof ver === 'undefined' || ver != saveVersion) {
- ObjectStorage.clear();
- ObjectStorage.save('saveVersion', saveVersion);
- }
- };
-
- return {
- loadFile: loadFile,
- formatNumberPostfix: formatNumberPostfix,
- formatTime: formatTime,
- validateSaveVersion: validateSaveVersion,
- analytics: ''
- };
+ return {
+ loadFile: loadFile,
+ formatNumberPostfix: formatNumberPostfix,
+ formatTime: formatTime,
+ validateSaveVersion: validateSaveVersion,
+ analytics: ''
+ };
})();
diff --git a/json/elements.json b/json/elements.json
index bc51132..b2655f8 100644
--- a/json/elements.json
+++ b/json/elements.json
@@ -1,83 +1,59 @@
-[
- {"key":"ᚠ"},
- {"key":"ᚡ"},
- {"key":"ᚢ"},
- {"key":"ᚣ"},
- {"key":"ᚤ"},
- {"key":"ᚥ"},
- {"key":"ᚦ"},
- {"key":"ᚧ"},
- {"key":"ᚨ"},
- {"key":"ᚩ"},
- {"key":"ᚪ"},
- {"key":"ᚫ"},
- {"key":"ᚬ"},
- {"key":"ᚭ"},
- {"key":"ᚮ"},
- {"key":"ᚯ"},
- {"key":"ᚰ"},
- {"key":"ᚱ"},
- {"key":"ᚲ"},
- {"key":"ᚳ"},
- {"key":"ᚴ"},
- {"key":"ᚵ"},
- {"key":"ᚶ"},
- {"key":"ᚷ"},
- {"key":"ᚸ"},
- {"key":"ᚹ"},
- {"key":"ᚺ"},
- {"key":"ᚻ"},
- {"key":"ᚼ"},
- {"key":"ᚽ"},
- {"key":"ᚾ"},
- {"key":"ᚿ"},
- {"key":"ᛀ"},
- {"key":"ᛁ"},
- {"key":"ᛂ"},
- {"key":"ᛃ"},
- {"key":"ᛄ"},
- {"key":"ᛅ"},
- {"key":"ᛆ"},
- {"key":"ᛇ"},
- {"key":"ᛈ"},
- {"key":"ᛉ"},
- {"key":"ᛊ"},
- {"key":"ᛋ"},
- {"key":"ᛌ"},
- {"key":"ᛍ"},
- {"key":"ᛎ"},
- {"key":"ᛏ"},
- {"key":"ᛐ"},
- {"key":"ᛑ"},
- {"key":"ᛒ"},
- {"key":"ᛓ"},
- {"key":"ᛔ"},
- {"key":"ᛕ"},
- {"key":"ᛖ"},
- {"key":"ᛗ"},
- {"key":"ᛘ"},
- {"key":"ᛙ"},
- {"key":"ᛚ"},
- {"key":"ᛛ"},
- {"key":"ᛜ"},
- {"key":"ᛝ"},
- {"key":"ᛞ"},
- {"key":"ᛟ"},
- {"key":"ᛠ"},
- {"key":"ᛡ"},
- {"key":"ᛢ"},
- {"key":"ᛣ"},
- {"key":"ᛤ"},
- {"key":"ᛥ"},
- {"key":"ᛦ"},
- {"key":"ᛧ"},
- {"key":"ᛨ"},
- {"key":"ᛩ"},
- {"key":"ᛪ"},
- {"key":"᛫"},
- {"key":"᛬"},
- {"key":"᛭"},
- {"key":"ᛮ"},
- {"key":"ᛯ"},
- {"key":"ᛰ"}
-]
+[{"key": "🂡","name":"Ace","value":"1","suite":"Spades","color":"Black","royal":"false","face":"false","number":"false"},
+{"key": "🂢","name":"Two","value":"2","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂣","name":"Three","value":"3","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂤","name":"Four","value":"4","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂥","name":"Five","value":"5","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂦","name":"Six","value":"6","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂧","name":"Seven","value":"7","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂨","name":"Eight","value":"8","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂩","name":"Nine","value":"9","suite":"Spades","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🂪","name":"Ten","value":"10","suite":"Spades","color":"Black","royal":"false","face":"true","number":"true"},
+{"key": "🂫","name":"Jack","value":"11","suite":"Spades","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🂬","name":"Knight","value":"12","suite":"Spades","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🂭","name":"Queen","value":"13","suite":"Spades","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🂮","name":"King","value":"14","suite":"Spades","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🂱","name":"Ace","value":"1","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"false"},
+{"key": "🂲","name":"Two","value":"2","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂳","name":"Three","value":"3","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂴","name":"Four","value":"4","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂵","name":"Five","value":"5","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂶","name":"Six","value":"6","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂷","name":"Seven","value":"7","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂸","name":"Eight","value":"8","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂹","name":"Nine","value":"9","suite":"Hearts","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🂺","name":"Ten","value":"10","suite":"Hearts","color":"Red","royal":"false","face":"true","number":"true"},
+{"key": "🂻","name":"Jack","value":"11","suite":"Hearts","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🂼","name":"Knight","value":"12","suite":"Hearts","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🂽","name":"Queen","value":"13","suite":"Hearts","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🂾","name":"King","value":"14","suite":"Hearts","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🃁","name":"Ace","value":"1","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"false"},
+{"key": "🃂","name":"Two","value":"2","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃃","name":"Three","value":"3","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃄","name":"Four","value":"4","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃅","name":"Five","value":"5","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃆","name":"Six","value":"6","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃇","name":"Seven","value":"7","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃈","name":"Eight","value":"8","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃉","name":"Nine","value":"9","suite":"Diamonds","color":"Red","royal":"false","face":"false","number":"true"},
+{"key": "🃊","name":"Ten","value":"10","suite":"Diamonds","color":"Red","royal":"false","face":"true","number":"true"},
+{"key": "🃋","name":"Jack","value":"11","suite":"Diamonds","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🃌","name":"Knight","value":"12","suite":"Diamonds","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🃍","name":"Queen","value":"13","suite":"Diamonds","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🃎","name":"King","value":"14","suite":"Diamonds","color":"Red","royal":"true","face":"true","number":"false"},
+{"key": "🃑","name":"Ace","value":"1","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"false"},
+{"key": "🃒","name":"Two","value":"2","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃓","name":"Three","value":"3","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃔","name":"Four","value":"4","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃕","name":"Five","value":"5","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃖","name":"Six","value":"6","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃗","name":"Seven","value":"7","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃘","name":"Eight","value":"8","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃙","name":"Nine","value":"9","suite":"Clubs","color":"Black","royal":"false","face":"false","number":"true"},
+{"key": "🃚","name":"Ten","value":"10","suite":"Clubs","color":"Black","royal":"false","face":"true","number":"true"},
+{"key": "🃛","name":"Jack","value":"11","suite":"Clubs","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🃜","name":"Knight","value":"12","suite":"Clubs","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🃝","name":"Queen","value":"13","suite":"Clubs","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🃞","name":"King","value":"14","suite":"Clubs","color":"Black","royal":"true","face":"true","number":"false"},
+{"key": "🂠","name":"Playing Card","value":"15","suite":"Black","color":"Black","royal":"false","face":"false","number":"false"},
+{"key": "🃏","name":"Joker","value":"16","suite":"Black","color":"Black","royal":"false","face":"true","number":"false"},
+{"key": "🃟","name":"Joker","value":"16","suite":"Red","color":"Red","royal":"false","face":"true","number":"false"}]
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0af1108
--- /dev/null
+++ b/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "sciencealchemy",
+ "version": "0.0.5",
+ "description": "Science Alchemy",
+ "main": "js/app.js",
+ "directories": {
+ "test": "tests"
+ },
+ "scripts": {
+ "postinstall": "bower install",
+ "prestart": "npm install",
+ "start": "http-server -a 0.0.0.0 -p 8000",
+ "pretest": "npm install",
+ "test": "node node_modules/karma/bin/karma start test/karma.conf.js",
+ "test-single-run": "node node_modules/karma/bin/karma start test/karma.conf.js --single-run",
+ "preupdate-webdriver": "npm install",
+ "update-webdriver": "webdriver-manager update",
+ "preprotractor": "npm run update-webdriver",
+ "protractor": "protractor test/protractor-conf.js",
+ "update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('bower_components/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'app/index-async.html');\""
+ },
+ "author": "wassname",
+ "license": "MIT",
+ "devDependencies": {
+ "bower": "^1.7.7",
+ "eslint": "^2.2.0",
+ "eslint-config-angular": "^0.4.0",
+ "eslint-plugin-angular": "^0.15.0",
+ "http-server": "^0.9.0",
+ "jasmine": "^2.4.1",
+ "karma": "^0.13.21",
+ "karma-chrome-launcher": "^0.2.2",
+ "karma-firefox-launcher": "^0.1.7",
+ "karma-jasmine": "^0.3.7",
+ "ng-html2js": "^2.0.0",
+ "protractor": "^3.1.1",
+ "shelljs": "^0.6.0",
+ "tmp": "0.0.28",
+ "webdriver": "0.0.1"
+ }
+}
diff --git a/test/e2e/scenarios.js b/test/e2e/scenarios.js
new file mode 100644
index 0000000..79b5b6e
--- /dev/null
+++ b/test/e2e/scenarios.js
@@ -0,0 +1,101 @@
+'use strict';
+
+/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
+
+describe('PhoneCat App', function() {
+
+ it('should redirect index.html to index.html#/phones', function() {
+ browser.get('app/index.html');
+ browser.getLocationAbsUrl().then(function(url) {
+ expect(url).toEqual('/phones');
+ });
+ });
+
+
+ describe('Phone list view', function() {
+
+ beforeEach(function() {
+ browser.get('app/index.html#/phones');
+ });
+
+
+ it('should filter the phone list as a user types into the search box', function() {
+
+ var phoneList = element.all(by.repeater('phone in phones'));
+ var query = element(by.model('query'));
+
+ expect(phoneList.count()).toBe(20);
+
+ query.sendKeys('nexus');
+ expect(phoneList.count()).toBe(1);
+
+ query.clear();
+ query.sendKeys('motorola');
+ expect(phoneList.count()).toBe(8);
+ });
+
+
+ it('should be possible to control phone order via the drop down select box', function() {
+
+ var phoneNameColumn = element.all(by.repeater('phone in phones').column('phone.name'));
+ var query = element(by.model('query'));
+
+ function getNames() {
+ return phoneNameColumn.map(function(elm) {
+ return elm.getText();
+ });
+ }
+
+ query.sendKeys('tablet'); //let's narrow the dataset to make the test assertions shorter
+
+ expect(getNames()).toEqual([
+ "Motorola XOOM\u2122 with Wi-Fi",
+ "MOTOROLA XOOM\u2122"
+ ]);
+
+ element(by.model('orderProp')).element(by.css('option[value="name"]')).click();
+
+ expect(getNames()).toEqual([
+ "MOTOROLA XOOM\u2122",
+ "Motorola XOOM\u2122 with Wi-Fi"
+ ]);
+ });
+
+
+ it('should render phone specific links', function() {
+ var query = element(by.model('query'));
+ query.sendKeys('nexus');
+ element.all(by.css('.phones li a')).first().click();
+ browser.getLocationAbsUrl().then(function(url) {
+ expect(url).toEqual('/phones/nexus-s');
+ });
+ });
+ });
+
+
+ describe('Phone detail view', function() {
+
+ beforeEach(function() {
+ browser.get('app/index.html#/phones/nexus-s');
+ });
+
+
+ it('should display nexus-s page', function() {
+ expect(element(by.binding('phone.name')).getText()).toBe('Nexus S');
+ });
+
+
+ it('should display the first phone image as the main phone image', function() {
+ expect(element(by.css('img.phone.active')).getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/);
+ });
+
+
+ it('should swap main image if a thumbnail image is clicked on', function() {
+ element(by.css('.phone-thumbs li:nth-child(3) img')).click();
+ expect(element(by.css('img.phone.active')).getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/);
+
+ element(by.css('.phone-thumbs li:nth-child(1) img')).click();
+ expect(element(by.css('img.phone.active')).getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/);
+ });
+ });
+});
diff --git a/test/karma.conf.js b/test/karma.conf.js
new file mode 100644
index 0000000..c0189b6
--- /dev/null
+++ b/test/karma.conf.js
@@ -0,0 +1,101 @@
+module.exports = function (config) {
+ config.set({
+
+ basePath: '../',
+ port: 9876,
+ // urlRoot: "/",
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+ frameworks: ['jasmine'],
+
+ browsers: ['Chrome', 'Firefox'],
+
+ plugins: [
+ 'karma-chrome-launcher',
+ 'karma-firefox-launcher',
+ 'karma-jasmine'
+ ],
+
+ junitReporter: {
+ outputFile: 'test_out/unit.xml',
+ suite: 'unit'
+ },
+
+ preprocessors: {
+ "*.html": ["ng-html2js"]
+ },
+
+ // ngHtml2JsPreprocessor: {
+ // // If your build process changes the path to your templates,
+ // // use stripPrefix and prependPrefix to adjust it.
+ // // stripPrefix: "source/path/to/templates/.*/",
+ // // prependPrefix: "web/path/to/templates/",
+ //
+ // // the name of the Angular module to create
+ // moduleName: "scienceAlchemy.templates"
+ // },
+
+
+ // use this to fix server 404 errors. Karma server everything at /base
+ proxies: {
+ '/json/': '/base/json/'
+ },
+
+
+ // list of files / patterns to load in the browser
+ files: [
+
+ // dependencies
+ 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/jquery-ui/jquery-ui.js',
+ 'bower_components/bootstrap/dist/js/bootstrap.js',
+ 'bower_components/angular/angular.js',
+ 'bower_components/angular-route/angular-route.js',
+ 'bower_components/angular-resource/angular-resource.js',
+ 'bower_components/angular-animate/angular-animate.js',
+ 'bower_components/angular-mocks/angular-mocks.js',
+ 'bower_components/angular-dragdrop/src/angular-dragdrop.js',
+ 'bower_components/angular-ui-grid/ui-grid.js',
+ 'bower_components/lodash/dist/lodash.js',
+ 'js/external/*.js',
+
+ // fixtures
+ {
+ pattern: 'index.html',
+ watched: true,
+ served: true,
+ included: false
+ }, {
+ pattern: 'json/*.json',
+ watched: true,
+ served: true,
+ included: false
+ },
+ {
+ pattern: 'css/*.css',
+ watched: true,
+ served: true,
+ included: false
+ },
+
+ // files to test
+ 'js/storage.js',
+ 'js/helpers.js',
+ 'js/analytics.js',
+ 'js/gameobjects.js',
+ 'js/detector/flame.js',
+ 'js/detector/bubblr.js',
+ 'js/detector/event.js',
+ 'js/detector/detector.js',
+ 'js/ui.js',
+ 'js/game.js',
+ 'js/app.js',
+ 'test/unit/**/*.js'
+ ],
+ });
+};
diff --git a/test/protractor-conf.js b/test/protractor-conf.js
new file mode 100644
index 0000000..30c78c8
--- /dev/null
+++ b/test/protractor-conf.js
@@ -0,0 +1,22 @@
+
+exports.config = {
+ allScriptsTimeout: 11000,
+
+ specs: [
+ 'e2e/*.js'
+ ],
+
+ capabilities: {
+ 'browserName': 'chrome'
+ },
+
+ chromeOnly: true,
+
+ baseUrl: 'http://localhost:8000/',
+
+ framework: 'jasmine',
+
+ jasmineNodeOpts: {
+ defaultTimeoutInterval: 30000
+ }
+};
diff --git a/test/unit/controllersSpec.js b/test/unit/controllersSpec.js
new file mode 100644
index 0000000..f4a336c
--- /dev/null
+++ b/test/unit/controllersSpec.js
@@ -0,0 +1,53 @@
+'use strict';
+
+/* jasmine specs for controllers go here */
+describe('scienceAlchemy controllers', function () {
+ var $controller;
+
+ beforeEach(function () {
+ jasmine.addMatchers({
+ toEqualData: function(util, customEqualityTesters) {
+ return {
+ compare: function(actual, expected) {
+ var passed = angular.equals(actual, expected);
+ return {
+ pass: passed,
+ message: 'Expected "' + actual + '"' + (passed ? '' : ' not') + ' to angular.equals "' + expected + '"'
+ };
+ }
+ };
+ }
+ });
+ });
+ beforeEach(module('scienceAlchemy'));
+ beforeEach(inject(function (_$controller_) {
+ // The injector unwraps the underscores (_) from around the parameter names when matching
+ $controller = _$controller_;
+ }));
+
+ describe('ElementController', function () {
+ var $scope, controller;
+
+ beforeEach(function () {
+ $scope = {};
+ controller = $controller('ElementController',{$scope:$scope});
+ });
+
+ it('should have elements', function () {
+ expect(controller.elements).toBeDefined();
+ });
+
+ it('should be visible', function () {
+ var item = controller.elements[0];
+ expect(controller.isVisible(item)).toBeDefined();
+ });
+
+ it('should be isAvailable', function () {
+ var item = controller.elements[0];
+ expect(controller.isAvailable(item)).toBeDefined();
+ });
+
+ // onDrop
+ });
+
+});
diff --git a/test/unit/directivesSpec.js b/test/unit/directivesSpec.js
new file mode 100644
index 0000000..2e5469a
--- /dev/null
+++ b/test/unit/directivesSpec.js
@@ -0,0 +1,7 @@
+'use strict';
+
+/* jasmine specs for directives go here */
+
+describe('directives', function() {
+
+});
diff --git a/test/unit/filtersSpec.js b/test/unit/filtersSpec.js
new file mode 100644
index 0000000..43a61c7
--- /dev/null
+++ b/test/unit/filtersSpec.js
@@ -0,0 +1,53 @@
+'use strict';
+
+/* jasmine specs for filters go here */
+
+describe('filter', function () {
+
+ beforeEach(
+ module('scienceAlchemy')
+ );
+
+ describe('niceNumber', function () {
+ it('should make numbers human readable',
+ inject(function (niceNumberFilter) {
+ expect(niceNumberFilter(100000000)).toBe("100.0M");
+ expect(niceNumberFilter(10000)).toBe("10.0k");
+ expect(niceNumberFilter(0.000000001)).toBe(1e-9);
+
+ }));
+ });
+
+ describe('niceTime', function () {
+ it('should make time human readable',
+ inject(function (niceTimeFilter) {
+ expect(niceTimeFilter(100000000)).toBe("1 day, 3 h, 46 min, 40 s");
+ expect(niceTimeFilter(10000)).toBe("10 s");
+ expect(niceTimeFilter(0.000000001)).toBe("1 s");
+
+ }));
+ });
+
+ describe('currency', function () {
+ it('should make currency human readable',
+ inject(function (currencyFilter) {
+ expect(currencyFilter(100000000)).toBe("JTN 100.0M");
+ expect(currencyFilter(10000)).toBe("JTN 10.0k");
+ expect(currencyFilter(0.000000001)).toBe('JTN 1e-9');
+ }));
+ });
+
+ describe('reverse', function () {
+ it('should reverse',
+ inject(function (reverseFilter) {
+ expect(reverseFilter([1,2,3])[0]).toBe(3);
+ expect(reverseFilter([1,2,3])[1]).toBe(2);
+ expect(reverseFilter([1,2,3])[2]).toBe(1);
+ expect(reverseFilter([]).length).toBe(0);
+ expect(reverseFilter([{i:1,2:2},{i:2},{i:3}])[0].i).toBe(3);
+ expect(reverseFilter([{i:1,2:2},{i:2},{i:3}])[1].i).toBe(2);
+ expect(reverseFilter([{i:1,2:2},{i:2},{i:3}])[2].i).toBe(1);
+
+ }));
+ });
+});
diff --git a/test/unit/servicesSpec.js b/test/unit/servicesSpec.js
new file mode 100644
index 0000000..d6bd752
--- /dev/null
+++ b/test/unit/servicesSpec.js
@@ -0,0 +1,27 @@
+'use strict';
+
+describe('services', function () {
+
+ //load modules
+ beforeEach(module('scienceAlchemy'));
+
+ // Test service availability
+ describe('game', function () {
+ it('should exist', inject(function (game) {
+ expect(game).toBeDefined();
+ }));
+ });
+
+ describe('detector', function () {
+ it('should exist', inject(function (detector) {
+ expect(detector).toBeDefined();
+ }));
+ });
+
+ describe('lab', function () {
+ it('should exist', inject(function (lab) {
+ expect(lab).toBeDefined();
+ }));
+ });
+
+});