import { ParseOptions, ParseResult, ParseChatDetailedResult, ParseResultStraight, Period, ContestantType, KnownLeague, Sport, League, SportSource } from './types-only.js'; export { Bet, BetType, ChatFillResult, ChatOrderResult, ChatType, Contract, ContractSportCompetitionMatch, ContractSportCompetitionMatchBase, ContractSportCompetitionMatchHandicapContestantLine, ContractSportCompetitionMatchHandicapContestantML, ContractSportCompetitionMatchPropOU, ContractSportCompetitionMatchPropYN, ContractSportCompetitionMatchTotalPoints, ContractSportCompetitionMatchTotalPointsContestant, ContractSportCompetitionMatchType, ContractSportCompetitionSeries, ContractType, ContractWritein, Match, OrderShapeAssessment, ParseDiagnostics, ParseResultBase, ParseResultParlay, ParseResultRoundRobin, PeriodTypeCode, isFill, isHandicapLine, isHandicapML, isOrder, isParlay, isPropOU, isPropYN, isRoundRobin, isSeries, isStraight, isTotalPoints, isTotalPointsContestant, isWritein, knownLeagues, knownSports, leagueSportMap } from './types-only.js'; export { BET_CANDIDATE_SIGNAL, EXPLICIT_PREFIX_SIGNAL, FUSED_BARE_PREFIX, OVER_UNDER_CLIPPINGS, RECOGNIZED_PREFIXES } from './signals.js'; /** * Main parsing engine for chat-bet-parse * Implements the EBNF grammar from README.md */ declare function parseChatOrder(message: string, options?: ParseOptions): ParseResultStraight; declare function parseChatFill(message: string, options?: ParseOptions): ParseResultStraight; declare function parseChat(message: string, options?: ParseOptions): ParseResult; declare function parseChatDetailed(message: string, options?: ParseOptions): ParseChatDetailedResult; /** * Error classes for chat-bet-parse * Provides descriptive error messages for parsing failures */ declare class ChatBetParseError extends Error { readonly rawInput: string; position?: number; constructor(message: string, rawInput: string, position?: number); } declare class InvalidChatFormatError extends ChatBetParseError { constructor(rawInput: string, reason: string); } declare class InvalidContractTypeError extends ChatBetParseError { constructor(rawInput: string, contractPortion: string); } declare class InvalidPriceFormatError extends ChatBetParseError { constructor(rawInput: string, priceStr: string); } declare class InvalidSizeFormatError extends ChatBetParseError { constructor(rawInput: string, sizeStr: string, expectedFormat: string); } declare class InvalidLineValueError extends ChatBetParseError { constructor(rawInput: string, line: number); } declare class InvalidTeamFormatError extends ChatBetParseError { constructor(rawInput: string, teamStr: string, reason: string); } declare class InvalidPeriodFormatError extends ChatBetParseError { constructor(rawInput: string, periodStr: string); } declare class InvalidGameNumberError extends ChatBetParseError { constructor(rawInput: string, gameStr: string); } declare class InvalidRotationNumberError extends ChatBetParseError { constructor(rawInput: string, rotationStr: string); } declare class InvalidPropFormatError extends ChatBetParseError { constructor(rawInput: string, propStr: string, availableProps: string[]); } declare class InvalidSeriesLengthError extends ChatBetParseError { constructor(rawInput: string, lengthStr: string); } declare class MissingSizeForFillError extends ChatBetParseError { constructor(rawInput: string); } declare class UnrecognizedChatPrefixError extends ChatBetParseError { constructor(rawInput: string, prefix: string); } declare class AmbiguousContractError extends ChatBetParseError { constructor(rawInput: string, possibleTypes: string[]); } declare class InvalidDateError extends ChatBetParseError { constructor(rawInput: string, dateStr: string, reason: string); } declare class InvalidWriteinDateError extends ChatBetParseError { constructor(rawInput: string, dateStr: string, reason: string); } declare class InvalidWriteinDescriptionError extends ChatBetParseError { constructor(rawInput: string, description: string, reason: string); } declare class InvalidWriteinFormatError extends ChatBetParseError { constructor(rawInput: string, reason: string); } declare class InvalidKeywordSyntaxError extends ChatBetParseError { constructor(rawInput: string, _keyword: string, message: string); } declare class InvalidKeywordValueError extends ChatBetParseError { constructor(rawInput: string, _keyword: string, _value: string, message: string); } declare class UnknownKeywordError extends ChatBetParseError { constructor(rawInput: string, keyword: string); } declare class InvalidParlayStructureError extends ChatBetParseError { constructor(rawInput: string, message: string); } declare class InvalidParlayLegError extends ChatBetParseError { constructor(rawInput: string, legNumber: number, message: string); } declare class InvalidParlayToWinError extends ChatBetParseError { constructor(rawInput: string, message: string); } declare class MissingNcrNotationError extends ChatBetParseError { constructor(rawInput: string, message?: string); } declare class LegCountMismatchError extends ChatBetParseError { constructor(rawInput: string, expected: number, actual: number); } declare class MissingRiskTypeError extends ChatBetParseError { constructor(rawInput: string); } declare class InvalidRiskTypeError extends ChatBetParseError { constructor(rawInput: string, value: string); } declare class InvalidRoundRobinLegError extends ChatBetParseError { constructor(rawInput: string, legNumber: number, message: string); } declare class InvalidRoundRobinToWinError extends ChatBetParseError { constructor(rawInput: string, message: string); } declare function createPositionError(ErrorClass: new (rawInput: string, ...args: any[]) => ChatBetParseError, rawInput: string, position: number, ...args: any[]): ChatBetParseError; /** * The words a chat uses for an even-money price: even / ev / pk / pick / * pick'em, any case. Accepted wherever a numeric price is — after "@", as * a standalone token, or glued to a total line — and always +100 (live * fills 2026-09-08: "h1 phillies under 4.5 even" lost the word and booked * at -110). */ declare const PRICE_WORD_SOURCE = "(?:even|ev|pk|pick(?:'?em)?)"; declare const PRICE_WORD: RegExp; /** * Parses USA odds format: +150, -110, -115.5, or a price word (even, pk) */ declare function parsePrice(priceStr: string, rawInput: string): number; /** * Calculate risk and toWin amounts from American odds price and size * * American odds work as follows: * - Positive odds (e.g., +150): Size is risk amount → risk = size, toWin = size * odds / 100 * - Negative odds (e.g., -150): Size is to-win amount → risk = size * abs(odds) / 100, toWin = size * * @param price - American odds price (must be >= 100 or <= -100) * @param size - The bet size/stake amount (interpreted based on odds sign) * @returns Object containing risk and toWin amounts, both rounded to 2 decimal places */ declare function calculateRiskAndToWin(price: number, size: number): { risk: number; toWin: number; }; /** * Calculate toWin from risk amount and price */ declare function calculateToWinFromRisk(price: number, risk: number): number; /** * Calculate risk from toWin amount and price */ declare function calculateRiskFromToWin(price: number, toWin: number): number; type SizeFormat = 'unit' | 'decimal_thousands' | 'k_notation' | 'dollar' | 'plain_number'; interface ParsedSize { value: number; format: SizeFormat; } /** * Shared size parsing implementation */ type SizeInterpretation = 'unit' | 'decimal_thousands'; /** * Parse size for chat orders (unit interpretation) */ declare function parseOrderSize(sizeStr: string, rawInput: string): ParsedSize; /** * Parse size for chat fills (thousands interpretation for decimals) */ declare function parseFillSize(sizeStr: string, rawInput: string): ParsedSize; interface ParsedStraightSize { risk?: number; toWin?: number; size?: number; } /** * Parse straight bet size specification with support for extended syntax * Formats: * Simple: "= 2.5" or "= $100" (sets size, caller infers risk/toWin from price) * Risk + ToWin: "= $110 tw $100" or "= $110 to win $100" * Risk + ToPay: "= $120 tp $220" or "= $120 to pay $220" (calculates toWin = toPay - risk) * Risk only: "= risk $110" (caller calculates toWin from price) * ToWin only: "= towin $150" (caller calculates risk from price) */ declare function parseStraightSize(sizeText: string, rawInput: string, interpretation: SizeInterpretation): ParsedStraightSize; /** * Parse betting line - must be divisible by 0.5 */ declare function parseLine(lineStr: string, rawInput: string): number; /** * Parse period according to EBNF grammar */ declare function parsePeriod(periodStr: string, rawInput: string): Period; /** * Parse game number: G2, GM1, DH1, #2, G 2, GM 1, DH 1, # 2, etc. */ declare function parseGameNumber(gameStr: string, rawInput: string): number; /** * Parse rotation number (must appear immediately after YG/IW) */ declare function parseRotationNumber(rotationStr: string, rawInput: string): number; /** * Clean and validate team name, with detection for individual contestants */ declare function parseTeam(teamStr: string, rawInput: string): string; /** * Team names that begin with digits: the ONLY digits a moneyline contestant * may carry, and the digit prefix the team-name patterns admit. */ declare const NUMERIC_TEAM_NAMES: readonly ["49ers", "76ers"]; declare const NUMERIC_TEAM_NAME_PREFIX: string; /** * A moneyline contestant is a name, not a fragment: every token is digit-free * or an allowlisted digit-led name. Text that reaches the moneyline paths * with any other digit — "mil un 4", "Guardians-128", "Pirates u8.5" — is a * side, line or price the grammar did not consume, and the caller fails * closed instead of minting a moneyline on it. A bare "ML" is the moneyline * marker with no team ("YG 913 ml +100"), never a name. */ declare function isMoneylineContestant(name: string): boolean; /** * Detect if a contestant name is an individual (follows pattern like "B. Falter") */ declare function detectContestantType(contestant: string): ContestantType | undefined; /** * The two ways a chat spells a two-team matchup: "Team1/Team2" and * "Team1 vs Team2" ("vs." and any case, whitespace on both sides so a name * ending in "vs" — Cavs — never splits). Live fills 2026-09-13 wrote * "Cincinnati Reds vs LA Dodgers U0.5 1st inning" and the whole matchup * landed as one participant. Contract-type detection and the split below * share this one definition. Not separators: "@" (the price grammar owns * it) and a bare "v"/"v." (it is an individual-contestant initial, "V. Smith"). * The whitespace around "vs" is asserted, not consumed, so a scan over a long * whitespace run stays linear; parseTeam trims what the split leaves. */ declare const MATCHUP_SEPARATOR: RegExp; /** * Parse teams string: "Team1/Team2", "Team1 vs Team2", or just "Team1" */ declare function parseTeams(teamsStr: string, rawInput: string): { team1: string; team2?: string; }; /** * Infer sport and league from context (rotation number, teams, etc.) * This is a simplified version - in practice, you might use rotation number ranges */ declare function inferSportAndLeague(rotationNumber?: number, explicitLeague?: KnownLeague, explicitSport?: Sport): { sport?: Sport; league?: League; }; /** * Case-insensitive text matching */ declare function matchesIgnoreCase(text: string, pattern: string): boolean; /** * Extract player name and optional team affiliation * Pattern: "Cooper Flagg (DAL)" or "B. Falter" * * @param text - Player text potentially containing team in parentheses * @returns Object with player name and optional team */ declare function parsePlayerWithTeam(text: string): { player: string; team?: string; }; /** * Extract over/under from text: "o4.5" -> { isOver: true, line: 4.5 } * Also handles attached prices: "u2.5-125" -> { isOver: false, line: 2.5, attachedPrice: -125 } */ declare function parseOverUnder(ouStr: string, rawInput: string): { isOver: boolean; line: number; attachedPrice?: number; }; type PropCategory = 'PropOU' | 'PropYN'; interface PropTypeInfo { standardName: string; category: PropCategory; contestantType?: 'Individual' | 'TeamLeague'; } /** * Prop phrases whose canonical names contain the word "and" ("points and * assists"). Derived from PROP_TYPE_MAP so the free-form parlay leg * splitter — which splits on "and" — can protect them without a second, * drift-prone list. */ declare const PROP_PHRASES_WITH_AND: readonly string[]; /** * Detect prop type from text and return standardized info * Note: Matches longest phrases first to avoid partial matches */ declare function detectPropType(propText: string): PropTypeInfo | null; /** * Extract contestant name and prop keyword from text * Handles multi-word names like "Cooper Flagg pts" or "Team123 passing yards" * * @param text - Text containing contestant and prop (e.g., "Cooper Flagg pts") * @returns Object with contestant name and prop keyword */ declare function extractContestantAndProp(text: string): { contestant: string; propText: string; } | null; /** * Validate prop format based on category */ declare function validatePropFormat(propText: string, hasLine: boolean, rawInput: string): void; /** * Parse writein date with multiple format support and smart year inference */ declare function parseWriteinDate(dateString: string, rawInput: string, isWritein?: boolean, referenceDate?: Date): Date; /** * Validate writein description */ declare function validateWriteinDescription(description: string, rawInput: string): string; interface ParsedKeywords { date?: string; league?: string; freebet?: boolean; cleanedText: string; } declare function parseKeywords(text: string, rawInput: string, allowedKeys: string[]): ParsedKeywords; interface ParsedParlayKeywords { pusheslose?: boolean; tieslose?: boolean; freebet?: boolean; cleanedText: string; } /** * Parse parlay-specific keywords (appear on first line only) * Format: key:value (no spaces around colon) * Returns parsed keywords and text with keywords removed */ declare function parseParlayKeywords(text: string, rawInput: string, allowedKeys: string[]): ParsedParlayKeywords; interface ParsedParlaySize { risk: number; toWin?: number; useFair: boolean; } interface ParsedRoundRobinSize { risk: number; toWin?: number; useFair: boolean; riskType: 'perSelection' | 'total'; } /** * Parse parlay size specification with optional to-win override * Format: "= $100" or "= $100 tw $500" */ declare function parseParlaySize(sizeText: string, rawInput: string): ParsedParlaySize; /** * Parse round robin size with risk type specification * Format: "= $100 per" or "= $600 total" or "= $100 per tw $500" */ declare function parseRoundRobinSize(sizeText: string, rawInput: string): ParsedRoundRobinSize; /** * Calculate the combination C(n, r) = n! / (r! * (n-r)!) * This represents "n choose r" - the number of ways to choose r items from n items */ declare function calculateCombination(n: number, r: number): number; /** * Calculate the total number of parlays for a round robin bet * For exact notation (e.g., 4c2): returns C(n, r) * For at-most notation (e.g., 4c3-): returns sum of C(n, 2) + C(n, 3) + ... + C(n, r) */ declare function calculateTotalParlays(totalLegs: number, parlaySize: number, isAtMost: boolean): number; /** * Convert American odds to decimal odds * Positive odds (e.g., +120): decimal = 1 + (odds / 100) → 2.20 * Negative odds (e.g., -110): decimal = 1 + (100 / abs(odds)) → 1.909090... */ declare function americanToDecimalOdds(americanOdds: number): number; /** * Calculate fair ToWin for a parlay given leg prices and risk amount * Formula: ToWin = Risk × (product of all decimal odds - 1) */ declare function calculateParlayFairToWin(legPrices: number[], risk: number): number; /** * Calculate fair ToWin for a round robin given leg prices, risk, and configuration * For per-selection: risk is per-parlay amount * For total: risk is total, need to divide by number of parlays */ declare function calculateRoundRobinFairToWin(legPrices: number[], totalRisk: number, riskType: 'perSelection' | 'total', parlaySize: number, isAtMost: boolean): number; /** * Type definitions for tracking module * Matches SQL Server ContractLegSpecTableType for ticket tracking */ /** * Contract leg specification matching the SQL Server ContractLegSpecTableType * Used for tracking and storing bet tickets */ interface ContractLegSpec { /** Leg sequence number (1-based) */ LegSequence: number; /** Contract type */ ContractType: string; /** Event date for the contract */ EventDate: Date; /** First contestant raw name */ Contestant1_RawName?: string; /** Second contestant raw name */ Contestant2_RawName?: string; /** League code */ League?: string; /** Day sequence for multiple games */ DaySequence?: number; /** Rotation number as written in the message (the leg's own, for parlays); unset when none was given */ RotationNumber?: number; /** Contestant type */ ContestantType?: string; /** Sport */ Sport?: string; /** Where Sport came from (see SportSource); unset when Sport is unset */ SportSource?: SportSource; /** Period type code */ PeriodTypeCode?: string; /** Period number */ PeriodNumber?: number; /** Line value */ Line?: number; /** Is over/under */ IsOver?: boolean; /** Selected contestant raw name */ SelectedContestant_RawName?: string; /** Ties lose flag */ TiesLose: boolean; /** Prop name */ Prop?: string; /** Prop contestant type */ PropContestantType?: string; /** Is yes/no */ IsYes?: boolean; /** Series length */ SeriesLength?: number; /** Write-in description */ WriteInDescription?: string; /** Price in American odds format (null for straight bets) */ Price?: number | null; } /** * Options for mapping ParseResult to ContractLegSpec */ interface ContractMappingOptions { /** Event date to use for the contract (optional - will infer from ExecutionDtm if not provided) */ eventDate?: Date; /** League to use for the contract (optional - will infer from contract if not provided) */ league?: string; } /** * Error class for contract mapping failures */ declare class ContractMappingError extends ChatBetParseError { readonly contractType?: string; constructor(message: string, contractType?: string); } /** * Mappers to convert ParseResult to ContractLegSpec for SQL Server tracking */ /** * Convert a ParseResult to ContractLegSpec for SQL Server * For straight bets, returns a single ContractLegSpec object * For parlays/round robins, returns an array of ContractLegSpec (one per leg) */ declare function mapParseResultToContractLegSpec(result: ParseResult, options?: ContractMappingOptions): ContractLegSpec | ContractLegSpec[]; /** * Validate that required parameters are present for contract mapping */ declare function validateContractLegSpec(spec: Partial): void; export { AmbiguousContractError, ChatBetParseError, ContestantType, type ContractLegSpec, ContractMappingError, type ContractMappingOptions, InvalidChatFormatError, InvalidContractTypeError, InvalidDateError, InvalidGameNumberError, InvalidKeywordSyntaxError, InvalidKeywordValueError, InvalidLineValueError, InvalidParlayLegError, InvalidParlayStructureError, InvalidParlayToWinError, InvalidPeriodFormatError, InvalidPriceFormatError, InvalidPropFormatError, InvalidRiskTypeError, InvalidRotationNumberError, InvalidRoundRobinLegError, InvalidRoundRobinToWinError, InvalidSeriesLengthError, InvalidSizeFormatError, InvalidTeamFormatError, InvalidWriteinDateError, InvalidWriteinDescriptionError, InvalidWriteinFormatError, KnownLeague, League, LegCountMismatchError, MATCHUP_SEPARATOR, MissingNcrNotationError, MissingRiskTypeError, MissingSizeForFillError, NUMERIC_TEAM_NAMES, NUMERIC_TEAM_NAME_PREFIX, PRICE_WORD, PRICE_WORD_SOURCE, PROP_PHRASES_WITH_AND, ParseChatDetailedResult, ParseOptions, ParseResult, ParseResultStraight, type ParsedKeywords, type ParsedParlayKeywords, type ParsedParlaySize, type ParsedRoundRobinSize, type ParsedSize, type ParsedStraightSize, Period, type PropCategory, type PropTypeInfo, type SizeFormat, Sport, SportSource, UnknownKeywordError, UnrecognizedChatPrefixError, americanToDecimalOdds, calculateCombination, calculateParlayFairToWin, calculateRiskAndToWin, calculateRiskFromToWin, calculateRoundRobinFairToWin, calculateToWinFromRisk, calculateTotalParlays, createPositionError, parseChat as default, detectContestantType, detectPropType, extractContestantAndProp, inferSportAndLeague, isMoneylineContestant, mapParseResultToContractLegSpec, matchesIgnoreCase, parseChat, parseChatDetailed, parseChatFill, parseChatOrder, parseFillSize, parseGameNumber, parseKeywords, parseLine, parseOrderSize, parseOverUnder, parseParlayKeywords, parseParlaySize, parsePeriod, parsePlayerWithTeam, parsePrice, parseRotationNumber, parseRoundRobinSize, parseStraightSize, parseTeam, parseTeams, parseWriteinDate, validateContractLegSpec, validatePropFormat, validateWriteinDescription };