/** * balance.ts — find the database entries that are out of line with their peers. * * Balance is relative: a skill dealing 400 damage is fine in a game where * everything does, and broken in one where nothing else breaks 60. So rather * than checking numbers against thresholds invented here, each entry is scored * on a power metric and compared against the OTHER entries in its category. * * The comparison is leave-one-out: the mean and standard deviation an entry is * judged against exclude that entry. Without it a single extreme value inflates * the very statistics meant to catch it — the more broken the outlier, the * further it drags the mean toward itself, and past a point it hides * completely. Same reason one bad measurement should never help decide whether * it is bad. * * A formula the evaluator cannot read statically is reported separately, never * scored as zero. Counting unreadable formulas as no damage would pull every * average down and quietly break the whole analysis. */ export interface BalanceOutlier { id: number; name: string; value: number; /** How many standard deviations from the leave-one-out mean. */ deviations: number; direction: 'high' | 'low'; message: string; } export interface BalanceCategory { category: string; /** What was measured, in words, so the numbers can be argued with. */ metric: string; sampled: number; /** Entries with no meaningful value for this metric (free skills, etc.). */ skipped: number; stats: { mean: number; sd: number; min: number; max: number; median: number; } | null; outliers: BalanceOutlier[]; /** The extremes, for context, whether or not they were flagged. */ highest: { id: number; name: string; value: number; }[]; lowest: { id: number; name: string; value: number; }[]; } export interface UnreadableFormula { id: number; name: string; formula: string; reason: string; } export interface BalanceReport { thresholdSd: number; outlierCount: number; categories: BalanceCategory[]; /** * Damage formulas that could not be evaluated without executing them. These * are excluded from the statistics rather than counted as zero. */ unreadableFormulas: UnreadableFormula[]; } /** * Analyse a project's database for balance outliers. * * Read-only. `thresholdSd` is how far from its peers an entry has to sit before * it is worth mentioning; 2 standard deviations is the usual convention and * flags roughly the most extreme 5% of a normal distribution. */ export declare function analyseBalance(projectPath: string, opts?: { thresholdSd?: number; category?: string; }): Promise;