@randsum/notation
Version:
Dice notation parser and types for the @randsum ecosystem
51 lines (40 loc) • 1.32 kB
text/typescript
import type { ModifierOptions } from '../types'
import { defineNotationSchema } from '../schema'
type ArithmeticKey = 'plus' | 'minus'
interface ArithmeticNotationConfig {
name: ArithmeticKey
priority: number
operator: '+' | '-'
verb: string
}
export function createArithmeticNotation(
config: ArithmeticNotationConfig
): ReturnType<typeof defineNotationSchema<number>> {
const { name, priority, operator, verb } = config
const escapedOperator = operator === '+' ? '\\+' : '-'
const pattern = new RegExp(`${escapedOperator}(\\d+)`)
const globalPattern = new RegExp(`${escapedOperator}(\\d+)`, 'g')
return defineNotationSchema<number>({
name,
priority,
pattern,
parse: notation => {
const matches = Array.from(notation.matchAll(globalPattern))
if (matches.length === 0) return {}
const total = matches.reduce((sum, match) => sum + Number(match[1]), 0)
const result: Pick<ModifierOptions, ArithmeticKey> = {
[name]: total
} as Pick<ModifierOptions, ArithmeticKey>
return result
},
toNotation: options => {
if (name === 'plus' && options < 0) {
return `-${Math.abs(options)}`
}
return `${operator}${options}`
},
toDescription: options => {
return [`${verb} ${options}`]
}
})
}