Skip to content

Commit bbc9162

Browse files
authored
[bot] Add rollback context to flagged player review (#302)
* Add rollback context to flagged player review * fix formatting
1 parent 305acb5 commit bbc9162

File tree

3 files changed

+72
-46
lines changed

3 files changed

+72
-46
lines changed

package-lock.json

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"@sapphire/discord.js-utilities": "^7.1.6",
4747
"@sentry/node": "^7.28.0",
4848
"@sentry/tracing": "^7.28.0",
49-
"@wise-old-man/utils": "^4.0.6",
49+
"@wise-old-man/utils": "^4.0.8",
5050
"axios": "^1.9.0",
5151
"canvas": "^2.6.1",
5252
"cors": "^2.8.5",

src/events/instances/PlayerFlaggedReview.ts

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import { AsyncResult, complete, errored, fromPromise, isErrored } from '@attio/fetchable';
22
import {
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';
1814
import {
@@ -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+
538565
export default new PlayerFlaggedReview();

0 commit comments

Comments
 (0)