From 71c2168fa25ead2ac755658af2dfca04fcd1ff43 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:55:35 +1100 Subject: [PATCH] Leaderboard fixes and tests --- src/lib/util/clLeaderboard.ts | 20 ++++++++++--------- src/mahoji/commands/testpotato.ts | 20 ++++++++++++++++++- tests/integration/misc.test.ts | 32 +++++++++++++++++++++++++++++++ tests/integration/setup.ts | 6 ++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/lib/util/clLeaderboard.ts b/src/lib/util/clLeaderboard.ts index c3d35cb8be..5100fd90fd 100644 --- a/src/lib/util/clLeaderboard.ts +++ b/src/lib/util/clLeaderboard.ts @@ -19,15 +19,18 @@ export async function fetchCLLeaderboard({ const userEventMap = userEventsToMap(userEvents); const userIds = Array.from(userEventMap.keys()); if (method === 'cl_array') { - const [specificUsers, generalUsers] = await prisma.$transaction([ - prisma.$queryRawUnsafe<{ id: string; qty: number }[]>(` + const userIdsList = userIds.length > 0 ? userIds.map(i => `'${i}'`).join(', ') : 'NULL'; + const specificUsers = + userIds.length > 0 + ? await prisma.$queryRawUnsafe<{ id: string; qty: number }[]>(` SELECT user_id::text AS id, CARDINALITY(cl_array) - CARDINALITY(cl_array - array[${items .map(i => `${i}`) .join(', ')}]) AS qty FROM user_stats - WHERE user_id::text in (${userIds.map(i => `'${i}'`).join(', ')}) -`), - prisma.$queryRawUnsafe<{ id: string; qty: number }[]>(` + WHERE user_id::text IN (${userIdsList}) +`) + : []; + const generalUsers = await prisma.$queryRawUnsafe<{ id: string; qty: number }[]>(` SELECT user_id::text AS id, CARDINALITY(cl_array) - CARDINALITY(cl_array - array[${items .map(i => `${i}`) .join(', ')}]) AS qty @@ -35,11 +38,10 @@ export async function fetchCLLeaderboard({ ${ironmenOnly ? 'INNER JOIN "users" on "users"."id" = "user_stats"."user_id"::text' : ''} WHERE (cl_array && array[${items.map(i => `${i}`).join(', ')}] ${ironmenOnly ? 'AND "users"."minion.ironman" = true' : ''}) - AND user_id::text NOT IN (${userIds.map(i => `'${i}'`).join(', ')}) + ${userIds.length > 0 ? `AND user_id::text NOT IN (${userIdsList})` : ''} ORDER BY qty DESC LIMIT ${resultLimit} -`) - ]); +`); const users = [...specificUsers, ...generalUsers] .sort((a, b) => { @@ -75,7 +77,7 @@ SELECT id, (cardinality(u.cl_keys) - u.inverse_length) as qty FROM users WHERE ("collectionLogBank" ?| array[${items.map(i => `'${i}'`).join(', ')}] ${ironmenOnly ? 'AND "minion.ironman" = true' : ''}) - OR user_id::text in (${userIds.map(i => `'${i}'`).join(', ')}) + ${userIds.length > 0 ? `OR id in (${userIds.map(i => `'${i}'`).join(', ')})` : ''} ) u ORDER BY qty DESC LIMIT ${resultLimit}; diff --git a/src/mahoji/commands/testpotato.ts b/src/mahoji/commands/testpotato.ts index eb10ce82a8..8f273fe630 100644 --- a/src/mahoji/commands/testpotato.ts +++ b/src/mahoji/commands/testpotato.ts @@ -38,6 +38,7 @@ import { import getOSItem from '../../lib/util/getOSItem'; import { logError } from '../../lib/util/logError'; import { parseStringBank } from '../../lib/util/parseStringBank'; +import { userEventToStr } from '../../lib/util/userEvents'; import { getPOH } from '../lib/abstracted_commands/pohCommand'; import { MAX_QP } from '../lib/abstracted_commands/questCommand'; import { allUsableItems } from '../lib/abstracted_commands/useCommand'; @@ -550,6 +551,12 @@ export const testPotatoCommand: OSBMahojiCommand | null = production max_value: 1000 } ] + }, + { + type: ApplicationCommandOptionType.Subcommand, + name: 'events', + description: 'See events', + options: [] } ], run: async ({ @@ -571,13 +578,24 @@ export const testPotatoCommand: OSBMahojiCommand | null = production check?: { monster_droprates?: string }; bingo_tools?: { start_bingo: string }; setslayertask?: { master: string; monster: string; quantity: number }; + events?: {}; }>) => { if (production) { logError('Test command ran in production', { userID: userID.toString() }); return 'This will never happen...'; } const user = await mUserFetch(userID.toString()); - + if (options.events) { + const events = await prisma.userEvent.findMany({ + where: { + user_id: user.id + }, + orderBy: { + date: 'desc' + } + }); + return events.map(userEventToStr).join('\n'); + } if (options.bingo_tools) { if (options.bingo_tools.start_bingo) { const bingo = await prisma.bingo.findFirst({ diff --git a/tests/integration/misc.test.ts b/tests/integration/misc.test.ts index 0b33f7f21c..b1aaee1675 100644 --- a/tests/integration/misc.test.ts +++ b/tests/integration/misc.test.ts @@ -1,6 +1,10 @@ +import { UserEvent } from '@prisma/client'; +import { randArrItem } from 'e'; import { describe, expect, test } from 'vitest'; import { analyticsTick } from '../../src/lib/analytics'; +import { allCollectionLogsFlat } from '../../src/lib/data/Collections'; +import { fetchCLLeaderboard } from '../../src/lib/util/clLeaderboard'; import { minionStatsEmbed } from '../../src/lib/util/minionStatsEmbed'; import { mockClient } from './util'; @@ -13,4 +17,32 @@ describe('Integration Misc', () => { await analyticsTick(); expect(await global.prisma!.analytic.count()).toBeGreaterThanOrEqual(1); }); + test('fetchCLLeaderboard', async () => { + for (const ironManOnly of [true, false]) { + for (const method of ['cl_array', 'raw_cl'] as const) { + for (const userEvents of [ + [ + { + id: 'asdf', + date: new Date(), + user_id: '123', + type: 'CLCompletion', + skill: null, + collection_log_name: 'giant mole' + } as UserEvent + ], + null + ]) { + await fetchCLLeaderboard({ + ironmenOnly: ironManOnly, + method, + userEvents, + resultLimit: 100, + items: randArrItem(allCollectionLogsFlat).items + }); + } + } + } + await Promise.all([fetchCLLeaderboard]); + }); }); diff --git a/tests/integration/setup.ts b/tests/integration/setup.ts index 043df84e3f..8cb634c063 100644 --- a/tests/integration/setup.ts +++ b/tests/integration/setup.ts @@ -36,3 +36,9 @@ beforeEach(async () => { afterEach(async () => { await prisma.$disconnect(); }); + +async function init() { + await prisma.$queryRaw`CREATE EXTENSION IF NOT EXISTS intarray;`; +} + +init();