diff --git a/src/collections/users/Profiles.ts b/src/collections/users/Profiles.ts index ec4aaba..9c8736a 100644 --- a/src/collections/users/Profiles.ts +++ b/src/collections/users/Profiles.ts @@ -122,6 +122,7 @@ export const Profiles: CollectionConfig = { flappyBird?: { xpEarned?: number | null }; eodMinesweeper?: { xpEarned?: number | null }; radioTraffic?: { xpEarned?: number | null }; + aimTrainer?: { xpEarned?: number | null }; }; }; const awardsList = progressionData?.awards || []; @@ -135,6 +136,7 @@ export const Profiles: CollectionConfig = { const flappyXp = progressionData?.minigames?.flappyBird?.xpEarned ?? 0; const eodXp = progressionData?.minigames?.eodMinesweeper?.xpEarned ?? 0; const radioTrafficXp = progressionData?.minigames?.radioTraffic?.xpEarned ?? 0; + const aimTrainerXp = progressionData?.minigames?.aimTrainer?.xpEarned ?? 0; if (awardIds.length > 0) { await req.payload @@ -175,6 +177,7 @@ export const Profiles: CollectionConfig = { // EOD Minesweeper: XP from cleared minefields xpAcc += eodXp; xpAcc += radioTrafficXp; + xpAcc += aimTrainerXp; return xpAcc; }, @@ -482,6 +485,66 @@ export const Profiles: CollectionConfig = { }, ], }, + { + name: "aimTrainer", + label: "Aim Trainer", + type: "group", + fields: [ + { + name: "gamesPlayed", + type: "number", + defaultValue: 0, + }, + { + name: "bestScore", + label: "Best Score", + type: "number", + defaultValue: 0, + }, + { + name: "recruitBestScore", + label: "Recruit Best Score", + type: "number", + defaultValue: 0, + }, + { + name: "veteranBestScore", + label: "Veteran Best Score", + type: "number", + defaultValue: 0, + }, + { + name: "eliteBestScore", + label: "Elite Best Score", + type: "number", + defaultValue: 0, + }, + { + name: "recruitBestAccuracy", + label: "Recruit Best Accuracy", + type: "number", + defaultValue: 0, + }, + { + name: "veteranBestAccuracy", + label: "Veteran Best Accuracy", + type: "number", + defaultValue: 0, + }, + { + name: "eliteBestAccuracy", + label: "Elite Best Accuracy", + type: "number", + defaultValue: 0, + }, + { + name: "xpEarned", + label: "XP Earned", + type: "number", + defaultValue: 0, + }, + ], + }, ], }, ], diff --git a/src/migrations/20260903_062000_add_aim_trainer_stats.ts b/src/migrations/20260903_062000_add_aim_trainer_stats.ts new file mode 100644 index 0000000..5da6547 --- /dev/null +++ b/src/migrations/20260903_062000_add_aim_trainer_stats.ts @@ -0,0 +1,25 @@ +import { MigrateDownArgs, MigrateUpArgs, sql } from '@payloadcms/db-postgres' + +const columns = [ + 'progression_minigames_aim_trainer_games_played', + 'progression_minigames_aim_trainer_best_score', + 'progression_minigames_aim_trainer_recruit_best_score', + 'progression_minigames_aim_trainer_veteran_best_score', + 'progression_minigames_aim_trainer_elite_best_score', + 'progression_minigames_aim_trainer_recruit_best_accuracy', + 'progression_minigames_aim_trainer_veteran_best_accuracy', + 'progression_minigames_aim_trainer_elite_best_accuracy', + 'progression_minigames_aim_trainer_xp_earned', +] as const + +export async function up({ db }: MigrateUpArgs): Promise { + for (const column of columns) { + await db.execute(sql.raw(`ALTER TABLE "profiles" ADD COLUMN "${column}" numeric DEFAULT 0;`)) + } +} + +export async function down({ db }: MigrateDownArgs): Promise { + for (const column of [...columns].reverse()) { + await db.execute(sql.raw(`ALTER TABLE "profiles" DROP COLUMN "${column}";`)) + } +} diff --git a/src/migrations/index.ts b/src/migrations/index.ts index aa08177..7a8dcbc 100644 --- a/src/migrations/index.ts +++ b/src/migrations/index.ts @@ -20,6 +20,7 @@ import * as migration_20260903_044047 from './20260903_044047'; import * as migration_20260903_053419 from './20260903_053419'; import * as migration_20260903_060000_add_radio_mode_stats from './20260903_060000_add_radio_mode_stats'; import * as migration_20260903_061000_add_radio_incorrect_counts from './20260903_061000_add_radio_incorrect_counts'; +import * as migration_20260903_062000_add_aim_trainer_stats from './20260903_062000_add_aim_trainer_stats'; export const migrations = [ { @@ -132,4 +133,9 @@ export const migrations = [ down: migration_20260903_061000_add_radio_incorrect_counts.down, name: '20260903_061000_add_radio_incorrect_counts', }, + { + up: migration_20260903_062000_add_aim_trainer_stats.up, + down: migration_20260903_062000_add_aim_trainer_stats.down, + name: '20260903_062000_add_aim_trainer_stats', + }, ]; diff --git a/src/payload-types.ts b/src/payload-types.ts index 8ba0769..a48e2f1 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -1803,6 +1803,17 @@ export interface Profile { watchBestAccuracy?: number | null; xpEarned?: number | null; }; + aimTrainer?: { + gamesPlayed?: number | null; + bestScore?: number | null; + recruitBestScore?: number | null; + veteranBestScore?: number | null; + eliteBestScore?: number | null; + recruitBestAccuracy?: number | null; + veteranBestAccuracy?: number | null; + eliteBestAccuracy?: number | null; + xpEarned?: number | null; + }; }; }; updatedAt: string; @@ -3832,6 +3843,19 @@ export interface ProfilesSelect { watchBestAccuracy?: T; xpEarned?: T; }; + aimTrainer?: + | T + | { + gamesPlayed?: T; + bestScore?: T; + recruitBestScore?: T; + veteranBestScore?: T; + eliteBestScore?: T; + recruitBestAccuracy?: T; + veteranBestAccuracy?: T; + eliteBestAccuracy?: T; + xpEarned?: T; + }; }; }; updatedAt?: T;