diff --git a/dist/habitrpg-shared.js b/dist/habitrpg-shared.js index 21da91e0b0..95526bfe55 100644 --- a/dist/habitrpg-shared.js +++ b/dist/habitrpg-shared.js @@ -12738,7 +12738,6 @@ api.userDefaults = { }; - },{"./i18n.coffee":6,"lodash":3,"moment":4}],6:[function(require,module,exports){ var _; @@ -12783,7 +12782,6 @@ module.exports = { }; - },{"lodash":3}],7:[function(require,module,exports){ (function (process){ var $w, api, content, i18n, moment, preenHistory, sanitizeOptions, sortOrder, _, @@ -14137,7 +14135,7 @@ api.wrap = function(user, main) { return typeof cb === "function" ? cb(null, 'items.special') : void 0; }, score: function(req, cb) { - var addPoints, calculateDelta, delta, direction, id, mpDelta, multiplier, num, options, stats, subtractPoints, task, th, _ref; + var addPoints, calculateDelta, calculateReverseDelta, changeTaskValue, delta, direction, id, mpDelta, multiplier, num, options, stats, subtractPoints, task, th, _ref; _ref = req.params, id = _ref.id, direction = _ref.direction; task = user.tasks[id]; options = req.query || {}; @@ -14164,29 +14162,53 @@ api.wrap = function(user, main) { } delta = 0; calculateDelta = function() { - return _.times(options.times, function() { - var currVal, nextDelta, _ref1, _ref2; - currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value; - nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1); - if (((_ref1 = task.checklist) != null ? _ref1.length : void 0) > 0) { - if (direction === 'down' && task.type === 'daily' && options.cron) { - nextDelta *= 1 - _.reduce(task.checklist, (function(m, i) { - return m + (i.completed ? 1 : 0); - }), 0) / task.checklist.length; - } - if (task.type === 'todo') { - nextDelta *= 1 + _.reduce(task.checklist, (function(m, i) { - return m + (i.completed ? 1 : 0); - }), 0); - } + var currVal, nextDelta, _ref1; + currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value; + nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1); + if (((_ref1 = task.checklist) != null ? _ref1.length : void 0) > 0) { + if (direction === 'down' && task.type === 'daily' && options.cron) { + nextDelta *= 1 - _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0) / task.checklist.length; } + if (task.type === 'todo') { + nextDelta *= 1 + _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0); + } + } + return nextDelta; + }; + calculateReverseDelta = function() { + var calc, closeEnough, currVal, diff, testVal; + currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value; + testVal = currVal + Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1); + closeEnough = 0.0001; + while (true) { + calc = testVal + Math.pow(0.9747, testVal); + diff = currVal - calc; + if (Math.abs(diff) < closeEnough) { + break; + } + if (diff > 0) { + testVal -= diff; + } else { + testVal += diff; + } + } + return testVal - currVal; + }; + changeTaskValue = function(reverse) { + return _.times(options.times, function() { + var nextDelta, _ref1; + nextDelta = reverse ? calculateReverseDelta() : calculateDelta(); if (task.type !== 'reward') { if (user.preferences.automaticAllocation === true && user.preferences.allocationMode === 'taskbased' && !(task.type === 'todo' && direction === 'down')) { user.stats.training[task.attribute] += nextDelta; } if (direction === 'up' && !(task.type === 'habit' && !task.down)) { user.party.quest.progress.up = user.party.quest.progress.up || 0; - if ((_ref2 = task.type) === 'daily' || _ref2 === 'todo') { + if ((_ref1 = task.type) === 'daily' || _ref1 === 'todo') { user.party.quest.progress.up += nextDelta * (1 + (user._statsComputed.str / 200)); } } @@ -14218,7 +14240,7 @@ api.wrap = function(user, main) { }; switch (task.type) { case 'habit': - calculateDelta(); + changeTaskValue(); if (delta > 0) { addPoints(); } else { @@ -14241,13 +14263,16 @@ api.wrap = function(user, main) { break; case 'daily': if (options.cron) { - calculateDelta(); + changeTaskValue(); subtractPoints(); if (!user.stats.buffs.streaks) { task.streak = 0; } } else { - calculateDelta(); + changeTaskValue(delta < 0); + if (delta < 0) { + delta = calculateDelta(); + } addPoints(); if (direction === 'up') { task.streak = task.streak ? task.streak + 1 : 1; @@ -14264,10 +14289,13 @@ api.wrap = function(user, main) { break; case 'todo': if (options.cron) { - calculateDelta(); + changeTaskValue(); } else { task.dateCompleted = direction === 'up' ? new Date : void 0; - calculateDelta(); + changeTaskValue(delta < 0); + if (delta < 0) { + delta = calculateDelta(); + } addPoints(); multiplier = _.max([ _.reduce(task.checklist, (function(m, i) { @@ -14289,7 +14317,7 @@ api.wrap = function(user, main) { } break; case 'reward': - calculateDelta(); + changeTaskValue(); stats.gp -= Math.abs(task.value); num = parseFloat(task.value).toFixed(2); if (stats.gp < 0) { @@ -14843,6 +14871,5 @@ api.wrap = function(user, main) { }; - -}).call(this,require("/Users/lefnire/Dropbox/Sites/habitrpg/modules/habitrpg-shared/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) -},{"./content.coffee":5,"./i18n.coffee":6,"/Users/lefnire/Dropbox/Sites/habitrpg/modules/habitrpg-shared/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":2,"lodash":3,"moment":4}]},{},[1]) \ No newline at end of file +}).call(this,require("/Users/brando37/Documents/Projects/habitrpg/node_modules/habitrpg-shared/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) +},{"./content.coffee":5,"./i18n.coffee":6,"/Users/brando37/Documents/Projects/habitrpg/node_modules/habitrpg-shared/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":2,"lodash":3,"moment":4}]},{},[1]) \ No newline at end of file diff --git a/script/index.coffee b/script/index.coffee index 8d8e573e32..6d8b7c595f 100644 --- a/script/index.coffee +++ b/script/index.coffee @@ -845,28 +845,60 @@ api.wrap = (user, main=true) -> delta = 0 calculateDelta = -> + # Calculates the next task.value based on direction + # Uses a capped inverse log y=.95^x, y>= -5 + + # Min/max on task redness + currVal = + if task.value < -47.27 then -47.27 + else if task.value > 21.27 then 21.27 + else task.value + nextDelta = Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1) + + # Checklists + if task.checklist?.length > 0 + # If the Daily, only dock them them a portion based on their checklist completion + if direction is 'down' and task.type is 'daily' and options.cron + nextDelta *= (1 - _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) / task.checklist.length) + # If To-Do, point-match the TD per checklist item completed + if task.type is 'todo' + nextDelta *= (1 + _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0)) + nextDelta + + calculateReverseDelta = -> + # Approximates the reverse delta for the task value + # This is meant to return the task value to its original value when unchecking a task. + # First, calculate the the value using the normal way for our first guess although + # it will be a bit off + currVal = + if task.value < -47.27 then -47.27 + else if task.value > 21.27 then 21.27 + else task.value + testVal = currVal + Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1) + + # Now keep moving closer to the original value until we get "close enough" + closeEnough = 0.0001 + while true + # Check how close we are to the original value by computing the delta off our guess + # and looking at the difference between that and our current value. + calc = (testVal) + Math.pow(0.9747, testVal) + diff = currVal-calc + if Math.abs(diff) < closeEnough + break + if diff > 0 + testVal -= diff + else + testVal += diff + # When we get close enough, return the difference between our approximated value + # and the current value. This will be the delta calculated from the original value + # before the task was checked. + testVal - currVal + + changeTaskValue = (reverse) -> # If multiple days have passed, multiply times days missed _.times options.times, -> # Each iteration calculate the nextDelta, which is then accumulated in the total delta. - # Calculates the next task.value based on direction - # Uses a capped inverse log y=.95^x, y>= -5 - - # Min/max on task redness - currVal = - if task.value < -47.27 then -47.27 - else if task.value > 21.27 then 21.27 - else task.value - nextDelta = Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1) - - # Checklists - if task.checklist?.length > 0 - # If the Daily, only dock them them a portion based on their checklist completion - if direction is 'down' and task.type is 'daily' and options.cron - nextDelta *= (1 - _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) / task.checklist.length) - # If To-Do, point-match the TD per checklist item completed - if task.type is 'todo' - nextDelta *= (1 + _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0)) - + nextDelta = if reverse then calculateReverseDelta() else calculateDelta() 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 # ===== STRENGTH ===== @@ -915,7 +947,7 @@ api.wrap = (user, main=true) -> switch task.type when 'habit' - calculateDelta() + changeTaskValue() # Add habit value to habit-history (if different) if (delta > 0) then addPoints() else subtractPoints() @@ -929,11 +961,13 @@ api.wrap = (user, main=true) -> when 'daily' if options.cron - calculateDelta() + changeTaskValue() subtractPoints() task.streak = 0 unless user.stats.buffs.streaks else - calculateDelta() + changeTaskValue(delta < 0) + if delta < 0 + delta = calculateDelta() addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes if direction is 'up' task.streak = if task.streak then task.streak + 1 else 1 @@ -948,11 +982,13 @@ api.wrap = (user, main=true) -> when 'todo' if options.cron - calculateDelta() + changeTaskValue() #don't touch stats on cron else task.dateCompleted = if direction is 'up' then new Date else undefined - calculateDelta() + changeTaskValue(delta < 0) + if delta < 0 + delta = calculateDelta() addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes # MP++ per checklist item in ToDo, bonus per CLI multiplier = _.max([(_.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),1)),1]) @@ -965,7 +1001,7 @@ api.wrap = (user, main=true) -> when 'reward' # Don't adjust values for rewards - calculateDelta() + changeTaskValue() # purchase item stats.gp -= Math.abs(task.value) num = parseFloat(task.value).toFixed(2)