From dbf406c92104631a2d173189f2b3e5d161928c5c Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Wed, 15 Jul 2015 11:58:08 -0400 Subject: [PATCH 01/35] Fixes #5623 and fixes #5135 (correctly displays equipment stats in member modals) --- website/public/js/controllers/groupsCtrl.js | 1 + 1 file changed, 1 insertion(+) diff --git a/website/public/js/controllers/groupsCtrl.js b/website/public/js/controllers/groupsCtrl.js index 2cd61ad518..4b8245b24e 100644 --- a/website/public/js/controllers/groupsCtrl.js +++ b/website/public/js/controllers/groupsCtrl.js @@ -173,6 +173,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets); member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts); $scope.profile = member; + $scope.e = member.items.gear.equipped; }); $scope.sendPrivateMessage = function(uuid, message){ // Don't do anything if the user somehow gets here without a message. From d8f74e5d9fb5f0e715a54d0a5732c95bacd81384 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Wed, 15 Jul 2015 13:35:25 -0400 Subject: [PATCH 02/35] First shot at modifying stats.jade attribute table to use ng-repeat --- website/views/shared/profiles/stats.jade | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/website/views/shared/profiles/stats.jade b/website/views/shared/profiles/stats.jade index 686e070965..aa7aed8028 100644 --- a/website/views/shared/profiles/stats.jade +++ b/website/views/shared/profiles/stats.jade @@ -31,30 +31,30 @@ unless mobile h4(class=mobile?'item item-divider':'')=env.t('attributes') table.table.table-striped - each v,k in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } - tr - td - span.hint(popover-title=env.t(v.title), popover-placement='right', popover=env.t(v.popover), popover-trigger='mouseenter', style='margin-right:3px') - strong=env.t(v.title) - span - strong : {{profile._statsComputed.#{k}}} - td - ul.list-unstyled(ng-init='g=Content.gear.flat;e=profile.items.gear.equipped') - li(ng-show='profile.stats.lvl > 1') - span.hint(popover-title=env.t('levelBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('levelBonusText'))=env.t('level') - |: {{Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2)}}  - li(ng-show='g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} > 0') - span.hint(popover-title=env.t('equipment'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('equipmentBonusText'))=env.t('equipment') - |: {{g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} || 0}}  - li(ng-show='profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k} > 0') - span.hint(popover-title=env.t('classBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('classBonusText'))=env.t('classEquipBonus') - |: {{profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1,100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k}}}  - li(ng-show='profile.stats.#{k} > 0') - span.hint(popover-title=env.t('allocatedPoints'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('allocatedPointsText'))=env.t('allocated') - |: {{profile.stats.#{k} || 0}}  - li(ng-show='profile.stats.buffs.#{k} > 0') - span.hint(popover-title=env.t('buffs'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('buffsText'))=env.t('buffs') - |: {{profile.stats.buffs.#{k} || 0}}  + //each v,k in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } + tr(ng-repeat='(k,v) in { str: {title:"strength",popover:"strengthText"},int: {title:"intelligence",popover:"intText"},con: {title:"constitution",popover:"conText"},per: {title:"perception",popover:"perText"} }', ng-init='g=Content.gear.flat;e=profile.items.gear.equipped') + td + span.hint(popover-title=env.t('{{v.title}}'), popover-placement='right', popover=env.t('{{v.popover}}'), popover-trigger='mouseenter', style='margin-right:3px') + strong=env.t('{{v.title}}') + span + strong : {{profile._statsComputed.k}} + td + ul.list-unstyled + li(ng-show='profile.stats.lvl > 1') + span.hint(popover-title=env.t('levelBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('levelBonusText'))=env.t('level') + |: {{Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2)}}  + li(ng-show='Content.gear.flat[profile.items.equipped.weapon].k + g[e.armor].k + g[e.head].k + g[e.shield].k > 0') + span.hint(popover-title=env.t('equipment'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('equipmentBonusText'))=env.t('equipment') + |: {{g[e.weapon].k + g[e.armor].k + g[e.head].k + g[e.shield].k || 0}}  + li(ng-show='profile._statsComputed.k - profile.stats.buffs.k - Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2) - g[e.weapon].k - g[e.armor].k - g[e.head].k - g[e.shield].k - profile.stats.k > 0') + span.hint(popover-title=env.t('classBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('classBonusText'))=env.t('classEquipBonus') + |: {{profile._statsComputed.k - profile.stats.buffs.k - Math.ceil((Math.min(profile.stats.lvl - 1,100)) / 2) - g[e.weapon].k - g[e.armor].k - g[e.head].k - g[e.shield].k - profile.stats.k}}  + li(ng-show='profile.stats.k > 0') + span.hint(popover-title=env.t('allocatedPoints'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('allocatedPointsText'))=env.t('allocated') + |: {{profile.stats.k || 0}}  + li(ng-show='profile.stats.buffs.k > 0') + span.hint(popover-title=env.t('buffs'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('buffsText'))=env.t('buffs') + |: {{profile.stats.buffs.k || 0}}  tr(ng-if='profile.stats.buffs.stealth') td span.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', popover-placement='right', popover=env.t('stealthNewDay')) From 6525cd6f8c181455f291fc02c061929ec248a291 Mon Sep 17 00:00:00 2001 From: hairlessbear Date: Wed, 15 Jul 2015 13:39:16 -0400 Subject: [PATCH 03/35] Revert "First shot at modifying stats.jade attribute table to use ng-repeat" This reverts commit 0d6bc403d069036d998f43c6f7b9173be8f13157. --- website/views/shared/profiles/stats.jade | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/website/views/shared/profiles/stats.jade b/website/views/shared/profiles/stats.jade index aa7aed8028..686e070965 100644 --- a/website/views/shared/profiles/stats.jade +++ b/website/views/shared/profiles/stats.jade @@ -31,30 +31,30 @@ unless mobile h4(class=mobile?'item item-divider':'')=env.t('attributes') table.table.table-striped - //each v,k in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } - tr(ng-repeat='(k,v) in { str: {title:"strength",popover:"strengthText"},int: {title:"intelligence",popover:"intText"},con: {title:"constitution",popover:"conText"},per: {title:"perception",popover:"perText"} }', ng-init='g=Content.gear.flat;e=profile.items.gear.equipped') - td - span.hint(popover-title=env.t('{{v.title}}'), popover-placement='right', popover=env.t('{{v.popover}}'), popover-trigger='mouseenter', style='margin-right:3px') - strong=env.t('{{v.title}}') - span - strong : {{profile._statsComputed.k}} - td - ul.list-unstyled - li(ng-show='profile.stats.lvl > 1') - span.hint(popover-title=env.t('levelBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('levelBonusText'))=env.t('level') - |: {{Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2)}}  - li(ng-show='Content.gear.flat[profile.items.equipped.weapon].k + g[e.armor].k + g[e.head].k + g[e.shield].k > 0') - span.hint(popover-title=env.t('equipment'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('equipmentBonusText'))=env.t('equipment') - |: {{g[e.weapon].k + g[e.armor].k + g[e.head].k + g[e.shield].k || 0}}  - li(ng-show='profile._statsComputed.k - profile.stats.buffs.k - Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2) - g[e.weapon].k - g[e.armor].k - g[e.head].k - g[e.shield].k - profile.stats.k > 0') - span.hint(popover-title=env.t('classBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('classBonusText'))=env.t('classEquipBonus') - |: {{profile._statsComputed.k - profile.stats.buffs.k - Math.ceil((Math.min(profile.stats.lvl - 1,100)) / 2) - g[e.weapon].k - g[e.armor].k - g[e.head].k - g[e.shield].k - profile.stats.k}}  - li(ng-show='profile.stats.k > 0') - span.hint(popover-title=env.t('allocatedPoints'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('allocatedPointsText'))=env.t('allocated') - |: {{profile.stats.k || 0}}  - li(ng-show='profile.stats.buffs.k > 0') - span.hint(popover-title=env.t('buffs'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('buffsText'))=env.t('buffs') - |: {{profile.stats.buffs.k || 0}}  + each v,k in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } + tr + td + span.hint(popover-title=env.t(v.title), popover-placement='right', popover=env.t(v.popover), popover-trigger='mouseenter', style='margin-right:3px') + strong=env.t(v.title) + span + strong : {{profile._statsComputed.#{k}}} + td + ul.list-unstyled(ng-init='g=Content.gear.flat;e=profile.items.gear.equipped') + li(ng-show='profile.stats.lvl > 1') + span.hint(popover-title=env.t('levelBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('levelBonusText'))=env.t('level') + |: {{Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2)}}  + li(ng-show='g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} > 0') + span.hint(popover-title=env.t('equipment'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('equipmentBonusText'))=env.t('equipment') + |: {{g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} || 0}}  + li(ng-show='profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k} > 0') + span.hint(popover-title=env.t('classBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('classBonusText'))=env.t('classEquipBonus') + |: {{profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1,100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k}}}  + li(ng-show='profile.stats.#{k} > 0') + span.hint(popover-title=env.t('allocatedPoints'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('allocatedPointsText'))=env.t('allocated') + |: {{profile.stats.#{k} || 0}}  + li(ng-show='profile.stats.buffs.#{k} > 0') + span.hint(popover-title=env.t('buffs'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('buffsText'))=env.t('buffs') + |: {{profile.stats.buffs.#{k} || 0}}  tr(ng-if='profile.stats.buffs.stealth') td span.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', popover-placement='right', popover=env.t('stealthNewDay')) From a9757c9dbb9c318f9af05c26da70df534d32d241 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 17 Jul 2015 08:43:37 -0500 Subject: [PATCH 04/35] Refactor member service; Remove logic in functions that were never used --- test/spec/services/memberServicesSpec.js | 59 ++++++--- website/public/js/services/memberServices.js | 125 ++++++++----------- website/public/js/services/questServices.js | 5 +- 3 files changed, 95 insertions(+), 94 deletions(-) diff --git a/test/spec/services/memberServicesSpec.js b/test/spec/services/memberServicesSpec.js index 0689cab3c3..d33ccd8c98 100644 --- a/test/spec/services/memberServicesSpec.js +++ b/test/spec/services/memberServicesSpec.js @@ -8,30 +8,59 @@ describe('memberServices', function() { members = Members; })); + afterEach(function() { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + it('has no members at the beginning', function() { expect(members.members).to.be.an('object'); expect(members.members).to.eql({}); expect(members.selectedMember).to.be.undefined; }); - it('populates members', function(){ - var uid = 'abc'; - members.populate({ - members: [{ _id: uid }] - }); - expect(members.members).to.eql({ - abc: { _id: uid } + describe('addToMembersList', function() { + it('adds member to members object', function() { + var member = { _id: 'user_id' }; + members.addToMembersList(member); + expect(members.members).to.eql({ + user_id: { _id: 'user_id' } + }); }); }); - it('selects a member', function(){ - var uid = 'abc'; - $httpBackend.expectGET('/api/v2/members/' + uid).respond({ _id: uid }); - members.selectMember(uid, function(){}); - $httpBackend.flush(); + describe('selectMember', function() { + it('fetches member if not already in cache', function() { + var uid = 'abc'; + $httpBackend.expectGET('/api/v2/members/' + uid).respond({ _id: uid }); + members.selectMember(uid, function(){}); + $httpBackend.flush(); - expect(members.selectedMember._id).to.eql(uid); - expect(members.members).to.have.property(uid); + expect(members.selectedMember._id).to.eql(uid); + expect(members.members).to.have.property(uid); + }); + + it('fetches member if member data in cache is incomplete', function() { + var uid = 'abc'; + members.members = { + abc: { _id: 'abc', items: {} } + } + $httpBackend.expectGET('/api/v2/members/' + uid).respond({ _id: uid }); + members.selectMember(uid, function(){}); + $httpBackend.flush(); + + expect(members.selectedMember._id).to.eql(uid); + expect(members.members).to.have.property(uid); + }); + + it('gets member from cache if member has a weapons object', function() { + var uid = 'abc'; + members.members[uid] = { _id: uid, items: { weapon: {} } }; + members.selectMember(uid, function(){ + expect(members.selectedMember._id).to.eql(uid); + expect(members.members).to.have.property(uid); + }); + }); }); - }); diff --git a/website/public/js/services/memberServices.js b/website/public/js/services/memberServices.js index 53a1c1e998..082fe27bbb 100644 --- a/website/public/js/services/memberServices.js +++ b/website/public/js/services/memberServices.js @@ -1,87 +1,60 @@ 'use strict'; +(function(){ + angular + .module('habitrpg') + .factory('Members', membersFactory); -/** - * Services that persists and retrieves user from localStorage. - */ + membersFactory.$inject = [ + '$rootScope', + 'Shared', + 'ApiUrl', + '$resource' + ]; -angular.module('habitrpg').factory('Members', -['$rootScope', 'Shared', 'ApiUrl', '$resource', -function($rootScope, Shared, ApiUrl, $resource) { - var members = {}; - var Member = $resource(ApiUrl.get() + '/api/v2/members/:uid', {uid:'@_id'}); - var memberServices = { + function membersFactory($rootScope, Shared, ApiUrl, $resource) { + var members = {}; + var fetchMember = $resource(ApiUrl.get() + '/api/v2/members/:uid', { uid: '@_id' }).get; - Member: Member, + function selectMember(uid, cb) { - members: members, - - /** - * Allows us to lazy-load party / group / public members throughout the application. - * @param obj - either a group or an individual member. If it's a group, we lazy-load all of its members. - */ - populate: function(obj){ - - function populateGroup(group){ - _.each(group.members, function(member){ - // meaning `populate('members')` wasn't run on the server, so we're getting the "in-database" form of - // the members array, which is just a list of IDs - not the populated objects - if (_.isString(member)) return; - - // lazy-load - members[member._id] = member; - }) - } - - // Array of groups - if (_.isArray(obj)) { - if (obj[0] && obj[0].members) { - _.each(obj, function(group){ - populateGroup(group); - }) - } - - // Individual Group - } else if (obj.members) - populateGroup(obj); - - // individual Member - if (obj._id) { - members[obj._id] = obj; - } - }, - - selectedMember: undefined, - - /** - * Once users are populated, we fetch them throughout the application (eg, modals). This - * either gets them or fetches if not available - * @param uid - */ - selectMember: function(uid, cb) { var self = this; - // Fetch from cache if we can. For guild members, only their uname will have been fetched on initial load, - // check if they have full fields (eg, check profile.items and an item inside - // because sometimes profile.items exists but it's empty like when user is fetched for party - // and then for guild) - // and if not, fetch them - if (members[uid] && members[uid].items && members[uid].items.weapon) { - Shared.wrap(members[uid],false); - self.selectedMember = members[uid]; - cb(); + var memberIsReady = _checkIfMemberIsReady(members[uid]); + + if (memberIsReady) { + _prepareMember(self, members[uid], cb); } else { - Member.get({uid: uid}, function(member){ - self.populate(member); // lazy load for later - Shared.wrap(member,false); - self.selectedMember = members[member._id]; - cb(); + fetchMember({ uid: uid }, function(member) { + addToMembersList(member); // lazy load for later + _prepareMember(self, member, cb); }); } } + + function addToMembersList(member){ + if (member._id) { + members[member._id] = member; + } + } + + function _checkIfMemberIsReady(member) { + return member && member.items && member.items.weapon; + } + + function _prepareMember(self, member, cb) { + Shared.wrap(member, false); + self.selectedMember = members[member._id]; + cb(); + } + + $rootScope.$on('userUpdated', function(event, user){ + populate(user); + }) + + return { + members: members, + addToMembersList: addToMembersList, + selectedMember: undefined, + selectMember: selectMember + } } - - $rootScope.$on('userUpdated', function(event, user){ - memberServices.populate(user); - }) - - return memberServices; -}]); +}()); diff --git a/website/public/js/services/questServices.js b/website/public/js/services/questServices.js index 1ca6995c38..6623d425b1 100644 --- a/website/public/js/services/questServices.js +++ b/website/public/js/services/questServices.js @@ -1,6 +1,5 @@ -/** - * Created by Sabe on 7/7/2015. - */ +'use strict'; + (function(){ angular .module('habitrpg') From 841923e054b69456b47242062ae96ba3236c310a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 17 Jul 2015 17:37:57 -0500 Subject: [PATCH 05/35] Add level bonus calculation script --- common/script/methods/statCalculations.js | 20 +++++++++++++ test/common/statCalculations.js | 35 +++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 common/script/methods/statCalculations.js create mode 100644 test/common/statCalculations.js diff --git a/common/script/methods/statCalculations.js b/common/script/methods/statCalculations.js new file mode 100644 index 0000000000..aac1880158 --- /dev/null +++ b/common/script/methods/statCalculations.js @@ -0,0 +1,20 @@ +'use strict'; + +var Content = require('../content.coffee'); + +function levelBonus(level) { + // Level bonus is derived by taking the level, subtracting one, + // taking the smaller of it or maxLevel (100), + // dividing that by two and then raising it to a whole number + + // TODO: 100 is a magic number, extract from script.index into own module and call here + var levelOrMaxLevel = Math.min((level - 1), 100) + var levelDividedByTwo = levelOrMaxLevel / 2 + var statBonus = Math.ceil(levelDividedByTwo ) + + return statBonus; +} + +module.exports = { + levelBonus: levelBonus +} diff --git a/test/common/statCalculations.js b/test/common/statCalculations.js new file mode 100644 index 0000000000..9f996ca68d --- /dev/null +++ b/test/common/statCalculations.js @@ -0,0 +1,35 @@ +'use strict'; +var sinon = require('sinon'); +var chai = require("chai"); +chai.use(require("sinon-chai")); +var expect = chai.expect; + +var statCalc = require('../../common/script/methods/statCalculations'); + +describe('stat calculation functions', function() { + describe('calculateLevelStatBonus', function() { + it('calculates bonus as half of level for even numbered level under 100', function() { + var level = 50; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(25); + }); + + it('calculates bonus as half of level, rounded down, for odd numbered level under 100', function() { + var level = 51; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(25); + }); + + it('calculates bonus as 50 for levels >= 100', function() { + var level = 150; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(50); + }); + + it('calculates bonus as 0 for level 1', function() { + var level = 1; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(0); + }); + }); +}); From e5428f29c1f8bf7b8d096a2511e743185a1c6cb8 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 07:44:49 -0500 Subject: [PATCH 06/35] Add calculation for equipment stat bonus --- common/script/methods/statCalculations.js | 21 +++++++++++++++++++-- test/common/statCalculations.js | 23 ++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/common/script/methods/statCalculations.js b/common/script/methods/statCalculations.js index aac1880158..7b6826b63f 100644 --- a/common/script/methods/statCalculations.js +++ b/common/script/methods/statCalculations.js @@ -15,6 +15,23 @@ function levelBonus(level) { return statBonus; } -module.exports = { - levelBonus: levelBonus +function equipmentStatBonus(stat, equipped) { + var gear = Content.gear.flat; + var total = 0; + + var equipmentTypes = ['weapon', 'armor', 'head', 'shield']; + + _(equipmentTypes).each(function(type) { + var equippedItem = equipped[type] + var equipmentStat = gear[equippedItem][stat]; + + total += equipmentStat; + }); + + return total; +} + +module.exports = { + levelBonus: levelBonus, + equipmentStatBonus: equipmentStatBonus } diff --git a/test/common/statCalculations.js b/test/common/statCalculations.js index 9f996ca68d..68fa399132 100644 --- a/test/common/statCalculations.js +++ b/test/common/statCalculations.js @@ -7,7 +7,7 @@ var expect = chai.expect; var statCalc = require('../../common/script/methods/statCalculations'); describe('stat calculation functions', function() { - describe('calculateLevelStatBonus', function() { + describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; var bonus = statCalc.levelBonus(level); @@ -32,4 +32,25 @@ describe('stat calculation functions', function() { expect(bonus).to.eql(0); }); }); + + describe('equipmentStatBonus', function() { + it('tallies up stats from euqipment that is equipped', function() { + var equippedGear = { + "weapon" : "weapon_special_1", + "shield" : "shield_special_1", + "head" : "head_special_1", + "armor" : "armor_special_1" + }; + + var strStat = statCalc.equipmentStatBonus('str', equippedGear); + var conStat = statCalc.equipmentStatBonus('con', equippedGear); + var intStat = statCalc.equipmentStatBonus('int', equippedGear); + var perStat = statCalc.equipmentStatBonus('per', equippedGear); + + expect(strStat).to.eql(24); + expect(conStat).to.eql(24); + expect(intStat).to.eql(24); + expect(perStat).to.eql(24); + }); + }); }); From 6d5b57d1393c35a73742e9efa0e2ad94e730aa46 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 08:07:16 -0500 Subject: [PATCH 07/35] Add class bonus calc function --- common/script/methods/statCalculations.js | 17 ++++++++++++--- test/common/statCalculations.js | 26 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/common/script/methods/statCalculations.js b/common/script/methods/statCalculations.js index 7b6826b63f..c5d6ab9a73 100644 --- a/common/script/methods/statCalculations.js +++ b/common/script/methods/statCalculations.js @@ -31,7 +31,18 @@ function equipmentStatBonus(stat, equipped) { return total; } -module.exports = { - levelBonus: levelBonus, - equipmentStatBonus: equipmentStatBonus +function classBonus(user, stat) { + var bonus = user._statsComputed[stat] + - user.stats.buffs[stat] + - levelBonus(user.stats.lvl) + - equipmentStatBonus(stat, user.items.gear.equipped) + - user.stats[stat] + + return bonus; +} + +module.exports = { + classBonus: classBonus, + equipmentStatBonus: equipmentStatBonus, + levelBonus: levelBonus } diff --git a/test/common/statCalculations.js b/test/common/statCalculations.js index 68fa399132..40e0931a82 100644 --- a/test/common/statCalculations.js +++ b/test/common/statCalculations.js @@ -53,4 +53,30 @@ describe('stat calculation functions', function() { expect(perStat).to.eql(24); }); }); + + describe('classBonus', function() { + it('calculates class bonus', function() { + var equippedGear = { + "weapon" : "weapon_warrior_1", + "shield" : "shield_warrior_1", + "head" : "head_warrior_1", + "armor" : "armor_warrior_1" + }; + var user = { + _statsComputed: { str: 50 }, + stats: { + lvl: 10, + buffs: { str: 10 }, + str: 10 + }, + items: { + gear: { equipped: equippedGear } + } + }; + var stat = 'str'; + var classBonus = statCalc.classBonus(user, stat); + + expect(classBonus).to.eql(20) + }); + }); }); From 163b0545e8f514667d9c2fffe896f527f2b24efb Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 08:18:31 -0500 Subject: [PATCH 08/35] Adjustments for error handling --- common/script/methods/statCalculations.js | 21 +++++++++++++-------- test/common/statCalculations.js | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/common/script/methods/statCalculations.js b/common/script/methods/statCalculations.js index c5d6ab9a73..51a554f9cf 100644 --- a/common/script/methods/statCalculations.js +++ b/common/script/methods/statCalculations.js @@ -23,22 +23,27 @@ function equipmentStatBonus(stat, equipped) { _(equipmentTypes).each(function(type) { var equippedItem = equipped[type] - var equipmentStat = gear[equippedItem][stat]; + if(gear[equippedItem]) { + var equipmentStat = gear[equippedItem][stat]; - total += equipmentStat; + total += equipmentStat; + } }); return total; } function classBonus(user, stat) { - var bonus = user._statsComputed[stat] - - user.stats.buffs[stat] - - levelBonus(user.stats.lvl) - - equipmentStatBonus(stat, user.items.gear.equipped) - - user.stats[stat] + var computedStats = user._statsComputed; + if(computedStats) { + var bonus = computedStats[stat] + - user.stats.buffs[stat] + - levelBonus(user.stats.lvl) + - equipmentStatBonus(stat, user.items.gear.equipped) + - user.stats[stat] - return bonus; + return bonus; + } } module.exports = { diff --git a/test/common/statCalculations.js b/test/common/statCalculations.js index 40e0931a82..f0ffd38ce6 100644 --- a/test/common/statCalculations.js +++ b/test/common/statCalculations.js @@ -78,5 +78,28 @@ describe('stat calculation functions', function() { expect(classBonus).to.eql(20) }); + + it('does not return value if user has not been wrapped (_statComputed)', function() { + var equippedGear = { + "weapon" : "weapon_warrior_1", + "shield" : "shield_warrior_1", + "head" : "head_warrior_1", + "armor" : "armor_warrior_1" + }; + var user = { + stats: { + lvl: 10, + buffs: { str: 10 }, + str: 10 + }, + items: { + gear: { equipped: equippedGear } + } + }; + var stat = 'str'; + var classBonus = statCalc.classBonus(user, stat); + + expect(classBonus).to.not.exist; + }); }); }); From 20148be288db4ab33cbb28925f4d82acf691ab37 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 09:14:44 -0500 Subject: [PATCH 09/35] Watch js files in common folder --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 036850c2de..68d3526a16 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -169,7 +169,7 @@ module.exports = function(grunt) { watch: { dev: { - files: ['website/public/**/*.styl', 'common/script/**/*.coffee'], // 'public/**/*.js' Not needed because not in production + files: ['website/public/**/*.styl', 'common/script/**/*.coffee', 'common/script/**/*.js'], // 'public/**/*.js' Not needed because not in production tasks: [ 'build:dev' ], options: { nospawn: true From 2b4e48fbe62b7c231641753decab3213fa8de947 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 09:16:45 -0500 Subject: [PATCH 10/35] Add stat calc to common --- common/script/index.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/script/index.coffee b/common/script/index.coffee index fc1b0978cb..209683858c 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -33,6 +33,8 @@ api.planGemLimits = convRate: 20 #how much does a gem cost? convCap: 25 #how many gems can be converted / month? +api.statCalc = require('./methods/statCalculations') + ### ------------------------------------------------------ Time / Day From ff42505d1bfe7cbb800fd9c8b17cda3dfc6a71fc Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 10:52:02 -0500 Subject: [PATCH 11/35] Add string --- common/locales/en/character.json | 1 + 1 file changed, 1 insertion(+) diff --git a/common/locales/en/character.json b/common/locales/en/character.json index 17e609c752..a4f3a2bb8c 100644 --- a/common/locales/en/character.json +++ b/common/locales/en/character.json @@ -45,6 +45,7 @@ "hauntedColors": "Haunted Colors", "winteryColors": "Wintery Colors", "equipment": "Equipment", + "equipmentBonus": "Equipment", "equipmentBonusText": "Attribute bonuses provided by your equipped battle gear. See the Equipment tab under Inventory to select your battle gear.", "classBonus": "Class Equipment Bonus", "classBonusText": "Your class (Warrior, if you haven't unlocked or selected another class) uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.", From 94d476f8375d04bfb37b7d71778a487156bbb239 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 10:52:29 -0500 Subject: [PATCH 12/35] Correct method name --- website/public/js/services/memberServices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/public/js/services/memberServices.js b/website/public/js/services/memberServices.js index 082fe27bbb..4146a4ea1f 100644 --- a/website/public/js/services/memberServices.js +++ b/website/public/js/services/memberServices.js @@ -47,7 +47,7 @@ } $rootScope.$on('userUpdated', function(event, user){ - populate(user); + addToMembersList(user); }) return { From 3926a6e95a6c67e8f68f009702b793c83e4a2594 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 10:52:50 -0500 Subject: [PATCH 13/35] Remove unnecssary semicolons --- common/script/index.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 209683858c..e8ca6096ae 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -90,7 +90,7 @@ api.shouldDo = (day, dailyTask, options = {}) -> # The time portion of the Start Date is never visible to or modifiable by the user so we must ignore it. # Therefore, we must also ignore the time portion of the user's day start (startOfDayWithCDSTime), otherwise the date comparison will be wrong for some times. # NB: The user's day start date has already been converted to the PREVIOUS day's date if the time portion was before CDS. - taskStartDate = moment(taskStartDate).startOf('day'); + taskStartDate = moment(taskStartDate).startOf('day') if taskStartDate > startOfDayWithCDSTime.startOf('day') return false # Daily starts in the future @@ -514,7 +514,7 @@ api.wrap = (user, main=true) -> gear[type].weapon = 'weapon_base_0' gear[type].head = 'head_base_0' gear[type].shield = 'shield_base_0' - gear.owned = {} if typeof gear.owned == 'undefined'; + gear.owned = {} if typeof gear.owned == 'undefined' _.each gear.owned, (v, k)-> gear.owned[k]=false if gear.owned[k];true gear.owned.weapon_warrior_0 = true user.markModified? 'items.gear.owned' @@ -709,7 +709,7 @@ api.wrap = (user, main=true) -> addPushDevice: (req, cb) -> user.pushDevices = [] unless user.pushDevices pd = user.pushDevices - item = {regId:req.body.regId, type:req.body.type}; + item = {regId:req.body.regId, type:req.body.type} i = _.findIndex pd, {regId: item.regId} pd.push(item) unless i != -1 @@ -1188,7 +1188,7 @@ api.wrap = (user, main=true) -> unless task.type is 'reward' if (user.preferences.automaticAllocation is true and user.preferences.allocationMode is 'taskbased' and !(task.type is 'todo' and direction is 'down')) then user.stats.training[task.attribute] += nextDelta if direction is 'up' # Make progress on quest based on STR - user.party.quest.progress.up = user.party.quest.progress.up || 0; + user.party.quest.progress.up = user.party.quest.progress.up || 0 user.party.quest.progress.up += (nextDelta * (1 + (user._statsComputed.str / 200))) if task.type in ['daily','todo'] user.party.quest.progress.up += (nextDelta * (0.5 + (user._statsComputed.str / 400))) if task.type is 'habit' task.value += nextDelta @@ -1512,7 +1512,7 @@ api.wrap = (user, main=true) -> user.fns.autoAllocate() else # add new allocatable points. We could do user.stats.points++, but this does a fail-safe just in case - user.stats.points = user.stats.lvl - (user.stats.con + user.stats.str + user.stats.per + user.stats.int); + user.stats.points = user.stats.lvl - (user.stats.con + user.stats.str + user.stats.per + user.stats.int) if user.stats.points < 0 user.stats.points = 0 # This happens after dropping level with Fix Character Values and perhaps from other causes. From f9304bd28f347c60bdb339f5a6ebfd3cfcc4b230 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 12:57:54 -0500 Subject: [PATCH 14/35] Move stat calc scripts to angular service --- common/script/index.coffee | 2 - common/script/methods/statCalculations.js | 53 --------------- karma.conf.js | 1 + .../services/statServicesSpec.js} | 20 ++++-- website/public/js/services/statServices.js | 65 +++++++++++++++++++ website/public/manifest.json | 1 + 6 files changed, 81 insertions(+), 61 deletions(-) delete mode 100644 common/script/methods/statCalculations.js rename test/{common/statCalculations.js => spec/services/statServicesSpec.js} (90%) create mode 100644 website/public/js/services/statServices.js diff --git a/common/script/index.coffee b/common/script/index.coffee index e8ca6096ae..88402eeaf4 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -33,8 +33,6 @@ api.planGemLimits = convRate: 20 #how much does a gem cost? convCap: 25 #how many gems can be converted / month? -api.statCalc = require('./methods/statCalculations') - ### ------------------------------------------------------ Time / Day diff --git a/common/script/methods/statCalculations.js b/common/script/methods/statCalculations.js deleted file mode 100644 index 51a554f9cf..0000000000 --- a/common/script/methods/statCalculations.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -var Content = require('../content.coffee'); - -function levelBonus(level) { - // Level bonus is derived by taking the level, subtracting one, - // taking the smaller of it or maxLevel (100), - // dividing that by two and then raising it to a whole number - - // TODO: 100 is a magic number, extract from script.index into own module and call here - var levelOrMaxLevel = Math.min((level - 1), 100) - var levelDividedByTwo = levelOrMaxLevel / 2 - var statBonus = Math.ceil(levelDividedByTwo ) - - return statBonus; -} - -function equipmentStatBonus(stat, equipped) { - var gear = Content.gear.flat; - var total = 0; - - var equipmentTypes = ['weapon', 'armor', 'head', 'shield']; - - _(equipmentTypes).each(function(type) { - var equippedItem = equipped[type] - if(gear[equippedItem]) { - var equipmentStat = gear[equippedItem][stat]; - - total += equipmentStat; - } - }); - - return total; -} - -function classBonus(user, stat) { - var computedStats = user._statsComputed; - if(computedStats) { - var bonus = computedStats[stat] - - user.stats.buffs[stat] - - levelBonus(user.stats.lvl) - - equipmentStatBonus(stat, user.items.gear.equipped) - - user.stats[stat] - - return bonus; - } -} - -module.exports = { - classBonus: classBonus, - equipmentStatBonus: equipmentStatBonus, - levelBonus: levelBonus -} diff --git a/karma.conf.js b/karma.conf.js index d1d576e53b..bbb3bb45a8 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -55,6 +55,7 @@ module.exports = function(config) { "website/public/js/services/taskServices.js", "website/public/js/services/paymentServices.js", "website/public/js/services/questServices.js", + "website/public/js/services/statServices.js", "website/public/js/filters/money.js", "website/public/js/filters/roundLargeNumbers.js", diff --git a/test/common/statCalculations.js b/test/spec/services/statServicesSpec.js similarity index 90% rename from test/common/statCalculations.js rename to test/spec/services/statServicesSpec.js index f0ffd38ce6..4593038171 100644 --- a/test/common/statCalculations.js +++ b/test/spec/services/statServicesSpec.js @@ -1,12 +1,20 @@ 'use strict'; -var sinon = require('sinon'); -var chai = require("chai"); -chai.use(require("sinon-chai")); -var expect = chai.expect; -var statCalc = require('../../common/script/methods/statCalculations'); +describe('Stats Service', function() { + var scope, statCalc, user; + + beforeEach(function() { + user = specHelper.newUser(); + + module(function($provide) { + $provide.value('User', {user: user}); + }); + + inject(function($rootScope, $controller, Stats) { + statCalc = Stats; + }); + }); -describe('stat calculation functions', function() { describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js new file mode 100644 index 0000000000..593031526f --- /dev/null +++ b/website/public/js/services/statServices.js @@ -0,0 +1,65 @@ +'use strict'; + +(function(){ + angular + .module('habitrpg') + .factory('Stats', statsFactory); + + statsFactory.$inject = [ + 'Content', + 'Shared' + ]; + + function statsFactory(Content, Shared) { + + function levelBonus(level) { + // Level bonus is derived by taking the level, subtracting one, + // taking the smaller of it or maxLevel (100), + // dividing that by two and then raising it to a whole number + + var levelOrMaxLevel = Math.min((level - 1), Shared.maxLevel); + var levelDividedByTwo = levelOrMaxLevel / 2; + var bonus = Math.ceil(levelDividedByTwo ); + + return bonus; + } + + function equipmentStatBonus(stat, equipped) { + var gear = Content.gear.flat; + var total = 0; + + var equipmentTypes = ['weapon', 'armor', 'head', 'shield']; + + _(equipmentTypes).each(function(type) { + var equippedItem = equipped[type]; + if(gear[equippedItem]) { + var equipmentStat = gear[equippedItem][stat]; + + total += equipmentStat; + } + }); + + return total; + } + + function classBonus(user, stat) { + var computedStats = user._statsComputed; + + if(computedStats) { + var bonus = computedStats[stat] + - user.stats.buffs[stat] + - levelBonus(user.stats.lvl) + - equipmentStatBonus(stat, user.items.gear.equipped) + - user.stats[stat]; + + return bonus; + } + } + + return { + classBonus: classBonus, + equipmentStatBonus: equipmentStatBonus, + levelBonus: levelBonus + } + } +}()); diff --git a/website/public/manifest.json b/website/public/manifest.json index 029b618a94..7d4189887a 100644 --- a/website/public/manifest.json +++ b/website/public/manifest.json @@ -52,6 +52,7 @@ "js/services/challengeServices.js", "js/services/paymentServices.js", "js/services/questServices.js", + "js/services/statServices.js", "js/filters/money.js", "js/filters/roundLargeNumbers.js", From 17ef7e28850e1e6a933e5d20fec686b86a221db6 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 13:12:11 -0500 Subject: [PATCH 15/35] Add hpDisplay function --- test/spec/services/statServicesSpec.js | 17 +++++++++++++++++ website/public/js/services/statServices.js | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 4593038171..a8fbe5f6f8 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -15,6 +15,23 @@ describe('Stats Service', function() { }); }); + describe('hpDisplay', function() { + it('displays hp as "hp / totalHP"', function() { + var hp = 34; + var hpDisplay = statCalc.hpDisplay(hp); + + expect(hpDisplay).to.eql('34/50'); + }); + + it('Rounds hp up when given a decimal', function() { + + var hp = 34.4; + var hpDisplay = statCalc.hpDisplay(hp); + + expect(hpDisplay).to.eql('35/50'); + }); + }); + describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 593031526f..6fbe6d4f73 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -12,6 +12,14 @@ function statsFactory(Content, Shared) { + function hpDisplay(hp) { + var remainingHP = Math.ceil(hp); + var totalHP = Shared.maxHealth; + var display = remainingHP + '/' + totalHP; + + return display; + } + function levelBonus(level) { // Level bonus is derived by taking the level, subtracting one, // taking the smaller of it or maxLevel (100), @@ -59,6 +67,7 @@ return { classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, + hpDisplay: hpDisplay, levelBonus: levelBonus } } From 2eb62de0567970c5cdfaf10ca3c78289e47eb0c5 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 14:08:25 -0500 Subject: [PATCH 16/35] Add mpdisplay function --- test/spec/services/statServicesSpec.js | 18 ++++++++++++++++++ website/public/js/services/statServices.js | 11 ++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index a8fbe5f6f8..568b44ae91 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -32,6 +32,24 @@ describe('Stats Service', function() { }); }); + describe('mpDisplay', function() { + it('displays mp as "mp / totalMP"', function() { + user._statsComputed = { maxMP: 100 }; + user.stats.mp = 30; + var mpDisplay = statCalc.mpDisplay(user); + + expect(mpDisplay).to.eql('30/100'); + }); + + it('Rounds mp down when given a decimal', function() { + user._statsComputed = { maxMP: 100 }; + user.stats.mp = 30.99; + var mpDisplay = statCalc.mpDisplay(user); + + expect(mpDisplay).to.eql('30/100'); + }); + }); + describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 6fbe6d4f73..2eea238da1 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -20,6 +20,14 @@ return display; } + function mpDisplay(user) { + var remainingMP = Math.floor(user.stats.mp); + var totalMP = user._statsComputed.maxMP; + var display = remainingMP + '/' + totalMP; + + return display; + } + function levelBonus(level) { // Level bonus is derived by taking the level, subtracting one, // taking the smaller of it or maxLevel (100), @@ -68,7 +76,8 @@ classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, hpDisplay: hpDisplay, - levelBonus: levelBonus + levelBonus: levelBonus, + mpDisplay: mpDisplay } } }()); From f1453d30c4c33432b413d521ef810fc5d9bdf840 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 14:29:40 -0500 Subject: [PATCH 17/35] Add gold display function --- test/spec/services/statServicesSpec.js | 16 ++++++++++++++++ website/public/js/services/statServices.js | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 568b44ae91..6b0b2edec7 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -50,6 +50,22 @@ describe('Stats Service', function() { }); }); + describe('goldDisplay', function() { + it('displays gold', function() { + var gold = 30; + var goldDisplay = statCalc.goldDisplay(gold); + + expect(goldDisplay).to.eql(30); + }); + + it('Rounds gold down when given a decimal', function() { + var gold = 30.999; + var goldDisplay = statCalc.goldDisplay(gold); + + expect(goldDisplay).to.eql(30); + }); + }); + describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 2eea238da1..b2418c6900 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -20,6 +20,11 @@ return display; } + function goldDisplay(gold) { + var display = Math.floor(gold); + return display; + } + function mpDisplay(user) { var remainingMP = Math.floor(user.stats.mp); var totalMP = user._statsComputed.maxMP; @@ -75,6 +80,7 @@ return { classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, + goldDisplay: goldDisplay, hpDisplay: hpDisplay, levelBonus: levelBonus, mpDisplay: mpDisplay From 53fb0ec8b04534afe176ba68f8ed4e0c120d760a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 14:50:02 -0500 Subject: [PATCH 18/35] Add display experience function --- test/spec/services/statServicesSpec.js | 18 ++++++++++++++++++ website/public/js/services/statServices.js | 9 +++++++++ 2 files changed, 27 insertions(+) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 6b0b2edec7..35e53109a1 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -66,6 +66,24 @@ describe('Stats Service', function() { }); }); + describe('expDisplay', function() { + it('displays exp as "exp / toNextLevelExp"', function() { + user.stats.exp = 10; + user.stats.lvl = 29; + var expDisplay = statCalc.expDisplay(user); + + expect(expDisplay).to.eql('10/640'); + }); + + it('Rounds exp down when given a decimal', function() { + user.stats.exp = 10.999; + user.stats.lvl = 29; + var expDisplay = statCalc.expDisplay(user); + + expect(expDisplay).to.eql('10/640'); + }); + }); + describe('levelBonus', function() { it('calculates bonus as half of level for even numbered level under 100', function() { var level = 50; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index b2418c6900..c05afb3390 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -33,6 +33,14 @@ return display; } + function expDisplay(user) { + var exp = Math.floor(user.stats.exp); + var toNextLevel = Shared.tnl(user.stats.lvl); + var display = exp + '/' + toNextLevel; + + return display; + } + function levelBonus(level) { // Level bonus is derived by taking the level, subtracting one, // taking the smaller of it or maxLevel (100), @@ -80,6 +88,7 @@ return { classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, + expDisplay: expDisplay, goldDisplay: goldDisplay, hpDisplay: hpDisplay, levelBonus: levelBonus, From c784b97586ecc9ce8523eea9edfb6fd3ac8d8a44 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 14:53:14 -0500 Subject: [PATCH 19/35] Create private method for how stats should be displayed --- website/public/js/services/statServices.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index c05afb3390..e7ec65eda8 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -15,7 +15,7 @@ function hpDisplay(hp) { var remainingHP = Math.ceil(hp); var totalHP = Shared.maxHealth; - var display = remainingHP + '/' + totalHP; + var display = _formatOutOfTotalDisplay(remainingHP, totalHP); return display; } @@ -28,7 +28,7 @@ function mpDisplay(user) { var remainingMP = Math.floor(user.stats.mp); var totalMP = user._statsComputed.maxMP; - var display = remainingMP + '/' + totalMP; + var display = _formatOutOfTotalDisplay(remainingMP, totalMP); return display; } @@ -36,7 +36,7 @@ function expDisplay(user) { var exp = Math.floor(user.stats.exp); var toNextLevel = Shared.tnl(user.stats.lvl); - var display = exp + '/' + toNextLevel; + var display = _formatOutOfTotalDisplay(exp, toNextLevel); return display; } @@ -85,6 +85,11 @@ } } + function _formatOutOfTotalDisplay(stat, totalStat) { + var display = stat + "/" + totalStat; + return display; + } + return { classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, From b716d882b64f738e4e25084d580aa399c8c4575e Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 15:24:32 -0500 Subject: [PATCH 20/35] Began refactor of stats page --- website/public/js/controllers/groupsCtrl.js | 24 ++-- website/public/js/controllers/userCtrl.js | 7 +- website/views/shared/profiles/stats.jade | 117 ++++++++------------ 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/website/public/js/controllers/groupsCtrl.js b/website/public/js/controllers/groupsCtrl.js index 4b8245b24e..f7b05701d4 100644 --- a/website/public/js/controllers/groupsCtrl.js +++ b/website/public/js/controllers/groupsCtrl.js @@ -159,22 +159,26 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' }; }]) - .controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups', 'Chat', '$controller', - function($scope, $rootScope, Members, Shared, $http, Notification, Groups, Chat, $controller) { + .controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups', 'Chat', '$controller', 'Stats', + function($scope, $rootScope, Members, Shared, $http, Notification, Groups, Chat, $controller, Stats) { $controller('RootCtrl', {$scope: $scope}); $scope.timestamp = function(timestamp){ return moment(timestamp).format($rootScope.User.user.preferences.dateFormat.toUpperCase()); } + + $scope.statCalc = Stats; + // We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here $scope.$watch( function() { return Members.selectedMember; }, function (member) { - if(member) + if(member) { member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets); member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts); - $scope.profile = member; - $scope.e = member.items.gear.equipped; + $scope.profile = member; + } }); + $scope.sendPrivateMessage = function(uuid, message){ // Don't do anything if the user somehow gets here without a message. if (!message) return; @@ -184,27 +188,31 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' $rootScope.User.sync(); $scope.$close(); }); - } + }; + $scope.gift = { type: 'gems', gems: {amount:0, fromBalance:true}, subscription: {key:''}, message:'' }; + $scope.sendGift = function(uuid, gift){ $http.post('/api/v2/members/'+uuid+'/gift', gift).success(function(){ Notification.text('Gift sent!') $rootScope.User.sync(); $scope.$close(); }) - } + }; + $scope.reportAbuse = function(reporter, message, groupId) { message.flags[reporter._id] = true; Chat.utils.flagChatMessage({gid: groupId, messageId: message.id}, undefined, function(data){ Notification.text(window.env.t('abuseReported')); $scope.$close(); }); - } + }; + $scope.clearFlagCount = function(message, groupId) { Chat.utils.clearFlagCount({gid: groupId, messageId: message.id}, undefined, function(data){ message.flagCount = 0; diff --git a/website/public/js/controllers/userCtrl.js b/website/public/js/controllers/userCtrl.js index 81c1958953..a31f10cc86 100644 --- a/website/public/js/controllers/userCtrl.js +++ b/website/public/js/controllers/userCtrl.js @@ -1,10 +1,13 @@ "use strict"; -habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http', '$state', 'Guide', 'Shared', - function($rootScope, $scope, $location, User, $http, $state, Guide, Shared) { +habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http', '$state', 'Guide', 'Shared', 'Content', 'Stats', + function($rootScope, $scope, $location, User, $http, $state, Guide, Shared, Content, Stats) { $scope.profile = User.user; $scope.profile.petCount = Shared.countPets($rootScope.countExists($scope.profile.items.pets), $scope.profile.items.pets); $scope.profile.mountCount = Shared.countMounts($rootScope.countExists($scope.profile.items.mounts), $scope.profile.items.mounts); + + $scope.statCalc = Stats; + $scope.hideUserAvatar = function() { $(".userAvatar").hide(); }; diff --git a/website/views/shared/profiles/stats.jade b/website/views/shared/profiles/stats.jade index 686e070965..7a7f2a737b 100644 --- a/website/views/shared/profiles/stats.jade +++ b/website/views/shared/profiles/stats.jade @@ -1,90 +1,71 @@ +mixin basicRow(label, value) + tr&attributes(attributes) + td + strong=env.t(label) + | : #{value} + +mixin statList(calculatedStat, popover, text, useOneTimeBinding) + - var binding = useOneTimeBinding ? "::" : "" + li(ng-if=binding + '#{calculatedStat} > 0') + span.hint(popover-title=env.t('#{popover}'), popover-trigger='mouseenter', + popover-placement='top', popover=env.t('#{popover}Text')) + =env.t(text) + =': {{' + binding + calculatedStat + '}}' + h4(class=mobile?'item item-divider':'')=env.t('stats') table.table.table-striped - tr - td - strong=env.t('health') - | : {{Math.ceil(profile.stats.hp)}} / {{::Shared.maxHealth}} - tr(ng-if='profile.stats.lvl >= 10 && !profile.preferences.disableClasses') - td - strong=env.t('mana') - | : {{Math.floor(profile.stats.mp)}} / {{profile._statsComputed.maxMP}} - tr - td - strong=env.t('gold') - | : {{Math.floor(profile.stats.gp)}} - tr - td - strong=env.t('level') - | : {{profile.stats.lvl}} - tr - td - strong=env.t('experience') - | : {{Math.floor(profile.stats.exp)}} / {{Shared.tnl(profile.stats.lvl)}} + +basicRow('health', '{{::statCalc.hpDisplay(profile.stats.hp)}}') + +basicRow('mana', '{{statCalc.mpDisplay(profile)}}')(ng-if='profile.stats.lvl >= 10 && !profile.preferences.disableClasses') + +basicRow('gold', '{{::statCalc.goldDisplay(profile.stats.gp)}}') + +basicRow('level', '{{::profile.stats.lvl}}') + +basicRow('experience', '{{::statCalc.expDisplay(profile)}}') unless mobile - h4.stats-equipment(class=mobile?'item item-divider':'',ng-show='user.flags.itemsEnabled')=env.t('equipment') + h4.stats-equipment(class=mobile?'item item-divider':'', + ng-show='user.flags.itemsEnabled')=env.t('equipment') table.table.table-striped(ng-show='user.flags.itemsEnabled') - tr(ng-repeat='(k,v) in profile.items.gear.equipped', ng-init='piece=Content.gear.flat[v]', ng-show='piece') + tr(ng-repeat='(itemType,gear) in profile.items.gear.equipped', + ng-init='piece=Content.gear.flat[gear]', ng-show='piece') td strong {{piece.text()}}:  span(ng-repeat='stat in ["str","con","per","int"]', ng-show='piece[stat]') {{piece[stat]}} {{stat.toUpperCase()}}  h4(class=mobile?'item item-divider':'')=env.t('attributes') + table.table.table-striped - each v,k in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } + each statInfo, stat in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } tr td - span.hint(popover-title=env.t(v.title), popover-placement='right', popover=env.t(v.popover), popover-trigger='mouseenter', style='margin-right:3px') - strong=env.t(v.title) - span - strong : {{profile._statsComputed.#{k}}} - td - ul.list-unstyled(ng-init='g=Content.gear.flat;e=profile.items.gear.equipped') - li(ng-show='profile.stats.lvl > 1') - span.hint(popover-title=env.t('levelBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('levelBonusText'))=env.t('level') - |: {{Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2)}}  - li(ng-show='g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} > 0') - span.hint(popover-title=env.t('equipment'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('equipmentBonusText'))=env.t('equipment') - |: {{g[e.weapon].#{k} + g[e.armor].#{k} + g[e.head].#{k} + g[e.shield].#{k} || 0}}  - li(ng-show='profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1, 100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k} > 0') - span.hint(popover-title=env.t('classBonus'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('classBonusText'))=env.t('classEquipBonus') - |: {{profile._statsComputed.#{k} - profile.stats.buffs.#{k} - Math.ceil((Math.min(profile.stats.lvl - 1,100)) / 2) - g[e.weapon].#{k} - g[e.armor].#{k} - g[e.head].#{k} - g[e.shield].#{k} - profile.stats.#{k}}}  - li(ng-show='profile.stats.#{k} > 0') - span.hint(popover-title=env.t('allocatedPoints'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('allocatedPointsText'))=env.t('allocated') - |: {{profile.stats.#{k} || 0}}  - li(ng-show='profile.stats.buffs.#{k} > 0') - span.hint(popover-title=env.t('buffs'), popover-trigger='mouseenter', popover-placement='top', popover=env.t('buffsText'))=env.t('buffs') - |: {{profile.stats.buffs.#{k} || 0}}  + span.hint(popover-title=env.t(statInfo.title), popover-placement='right', + popover=env.t(statInfo.popover), popover-trigger='mouseenter') + strong=env.t(statInfo.title) + strong : {{profile._statsComputed.#{stat}}} + + td: ul.list-unstyled + +statList('statCalc.levelBonus(profile.stats.lvl)', 'levelBonus', 'level', true) + +statList('statCalc.equipmentStatBonus("' + stat + '", profile.items.gear.equipped)', 'equipmentBonus', 'equipment', true) + +statList('statCalc.classBonus(profile, "' + stat + '")', 'classBonus', 'classEquipBonus') + +statList('profile.stats.' + stat, 'allocatedPoints', 'allocated') + +statList('profile.stats.buffs.' + stat, 'buffs', 'buffs', true) + tr(ng-if='profile.stats.buffs.stealth') - td - span.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', popover-placement='right', popover=env.t('stealthNewDay')) - strong - =env.t('stealth') + td(colspan='2') + strong.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', + popover-placement='right', popover=env.t('stealthNewDay')) + =env.t('stealth') strong : {{profile.stats.buffs.stealth}}  - td tr(ng-if='profile.stats.buffs.streaks') - td - strong.hint(popover-title=env.t('streaksFrozen'), popover-trigger='mouseenter', popover-placement='right', popover=env.t('streaksFrozenText'))=env.t('streaksFrozen') - td + td(colspan='2') + strong.hint(popover-title=env.t('streaksFrozen'), popover-trigger='mouseenter', + popover-placement='right', popover=env.t('streaksFrozenText')) + =env.t('streaksFrozen') h4(class=mobile?'item item-divider':'',ng-if='user.flags.dropsEnabled')=env.t('pets') table.table.table-striped(ng-if='user.flags.dropsEnabled') - tr - td - strong=env.t('petsFound') - | : {{_.size(profile.items.pets)}} - tr - td - strong=env.t('beastMasterProgress') - | : {{profile.petCount}}/90 + +basicRow('petsFound','{{_.size(profile.items.pets)}}') + +basicRow('beastMasterProgress','{{profile.petCount}}/90') h4(class=mobile?'item item-divider':'', ng-if='user.flags.dropsEnabled')=env.t('mounts') table.table.table-striped(ng-if='user.flags.dropsEnabled') - tr - td - strong=env.t('mountsTamed') - | : {{_.size(profile.items.mounts)}} - tr - td - strong=env.t('mountMasterProgress') - | : {{profile.mountCount}}/90 + +basicRow('mountsTamed','{{_.size(profile.items.mounts)}}') + +basicRow('mountMasterProgress','{{profile.mountCount}}/90') From d44dbef85957c47a56967afd03b01228d566e6c0 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 15:29:00 -0500 Subject: [PATCH 21/35] Move member modal controller to own file --- karma.conf.js | 1 + website/public/js/controllers/groupsCtrl.js | 64 ------------------ .../public/js/controllers/memberModalCtrl.js | 66 +++++++++++++++++++ website/public/manifest.json | 1 + 4 files changed, 68 insertions(+), 64 deletions(-) create mode 100644 website/public/js/controllers/memberModalCtrl.js diff --git a/karma.conf.js b/karma.conf.js index bbb3bb45a8..9f5fe99f30 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -73,6 +73,7 @@ module.exports = function(config) { "website/public/js/directives/when-scrolled.directive.js", "website/public/js/controllers/authCtrl.js", + "website/public/js/controllers/memberModalCtrl.js", "website/public/js/controllers/menuCtrl.js", "website/public/js/controllers/notificationCtrl.js", "website/public/js/controllers/rootCtrl.js", diff --git a/website/public/js/controllers/groupsCtrl.js b/website/public/js/controllers/groupsCtrl.js index f7b05701d4..fab6dae3f6 100644 --- a/website/public/js/controllers/groupsCtrl.js +++ b/website/public/js/controllers/groupsCtrl.js @@ -159,70 +159,6 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' }; }]) - .controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups', 'Chat', '$controller', 'Stats', - function($scope, $rootScope, Members, Shared, $http, Notification, Groups, Chat, $controller, Stats) { - - $controller('RootCtrl', {$scope: $scope}); - - $scope.timestamp = function(timestamp){ - return moment(timestamp).format($rootScope.User.user.preferences.dateFormat.toUpperCase()); - } - - $scope.statCalc = Stats; - - // We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here - $scope.$watch( function() { return Members.selectedMember; }, function (member) { - if(member) { - member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets); - member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts); - $scope.profile = member; - } - }); - - $scope.sendPrivateMessage = function(uuid, message){ - // Don't do anything if the user somehow gets here without a message. - if (!message) return; - - $http.post('/api/v2/members/'+uuid+'/message',{message:message}).success(function(){ - Notification.text(window.env.t('messageSentAlert')); - $rootScope.User.sync(); - $scope.$close(); - }); - }; - - $scope.gift = { - type: 'gems', - gems: {amount:0, fromBalance:true}, - subscription: {key:''}, - message:'' - }; - - $scope.sendGift = function(uuid, gift){ - $http.post('/api/v2/members/'+uuid+'/gift', gift).success(function(){ - Notification.text('Gift sent!') - $rootScope.User.sync(); - $scope.$close(); - }) - }; - - $scope.reportAbuse = function(reporter, message, groupId) { - message.flags[reporter._id] = true; - Chat.utils.flagChatMessage({gid: groupId, messageId: message.id}, undefined, function(data){ - Notification.text(window.env.t('abuseReported')); - $scope.$close(); - }); - }; - - $scope.clearFlagCount = function(message, groupId) { - Chat.utils.clearFlagCount({gid: groupId, messageId: message.id}, undefined, function(data){ - message.flagCount = 0; - Notification.text("Flags cleared"); - $scope.$close(); - }); - } - } - ]) - .controller('AutocompleteCtrl', ['$scope', '$timeout', 'Groups', 'User', 'InputCaret', function ($scope,$timeout,Groups,User,InputCaret) { $scope.clearUserlist = function() { $scope.response = []; diff --git a/website/public/js/controllers/memberModalCtrl.js b/website/public/js/controllers/memberModalCtrl.js new file mode 100644 index 0000000000..f5cb70a77d --- /dev/null +++ b/website/public/js/controllers/memberModalCtrl.js @@ -0,0 +1,66 @@ +"use strict"; + +habitrpg + .controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups', 'Chat', '$controller', 'Stats', + function($scope, $rootScope, Members, Shared, $http, Notification, Groups, Chat, $controller, Stats) { + + $controller('RootCtrl', {$scope: $scope}); + + $scope.timestamp = function(timestamp){ + return moment(timestamp).format($rootScope.User.user.preferences.dateFormat.toUpperCase()); + } + + $scope.statCalc = Stats; + + // We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here + $scope.$watch( function() { return Members.selectedMember; }, function (member) { + if(member) { + member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets); + member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts); + $scope.profile = member; + } + }); + + $scope.sendPrivateMessage = function(uuid, message){ + // Don't do anything if the user somehow gets here without a message. + if (!message) return; + + $http.post('/api/v2/members/'+uuid+'/message',{message:message}).success(function(){ + Notification.text(window.env.t('messageSentAlert')); + $rootScope.User.sync(); + $scope.$close(); + }); + }; + + $scope.gift = { + type: 'gems', + gems: {amount:0, fromBalance:true}, + subscription: {key:''}, + message:'' + }; + + $scope.sendGift = function(uuid, gift){ + $http.post('/api/v2/members/'+uuid+'/gift', gift).success(function(){ + Notification.text('Gift sent!') + $rootScope.User.sync(); + $scope.$close(); + }) + }; + + $scope.reportAbuse = function(reporter, message, groupId) { + message.flags[reporter._id] = true; + Chat.utils.flagChatMessage({gid: groupId, messageId: message.id}, undefined, function(data){ + Notification.text(window.env.t('abuseReported')); + $scope.$close(); + }); + }; + + $scope.clearFlagCount = function(message, groupId) { + Chat.utils.clearFlagCount({gid: groupId, messageId: message.id}, undefined, function(data){ + message.flagCount = 0; + Notification.text("Flags cleared"); + $scope.$close(); + }); + } + } + ]); diff --git a/website/public/manifest.json b/website/public/manifest.json index 7d4189887a..3abf41969d 100644 --- a/website/public/manifest.json +++ b/website/public/manifest.json @@ -71,6 +71,7 @@ "js/controllers/authCtrl.js", "js/controllers/menuCtrl.js", + "js/controllers/memberModalCtrl.js", "js/controllers/notificationCtrl.js", "js/controllers/rootCtrl.js", "js/controllers/settingsCtrl.js", From 9994b27f1e57af12e312d673d8a3e9152c8ed3b2 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 15:44:32 -0500 Subject: [PATCH 22/35] Fix member modal on static/front --- website/public/js/static.js | 7 +++---- website/public/manifest.json | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/website/public/js/static.js b/website/public/js/static.js index 6494602e45..7c2853a81a 100644 --- a/website/public/js/static.js +++ b/website/public/js/static.js @@ -6,11 +6,12 @@ window.habitrpg = angular.module('habitrpg', ['chieffancypants.loadingBar', 'ui. .constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings') .constant("MOBILE_APP", false) -.controller("RootCtrl", ['$scope', '$location', '$modal', '$http', function($scope, $location, $modal, $http){ +.controller("RootCtrl", ['$scope', '$location', '$modal', '$http', 'Stats', function($scope, $location, $modal, $http, Stats){ var memberId = $location.search()['memberId']; if (memberId) { $http.get('/api/v2/members/'+memberId).success(function(data, status, headers, config){ - $scope.profile = data; + $scope.profile = window.habitrpgShared.wrap(data, false); + $scope.statCalc = Stats; $scope.Content = window.habitrpgShared.content; $modal.open({ templateUrl: 'modals/member.html', @@ -18,8 +19,6 @@ window.habitrpg = angular.module('habitrpg', ['chieffancypants.loadingBar', 'ui. }); }) } - - $scope.Math = window.Math; }]) .controller("PlansCtrl", ['$rootScope','Analytics', diff --git a/website/public/manifest.json b/website/public/manifest.json index 3abf41969d..848437642a 100644 --- a/website/public/manifest.json +++ b/website/public/manifest.json @@ -113,6 +113,8 @@ "js/static.js", "js/services/analyticsServices.js", "js/services/notificationServices.js", + "js/services/sharedServices.js", + "js/services/statServices.js", "common/script/public/userServices.js", "js/controllers/authCtrl.js", "js/controllers/footerCtrl.js" @@ -140,6 +142,8 @@ "js/static.js", "js/services/analyticsServices.js", "js/services/notificationServices.js", + "js/services/sharedServices.js", + "js/services/statServices.js", "common/script/public/userServices.js", "js/controllers/authCtrl.js", "js/controllers/footerCtrl.js" From 4cff85784de2536b763e7767a2bb8a18cffc1082 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 18 Jul 2015 15:57:25 -0500 Subject: [PATCH 23/35] Move stats to separate partials --- website/views/shared/profiles/stats.jade | 61 ++----------------- .../shared/profiles/stats/attributes.jade | 29 +++++++++ .../shared/profiles/stats/basic-stats.jade | 7 +++ .../shared/profiles/stats/equipment.jade | 9 +++ .../profiles/stats/pets-and-mounts.jade | 12 ++++ 5 files changed, 61 insertions(+), 57 deletions(-) create mode 100644 website/views/shared/profiles/stats/attributes.jade create mode 100644 website/views/shared/profiles/stats/basic-stats.jade create mode 100644 website/views/shared/profiles/stats/equipment.jade create mode 100644 website/views/shared/profiles/stats/pets-and-mounts.jade diff --git a/website/views/shared/profiles/stats.jade b/website/views/shared/profiles/stats.jade index 7a7f2a737b..c82674f731 100644 --- a/website/views/shared/profiles/stats.jade +++ b/website/views/shared/profiles/stats.jade @@ -12,60 +12,7 @@ mixin statList(calculatedStat, popover, text, useOneTimeBinding) =env.t(text) =': {{' + binding + calculatedStat + '}}' -h4(class=mobile?'item item-divider':'')=env.t('stats') -table.table.table-striped - +basicRow('health', '{{::statCalc.hpDisplay(profile.stats.hp)}}') - +basicRow('mana', '{{statCalc.mpDisplay(profile)}}')(ng-if='profile.stats.lvl >= 10 && !profile.preferences.disableClasses') - +basicRow('gold', '{{::statCalc.goldDisplay(profile.stats.gp)}}') - +basicRow('level', '{{::profile.stats.lvl}}') - +basicRow('experience', '{{::statCalc.expDisplay(profile)}}') - -unless mobile - h4.stats-equipment(class=mobile?'item item-divider':'', - ng-show='user.flags.itemsEnabled')=env.t('equipment') - table.table.table-striped(ng-show='user.flags.itemsEnabled') - tr(ng-repeat='(itemType,gear) in profile.items.gear.equipped', - ng-init='piece=Content.gear.flat[gear]', ng-show='piece') - td - strong {{piece.text()}}:  - span(ng-repeat='stat in ["str","con","per","int"]', ng-show='piece[stat]') {{piece[stat]}} {{stat.toUpperCase()}}  - -h4(class=mobile?'item item-divider':'')=env.t('attributes') - -table.table.table-striped - each statInfo, stat in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } - tr - td - span.hint(popover-title=env.t(statInfo.title), popover-placement='right', - popover=env.t(statInfo.popover), popover-trigger='mouseenter') - strong=env.t(statInfo.title) - strong : {{profile._statsComputed.#{stat}}} - - td: ul.list-unstyled - +statList('statCalc.levelBonus(profile.stats.lvl)', 'levelBonus', 'level', true) - +statList('statCalc.equipmentStatBonus("' + stat + '", profile.items.gear.equipped)', 'equipmentBonus', 'equipment', true) - +statList('statCalc.classBonus(profile, "' + stat + '")', 'classBonus', 'classEquipBonus') - +statList('profile.stats.' + stat, 'allocatedPoints', 'allocated') - +statList('profile.stats.buffs.' + stat, 'buffs', 'buffs', true) - - tr(ng-if='profile.stats.buffs.stealth') - td(colspan='2') - strong.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', - popover-placement='right', popover=env.t('stealthNewDay')) - =env.t('stealth') - strong : {{profile.stats.buffs.stealth}}  - tr(ng-if='profile.stats.buffs.streaks') - td(colspan='2') - strong.hint(popover-title=env.t('streaksFrozen'), popover-trigger='mouseenter', - popover-placement='right', popover=env.t('streaksFrozenText')) - =env.t('streaksFrozen') - -h4(class=mobile?'item item-divider':'',ng-if='user.flags.dropsEnabled')=env.t('pets') -table.table.table-striped(ng-if='user.flags.dropsEnabled') - +basicRow('petsFound','{{_.size(profile.items.pets)}}') - +basicRow('beastMasterProgress','{{profile.petCount}}/90') - -h4(class=mobile?'item item-divider':'', ng-if='user.flags.dropsEnabled')=env.t('mounts') -table.table.table-striped(ng-if='user.flags.dropsEnabled') - +basicRow('mountsTamed','{{_.size(profile.items.mounts)}}') - +basicRow('mountMasterProgress','{{profile.mountCount}}/90') +include ./stats/basic-stats +include ./stats/equipment +include ./stats/attributes +include ./stats/pets-and-mounts diff --git a/website/views/shared/profiles/stats/attributes.jade b/website/views/shared/profiles/stats/attributes.jade new file mode 100644 index 0000000000..0d222a42b4 --- /dev/null +++ b/website/views/shared/profiles/stats/attributes.jade @@ -0,0 +1,29 @@ +h4(class=mobile?'item item-divider':'')=env.t('attributes') + +table.table.table-striped + each statInfo, stat in { str: {title:"strength",popover:'strengthText'},int: {title:"intelligence",popover:'intText'},con: {title:"constitution",popover:'conText'},per: {title:"perception",popover:'perText'} } + tr + td + span.hint(popover-title=env.t(statInfo.title), popover-placement='right', + popover=env.t(statInfo.popover), popover-trigger='mouseenter') + strong=env.t(statInfo.title) + strong : {{profile._statsComputed.#{stat}}} + + td: ul.list-unstyled + +statList('statCalc.levelBonus(profile.stats.lvl)', 'levelBonus', 'level', true) + +statList('statCalc.equipmentStatBonus("' + stat + '", profile.items.gear.equipped)', 'equipmentBonus', 'equipment', true) + +statList('statCalc.classBonus(profile, "' + stat + '")', 'classBonus', 'classEquipBonus') + +statList('profile.stats.' + stat, 'allocatedPoints', 'allocated') + +statList('profile.stats.buffs.' + stat, 'buffs', 'buffs', true) + + tr(ng-if='profile.stats.buffs.stealth') + td(colspan='2') + strong.hint(popover-title=env.t('stealth'), popover-trigger='mouseenter', + popover-placement='right', popover=env.t('stealthNewDay')) + =env.t('stealth') + strong : {{profile.stats.buffs.stealth}}  + tr(ng-if='profile.stats.buffs.streaks') + td(colspan='2') + strong.hint(popover-title=env.t('streaksFrozen'), popover-trigger='mouseenter', + popover-placement='right', popover=env.t('streaksFrozenText')) + =env.t('streaksFrozen') diff --git a/website/views/shared/profiles/stats/basic-stats.jade b/website/views/shared/profiles/stats/basic-stats.jade new file mode 100644 index 0000000000..694e7408fb --- /dev/null +++ b/website/views/shared/profiles/stats/basic-stats.jade @@ -0,0 +1,7 @@ +h4(class=mobile?'item item-divider':'')=env.t('stats') +table.table.table-striped + +basicRow('health', '{{::statCalc.hpDisplay(profile.stats.hp)}}') + +basicRow('mana', '{{statCalc.mpDisplay(profile)}}')(ng-if='profile.stats.lvl >= 10 && !profile.preferences.disableClasses') + +basicRow('gold', '{{::statCalc.goldDisplay(profile.stats.gp)}}') + +basicRow('level', '{{::profile.stats.lvl}}') + +basicRow('experience', '{{::statCalc.expDisplay(profile)}}') diff --git a/website/views/shared/profiles/stats/equipment.jade b/website/views/shared/profiles/stats/equipment.jade new file mode 100644 index 0000000000..69e4edee5b --- /dev/null +++ b/website/views/shared/profiles/stats/equipment.jade @@ -0,0 +1,9 @@ +unless mobile + h4.stats-equipment(class=mobile?'item item-divider':'', + ng-show='user.flags.itemsEnabled')=env.t('equipment') + table.table.table-striped(ng-show='user.flags.itemsEnabled') + tr(ng-repeat='(itemType,gear) in profile.items.gear.equipped', + ng-init='piece=Content.gear.flat[gear]', ng-show='piece') + td + strong {{piece.text()}}:  + span(ng-repeat='stat in ["str","con","per","int"]', ng-show='piece[stat]') {{piece[stat]}} {{stat.toUpperCase()}}  diff --git a/website/views/shared/profiles/stats/pets-and-mounts.jade b/website/views/shared/profiles/stats/pets-and-mounts.jade new file mode 100644 index 0000000000..f3bb0bef25 --- /dev/null +++ b/website/views/shared/profiles/stats/pets-and-mounts.jade @@ -0,0 +1,12 @@ +div(ng-if='user.flags.dropsEnabled') + h4(class=mobile?'item item-divider':'')=env.t('pets') + + table.table.table-striped + +basicRow('petsFound','{{_.size(profile.items.pets)}}') + +basicRow('beastMasterProgress','{{profile.petCount}}/90') + + h4(class=mobile?'item item-divider':'')=env.t('mounts') + + table.table.table-striped + +basicRow('mountsTamed','{{_.size(profile.items.mounts)}}') + +basicRow('mountMasterProgress','{{profile.mountCount}}/90') From 89bfc83b950866dc98aad760fffa8f034ca4902a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 19 Jul 2015 20:19:16 -0500 Subject: [PATCH 24/35] Organize stat functions alphabetically --- test/spec/services/statServicesSpec.js | 232 ++++++++++----------- website/public/js/services/statServices.js | 94 ++++----- 2 files changed, 163 insertions(+), 163 deletions(-) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 35e53109a1..3555fa4406 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -15,122 +15,6 @@ describe('Stats Service', function() { }); }); - describe('hpDisplay', function() { - it('displays hp as "hp / totalHP"', function() { - var hp = 34; - var hpDisplay = statCalc.hpDisplay(hp); - - expect(hpDisplay).to.eql('34/50'); - }); - - it('Rounds hp up when given a decimal', function() { - - var hp = 34.4; - var hpDisplay = statCalc.hpDisplay(hp); - - expect(hpDisplay).to.eql('35/50'); - }); - }); - - describe('mpDisplay', function() { - it('displays mp as "mp / totalMP"', function() { - user._statsComputed = { maxMP: 100 }; - user.stats.mp = 30; - var mpDisplay = statCalc.mpDisplay(user); - - expect(mpDisplay).to.eql('30/100'); - }); - - it('Rounds mp down when given a decimal', function() { - user._statsComputed = { maxMP: 100 }; - user.stats.mp = 30.99; - var mpDisplay = statCalc.mpDisplay(user); - - expect(mpDisplay).to.eql('30/100'); - }); - }); - - describe('goldDisplay', function() { - it('displays gold', function() { - var gold = 30; - var goldDisplay = statCalc.goldDisplay(gold); - - expect(goldDisplay).to.eql(30); - }); - - it('Rounds gold down when given a decimal', function() { - var gold = 30.999; - var goldDisplay = statCalc.goldDisplay(gold); - - expect(goldDisplay).to.eql(30); - }); - }); - - describe('expDisplay', function() { - it('displays exp as "exp / toNextLevelExp"', function() { - user.stats.exp = 10; - user.stats.lvl = 29; - var expDisplay = statCalc.expDisplay(user); - - expect(expDisplay).to.eql('10/640'); - }); - - it('Rounds exp down when given a decimal', function() { - user.stats.exp = 10.999; - user.stats.lvl = 29; - var expDisplay = statCalc.expDisplay(user); - - expect(expDisplay).to.eql('10/640'); - }); - }); - - describe('levelBonus', function() { - it('calculates bonus as half of level for even numbered level under 100', function() { - var level = 50; - var bonus = statCalc.levelBonus(level); - expect(bonus).to.eql(25); - }); - - it('calculates bonus as half of level, rounded down, for odd numbered level under 100', function() { - var level = 51; - var bonus = statCalc.levelBonus(level); - expect(bonus).to.eql(25); - }); - - it('calculates bonus as 50 for levels >= 100', function() { - var level = 150; - var bonus = statCalc.levelBonus(level); - expect(bonus).to.eql(50); - }); - - it('calculates bonus as 0 for level 1', function() { - var level = 1; - var bonus = statCalc.levelBonus(level); - expect(bonus).to.eql(0); - }); - }); - - describe('equipmentStatBonus', function() { - it('tallies up stats from euqipment that is equipped', function() { - var equippedGear = { - "weapon" : "weapon_special_1", - "shield" : "shield_special_1", - "head" : "head_special_1", - "armor" : "armor_special_1" - }; - - var strStat = statCalc.equipmentStatBonus('str', equippedGear); - var conStat = statCalc.equipmentStatBonus('con', equippedGear); - var intStat = statCalc.equipmentStatBonus('int', equippedGear); - var perStat = statCalc.equipmentStatBonus('per', equippedGear); - - expect(strStat).to.eql(24); - expect(conStat).to.eql(24); - expect(intStat).to.eql(24); - expect(perStat).to.eql(24); - }); - }); - describe('classBonus', function() { it('calculates class bonus', function() { var equippedGear = { @@ -179,4 +63,120 @@ describe('Stats Service', function() { expect(classBonus).to.not.exist; }); }); + + describe('expDisplay', function() { + it('displays exp as "exp / toNextLevelExp"', function() { + user.stats.exp = 10; + user.stats.lvl = 29; + var expDisplay = statCalc.expDisplay(user); + + expect(expDisplay).to.eql('10/640'); + }); + + it('Rounds exp down when given a decimal', function() { + user.stats.exp = 10.999; + user.stats.lvl = 29; + var expDisplay = statCalc.expDisplay(user); + + expect(expDisplay).to.eql('10/640'); + }); + }); + + describe('equipmentStatBonus', function() { + it('tallies up stats from euqipment that is equipped', function() { + var equippedGear = { + "weapon" : "weapon_special_1", + "shield" : "shield_special_1", + "head" : "head_special_1", + "armor" : "armor_special_1" + }; + + var strStat = statCalc.equipmentStatBonus('str', equippedGear); + var conStat = statCalc.equipmentStatBonus('con', equippedGear); + var intStat = statCalc.equipmentStatBonus('int', equippedGear); + var perStat = statCalc.equipmentStatBonus('per', equippedGear); + + expect(strStat).to.eql(24); + expect(conStat).to.eql(24); + expect(intStat).to.eql(24); + expect(perStat).to.eql(24); + }); + }); + + describe('goldDisplay', function() { + it('displays gold', function() { + var gold = 30; + var goldDisplay = statCalc.goldDisplay(gold); + + expect(goldDisplay).to.eql(30); + }); + + it('Rounds gold down when given a decimal', function() { + var gold = 30.999; + var goldDisplay = statCalc.goldDisplay(gold); + + expect(goldDisplay).to.eql(30); + }); + }); + + describe('hpDisplay', function() { + it('displays hp as "hp / totalHP"', function() { + var hp = 34; + var hpDisplay = statCalc.hpDisplay(hp); + + expect(hpDisplay).to.eql('34/50'); + }); + + it('Rounds hp up when given a decimal', function() { + + var hp = 34.4; + var hpDisplay = statCalc.hpDisplay(hp); + + expect(hpDisplay).to.eql('35/50'); + }); + }); + + describe('levelBonus', function() { + it('calculates bonus as half of level for even numbered level under 100', function() { + var level = 50; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(25); + }); + + it('calculates bonus as half of level, rounded down, for odd numbered level under 100', function() { + var level = 51; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(25); + }); + + it('calculates bonus as 50 for levels >= 100', function() { + var level = 150; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(50); + }); + + it('calculates bonus as 0 for level 1', function() { + var level = 1; + var bonus = statCalc.levelBonus(level); + expect(bonus).to.eql(0); + }); + }); + + describe('mpDisplay', function() { + it('displays mp as "mp / totalMP"', function() { + user._statsComputed = { maxMP: 100 }; + user.stats.mp = 30; + var mpDisplay = statCalc.mpDisplay(user); + + expect(mpDisplay).to.eql('30/100'); + }); + + it('Rounds mp down when given a decimal', function() { + user._statsComputed = { maxMP: 100 }; + user.stats.mp = 30.99; + var mpDisplay = statCalc.mpDisplay(user); + + expect(mpDisplay).to.eql('30/100'); + }); + }); }); diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index e7ec65eda8..53ba032de5 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -12,45 +12,18 @@ function statsFactory(Content, Shared) { - function hpDisplay(hp) { - var remainingHP = Math.ceil(hp); - var totalHP = Shared.maxHealth; - var display = _formatOutOfTotalDisplay(remainingHP, totalHP); + function classBonus(user, stat) { + var computedStats = user._statsComputed; - return display; - } + if(computedStats) { + var bonus = computedStats[stat] + - user.stats.buffs[stat] + - levelBonus(user.stats.lvl) + - equipmentStatBonus(stat, user.items.gear.equipped) + - user.stats[stat]; - function goldDisplay(gold) { - var display = Math.floor(gold); - return display; - } - - function mpDisplay(user) { - var remainingMP = Math.floor(user.stats.mp); - var totalMP = user._statsComputed.maxMP; - var display = _formatOutOfTotalDisplay(remainingMP, totalMP); - - return display; - } - - function expDisplay(user) { - var exp = Math.floor(user.stats.exp); - var toNextLevel = Shared.tnl(user.stats.lvl); - var display = _formatOutOfTotalDisplay(exp, toNextLevel); - - return display; - } - - function levelBonus(level) { - // Level bonus is derived by taking the level, subtracting one, - // taking the smaller of it or maxLevel (100), - // dividing that by two and then raising it to a whole number - - var levelOrMaxLevel = Math.min((level - 1), Shared.maxLevel); - var levelDividedByTwo = levelOrMaxLevel / 2; - var bonus = Math.ceil(levelDividedByTwo ); - - return bonus; + return bonus; + } } function equipmentStatBonus(stat, equipped) { @@ -71,18 +44,45 @@ return total; } - function classBonus(user, stat) { - var computedStats = user._statsComputed; + function expDisplay(user) { + var exp = Math.floor(user.stats.exp); + var toNextLevel = Shared.tnl(user.stats.lvl); + var display = _formatOutOfTotalDisplay(exp, toNextLevel); - if(computedStats) { - var bonus = computedStats[stat] - - user.stats.buffs[stat] - - levelBonus(user.stats.lvl) - - equipmentStatBonus(stat, user.items.gear.equipped) - - user.stats[stat]; + return display; + } - return bonus; - } + function goldDisplay(gold) { + var display = Math.floor(gold); + return display; + } + + function hpDisplay(hp) { + var remainingHP = Math.ceil(hp); + var totalHP = Shared.maxHealth; + var display = _formatOutOfTotalDisplay(remainingHP, totalHP); + + return display; + } + + function levelBonus(level) { + // Level bonus is derived by taking the level, subtracting one, + // taking the smaller of it or maxLevel (100), + // dividing that by two and then raising it to a whole number + + var levelOrMaxLevel = Math.min((level - 1), Shared.maxLevel); + var levelDividedByTwo = levelOrMaxLevel / 2; + var bonus = Math.ceil(levelDividedByTwo ); + + return bonus; + } + + function mpDisplay(user) { + var remainingMP = Math.floor(user.stats.mp); + var totalMP = user._statsComputed.maxMP; + var display = _formatOutOfTotalDisplay(remainingMP, totalMP); + + return display; } function _formatOutOfTotalDisplay(stat, totalStat) { From aee37b2a0ebe3866fe665a141747fd3a82c69c54 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 19 Jul 2015 20:40:15 -0500 Subject: [PATCH 25/35] Swap out pet and mount count with stat calc functions --- test/spec/services/statServicesSpec.js | 84 +++++++++++++++++++ website/public/js/services/statServices.js | 16 +++- .../profiles/stats/pets-and-mounts.jade | 4 +- 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 3555fa4406..3e442c4f94 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -179,4 +179,88 @@ describe('Stats Service', function() { expect(mpDisplay).to.eql('30/100'); }); }); + + describe('totalPetCount', function() { + it('counts all pets that user has', function() { + user.items.pets = { + "BearCub-Base" : 5, + "BearCub-CottonCandyBlue" : 5, + "Cactus-Zombie" : 5, + "Deer-Golden" : 5, + "Deer-Red" : 5, + "Egg-Desert" : 5, + "MantisShrimp-Base" : 5 + } + + var petsFound = statCalc.totalPetCount(user.items.pets); + + expect(petsFound).to.eql(7); + }); + + it('includes pets that have a value of 0', function() { + user.items.pets = { + "BearCub-Base" : 0, + "BearCub-CottonCandyBlue" : 5, + "Cactus-Zombie" : 0, + "Deer-Golden" : 0, + "Deer-Red" : 0, + "Egg-Desert" : 0, + "MantisShrimp-Base" : 5 + } + + var petsFound = statCalc.totalPetCount(user.items.pets); + + expect(petsFound).to.eql(7); + }); + + it('includes pets that have a value of -1', function() { + user.items.pets = { + "BearCub-Base" : -1, + "BearCub-CottonCandyBlue" : 5, + "Cactus-Zombie" : -1, + "Deer-Golden" : -1, + "Deer-Red" : -1, + "Egg-Desert" : -1, + "MantisShrimp-Base" : 5 + } + + var petsFound = statCalc.totalPetCount(user.items.pets); + + expect(petsFound).to.eql(7); + }); + }); + + describe('totalMountCount', function() { + it('counts all mounts that user has', function() { + user.items.mounts = { + "Hedgehog-Desert" : true, + "Octopus-CottonCandyPink" : true, + "TigerCub-White" : true, + "Wolf-Golden" : true, + "Owl-CottonCandyBlue" : true, + "Mammoth-Base" : true, + "Bunny-Skeleton" : true + } + + var mountsFound = statCalc.totalMountCount(user.items.mounts); + + expect(mountsFound).to.eql(7); + }); + + it('inlcudes mounts with a value of false', function() { + user.items.mounts = { + "Hedgehog-Desert" : false, + "Octopus-CottonCandyPink" : true, + "TigerCub-White" : false, + "Wolf-Golden" : false, + "Owl-CottonCandyBlue" : false, + "Mammoth-Base" : true, + "Bunny-Skeleton" : false + } + + var mountsFound = statCalc.totalMountCount(user.items.mounts); + + expect(mountsFound).to.eql(7); + }); + }); }); diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 53ba032de5..7ee6df2428 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -85,6 +85,18 @@ return display; } + function totalPetCount(pets) { + var total = _.size(pets); + + return total; + } + + function totalMountCount(mounts) { + var total = _.size(mounts); + + return total; + } + function _formatOutOfTotalDisplay(stat, totalStat) { var display = stat + "/" + totalStat; return display; @@ -97,7 +109,9 @@ goldDisplay: goldDisplay, hpDisplay: hpDisplay, levelBonus: levelBonus, - mpDisplay: mpDisplay + mpDisplay: mpDisplay, + totalPetCount: totalPetCount, + totalMountCount: totalMountCount } } }()); diff --git a/website/views/shared/profiles/stats/pets-and-mounts.jade b/website/views/shared/profiles/stats/pets-and-mounts.jade index f3bb0bef25..0b693e847b 100644 --- a/website/views/shared/profiles/stats/pets-and-mounts.jade +++ b/website/views/shared/profiles/stats/pets-and-mounts.jade @@ -2,11 +2,11 @@ div(ng-if='user.flags.dropsEnabled') h4(class=mobile?'item item-divider':'')=env.t('pets') table.table.table-striped - +basicRow('petsFound','{{_.size(profile.items.pets)}}') + +basicRow('petsFound','{{::statCalc.totalPetCount(profile.items.pets)}}') +basicRow('beastMasterProgress','{{profile.petCount}}/90') h4(class=mobile?'item item-divider':'')=env.t('mounts') table.table.table-striped - +basicRow('mountsTamed','{{_.size(profile.items.mounts)}}') + +basicRow('mountsTamed','{{::statCalc.totalPetCount(profile.items.mounts)}}') +basicRow('mountMasterProgress','{{profile.mountCount}}/90') From 3643d11d97d8f610776fbb0c1196d6a537c48ca9 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 19 Jul 2015 20:56:14 -0500 Subject: [PATCH 26/35] Refactor pet and mount count into one method --- test/spec/services/statServicesSpec.js | 14 ++++++-------- website/public/js/services/statServices.js | 18 ++++++++---------- .../shared/profiles/stats/pets-and-mounts.jade | 4 ++-- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 3e442c4f94..2dd65a3ccd 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -180,7 +180,7 @@ describe('Stats Service', function() { }); }); - describe('totalPetCount', function() { + describe('totalCount', function() { it('counts all pets that user has', function() { user.items.pets = { "BearCub-Base" : 5, @@ -192,7 +192,7 @@ describe('Stats Service', function() { "MantisShrimp-Base" : 5 } - var petsFound = statCalc.totalPetCount(user.items.pets); + var petsFound = statCalc.totalCount(user.items.pets); expect(petsFound).to.eql(7); }); @@ -208,7 +208,7 @@ describe('Stats Service', function() { "MantisShrimp-Base" : 5 } - var petsFound = statCalc.totalPetCount(user.items.pets); + var petsFound = statCalc.totalCount(user.items.pets); expect(petsFound).to.eql(7); }); @@ -224,13 +224,11 @@ describe('Stats Service', function() { "MantisShrimp-Base" : 5 } - var petsFound = statCalc.totalPetCount(user.items.pets); + var petsFound = statCalc.totalCount(user.items.pets); expect(petsFound).to.eql(7); }); - }); - describe('totalMountCount', function() { it('counts all mounts that user has', function() { user.items.mounts = { "Hedgehog-Desert" : true, @@ -242,7 +240,7 @@ describe('Stats Service', function() { "Bunny-Skeleton" : true } - var mountsFound = statCalc.totalMountCount(user.items.mounts); + var mountsFound = statCalc.totalCount(user.items.mounts); expect(mountsFound).to.eql(7); }); @@ -258,7 +256,7 @@ describe('Stats Service', function() { "Bunny-Skeleton" : false } - var mountsFound = statCalc.totalMountCount(user.items.mounts); + var mountsFound = statCalc.totalCount(user.items.mounts); expect(mountsFound).to.eql(7); }); diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 7ee6df2428..55affe670a 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -12,6 +12,10 @@ function statsFactory(Content, Shared) { + function beastMasterProgress(pets) { + + } + function classBonus(user, stat) { var computedStats = user._statsComputed; @@ -85,14 +89,8 @@ return display; } - function totalPetCount(pets) { - var total = _.size(pets); - - return total; - } - - function totalMountCount(mounts) { - var total = _.size(mounts); + function totalCount(objectToCount) { + var total = _.size(objectToCount); return total; } @@ -103,6 +101,7 @@ } return { + beastMasterProgress: beastMasterProgress, classBonus: classBonus, equipmentStatBonus: equipmentStatBonus, expDisplay: expDisplay, @@ -110,8 +109,7 @@ hpDisplay: hpDisplay, levelBonus: levelBonus, mpDisplay: mpDisplay, - totalPetCount: totalPetCount, - totalMountCount: totalMountCount + totalCount: totalCount } } }()); diff --git a/website/views/shared/profiles/stats/pets-and-mounts.jade b/website/views/shared/profiles/stats/pets-and-mounts.jade index 0b693e847b..3bb2c10b1d 100644 --- a/website/views/shared/profiles/stats/pets-and-mounts.jade +++ b/website/views/shared/profiles/stats/pets-and-mounts.jade @@ -2,11 +2,11 @@ div(ng-if='user.flags.dropsEnabled') h4(class=mobile?'item item-divider':'')=env.t('pets') table.table.table-striped - +basicRow('petsFound','{{::statCalc.totalPetCount(profile.items.pets)}}') + +basicRow('petsFound','{{::statCalc.totalCount(profile.items.pets)}}') +basicRow('beastMasterProgress','{{profile.petCount}}/90') h4(class=mobile?'item item-divider':'')=env.t('mounts') table.table.table-striped - +basicRow('mountsTamed','{{::statCalc.totalPetCount(profile.items.mounts)}}') + +basicRow('mountsTamed','{{::statCalc.totalCount(profile.items.mounts)}}') +basicRow('mountMasterProgress','{{profile.mountCount}}/90') From 2695419182e2df279b5b1587124f1b066b083dab Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sun, 19 Jul 2015 21:48:38 -0500 Subject: [PATCH 27/35] Use better beastMaster / mountMaster counts --- common/script/index.coffee | 18 ++++ test/spec/services/statServicesSpec.js | 84 +++++++++++++++++++ website/public/js/services/statServices.js | 13 +++ .../profiles/stats/pets-and-mounts.jade | 4 +- 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 88402eeaf4..57e879f776 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -386,6 +386,24 @@ api.countPets = (originalCount, pets) -> count-- if pets[pet] count +DROP_ANIMALS = _.keys(content.pets) + +api.countBeastMasterProgress = (pets) -> + count = 0 + for animal in DROP_ANIMALS + if pets[animal] > 0 || pets[animal] == -1 + count++ + + count + +api.countMountMasterProgress = (mounts) -> + count = 0 + for animal in DROP_ANIMALS + if mounts[animal] + count++ + + count + api.countMounts = (originalCount, mounts) -> count2 = if originalCount? then originalCount else _.size(mounts) for mount of content.questPets diff --git a/test/spec/services/statServicesSpec.js b/test/spec/services/statServicesSpec.js index 2dd65a3ccd..8a1694b16a 100644 --- a/test/spec/services/statServicesSpec.js +++ b/test/spec/services/statServicesSpec.js @@ -15,6 +15,56 @@ describe('Stats Service', function() { }); }); + describe('beastMasterProgress', function() { + it('counts drop pets that user has', function() { + user.items.pets = { + "BearCub-Base" : 5, + "BearCub-CottonCandyBlue" : 5, + "Cactus-Zombie" : 5, + "Deer-Golden" : 5, + "Deer-Red" : 5, + "Egg-Desert" : 5, + "MantisShrimp-Base" : 5 + } + + var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets); + + expect(beastMasterDisplay).to.eql('3/90'); + }); + + it('counts drop pets with a value of -1', function() { + user.items.pets = { + "BearCub-Base" : -1, + "BearCub-CottonCandyBlue" : -1, + "Cactus-Zombie" : 5, + "Deer-Golden" : 5, + "Deer-Red" : 5, + "Egg-Desert" : 5, + "MantisShrimp-Base" : 5 + } + + var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets); + + expect(beastMasterDisplay).to.eql('3/90'); + }); + + it('does not count drop pets with a value of 0', function() { + user.items.pets = { + "BearCub-Base" : 0, + "BearCub-CottonCandyBlue" : 0, + "Cactus-Zombie" : 5, + "Deer-Golden" : 5, + "Deer-Red" : 5, + "Egg-Desert" : 5, + "MantisShrimp-Base" : 5 + } + + var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets); + + expect(beastMasterDisplay).to.eql('1/90'); + }); + }); + describe('classBonus', function() { it('calculates class bonus', function() { var equippedGear = { @@ -162,6 +212,40 @@ describe('Stats Service', function() { }); }); + describe('mountMasterProgress', function() { + it('counts drop mounts that user has', function() { + user.items.mounts = { + "Hedgehog-Desert" : true, + "Octopus-CottonCandyPink" : true, + "TigerCub-White" : true, + "Wolf-Golden" : true, + "Owl-CottonCandyBlue" : true, + "Mammoth-Base" : true, + "Bunny-Skeleton" : true + } + + var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts); + + expect(mountMasterDisplay).to.eql('2/90'); + }); + + it('does not count drop mounts with a value of false', function() { + user.items.mounts = { + "Hedgehog-Desert" : true, + "Octopus-CottonCandyPink" : true, + "TigerCub-White" : false, + "Wolf-Golden" : false, + "Owl-CottonCandyBlue" : true, + "Mammoth-Base" : true, + "Bunny-Skeleton" : true + } + + var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts); + + expect(mountMasterDisplay).to.eql('0/90'); + }); + }); + describe('mpDisplay', function() { it('displays mp as "mp / totalMP"', function() { user._statsComputed = { maxMP: 100 }; diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 55affe670a..2935eaa798 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -11,9 +11,14 @@ ]; function statsFactory(Content, Shared) { + var DROP_ANIMALS = _.keys(Content.pets); + var TOTAL_NUMBER_OF_DROP_ANIMALS = DROP_ANIMALS.length; function beastMasterProgress(pets) { + var dropPetsFound = Shared.countBeastMasterProgress(pets); + var display = _formatOutOfTotalDisplay(dropPetsFound, TOTAL_NUMBER_OF_DROP_ANIMALS); + return display; } function classBonus(user, stat) { @@ -81,6 +86,13 @@ return bonus; } + function mountMasterProgress(mounts) { + var dropMountsFound = Shared.countMountMasterProgress(mounts); + var display = _formatOutOfTotalDisplay(dropMountsFound, TOTAL_NUMBER_OF_DROP_ANIMALS); + + return display; + } + function mpDisplay(user) { var remainingMP = Math.floor(user.stats.mp); var totalMP = user._statsComputed.maxMP; @@ -108,6 +120,7 @@ goldDisplay: goldDisplay, hpDisplay: hpDisplay, levelBonus: levelBonus, + mountMasterProgress: mountMasterProgress, mpDisplay: mpDisplay, totalCount: totalCount } diff --git a/website/views/shared/profiles/stats/pets-and-mounts.jade b/website/views/shared/profiles/stats/pets-and-mounts.jade index 3bb2c10b1d..3d4817d338 100644 --- a/website/views/shared/profiles/stats/pets-and-mounts.jade +++ b/website/views/shared/profiles/stats/pets-and-mounts.jade @@ -3,10 +3,10 @@ div(ng-if='user.flags.dropsEnabled') table.table.table-striped +basicRow('petsFound','{{::statCalc.totalCount(profile.items.pets)}}') - +basicRow('beastMasterProgress','{{profile.petCount}}/90') + +basicRow('beastMasterProgress','{{::statCalc.beastMasterProgress(profile.items.pets)}}') h4(class=mobile?'item item-divider':'')=env.t('mounts') table.table.table-striped +basicRow('mountsTamed','{{::statCalc.totalCount(profile.items.mounts)}}') - +basicRow('mountMasterProgress','{{profile.mountCount}}/90') + +basicRow('mountMasterProgress','{{::statCalc.mountMasterProgress(profile.items.mounts)}}') From 610f7faa5cb2c9eec9b3d61e186706350582064b Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 20 Jul 2015 08:04:03 -0500 Subject: [PATCH 28/35] Add test for count beast/mount master progress --- test/common/count.js | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/common/count.js diff --git a/test/common/count.js b/test/common/count.js new file mode 100644 index 0000000000..f3d604dfab --- /dev/null +++ b/test/common/count.js @@ -0,0 +1,87 @@ +var sinon = require('sinon'); +var chai = require("chai") +chai.use(require("sinon-chai")) +var expect = chai.expect + +require('coffee-script'); +var shared = require('../../common/script/index.coffee'); + +describe('count', function() { + describe('countBeastMasterProgress', function() { + it('returns 0 if no pets', function() { + var pets = {}; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(0); + }); + + it('counts drop pets', function() { + var pets = { "Dragon-Red": 1, "Wolf-Base": 2 }; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(2); + }); + + it('does not count quest pets', function() { + var pets = { "Dragon-Red": 1, "Gryphon-Base": 1 }; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(1); + }); + + it('does not count special pets', function() { + var pets = { + "Wolf-Base": 2, + "Wolf-Veteran": 1, + "Wolf-Cerberus": 1, + "Dragon-Hydra": 1 + }; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(1); + }); + + it('counts drop pets that have been raised to a mount', function() { + var raisedToMount = -1; + var pets = { "Dragon-Red": 1, "Wolf-Base": raisedToMount }; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(2); + }); + + it('does not counts drop pets that have been released', function() { + var releasedPet = 0; + var pets = { "Dragon-Red": 1, "Wolf-Base": releasedPet }; + var beastMasterTotal = shared.countBeastMasterProgress(pets); + expect(beastMasterTotal).to.eql(1); + }); + }); + + describe('countMountMasterProgress', function() { + it('returns 0 if no mounts', function() { + var mounts = {}; + var mountMasterTotal = shared.countMountMasterProgress(mounts); + expect(mountMasterTotal).to.eql(0); + }); + + it('counts drop mounts', function() { + var mounts = { "Dragon-Red": true, "Wolf-Base": true }; + var mountMasterTotal = shared.countMountMasterProgress(mounts); + expect(mountMasterTotal).to.eql(2); + }); + + it('does not count quest mounts', function() { + var mounts = { "Dragon-Red": true, "Gryphon-Base": true }; + var mountMasterTotal = shared.countMountMasterProgress(mounts); + expect(mountMasterTotal).to.eql(1); + }); + + it('does not count special mounts', function() { + var mounts = { "Wolf-Base": true, "BearCub-Polar": true}; + var mountMasterTotal = shared.countMountMasterProgress(mounts); + expect(mountMasterTotal).to.eql(1); + }); + + it('only counts drop mounts that are currently owned', function() { + var notCurrentlyOwned = false; + var mounts = { "Dragon-Red": true, "Wolf-Base": notCurrentlyOwned }; + var mountMasterTotal = shared.countMountMasterProgress(mounts); + expect(mountMasterTotal).to.eql(1); + }); + }); +}); From 3d40da4004baa8237853da63e5d8da8655a00af9 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 20 Jul 2015 08:11:00 -0500 Subject: [PATCH 29/35] Remove countPets and countMounts from codebase --- common/script/index.coffee | 16 ---- test/common/algos.mocha.coffee | 90 ------------------- .../public/js/controllers/inventoryCtrl.js | 2 - .../public/js/controllers/memberModalCtrl.js | 2 - website/public/js/controllers/rootCtrl.js | 3 - website/public/js/controllers/userCtrl.js | 2 - website/src/models/user.js | 13 +-- 7 files changed, 3 insertions(+), 125 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 57e879f776..9b7002bdf5 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -378,14 +378,6 @@ api.appliedTags = (userTags, taskTags) -> arr.push(t.name) if taskTags?[t.id] arr.join(', ') -api.countPets = (originalCount, pets) -> - count = if originalCount? then originalCount else _.size(pets) - for pet of content.questPets - count-- if pets[pet] - for pet of content.specialPets - count-- if pets[pet] - count - DROP_ANIMALS = _.keys(content.pets) api.countBeastMasterProgress = (pets) -> @@ -404,14 +396,6 @@ api.countMountMasterProgress = (mounts) -> count -api.countMounts = (originalCount, mounts) -> - count2 = if originalCount? then originalCount else _.size(mounts) - for mount of content.questPets - count2-- if mounts[mount] - for mount of content.specialMounts - count2-- if mounts[mount] - count2 - api.countTriad = (pets) -> count3 = 0 for egg of content.dropEggs diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index 9418b5d217..86c989b5e8 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -652,62 +652,6 @@ describe 'User', -> user.ops.buy {params:'shield_warrior_5'} expect(user.achievements.ultimateGearSets).to.eql {'healer':true,'wizard':true,'rogue':true,'warrior':true} - it 'does not get beastMaster if user has less than 90 drop pets', -> - user = newUser() - user.items.pets = {'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 } - expect(shared.countPets(null,user.items.pets)).to.eql 89 - expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89 - expect(user.achievements.beastMaster).to.not.be.ok() - - it 'does not get beastMaster with 89 drop pets + 1 gryphon', -> - user = newUser() - user.items.pets = {'Gryphon-Base': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 } - expect(shared.countPets(null,user.items.pets)).to.eql 89 - expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89 - expect(user.achievements.beastMaster).to.not.be.ok() - - it 'does not get beastMaster with 89 pets + 1 hydra', -> - user = newUser() - user.items.pets = {'Dragon-Hydra': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 } - expect(shared.countPets(null,user.items.pets)).to.eql 89 - expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89 - expect(user.achievements.beastMaster).to.not.be.ok() - - xit 'does get beastMaster', -> - user = newUser() - user.items.pets = {'Wolf-Base': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 } - expect(shared.countPets(null,user.items.pets)).to.eql 90 - expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 90 - expect(user.achievements.beastMaster).to.be.ok() - - it 'does not get mountMaster if user has less than 90 drop mounts', -> - user = newUser() - user.items.mounts = {'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true } - expect(shared.countMounts(null,user.items.mounts)).to.eql 89 - expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89 - expect(user.achievements.mountMaster).to.not.be.ok() - - it 'does not get mountMaster with 89 drop pets + 1 gryphon', -> - user = newUser() - user.items.mounts = {'Gryphon-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true } - expect(shared.countMounts(null,user.items.mounts)).to.eql 89 - expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89 - expect(user.achievements.mountMaster).to.not.be.ok() - - it 'does not get mountMaster with 89 drop pets + 1 mantis shrimp', -> - user = newUser() - user.items.mounts = {'MantisShrimp-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true } - expect(shared.countMounts(null,user.items.mounts)).to.eql 89 - expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89 - expect(user.achievements.mountMaster).to.not.be.ok() - - xit 'does get mountMaster', -> - user = newUser() - user.items.mounts = {'Wolf-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true } - expect(shared.countMounts(null,user.items.mounts)).to.eql 90 - expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 90 - expect(user.achievements.mountMaster).to.be.ok() - describe 'Simple Scoring', -> beforeEach -> {@before, @after} = beforeAfter() @@ -1023,37 +967,3 @@ describe 'Helper', -> expect(shared.startOfDay({now: new Date(2013, 0, 1, 0)}, timezoneOffset:zone).format(fstr)).to.eql today expect(shared.startOfDay({now: new Date(2013, 0, 1, 5)}, timezoneOffset:zone).format(fstr)).to.eql today expect(shared.startOfDay({now: new Date(2013, 0, 1, 23, 59, 59), timezoneOffset:zone}).format(fstr)).to.eql today - - it 'counts pets', -> - pets = {} - expect(shared.countPets(null, pets)).to.eql 0 - expect(shared.countPets(1, pets)).to.eql 1 - - pets = { "Dragon-Red": 1, "Wolf-Base": 2 } - expect(shared.countPets(null, pets)).to.eql 2 - expect(shared.countPets(2, pets)).to.eql 2 - - pets = { "Dragon-Red": 1, "Gryphon-Base": 1 } - expect(shared.countPets(null, pets)).to.eql 1 - expect(shared.countPets(_.size(pets), pets)).to.eql 1 - - pets = { "Wolf-Base": 2, "Wolf-Veteran": 1, "Wolf-Cerberus": 1, "Dragon-Hydra": 1} - expect(shared.countPets(null, pets)).to.eql 1 - expect(shared.countPets(_.size(pets), pets)).to.eql 1 - - it 'counts mounts', -> - mounts = {} - expect(shared.countMounts(null, mounts)).to.eql 0 - expect(shared.countMounts(1, mounts)).to.eql 1 - - mounts = { "Dragon-Red": true, "Wolf-Base": true } - expect(shared.countMounts(null, mounts)).to.eql 2 - expect(shared.countMounts(2, mounts)).to.eql 2 - - mounts = { "Dragon-Red": true, "Gryphon-Base": true } - expect(shared.countMounts(null, mounts)).to.eql 1 - expect(shared.countMounts(_.size(mounts), mounts)).to.eql 1 - - mounts = { "Wolf-Base": true, "BearCub-Polar": true} - expect(shared.countMounts(null, mounts)).to.eql 1 - expect(shared.countMounts(_.size(mounts), mounts)).to.eql 1 diff --git a/website/public/js/controllers/inventoryCtrl.js b/website/public/js/controllers/inventoryCtrl.js index 4bc97cbc42..c8afc62a62 100644 --- a/website/public/js/controllers/inventoryCtrl.js +++ b/website/public/js/controllers/inventoryCtrl.js @@ -92,8 +92,6 @@ habitrpg.controller("InventoryCtrl", $scope.selectedEgg = null; $scope.selectedPotion = null; - $rootScope.petCount = Shared.countPets($rootScope.countExists(User.user.items.pets), User.user.items.pets); - // Checks if beastmaster has been reached for the first time if(!User.user.achievements.beastMaster && $rootScope.petCount >= 90) { diff --git a/website/public/js/controllers/memberModalCtrl.js b/website/public/js/controllers/memberModalCtrl.js index f5cb70a77d..54f0bb054a 100644 --- a/website/public/js/controllers/memberModalCtrl.js +++ b/website/public/js/controllers/memberModalCtrl.js @@ -15,8 +15,6 @@ habitrpg // We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here $scope.$watch( function() { return Members.selectedMember; }, function (member) { if(member) { - member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets); - member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts); $scope.profile = member; } }); diff --git a/website/public/js/controllers/rootCtrl.js b/website/public/js/controllers/rootCtrl.js index 1c520879b8..258f159cbe 100644 --- a/website/public/js/controllers/rootCtrl.js +++ b/website/public/js/controllers/rootCtrl.js @@ -89,9 +89,6 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ // count pets, mounts collected totals, etc $rootScope.countExists = function(items) {return _.reduce(items,function(m,v){return m+(v?1:0)},0)} - $rootScope.petCount = Shared.countPets($rootScope.countExists(User.user.items.pets), User.user.items.pets); - $rootScope.mountCount = Shared.countMounts($rootScope.countExists(User.user.items.mounts), User.user.items.mounts); - $scope.safeApply = function(fn) { var phase = this.$root.$$phase; if(phase == '$apply' || phase == '$digest') { diff --git a/website/public/js/controllers/userCtrl.js b/website/public/js/controllers/userCtrl.js index a31f10cc86..db8559d728 100644 --- a/website/public/js/controllers/userCtrl.js +++ b/website/public/js/controllers/userCtrl.js @@ -3,8 +3,6 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http', '$state', 'Guide', 'Shared', 'Content', 'Stats', function($rootScope, $scope, $location, User, $http, $state, Guide, Shared, Content, Stats) { $scope.profile = User.user; - $scope.profile.petCount = Shared.countPets($rootScope.countExists($scope.profile.items.pets), $scope.profile.items.pets); - $scope.profile.mountCount = Shared.countMounts($rootScope.countExists($scope.profile.items.mounts), $scope.profile.items.mounts); $scope.statCalc = Stats; diff --git a/website/src/models/user.js b/website/src/models/user.js index 913ed580d1..cb3e9193a6 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -495,20 +495,13 @@ UserSchema.pre('save', function(next) { } // Determines if Beast Master should be awarded - var petCount = shared.countPets(_.reduce(this.items.pets,function(m,v){ - //HOTFIX - Remove when solution is found, the first argument passed to reduce is a function - if(_.isFunction(v)) return m; - return m+(v?1:0)},0), this.items.pets); - + var petCount = shared.countBeastMasterProgress(this.items.pets); if (petCount >= 90 || this.achievements.beastMasterCount > 0) { - this.achievements.beastMaster = true + this.achievements.beastMaster = true; } // Determines if Mount Master should be awarded - var mountCount = shared.countMounts(_.reduce(this.items.mounts,function(m,v){ - //HOTFIX - Remove when solution is found, the first argument passed to reduce is a function - if(_.isFunction(v)) return m; - return m+(v?1:0)},0), this.items.mounts); + var mountCount = shared.countMountMasterProgress(this.items.mounts); if (mountCount >= 90 || this.achievements.mountMasterCount > 0) { this.achievements.mountMaster = true From 65c14b1e3f2c81ecdcf29bb1e5fe38b06ef21c4a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 20 Jul 2015 12:51:10 -0500 Subject: [PATCH 30/35] Refactor inventory ctrl variables --- .../public/js/controllers/inventoryCtrl.js | 40 ++++++++++++------- website/public/js/controllers/settingsCtrl.js | 2 - website/src/models/user.js | 10 ++--- website/views/options/inventory/mounts.jade | 2 +- website/views/options/inventory/pets.jade | 2 +- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/website/public/js/controllers/inventoryCtrl.js b/website/public/js/controllers/inventoryCtrl.js index c8afc62a62..a07d43fa7e 100644 --- a/website/public/js/controllers/inventoryCtrl.js +++ b/website/public/js/controllers/inventoryCtrl.js @@ -1,6 +1,6 @@ habitrpg.controller("InventoryCtrl", - ['$rootScope', '$scope', 'Shared', '$window', 'User', 'Content', 'Analytics', 'Quests', - function($rootScope, $scope, Shared, $window, User, Content, Analytics, Quests) { + ['$rootScope', '$scope', 'Shared', '$window', 'User', 'Content', 'Analytics', 'Quests', 'Stats', + function($rootScope, $scope, Shared, $window, User, Content, Analytics, Quests, Stats) { var user = User.user; @@ -8,8 +8,8 @@ habitrpg.controller("InventoryCtrl", $scope.selectedEgg = null; // {index: 1, name: "Tiger", value: 5} $scope.selectedPotion = null; // {index: 5, name: "Red", value: 3} - $scope.totalPets = _.size(Content.dropEggs) * _.size(Content.hatchingPotions); - $scope.totalMounts = _.size(Content.dropEggs) * _.size(Content.hatchingPotions); + + _updateDropAnimalCount(user.items); // Functions from Quests service $scope.lockQuest = Quests.lockQuest; @@ -92,16 +92,18 @@ habitrpg.controller("InventoryCtrl", $scope.selectedEgg = null; $scope.selectedPotion = null; + _updateDropAnimalCount(user.items); + // Checks if beastmaster has been reached for the first time - if(!User.user.achievements.beastMaster - && $rootScope.petCount >= 90) { + if(!user.achievements.beastMaster + && $scope.petCount >= 90) { User.user.achievements.beastMaster = true; $rootScope.openModal('achievements/beastMaster'); } // Checks if Triad Bingo has been reached for the first time - if(!User.user.achievements.triadBingo - && $rootScope.mountCount >= 90 + if(!user.achievements.triadBingo + && $scope.mountCount >= 90 && Shared.countTriad(User.user.items.pets) >= 90) { User.user.achievements.triadBingo = true; $rootScope.openModal('achievements/triadBingo'); @@ -125,14 +127,15 @@ habitrpg.controller("InventoryCtrl", } User.user.ops.feed({params:{pet: pet, food: food.key}}); $scope.selectedFood = null; - $rootScope.mountCount = Shared.countMounts($rootScope.countExists(User.user.items.mounts), User.user.items.mounts); - // Checks if mountmaster has been reached for the first time - if(!User.user.achievements.mountMaster - && $rootScope.mountCount >= 90) { - User.user.achievements.mountMaster = true; - $rootScope.openModal('achievements/mountMaster'); - } + _updateDropAnimalCount(user.items); + + // Checks if mountmaster has been reached for the first time + if(!user.achievements.mountMaster + && $scope.mountCount >= 90) { + User.user.achievements.mountMaster = true; + $rootScope.openModal('achievements/mountMaster'); + } // Selecting Pet } else { @@ -209,5 +212,12 @@ habitrpg.controller("InventoryCtrl", break; } }; + + function _updateDropAnimalCount(items) { + $scope.petCount = Shared.countBeastMasterProgress(items.pets); + $scope.mountCount = Shared.countMountMasterProgress(items.mounts); + $scope.beastMasterProgress = Stats.beastMasterProgress(items.pets); + $scope.mountMasterProgress = Stats.mountMasterProgress(items.mounts); + } } ]); diff --git a/website/public/js/controllers/settingsCtrl.js b/website/public/js/controllers/settingsCtrl.js index 5c83b5756c..5c0f078761 100644 --- a/website/public/js/controllers/settingsCtrl.js +++ b/website/public/js/controllers/settingsCtrl.js @@ -162,13 +162,11 @@ habitrpg.controller('SettingsCtrl', $scope.releaseMounts = function() { User.user.ops.releaseMounts({}); - $rootScope.mountCount = 0; $rootScope.$state.go('tasks'); } $scope.releaseBoth = function() { User.user.ops.releaseBoth({}); - $rootScope.mountCount = 0; $rootScope.$state.go('tasks'); } diff --git a/website/src/models/user.js b/website/src/models/user.js index cb3e9193a6..f699145e2e 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -495,15 +495,15 @@ UserSchema.pre('save', function(next) { } // Determines if Beast Master should be awarded - var petCount = shared.countBeastMasterProgress(this.items.pets); - if (petCount >= 90 || this.achievements.beastMasterCount > 0) { + var beastMasterProgress = shared.countBeastMasterProgress(this.items.pets); + if (beastMasterProgress >= 90 || this.achievements.beastMasterCount > 0) { this.achievements.beastMaster = true; } // Determines if Mount Master should be awarded - var mountCount = shared.countMountMasterProgress(this.items.mounts); + var mountMasterProgress = shared.countMountMasterProgress(this.items.mounts); - if (mountCount >= 90 || this.achievements.mountMasterCount > 0) { + if (mountMasterProgress >= 90 || this.achievements.mountMasterCount > 0) { this.achievements.mountMaster = true } @@ -511,7 +511,7 @@ UserSchema.pre('save', function(next) { var triadCount = shared.countTriad(this.items.pets); - if ((mountCount >= 90 && triadCount >= 90) || this.achievements.triadBingoCount > 0) { + if ((mountMasterProgress >= 90 && triadCount >= 90) || this.achievements.triadBingoCount > 0) { this.achievements.triadBingo = true; } diff --git a/website/views/options/inventory/mounts.jade b/website/views/options/inventory/mounts.jade index 71d1103a7d..f5de6d2df2 100644 --- a/website/views/options/inventory/mounts.jade +++ b/website/views/options/inventory/mounts.jade @@ -22,7 +22,7 @@ mixin mountList(source) a(target='_blank', href='http://www.kickstarter.com/profile/mattboch')=env.t('mattBoch') .popover-content p=env.t('mattShall', {name: "{{user.profile.name}}"}) - h4= env.t('mountMasterProgress') + ': {{mountCount}} / {{totalMounts}} ' + env.t('mountsTamed') + h4= env.t('mountMasterProgress') + ': {{::mountMasterProgress}} ' + env.t('mountsTamed') .row: .col-md-12 +mountList(env.Content.dropEggs) .row: .col-md-12 diff --git a/website/views/options/inventory/pets.jade b/website/views/options/inventory/pets.jade index e2a845c4bd..c449806d5e 100644 --- a/website/views/options/inventory/pets.jade +++ b/website/views/options/inventory/pets.jade @@ -22,7 +22,7 @@ mixin petList(source) a(target='_blank', href='http://www.kickstarter.com/profile/mattboch')=env.t('mattBoch') .popover-content p=env.t('mattBochText1') - h4=env.t('beastMasterProgress') + ': {{petCount}} / {{totalPets}} ' + env.t('petsFound') + h4=env.t('beastMasterProgress') + ': {{::beastMasterProgress}} ' + env.t('petsFound') .row: .col-md-12 +petList(env.Content.dropEggs) From 73e17644137580c93448f4905002726ce0f5b84b Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 21 Jul 2015 08:13:50 -0500 Subject: [PATCH 31/35] Move beast/mount master counts to separate file --- common/script/count.js | 32 ++++++++++++++++++++++++++++++++ test/common/count.js | 28 ++++++++++++++-------------- 2 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 common/script/count.js diff --git a/common/script/count.js b/common/script/count.js new file mode 100644 index 0000000000..cbb7fe3b47 --- /dev/null +++ b/common/script/count.js @@ -0,0 +1,32 @@ +'use strict'; + +require('coffee-script'); +var _ = require('lodash'); +var content = require('./content'); + +var DROP_ANIMALS = _.keys(content.pets); + +function beastMasterProgress(pets) { + var count = 0; + _(DROP_ANIMALS).each(function(animal) { + if(pets[animal] > 0 || pets[animal] == -1) + count++ + }); + + return count; +} + +function mountMasterProgress(mounts) { + var count = 0; + _(DROP_ANIMALS).each(function(animal) { + if (mounts[animal]) + count++ + }); + + return count; +} + +module.exports = { + beastMasterProgress: beastMasterProgress, + mountMasterProgress: mountMasterProgress +}; diff --git a/test/common/count.js b/test/common/count.js index f3d604dfab..44fc14e6ae 100644 --- a/test/common/count.js +++ b/test/common/count.js @@ -4,25 +4,25 @@ chai.use(require("sinon-chai")) var expect = chai.expect require('coffee-script'); -var shared = require('../../common/script/index.coffee'); +var count = require('../../common/script/count'); describe('count', function() { - describe('countBeastMasterProgress', function() { + describe('beastMasterProgress', function() { it('returns 0 if no pets', function() { var pets = {}; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(0); }); it('counts drop pets', function() { var pets = { "Dragon-Red": 1, "Wolf-Base": 2 }; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(2); }); it('does not count quest pets', function() { var pets = { "Dragon-Red": 1, "Gryphon-Base": 1 }; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(1); }); @@ -33,54 +33,54 @@ describe('count', function() { "Wolf-Cerberus": 1, "Dragon-Hydra": 1 }; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(1); }); it('counts drop pets that have been raised to a mount', function() { var raisedToMount = -1; var pets = { "Dragon-Red": 1, "Wolf-Base": raisedToMount }; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(2); }); it('does not counts drop pets that have been released', function() { var releasedPet = 0; var pets = { "Dragon-Red": 1, "Wolf-Base": releasedPet }; - var beastMasterTotal = shared.countBeastMasterProgress(pets); + var beastMasterTotal = count.beastMasterProgress(pets); expect(beastMasterTotal).to.eql(1); }); }); - describe('countMountMasterProgress', function() { + describe('mountMasterProgress', function() { it('returns 0 if no mounts', function() { var mounts = {}; - var mountMasterTotal = shared.countMountMasterProgress(mounts); + var mountMasterTotal = count.mountMasterProgress(mounts); expect(mountMasterTotal).to.eql(0); }); it('counts drop mounts', function() { var mounts = { "Dragon-Red": true, "Wolf-Base": true }; - var mountMasterTotal = shared.countMountMasterProgress(mounts); + var mountMasterTotal = count.mountMasterProgress(mounts); expect(mountMasterTotal).to.eql(2); }); it('does not count quest mounts', function() { var mounts = { "Dragon-Red": true, "Gryphon-Base": true }; - var mountMasterTotal = shared.countMountMasterProgress(mounts); + var mountMasterTotal = count.mountMasterProgress(mounts); expect(mountMasterTotal).to.eql(1); }); it('does not count special mounts', function() { var mounts = { "Wolf-Base": true, "BearCub-Polar": true}; - var mountMasterTotal = shared.countMountMasterProgress(mounts); + var mountMasterTotal = count.mountMasterProgress(mounts); expect(mountMasterTotal).to.eql(1); }); it('only counts drop mounts that are currently owned', function() { var notCurrentlyOwned = false; var mounts = { "Dragon-Red": true, "Wolf-Base": notCurrentlyOwned }; - var mountMasterTotal = shared.countMountMasterProgress(mounts); + var mountMasterTotal = count.mountMasterProgress(mounts); expect(mountMasterTotal).to.eql(1); }); }); From 20660f50c05d541eded2454d3573713817235293 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 21 Jul 2015 18:04:48 -0500 Subject: [PATCH 32/35] Add count function for remaining items in gear set --- common/script/count.js | 16 +++++++++++++++- test/common/count.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/common/script/count.js b/common/script/count.js index cbb7fe3b47..14c41bee36 100644 --- a/common/script/count.js +++ b/common/script/count.js @@ -26,7 +26,21 @@ function mountMasterProgress(mounts) { return count; } +function remainingGearInSet(userGear, set) { + var gear = _.filter(content.gear.flat, function(item) { + var setMatches = item.klass === set; + var hasItem = _.has(userGear, item.key); + + return setMatches && !hasItem; + }); + + var count = _.size(gear); + + return count; +} + module.exports = { beastMasterProgress: beastMasterProgress, - mountMasterProgress: mountMasterProgress + mountMasterProgress: mountMasterProgress, + remainingGearInSet: remainingGearInSet }; diff --git a/test/common/count.js b/test/common/count.js index 44fc14e6ae..f0a25a771d 100644 --- a/test/common/count.js +++ b/test/common/count.js @@ -84,4 +84,32 @@ describe('count', function() { expect(mountMasterTotal).to.eql(1); }); }); + + describe('remainingGearInSet', function() { + it('counts remaining gear based on set', function() { + var gear = { + 'weapon_wizard_0':true, + 'weapon_wizard_1':true, + 'weapon_warrior_0':true, + 'weapon_warrior_1':true, + 'weapon_armor_0':true, + 'weapon_armor_1':true + }; + + var armoireCount = count.remainingGearInSet(gear, 'warrior'); + expect(armoireCount).to.eql(20); + }); + + it('includes previously owned items in count', function() { + var gear = { + 'weapon_warrior_0':false, + 'weapon_warrior_1':false, + 'weapon_armor_0':true, + 'weapon_armor_1':true + }; + + var armoireCount = count.remainingGearInSet(gear, 'warrior'); + expect(armoireCount).to.eql(20); + }); + }); }); From 063e53b0eaf0eeef948bd028ae1e1070ed529c4a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 21 Jul 2015 20:14:15 -0500 Subject: [PATCH 33/35] Added function to count pets that are actually owned --- common/script/count.js | 13 +++++++++++++ test/common/count.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/common/script/count.js b/common/script/count.js index 14c41bee36..b0ae608675 100644 --- a/common/script/count.js +++ b/common/script/count.js @@ -16,6 +16,18 @@ function beastMasterProgress(pets) { return count; } +function dropPetsCurrentlyOwned(pets) { + var count = 0; + + _(DROP_ANIMALS).each(function(animal) { + if(pets[animal] > 0) + count++ + }); + + return count; +} + + function mountMasterProgress(mounts) { var count = 0; _(DROP_ANIMALS).each(function(animal) { @@ -41,6 +53,7 @@ function remainingGearInSet(userGear, set) { module.exports = { beastMasterProgress: beastMasterProgress, + dropPetsCurrentlyOwned: dropPetsCurrentlyOwned, mountMasterProgress: mountMasterProgress, remainingGearInSet: remainingGearInSet }; diff --git a/test/common/count.js b/test/common/count.js index f0a25a771d..d02c3b665c 100644 --- a/test/common/count.js +++ b/test/common/count.js @@ -112,4 +112,46 @@ describe('count', function() { expect(armoireCount).to.eql(20); }); }); + + describe('dropPetsCurrentlyOwned', function() { + it('counts drop pets owned', function() { + var pets = { + "Wolf-Base": 2, + "Wolf-Red": 4 + }; + var dropPets = count.dropPetsCurrentlyOwned(pets); + expect(dropPets).to.eql(2); + }); + + it('does not count pets that have been raised to mounts', function() { + var pets = { + "Wolf-Base": -1, + "Wolf-Red": 4, + "Wolf-Veteran": 1, + "Gryphon-Base": 1 + }; + var dropPets = count.dropPetsCurrentlyOwned(pets); + expect(dropPets).to.eql(1); + }); + + it('does not count quest pets', function() { + var pets = { + "Wolf-Base": 2, + "Wolf-Red": 4, + "Gryphon-Base": 1 + }; + var dropPets = count.dropPetsCurrentlyOwned(pets); + expect(dropPets).to.eql(2); + }); + + it('does not count special pets', function() { + var pets = { + "Wolf-Base": 2, + "Wolf-Red": 4, + "Wolf-Veteran": 1 + }; + var dropPets = count.dropPetsCurrentlyOwned(pets); + expect(dropPets).to.eql(2); + }); + }); }); From f40cfd2b66fa3ae63ce6c3fbc3e428e3ede7f573 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 22 Jul 2015 17:32:12 -0500 Subject: [PATCH 34/35] Move all pet counting to shared count scripts --- common/script/count.js | 2 +- common/script/index.coffee | 30 ++++--------------- .../public/js/controllers/inventoryCtrl.js | 6 ++-- website/public/js/services/statServices.js | 4 +-- website/src/models/user.js | 9 +++--- 5 files changed, 16 insertions(+), 35 deletions(-) diff --git a/common/script/count.js b/common/script/count.js index b0ae608675..8832d6379f 100644 --- a/common/script/count.js +++ b/common/script/count.js @@ -2,7 +2,7 @@ require('coffee-script'); var _ = require('lodash'); -var content = require('./content'); +var content = require('./content.coffee'); var DROP_ANIMALS = _.keys(content.pets); diff --git a/common/script/index.coffee b/common/script/index.coffee index 9b7002bdf5..1670d0398a 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -378,35 +378,15 @@ api.appliedTags = (userTags, taskTags) -> arr.push(t.name) if taskTags?[t.id] arr.join(', ') -DROP_ANIMALS = _.keys(content.pets) - -api.countBeastMasterProgress = (pets) -> - count = 0 - for animal in DROP_ANIMALS - if pets[animal] > 0 || pets[animal] == -1 - count++ - - count - -api.countMountMasterProgress = (mounts) -> - count = 0 - for animal in DROP_ANIMALS - if mounts[animal] - count++ - - count - -api.countTriad = (pets) -> - count3 = 0 - for egg of content.dropEggs - for potion of content.hatchingPotions - if pets[egg + "-" + potion] > 0 then count3++ - count3 - api.countArmoire = (gear) -> count = _.size(_.filter(content.gear.flat, ((i)->i.klass is 'armoire' and !gear[i.key]))) count +### +Various counting functions +### +api.count = require('./count') + ### ------------------------------------------------------ User (prototype wrapper to give it ops, helper funcs, and virtuals diff --git a/website/public/js/controllers/inventoryCtrl.js b/website/public/js/controllers/inventoryCtrl.js index a07d43fa7e..d8cb369cc5 100644 --- a/website/public/js/controllers/inventoryCtrl.js +++ b/website/public/js/controllers/inventoryCtrl.js @@ -104,7 +104,7 @@ habitrpg.controller("InventoryCtrl", // Checks if Triad Bingo has been reached for the first time if(!user.achievements.triadBingo && $scope.mountCount >= 90 - && Shared.countTriad(User.user.items.pets) >= 90) { + && Shared.count.dropPetsCurrentlyOwned(User.user.items.pets) >= 90) { User.user.achievements.triadBingo = true; $rootScope.openModal('achievements/triadBingo'); } @@ -214,8 +214,8 @@ habitrpg.controller("InventoryCtrl", }; function _updateDropAnimalCount(items) { - $scope.petCount = Shared.countBeastMasterProgress(items.pets); - $scope.mountCount = Shared.countMountMasterProgress(items.mounts); + $scope.petCount = Shared.count.beastMasterProgress(items.pets); + $scope.mountCount = Shared.count.mountMasterProgress(items.mounts); $scope.beastMasterProgress = Stats.beastMasterProgress(items.pets); $scope.mountMasterProgress = Stats.mountMasterProgress(items.mounts); } diff --git a/website/public/js/services/statServices.js b/website/public/js/services/statServices.js index 2935eaa798..e836b39fb2 100644 --- a/website/public/js/services/statServices.js +++ b/website/public/js/services/statServices.js @@ -15,7 +15,7 @@ var TOTAL_NUMBER_OF_DROP_ANIMALS = DROP_ANIMALS.length; function beastMasterProgress(pets) { - var dropPetsFound = Shared.countBeastMasterProgress(pets); + var dropPetsFound = Shared.count.beastMasterProgress(pets); var display = _formatOutOfTotalDisplay(dropPetsFound, TOTAL_NUMBER_OF_DROP_ANIMALS); return display; @@ -87,7 +87,7 @@ } function mountMasterProgress(mounts) { - var dropMountsFound = Shared.countMountMasterProgress(mounts); + var dropMountsFound = Shared.count.mountMasterProgress(mounts); var display = _formatOutOfTotalDisplay(dropMountsFound, TOTAL_NUMBER_OF_DROP_ANIMALS); return display; diff --git a/website/src/models/user.js b/website/src/models/user.js index f699145e2e..e8dc06e60f 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -495,13 +495,13 @@ UserSchema.pre('save', function(next) { } // Determines if Beast Master should be awarded - var beastMasterProgress = shared.countBeastMasterProgress(this.items.pets); + var beastMasterProgress = shared.count.beastMasterProgress(this.items.pets); if (beastMasterProgress >= 90 || this.achievements.beastMasterCount > 0) { this.achievements.beastMaster = true; } // Determines if Mount Master should be awarded - var mountMasterProgress = shared.countMountMasterProgress(this.items.mounts); + var mountMasterProgress = shared.count.mountMasterProgress(this.items.mounts); if (mountMasterProgress >= 90 || this.achievements.mountMasterCount > 0) { this.achievements.mountMaster = true @@ -509,9 +509,10 @@ UserSchema.pre('save', function(next) { // Determines if Triad Bingo should be awarded - var triadCount = shared.countTriad(this.items.pets); + var dropPetCount = shared.count.dropPetsCurrentlyOwned(this.items.pets); + var qualifiesForTriad = dropPetCount >= 90 && mountMasterProgress >= 90; - if ((mountMasterProgress >= 90 && triadCount >= 90) || this.achievements.triadBingoCount > 0) { + if (qualifiesForTriad || this.achievements.triadBingoCount > 0) { this.achievements.triadBingo = true; } From 7b9102c88ced9a935119dbc4b85251e19341d56a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 22 Jul 2015 17:37:35 -0500 Subject: [PATCH 35/35] Move gear counting to counting script --- common/script/index.coffee | 6 +----- test/common/algos.mocha.coffee | 8 ++++---- website/public/js/controllers/tasksCtrl.js | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index 1670d0398a..d4e72287ba 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -378,10 +378,6 @@ api.appliedTags = (userTags, taskTags) -> arr.push(t.name) if taskTags?[t.id] arr.join(', ') -api.countArmoire = (gear) -> - count = _.size(_.filter(content.gear.flat, ((i)->i.klass is 'armoire' and !gear[i.key]))) - count - ### Various counting functions ### @@ -884,7 +880,7 @@ api.wrap = (user, main=true) -> user.items.gear.owned[drop.key] = true user.flags.armoireOpened = true message = i18n.t('armoireEquipment', {image: '', dropText: drop.text(req.language)}, req.language) - if api.countArmoire(user.items.gear.owned) is 0 then user.flags.armoireEmpty = true + if api.count.remainingGearInSet(user.items.gear.owned, 'armoire') is 0 then user.flags.armoireEmpty = true else if (!_.isEmpty(eligibleEquipment) and armoireResult < .8) or armoireResult < .5 drop = user.fns.randomVal _.where(content.food, {canDrop:true}) user.items.food[drop.key] ?= 0 diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index 86c989b5e8..f720d473e1 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -541,7 +541,7 @@ describe 'User', -> it 'counts all available equipment before any are claimed', -> sinon.stub(user.fns, 'predictableRandom').returns 0 - expect(shared.countArmoire(user.items.gear.owned)).to.eql (_.size(fullArmoire) - 1) + expect(shared.count.remainingGearInSet(user.items.gear.owned, 'armoire')).to.eql (_.size(fullArmoire) - 1) it 'does not open without paying', -> sinon.stub(user.fns, 'predictableRandom').returns 0 @@ -565,7 +565,7 @@ describe 'User', -> user.achievements.ultimateGearSets = {'healer':false,'wizard':false,'rogue':true,'warrior':false} user.ops.buy({params: {key: 'armoire'}}) expect(user.items.gear.owned).to.eql {'weapon_warrior_0': true, 'shield_armoire_gladiatorShield':true} - expect(shared.countArmoire(user.items.gear.owned)).to.eql (_.size(fullArmoire) - 2) + expect(shared.count.remainingGearInSet(user.items.gear.owned, 'armoire')).to.eql (_.size(fullArmoire) - 2) expect(user.items.food).to.eql {} expect(user.stats.exp).to.eql 0 expect(user.stats.gp).to.eql 400 @@ -590,7 +590,7 @@ describe 'User', -> sinon.stub(user.fns, 'predictableRandom', cycle [.5,.5]) user.ops.buy({params: {key: 'armoire'}}) expect(user.items.gear.owned).to.eql {'weapon_warrior_0': true, 'shield_armoire_gladiatorShield':true, 'head_armoire_blueHairbow':true} - expect(shared.countArmoire(user.items.gear.owned)).to.eql (_.size(fullArmoire) - 3) + expect(shared.count.remainingGearInSet(user.items.gear.owned, 'armoire')).to.eql (_.size(fullArmoire) - 3) expect(user.items.food).to.eql {'Honey': 1} expect(user.stats.exp).to.eql 30 expect(user.stats.gp).to.eql 100 @@ -600,7 +600,7 @@ describe 'User', -> user.items.gear.owned = fullArmoire user.ops.buy({params: {key: 'armoire'}}) expect(user.items.gear.owned).to.eql fullArmoire - expect(shared.countArmoire(user.items.gear.owned)).to.eql 0 + expect(shared.count.remainingGearInSet(user.items.gear.owned, 'armoire')).to.eql 0 expect(user.items.food).to.eql {'Honey': 1} expect(user.stats.exp).to.eql 60 expect(user.stats.gp).to.eql 0 diff --git a/website/public/js/controllers/tasksCtrl.js b/website/public/js/controllers/tasksCtrl.js index 74d4c2d642..6fecc56f57 100644 --- a/website/public/js/controllers/tasksCtrl.js +++ b/website/public/js/controllers/tasksCtrl.js @@ -6,7 +6,7 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N $scope.user = User.user; $scope.armoireCount = function(gear) { - return Shared.countArmoire(gear); + return Shared.count.remainingGearInSet(gear, 'armoire'); }; $scope.score = function(task, direction) {