add preen_history to user cron (see

https://github.com/HabitRPG/habitrpg/issues/1492), to cut back on user
object sizes (and hopefully angular performance) dramatically. Start
writing tests, but they're not complete. @djuretic could you take a peak
at this? My brain is melting
This commit is contained in:
Tyler Renelle 2013-11-05 17:10:31 -08:00
parent f0cc17bfaf
commit 5482a83a00
3 changed files with 177 additions and 2 deletions

View file

@ -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',

View file

@ -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')

View file

@ -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})