All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 5s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
267 lines
17 KiB
Markdown
267 lines
17 KiB
Markdown
# 13. Implementation Phases and Checklists
|
|
|
|
[< Back to Index](README.md) | [Next: Risks and Open Questions >](14-risks.md)
|
|
|
|
---
|
|
|
|
## Phase 0 — Render Pipeline Optimization (Week 0, Pre-Requisite)
|
|
|
|
Focus: Persistent browser, self-hosted fonts, concurrent upload pipeline. This phase is
|
|
**independent of evolution** and benefits all existing card generation workflows immediately.
|
|
Should be implemented before any evolution work begins.
|
|
|
|
**Deliverables:**
|
|
- Persistent Chromium browser instance in API server (replaces per-request browser launch)
|
|
- FastAPI lifespan hooks for browser startup/shutdown with auto-reconnect
|
|
- Self-hosted fonts: download Source Sans 3 + Open Sans WOFF2 files, base64-embed in template
|
|
- Remove Google Fonts CDN `@import` from `style.html`
|
|
- Concurrent upload pipeline in `pd_cards/core/upload.py` using `asyncio.Semaphore(8)` + `asyncio.gather`
|
|
- Increase `fetch_card_image` timeout from 6s to 10s to account for render queue contention
|
|
- Benchmark: measure per-card render time before/after, total run time for full cardset
|
|
|
|
**Implementation details:** See [02-architecture.md § Card Render Pipeline Optimization](02-architecture.md#card-render-pipeline-optimization)
|
|
|
|
**Success Criteria:** Per-card render time drops from ~3s to ~0.6-1.0s. Full 800-card upload
|
|
run completes in under 5 minutes (down from ~40 minutes). No external font CDN dependency.
|
|
|
|
**Files changed:**
|
|
|
|
| File | Change |
|
|
|---|---|
|
|
| `database/app/routers_v2/players.py` | Persistent browser, page-per-request pattern |
|
|
| `database/app/main.py` | FastAPI lifespan hooks |
|
|
| `database/storage/templates/style.html` | `@font-face` with base64 WOFF2 |
|
|
| `database/storage/fonts/` | Font files (new directory) |
|
|
| `pd_cards/core/upload.py` | `asyncio.gather` with semaphore |
|
|
| `check_cards_and_upload.py` | Same concurrency pattern (legacy script) |
|
|
|
|
---
|
|
|
|
## 13.1 Phase 1 — Foundation (Weeks 1-3)
|
|
|
|
Focus: Database schema, lazy evaluation engine, tier badge display, basic Discord commands.
|
|
|
|
**Deliverables:**
|
|
- `player_season_stats` materialized aggregate table created (reference Major Domo implementation)
|
|
- Incremental update logic in post-game callback for `player_season_stats`
|
|
- Backfill script to populate `player_season_stats` from existing `stratplay`/`decision` data
|
|
- All evolution database tables created with migrations
|
|
- `evolution_card_state` initialization on card acquisition (pack opening hook): create if no `(player_id, team_id)` state exists, otherwise inherit existing state
|
|
- API endpoints: track catalog, card state GET, evaluate POST
|
|
- Post-game callback integration: evaluate participating cards after each game
|
|
- Milestone evaluation engine for all stratplay/decision/stratgame milestone types
|
|
- Bot command: `!evo status` (roster-wide view and per-card view)
|
|
- Basic Discord embed: tier badge on card name
|
|
- No rating boosts yet — tier advances are tracked but boosts deferred to Phase 2
|
|
- Three universal evolution tracks seeded in database (Batter, Starting Pitcher, Relief Pitcher)
|
|
- Backfill job: initialize `evolution_card_state` for all unique `(player_id, team_id)` pairs with `progress_since = earliest card.created_at`
|
|
|
|
**Success Criteria:** All cards have evolution state. Players can see tier progress. Milestones
|
|
complete automatically after games.
|
|
|
|
## 13.2 Phase 2 — Rating Boosts (Weeks 4-6)
|
|
|
|
Focus: Apply rating boosts on tier completion, variant card API.
|
|
|
|
**Deliverables:**
|
|
- `apply_evolution_boosts()` function in card-creation repo
|
|
- Batter and pitcher player profile detection from existing ratings
|
|
- Tier boost application on tier completion: writes new variant rows to battingcardratings/pitchingcardratings
|
|
- `evolution_tier_boost` audit table populated
|
|
- Updated card API: `card_id` param for variant resolution
|
|
- Discord notification on milestone and tier completion (with boost summary)
|
|
- T4 rarity upgrade (universal, capped at HoF)
|
|
- Evolved card display name (`[Team]'s Evolved [Player]`)
|
|
|
|
**Success Criteria:** Tier completion triggers rating boost. Evolved cards show higher ratings
|
|
in card embed.
|
|
|
|
## 13.3 Phase 3 — Static Cosmetics (Weeks 7-10)
|
|
|
|
Focus: Premium static cosmetics, visual differentiation, economy tuning.
|
|
|
|
**Deliverables:**
|
|
- Cosmetics catalog seeded in database (static cosmetics only: frames, themes, badges)
|
|
- Cosmetics purchase and display endpoints
|
|
- Cosmetic CSS injection in card HTML template (frame overlays, background colors, badges)
|
|
- Variant render pipeline: Playwright renders cards with cosmetic CSS, uploads to S3
|
|
- `battingcard.image_url` column populated for variant rows
|
|
- Bot image resolution updated: variant → `battingcard.image_url` fallback to `player.image`
|
|
- Verify all three tracks work correctly across all rarity levels (Rep through HoF)
|
|
- Discord embed accent colors per tier (T2 gold, T3 purple, T4 teal)
|
|
- Analytics query for admin: evolution completion rates, milestone drop-off, cosmetic revenue
|
|
- Economy review: check cosmetics pricing against actual currency circulation data
|
|
|
|
**Success Criteria:** Static cosmetics purchasable and visually distinct. Full T0-T4 evolution
|
|
journey works end to end including cosmetics.
|
|
|
|
## 13.4 Phase 4 — Animated Cosmetics (Weeks 11-13)
|
|
|
|
Focus: APNG render pipeline, animated cosmetic effects.
|
|
|
|
**Prerequisite:** Phase 0 (persistent browser) must be complete. The APNG pipeline depends on
|
|
the persistent browser for efficient multi-frame capture.
|
|
|
|
**Deliverables:**
|
|
- Deterministic multi-frame capture using `--anim-progress` CSS custom property
|
|
- `capture_animated_frames()` function using persistent browser page pool
|
|
- APNG assembly from frame buffers using `apng` Python library (`pip install apng`)
|
|
- CSS custom property-driven animations in card HTML template (no `@keyframes` for animated cosmetics)
|
|
- Animated cosmetics added to catalog: Holographic Frame, Rarity Glow (Subtle/Strong), T4 Badge Sparkle
|
|
- S3 upload with `.apng` extension and `image/apng` content type and `CacheControl: public, max-age=31536000`
|
|
- File size validation (target <4 MB per animated card)
|
|
- Bot display verified: APNG auto-plays in Discord embeds (desktop + mobile)
|
|
- Performance benchmarking: target ~4.5s for 8-frame, ~6s for 12-frame animated variant
|
|
- pngquant integration for frame compression if file sizes exceed budget
|
|
|
|
**Success Criteria:** Animated cosmetics render correctly as APNG, auto-play in Discord embeds,
|
|
file sizes within budget, render time <8 seconds per animated variant.
|
|
|
|
---
|
|
|
|
## 13.5 Render Pipeline Optimization Checklist (Phase 0)
|
|
|
|
- [ ] Download Source Sans 3 (400, 700) and Open Sans (300, 400, 700) WOFF2 files
|
|
- [ ] Base64-encode font files and create `@font-face` declarations
|
|
- [ ] Replace `@import url('fonts.googleapis.com/...')` in `style.html` with local `@font-face` — PR #96 (next-release)
|
|
- [ ] Verify card renders identically with self-hosted fonts (visual diff)
|
|
- [x] Create `get_browser()` / `shutdown_browser()` functions in players.py — merged 2026.3.17
|
|
- [x] Add FastAPI lifespan hooks for browser startup/shutdown — merged 2026.3.17
|
|
- [x] Replace `async with async_playwright()` block with persistent browser + page-per-request — merged 2026.3.17
|
|
- [x] Add `is_connected()` check with automatic browser reconnect — implemented via `asyncio.Lock`, merged 2026.3.17
|
|
- [ ] Test: render 10 cards sequentially, verify no browser leaks (page count stays at 0 between renders)
|
|
- [ ] Test: concurrent renders (4 simultaneous requests) complete without errors
|
|
- [ ] Benchmark: measure per-card render time (target: <1.0s, down from ~3.0s) — script in PR #95 (next-release)
|
|
- [ ] Refactor `pd_cards/core/upload.py` loop to use `asyncio.Semaphore(8)` + `asyncio.gather`
|
|
- [ ] Add error handling: individual card failures don't abort the batch
|
|
- [ ] Add progress reporting: log every N completions (not every 20 starts)
|
|
- [ ] Increase `fetch_card_image` timeout from 6s to 10s
|
|
- [ ] Benchmark: full 800-card upload run (target: <5 minutes)
|
|
- [ ] Update `check_cards_and_upload.py` legacy script with same concurrency pattern
|
|
- [ ] Deploy to dev, run full cardset upload, verify all cards render correctly
|
|
- [x] Deploy to production — persistent browser deployed 2026.3.17
|
|
|
|
## 13.6 Database Checklist
|
|
|
|
- [ ] Write Peewee model for `evolution_track` — pending PR #84 (card-evolution)
|
|
- [ ] Write Peewee model for `evolution_milestone` — pending PR #84 (card-evolution)
|
|
- [ ] Write Peewee model for `evolution_card_state` — pending PR #84 (card-evolution)
|
|
- [ ] Write Peewee model for `evolution_progress`
|
|
- [ ] Write Peewee model for `evolution_tier_boost` — stub schema in PR #84
|
|
- [ ] Write Peewee model for `evolution_cosmetic` — stub schema in PR #84
|
|
- [ ] Write migration scripts for all new tables (idempotent) — pending PR #84 (card-evolution)
|
|
- [x] Write Peewee model for `player_season_stats` — split into `BattingSeasonStats` + `PitchingSeasonStats` in `app/models/season_stats.py`, merged 2026.3.17
|
|
- [ ] Implement incremental update in post-game callback (delta-based, not full recompute)
|
|
- [ ] Add `last_game_id` check to prevent double-counting on callback retries
|
|
- [ ] Write backfill script to populate from existing `stratplay`/`decision` rows
|
|
- [ ] Verify backfill totals match on-demand `GROUP BY` queries for a sample of players
|
|
- [ ] Reference Major Domo implementation for patterns and edge cases
|
|
- [x] Seed three universal evolution tracks (Batter, SP, RP) — seed data + JSON in `app/seed/evolution_tracks.py`, merged 2026.3.17; runnable once migration (PR #84) lands
|
|
- [ ] Add `image_url` nullable column to `battingcard` and `pitchingcard` — in PR #84 migration
|
|
- [ ] Add `variant` column to `card` table (integer, default 0) — in PR #84 migration
|
|
- [ ] Verify `battingcard.variant` UNIQUE constraint behavior with hash-based integers
|
|
- [ ] Index all FK columns and query-hot columns on new tables — indexes in PR #84 migration
|
|
- [ ] Ensure `player_season_stats` has appropriate indexes for `(team_id, player_id)` lookups — indexes in PR #84 migration
|
|
- [ ] Test schema in dev environment before production migration
|
|
- [ ] Write and test backfill script: create `evolution_card_state` for each unique `(player_id, team_id)` pair, propagate variant to all matching card instances
|
|
|
|
## 13.7 Card Creation System Checklist
|
|
|
|
- [ ] Implement `apply_evolution_boosts(card_ratings_df, boost_tier, player_profile)` in `creation_helpers.py` or `batters/calcs_batter.py`
|
|
- [ ] Implement batter player profile detection (power, contact, patient) from existing ratings
|
|
- [ ] Implement pitcher player profile detection (SP power, SP control, RP) from existing ratings
|
|
- [ ] Write unit tests for boost distribution: verify column sums remain valid post-boost
|
|
- [ ] Write unit tests for rating cap enforcement: verify boosts truncate at caps (e.g., hold at -5)
|
|
- [ ] Write unit tests for cap truncation: verify excess budget is discarded (not redistributed) when a stat hits its cap
|
|
- [ ] Write unit test for rarity upgrade eligibility check (HoF ceiling)
|
|
- [ ] Integrate `apply_evolution_boosts()` with API endpoint trigger (or standalone script callable by API service)
|
|
- [ ] Implement `compute_variant_hash()` function for deterministic variant numbering
|
|
- [ ] Handle variant field correctly: check for existing variant row before creating new one
|
|
- [ ] Implement cosmetic CSS injection in card HTML template (frames, backgrounds, badges)
|
|
- [ ] Implement CSS `--anim-progress` custom property animations for animated cosmetics (holographic, glow pulse, sparkle)
|
|
- [ ] Implement multi-frame Playwright capture for animated variants
|
|
- [ ] Implement APNG assembly from frame buffers
|
|
- [ ] Add file size validation for animated output
|
|
- [ ] Add CLI command: `pd-cards evolution apply-boost --card-id <id> --tier <n>` for admin use
|
|
- [ ] Add CLI command: `pd-cards evolution render-variant --player-id <id> --variant <hash>` for manual re-renders
|
|
|
|
## 13.8 API Development Checklist
|
|
|
|
- [x] Implement track catalog endpoints (GET list, GET single) — `GET /api/v2/evolution/tracks` and `/tracks/{id}` in `app/routers_v2/evolution.py`, merged 2026.3.17; returns 500 until PR #84 (EvolutionTrack model) lands
|
|
- [ ] Implement track milestones endpoint (GET milestones for track)
|
|
- [x] Implement season stats CRUD — full REST endpoints in `app/routers_v2/season_stats.py`, merged 2026.3.17
|
|
- [x] Formula engine — `app/services/formula_engine.py`, batter OPS + pitcher ERA/WHIP/K formulas, merged 2026.3.17
|
|
- [ ] Implement card state endpoints (GET by team, GET by card)
|
|
- [ ] Implement POST evaluate endpoint — in PR #98 (card-evolution); `POST /api/v2/evolution/cards/{card_id}/evaluate` with evaluator service
|
|
- [ ] Implement cosmetics endpoints (GET catalog, GET card cosmetics, POST purchase, DELETE deactivate)
|
|
- [ ] Modify battingcard/pitchingcard endpoints to accept optional `card_id` param
|
|
- [ ] Implement variant resolution logic in card endpoints using `evolution_card_state`
|
|
- [ ] Implement admin endpoints for track/milestone management and manual boost application
|
|
- [ ] Implement idempotent milestone evaluator (recalculate from source, not increment)
|
|
- [ ] Render endpoint: detect animated vs static cosmetics, route to correct pipeline
|
|
- [ ] Write API integration tests for full T0-T4 evolution lifecycle
|
|
- [ ] Write API integration tests for cosmetics purchase flow (static + animated)
|
|
- [ ] Document all new endpoints in API reference
|
|
|
|
## 13.9 Bot Integration Checklist
|
|
|
|
- [ ] Add `!evo status` command with roster-wide formatted embed
|
|
- [ ] Add `!evo card <card_id>` command for detailed single-card milestone breakdown
|
|
- [ ] Add `!evo cosmetics <card_id>` command for premium cosmetics browsing
|
|
- [ ] Integrate post-game evolution evaluator in post-game processing pipeline
|
|
- [ ] Verify evaluator fires after game resolution in all modes (campaign, gauntlet, exhibition, unlimited)
|
|
- [ ] Add milestone completion notification to team channel
|
|
- [ ] Add tier completion notification with rating boost summary
|
|
- [ ] Add Full Evolution notification with rarity upgrade announcement
|
|
- [ ] Update card display embed to show tier badge from `evolution_card_state.current_tier`
|
|
- [ ] Update card display embed to show evolved name for fully evolved cards
|
|
- [ ] Update card display embed to apply active cosmetic styling
|
|
- [ ] Verify APNG auto-plays correctly in Discord embeds across desktop and mobile
|
|
- [ ] Update trade processing: set traded card's variant to 0, check for existing state on new team's `(player_id, team_id)`, create fresh state if none exists
|
|
|
|
## 13.10 Testing Checklist
|
|
|
|
- [ ] Unit tests: `apply_evolution_boosts()` for all player profiles and tiers
|
|
- [ ] Unit tests: milestone evaluation logic for all challenge types
|
|
- [ ] Unit tests: variant resolution in card endpoint
|
|
- [ ] Unit tests: idempotent evaluator (calling twice yields same result)
|
|
- [ ] Unit tests: APNG assembly produces valid APNG output
|
|
- [ ] Integration tests: game -> post-game callback -> milestone completion -> tier boost full flow
|
|
- [ ] Integration tests: T4 rarity upgrade across all rarity levels (Rep→Res, Sta→All, MVP→HoF, HoF stays HoF)
|
|
- [ ] Integration tests: evolved card state and name update correctly after trade
|
|
- [ ] Integration tests: cosmetics remain on selling team's `(player_id, team_id)` state after trade
|
|
- [ ] Integration tests: animated cosmetic purchase triggers APNG render pipeline
|
|
- [ ] Load test: milestone query latency against player_season_stats with large dataset
|
|
- [ ] Regression test: base card ratings unaffected by evolution variant writes
|
|
- [ ] Regression test: scouting report generation ignores variant rows
|
|
- [ ] Visual test: animated APNG renders correctly in Discord (desktop + mobile)
|
|
- [ ] Visual test: APNG graceful degradation (first frame displays if client doesn't support animation)
|
|
|
|
## 13.11 Security and Balance Checklist
|
|
|
|
- [ ] Verify cosmetic purchase currency deducted atomically (wallet check + deduction in single transaction)
|
|
- [ ] Verify card ownership validated before cosmetic purchase (card.team_id == requesting team_id)
|
|
- [ ] Verify cosmetics are non-transferable on trade (team_id check in display layer)
|
|
- [ ] Review milestone thresholds against expected games-per-week before launch
|
|
- [ ] Verify rarity cap enforcement (no evolution beyond HoF)
|
|
- [ ] Verify individual stat column caps enforced during boost application (e.g., hold ≥ -5)
|
|
- [ ] Verify evolved card stats cannot exceed designed boost budget (4.0 chances/108 total) via any combination of track + boost
|
|
|
|
## 13.12 Deployment Checklist
|
|
|
|
- [ ] Run schema migration in dev, verify all tables and indexes created correctly — blocked on PR #84
|
|
- [ ] Seed evolution tracks and milestones in dev — seed script ready, blocked on schema
|
|
- [ ] Run backfill job on dev copy of card inventory, verify all cards get state records
|
|
- [ ] Run full Phase 1 test suite in dev environment
|
|
- [ ] Deploy API changes to dev, smoke test all new endpoints — season stats + formula engine deployed to prod 2026.3.17; track catalog deployed but non-functional (missing model)
|
|
- [ ] Deploy bot changes to dev instance, run a game to verify post-game evaluator fires
|
|
- [ ] Demo full T0 -> T1 progression flow in dev
|
|
- [ ] Cal approves dev demo
|
|
- [ ] Run schema migration in production during low-traffic window
|
|
- [ ] Run backfill job in production for existing card inventory
|
|
- [ ] Deploy API changes to production
|
|
- [ ] Deploy bot changes to production
|
|
- [ ] Monitor milestone query latency for first 48 hours
|
|
- [ ] Monitor tier completion rate and cosmetic purchase rate after first week
|
|
- [ ] Schedule economy review at Day 30
|