From f653d83c1447c9aef69b3891bbc51072094484d9 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 6 Jan 2019 10:41:04 -0700 Subject: [PATCH] Implement retroactive achievements (for userStat types so far) --- art/themes/luciano_blocktronics/STATUS.ANS | Bin 4686 -> 4638 bytes art/themes/luciano_blocktronics/theme.hjson | 2 +- config/achievements.hjson | 8 +-- core/achievement.js | 56 ++++++++++++++++---- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/art/themes/luciano_blocktronics/STATUS.ANS b/art/themes/luciano_blocktronics/STATUS.ANS index 679e21d691e6973dfd63e41c32257b29735eff56..6871ff457b0b3d44ec533e785fac3b02aa03586e 100644 GIT binary patch delta 253 zcmX@7GEZf~5oYOV!-;q8r4^*3jm>iN@>5cQEW=z?KNmCUXoFk@AegMr=*$6@F4fPQ ze1S=ZH&->(&k!UHRBAMN31bnX!DMkJ!^w*o#U{rwWiT2}KF(yqXf*i`Q`6*nW-TCV z74!DV=`1>vC$X&Lwgy_1SpYQ9Ja@7Ss|rwcChLsJ+-!P4byjQ>CtqY!2eN*$ZDq8c zyop^O$bQ5=eR36t-sB%_ypy+bY-Ir&kTUr%m-OVxoU<9tC+l+^pZuLmYqA3OCPvfA nm$?l#Gw~=h34(1%OwPzmElbT!%_}M1Y{vJAnQ`l6O(9hPb2v~S delta 293 zcmbQIa!zH!5lIEdU)z8IDI@%ytI(p)9dtso6wK0fe;S3QpbDpfo z=*$VxRH~mh`5=?bB5#?RCg(A0PYz`j zpS*#2A*)d?Q1|2j7Tw8pEGsxc9H9M~1(OX~Re(CfSZ8nn?KA_48(2?%$EpW3LY8eJ z(72UsIzaX{wyi8+6MES7f!sap(I55a05Ty(KS!asYH|XH_~c~H zS&SBw|8X9le1uDT@&~SsjAoM;aT{#D%&o*E2y%gWZensqW@=e#Zfai1W;VW0%#2Sb I{}faO0Q$^X9{>OV diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index 28f17ff9..1dfeac55 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -984,7 +984,7 @@ achievements: { defaults: { format: "|08 > |10{title} |08(|11{points} |03points|08)\r\n\r\n {message}" - globalFformat: "|08 > |10{title} |08(|11{points} |03points|08)\r\n\r\n {message}" + globalformat: "|08 > |10{title} |08(|11{points} |03points|08)\r\n\r\n {message}" titleSGR: "|10" pointsSGR: "|12" textSGR: "|00|03" diff --git a/config/achievements.hjson b/config/achievements.hjson index 41bfd4c1..a711bff4 100644 --- a/config/achievements.hjson +++ b/config/achievements.hjson @@ -55,12 +55,11 @@ user_login_count: { type: userStat statName: login_count - retroactive: true match: { 2: { title: "Return Caller" globalText: "{userName} has returned to {boardName}!" - text: "You\"ve returned to {boardName}!" + text: "You've returned to {boardName}!" points: 5 } 10: { @@ -93,7 +92,6 @@ user_post_count: { type: userStat statName: post_count - retroactive: true match: { 5: { title: "Poster" @@ -125,7 +123,6 @@ user_upload_count: { type: userStat statName: ul_total_count - retroactive: true match: { 1: { title: "Uploader" @@ -164,7 +161,6 @@ user_download_count: { type: userStat statName: dl_total_count - retroactive: true match: { 1: { title: "Downloader" @@ -202,7 +198,6 @@ user_door_runs: { type: userStat statName: door_run_total_count - retroactive: true match: { 1: { title: "Nostalgia Toe Dip", @@ -240,7 +235,6 @@ user_door_total_minutes: { type: userStat statName: door_run_total_minutes - retroactive: true match: { 1: { title: "Nevermind!" diff --git a/core/achievement.js b/core/achievement.js index adfae332..f3a04f1f 100644 --- a/core/achievement.js +++ b/core/achievement.js @@ -37,6 +37,9 @@ const paths = require('path'); class Achievement { constructor(data) { this.data = data; + + // achievements are retroactive by default + this.data.retroactive = _.get(this.data, 'retroactive', true); } static factory(data) { @@ -87,6 +90,9 @@ class Achievement { class UserStatAchievement extends Achievement { constructor(data) { super(data); + + // sort match keys for quick match lookup + this.matchKeys = Object.keys(this.data.match || {}).map(k => parseInt(k)).sort( (a, b) => b - a); } isValid() { @@ -97,7 +103,7 @@ class UserStatAchievement extends Achievement { } getMatchDetails(matchValue) { - let matchField = Object.keys(this.data.match || {}).sort( (a, b) => b - a).find(v => matchValue >= v); + let matchField = this.matchKeys.find(v => matchValue >= v); if(matchField) { const match = this.data.match[matchField]; if(this.isValidMatchDetails(match)) { @@ -218,6 +224,22 @@ class Achievements { }); } + recordAndDisplayAchievement(info, cb) { + async.series( + [ + (callback) => { + return this.record(info, callback); + }, + (callback) => { + return this.display(info, callback); + } + ], + err => { + return cb(err); + } + ); + } + monitorUserStatUpdateEvents() { if(this.userStatEventListener) { return; // already listening @@ -287,15 +309,31 @@ class Achievements { timestamp : moment(), }; - return callback(null, info); - }, - (info, callback) => { - this.record(info, err => { - return callback(err, info); + const achievementsInfo = [ info ]; + if(true === achievement.data.retroactive) { + // For userStat, any lesser match keys(values) are also met. Example: + // matchKeys: [ 500, 200, 100, 20, 10, 2 ] + // ^---- we met here + // ^------------^ retroactive range + // + const index = achievement.matchKeys.findIndex(v => v < matchField); + if(index > -1) { + achievementsInfo.push(...achievement.matchKeys.slice(index).map(k => { + const [ d, f, v ] = achievement.getMatchDetails(k); + return Object.assign({}, info, { details : d, matchField : f, achievedValue : f, matchValue : v } ); + })); + } + } + + // reverse achievementsInfo so we display smallest > largest + achievementsInfo.reverse(); + + async.each(achievementsInfo, (achInfo, nextAchInfo) => { + return this.recordAndDisplayAchievement(achInfo, nextAchInfo); + }, + err => { + return callback(err); }); - }, - (info, callback) => { - return this.display(info, callback); } ], err => {