11import { AsyncResult , complete , errored , fromPromise , isErrored } from '@attio/fetchable' ;
22import {
3- ACTIVITIES ,
43 Activity ,
54 Boss ,
6- BOSSES ,
75 formatNumber ,
86 isActivity ,
97 isBoss ,
108 isSkill ,
119 MetricProps ,
1210 PlayerResponse ,
13- REAL_SKILLS ,
1411 Skill ,
15- SKILLS ,
1612 SnapshotResponse
1713} from '@wise-old-man/utils' ;
1814import {
@@ -35,10 +31,15 @@ interface PlayerFlaggedData {
3531 flagContext : {
3632 previous : SnapshotResponse ;
3733 rejected : SnapshotResponse ;
38- negativeGains : boolean ;
39- excessiveGains : boolean ;
40- possibleRollback : boolean ;
41- excessiveGainsReversed : boolean ;
34+ hasNegativeGains : boolean ;
35+ hasExcessiveGains : boolean ;
36+ hasExcessiveGainsReversed : boolean ;
37+ isPossibleRollback : boolean ;
38+ rollbackContext : {
39+ earliestMatchDate : string ;
40+ latestMatchDate : string ;
41+ totalMatches : number ;
42+ } | null ;
4243 data : {
4344 stackableGainedRatio : number ;
4445 previousEHP : number ;
@@ -68,7 +69,14 @@ class PlayerFlaggedReview implements Event {
6869 | { code : 'FAILED_TO_SEND_REVIEW_MESSAGE' }
6970 > {
7071 const { player, flagContext } = data ;
71- const { previous, rejected, possibleRollback, negativeGains, excessiveGains } = flagContext ;
72+ const {
73+ previous,
74+ rejected,
75+ rollbackContext,
76+ isPossibleRollback,
77+ hasNegativeGains,
78+ hasExcessiveGains
79+ } = flagContext ;
7280
7381 const {
7482 previousEHP,
@@ -89,29 +97,38 @@ class PlayerFlaggedReview implements Event {
8997 const uniqueId = `${ player . id } _${ new Date ( rejected . createdAt ) . getTime ( ) } ` ;
9098 const actions = new ActionRowBuilder < ButtonBuilder > ( ) ;
9199
92- const timeDiff = new Date ( rejected . createdAt ) . getTime ( ) - new Date ( previous . createdAt ) . getTime ( ) ;
100+ const timeDiff = getTimeDiff ( new Date ( rejected . createdAt ) , new Date ( previous . createdAt ) ) ;
93101
94102 const lines : string [ ] = [ ] ;
95103
96- if ( negativeGains ) {
104+ if ( hasNegativeGains ) {
97105 lines . push ( `**Main cause**: Negative gains` ) ;
98-
99- const hoursDiff = Math . floor ( timeDiff / 1000 / 60 / 60 ) ;
100-
101- if ( hoursDiff > 6 ) {
102- lines . push ( `**Time diff**: ${ hoursDiff } hours` ) ;
103- } else {
104- lines . push ( `**Time diff**: ${ Math . floor ( timeDiff / 1000 / 60 ) } minutes` ) ;
105- }
106-
106+ lines . push ( `**Time diff**: ${ timeDiff } ` ) ;
107107 lines . push ( `**Last updated**: <t:${ Math . floor ( new Date ( previous . createdAt ) . getTime ( ) / 1000 ) } :f>` ) ;
108108
109- if ( possibleRollback ) {
109+ if ( isPossibleRollback ) {
110110 lines . push ( `\n**🤔 Prediction 🤔**\n Name transfer (common) or Hiscores rollback (rare)` ) ;
111111 } else {
112112 lines . push ( `\n**🤔 Prediction 🤔**\n Name transfer` ) ;
113113 }
114114
115+ if ( rollbackContext !== null ) {
116+ const rollbackTimeDiff = getTimeDiff (
117+ new Date ( rollbackContext . latestMatchDate ) ,
118+ new Date ( rollbackContext . earliestMatchDate )
119+ ) ;
120+
121+ lines . push ( `\n**Rollback info:**` ) ;
122+ lines . push ( `Rollback matches: ${ rollbackContext . totalMatches } ` ) ;
123+ lines . push (
124+ `Earliest match: <t:${ Math . floor ( new Date ( rollbackContext . earliestMatchDate ) . getTime ( ) / 1000 ) } :f>`
125+ ) ;
126+ lines . push (
127+ `Latest match: <t:${ Math . floor ( new Date ( rollbackContext . latestMatchDate ) . getTime ( ) / 1000 ) } :f>`
128+ ) ;
129+ lines . push ( `Matches time diff: ${ rollbackTimeDiff } ` ) ;
130+ }
131+
115132 actions . addComponents (
116133 new ButtonBuilder ( )
117134 . setCustomId ( `name_transfer/${ uniqueId } ` )
@@ -145,23 +162,15 @@ class PlayerFlaggedReview implements Event {
145162 `\`${ formatNumber ( ehbDiff , false , 3 ) } \` (\`${ ehbChange } %\`)`
146163 ] . join ( ' · ' )
147164 ) ;
148- } else if ( excessiveGains ) {
165+ } else if ( hasExcessiveGains ) {
149166 const previousExp = previous . data . skills . overall . experience ;
150167 const rejectedExp = rejected . data . skills . overall . experience ;
151168
152169 const rankChange = getPercentageIncrease ( previousRank , rejectedRank ) ;
153170 const expChange = getPercentageIncrease ( previousExp , rejectedExp ) ;
154171
155172 lines . push ( `**Main cause**: Excessive gains` ) ;
156-
157- const hoursDiff = Math . floor ( timeDiff / 1000 / 60 / 60 ) ;
158-
159- if ( hoursDiff > 6 ) {
160- lines . push ( `**Time diff**: ${ hoursDiff } hours` ) ;
161- } else {
162- lines . push ( `**Time diff**: ${ Math . floor ( timeDiff / 1000 / 60 ) } minutes` ) ;
163- }
164-
173+ lines . push ( `**Time diff**: ${ timeDiff } ` ) ;
165174 lines . push ( `**Last updated**: <t:${ Math . floor ( new Date ( previous . createdAt ) . getTime ( ) / 1000 ) } :f>` ) ;
166175
167176 if ( stackableGainedRatio > 0.7 ) {
@@ -232,9 +241,13 @@ class PlayerFlaggedReview implements Event {
232241 ) ;
233242 }
234243
235- const realMetrics = [ ...SKILLS , ...BOSSES , ...ACTIVITIES ] ;
244+ const metrics = [
245+ ...Object . keys ( previous . data . skills ) ,
246+ ...Object . keys ( previous . data . bosses ) ,
247+ ...Object . keys ( previous . data . activities )
248+ ] ;
236249
237- const sameMetrics = realMetrics . map ( m => {
250+ const sameMetrics = metrics . map ( m => {
238251 let previousValue ;
239252 let rejectedValue ;
240253
@@ -258,7 +271,7 @@ class PlayerFlaggedReview implements Event {
258271
259272 const unrankedCount = sameMetrics . filter ( v => v === - 1 ) . length ;
260273
261- const rankedCount = realMetrics . length - unrankedCount ;
274+ const rankedCount = metrics . length - unrankedCount ;
262275 const equalityCount = sameMetrics . filter ( v => v !== null ) . length - unrankedCount ;
263276
264277 const equalityPercent = Math . round ( ( equalityCount / rankedCount ) * 100 ) ;
@@ -428,10 +441,10 @@ function getLargestSkillChanges(previous: SnapshotResponse, rejected: SnapshotRe
428441
429442 const map = new Map < Skill , number > ( ) ;
430443
431- REAL_SKILLS . map ( s => {
444+ Object . keys ( previous . data . skills ) . map ( s => {
432445 if ( rejected . data . skills [ s ] . experience === - 1 ) return ;
433446 map . set (
434- s ,
447+ s as Skill ,
435448 Math . max ( 0 , rejected . data . skills [ s ] . experience ) - Math . max ( 0 , previous . data . skills [ s ] . experience )
436449 ) ;
437450 } ) ;
@@ -465,8 +478,11 @@ function getLargestBossChanges(previous: SnapshotResponse, rejected: SnapshotRes
465478
466479 const map = new Map < Boss , number > ( ) ;
467480
468- BOSSES . map ( b => {
469- map . set ( b , Math . max ( 0 , rejected . data . bosses [ b ] . kills ) - Math . max ( 0 , previous . data . bosses [ b ] . kills ) ) ;
481+ Object . keys ( previous . data . bosses ) . map ( b => {
482+ map . set (
483+ b as Boss ,
484+ Math . max ( 0 , rejected . data . bosses [ b ] . kills ) - Math . max ( 0 , previous . data . bosses [ b ] . kills )
485+ ) ;
470486 } ) ;
471487
472488 const entries = Array . from ( map . entries ( ) ) . sort ( ( a , b ) => b [ 1 ] - a [ 1 ] ) ;
@@ -498,9 +514,9 @@ function getLargestActivityChanges(previous: SnapshotResponse, rejected: Snapsho
498514
499515 const map = new Map < Activity , number > ( ) ;
500516
501- ACTIVITIES . map ( a => {
517+ Object . keys ( previous . data . activities ) . map ( a => {
502518 map . set (
503- a ,
519+ a as Activity ,
504520 Math . max ( 0 , rejected . data . activities [ a ] . score ) - Math . max ( 0 , previous . data . activities [ a ] . score )
505521 ) ;
506522 } ) ;
@@ -535,4 +551,15 @@ function getPercentageIncrease(previous: number, current: number) {
535551 return ( current - previous ) / previous ;
536552}
537553
554+ function getTimeDiff ( a : Date , b : Date ) {
555+ const timeDiff = a . getTime ( ) - b . getTime ( ) ;
556+ const hoursDiff = Math . floor ( timeDiff / 1000 / 60 / 60 ) ;
557+
558+ if ( hoursDiff > 6 ) {
559+ return `${ hoursDiff } hours` ;
560+ }
561+
562+ return `${ Math . floor ( timeDiff / 1000 / 60 ) } minutes` ;
563+ }
564+
538565export default new PlayerFlaggedReview ( ) ;
0 commit comments