first commmit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Chapter settlement logic (task 8.2, req 14.1-14.5).
|
||||
*
|
||||
* After the boss dies the chapter-1 cutscene sequence is strictly:
|
||||
*
|
||||
* princess_taken_cutscene (≤ 3s) — optional, plays mid-fight when HP ≤ 1/2
|
||||
* boss_killed (≤ 2s) — freeze-frame
|
||||
* settlement_screen — score + stats UI
|
||||
*
|
||||
* There is **no** rope-severing rescue event in the MVP (req 14.5), so we
|
||||
* expose a single `BANNED_RESCUE_SEQUENCE` constant the QA test asserts
|
||||
* against; any future code that tries to play it will fail the guardrail.
|
||||
*/
|
||||
|
||||
export type CutsceneId = 'princess_taken' | 'boss_killed_freeze' | 'settlement_screen';
|
||||
|
||||
/** Any rescue-style cutscene ID in this set will fail CI (req 14.5). */
|
||||
export const BANNED_RESCUE_SEQUENCE: ReadonlyArray<string> = Object.freeze([
|
||||
'rope_cut_rescue',
|
||||
'princess_rescued',
|
||||
'chapter_end_rescue',
|
||||
]);
|
||||
|
||||
export interface ISettlementStats {
|
||||
totalScore: number;
|
||||
stageScore: number;
|
||||
comboCount: number;
|
||||
flawless: boolean;
|
||||
remainingTimeSec: number;
|
||||
}
|
||||
|
||||
export interface ISettlementResult {
|
||||
stats: ISettlementStats;
|
||||
closingLine: string;
|
||||
}
|
||||
|
||||
export class ChapterSettlement {
|
||||
private stats: ISettlementStats;
|
||||
|
||||
constructor(initialStats: ISettlementStats) {
|
||||
this.stats = { ...initialStats };
|
||||
}
|
||||
|
||||
public addScore(pts: number): void {
|
||||
this.stats.stageScore += pts;
|
||||
this.stats.totalScore += pts;
|
||||
}
|
||||
|
||||
public registerCombo(): void {
|
||||
this.stats.comboCount++;
|
||||
}
|
||||
|
||||
public markTaken(): void {
|
||||
this.stats.flawless = false;
|
||||
}
|
||||
|
||||
public setRemainingTime(sec: number): void {
|
||||
this.stats.remainingTimeSec = sec;
|
||||
}
|
||||
|
||||
public assertCutsceneAllowed(id: CutsceneId | string): void {
|
||||
if (BANNED_RESCUE_SEQUENCE.includes(id)) {
|
||||
throw new Error(
|
||||
`ChapterSettlement: cutscene "${id}" is explicitly banned — chapter 1 must end with the princess taken (req 14.5)`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public build(): ISettlementResult {
|
||||
const closing = '公主被带走,续章待续…';
|
||||
return { stats: { ...this.stats }, closingLine: closing };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user