Achievements are now recorded in more detail such that they can be retrieved *as they were* at the time of earning

This commit is contained in:
Bryan Ashby 2019-01-20 21:58:00 -07:00
parent 18a7a79f14
commit 16e903d4c6
2 changed files with 96 additions and 27 deletions

View File

@ -22,7 +22,10 @@ const {
ErrorReasons ErrorReasons
} = require('./enig_error.js'); } = require('./enig_error.js');
const { getThemeArt } = require('./theme.js'); const { getThemeArt } = require('./theme.js');
const { pipeToAnsi } = require('./color_codes.js'); const {
pipeToAnsi,
stripMciColorCodes
} = require('./color_codes.js');
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const StatLog = require('./stat_log.js'); const StatLog = require('./stat_log.js');
const Log = require('./logger.js').log; const Log = require('./logger.js').log;
@ -127,6 +130,56 @@ class Achievements {
this.events = events; this.events = events;
} }
getAchievementsEarnedByUser(userId, cb) {
if(!this.isEnabled()) {
return cb(Errors.General('Achievements not enabled', ErrorReasons.Disabled));
}
UserDb.all(
`SELECT achievement_tag, timestamp, match, title, text, points
FROM user_achievement
WHERE user_id = ?
ORDER BY DATETIME(timestamp);`,
[ userId ],
(err, rows) => {
if(err) {
return cb(err);
}
const earned = rows.map(row => {
const achievement = Achievement.factory(this.achievementConfig.achievements[row.achievement_tag]);
if(!achievement) {
return;
}
const earnedInfo = {
achievementTag : row.achievement_tag,
type : achievement.data.type,
retroactive : achievement.data.retroactive,
title : row.title,
text : row.text,
points : row.points,
};
switch(earnedInfo.type) {
case [ Achievement.Types.UserStatSet ] :
case [ Achievement.Types.UserStatInc ] :
earnedInfo.statName = achievement.data.statName;
break;
}
return earnedInfo;
}).filter(a => a); // remove any empty records (ie: no achievement.hjson entry exists anymore).
return cb(null, earned);
}
);
}
isEnabled() {
return !_.isUndefined(this.achievementConfig);
}
init(cb) { init(cb) {
let achievementConfigPath = _.get(Config(), 'general.achievementFile'); let achievementConfigPath = _.get(Config(), 'general.achievementFile');
if(!achievementConfigPath) { if(!achievementConfigPath) {
@ -188,14 +241,19 @@ class Achievements {
); );
} }
record(info, cb) { record(info, localInterruptItem, cb) {
StatLog.incrementUserStat(info.client.user, UserProps.AchievementTotalCount, 1); StatLog.incrementUserStat(info.client.user, UserProps.AchievementTotalCount, 1);
StatLog.incrementUserStat(info.client.user, UserProps.AchievementTotalPoints, info.details.points); StatLog.incrementUserStat(info.client.user, UserProps.AchievementTotalPoints, info.details.points);
const recordData = [
info.client.user.userId, info.achievementTag, getISOTimestampString(info.timestamp), info.matchField,
stripMciColorCodes(localInterruptItem.title), stripMciColorCodes(localInterruptItem.achievText), info.details.points,
];
UserDb.run( UserDb.run(
`INSERT OR IGNORE INTO user_achievement (user_id, achievement_tag, timestamp, match) `INSERT OR IGNORE INTO user_achievement (user_id, achievement_tag, timestamp, match, title, text, points)
VALUES (?, ?, ?, ?);`, VALUES (?, ?, ?, ?, ?, ?, ?);`,
[ info.client.user.userId, info.achievementTag, getISOTimestampString(info.timestamp), info.matchField ], recordData,
err => { err => {
if(err) { if(err) {
return cb(err); return cb(err);
@ -215,12 +273,7 @@ class Achievements {
); );
} }
display(info, cb) { display(info, interruptItems, cb) {
this.createAchievementInterruptItems(info, (err, interruptItems) => {
if(err) {
return cb(err);
}
if(interruptItems.local) { if(interruptItems.local) {
UserInterruptQueue.queue(interruptItems.local, { clients : info.client } ); UserInterruptQueue.queue(interruptItems.local, { clients : info.client } );
} }
@ -230,17 +283,21 @@ class Achievements {
} }
return cb(null); return cb(null);
});
} }
recordAndDisplayAchievement(info, cb) { recordAndDisplayAchievement(info, cb) {
async.series( async.waterfall(
[ [
(callback) => { (callback) => {
return this.record(info, callback); return this.createAchievementInterruptItems(info, callback);
}, },
(callback) => { (interruptItems, callback) => {
return this.display(info, callback); this.record(info, interruptItems.local, err => {
return callback(err, interruptItems);
});
},
(interruptItems, callback) => {
return this.display(info, interruptItems, callback);
} }
], ],
err => { err => {
@ -394,7 +451,7 @@ class Achievements {
userAffils : info.user.properties[UserProps.Affiliations], userAffils : info.user.properties[UserProps.Affiliations],
nodeId : info.client.node, nodeId : info.client.node,
title : info.details.title, title : info.details.title,
text : info.global ? info.details.globalText : info.details.text, //text : info.global ? info.details.globalText : info.details.text,
points : info.details.points, points : info.details.points,
achievedValue : info.achievedValue, achievedValue : info.achievedValue,
matchField : info.matchField, matchField : info.matchField,
@ -480,6 +537,8 @@ class Achievements {
(headerArt, footerArt, callback) => { (headerArt, footerArt, callback) => {
const itemText = 'global' === itemType ? globalText : text; const itemText = 'global' === itemType ? globalText : text;
interruptItems[itemType] = { interruptItems[itemType] = {
title,
achievText : itemText,
text : `${title}\r\n${itemText}`, text : `${title}\r\n${itemText}`,
pause : true, pause : true,
}; };
@ -518,5 +577,12 @@ let achievements;
exports.moduleInitialize = (initInfo, cb) => { exports.moduleInitialize = (initInfo, cb) => {
achievements = new Achievements(initInfo.events); achievements = new Achievements(initInfo.events);
return achievements.init(cb); achievements.init( err => {
if(err) {
return cb(err);
}
exports.achievements = achievements;
return cb(null);
});
}; };

View File

@ -195,6 +195,9 @@ const DB_INIT_TABLE = {
achievement_tag VARCHAR NOT NULL, achievement_tag VARCHAR NOT NULL,
timestamp DATETIME NOT NULL, timestamp DATETIME NOT NULL,
match VARCHAR NOT NULL, match VARCHAR NOT NULL,
title VARCHAR NOT NULL,
text VARCHAR NOT NULL,
points INTEGER NOT NULL,
UNIQUE(user_id, achievement_tag, match), UNIQUE(user_id, achievement_tag, match),
FOREIGN KEY(user_id) REFERENCES user(id) ON DELETE CASCADE FOREIGN KEY(user_id) REFERENCES user(id) ON DELETE CASCADE
);` );`