diff --git a/dist/habitrpg-shared.js b/dist/habitrpg-shared.js index 2d9e1572ff..b05afe1506 100644 --- a/dist/habitrpg-shared.js +++ b/dist/habitrpg-shared.js @@ -8131,7 +8131,7 @@ if(typeof module != 'undefined' && module.exports){ },{}],5:[function(require,module,exports){ (function() { - var HP, XP, hatchingPotions, helpers, items, moment, obj, pets, randomDrop, updateStats, _, _ref, + var HP, XP, hatchingPotions, helpers, items, moment, obj, pets, preenHistory, randomDrop, updateStats, _, _ref, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; moment = require('moment'); @@ -8675,9 +8675,74 @@ if(typeof module != 'undefined' && module.exports){ value: expTally }); paths["history"] = true; + obj.preenUserHistory(user); return user; }; + /* + 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 + of averages, condensing more the further back in time we go. Eg, 7 entries each for last 7 days; 1 entry each week + of this month; 1 entry for each month of this year; 1 entry per previous year: [day*7 week*4 month*12 year*infinite] + */ + + + preenHistory = function(history) { + var newHistory, preen, thisMonth; + history = _.filter(history, function(h) { + return !!h; + }); + newHistory = []; + preen = function(amount, groupBy) { + var groups; + groups = _.chain(history).groupBy(function(h) { + return moment(h.date).format(groupBy); + }).sortBy(function(h, k) { + return k; + }).value(); + groups = groups.slice(-amount); + groups.pop(); + return _.each(groups, function(group) { + newHistory.push({ + date: moment(group[0].date).toDate(), + value: _.reduce(group, (function(m, obj) { + return m + obj.value; + }), 0) / group.length + }); + return true; + }); + }; + preen(50, "YYYY"); + preen(moment().format('MM'), "YYYYMM"); + thisMonth = moment().format('YYYYMM'); + newHistory = newHistory.concat(_.filter(history, function(h) { + return moment(h.date).format('YYYYMM') === thisMonth; + })); + return newHistory; + }; + + obj.preenUserHistory = function(user) { + var minHistLen; + minHistLen = 7; + _.each(user.habits.concat(user.dailys), function(task) { + var _ref1; + if (((_ref1 = task.history) != null ? _ref1.length : void 0) > minHistLen) { + task.history = preenHistory(task.history); + } + return true; + }); + _.defaults(user.history, { + todos: [], + exp: [] + }); + if (user.history.exp.length > minHistLen) { + user.history.exp = preenHistory(user.history.exp); + } + if (user.history.todos.length > minHistLen) { + return user.history.todos = preenHistory(user.history.todos); + } + }; + }).call(this); @@ -8866,7 +8931,11 @@ var process=require("__browserify_process");(function() { weapon: 0, armor: 0, head: 0, - shield: 0 + shield: 0, + lastDrop: { + date: +(new Date), + count: 0 + } }, preferences: { gender: 'm', diff --git a/script/algos.coffee b/script/algos.coffee index f0659e3a76..43c34bb755 100644 --- a/script/algos.coffee +++ b/script/algos.coffee @@ -436,4 +436,56 @@ obj.cron = (user, options={}) -> expTally += obj.tnl(lvl) (user.history.exp ?= []).push { date: now, value: expTally } paths["history"] = true + obj.preenUserHistory(user) # we can probably start removing paths[...] stuff, no longer used by our app user + +### +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 +of averages, condensing more the further back in time we go. Eg, 7 entries each for last 7 days; 1 entry each week +of this month; 1 entry for each month of this year; 1 entry per previous year: [day*7 week*4 month*12 year*infinite] +### +preenHistory = (history) -> + history = _.filter(history, (h) -> !!h) # discard nulls (corrupted somehow) + newHistory = [] + preen = (amount, groupBy) -> + groups = _.chain(history) + .groupBy((h) -> moment(h.date).format groupBy) # get date groupings to average against + .sortBy((h, k) -> k) # sort by date + .value() # turn into an array + groups = groups.slice(-amount) + groups.pop() # get rid of "this week", "this month", etc (except for case of days) + _.each groups, (group) -> + newHistory.push + date: moment(group[0].date).toDate() + #date: moment(group[0].date).format('MM/DD/YYYY') # Use this one when testing + value: _.reduce(group, ((m, obj) -> m + obj.value), 0) / group.length # average + true + + # Keep the last: + preen 50, "YYYY" # 50 years (habit will toootally be around that long!) + preen moment().format('MM'), "YYYYMM" # last MM months (eg, if today is 05, keep the last 5 months) + + # Then keep all days of this month. Note, the extra logic is to account for Habits, which can be counted multiple times per day + # FIXME I'd rather keep 1-entry/week of this month, then last 'd' days in this week. However, I'm having issues where the 1st starts mid week + thisMonth = moment().format('YYYYMM') + newHistory = newHistory.concat _.filter(history, (h)-> moment(h.date).format('YYYYMM') is thisMonth) + #preen Math.ceil(moment().format('D')/7), "YYYYww" # last __ weeks (# weeks so far this month) + #newHistory = newHistory.concat(history.slice -moment().format('D')) # each day of this week + + newHistory + +# Registered users with some history +obj.preenUserHistory = (user) -> + minHistLen = 7 + _.each user.habits.concat(user.dailys), (task) -> + task.history = preenHistory(task.history) if task.history?.length > minHistLen + true + + _.defaults user.history, {todos:[], exp: []} + user.history.exp = preenHistory(user.history.exp) if user.history.exp.length > minHistLen + user.history.todos = preenHistory(user.history.todos) if user.history.todos.length > minHistLen + #user.markModified('history') + #user.markModified('habits') + #user.markModified('dailys') + diff --git a/tests/algos.mocha.coffee b/tests/algos.mocha.coffee index 3e81baf748..644434e021 100644 --- a/tests/algos.mocha.coffee +++ b/tests/algos.mocha.coffee @@ -221,6 +221,60 @@ describe 'Cron', -> afterTasks = after.habits.concat(after.dailys).concat(after.todos).concat(after.rewards) expect(beforeTasks).to.eql afterTasks + it.only 'should preen user history', -> + {before,after} = beforeAfter({daysAgo:1}) + history = [ + # Last year should be condensed to one entry, avg: 1 + {date:'09/01/2012', value: 0} + {date:'10/01/2012', value: 0} + {date:'11/01/2012', value: 2} + {date:'12/01/2012', value: 2} + + # Each month of this year should be condensed to 1/mo, averages follow + {date:'01/01/2013', value: 1} #2 + {date:'01/15/2013', value: 3} + + {date:'02/01/2013', value: 2} #3 + {date:'02/15/2013', value: 4} + + {date:'03/01/2013', value: 3} #4 + {date:'03/15/2013', value: 5} + + {date:'04/01/2013', value: 4} #5 + {date:'04/15/2013', value: 6} + + {date:'05/01/2013', value: 5} #6 + {date:'05/15/2013', value: 7} + + {date:'06/01/2013', value: 6} #7 + {date:'06/15/2013', value: 8} + + {date:'07/01/2013', value: 7} #8 + {date:'07/15/2013', value: 9} + + {date:'08/01/2013', value: 8} #9 + {date:'08/15/2013', value: 10} + + {date:'09/01/2013', value: 9} #10 + {date:'09/15/2013', value: 11} + + {date:'010/01/2013', value: 10} #11 + {date:'010/15/2013', value: 12} + + # This month should condense each week + {date:'011/01/2013', value: 12} + {date:'011/02/2013', value: 13} + {date:'011/03/2013', value: 14} + {date:'011/04/2013', value: 15} + ] + after.history = {exp: _.cloneDeep(history), todos: _.cloneDeep(history)} + after.habits[0].history = _.cloneDeep(history) + algos.cron(after) + console.log after.habits[0].history +# _.each [after.history.exp, after.history.todos, after.habits[0].history], (arr) -> +# expect(arr.length).to.be 15 +# expect(arr).to.eql [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + describe 'Todos', -> it '1 day missed', -> {before,after} = beforeAfter({daysAgo:1})