├── .bowerrc
├── .gitignore
├── README.md
├── bower.json
├── config.xml
├── gulpfile.js
├── hooks
├── .gitignore
├── README.md
└── after_platform_add
│ └── 010_install_plugins.js
├── package.json
├── readme
├── app_store.png
├── character.png
├── character_green.png
├── character_half_green.png
├── github_promo.png
├── google_play.png
├── icon.png
├── items.png
├── items_green.png
├── quests.png
└── quests_green.png
├── scss
└── ionic.app.scss
└── www
├── app
├── app.js
├── battle
│ ├── battle-controller.js
│ ├── battle.html
│ └── battle.js
├── components
│ ├── auth
│ │ ├── auth-controller.js
│ │ ├── auth-fitbit-service.js
│ │ ├── auth-jawbone-service.js
│ │ ├── auth-login-controller.js
│ │ └── auth.js
│ ├── resource
│ │ ├── resource-service.js
│ │ └── resource.js
│ └── utility
│ │ └── utility.js
├── feedback
│ ├── feedback-controller.js
│ ├── feedback.html
│ └── feedback.js
├── friends
│ ├── friends-add-controller.js
│ ├── friends-add.html
│ ├── friends-controller.js
│ ├── friends.html
│ └── friends.js
├── help
│ ├── help-controller.js
│ ├── help.html
│ └── help.js
├── inventory
│ ├── inventory-controller.js
│ ├── inventory-detail-controller.js
│ ├── inventory-detail.html
│ ├── inventory.html
│ └── inventory.js
├── leaderboard
│ ├── leaderboard-controller.js
│ ├── leaderboard.html
│ └── leaderboard.js
├── main
│ ├── main-controller.js
│ ├── main.html
│ └── main.js
├── menu
│ └── menu.html
├── quest
│ ├── quest-controller.js
│ ├── quest-detail-controller.js
│ ├── quest-detail.html
│ ├── quest-service.js
│ ├── quest.html
│ └── quest.js
├── select
│ ├── select-class-controller.js
│ ├── select-class.html
│ ├── select-username-controller.js
│ ├── select-username.html
│ └── select.js
└── shop
│ ├── shop-controller.js
│ ├── shop-detail-controller.js
│ ├── shop-detail.html
│ ├── shop.html
│ └── shop.js
├── assets
├── css
│ ├── icostyle.css
│ └── style.css
├── fonts
│ ├── icomoon.eot
│ ├── icomoon.svg
│ ├── icomoon.ttf
│ └── icomoon.woff
└── img
│ ├── arrow.png
│ ├── dagger.png
│ ├── fitbit.png
│ ├── fitbitbutton.png
│ ├── ionic.png
│ ├── jawbone_icon.jpg
│ ├── jawbonebutton.png
│ └── questIcon.png
└── index.html
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "www/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | platforms/
3 | plugins/
4 | www/lib
5 | *.DS_store
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
9 |
10 |
11 | FitRPG is a mobile app created by [Amira Anuar](https://github.com/aellawind), [Matt Gutierrez](https://github.com/fatchicken007), and [Conor Fennell](https://github.com/conorfennell) at [Hack Reactor](http://www.hackreactor.com/). FitRPG transforms a Fitbit user's data into a character that can fight friends, battle bosses, and go on quests using the steps, distance, and sleep tracked by the Fitbit. The game logic seeks to motivate users to stay fit and challenge themselves to go that extra mile in order to win a battle or complete a quest.
12 |
13 |
Loading...
' 67 | }); 68 | }, 500); 69 | 70 | var stopLoading = function() { 71 | clearTimeout(loading); 72 | $ionicLoading.hide(); 73 | }; 74 | 75 | var checkLevel = function(user) { 76 | var newLevel = util.calcLevel(user.fitbit.experience + user.attributes.experience); 77 | user.attributes.skillPts = util.calcSkillPoints(user.attributes.skillPts,newLevel,user.attributes.level); 78 | user.attributes.level = newLevel; 79 | }; 80 | 81 | // TEXT PROMPTS 82 | var healthWarning = function() { 83 | var title = 'Unfit for Battle'; 84 | var body = 'You don\'t look so good. You need to recover some of your health before you can battle again.'; 85 | 86 | util.showAlert($ionicPopup, title, body, 'OK', function() { 87 | $ionicListDelegate.closeOptionButtons(); 88 | }); 89 | }; 90 | 91 | var listOfBattles = function() { 92 | // make a copy of the $scope.user.missionsVersus 93 | for (var i=0; i<$scope.user.missionsVersus.length; i++) { 94 | battles[i] = {}; 95 | for (var key in $scope.user.missionsVersus[i]) { 96 | battles[i][key] = $scope.user.missionsVersus[i][key]; 97 | } 98 | } 99 | 100 | if ($scope.user.friends.length === 0) { 101 | stopLoading(); 102 | }; 103 | 104 | var getFriendData = function(id) { 105 | User.get({id: id}, function(user){ 106 | if (user._id) { 107 | $scope.friends.push(user); 108 | var friend = $scope.friends[$scope.friends.length-1]; 109 | for (var j=0; jLevel: {{friend.attributes.level}} Status: {{friend.battleData.status}}
40 |Wins
54 |Losses
58 |Level {{battle.attributes.level}} {{battle.character}}
68 |Level {{battle.attributes.level}} {{battle.character}}
79 |Level {{mission.level}}, 97 | Difficulty: 98 | 99 | 100 | 101 | 102 | 103 |
104 |loading...
', 14 | animation: 'fade-in', 15 | showBackdrop: false, 16 | maxWidth: 200, 17 | showDelay: 100 18 | }); 19 | 20 | User.get({id : localStorageService.get('userId') }, function(user) { 21 | if (user.username === undefined) { 22 | $ionicLoading.hide(); 23 | $state.transitionTo('username'); 24 | $scope.Authenticated = true; 25 | } else { 26 | $ionicLoading.hide(); 27 | $state.transitionTo('app.character'); 28 | $scope.Authenticated = true; 29 | } 30 | }); 31 | } else { 32 | $scope.needsAuthentication = true; 33 | } 34 | 35 | $scope.logout = function () { 36 | localStorageService.clearAll(); 37 | location.href=location.pathname; 38 | }; 39 | 40 | }); 41 | 42 | var isTokenInDate = function(localStorageService){ 43 | var tokenDate = new Date(JSON.parse(localStorageService.get('token-date'))); 44 | if (tokenDate) { 45 | var today = new Date(); 46 | var timeDiff = Math.abs(today.getTime() - tokenDate.getTime()); 47 | var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)); 48 | if(diffDays > 10) { 49 | return false; 50 | } 51 | } else { 52 | return false; 53 | } 54 | return true; 55 | }; 56 | -------------------------------------------------------------------------------- /www/app/components/auth/auth-fitbit-service.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.authentication.services') 2 | 3 | .factory('FitbitLoginService', function ($window, $state, $ionicLoading, $location, localStorageService, $location) { 4 | var url = 'http://fitrpg.azurewebsites.net/fitbit/auth'; 5 | var usernameUrl = 'http://fitrpg.azurewebsites.net/fitbit/getUsername'; 6 | var loginWindow, token, hasToken, userId, hasUserId; 7 | 8 | return { 9 | login: function () { 10 | loginWindow = $window.open(url, '_blank', 'location=no,toolbar=no,hidden=yes'); 11 | $ionicLoading.show({ 12 | template: 'Contacting Fitbit...
', 13 | animation: 'fade-in', 14 | showBackdrop: false, 15 | maxWidth: 200, 16 | showDelay: 200 17 | }); 18 | 19 | loginWindow.addEventListener("loadstop", function(e) { 20 | $ionicLoading.hide(); 21 | loginWindow.show(); 22 | }); 23 | 24 | loginWindow.addEventListener('loadstart', function (event) { 25 | hasToken = event.url.indexOf('?oauth_token='); 26 | hasUserId = event.url.indexOf('&userId='); 27 | if (hasToken > -1 && hasUserId > -1) { 28 | token = event.url.match('oauth_token=(.*)&userId')[1]; 29 | userId = event.url.match('&userId=(.*)')[1]; 30 | localStorageService.set('fitbit-token', token); 31 | localStorageService.set('token-date', JSON.stringify(new Date())); 32 | localStorageService.set('userId', userId); 33 | loginWindow.close(); 34 | location.href=location.pathname; 35 | } 36 | }); 37 | }, 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /www/app/components/auth/auth-jawbone-service.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.authentication.services') 2 | 3 | .factory('JawboneLoginService', function ($window, $state, localStorageService) { 4 | var url = 'https://fitrpg.azurewebsites.net/jawbone/auth'; 5 | var loginWindow, token, hasToken, userId, hasUserId; 6 | 7 | return { 8 | login: function () { 9 | loginWindow = $window.open(url, '_blank', 'location=no,toolbar=no,hidden=yes'); 10 | loginWindow.addEventListener('loadstart', function (event) { 11 | hasToken = event.url.indexOf('?token='); 12 | hasUserId = event.url.indexOf('&userid='); 13 | if (hasToken > -1) { 14 | token = event.url.substring(hasToken + 7); 15 | userId = event.url.substring(hasUserId + 8) 16 | localStorageService.set('jawbone-token', token); 17 | localStorageService.set('userId', userId); 18 | location.href=location.pathname; 19 | loginWindow.close(); 20 | } 21 | }); 22 | }, 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /www/app/components/auth/auth-login-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.authentication.controllers') 2 | 3 | .controller('LoginController', function ($scope, $state, FitbitLoginService, JawboneLoginService) { 4 | 5 | $scope.fitbitlogin = FitbitLoginService.login; 6 | $scope.jawbonelogin = JawboneLoginService.login; 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /www/app/components/auth/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('mobile.authentication', [ 4 | 5 | 'mobile.authentication.controllers', 6 | 'mobile.authentication.services' 7 | ]); 8 | 9 | angular.module('mobile.authentication.controllers', ['LocalStorageModule', 'ionic']); 10 | angular.module('mobile.authentication.services', ['LocalStorageModule', 'ionic']); 11 | -------------------------------------------------------------------------------- /www/app/components/resource/resource-service.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.resource.services') 2 | 3 | .constant('SERVER_URL', 'http://fitrpg.azurewebsites.net') 4 | 5 | .factory('authHttpInterceptor', ['localStorageService', function(localStorageService) { 6 | return { 7 | 'request': function(config) { 8 | config.headers = config.headers || {}; 9 | // do some API key setting 10 | // Add json web token 11 | if(localStorageService.get('fitbit-token')){ 12 | config.headers.Authorization = 'Bearer ' + localStorageService.get('fitbit-token'); 13 | } 14 | return config; 15 | } 16 | }; 17 | }]) 18 | 19 | .config(['$httpProvider', function($httpProvider) { 20 | $httpProvider.interceptors.push('authHttpInterceptor'); 21 | }]) 22 | 23 | .factory('CheckUsername', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 24 | return $resource(SERVER_URL + '/api/users/check/:username', {username: '@username'}); 25 | }]) 26 | 27 | .factory('Refresh', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 28 | return $resource(SERVER_URL + '/fitbit/refresh/:id', {id: '@id'}); 29 | }]) 30 | 31 | .factory('Settings', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 32 | return $resource(SERVER_URL + '/settings/:id', {id: '@id'}); 33 | }]) 34 | 35 | .factory('User', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 36 | return $resource(SERVER_URL + '/api/users/:id', {id : '@id'}, { 37 | update: { method: 'PUT' } 38 | }); 39 | }]) 40 | 41 | // get fitbit data based off of a date range 42 | .factory('DatesData', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 43 | return $resource(SERVER_URL + '/fitbit/daterange/:id/:type/:activity/:startDate/:endDate', 44 | {id: '@id', type: '@type', activity: '@activity', startDate: '@startDate', endDate: '@endDate'} ); 45 | }]) 46 | 47 | // get fitbit data based off of a time range 48 | .factory('NewTimesData', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 49 | return $resource(SERVER_URL + '/fitbit/new/timerange/:id/:activity/:startDate/:startTime/:endTime', 50 | {id: '@id', activity: '@activity', startDate: '@startDate', startTime: '@startTime', endTime: '@endTime'} ); 51 | }]) 52 | 53 | // OLD RESOURCE WE NEVER USE BECAUSE WE CHANGE IT--LEAVING IT HERE TO REMEMBER FOR BACKWARDS COMPATIABILITY 54 | .factory('TimesData', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 55 | return $resource(SERVER_URL + '/fitbit/timerange/:id/:activity/:startDate/:endDate/:startTime/:endTime', 56 | {id: '@id', activity: '@activity', startDate: '@startDate', endDate: '@endDate', startTime: '@startTime', endTime: '@endTime'} ); 57 | }]) 58 | 59 | 60 | .factory('Shop', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 61 | return $resource(SERVER_URL + '/api/items/:id', {id : '@id'}); 62 | }]) 63 | 64 | .factory('Battle', ['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 65 | return $resource(SERVER_URL + '/api/battles/:id', {id : '@id'}); 66 | }]) 67 | 68 | .factory('SoloMissions',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 69 | return $resource(SERVER_URL + '/api/solos/:id', {id : '@id'}); 70 | }]) 71 | 72 | .factory('Quests',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 73 | return $resource(SERVER_URL + '/api/quests/:id', {id : '@id'}); 74 | }]) 75 | 76 | .factory('VersusMissions',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 77 | return $resource(SERVER_URL + '/api/groups/:id', {id : '@id'}); 78 | }]) 79 | 80 | .factory('RandomUser',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 81 | return $resource(SERVER_URL + '/api/users/random/:id/:level', 82 | {id : '@id', level: '@level'}); 83 | }]) 84 | 85 | .factory('UserSearch',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 86 | return $resource(SERVER_URL + '/api/users/search/:username', {username : '@username'}); 87 | }]) 88 | 89 | .factory('Leaderboard',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 90 | return $resource(SERVER_URL + '/api/users/leaderboard'); 91 | }]) 92 | 93 | .factory('Feedback',['$resource', 'SERVER_URL', function($resource, SERVER_URL) { 94 | return $resource(SERVER_URL + '/feedback/:id', {id : '@id'}); 95 | }]); 96 | -------------------------------------------------------------------------------- /www/app/components/resource/resource.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('mobile.resource', [ 4 | 5 | 'mobile.resource.services' 6 | ]); 7 | 8 | angular.module('mobile.resource.services', ['ngResource']); -------------------------------------------------------------------------------- /www/app/components/utility/utility.js: -------------------------------------------------------------------------------- 1 | var util = { 2 | vitalityToHp: function(vitality, charClass){ 3 | var hp; 4 | // change character classes 5 | if (charClass === 'strength' || charClass === 'endurance') { 6 | hp = vitality * 10; 7 | } else if (charClass === 'dexterity') { 8 | hp = vitality * 12; 9 | } else if (charClass === 'vitality') { 10 | hp = vitality * 15; 11 | } else { 12 | hp = vitality * 10; 13 | } 14 | 15 | return hp; 16 | }, 17 | 18 | attack: function(first,second,count) { 19 | first.attackBonus = first.attackBonus || 1; 20 | if (Math.floor(count%(100/(first.endurance/20))) === 0) { 21 | if (Math.random() < 1/(1+second.dexterity/25)) { 22 | var strength = first.strength; 23 | if (Math.random() < 0.05) { 24 | strength *= 2; 25 | } 26 | // console.log(strength); 27 | return Math.floor(second.HP - strength*first.attackBonus); 28 | } 29 | } 30 | return second.HP; 31 | }, 32 | 33 | battleTurns: function(player1Attr, player2Attr) { 34 | var firstAttack = Math.random(); 35 | var count = 0; 36 | var characterBonus = function(player) { 37 | if (player.characterClass === 'strength') { 38 | player.strength *= 1.1; 39 | } else if (player.characterClass === 'dexterity') { 40 | player.dexterity *= 1.4; 41 | } else if (player.characterClass === 'endurance') { 42 | player.endurance *= 1.1; 43 | } else if (player.characterClass === 'vitality') { 44 | player.dexterity *= 1.2; 45 | } 46 | }; 47 | 48 | characterBonus(player1Attr); 49 | characterBonus(player2Attr); 50 | 51 | while (player1Attr.HP > 0 && player2Attr.HP > 0) { 52 | count++; 53 | if (firstAttack >= 0.5) { 54 | player2Attr.HP = this.attack(player1Attr,player2Attr,count); 55 | if (player2Attr.HP > 0) { 56 | player1Attr.HP = this.attack(player2Attr,player1Attr,count); 57 | } else { 58 | break; 59 | } 60 | } else { 61 | player1Attr.HP = this.attack(player2Attr,player1Attr,count); 62 | if (player1Attr.HP > 0) { 63 | player2Attr.HP = this.attack(player1Attr,player2Attr,count); 64 | } else { 65 | break; 66 | } 67 | } 68 | } 69 | }, 70 | 71 | playerAttr: function(player) { 72 | return { 73 | strength: player.attributes.strength + player.fitbit.strength, 74 | endurance: player.attributes.endurance + player.fitbit.endurance, 75 | dexterity: player.attributes.dexterity + player.fitbit.dexterity, 76 | HP: player.attributes.HP, 77 | attackBonus: player.fitbit.attackBonus, 78 | }; 79 | }, 80 | 81 | battle: function(player1, player2){ 82 | var player1Attr = this.playerAttr(player1); 83 | var player2Attr = this.playerAttr(player2); 84 | 85 | 86 | this.battleTurns(player1Attr,player2Attr); 87 | console.log(player1Attr.HP, player2Attr.HP); 88 | 89 | if (player1Attr.HP > player2Attr.HP) { 90 | return {result:'player 1', hp: player1Attr.HP}; 91 | } else { 92 | return {result:'player 2', hp: player2Attr.HP}; 93 | } 94 | 95 | }, 96 | 97 | bossBattle: function(player,boss) { 98 | var player1 = this.playerAttr(player); 99 | var count = 0; 100 | if (boss.difficulty !== null) { 101 | boss.HP = boss.vitality*5*boss.difficulty; 102 | } else { 103 | boss.HP = boss.vitality*10; 104 | } 105 | 106 | this.battleTurns(player1,boss); 107 | console.log(player1.HP,boss.HP); 108 | 109 | if (player1.HP > boss.HP) { 110 | return {result:'player', hp: player1.HP}; 111 | } else { 112 | return {result:'boss', hp: 0}; 113 | } 114 | }, 115 | 116 | capitalize: function(string) { 117 | return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase(); 118 | }, 119 | 120 | showAlert: function(controller, title, body, button, callback) { 121 | var alertPopup = controller.alert({ 122 | title: title, 123 | template: body, 124 | okText: button 125 | }); 126 | alertPopup.then(function(res) { 127 | callback(); 128 | }); 129 | }, 130 | 131 | showPrompt: function(controller,title,body,okText,cancelText,callbackTrue,callbackFalse) { 132 | var confirmPopup = controller.confirm({ 133 | title: title, 134 | template: body, 135 | okText: okText, 136 | cancelText : cancelText 137 | }); 138 | confirmPopup.then(function(res) { 139 | if(res) { 140 | callbackTrue(); 141 | } else if (callbackFalse) { 142 | callbackFalse(); 143 | } 144 | }); 145 | }, 146 | 147 | showPopup: function(controller,title,body,btn1,btn2,cancelBtn,callbackTrue,callbackFalse) { 148 | var myPopup = controller.show({ 149 | title: title, 150 | template: body, 151 | buttons: [ 152 | {text: cancelBtn}, 153 | {text: btn1, 154 | onTap: function(e) { 155 | return 'btn1'; 156 | } 157 | }, 158 | {text: btn2, 159 | onTap: function(e) { 160 | return 'btn2'; 161 | } 162 | } 163 | ] 164 | }); 165 | myPopup.then(function(res) { 166 | if(res === 'btn1') { 167 | callbackFalse(); 168 | } else if (res === 'btn2') { 169 | callbackTrue(); 170 | } 171 | }); 172 | }, 173 | 174 | currentLevelExp: function(lvl,exp) { 175 | return exp - (100*Math.pow(lvl-1,3) + 360*Math.pow(lvl-1,2) + 3500*(lvl-1)); 176 | }, 177 | 178 | nextLevelExp: function(lvl) { 179 | return (100*Math.pow(lvl,3) + 360*Math.pow(lvl,2) + 3500*lvl) - (100*Math.pow(lvl-1,3) + 360*Math.pow(lvl-1,2) + 3500*(lvl-1)); 180 | }, 181 | 182 | levelExp: function(lvl) { 183 | return 100*Math.pow(lvl-1,3) + 360*Math.pow(lvl-1,2) + 3500*(lvl-1); 184 | }, 185 | 186 | calcLevel: function(experience, currLvl) { 187 | var level = currLvl || 1; 188 | var total = experience; 189 | var expToLevel = function(lvl) { 190 | return 100*Math.pow(lvl,3) + 360*Math.pow(lvl,2) + 3500*lvl; 191 | }; 192 | while (expToLevel(level) <= total) { 193 | level++; 194 | } 195 | return level; 196 | }, 197 | 198 | calcSkillPoints: function(currSkillPts, lvl, currLvl) { 199 | return currSkillPts + (lvl-currLvl)*5; 200 | }, 201 | 202 | }; 203 | 204 | // Necessary to format to the way Fitbit wants our dates 205 | Date.prototype.yyyymmdd = function() { 206 | var yyyy = this.getFullYear().toString(); 207 | var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based 208 | var dd = this.getDate().toString(); 209 | return yyyy + '-' + (mm[1]?mm:'0'+mm[0]) + '-' + (dd[1]?dd:'0'+dd[0]); 210 | }; 211 | 212 | // Useful to add days and hours to the start time/day 213 | Date.prototype.addDays = function(days,hours) { 214 | var date = new Date(this.valueOf()); 215 | date.setDate(date.getDate() + days); 216 | if(hours) { 217 | date.setHours(this.getHours()+hours); 218 | } 219 | return date; 220 | }; -------------------------------------------------------------------------------- /www/app/feedback/feedback-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.feedback.controllers') 2 | 3 | .controller('FeedbackCtrl', function($scope, $state, $ionicPopup, User, Feedback, localStorageService) { 4 | $scope.feedback = { 5 | email: '', 6 | message: '', 7 | }; 8 | 9 | var navTo = function(location) { 10 | $state.go('app.' + location); 11 | }; 12 | 13 | 14 | $scope.submit = function(feedback) { 15 | if (!localStorageService.get('rate')) { 16 | localStorageService.set('rate',true); 17 | $scope.user.attributes.gold += 500; 18 | User.update($scope.user); 19 | } 20 | 21 | Feedback.save({email: feedback.email, message: feedback.message, createdAt: new Date()}); 22 | 23 | var title = 'Feedback Received'; 24 | var body = 'We are constantly implementing new features and improving this app. Your feedback will help us greatly!'; 25 | 26 | util.showAlert($ionicPopup,title,body,'OK',function(){ 27 | navTo('character'); 28 | }); 29 | 30 | }; 31 | }) 32 | -------------------------------------------------------------------------------- /www/app/feedback/feedback.html: -------------------------------------------------------------------------------- 1 |Level {{friend.attributes.level}} {{friend.character}}
32 |Loading...
' 21 | }); 22 | }, 500); 23 | 24 | var stopLoading = function() { 25 | clearTimeout(loading); 26 | $ionicLoading.hide(); 27 | }; 28 | 29 | if ($scope.user.friends.length === 0) { 30 | stopLoading(); 31 | } 32 | 33 | for (var i=0; i<$scope.user.friends.length; i++) { 34 | var friend = $scope.user.friends[i]; 35 | User.get({id: friend}, function(user){ 36 | if (user._id) { 37 | $scope.friends.push(user); 38 | $scope.hasFriends = true; 39 | } 40 | stopLoading(); 41 | }); 42 | } 43 | 44 | if ($scope.user.friendRequests) { 45 | for (var i=0; i<$scope.user.friendRequests.length; i++) { 46 | var friendRequest = $scope.user.friendRequests[i]; 47 | var getFriend = function(request) { 48 | User.get({id: friendRequest.id}, function(friend) { 49 | friend.requestStatus = request.status; 50 | $scope.friendRequests.push(friend); 51 | }); 52 | }; 53 | getFriend(friendRequest); 54 | } 55 | } 56 | 57 | var removeFriendRequest = function(user, friendId) { 58 | var index; 59 | for (var i=0; iLevel {{friend.attributes.level}} {{friend.character}}
29 | 30 |Level {{friend.attributes.level}} {{friend.character}}
42 |Level {{friend.attributes.level}} {{friend.character}}
54 |{{ answer.answer }}
37 |Loading...
' 19 | }); 20 | }, 500); 21 | 22 | Shop.query( function (storeItems) { 23 | for (var i=0; iType: {{inventoryItem.type}}
10 |
14 | Strength
15 | Vitality
16 | Endurance
17 | Dexterity
18 | Size
19 | Sell Price
20 |
22 |
23 | {{ user.attributes.strength }}
24 | {{ user.attributes.strength + inventoryItem.strength }}
25 |
26 | {{ user.attributes.vitality }}
27 | {{ user.attributes.vitality + inventoryItem.vitality }}
28 |
29 | {{ user.attributes.endurance }}
30 | {{ user.attributes.endurance + inventoryItem.endurance }}
31 |
32 | {{ user.attributes.dexterity }}
33 | {{ user.attributes.dexterity + inventoryItem.dexterity }}
34 |
35 | {{ inventoryItem.sizeText }}
36 |
37 | {{ inventoryItem.sellPrice }} Gold
38 |
39 |
{{ inventoryItem.description }}
Quantity: {{ inventoryItem.quantity }}
Sell Price
47 |{{ inventoryItem.sellPrice }} Gold
48 |{{item.equipped}}
24 | 25 | 26 | No Weapons Available 27 |{{item.equipped}}
37 | 38 | 39 | No Armor Available 40 |{{item.equipped}}
51 | 52 | 53 | No Accessories Available 54 |Loading...
' 7 | }); 8 | }, 500); 9 | 10 | $scope.allTab = 'button-tab-active'; 11 | $scope.all = function() { 12 | $scope.allTab = 'button-tab-active'; 13 | $scope.friendsTab = ''; 14 | $scope.leaderboard = []; 15 | Leaderboard.query(function(users) { 16 | $scope.leaderboard = users; 17 | clearTimeout(loading); 18 | $ionicLoading.hide(); 19 | }) 20 | }; 21 | 22 | $scope.friends = function() { 23 | $scope.allTab = ''; 24 | $scope.friendsTab = 'button-tab-active'; 25 | $scope.leaderboard = []; 26 | $scope.leaderboard.push($scope.user); 27 | for(var i = 0; i < $scope.user.friends.length; i++){ 28 | User.get({id : $scope.user.friends[i]}, function(user) { 29 | if (user['_id']) { 30 | $scope.leaderboard.push(user); 31 | } 32 | }) 33 | } 34 | }; 35 | 36 | $scope.all(); 37 | }); 38 | -------------------------------------------------------------------------------- /www/app/leaderboard/leaderboard.html: -------------------------------------------------------------------------------- 1 |Level {{leader.attributes.level}} {{leader.character}}
19 |Loading...
' 25 | }); 26 | }, 500); 27 | 28 | $scope.calculatedData = {}; 29 | $scope.alertCount = 0; 30 | $scope.showAlert = false; 31 | 32 | var device = { 33 | isApple: ionic.Platform.isIOS(), 34 | isGoogle: ionic.Platform.isAndroid(), 35 | }; 36 | 37 | var addAlert = function(status, name) { 38 | name = name || ''; 39 | var type, msg; 40 | if (status === 'loss') { 41 | type = 'danger'; 42 | msg = 'Looks like you need to work out more. You lost to ' + name + '.'; 43 | } else if (status === 'win') { 44 | type = 'success'; 45 | msg = 'You beat ' + name + '. You gained experience and gold.' 46 | } else if (status === 'request') { 47 | type = ''; 48 | msg = 'Someone wants to battle you.'; 49 | } 50 | $scope.alertCount++; 51 | $scope.alerts.push({type: type, msg: msg}); 52 | }; 53 | 54 | var addLevelUpAlert = function() { 55 | var type, msg; 56 | type = 'success'; 57 | msg = 'You leveled up! You\'ve gained skill points to increase your attributes.'; 58 | $scope.alertCount++; 59 | $scope.levelUpAlerts.push({type: type, msg: msg}); 60 | }; 61 | 62 | var addFriendRequestAlert = function() { 63 | var type, msg; 64 | type = 'success'; 65 | msg = 'You have a new friend request. Click here to view the requests.'; 66 | $scope.alertCount++; 67 | $scope.friendRequestAlerts.push({type: type, msg: msg}); 68 | }; 69 | 70 | var addQuestAlert = function(quest) { 71 | var type, msg; 72 | if (quest.status === 'success') { 73 | type = 'success'; 74 | msg = 'You completed your quest to ' + quest.shortDesc.toLowerCase() + ' You won ' + quest.gold + " pieces!"; 75 | } else if (quest.status === 'fail') { 76 | type = 'danger'; 77 | msg = 'Sorry, you didn\'t finish your quest to ' + quest.shortDesc.toLowerCase() + ' You lost gold. Try again in a few days.' 78 | } 79 | $scope.alertCount++; 80 | $scope.questAlerts.push({type: type, msg: msg}); 81 | }; 82 | 83 | $scope.displayAlerts = function() { 84 | $scope.alertCount = 0; 85 | $scope.showAlert = true; 86 | } 87 | 88 | $scope.closeAlert = function(index) { 89 | $scope.alerts.splice(index, 1); 90 | }; 91 | 92 | $scope.closeLevelUpAlert = function(index) { 93 | $scope.levelUpAlerts.splice(index, 1); 94 | }; 95 | 96 | $scope.closeFriendRequestAlert = function(index) { 97 | $scope.friendRequestAlerts.splice(index, 1); 98 | }; 99 | 100 | $scope.closeQuestAlert = function(index) { 101 | $scope.questAlerts.splice(index, 1); 102 | }; 103 | 104 | var calculateData = function(user) { 105 | $scope.calculatedData.currentXp = Math.floor(util.currentLevelExp(user.attributes.level, user.fitbit.experience + user.attributes.experience)); 106 | $scope.calculatedData.requiredXp = util.nextLevelExp(user.attributes.level); 107 | $scope.calculatedData.strength = user.attributes.strength + user.fitbit.strength; 108 | $scope.calculatedData.vitality = user.attributes.vitality + user.fitbit.vitality; 109 | $scope.calculatedData.dexterity = user.attributes.dexterity + user.fitbit.dexterity; 110 | $scope.calculatedData.endurance = user.attributes.endurance + user.fitbit.endurance; 111 | $scope.calculatedData.maxHp = util.vitalityToHp($scope.calculatedData.vitality,$scope.user.characterClass); //change to $scope.user.characterClass 112 | user.attributes.HP += user.fitbit.HPRecov; 113 | user.fitbit.HPRecov = 0; 114 | if (user.attributes.HP > $scope.calculatedData.maxHp) { 115 | user.attributes.HP = $scope.calculatedData.maxHp; 116 | } 117 | if (user.attributes.gold < 0) { 118 | user.attributes.gold = 0; 119 | } 120 | }; 121 | 122 | var alertBattleStatus = function() { 123 | $scope.alerts = []; 124 | var listOfIndices = []; 125 | var alertWin = false; 126 | var alertLoss = false; 127 | var alertRequest = false; 128 | for (var i=0; i<$rootScope.user.missionsVersus.length; i++) { 129 | var alertMission = function(index){ 130 | var mission = $rootScope.user.missionsVersus[index]; 131 | if (mission.type === 'battle') { 132 | if (mission.status === 'win' || mission.status === 'loss') { 133 | User.get({id: mission.enemy}, function(enemy){ 134 | addAlert(mission.status,enemy.profile.displayName); 135 | }); 136 | listOfIndices.push(index); 137 | } else if (mission.status === 'request' && !alertRequest) { 138 | alertRequest = true; 139 | addAlert(mission.status); 140 | } 141 | } 142 | }; 143 | alertMission(i); 144 | } 145 | 146 | var removeMission = function(index,count) { 147 | if (count < listOfIndices.length) { 148 | $rootScope.user.missionsVersus.splice(index-count,1); 149 | removeMission(listOfIndices[count+1],count+1); 150 | } 151 | }; 152 | 153 | if (listOfIndices.length > 0) { 154 | removeMission(listOfIndices[0],0); 155 | } 156 | 157 | }; 158 | 159 | var alertLevelUpStatus = function() { 160 | $scope.levelUpAlerts = []; 161 | var userLevel = localStorageService.get('level'); 162 | var currentLevel = $rootScope.user.attributes.level; 163 | if (!userLevel) { 164 | userLevel = localStorageService.set('level',1); 165 | } 166 | if (userLevel < currentLevel) { 167 | localStorageService.set('level', currentLevel); 168 | addLevelUpAlert(); 169 | } 170 | }; 171 | 172 | var alertFriendRequestStatus = function() { 173 | $scope.friendRequestAlerts = []; 174 | var alertRequest = false; 175 | if ($rootScope.user.friendRequests) { 176 | for (var i=0; i<$rootScope.user.friendRequests.length; i++) { 177 | var request = $rootScope.user.friendRequests[i]; 178 | if (request.status === 'request' && !alertRequest) { 179 | alertRequest = true; 180 | addFriendRequestAlert(); 181 | } 182 | } 183 | } 184 | }; 185 | 186 | var alertQuestStatus = function() { 187 | $scope.questAlerts = []; 188 | var today = parseInt(Date.parse(new Date())); 189 | for (var j =0; j< $rootScope.user.quests.length; j++) { 190 | (function(i) { 191 | var quest = $rootScope.user.quests[i]; 192 | if (quest.status === 'active') { 193 | var completeDate = parseInt(Date.parse(quest.completionTime)); 194 | if (today >= completeDate) { 195 | if (quest.numDays < 1) { 196 | TimesData.get(quest.getObj, function(result) { 197 | var total = result.total; 198 | if (total >= quest.winGoal) { 199 | $rootScope.user.quests[i].status = 'success'; 200 | $rootScope.user.attributes.gold += quest.gold; 201 | } else { 202 | $rootScope.user.quests[i].status = 'fail'; 203 | $rootScope.user.attributes.gold = $rootScope.user.attributes.gold - Math.floor(quest.gold/3); 204 | } 205 | User.update($rootScope.user); 206 | addQuestAlert(quest); 207 | }); 208 | } else if (quest.numDays > 0 ) { 209 | DatesData.get(quest.getObj, function(result) { 210 | var total = result.total; 211 | if (total >= quest.winGoal) { 212 | $rootScope.user.quests[i].status = 'success'; 213 | $rootScope.user.attributes.gold += quest.gold; 214 | } else { 215 | $rootScope.user.quests[i].status = 'fail'; 216 | $rootScope.user.attributes.gold = $rootScope.user.attributes.gold - Math.floor(quest.gold/3); 217 | } 218 | User.update($rootScope.user); 219 | addQuestAlert(quest); 220 | }); 221 | } 222 | } 223 | } 224 | }(j)); 225 | } 226 | }; 227 | 228 | var setWeapons = function() { 229 | var defaultWeapon = function(location) { 230 | $rootScope.user.equipped[location] = {}; 231 | $rootScope.user.equipped[location].name = ''; 232 | $rootScope.user.equipped[location].inventoryId = null; 233 | }; 234 | 235 | if (!$rootScope.user.equipped) { 236 | $rootScope.user.equipped = {}; 237 | defaultWeapon('weapon1'); 238 | defaultWeapon('weapon2'); 239 | defaultWeapon('armor'); 240 | defaultWeapon('accessory1'); 241 | defaultWeapon('accessory2'); 242 | } 243 | } 244 | 245 | var localUserId = localStorageService.get('userId'); //'2Q2TVT'; // 246 | 247 | var checkNewData = function() { 248 | User.get({id : localUserId}, function (user) { 249 | $rootScope.user = user; 250 | setWeapons(); 251 | getSettings(); 252 | if (user.needsUpdate === true) { 253 | Refresh.get({id:localUserId}, function() { 254 | User.get({id:localUserId}, function(user) { 255 | console.log('needed a new update'); 256 | $rootScope.user = user; 257 | calculateData($rootScope.user); 258 | alertBattleStatus(); 259 | alertLevelUpStatus(); 260 | alertFriendRequestStatus(); 261 | alertQuestStatus(); 262 | $rootScope.user.needsUpdate = false; 263 | User.update($rootScope.user); 264 | clearTimeout(loading); 265 | $ionicLoading.hide(); 266 | }); 267 | }); 268 | } else { 269 | console.log('did not need a new update'); 270 | alertBattleStatus(); 271 | calculateData($rootScope.user); 272 | User.update($rootScope.user); 273 | clearTimeout(loading); 274 | $ionicLoading.hide(); 275 | } 276 | }); 277 | } 278 | 279 | var refresh = function() { 280 | console.log('refreshing'); 281 | Refresh.get({id: localUserId}, function() { // this will tell fitbit to get new data 282 | User.get({id : localUserId}, function (user) { // this will retrieve that new data 283 | $rootScope.user = user; 284 | calculateData($rootScope.user); 285 | $scope.alertCount = 0; 286 | $scope.showAlert = false; 287 | alertBattleStatus(); 288 | alertLevelUpStatus(); 289 | alertFriendRequestStatus(); 290 | User.update($rootScope.user); 291 | $scope.$broadcast('scroll.refreshComplete'); 292 | }); 293 | }); 294 | getSettings(); 295 | }; 296 | 297 | $scope.refresh = refresh; 298 | 299 | checkNewData(); 300 | document.addEventListener("resume", checkNewData, false); //whenever we resume the app, retrieve new data if there is any 301 | 302 | $scope.hasSkillPoints = function() { 303 | if ($rootScope.user && $rootScope.user.attributes.skillPts > 0) { 304 | return true; 305 | } else { 306 | return false; 307 | } 308 | }; 309 | 310 | $scope.applyAttributes = function(attr) { 311 | if ($rootScope.user.attributes.skillPts > 0) { 312 | $rootScope.user.attributes[attr]++; 313 | $rootScope.user.attributes.skillPts--; 314 | if (attr === 'vitality') { 315 | // change char class from warrior to user class 316 | // $rootScope.user.attributes.hp = util.vitalityToHp($rootScope.user.attributes.vitality,'warrior'); 317 | $scope.calculatedData.maxHp = util.vitalityToHp($rootScope.user.attributes.vitality,'warrior'); 318 | } 319 | calculateData($rootScope.user); 320 | // update database 321 | User.update($rootScope.user); 322 | } 323 | }; 324 | 325 | $scope.isEquipped = function(slot) { 326 | var user = $rootScope.user; 327 | if (user && user.equipped[slot].inventoryId !== null) { 328 | return true; 329 | } else { 330 | return false; 331 | } 332 | }; 333 | 334 | $scope.unequip = function(slot){ 335 | var inventory = $rootScope.user.inventory; 336 | var inventoryId = $rootScope.user.equipped[slot].inventoryId; 337 | 338 | var empty = function(location) { 339 | $rootScope.user.equipped[location].name = ''; 340 | $rootScope.user.equipped[location].inventoryId = null; 341 | }; 342 | 343 | if (slot === 'weapon1' || slot === 'weapon2') { 344 | if ($rootScope.user.equipped['weapon1'].inventoryId === $rootScope.user.equipped['weapon2'].inventoryId) { 345 | empty('weapon1'); 346 | empty('weapon2'); 347 | } 348 | } 349 | 350 | empty(slot); 351 | 352 | var storeId; 353 | for (var i=0; iLevel: {{user.attributes.level}} {{user.character}}
36 |50 | XP 51 | {{calculatedData.currentXp}} / {{calculatedData.requiredXp}} 52 |
53 |60 | HP 61 | {{user.attributes.HP}} / {{calculatedData.maxHp}} 62 |
63 |Strength
72 |Vitality
77 |Endurance
82 |Dexterity
87 |{{user.equipped.weapon1.name}}
123 |{{user.equipped.weapon2.name}}
126 |{{user.equipped.armor.name}}
133 |{{user.equipped.accessory1.name}}
140 |{{user.equipped.accessory2.name}}
143 |Loading...
' 10 | }); 11 | }, 500); 12 | 13 | $scope.allTab = 'button-tab-active'; 14 | $scope.all = function() { 15 | $scope.isAll = true; 16 | $scope.isActive = false; 17 | $scope.isComplete = false; 18 | $scope.quests = []; 19 | $scope.availableQuests = []; 20 | $scope.allTab = 'button-tab-active'; 21 | $scope.activeTab = ''; 22 | $scope.completedTab = ''; 23 | $ionicScrollDelegate.scrollTop(); 24 | 25 | // Create an array of ids of quests the user is currently doing 26 | var currentQuests = []; 27 | for (var i = 0; i < $scope.user.quests.length; i++ ) { 28 | currentQuests.push($scope.user.quests[i].questId); 29 | } 30 | // Compare all quests against this array and only display them if they're not on it 31 | Quests.query(function(quests){ 32 | $scope.quests = quests; 33 | for (var i =0; i<$scope.quests.length;i++) { 34 | if (currentQuests.indexOf($scope.quests[i]._id) < 0) { 35 | $scope.availableQuests.push($scope.quests[i]); 36 | } 37 | } 38 | clearTimeout(loading); 39 | $ionicLoading.hide(); 40 | }); 41 | }; 42 | 43 | // Show all of the quests that are active 44 | $scope.active = function() { 45 | $scope.isAll = false; 46 | $scope.isActive = true; 47 | $scope.isComplete = false; 48 | $scope.allTab = ''; 49 | $scope.activeTab = 'button-tab-active'; 50 | $scope.completedTab = ''; 51 | $ionicScrollDelegate.scrollTop(); 52 | 53 | var today = new Date(); 54 | $scope.quests = []; 55 | for (var i =0; i< $scope.user.quests.length; i++) { 56 | if($scope.user.quests[i].status === 'active') { 57 | (function(i) { 58 | Quests.get({id : $scope.user.quests[i].questId}, function(q) { 59 | $scope.quests.push(q); 60 | }); 61 | }(i)); 62 | } 63 | } 64 | }; 65 | 66 | // Show all of the quests that have already been completed in the last week 67 | $scope.completed = function() { 68 | $scope.isAll = false; 69 | $scope.isActive = false; 70 | $scope.isComplete = true; 71 | $scope.successfulQuests = []; 72 | $scope.failedQuests = []; 73 | $scope.allTab = ''; 74 | $scope.activeTab = ''; 75 | $scope.completedTab = 'button-tab-active'; 76 | $ionicScrollDelegate.scrollTop(); 77 | var today = new Date(); 78 | var refreshQuests = []; 79 | 80 | // Iterate over all the quests that the user has stored; maybe eventually just save them 81 | // locally to the user object 82 | for (var j =0; j< $scope.user.quests.length; j++) { 83 | (function(i) { 84 | var quest = $scope.user.quests[i]; 85 | var completeDate = new Date(quest.completionTime); //convert date to matched format 86 | // Iterate over all the quests and get the ones that have status of completed 87 | if(quest.status === 'success' || quest.status === 'fail') { 88 | // if 7 days have passed since this was completed, they can do it again so we remove it from their user array 89 | if(completeDate.addDays(7) > today) { 90 | refreshQuests.push(quest); 91 | Quests.get({id : quest.questId}, function(q) { 92 | q.completionTime = quest.completionTime; //add completion time so we can sort them 93 | if (quest.status === 'success') { 94 | $scope.successfulQuests.push(q); 95 | } else { 96 | $scope.failedQuests.push(q); 97 | } 98 | }); 99 | } 100 | } else { 101 | refreshQuests.push(quest); 102 | } 103 | }(j)); 104 | } 105 | 106 | $scope.user.quests = refreshQuests; 107 | User.update($scope.user); 108 | }; 109 | 110 | $scope.all(); 111 | 112 | $scope.showList = { 113 | steps: true, 114 | distance: true, 115 | strength: true, 116 | sleep: true, 117 | succeed: true, 118 | fail: true 119 | } 120 | 121 | $scope.toggleList = function (list) { 122 | $scope.showList[list] = !$scope.showList[list]; 123 | }; 124 | 125 | }); 126 | -------------------------------------------------------------------------------- /www/app/quest/quest-detail-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('mobile.quest.controllers') 2 | 3 | .constant('daysWeek', { 4 | 0: 'Sunday', 5 | 1: 'Monday', 6 | 2: 'Tuesday', 7 | 3: 'Wedneday', 8 | 4: 'Thursday', 9 | 5: 'Friday', 10 | 6: 'Saturday' 11 | }) 12 | 13 | // This particular controller handles the individual pages of each quest 14 | .controller('QuestDetailCtrl', function($scope, $state, $stateParams, Quests, $ionicPopup, User, TimesData, DatesData, daysWeek, finishQuest, NewTimesData, $cordovaSocialSharing) { 15 | var questId = $stateParams.questId 16 | $scope.quest = Quests.get({id: questId}); 17 | $scope.availableQuest = true; 18 | $scope.activeQuest = false; 19 | $scope.completedQuest = false; 20 | $scope.userQuest; 21 | 22 | // Show 1-5 stars on the screen depending on the difficulty 23 | $scope.difficulty = function(num) { 24 | return num <= $scope.quest.difficulty; 25 | }; 26 | 27 | var sendTweet = function (message) { 28 | $cordovaSocialSharing.shareViaTwitter(message).then(function(result) { 29 | // Success! 30 | }, function(err) { 31 | // An error occured. Show a message to the user 32 | }); 33 | }; 34 | 35 | // Check if the user currently has this quest active or completed 36 | var pickOutQuest = function() { 37 | for (var i = 0; i < $scope.user.quests.length; i++) { 38 | $scope.winGoal = $scope.user.quests[i].winGoal; 39 | if ($scope.user.quests[i].questId === questId) { 40 | $scope.availableQuest = false; 41 | $scope.userQuest = $scope.user.quests[i]; 42 | evalQuest(); 43 | return; //stop looping 44 | } 45 | } 46 | }; 47 | 48 | // Called in pickOutQuest, and when we refresh to show updated data 49 | // We also return true or false for whether or not the quest has been completed 50 | var evalQuest = function(cb) { 51 | if ($scope.userQuest.status === 'active') { 52 | $scope.activeQuest = true; 53 | $scope.$broadcast('timer-set-countdown'); 54 | $scope.parsedDate = Date.parse($scope.userQuest.completionTime); 55 | if ($scope.userQuest.numDays < 1) { 56 | if ($scope.userQuest.getObj.startDate !== $scope.userQuest.getObj.endDate) { 57 | var newGetObjectBeforeMidnight = {}; 58 | newGetObjectBeforeMidnight.startTime = $scope.userQuest.getObj.startTime; 59 | newGetObjectBeforeMidnight.endTime = '23:59'; 60 | newGetObjectBeforeMidnight.startDate = $scope.userQuest.getObj.startDate; 61 | newGetObjectBeforeMidnight.id = $scope.userQuest.getObj.id; 62 | newGetObjectBeforeMidnight.activity = $scope.userQuest.getObj.activity; 63 | NewTimesData.get(newGetObjectBeforeMidnight, function(result) { 64 | var preMidnightTotal = parseInt(result.total) || 0; 65 | var newGetObjectAfterMidnight = {}; 66 | newGetObjectAfterMidnight.startTime = '00:00'; 67 | newGetObjectAfterMidnight.endTime = $scope.userQuest.getObj.endTime; 68 | newGetObjectAfterMidnight.startDate = $scope.userQuest.getObj.endDate; 69 | newGetObjectAfterMidnight.id = $scope.userQuest.getObj.id; 70 | newGetObjectAfterMidnight.activity = $scope.userQuest.getObj.activity; 71 | NewTimesData.get(newGetObjectAfterMidnight, function(result2) { 72 | var postMidnightTotal = parseInt(result2.total) || 0; 73 | $scope.progress = preMidnightTotal + postMidnightTotal; 74 | var completed = $scope.progress >= $scope.winGoal; 75 | console.log('completed',completed); 76 | if (cb) { cb(completed) }; 77 | }); 78 | }); 79 | } else { 80 | TimesData.get($scope.userQuest.getObj, function(result) { 81 | $scope.progress = result.total || 0; //current progress 82 | var completed = $scope.progress >= $scope.winGoal; 83 | if (cb) { cb(completed) }; 84 | }); 85 | } 86 | } else if ($scope.userQuest.numDays > 0 ) { // multiday quests 87 | DatesData.get($scope.userQuest.getObj, function(result) { 88 | $scope.progress = result.total || 0; // current progress 89 | var completed = $scope.progress >= $scope.winGoal; 90 | if (cb) { cb(completed) }; 91 | }); 92 | } 93 | } else if ($scope.userQuest.status === 'success' || $scope.userQuest.status === 'fail') { 94 | $scope.completedQuest = true; 95 | if (cb) {cb()}; 96 | } 97 | }; 98 | 99 | // function that helps us format the times for dates to make calls to fitbit, so '5' is '05' 100 | var timify = function(time) { 101 | if (time.length === 1) { 102 | time = '0' + time; 103 | } 104 | return time; 105 | } 106 | 107 | $scope.startQuest = function() { 108 | 109 | var numDays = $scope.quest.numDays; 110 | var numHours = $scope.quest.numHours; 111 | var winGoal = $scope.quest.winGoals; 112 | var gold = $scope.quest.gold; 113 | var desc = $scope.quest.shortDescription; 114 | var start = new Date(); // start date 115 | var addD = numDays-1 >= 0 ? numDays-1 : 0; // the number of days we're adding to get to 'end' 116 | var startTime = timify(start.getHours()) + ':' + timify(start.getMinutes()); 117 | var title = 'Embark On A New Quest!'; 118 | var endString,end,body; 119 | 120 | // for multi-day quests, there's a type, MAY LATER ON HAVE TO ACCOUNT FOR DIFFERENT SLEEP QUESTS 121 | if (numDays >=1) { 122 | end = start.addDays(addD); // end date 123 | end.setHours(23); 124 | end.setMinutes(59); // timer always ends at midnight 125 | endString = daysWeek[end.getDay()] + ' at 11:59PM'; 126 | body = 'This is the mission you\'ve chosen:Difficulty: 14 | 15 | 16 | 17 | 18 | 19 |
20 |{{quest.shortDescription}}
24 |{{quest.longDescription}}
Time Limit: {{quest.numDays}} day(s), {{quest.numHours}} hour(s)
26 |Reward: {{quest.gold}} gold pieces
Your Progress{{progress}} / {{winGoal}}
32 |{{quest.shortDescription}} Time: {{quest.numDays}} days, {{quest.numHours}} hrs
30 | 31 | 32 | 33 | 34 |{{quest.shortDescription}} Time: {{quest.numDays}} days, {{quest.numHours}} hrs
41 | 42 | 43 | 44 | 45 |{{quest.shortDescription}}
85 | 86 | 87 |{{quest.shortDescription}}
98 | 99 | 100 | 101 |{{quest.shortDescription}}
108 | 109 | 110 |{{ item.description }}
15 |Loading...
' 7 | }); 8 | }, 500); 9 | 10 | $scope.getData = function() { 11 | $scope.shop = []; 12 | Shop.query( function (items) { 13 | var userLvl = $scope.user.attributes.level; 14 | for (var i=0; iType: {{shopItem.type}}
10 |
14 | Strength
15 | Vitality
16 | Endurance
17 | Dexterity
18 | Size
19 | Cost
20 |
22 |
23 | {{ user.attributes.strength }}
24 | {{ user.attributes.strength + shopItem.strength }}
25 |
26 | {{ user.attributes.vitality }}
27 | {{ user.attributes.vitality + shopItem.vitality }}
28 |
29 | {{ user.attributes.endurance }}
30 | {{ user.attributes.endurance + shopItem.endurance }}
31 |
32 | {{ user.attributes.dexterity }}
33 | {{ user.attributes.dexterity + shopItem.dexterity }}
34 |
35 | {{ shopItem.sizeText }}
36 |
37 | {{ shopItem.cost }} Gold
38 |
{{ shopItem.description }}
45 |Cost
47 |{{ shopItem.cost }} Gold
48 |Get more out of your healthy lifestyle
97 |