Files
habitica/common/script/preenUserHistory.js

89 lines
3.1 KiB
JavaScript

import _ from 'lodash';
import moment from 'moment';
// Aggregate entries
function _aggregate (history, aggregateBy) {
return _.chain(history)
.groupBy(entry => { // group entries by aggregateBy
return moment(entry.date).format(aggregateBy);
})
.sortBy((entry, key) => key) // sort by date
.map(entries => {
return {
date: Number(entries[0].date),
value: _.reduce(entries, (previousValue, entry) => {
return previousValue + entry.value;
}, 0) / entries.length,
};
})
.value();
}
/* Preen an array of history entries
Free users:
- 1 value for each day of the past 60 days (no compression)
- 1 value each month for the previous 10 months
- 1 value each year for the previous years
Subscribers and challenges:
- 1 value for each day of the past 365 days (no compression)
- 1 value each month for the previous 12 months
- 1 value each year for the previous years
*/
export function preenHistory (history, isSubscribed, timezoneOffset) {
history = _.filter(history, historyEntry => Boolean(historyEntry)); // Filter missing entries
let now = timezoneOffset ? moment().zone(timezoneOffset) : moment();
// Date after which to begin compressing data
let cutOff = now.subtract(isSubscribed ? 365 : 60, 'days').startOf('day');
// Keep uncompressed entries (modifies history)
let newHistory = _.remove(history, entry => {
let date = moment(entry.date);
return date.isSame(cutOff) || date.isAfter(cutOff);
});
// Date after which to begin compressing data by year
let monthsCutOff = cutOff.subtract(isSubscribed ? 12 : 10, 'months').startOf('day');
let aggregateByMonth = _.remove(history, entry => {
let date = moment(entry.date);
return date.isSame(monthsCutOff) || date.isAfter(monthsCutOff);
});
// Aggregate remaining entries by month and year
if (aggregateByMonth.length > 0) newHistory.unshift(..._aggregate(aggregateByMonth, 'YYYYMM'));
if (history.length > 0) newHistory.unshift(..._aggregate(history, 'YYYY'));
return newHistory;
}
// Preen history for users and tasks. This code runs only on the server.
export function preenUserHistory (user) {
let isSubscribed = user.purchased && user.purchased.plan && user.purchased.plan.customerId;
let minHistoryLength = isSubscribed ? 365 : 60;
function _processTask (task, index) {
if (task.history && task.history.length > minHistoryLength) {
task.history = preenHistory(task.history, isSubscribed, user.preferences.timezoneOffset);
if (user.markModified) user.markModified(`${task.type}s.${index}.history`);
}
}
_.each(user.habits, _processTask);
_.each(user.dailys, _processTask);
_.defaults(user.history, {
todos: [],
exp: [],
});
if (user.history.exp.length > minHistoryLength) {
user.history.exp = preenHistory(user.history.exp, isSubscribed, user.preferences.timezoneOffset);
user.markModified('history.exp');
}
if (user.history.todos.length > minHistoryLength) {
user.history.todos = preenHistory(user.history.todos, isSubscribed, user.preferences.timezoneOffset);
user.markModified('history.todos');
}
}