feat(01-02): shared types module for leveling lib
Task 1 of Plan 01-02. Types-only file (no runtime behavior, no test). - Proficiency union (mirrors Prisma enum) - PROFICIENCY_BASE_BONUS lookup (untrained 0, trained 2, ..., legendary 8) - EvalResult discriminated union for prereq evaluation - StepKind union for wizard step ordering (D-10) - CharacterContext interface for prereq + recompute inputs - DerivedStats interface — does NOT include hpCurrent (Pitfall #9) - ClassProgressionRow interface (read-only) - WizardChoices interface
This commit is contained in:
88
server/src/modules/leveling/lib/types.ts
Normal file
88
server/src/modules/leveling/lib/types.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Shared types for the Level-Up pure-function library.
|
||||
* No runtime dependencies — types only.
|
||||
*/
|
||||
import type { AbilityAbbreviation } from './apply-attribute-boost';
|
||||
|
||||
export type { AbilityAbbreviation };
|
||||
|
||||
/** PF2e proficiency ranks (mirrors Prisma `Proficiency` enum). */
|
||||
export type Proficiency = 'UNTRAINED' | 'TRAINED' | 'EXPERT' | 'MASTER' | 'LEGENDARY';
|
||||
|
||||
/** Numeric proficiency bonus per rank, for use in proficiencyBonus(rank, level) calculation. */
|
||||
export const PROFICIENCY_BASE_BONUS: Record<Proficiency, number> = {
|
||||
UNTRAINED: 0,
|
||||
TRAINED: 2,
|
||||
EXPERT: 4,
|
||||
MASTER: 6,
|
||||
LEGENDARY: 8,
|
||||
};
|
||||
|
||||
/** Discriminated union for prereq evaluation result. */
|
||||
export type EvalResult =
|
||||
| { ok: true }
|
||||
| { ok: false; reason: string }
|
||||
| { unknown: true; raw: string };
|
||||
|
||||
/** Ordered union of wizard step kinds (UI-SPEC + RESEARCH §Pattern 1). */
|
||||
export type StepKind =
|
||||
| 'class-features'
|
||||
| 'class-feature-choice'
|
||||
| 'boost'
|
||||
| 'skill-increase'
|
||||
| 'feat-class'
|
||||
| 'feat-skill'
|
||||
| 'feat-general'
|
||||
| 'feat-ancestry'
|
||||
| 'feat-archetype'
|
||||
| 'spellcaster'
|
||||
| 'review';
|
||||
|
||||
/** Snapshot a character's mechanical state for prereq evaluation and recompute. */
|
||||
export interface CharacterContext {
|
||||
level: number;
|
||||
className: string;
|
||||
ancestryName: string;
|
||||
heritageName?: string;
|
||||
abilities: Record<AbilityAbbreviation, number>;
|
||||
skills: Record<string, Proficiency>;
|
||||
feats: Set<string>;
|
||||
}
|
||||
|
||||
/** Output of recomputeDerivedStats — never includes hpCurrent (Pitfall #9). */
|
||||
export interface DerivedStats {
|
||||
level: number;
|
||||
hpMax: number;
|
||||
ac: number;
|
||||
classDc: number;
|
||||
perception: number;
|
||||
fortitude: number;
|
||||
reflex: number;
|
||||
will: number;
|
||||
}
|
||||
|
||||
/** ClassProgression row shape — read-only input to recompute pipeline. */
|
||||
export interface ClassProgressionRow {
|
||||
className: string;
|
||||
level: number;
|
||||
grants: string[];
|
||||
proficiencyChanges: Partial<Record<'fortitude' | 'reflex' | 'will' | 'perception' | 'classDc' | 'ac', Proficiency>>;
|
||||
spellSlotIncrement?: { tradition: string; spellLevel: number; count: number } | null;
|
||||
cantripIncrement?: number | null;
|
||||
repertoireIncrement?: number | null;
|
||||
choiceType?: string | null;
|
||||
choiceOptionsRef?: string | null;
|
||||
}
|
||||
|
||||
/** Wizard choices subset — what the user picked across the wizard. */
|
||||
export interface WizardChoices {
|
||||
boostTargets?: AbilityAbbreviation[];
|
||||
skillIncrease?: { skillName: string; toRank: Proficiency };
|
||||
featClassId?: string;
|
||||
featSkillId?: string;
|
||||
featGeneralId?: string;
|
||||
featAncestryId?: string;
|
||||
featArchetypeId?: string;
|
||||
classFeatureChoices?: Record<string, string>;
|
||||
spellcasterRepertoirePicks?: string[];
|
||||
}
|
||||
Reference in New Issue
Block a user