Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions convex/_fixtures/createMockListData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { FlamesOfWarV4, TeamYankeeV2 } from '@ianpaschal/combat-command-game-systems';
import { GameSystem } from '@ianpaschal/combat-command-game-systems/common';
import { merge } from 'lodash';

import { Doc, Id } from '../_generated/dataModel';

type ListData = Omit<Doc<'lists'>, '_id'|'_creationTime'>;

const mockListDataByGameSystem: Record<GameSystem, FlamesOfWarV4.ListData | TeamYankeeV2.ListData> = {
[GameSystem.FlamesOfWarV4]: {
meta: {
faction: FlamesOfWarV4.Faction.UnitedStates,
alignment: FlamesOfWarV4.Alignment.Allies,
era: FlamesOfWarV4.Era.LW,
forceDiagram: FlamesOfWarV4.ForceDiagram.FortressEuropeAmerican,
pointsLimit: 100,
},
formations: [],
units: [],
commandCards: [],
},
[GameSystem.TeamYankeeV2]: {
meta: {
faction: TeamYankeeV2.Faction.UnitedStates,
alignment: TeamYankeeV2.Alignment.Nato,
era: TeamYankeeV2.Era.Default,
forceDiagram: TeamYankeeV2.ForceDiagram.American,
pointsLimit: 100,
},
formations: [],
units: [],
commandCards: [],
},
};

export const createMockListData = (
gameSystem: GameSystem,
userId: Id<'users'>,
overrides: Partial<ListData> = {},
): ListData => merge({
gameSystem,
userId,
locked: false,
data: mockListDataByGameSystem[gameSystem],
}, overrides);
8 changes: 4 additions & 4 deletions convex/_fixtures/createMockTournament.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
GameSystem,
getGameSystem,
} from '@ianpaschal/combat-command-game-systems/common';
import { merge } from 'lodash';

import { Doc } from '../_generated/dataModel';
import {
Expand Down Expand Up @@ -33,7 +34,7 @@ export const createMockTournament = (
overrides: Partial<TournamentData>,
): TournamentData => {
const { gameSystemConfig } = getGameSystem(gameSystem);
return {
return merge({}, {
gameSystem,
title: 'Test Tournament',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a elit vehicula, vehicula tortor vitae, varius mauris. Ut varius erat a eros venenatis auctor. Donec erat turpis, pulvinar a eleifend et, consequat vel enim. Etiam vehicula risus eu hendrerit lacinia. Duis rhoncus vehicula justo ut vehicula.',
Expand Down Expand Up @@ -61,7 +62,7 @@ export const createMockTournament = (
competitorSize: 1,
useNationalTeams: false,
roundStructure: {
pairingTime: 0,
pairingTime: (overrides.competitorSize ?? 1) > 1 ? 1 : 0,
setUpTime: 2,
playingTime: 3,
},
Expand All @@ -71,6 +72,5 @@ export const createMockTournament = (
'total_points',
'total_units_destroyed',
] as RankingFactor[],
...overrides,
};
}, overrides);
};
20 changes: 16 additions & 4 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
* @module
*/

import type * as _fixtures_createMockListData from "../_fixtures/createMockListData.js";
import type * as _fixtures_createMockTournament from "../_fixtures/createMockTournament.js";
import type * as _fixtures_createMockTournamentCompetitor from "../_fixtures/createMockTournamentCompetitor.js";
import type * as _fixtures_fowV4_createMockFowV4MatchResultData from "../_fixtures/fowV4/createMockFowV4MatchResultData.js";
import type * as _model__test__helpers_buildTestListData from "../_model/_test/_helpers/buildTestListData.js";
import type * as _model__test__helpers_testUsers from "../_model/_test/_helpers/testUsers.js";
import type * as _model__test_actions_populateUsers from "../_model/_test/actions/populateUsers.js";
import type * as _model__test_index from "../_model/_test/index.js";
import type * as _model__test_mutations_cleanUp from "../_model/_test/mutations/cleanUp.js";
import type * as _model__test_mutations_createTestTournament from "../_model/_test/mutations/createTestTournament.js";
import type * as _model__test_mutations_populateTestTournament from "../_model/_test/mutations/populateTestTournament.js";
import type * as _model_common_VisibilityLevel from "../_model/common/VisibilityLevel.js";
import type * as _model_common__helpers_buildFilteredQuery from "../_model/common/_helpers/buildFilteredQuery.js";
import type * as _model_common__helpers_checkAuth from "../_model/common/_helpers/checkAuth.js";
Expand All @@ -39,6 +43,7 @@ import type * as _model_common_errors from "../_model/common/errors.js";
import type * as _model_common_faction from "../_model/common/faction.js";
import type * as _model_common_gameSystemConfig from "../_model/common/gameSystemConfig.js";
import type * as _model_common_leagueStatus from "../_model/common/leagueStatus.js";
import type * as _model_common_listData from "../_model/common/listData.js";
import type * as _model_common_location from "../_model/common/location.js";
import type * as _model_common_matchResultDetails from "../_model/common/matchResultDetails.js";
import type * as _model_common_rankingFactor from "../_model/common/rankingFactor.js";
Expand Down Expand Up @@ -88,6 +93,7 @@ import type * as _model_listComments_index from "../_model/listComments/index.js
import type * as _model_listComments_mutations_createListComment from "../_model/listComments/mutations/createListComment.js";
import type * as _model_listComments_table from "../_model/listComments/table.js";
import type * as _model_listComments_types from "../_model/listComments/types.js";
import type * as _model_lists__helpers_checkListApproved from "../_model/lists/_helpers/checkListApproved.js";
import type * as _model_lists__helpers_checkListSubmittedOnTime from "../_model/lists/_helpers/checkListSubmittedOnTime.js";
import type * as _model_lists__helpers_deepenList from "../_model/lists/_helpers/deepenList.js";
import type * as _model_lists__helpers_getAvailableActions from "../_model/lists/_helpers/getAvailableActions.js";
Expand Down Expand Up @@ -146,7 +152,6 @@ import type * as _model_tournamentCompetitors__helpers_getDetails from "../_mode
import type * as _model_tournamentCompetitors__helpers_getDisplayName from "../_model/tournamentCompetitors/_helpers/getDisplayName.js";
import type * as _model_tournamentCompetitors__helpers_sortTournamentCompetitorsByName from "../_model/tournamentCompetitors/_helpers/sortTournamentCompetitorsByName.js";
import type * as _model_tournamentCompetitors_index from "../_model/tournamentCompetitors/index.js";
import type * as _model_tournamentCompetitors_mutations_createTournamentCompetitor from "../_model/tournamentCompetitors/mutations/createTournamentCompetitor.js";
import type * as _model_tournamentCompetitors_mutations_deleteTournamentCompetitor from "../_model/tournamentCompetitors/mutations/deleteTournamentCompetitor.js";
import type * as _model_tournamentCompetitors_mutations_toggleTournamentCompetitorActive from "../_model/tournamentCompetitors/mutations/toggleTournamentCompetitorActive.js";
import type * as _model_tournamentCompetitors_mutations_updateTournamentCompetitor from "../_model/tournamentCompetitors/mutations/updateTournamentCompetitor.js";
Expand Down Expand Up @@ -197,6 +202,7 @@ import type * as _model_tournamentRegistrations__helpers_getAvailableActions fro
import type * as _model_tournamentRegistrations__helpers_getCreateSuccessMessage from "../_model/tournamentRegistrations/_helpers/getCreateSuccessMessage.js";
import type * as _model_tournamentRegistrations__helpers_getDeleteSuccessMessage from "../_model/tournamentRegistrations/_helpers/getDeleteSuccessMessage.js";
import type * as _model_tournamentRegistrations__helpers_sortTournamentCompetitorsByName from "../_model/tournamentRegistrations/_helpers/sortTournamentCompetitorsByName.js";
import type * as _model_tournamentRegistrations__helpers_validateListMeta from "../_model/tournamentRegistrations/_helpers/validateListMeta.js";
import type * as _model_tournamentRegistrations_index from "../_model/tournamentRegistrations/index.js";
import type * as _model_tournamentRegistrations_mutations_createTournamentRegistration from "../_model/tournamentRegistrations/mutations/createTournamentRegistration.js";
import type * as _model_tournamentRegistrations_mutations_deleteTournamentRegistration from "../_model/tournamentRegistrations/mutations/deleteTournamentRegistration.js";
Expand Down Expand Up @@ -307,6 +313,7 @@ import type * as _model_utils_index from "../_model/utils/index.js";
import type * as _model_utils_mergeUser from "../_model/utils/mergeUser.js";
import type * as _model_utils_mutations_refreshSearchIndex from "../_model/utils/mutations/refreshSearchIndex.js";
import type * as _model_utils_mutations_revealTournamentPlayerNames from "../_model/utils/mutations/revealTournamentPlayerNames.js";
import type * as _test from "../_test.js";
import type * as auth from "../auth.js";
import type * as crons from "../crons.js";
import type * as emails_InviteUserEmail from "../emails/InviteUserEmail.js";
Expand All @@ -328,7 +335,6 @@ import type * as matchResults from "../matchResults.js";
import type * as migrations from "../migrations.js";
import type * as photos from "../photos.js";
import type * as scheduledTasks from "../scheduledTasks.js";
import type * as test from "../test.js";
import type * as tournamentCompetitors from "../tournamentCompetitors.js";
import type * as tournamentPairings from "../tournamentPairings.js";
import type * as tournamentRegistrations from "../tournamentRegistrations.js";
Expand All @@ -354,13 +360,17 @@ import type {
* ```
*/
declare const fullApi: ApiFromModules<{
"_fixtures/createMockListData": typeof _fixtures_createMockListData;
"_fixtures/createMockTournament": typeof _fixtures_createMockTournament;
"_fixtures/createMockTournamentCompetitor": typeof _fixtures_createMockTournamentCompetitor;
"_fixtures/fowV4/createMockFowV4MatchResultData": typeof _fixtures_fowV4_createMockFowV4MatchResultData;
"_model/_test/_helpers/buildTestListData": typeof _model__test__helpers_buildTestListData;
"_model/_test/_helpers/testUsers": typeof _model__test__helpers_testUsers;
"_model/_test/actions/populateUsers": typeof _model__test_actions_populateUsers;
"_model/_test/index": typeof _model__test_index;
"_model/_test/mutations/cleanUp": typeof _model__test_mutations_cleanUp;
"_model/_test/mutations/createTestTournament": typeof _model__test_mutations_createTestTournament;
"_model/_test/mutations/populateTestTournament": typeof _model__test_mutations_populateTestTournament;
"_model/common/VisibilityLevel": typeof _model_common_VisibilityLevel;
"_model/common/_helpers/buildFilteredQuery": typeof _model_common__helpers_buildFilteredQuery;
"_model/common/_helpers/checkAuth": typeof _model_common__helpers_checkAuth;
Expand All @@ -385,6 +395,7 @@ declare const fullApi: ApiFromModules<{
"_model/common/faction": typeof _model_common_faction;
"_model/common/gameSystemConfig": typeof _model_common_gameSystemConfig;
"_model/common/leagueStatus": typeof _model_common_leagueStatus;
"_model/common/listData": typeof _model_common_listData;
"_model/common/location": typeof _model_common_location;
"_model/common/matchResultDetails": typeof _model_common_matchResultDetails;
"_model/common/rankingFactor": typeof _model_common_rankingFactor;
Expand Down Expand Up @@ -434,6 +445,7 @@ declare const fullApi: ApiFromModules<{
"_model/listComments/mutations/createListComment": typeof _model_listComments_mutations_createListComment;
"_model/listComments/table": typeof _model_listComments_table;
"_model/listComments/types": typeof _model_listComments_types;
"_model/lists/_helpers/checkListApproved": typeof _model_lists__helpers_checkListApproved;
"_model/lists/_helpers/checkListSubmittedOnTime": typeof _model_lists__helpers_checkListSubmittedOnTime;
"_model/lists/_helpers/deepenList": typeof _model_lists__helpers_deepenList;
"_model/lists/_helpers/getAvailableActions": typeof _model_lists__helpers_getAvailableActions;
Expand Down Expand Up @@ -492,7 +504,6 @@ declare const fullApi: ApiFromModules<{
"_model/tournamentCompetitors/_helpers/getDisplayName": typeof _model_tournamentCompetitors__helpers_getDisplayName;
"_model/tournamentCompetitors/_helpers/sortTournamentCompetitorsByName": typeof _model_tournamentCompetitors__helpers_sortTournamentCompetitorsByName;
"_model/tournamentCompetitors/index": typeof _model_tournamentCompetitors_index;
"_model/tournamentCompetitors/mutations/createTournamentCompetitor": typeof _model_tournamentCompetitors_mutations_createTournamentCompetitor;
"_model/tournamentCompetitors/mutations/deleteTournamentCompetitor": typeof _model_tournamentCompetitors_mutations_deleteTournamentCompetitor;
"_model/tournamentCompetitors/mutations/toggleTournamentCompetitorActive": typeof _model_tournamentCompetitors_mutations_toggleTournamentCompetitorActive;
"_model/tournamentCompetitors/mutations/updateTournamentCompetitor": typeof _model_tournamentCompetitors_mutations_updateTournamentCompetitor;
Expand Down Expand Up @@ -543,6 +554,7 @@ declare const fullApi: ApiFromModules<{
"_model/tournamentRegistrations/_helpers/getCreateSuccessMessage": typeof _model_tournamentRegistrations__helpers_getCreateSuccessMessage;
"_model/tournamentRegistrations/_helpers/getDeleteSuccessMessage": typeof _model_tournamentRegistrations__helpers_getDeleteSuccessMessage;
"_model/tournamentRegistrations/_helpers/sortTournamentCompetitorsByName": typeof _model_tournamentRegistrations__helpers_sortTournamentCompetitorsByName;
"_model/tournamentRegistrations/_helpers/validateListMeta": typeof _model_tournamentRegistrations__helpers_validateListMeta;
"_model/tournamentRegistrations/index": typeof _model_tournamentRegistrations_index;
"_model/tournamentRegistrations/mutations/createTournamentRegistration": typeof _model_tournamentRegistrations_mutations_createTournamentRegistration;
"_model/tournamentRegistrations/mutations/deleteTournamentRegistration": typeof _model_tournamentRegistrations_mutations_deleteTournamentRegistration;
Expand Down Expand Up @@ -653,6 +665,7 @@ declare const fullApi: ApiFromModules<{
"_model/utils/mergeUser": typeof _model_utils_mergeUser;
"_model/utils/mutations/refreshSearchIndex": typeof _model_utils_mutations_refreshSearchIndex;
"_model/utils/mutations/revealTournamentPlayerNames": typeof _model_utils_mutations_revealTournamentPlayerNames;
_test: typeof _test;
auth: typeof auth;
crons: typeof crons;
"emails/InviteUserEmail": typeof emails_InviteUserEmail;
Expand All @@ -674,7 +687,6 @@ declare const fullApi: ApiFromModules<{
migrations: typeof migrations;
photos: typeof photos;
scheduledTasks: typeof scheduledTasks;
test: typeof test;
tournamentCompetitors: typeof tournamentCompetitors;
tournamentPairings: typeof tournamentPairings;
tournamentRegistrations: typeof tournamentRegistrations;
Expand Down
18 changes: 18 additions & 0 deletions convex/_model/_test/_helpers/buildTestListData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { FlamesOfWarV4, TeamYankeeV2 } from '@ianpaschal/combat-command-game-systems';
import { GameSystem, getGameSystem } from '@ianpaschal/combat-command-game-systems/common';

export const buildTestListData = (gameSystem: GameSystem): FlamesOfWarV4.ListData | TeamYankeeV2.ListData => {
const { listData } = getGameSystem(gameSystem);
const { meta, formations, units, commandCards } = listData.defaultValues;

const storageMeta = Object.fromEntries(
Object.entries(meta).filter(([, value]) => value !== null),
);

return {
meta: storageMeta,
formations,
units,
commandCards,
} as unknown as FlamesOfWarV4.ListData | TeamYankeeV2.ListData;
};
7 changes: 5 additions & 2 deletions convex/_model/_test/mutations/cleanUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export const cleanUp = async (
const preserved = new Set(args.preservedTables);
const tables = (Object.keys(schema.tables) as TableName[]).filter((t) => !preserved.has(t));
for (const table of tables) {
const docs = await ctx.db.query(table).collect();
await Promise.all(docs.map((doc) => ctx.db.delete(doc._id)));
let docs = await ctx.db.query(table).take(256);
while (docs.length > 0) {
await Promise.all(docs.map((doc) => ctx.db.delete(doc._id)));
docs = await ctx.db.query(table).take(256);
}
}
};
39 changes: 39 additions & 0 deletions convex/_model/_test/mutations/createTestTournament.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Infer, v } from 'convex/values';

import { createMockTournament } from '../../../_fixtures/createMockTournament';
import { Id } from '../../../_generated/dataModel';
import { MutationCtx } from '../../../_generated/server';
import { editableFields } from '../../tournaments/table';

export const createTestTournamentArgs = v.object({
...editableFields,
organizerUserId: v.id('users'),
});

export const createTestTournament = async (
ctx: MutationCtx,
args: Infer<typeof createTestTournamentArgs>,
): Promise<Id<'tournaments'>> => {
const { organizerUserId, ...restArgs } = args;

const competitorSize = args.competitorSize ?? 1;
const maxCompetitors = args.maxCompetitors ?? (competitorSize > 1 ? 12 : 24);

// 1. Gather users
const requiredUserCount = (maxCompetitors * competitorSize) + 1;
const users = await ctx.db.query('users').take(requiredUserCount);
if (users.length < requiredUserCount) {
throw new Error('Not enough users');
}

// 2. Insert the mock tournament
const tournamentId = await ctx.db.insert('tournaments', createMockTournament(args.gameSystem, restArgs));

// 3. Insert the mock organizer
await ctx.db.insert('tournamentOrganizers', {
userId: organizerUserId,
tournamentId,
});

return tournamentId;
};
96 changes: 96 additions & 0 deletions convex/_model/_test/mutations/populateTestTournament.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Infer, v } from 'convex/values';

import { createMockListData } from '../../../_fixtures/createMockListData';
import { Id } from '../../../_generated/dataModel';
import { MutationCtx } from '../../../_generated/server';

export const populateTestTournamentArgs = v.object({
tournamentId: v.id('tournaments'),
limit: v.optional(v.number()),
});

const countryCodes = [
'nl', 'be', 'de', 'dk',
'se', 'gb-nir', 'fr', 'it',
'es', 'pt', 'ie', 'us',
];

export const populateTestTournament = async (
ctx: MutationCtx,
args: Infer<typeof populateTestTournamentArgs>,
): Promise<Id<'tournaments'>> => {

const tournament = await ctx.db.get(args.tournamentId);
if (!tournament) {
throw new Error('Could not find a tournament with that ID!');
}

const { competitorSize, useNationalTeams } = tournament;
const limit = args.limit ?? tournament.maxCompetitors;

// 1. Find already-registered users so we don't reuse them:
const existingRegistrations = await ctx.db.query('tournamentRegistrations')
.withIndex('by_tournament', (q) => q.eq('tournamentId', args.tournamentId))
.collect();
const existingUserIds = new Set(existingRegistrations.map((r) => r.userId));

const existingCompetitors = await ctx.db.query('tournamentCompetitors')
.withIndex('by_tournament', (q) => q.eq('tournamentId', args.tournamentId))
.collect();
const slotsToFill = limit - existingCompetitors.length;

if (slotsToFill <= 0) {
return tournament._id;
}

// 2. Gather enough users not already in the tournament:
const requiredUserCount = slotsToFill * competitorSize;
const candidates = await ctx.db.query('users').collect();
const availableUsers = candidates.filter((u) => !existingUserIds.has(u._id));
if (availableUsers.length < requiredUserCount) {
throw new Error('Not enough users to fill remaining slots');
}

// 3. Publish the tournament if it's still a draft:
if (tournament.status === 'draft') {
await ctx.db.patch(tournament._id, { status: 'published' });
}

// 4. Insert competitors and registrations:
for (let i = 0; i < slotsToFill; i++) {
const competitorIndex = existingCompetitors.length + i;
const startingIndex = i * competitorSize;
const players = availableUsers.slice(startingIndex, startingIndex + competitorSize);

let teamName = undefined;
if (competitorSize > 1) {
if (useNationalTeams && countryCodes[competitorIndex]) {
teamName = countryCodes[competitorIndex];
} else {
teamName = `Team ${competitorIndex + 1}`;
}
}

const tournamentCompetitorId = await ctx.db.insert('tournamentCompetitors', {
captainUserId: players[0]._id,
teamName,
tournamentId: tournament._id,
});

for (const player of players) {
const tournamentRegistrationId = await ctx.db.insert('tournamentRegistrations', {
tournamentId: tournament._id,
tournamentCompetitorId,
userId: player._id,
active: true,
confirmed: true,
});

await ctx.db.insert('lists', createMockListData(tournament.gameSystem, player._id, {
tournamentRegistrationId,
}));
}
}

return tournament._id;
};
Loading
Loading