diff --git a/config/env/production.js b/config/env/production.js index 15bc0789ee..24a2bcc321 100755 --- a/config/env/production.js +++ b/config/env/production.js @@ -1,7 +1,7 @@ 'use strict'; module.exports = { - db: 'mongodb://localhost/mean-prod', + db: process.env.MONGOLAB_URI, /** * Database options that will be passed directly to mongoose.connect * Below are some examples. diff --git a/packages/custom/battle/app.js b/packages/custom/battle/app.js index 336af242f6..4e21da2acb 100755 --- a/packages/custom/battle/app.js +++ b/packages/custom/battle/app.js @@ -17,9 +17,16 @@ Battle.register(function(app, auth, database) { Battle.routes(app, auth, database); //We are adding a link to the main menu for all authenticated users + // Battle.menus.add({ + // title: 'battle example page', + // link: 'battle example page', + // roles: ['authenticated'], + // menu: 'main' + // }); + Battle.menus.add({ - title: 'battle example page', - link: 'battle example page', + title: 'Battle', + link: 'problem', roles: ['authenticated'], menu: 'main' }); diff --git a/packages/custom/battle/public/controllers/battle.js b/packages/custom/battle/public/controllers/battle.js index 1fd61ce2a2..60a7eb06dc 100755 --- a/packages/custom/battle/public/controllers/battle.js +++ b/packages/custom/battle/public/controllers/battle.js @@ -3,41 +3,199 @@ var clientIdProperty = 'clientID', defaultPrefix = 'DEFAULT_'; angular.module('mean.battle') - .controller('BattleController', ['$scope', '$rootScope', 'Global', 'Battle', 'MathProblemGenerator', - function($scope, $rootScope, Global, Battle, MathProblemGenerator) { - $scope.global = Global; - $scope.package = { - name: 'battle' - }; - $scope.battleMode = false; - $scope.choiceMode = true; - $scope.difficulty = 'easy'; - - $scope.chooseDifficulty = function chooseDifficulty (choice){ - if(choice == 'easy') { - $scope.problemScope = MathProblemGenerator.MathProblemGenerate(1); - } else if (choice == 'medium') { - $scope.problemScope = MathProblemGenerator.MathProblemGenerate(2); - } else if (choice == 'hard') { - $scope.problemScope = MathProblemGenerator.MathProblemGenerate(3); + .controller('Problem', ['$scope', '$rootScope', 'Global', 'Battle', 'apiFetch', 'stateMachine', + function($scope, $rootScope, Global, Battle, apiFetch, stateMachine) { + $scope.state = { + 'start': true, + 'battle': false, + 'success': false, + 'failure': false + }; + + $scope.battleState = { + 'question' : true, + 'postAnswer' : false, + 'done': false + }; + + $scope.activityLog = []; + + $scope.monster = { + // these will be filled in + health: 0 + }; + + $scope.player = { + currentHealth: Global.user.maxHealth, // set at max for now + power: 40 // I'm not sure what the spec is for power at the moment + }; + + $scope.addActivityLog = function(item) { + $scope.activityLog.push(item); + }; + + $scope.chooseDifficulty = function(diff) { + $scope.difficulty = diff; + stateMachine.switchState($scope.state, 'battle'); + $scope.addActivityLog('You choose to fight a ' + diff + ' monster'); + $scope.startBattle(); + }; + + // ML TODO: This feels like it's in the wrong place. Refactor eventually + $scope.startBattle = function() { + // Also determin power here too. + // ML TODO: Make a service/factory for generating a monster and so it can keep track of it's health + switch($scope.difficulty) { + case 'easy': + $scope.monster.health = 100; + $scope.monster.power = 10; + $scope.monster.xp = 100; + break; + case 'medium': + $scope.monster.health = 200; + $scope.monster.power = 20; + $scope.monster.xp = 200; + break; + case 'hard': + $scope.monster.health = 300; + $scope.monster.power = 30; + $scope.monster.xp = 300; + break; + } + }; + + $scope.restart = function() { + $scope.monster = {}; + $scope.player.currentHealth = Global.user.maxHealth; + $scope.activityLog = []; + stateMachine.switchState($scope.state, 'start'); + stateMachine.switchState($scope.battleState, 'question'); + }; + } + ]).controller('Battle', ['$scope', '$rootScope', 'apiFetch', 'rng', 'Global', 'stateMachine', + function($scope, $rootScope, apiFetch, rng, Global, stateMachine) { + $scope.problem = { + question: 'temp' + }; + + $scope.difficultyChances = { + 'easy': 0, + 'medium': 50, + 'hard': 75 + }; + + $scope.afterTurn = function(questionResult) { + // this all changes with difficulty as well + if(questionResult) { + switch($scope.difficulty) { + case 'easy': + $scope.playerAttack(); + $scope.endOfRound(); + break; + case 'medium': + $scope.rollPlayerAction(); + break; + case 'hard': + $scope.rollPlayerAction(); + break; + } + } else { + $scope.enemyAttack(); + $scope.endOfRound(); + } + }; + + $scope.fetchProblem = function() { + // change the difficulty here + apiFetch.fetchProblem('easy', 'math', function(p) { + $scope.problem = p; + }); + }; + + $scope.fetchProblem(); + + $scope.nextProblem = function() { + $scope.fetchProblem(); + stateMachine.switchState($scope.battleState, 'question'); + }; + + $scope.attempt = function() { + var attempt = $scope.user_attempt; + + apiFetch.submitAttempt($scope.problem.id, attempt, function(result) { + $scope.user_attempt = '' + if(result.result) { + $scope.addActivityLog('You answered correctly!'); + // stateMachine.switchState($scope.state, 'success'); + } else { + $scope.addActivityLog('You answered incorrectly.'); + // stateMachine.switchState($scope.state, 'failure'); + } + $scope.afterTurn(result.result); + }); + }; + + $scope.enemyAttack = function() { + // Enemy does damage + + // just basic health minus power + $scope.player.currentHealth -= $scope.monster.power; + $scope.addActivityLog('Monster dealt ' + $scope.monster.power + ' damage'); + }; + + $scope.playerAttack = function(factor) { + // Player does damage + factor = typeof(factor) === "undefined" ? 1.0 : factor; // attempt at default parameters + + var damage = $scope.player.power * factor; + $scope.monster.health -= damage; + + $scope.addActivityLog('You dealt ' + damage + ' damage'); + }; + + $scope.isSomeoneDead = function() { + return ($scope.monster.health <= 0 || $scope.player.currentHealth <= 0); } - $scope.choiceMode = false; - $scope.battleMode = true; - $scope.difficulty = choice; - console.log($scope.problemScope); - }; - - $scope.answer = function answer() { - var inputParsed = parseInt($scope.userInput); - if(inputParsed == $scope.problemScope.correctAnswer) { - alert('Congratulations! Answer is correct.') + + $scope.rollPlayerAction = function() { + + if(rng.rollDice($scope.difficultyChances[$scope.difficulty])) { + // roll succeded + // the player now has a choice between two actions + stateMachine.switchState($scope.battleState, 'postAnswer'); } else { - alert('Sorry, answer is wrong. 0 XP Awarded.'); + // roll failed. just do basic attack + $scope.playerAttack(); + $scope.endOfRound(); } - $scope.battleMode = false; - $scope.choiceMode = true; - }; + }; + $scope.powerAttack = function(choice) { + if(choice === 'critical') { + // player chose to critically hit the monster + $scope.playerAttack(1.5); + $scope.enemyAttack(); + } else { // choice === 'miss' + $scope.playerAttack(); + } - } -]); + $scope.endOfRound(); + }; + + $scope.endOfRound = function() { + if($scope.isSomeoneDead()) { + // we finished, figure out who died + if($scope.player.currentHealth <= 0) { + stateMachine.switchState($scope.state, 'failure'); + $scope.addActivityLog('You lost...'); + } else { // monster is dead + stateMachine.switchState($scope.state, 'success'); + $scope.addActivityLog('You won!'); + } + } else { + $scope.nextProblem(); + } + }; + } + ] +); diff --git a/packages/custom/battle/public/routes/battle.js b/packages/custom/battle/public/routes/battle.js index 24ace43c03..56d13f8716 100755 --- a/packages/custom/battle/public/routes/battle.js +++ b/packages/custom/battle/public/routes/battle.js @@ -2,9 +2,9 @@ angular.module('mean.battle').config(['$stateProvider', function($stateProvider) { - $stateProvider.state('battle example page', { - url: '/battle/example', - templateUrl: 'battle/views/index.html' + $stateProvider.state('problem', { + url: '/battle/problem', + templateUrl: 'battle/views/problem.html' }); } -]); +]); \ No newline at end of file diff --git a/packages/custom/battle/public/services/battle.js b/packages/custom/battle/public/services/battle.js index f3f0335da0..506976ad27 100755 --- a/packages/custom/battle/public/services/battle.js +++ b/packages/custom/battle/public/services/battle.js @@ -7,45 +7,52 @@ angular.module('mean.battle').factory('Battle', [ }; } ]) - .service('MathProblemGenerator', [ function () { + .service('apiFetch', ['$http', function($http) { + var self = this; // I dislike this 'practice' - this.MathProblemGenerate = function MathProblemGenerate(num) { - var self = this; - self.problemScope = {}; - var operatorsAvailable = ['+', '-']; - var numbers = []; - var operators = []; - self.problemScope.correctAnswer = 0; - self.problemScope.problemText = ''; - numbers[0] = -20 + Math.floor((Math.random() * 39) + 1); - numbers[1] = -20 + Math.floor((Math.random() * 39) + 1); + this.apiPost = function(url, data, callback) { + $http.post(url, data). + success(function(data, status) { + callback(data); + }). + error(function(data, status) { + console.log('ERROR: ' + data); + console.log('STATUS: ' + status); + }); + }; - operators[0] = operatorsAvailable[Math.floor((Math.random() * 2) + 1)]; + this.apiGet = function(url, callback) { + $http.get(url). + success(function(data, status) { + callback(data); + }). + error(function(data, status) { + console.log('ERROR: ' + data); + console.log('STATUS: ' + status); + }); + }; - if (num == 2) { - operators[1] = operatorsAvailable[Math.floor((Math.random() * 2) + 1)]; - numbers[2] = -20 + Math.floor((Math.random() * 39) + 1); + this.fetchProblem = function(difficulty, type, callback) { + self.apiGet('/problems/generate/' + type, callback); + }; + this.submitAttempt = function(id, attempt, callback) { + self.apiPost('/problems/attempt', { id: id, answer: attempt}, callback); + }; + }]). + service('rng', [function() { + // random function helpers + this.rollDice = function(requiredThreshold) { + return Math.random() * 100 >= requiredThreshold; + }; + }]) + .service('stateMachine', [function() { + this.switchState = function(dict, state) { + var keys = Object.keys(dict); + for(var i = 0; i < keys.length; i+=1) { + dict[keys[i]] = false; // make them all false } - angular.forEach(numbers, function (numVal, numIdx) { - if (numIdx == 0) { - self.problemScope.correctAnswer = (numVal); - self.problemScope.problemText += (numVal); - } else { - if (operators[numIdx - 1] === '-') { - self.problemScope.correctAnswer += -numVal; - self.problemScope.problemText += ' ' + operators[numIdx - 1] + ' ' + '(' + numVal + ')'; - } else if (operators[numIdx - 1] === '+') { - self.problemScope.correctAnswer += numVal; - self.problemScope.problemText += ' ' + operators[numIdx - 1] + ' ' + numVal; - } - } - }); - console.log('numbers are'); - console.log(numbers); - console.log('operators are'); - console.log(operators); - self.problemScope.problemText += " = ?"; - return this.problemScope; - } - }]); + dict[state] = true; // switch states + }; + }] +); diff --git a/packages/custom/battle/public/views/problem.html b/packages/custom/battle/public/views/problem.html new file mode 100644 index 0000000000..9cabc6c72b --- /dev/null +++ b/packages/custom/battle/public/views/problem.html @@ -0,0 +1,83 @@ +
+

Problems

+
+
+

Choose your difficulty

+ + + +
+
+ +
+
+
+

You are battling a {{difficulty}} monster!

+ +

+ ID: {{problem.id}}
+ Question: {{problem.question}}
+

+

+ Your Health: {{player.currentHealth}} +

+
+ + + + +
+
+ +
+ +

+ Monster's Health: {{monster.health}} +

+
+ +
+
+ + +
+
+ +
+

+ Congratulations! You won and gained {{monster.xp}} experience! + +

+

+ +

+
+ +
+

+ You lost. +

+

+ +

+
+ +
+ + + + + + + + + +
Activity Log
{{value}}
+
+
\ No newline at end of file diff --git a/packages/custom/battle/server/controllers/problems.js b/packages/custom/battle/server/controllers/problems.js index 82220cf380..665feeffbf 100644 --- a/packages/custom/battle/server/controllers/problems.js +++ b/packages/custom/battle/server/controllers/problems.js @@ -35,8 +35,8 @@ exports.generate = function(req, res) { }; exports.attempt = function(req, res) { - var id = req.body.id - var answer = req.body.answer + var id = req.body.id; + var answer = req.body.answer; Problem.findById(id, function(err, problem) { if(err) { diff --git a/packages/custom/battle/server/routes/battle.js b/packages/custom/battle/server/routes/battle.js index 1c1ff8a004..e94170dfbc 100755 --- a/packages/custom/battle/server/routes/battle.js +++ b/packages/custom/battle/server/routes/battle.js @@ -29,5 +29,5 @@ module.exports = function(Battle, app, auth, database) { // TODO: Make sure these have auth code app.get('/problems/generate/:type', problems.generate); - app.post('/problems/attempt', problems.attempt) + app.post('/problems/attempt', problems.attempt); }; diff --git a/scripts/heroku_deploy b/scripts/heroku_deploy new file mode 100755 index 0000000000..f41b19b9ee --- /dev/null +++ b/scripts/heroku_deploy @@ -0,0 +1 @@ +git push staging HEAD:master \ No newline at end of file