import { TRUTH_CARD_NAMES } from './truthtrance-card-names'; import type { TruthFact } from './truthtrance'; /** * Version 1 deliberately recognizes only complete, unambiguous current facts. * Keep its semantics stable for questions that persist an interpretation. * The caller must restrict use to fact-scoped questions; this function never * interprets current-turn commitments or consults private game state. */ export function parseFreeformFactV1(text: string): Extract | null { if (typeof text !== 'string' || text.length > 500) return null; const input = text.trim(); const spice = /^do[ \t]+you[ \t]+have[ \t]+(at[ \t]+least|exactly|at[ \t]+most)[ \t]+([0-9]+)[ \t]+spice[ \t]*\??$/i.exec(input); if (spice) { const value = Number(spice[2]); if (!Number.isSafeInteger(value) || value < 0) return null; const relation = spice[1].toLowerCase().replace(/[ \t]+/g, ' '); return { kind: 'spice', compare: relation === 'at least' ? 'gte' : relation === 'at most' ? 'lte' : 'eq', value }; } const card = /^do[ \t]+you[ \t]+have[ \t]+(?:a|an)[ \t]+(.+?)[ \t]*\??$/i.exec(input); if (!card) return null; const name = card[1].trim().toLowerCase(); const matches = TRUTH_CARD_NAMES.filter(candidate => candidate.toLowerCase() === name); return matches.length === 1 ? { kind: 'hand', name: matches[0] } : null; }