Observations and reactions almost working

This commit is contained in:
2016-02-23 21:08:32 +08:00
parent e4cde4d8c7
commit 1805afe17a
6 changed files with 173 additions and 97 deletions
+3
View File
@@ -371,3 +371,6 @@ h1 br {
.Paired .q9-12{color:rgb(106,61,154)}
.Paired .q10-12{color:rgb(255,255,153)}
.Paired .q11-12{color:rgb(177,89,40)}
/* data tables */
+33 -17
View File
@@ -12,6 +12,10 @@
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="css/angular-datatables.css">
<link rel="stylesheet" href="bower_components/datatables/media/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="bower_components/datatables/media/css/dataTables.bootstrap.min.css">
<link rel="stylesheet" href="bower_components/angular-datatables/dist/plugins/bootstrap/datatables.bootstrap.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="icon" type="image/png" href="assets/favicon.png" />
@@ -90,9 +94,9 @@
<div class="col-md-4" ng-repeat="r in rc.elements">
<span ng-show="rc.isVisible(r)"
id="{{r.key}}"
class="{{r.key}} element element-icon {{ r.state.interesting ? 'blink' : '' }} {{'q'+r.state.color+'-12'}} {{r.state.amount>0 ? '': 'empty'}} ui-draggable"
class="{{r.key}} element element-icon {{ r.state.interesting ? 'blink' : '' }} {{'q'+r.state.color+'-12'}} {{r.state.amount>0 ? ' ui-draggable': 'empty'}}"
data-element="{{r.key}}"
data-drag="{{r.state.amount>0}}"
data-drag="true"
jqyoui-draggable="{containment:'offset'}"
data-jqyoui-options="{{rc.dragOptions}}"
data-hashkey={{r.$$hashKey}}
@@ -177,22 +181,28 @@
<div class="panel panel-default panel-stick">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fa fa-users"></i> HR
<i class="fa fa-users"></i> Observations
</h4>
</div>
<div class="panel-body scrollable large" id="hrLarge">
<div id="hrContent" ng-controller="HRController as hrc">
<ul class="media-list" ng-cloak>
<li class="media" ng-repeat="w in hrc.workers" ng-show="hrc.isVisible(w)">
<div class="media-body">
<h4 class="media-heading">{{ w.name }} <span ng-show="w.state.hired > 0" class="badge">{{ w.state.hired | niceNumber }}</span></h4>
<p ng-show="w.state.hired > 0">{{ w.description }}</p>
<p ng-show="w.state.hired > 0" class="small">Produce <strong>{{ w.state.rate | niceNumber }}</strong> data per second.</p>
<button class="btn btn-primary" ng-disabled="!hrc.isAvailable(w)" ng-click="hrc.hire(w)"><i class="fa fa-user"></i> <small>{{ w.state.cost | currency }}</small></button>
</div>
</li>
</ul>
<div id="hrContent" ng-controller="ObservationsController as oc">
<table datatable="ng" dt-options="oc.dtOptions" class="compact">
<thead>
<tr>
<th>Reactants</th>
<th>Results</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="o in ::oc.observations" ng-cloak>
<td>{{ o.inputs.join('') }}</td>
<td>{{ o.results.join('') }}</td>
</tr>
</tbody>
</table>
</div>
</div>
@@ -344,14 +354,20 @@
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script>
<script src="bower_components/angular-dragdrop/src/angular-dragdrop.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="js/external/jquery.ui.touch-punch.min.js"></script>
<script src="js/external/jquery.cookie-1.4.1.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script>
<script src="bower_components/angular-dragdrop/src/angular-dragdrop.min.js"></script>
<script src="js/external/retina.js"></script>
<script src="js/external/fastclick.js"></script>
<script src="bower_components/datatables/media/js/jquery.dataTables.min.js"></script>
<script src="bower_components/angular-datatables/dist/angular-datatables.min.js"></script>
<script src="js/storage.js"></script>
<script src="js/helpers.js"></script>
<script src="js/analytics.js"></script>
+14 -18
View File
@@ -17,7 +17,7 @@ var app = (function () {
// var allObjects = game.allObjects;
// var lastSaved;
var app = angular.module('scienceAlchemy', ['ngDragDrop']);
var app = angular.module('scienceAlchemy', ['ngDragDrop', 'datatables']);
// directives
@@ -96,8 +96,8 @@ var app = (function () {
if (!draggable.hasClass('element-icon')) {
var elementStore = vs.elements.get(key);
var i = findIndexByHashKey(draggable.data('hashkey'));
detector.elements.splice(i,1);
elementStore.state.amount+=1;
detector.elements.splice(i, 1);
elementStore.state.amount += 1;
}
};
vs.doElement = function (item) {
@@ -135,7 +135,9 @@ var app = (function () {
// containment:false
};
vm.onDrop = function (event, ui) {
detector.onDrop(event, ui, game);
var result = detector.onDrop(event, ui, game);
if (result)
game.lab.observe(result);
};
vm.click = function () {
game.lab.clickDetector();
@@ -148,7 +150,7 @@ var app = (function () {
console.log('toggleFlameFuel');
detector.flamer.toggleFuel();
};
vm.clearAll = function(){
vm.clearAll = function () {
detector.clearAll(game);
}
}]);
@@ -180,20 +182,14 @@ var app = (function () {
}, 1000);
}]);
app.controller('HRController', ['$scope', 'game', function ($scope, game) {
this.workers = game.workers;
this.isVisible = function (worker) {
return worker.isVisible(game.lab);
};
this.isAvailable = function (worker) {
return worker.isAvailable(game.lab);
};
this.hire = function (worker) {
var cost = worker.hire(game.lab);
if (cost > 0) {
UI.showUpdateValue("#update-funding", -cost);
}
app.controller('ObservationsController', ['$scope', 'game', function ($scope, game) {
var vm = this;
vm.observations = game.lab.state.observations;
vm.dtOptions = {
paginationType: 'full_numbers',
displayLength: 2
};
}]);
app.controller('UpgradesController', ['$scope', 'game', function ($scope, game) {
+37 -16
View File
@@ -150,11 +150,12 @@ var Detector = function(){
$droppable = angular.element(event.target);
// if the dragger came from the elements panels, clone it to here
var newElement;
if ($draggable.hasClass('element-icon')){
var elementStore = game.elements.filter(function(e){return e.key==$draggable.data('element');})[0];
elementStore.state.amount-=1;
var newElement = angular.copy(elementStore);
newElement = angular.copy(elementStore);
newElement.state.top=$draggable.offset().top;
newElement.state.left=$draggable.offset().left;
this.elements.push(newElement);
@@ -168,8 +169,8 @@ var Detector = function(){
var draggableLeft = $draggable.offset().left;
var draggableWidth = $draggable.height();
var draggableRight = draggableLeft + draggableWidth;
var $draggables = angular.element('#detector').find('.element').not('.element-icon'); // replace with detector.elements
var inputs = $draggables.filter( function() {
var detectorDOMElems = angular.element('#detector').find('.element').not('.element-icon'); // replace with detector.elements
var intersectingDOMElems = detectorDOMElems.filter( function() {
var $elem = angular.element(this);
var top = $elem.offset().top;
var height = $elem.height();
@@ -184,31 +185,51 @@ var Detector = function(){
return isCoveredByDraggable;
});
var reaction = this.experiment({inputs:inputs},game);
console.log('droppables', inputs.length);
// We have the DOM's in the area (maybe missing the newly dropped one)
// var droppedModel = game.elements.getByHashKey($draggable.data('hashkey'));
var intersectingElements = intersectingDOMElems.toArray().map(function(input){
return self.elements.getByHashKey(angular.element(input).data('hashkey'));
});
// make sure we include the dropped element as in some cases
// it wont have DOM object yet so it wont be picked up as intersecting
if (newElement && intersectingElements.indexOf(newElement)===-1) intersectingElements.push(newElement);
var observation = this.experiment({inputs:intersectingElements,location:$draggable.offset()},game);
console.log('droppables', intersectingElements.length, observation);
return observation;
},
/** Run an experiment depending on ingredients and conditions **/
/** Run an experiment depending on reactants and conditions **/
experiment: function(options,game) {
var inputs = options.inputs || [];
var inputKeys = inputs.map(function(i,e){return $(e).data('element')});
var inputKeys = inputs.map(function(e){return e.key;});
inputKeys.sort(); // this makes reaction be independant of order
var result = game.rules[inputKeys]
var result = game.rules[inputKeys];
if (result) {
return this.reaction(result.ingredients,result.rune,game)
this.reaction(result.reactants,result.results, game);
} else {
result = {
reactants: [],
catalysts: [],
conditions: [],
results: [],
inputs: inputKeys
};
}
return result;
},
/** Remove ingredients and make results with animations **/
reaction: function(ingredients,results,game){
/** Remove reactants and make results with animations **/
reaction: function(reactants,results,game){
// remove ingredients from detector
for (var i = 0; i < ingredients.length; i++) {
var ingredient = ingredients[i];
// remove reactants from detector
for (var i = 0; i < reactants.length; i++) {
var ingredient = reactants[i];
}
// TODO use angular effects to remove in puff of fade
@@ -218,7 +239,7 @@ var Detector = function(){
var resultKey = results[i];
// make sure it's discovered
var elementStore = this.elements.filter(function(e){return e.key===resultKey;});
var elementStore = game.elements.get(resultKey);
elementStore.state.discovered=true;
// add new element to beaker
@@ -229,7 +250,7 @@ var Detector = function(){
}
// effects
this.bubblr.start(1500);
this.bubblr.bubble();
},
}
+45 -40
View File
@@ -41,7 +41,7 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
_this.allObjects[o.key] = o;
return o;
};
this.elements = this.elements.map(
this.elements = this.elements.slice(0,20).map(
function (r) {
return makeGameObject(GameObjects.Element, r);
});
@@ -65,8 +65,8 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
// put elements in extended array with utility methods
this.elementStore = new GameObjects.ElementStore();
this.elementStore.push.apply(this.elementStore,this.elements);
this.elements=this.elementStore;
this.elementStore.push.apply(this.elementStore, this.elements);
this.elements = this.elementStore;
this.rules = this.generateRules();
@@ -75,46 +75,51 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
/** Generate rules between runes **/
Game.prototype.generateRules = function () {
var elements = this.elements;
// generate rules and store them with a hash of inredients
// the rule will be an object with ingredients, catalysts, conditions, results
// todo make a strcture that's more like a tree with progression etc
// todo add duds, misleading ones, explosions wildcards
// todo make this theory based?
// todo simulation
var rules = {};
for (var k = 0; k < this.elements.length * 5; k++) {
// make a rules
var rule = {
ingredients: [],
catalysts: [],
conditions: [],
results: [],
inputs: []
}
var numOfIngredients = 2 + Math.round(Math.random() * 2);
for (var i = 0; i < numOfIngredients; i++) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.ingredients.push(elements[j].key);
var rules = ObjectStorage['rules'];
if (!rules) {
var elements = this.elements;
// generate rules and store them with a hash of inredients
// the rule will be an object with reactants, catalysts, conditions, results
// todo make a strcture that's more like a tree with progression etc
// todo add duds, misleading ones, explosions wildcards
// todo make this theory based?
// todo simulation
var rules = {};
for (var k = 0; k < this.elements.length * 20; k++) {
// make a rules
var rule = {
reactants: [],
catalysts: [],
conditions: [],
results: [],
inputs: []
}
var numOfIngredients = 2 + Math.round(Math.random() * 2);
for (var i = 0; i < numOfIngredients; i++) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.reactants.push(elements[j].key);
}
if (Math.random() < 0.1) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.catalysts.push(elements[j].key);
}
var numOfresults = Math.round(Math.random() * 3);
for (var i = 0; i < numOfresults; i++) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.results.push(elements[j].key);
}
rule.inputs = [].concat(rule.reactants, rule.catalysts)
rule.reactants.sort()
rule.results.sort()
rule.catalysts.sort()
rule.inputs.sort();
// index byhash of sorted array of reactants
rules[rule.inputs] = rule
}
if (Math.random() < 0.1) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.catalysts.push(elements[j].key);
}
var numOfresults = Math.round(Math.random() * 3);
for (var i = 0; i < numOfresults; i++) {
var j = Math.round(Math.random() * (elements.length - 1));
rule.results.push(elements[j].key);
}
rule.inputs = [].concat(rule.ingredients, rule.catalysts)
rule.ingredients.sort()
rule.results.sort()
rule.catalysts.sort()
rule.inputs.sort();
// index byhash of sorted array of ingredients
rules[rule.inputs] = rule
}
ObjectStorage['rules'] = rules;
return rules;
},
Game.prototype.save = function () {
+41 -6
View File
@@ -21,6 +21,15 @@ var GameObjects = (function () {
function (state) {
$.extend(this.state, state);
};
GameObject.prototype.guid = function () {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
/** @class Lab
*/
@@ -39,7 +48,8 @@ var GameObjects = (function () {
moneySpent: 0,
dataCollected: 0,
dataSpent: 0,
time: 0
time: 0,
observations: [],
}
}]);
@@ -76,6 +86,14 @@ var GameObjects = (function () {
return false;
};
/**
* Takes in a rule/observation object and records observation in journal
* with reactants, inputs, catalysts, conditions, results
***/
Lab.prototype.observe = function (observation) {
this.state.observations.push(observation);
};
Lab.prototype.buy = function (cost) {
if (this.state.money >= cost) {
@@ -95,15 +113,15 @@ var GameObjects = (function () {
ElementStore.prototype.constructor = ElementStore;
/** Add a random element or specify it's key **/
ElementStore.prototype.addToStore = function(element){
ElementStore.prototype.addToStore = function (element) {
if (!element) this.get(element);
if (!element) element = this.select();
return element.state.amount+=1;
return element.state.amount += 1;
};
/** Select random element from store **/
ElementStore.prototype.select = function () {
var i = Math.floor((this.length-1)*Math.random());
var i = Math.floor((this.length - 1) * Math.random());
return this[i];
};
/** Get element by hashid **/
@@ -115,13 +133,29 @@ var GameObjects = (function () {
/** Get element by hashid **/
ElementStore.prototype.getByHashKey = function (hashKey) {
return this.filter(function (e) {
if (hashKey === undefined) {
console.warn('GetByHashKey given an undefined hashkey', hashKey)
return;
}
var res = this.filter(function (e) {
return e.$$hashKey === hashKey;
})[0];
});
if (res.length == 1) return res[0];
else if (res.length) {
console.warn('Got multiple results when filtering on hashKey', hashKey);
return res[0];
} else {
console.warn('Got no results when filtering on hashKey', hashKey);
return;
}
}
/** Get element by hashid **/
ElementStore.prototype.findIndexByHashKey = function (hashKey) {
if (hashKey === undefined) {
console.warn('FindIndexByHashKey given an undefined hashkey', hashKey)
return;
}
return this.findIndex(function (e) {
return e.$$hashKey === hashKey;
})[0];
@@ -135,6 +169,7 @@ var GameObjects = (function () {
this.state.discovered = Math.random() < 0.1;
this.state.interesting = Math.random() < 0.1;
this.state.color = Math.round(Math.random() * 11);
this.uuid=this.guid();
};
Element.prototype = Object.create(GameObject.prototype);