👁️
at dev 131 lines 2.7 kB view raw
1import type { Deck, Section } from "@/lib/deck-types"; 2import type { 3 Card, 4 ManaColor, 5 OracleId, 6 ScryfallId, 7} from "@/lib/scryfall-types"; 8 9/** 10 * MTG Comprehensive Rules citation (e.g., "100.2a", "903.5c") 11 * Branded type for type safety 12 */ 13export type RuleNumber = string & { readonly __brand: "RuleNumber" }; 14 15export function asRuleNumber(rule: string): RuleNumber { 16 return rule as RuleNumber; 17} 18 19/** 20 * Categories for grouping related rules 21 */ 22export type RuleCategory = "legality" | "quantity" | "identity" | "structure"; 23 24/** 25 * Severity level for violations 26 */ 27export type Severity = "error" | "warning"; 28 29/** 30 * A single rule violation with context 31 */ 32export interface Violation { 33 ruleId: string; 34 rule: RuleNumber; 35 category: RuleCategory; 36 cardName?: string; 37 oracleId?: OracleId; 38 section?: Section; 39 quantity?: number; 40 message: string; 41 severity: Severity; 42} 43 44/** 45 * Result of validating a deck 46 */ 47export interface ValidationResult { 48 valid: boolean; 49 violations: Violation[]; 50 byCard: Map<OracleId, Violation[]>; 51 byRule: Map<RuleNumber, Violation[]>; 52} 53 54/** 55 * Context passed to rule validators 56 */ 57export interface ValidationContext { 58 deck: Deck; 59 cardLookup: (id: ScryfallId) => Card | undefined; 60 oracleLookup: (id: OracleId) => Card | undefined; 61 getPrintings: (id: OracleId) => Card[]; 62 format: string | undefined; 63 commanderColors: ManaColor[] | undefined; 64 config: FormatConfig; 65} 66 67/** 68 * Per-format configuration parameters 69 */ 70export interface FormatConfig { 71 legalityField?: string; 72 minDeckSize?: number; 73 deckSize?: number; 74 sideboardSize?: number; 75 /** Format supports alchemy (rebalanced A-) cards - Arena formats only */ 76 supportsAlchemy?: boolean; 77} 78 79/** 80 * Rule definition 81 */ 82export interface Rule<Id extends string = string> { 83 id: Id; 84 rule: RuleNumber; 85 ruleText?: string; 86 category: RuleCategory; 87 description: string; 88 validate: (ctx: ValidationContext) => Violation[]; 89} 90 91/** 92 * Options for validation 93 */ 94export interface ValidationOptions { 95 disabledRules?: Set<string>; 96 disabledCategories?: Set<RuleCategory>; 97 configOverrides?: Partial<FormatConfig>; 98 includeMaybeboard?: boolean; 99} 100 101/** 102 * Format preset combining rules and config 103 */ 104export interface Preset<RuleId extends string = string> { 105 rules: readonly RuleId[]; 106 config: FormatConfig; 107} 108 109/** 110 * Helper to create a violation 111 */ 112export function violation( 113 rule: Rule, 114 message: string, 115 severity: Severity, 116 context?: { 117 cardName?: string; 118 oracleId?: OracleId; 119 section?: Section; 120 quantity?: number; 121 }, 122): Violation { 123 return { 124 ruleId: rule.id, 125 rule: rule.rule, 126 category: rule.category, 127 message, 128 severity, 129 ...context, 130 }; 131}