Skip to content

Commit f3ca0e4

Browse files
fix: exclude milestone quests from community pulse stats (#3808)
1 parent 0331998 commit f3ca0e4

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

__tests__/leaderboard.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,95 @@ describe('leaderboard', () => {
10101010
},
10111011
});
10121012
});
1013+
1014+
it('should exclude milestone quests from all stats', async () => {
1015+
const now = new Date();
1016+
const { periodStart: weekStart } = getQuestWindow(QuestType.Weekly, now);
1017+
1018+
await saveFixtures(con, Quest, [
1019+
{
1020+
id: '00000000-0000-0000-0000-000000000301',
1021+
name: 'Daily Quest',
1022+
description: 'A daily quest',
1023+
type: QuestType.Daily,
1024+
eventType: QuestEventType.HotTakeVote,
1025+
criteria: { targetCount: 1 },
1026+
active: true,
1027+
},
1028+
{
1029+
id: '00000000-0000-0000-0000-000000000302',
1030+
name: 'Read 1000 Articles',
1031+
description: 'A milestone quest',
1032+
type: QuestType.Milestone,
1033+
eventType: QuestEventType.BriefRead,
1034+
criteria: { targetCount: 1000 },
1035+
active: true,
1036+
},
1037+
]);
1038+
1039+
await saveFixtures(con, QuestRotation, [
1040+
{
1041+
id: '00000000-0000-0000-0000-000000000311',
1042+
questId: '00000000-0000-0000-0000-000000000301',
1043+
type: QuestType.Daily,
1044+
plusOnly: false,
1045+
slot: 1,
1046+
periodStart: weekStart,
1047+
periodEnd: new Date(weekStart.getTime() + 24 * 60 * 60 * 1000),
1048+
},
1049+
{
1050+
id: '00000000-0000-0000-0000-000000000312',
1051+
questId: '00000000-0000-0000-0000-000000000302',
1052+
type: QuestType.Milestone,
1053+
plusOnly: false,
1054+
slot: 1,
1055+
periodStart: new Date('2024-01-01'),
1056+
periodEnd: new Date('2099-01-01'),
1057+
},
1058+
]);
1059+
1060+
await con.getRepository(UserQuest).save([
1061+
{
1062+
userId: '1',
1063+
rotationId: '00000000-0000-0000-0000-000000000311',
1064+
status: UserQuestStatus.Completed,
1065+
progress: 1,
1066+
completedAt: new Date(weekStart.getTime() + 2 * 60 * 60 * 1000),
1067+
},
1068+
{
1069+
userId: '1',
1070+
rotationId: '00000000-0000-0000-0000-000000000312',
1071+
status: UserQuestStatus.Completed,
1072+
progress: 1000,
1073+
completedAt: new Date(weekStart.getTime() + 3 * 60 * 60 * 1000),
1074+
},
1075+
{
1076+
userId: '2',
1077+
rotationId: '00000000-0000-0000-0000-000000000312',
1078+
status: UserQuestStatus.Claimed,
1079+
progress: 1000,
1080+
completedAt: new Date(weekStart.getTime() + 4 * 60 * 60 * 1000),
1081+
claimedAt: new Date(weekStart.getTime() + 5 * 60 * 60 * 1000),
1082+
},
1083+
]);
1084+
1085+
const res = await client.query(QUEST_COMPLETION_STATS_QUERY);
1086+
1087+
expect(res.errors).toBeFalsy();
1088+
expect(res.data.questCompletionStats).toMatchObject({
1089+
totalCount: 1,
1090+
allTimeLeader: {
1091+
questId: '00000000-0000-0000-0000-000000000301',
1092+
questName: 'Daily Quest',
1093+
count: 1,
1094+
},
1095+
weeklyLeader: {
1096+
questId: '00000000-0000-0000-0000-000000000301',
1097+
questName: 'Daily Quest',
1098+
count: 1,
1099+
},
1100+
});
1101+
});
10131102
});
10141103

10151104
describe('popularHotTakes', () => {

src/schema/leaderboard.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ const completedQuestStatuses = [
214214
UserQuestStatus.Claimed,
215215
];
216216

217+
const communityPulseQuestTypes = [QuestType.Daily, QuestType.Weekly];
218+
217219
const completedQuestTimestampExpression = `COALESCE(uq."completedAt", uq."claimedAt", uq."updatedAt")`;
218220

219221
const getUserLeaderboardForStat = async ({
@@ -346,6 +348,9 @@ const getTopCompletedQuest = async ({
346348
completedStatuses: completedQuestStatuses,
347349
})
348350
.andWhere('uq."userId" NOT IN (:...excludedUsers)', { excludedUsers })
351+
.andWhere('qr.type IN (:...communityPulseQuestTypes)', {
352+
communityPulseQuestTypes,
353+
})
349354
.andWhere(`${completedQuestTimestampExpression} IS NOT NULL`)
350355
.groupBy('q.id')
351356
.addGroupBy('q.name')
@@ -392,11 +397,15 @@ const getQuestCompletionStats = async ({
392397
con
393398
.createQueryBuilder()
394399
.from(UserQuest, 'uq')
400+
.innerJoin(QuestRotation, 'qr', 'qr.id = uq."rotationId"')
395401
.select('COUNT(*)', 'count')
396402
.where('uq.status IN (:...completedStatuses)', {
397403
completedStatuses: completedQuestStatuses,
398404
})
399405
.andWhere('uq."userId" NOT IN (:...excludedUsers)', { excludedUsers })
406+
.andWhere('qr.type IN (:...communityPulseQuestTypes)', {
407+
communityPulseQuestTypes,
408+
})
400409
.andWhere(`${completedQuestTimestampExpression} IS NOT NULL`)
401410
.getRawOne<{ count: number | string }>(),
402411
getTopCompletedQuest({ con }),

0 commit comments

Comments
 (0)