Files
gridpilot.gg/plans/seeds-plan.md
2025-12-30 00:15:35 +01:00

7.4 KiB

Comprehensive Seeding Plan for GridPilot

Current Seeding Setup

Current seeding in adapters/bootstrap includes:

  • EnsureInitialData.ts: Creates admin user (admin@gridpilot.local / admin123) and all achievements (driver, steward, admin, community).
  • SeedRacingData.ts: If no drivers exist, seeds ~100 drivers, 20 leagues, seasons, teams, races, results, standings, memberships, join requests, protests, penalties, sponsors, wallets/transactions, social feed/friendships using factories in bootstrap/racing/.

Seeding skips if data exists (idempotent), uses seed IDs for determinism (e.g., seedId('league-1', persistence)).

Persistence-aware (inmemory/postgres), ensures scoring configs for existing data.

Identified Entities

From core/*/domain/entities/ and factories/repositories:

Identity Domain

Racing Domain (primary, most seeded)

  • Driver: id, iracingId, name, country, bio?, joinedAt
  • League: id, name, description, ownerId, settings (pointsSystem enum ['f1-2024','indycar','custom'], sessionDuration, qualifyingFormat enum, maxDrivers, visibility enum ['ranked','unranked'], stewarding config), createdAt, socialLinks?, participantCount (0-max)
  • Season: id, leagueId, gameId, name, year?, order?, status enum ['planned','active','completed','archived','cancelled'], start/endDate?, schedule?, schedulePublished bool, scoringConfig?, dropPolicy?, stewardingConfig?, maxDrivers?, participantCount
  • Team: id, name, tag, description, ownerId (DriverId), leagues[], createdAt
  • Standing: id (leagueId:driverId), leagueId, driverId, points, wins, position, racesCompleted
  • Race-related: Race, RaceEvent, Session, Result, RaceRegistration
  • Stewarding: Protest (statuses), Penalty (types enum, status)
  • Other: JoinRequest, LeagueMembership, Sponsor, SeasonSponsorship, LeagueWallet, Transaction, Track, Car, etc.
  • ChampionshipStanding

Other Domains

  • Analytics: AnalyticsSnapshot, EngagementEvent, PageView
  • Media: Avatar, AvatarGenerationRequest, Media
  • Notifications: Notification, NotificationPreference
  • Payments: MemberPayment, MembershipFee, Payment, Prize, Wallet

Seeding Strategy

Goal: Cover every valid state/combination for testing all validations, transitions, queries, UIs.

  • Use factories extending current Racing*Factory pattern.
  • Deterministic IDs via seedId(name, persistence).
  • Group by domain, vary enums/states systematically.
  • Relations: Create minimal graphs covering with/without relations.
  • Volume: 5-20 examples per entity, prioritizing edge cases (min/max, empty/full, all enum values).
  • Idempotent: Check existence before create.

1. Identity Seeding

User:

  • Fields: id, displayName (1-50 chars), email (valid/invalid? but valid), passwordHash, iracingCustomerId?, primaryDriverId?, avatarUrl?
  • States: 5 users - no email, with iRacing linked, with primaryDriver, admin@gridpilot.local (existing), verified/unverified (if state).
  • Examples:

Achievement etc.: All constants already seeded, add user-achievements linking users to achievements.

2. Racing Seeding (extend current)

Driver (100+):

  • Fields: id, iracingId (unique), name, country (ISO), bio?, joinedAt
  • States: 20 countries, bio empty/full, recent/past joined.
  • Relations: Link to users, teams.

League (20+):

  • Fields/Constraints: name(3-100), desc(10-500), ownerId (valid Driver), settings.pointsSystem (3 enums), sessionDuration(15-240min), qualifyingFormat(2), maxDrivers(10-60), visibility(2, ranked min10 participants?), stewarding.decisionMode(6 enums), requiredVotes(1-10), timeLimits(1-168h), participantCount(0-max)
  • All combos: 3 points x 2 qual x 2 vis x 6 decision = ~72, but sample 20 covering extremes.
  • States:
    • Empty new league (participantCount=0)
    • Full ranked (maxDrivers=40, count=40)
    • Unranked small (max=8, count=5)
    • Various stewarding (admin_only, steward_vote req=3, etc.)
  • Examples:
    • league-1: ranked, f1-2024, max40, participant20, steward_vote req3
    • league-empty: unranked, custom, max10, count0

Season (per league 2-3):

  • Fields: status(5), schedule pub Y/N, scoring/drop/stewarding present/absent, participantCount 0-max
  • States: All status transitions valid, planned no dates, active mid, completed full schedule, cancelled early, archived old.
  • Combos: 5 status x 2 pub x 3 configs present = 30+

Standing:

  • position 1-60, points 0-high, wins 0-totalRaces, racesCompleted 0-total

Protest/Penalty:

  • ProtestStatus enum (filed, defended, voted, decided...), IncidentDescription, etc.
  • PenaltyType (time, positionDrop, pointsDeduct, ban), status (pending,applied)

Relations:

  • Memberships: pending/active/banned roles (owner,driver,steward)
  • JoinRequests: pending/approved/rejected
  • Races: scheduled/running/completed/cancelled, registrations full/partial
  • Results: all positions, incidents 0-high
  • Teams: 0-N drivers, join requests
  • Sponsors: active/pending, requests pending/accepted/rejected
  • Wallets: balance 0+, transactions deposit/withdraw

3. Other Domains

Media/Notifications/Analytics/Payments: Minimal graphs linking to users/drivers/leagues (e.g. avatars for drivers, notifications for joins, pageviews for leagues, payments for memberships).

Proposed Seed Data Volume

  • Identity: 10 users, 50 achievements+links
  • Racing: 150 drivers, 30 leagues (all settings combos), 100 seasons (all status), 50 teams, 500 standings/results, 100 protests/penalties, full relation graphs
  • Other: 50 each
  • Total ~2000 records, covering 100% valid states.

Implementation Steps (for Code mode)

  1. Extend factories for new states/combos.
  2. Add factories for non-racing entities.
  3. Update SeedRacingData to call all.
  4. EnsureInitialData for non-racing.

This plan covers every single possible valid state via systematic enum cartesian + edges (0/max/empty/full/pending/complete)."