feat(game): skill XP on task completion + power bands in duration (#45)
CI / build + unit + e2e (pull_request) Successful in 2m48s
CI / build + unit + e2e (pull_request) Successful in 2m48s
This commit is contained in:
+16
-2
@@ -1,6 +1,8 @@
|
||||
// Pure skill-progression module (spec §6): XP accrual, level→power, titles. No lib/db imports — operates on plain SkillRow data (Task 12's crew_skills table); the frontend imports it for the CREW-tab display.
|
||||
import type { SkillName } from './crew-costs'
|
||||
import { POWER_BANDS, XP_THRESHOLDS } from './crew-costs'
|
||||
import { ACTION_SKILL, POWER_BANDS, XP_THRESHOLDS, type SkillName } from './crew-costs'
|
||||
import type { CrewMember } from './crew'
|
||||
import type { CrewDto } from './save'
|
||||
import type { TaskType } from './tasks'
|
||||
export interface SkillRow {
|
||||
saveId: string
|
||||
crewId: string
|
||||
@@ -51,3 +53,15 @@ export function grantXp(
|
||||
}
|
||||
return { rows, events }
|
||||
}
|
||||
|
||||
// The duration formula's powerOf (Task 1) driven by the skill band (PR B, §6): each member's
|
||||
// power is the band of that member's level in the action's skill (ACTION_SKILL[type]). Names
|
||||
// map to crew ids (unique per single-player save); an unknown member or a missing row falls
|
||||
// back to L0 → power 1 (Task 1's default). Called by save.ts's makePowerOfFor (the queueing
|
||||
// routes) and — once /api/crew carries each member's skill rows — by the team builder's live
|
||||
// preview (Task 15).
|
||||
export function makePowerOf(roster: CrewDto[], skillRows: SkillRow[], type: TaskType): (m: CrewMember) => number {
|
||||
const idByName = new Map(roster.map((c): [string, string] => [c.name, String(c.id)]))
|
||||
const levelByCrew = new Map(skillRows.filter((r) => r.skill === ACTION_SKILL[type]).map((r): [string, number] => [r.crewId, r.level]))
|
||||
return (m) => powerForLevel(levelByCrew.get(idByName.get(m.name) ?? '') ?? 0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user