diff --git a/common/script/index.js b/common/script/index.js index 6a3558f937..9bb5c8312e 100644 --- a/common/script/index.js +++ b/common/script/index.js @@ -13,6 +13,14 @@ api = module.exports = {}; api.i18n = i18n; +import statHelpers from './statHelpers.js' + +api.maxLevel = statHelpers.maxLevel; +api.capByLevel = statHelpers.capByLevel; +api.maxHealth = statHelpers.maxHealth; +api.tnl = statHelpers.tnl; +api.diminishingReturns = statHelpers.diminishingReturns; + $w = api.$w = function(s) { return s.split(' '); }; @@ -182,63 +190,6 @@ api.shouldDo = function(day, dailyTask, options) { } }; - -/* - ------------------------------------------------------ - Level cap - ------------------------------------------------------ - */ - -api.maxLevel = 100; - -api.capByLevel = function(lvl) { - if (lvl > api.maxLevel) { - return api.maxLevel; - } else { - return lvl; - } -}; - - -/* - ------------------------------------------------------ - Health cap - ------------------------------------------------------ - */ - -api.maxHealth = 50; - - -/* - ------------------------------------------------------ - Scoring - ------------------------------------------------------ - */ - -api.tnl = function(lvl) { - return Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10; -}; - - -/* - A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain). - {max} The asymptote - {bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc) - {halfway} (optional) the point at which the graph starts bending - */ - -api.diminishingReturns = function(bonus, max, halfway) { - if (halfway == null) { - halfway = max / 2; - } - return max * (bonus / (bonus + halfway)); -}; - -api.monod = function(bonus, rateOfIncrease, max) { - return rateOfIncrease * max * bonus / (rateOfIncrease * bonus + max); -}; - - /* Preen history for users with > 7 history entries This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array diff --git a/common/script/statHelpers.js b/common/script/statHelpers.js new file mode 100644 index 0000000000..005663d741 --- /dev/null +++ b/common/script/statHelpers.js @@ -0,0 +1,55 @@ +/* + ------------------------------------------------------ + Level cap + ------------------------------------------------------ + */ + +const maxLevel = 100; + +function capByLevel (lvl) { + if (lvl > maxLevel) { + return maxLevel; + } else { + return lvl; + } +} + +/* + ------------------------------------------------------ + Health cap + ------------------------------------------------------ + */ + +const maxHealth = 50; + +/* + ------------------------------------------------------ + Scoring + ------------------------------------------------------ + */ + +function tnl (lvl) { + return Math.round((Math.pow(lvl, 2) * 0.25 + 10 * lvl + 139.75) / 10) * 10; +} + +/* + A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain). + {max} The asymptote + {bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc) + {halfway} (optional) the point at which the graph starts bending + */ + +function diminishingReturns (bonus, max, halfway) { + if (halfway === null) { + halfway = max / 2; + } + return max * (bonus / (bonus + halfway)); +} + +export default { + maxLevel, + capByLevel, + maxHealth, + tnl, + diminishingReturns, +}; diff --git a/test/common/statHelpers.test.js b/test/common/statHelpers.test.js new file mode 100644 index 0000000000..d757d40381 --- /dev/null +++ b/test/common/statHelpers.test.js @@ -0,0 +1,58 @@ +var sinon = require('sinon'); +var chai = require("chai") +chai.use(require("sinon-chai")) +var expect = chai.expect + +var shared = require('../../common/script/index.js'); + +describe('helper functions used in stat calculations', function() { + + var HEALTH_CAP = 50; + var LEVEL_CAP = 100; + var LEVEL = 57; + var BONUS = 600; + var MAXIMUM = 200; + var HALFWAY = 75; + + it('provides a maximum Health value', function() { + expect(shared.maxHealth).to.eql(HEALTH_CAP); + }); + + describe('maximum level cap', function() { + it('returns a maximum level for attribute gain', function() { + expect(shared.maxLevel).to.eql(LEVEL_CAP); + }); + + it('returns level given if below cap', function() { + expect(shared.capByLevel(LEVEL)).to.eql(LEVEL); + }); + + it('returns level given if equal to cap', function() { + expect(shared.capByLevel(LEVEL_CAP)).to.eql(LEVEL_CAP); + }); + + it('returns level cap if above cap', function() { + expect(shared.capByLevel(LEVEL_CAP + LEVEL)).to.eql(LEVEL_CAP); + }); + }); + + describe('Experience to next level', function() { + it('increases Experience target from one level to the next', function() { + expect(shared.tnl(LEVEL + 1)).to.be.greaterThan(shared.tnl(LEVEL)); + }); + }); + + describe('diminishing returns', function() { + it('provides a value under the maximum, given a bonus and maximum', function() { + expect(shared.diminishingReturns(BONUS,MAXIMUM)).to.be.lessThan(MAXIMUM); + }); + + it('provides a value under the maximum, given a bonus, maximum, and halfway point', function() { + expect(shared.diminishingReturns(BONUS,MAXIMUM,HALFWAY)).to.be.lessThan(MAXIMUM); + }); + + it('provides a different curve if a halfway point is defined', function() { + expect(shared.diminishingReturns(BONUS,MAXIMUM,HALFWAY)).to.not.eql(shared.diminishingReturns(BONUS,MAXIMUM)); + }); + }); +});