Create the apps/web/src/features/deck/analysis/ module and implement deckStats.ts.
Scope — calculateDeckStats(deck, getCardById) returns: total cards, unique cards, ink distribution, cost curve (0..6+ buckets), type distribution, inkable count, ink count, legality (≥60, ≤4 per unique fullName, ≤2 inks via canShareDeck/getInks) + enumerated legalityErrors.
- Pure, no React. Handle unknown/rotated
cardIds gracefully.
Tests (5–15): legal 60-card deck, under-60, 5th copy, 3rd ink, dual-ink counted as both.
Part of #450 · Deck Builder & Engine Score milestone.
Create the
apps/web/src/features/deck/analysis/module and implementdeckStats.ts.Scope —
calculateDeckStats(deck, getCardById)returns: total cards, unique cards, ink distribution, cost curve (0..6+ buckets), type distribution, inkable count, ink count, legality (≥60, ≤4 per uniquefullName, ≤2 inks viacanShareDeck/getInks) + enumeratedlegalityErrors.cardIds gracefully.Tests (5–15): legal 60-card deck, under-60, 5th copy, 3rd ink, dual-ink counted as both.
Part of #450 · Deck Builder & Engine Score milestone.