mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
add cliff for completed todos and PMs
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import scoreTask from './scoreTask';
|
import scoreTask from './scoreTask';
|
||||||
|
import preenUserHistory from './preenHistory';
|
||||||
import common from '../../';
|
import common from '../../';
|
||||||
import {
|
import {
|
||||||
shouldDo,
|
shouldDo,
|
||||||
@@ -20,7 +21,7 @@ let clearBuffs = {
|
|||||||
// Make sure to run this function once in a while as server will not take care of overnight calculations.
|
// Make sure to run this function once in a while as server will not take care of overnight calculations.
|
||||||
// And you have to run it every time client connects.
|
// And you have to run it every time client connects.
|
||||||
export default function cron (options = {}) {
|
export default function cron (options = {}) {
|
||||||
let {user, tasks, tasksByType, analytics, now, daysMissed} = options;
|
let {user, tasksByType, analytics, now, daysMissed} = options;
|
||||||
|
|
||||||
user.auth.timestamps.loggedin = now;
|
user.auth.timestamps.loggedin = now;
|
||||||
user.lastCron = now;
|
user.lastCron = now;
|
||||||
@@ -93,8 +94,7 @@ export default function cron (options = {}) {
|
|||||||
// Tally each task
|
// Tally each task
|
||||||
let todoTally = 0;
|
let todoTally = 0;
|
||||||
|
|
||||||
tasksByType.todos.forEach((task) => { // make uncompleted todos redder
|
tasksByType.todos.forEach(task => { // make uncompleted todos redder
|
||||||
let completed = task.completed;
|
|
||||||
scoreTask({
|
scoreTask({
|
||||||
task,
|
task,
|
||||||
user,
|
user,
|
||||||
@@ -104,8 +104,7 @@ export default function cron (options = {}) {
|
|||||||
// TODO pass req for analytics?
|
// TODO pass req for analytics?
|
||||||
});
|
});
|
||||||
|
|
||||||
let absVal = completed ? Math.abs(task.value) : task.value;
|
todoTally += task.value;
|
||||||
todoTally += absVal;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let dailyChecked = 0; // how many dailies were checked?
|
let dailyChecked = 0; // how many dailies were checked?
|
||||||
@@ -184,7 +183,8 @@ export default function cron (options = {}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Finished tallying
|
// Finished tallying
|
||||||
user.history.todos({date: now, value: todoTally});
|
user.history.todos.push({date: now, value: todoTally});
|
||||||
|
|
||||||
// tally experience
|
// tally experience
|
||||||
let expTally = user.stats.exp;
|
let expTally = user.stats.exp;
|
||||||
let lvl = 0; // iterator
|
let lvl = 0; // iterator
|
||||||
@@ -197,7 +197,7 @@ export default function cron (options = {}) {
|
|||||||
// preen user history so that it doesn't become a performance problem
|
// preen user history so that it doesn't become a performance problem
|
||||||
// also for subscribed users but differentyly
|
// also for subscribed users but differentyly
|
||||||
// premium subscribers can keep their full history.
|
// premium subscribers can keep their full history.
|
||||||
user.fns.preenUserHistory(tasks);
|
preenUserHistory(user, tasksByType);
|
||||||
|
|
||||||
if (perfect) {
|
if (perfect) {
|
||||||
user.achievements.perfect++;
|
user.achievements.perfect++;
|
||||||
@@ -231,6 +231,19 @@ export default function cron (options = {}) {
|
|||||||
_.merge(progress, {down: 0, up: 0});
|
_.merge(progress, {down: 0, up: 0});
|
||||||
progress.collect = _.transform(progress.collect, (m, v, k) => m[k] = 0);
|
progress.collect = _.transform(progress.collect, (m, v, k) => m[k] = 0);
|
||||||
|
|
||||||
|
// Clean PMs - keep 200 for subscribers and 50 for free users
|
||||||
|
let maxPMs = user.isSubscribed() ? 200 : 50; // TODO 200 limit for contributors too
|
||||||
|
let numberOfPMs = Object.keys(user.inbox.messages).length;
|
||||||
|
if (Object.keys(user.inbox.messages).length > maxPMs) {
|
||||||
|
_(user.inbox.messages)
|
||||||
|
.sortBy('timestamp')
|
||||||
|
.takeRight(numberOfPMs - maxPMs)
|
||||||
|
.each(pm => {
|
||||||
|
user.inbox.messages[pm.id] = undefined;
|
||||||
|
}).value();
|
||||||
|
|
||||||
|
user.markModified('inbox.messages');
|
||||||
|
}
|
||||||
|
|
||||||
// Analytics
|
// Analytics
|
||||||
user.flags.cronCount++;
|
user.flags.cronCount++;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
daysSince,
|
daysSince,
|
||||||
} from '../../../../common/script/cron';
|
} from '../../../../common/script/cron';
|
||||||
@@ -15,7 +16,7 @@ export default function cronMiddleware (req, res, next) {
|
|||||||
let now = new Date();
|
let now = new Date();
|
||||||
let daysMissed = daysSince(user.lastCron, _.defaults({now}, user.preferences));
|
let daysMissed = daysSince(user.lastCron, _.defaults({now}, user.preferences));
|
||||||
|
|
||||||
if (daysMissed <= 0) return next(null, user); // TODO why are we passing user down here?
|
if (daysMissed <= 0) return next();
|
||||||
|
|
||||||
// Fetch active tasks (no completed todos)
|
// Fetch active tasks (no completed todos)
|
||||||
Task.find({
|
Task.find({
|
||||||
@@ -30,13 +31,23 @@ export default function cronMiddleware (req, res, next) {
|
|||||||
tasks.forEach(task => tasksByType[`${task.type}s`].push(task));
|
tasks.forEach(task => tasksByType[`${task.type}s`].push(task));
|
||||||
|
|
||||||
// Run cron
|
// Run cron
|
||||||
cron({user, tasks, tasksByType, now, daysMissed, analytics});
|
cron({user, tasksByType, now, daysMissed, analytics});
|
||||||
|
|
||||||
|
// Clean completed todos - 30 days for free users, 90 for subscribers
|
||||||
|
Task.remove({
|
||||||
|
userId: user._id,
|
||||||
|
type: 'todo',
|
||||||
|
completed: true,
|
||||||
|
dateCompleted: {
|
||||||
|
$lt: moment(now).subtract(user.isSubscribed() ? 90 : 30, 'days'),
|
||||||
|
},
|
||||||
|
}).exec(); // TODO catch error or at least log it
|
||||||
|
|
||||||
let ranCron = user.isModified();
|
let ranCron = user.isModified();
|
||||||
let quest = common.content.quests[user.party.quest.key];
|
let quest = common.content.quests[user.party.quest.key];
|
||||||
|
|
||||||
// if (ranCron) res.locals.wasModified = true; // TODO remove?
|
// if (ranCron) res.locals.wasModified = true; // TODO remove?
|
||||||
if (!ranCron) return next(null, user); // TODO why are we passing user to next?
|
if (!ranCron) return next();
|
||||||
// TODO Group.tavernBoss(user, progress);
|
// TODO Group.tavernBoss(user, progress);
|
||||||
if (!quest || true /* TODO remove */) return user.save(next);
|
if (!quest || true /* TODO remove */) return user.save(next);
|
||||||
|
|
||||||
|
|||||||
@@ -450,7 +450,9 @@ export let schema = new Schema({
|
|||||||
inbox: {
|
inbox: {
|
||||||
newMessages: {type: Number, default: 0},
|
newMessages: {type: Number, default: 0},
|
||||||
blocks: {type: Array, default: []},
|
blocks: {type: Array, default: []},
|
||||||
messages: {type: Schema.Types.Mixed, default: {}},
|
messages: {type: Schema.Types.Mixed, default: () => {
|
||||||
|
return {};
|
||||||
|
}},
|
||||||
optOut: {type: Boolean, default: false},
|
optOut: {type: Boolean, default: false},
|
||||||
},
|
},
|
||||||
tasksOrder: {
|
tasksOrder: {
|
||||||
|
|||||||
Reference in New Issue
Block a user