Habits: store one history entry per day (#10442)

* initial refactor

* add scoredUp and scoredDown values for habits history entries, one entry per habit per day

* fix lint and add initial migration

* update old test

* remove scoreNotes

* dry run for migration

* migration fixes

* update migration and remove old test

* fix

* add challenges migration (read only)

* fix challenges migration

* handle custom day start

* update tasks in migration

* scoring: support cds

* add new test
This commit is contained in:
Matteo Pagliazzi
2018-06-21 21:25:19 +02:00
committed by GitHub
parent 8437b916c4
commit c1bd7f5dc5
11 changed files with 421 additions and 67 deletions

View File

@@ -2,10 +2,12 @@ import _ from 'lodash';
import moment from 'moment';
// Aggregate entries
function _aggregate (history, aggregateBy) {
function _aggregate (history, aggregateBy, timezoneOffset, dayStart) {
return _.chain(history)
.groupBy(entry => { // group entries by aggregateBy
return moment(entry.date).format(aggregateBy);
const entryDate = moment(entry.date).zone(timezoneOffset);
if (entryDate.hour() < dayStart) entryDate.subtract(1, 'day');
return entryDate.format(aggregateBy);
})
.toPairs() // [key, entry]
.sortBy(([key]) => key) // sort by date
@@ -31,27 +33,29 @@ Subscribers and challenges:
- 1 value each month for the previous 12 months
- 1 value each year for the previous years
*/
export function preenHistory (history, isSubscribed, timezoneOffset) {
export function preenHistory (history, isSubscribed, timezoneOffset = 0, dayStart = 0) {
// history = _.filter(history, historyEntry => Boolean(historyEntry)); // Filter missing entries
let now = timezoneOffset ? moment().zone(timezoneOffset) : moment();
const now = moment().zone(timezoneOffset);
// Date after which to begin compressing data
let cutOff = now.subtract(isSubscribed ? 365 : 60, 'days').startOf('day');
const cutOff = now.subtract(isSubscribed ? 365 : 60, 'days').startOf('day');
// Keep uncompressed entries (modifies history and returns removed items)
let newHistory = _.remove(history, entry => {
let date = moment(entry.date);
return date.isSame(cutOff) || date.isAfter(cutOff);
const entryDate = moment(entry.date).zone(timezoneOffset);
if (entryDate.hour() < dayStart) entryDate.subtract(1, 'day');
return entryDate.isSame(cutOff) || entryDate.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);
const entryDate = moment(entry.date).zone(timezoneOffset);
if (entryDate.hour() < dayStart) entryDate.subtract(1, 'day');
return entryDate.isSame(monthsCutOff) || entryDate.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'));
if (aggregateByMonth.length > 0) newHistory.unshift(..._aggregate(aggregateByMonth, 'YYYYMM', timezoneOffset, dayStart));
if (history.length > 0) newHistory.unshift(..._aggregate(history, 'YYYY', timezoneOffset, dayStart));
return newHistory;
}
@@ -60,11 +64,12 @@ export function preenHistory (history, isSubscribed, timezoneOffset) {
export function preenUserHistory (user, tasksByType) {
let isSubscribed = user.isSubscribed();
let timezoneOffset = user.preferences.timezoneOffset;
let dayStart = user.preferences.dayStart;
let minHistoryLength = isSubscribed ? 365 : 60;
function _processTask (task) {
if (task.history && task.history.length > minHistoryLength) {
task.history = preenHistory(task.history, isSubscribed, timezoneOffset);
task.history = preenHistory(task.history, isSubscribed, timezoneOffset, dayStart);
task.markModified('history');
}
}
@@ -73,12 +78,12 @@ export function preenUserHistory (user, tasksByType) {
tasksByType.dailys.forEach(_processTask);
if (user.history.exp.length > minHistoryLength) {
user.history.exp = preenHistory(user.history.exp, isSubscribed, timezoneOffset);
user.history.exp = preenHistory(user.history.exp, isSubscribed, timezoneOffset, dayStart);
user.markModified('history.exp');
}
if (user.history.todos.length > minHistoryLength) {
user.history.todos = preenHistory(user.history.todos, isSubscribed, timezoneOffset);
user.history.todos = preenHistory(user.history.todos, isSubscribed, timezoneOffset, dayStart);
user.markModified('history.todos');
}
}