@jcendal/opencode-digital-pet 0.2.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/LICENSE +201 -0
- package/README.md +843 -0
- package/dist/adapters/opencode/create-server-hooks.d.ts +38 -0
- package/dist/adapters/opencode/digital-pet-toast.d.ts +33 -0
- package/dist/adapters/opencode/session-messages.d.ts +14 -0
- package/dist/adapters/opencode/usage-event-mapper.d.ts +4 -0
- package/dist/adapters/sqlite/bun-sqlite-driver.d.ts +6 -0
- package/dist/adapters/sqlite/sqlite-digital-pet-archive-reader.d.ts +11 -0
- package/dist/adapters/sqlite/sqlite-digital-pet-write-store.d.ts +11 -0
- package/dist/adapters/sqlite/sqlite-sidebar-snapshot-reader.d.ts +8 -0
- package/dist/cli/install.d.ts +8 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +92 -0
- package/dist/commands/digital-pet-command-result.d.ts +17 -0
- package/dist/commands/digital-pet-freeze.d.ts +7 -0
- package/dist/commands/digital-pet-set.d.ts +10 -0
- package/dist/commands/digital-pet-spawn.d.ts +8 -0
- package/dist/commands/digital-pet-unfreeze.d.ts +7 -0
- package/dist/config/global-digital-pet-settings.d.ts +14 -0
- package/dist/dev/attach-dev-tools.js +6465 -0
- package/dist/digital-pet-animation/constants/evolution-battle.d.ts +5 -0
- package/dist/digital-pet-animation/constants/monster-artwork.d.ts +4 -0
- package/dist/digital-pet-animation/constants/presentation-timing.d.ts +19 -0
- package/dist/digital-pet-animation/idle/monster-action-policy.d.ts +7 -0
- package/dist/digital-pet-animation/idle/monster-animation.d.ts +73 -0
- package/dist/digital-pet-animation/idle/monster-artwork-mirror.d.ts +22 -0
- package/dist/digital-pet-animation/idle/monster-walking-policy.d.ts +42 -0
- package/dist/digital-pet-animation/render/positioned-artwork.d.ts +3 -0
- package/dist/digital-pet-animation/sequences/defeat-artwork.d.ts +7 -0
- package/dist/digital-pet-animation/sequences/evolution-artwork.d.ts +8 -0
- package/dist/digital-pet-animation/sequences/evolution-battle-artwork.d.ts +33 -0
- package/dist/digital-pet-animation/sessions/evolution-battle-session.d.ts +14 -0
- package/dist/digital-pet-animation/sessions/evolution-reveal-session.d.ts +9 -0
- package/dist/digital-pet-animation/utils/assert-never.d.ts +1 -0
- package/dist/digital-pet-animation/utils/random.d.ts +2 -0
- package/dist/digital-pet-animation/utils/sleep.d.ts +1 -0
- package/dist/digital-pet-core/adapters/sqlite/app-data-path.d.ts +5 -0
- package/dist/digital-pet-core/adapters/sqlite/sqlite-digital-pet-schema.d.ts +48 -0
- package/dist/digital-pet-core/adapters/sqlite/sqlite-digital-pet-types.d.ts +43 -0
- package/dist/digital-pet-core/adapters/sqlite/sqlite-digital-pet-write-store.d.ts +8 -0
- package/dist/digital-pet-core/adapters/sqlite/sqlite-migrations.d.ts +4 -0
- package/dist/digital-pet-core/application/models/digital-pet-archive.d.ts +21 -0
- package/dist/digital-pet-core/application/models/digital-pet-control.d.ts +17 -0
- package/dist/digital-pet-core/application/models/sidebar-card-inputs.d.ts +13 -0
- package/dist/digital-pet-core/application/models/spawn-partner.d.ts +9 -0
- package/dist/digital-pet-core/application/models/usage.d.ts +42 -0
- package/dist/digital-pet-core/application/ports/digital-pet-archive.d.ts +4 -0
- package/dist/digital-pet-core/application/ports/digital-pet-control.d.ts +6 -0
- package/dist/digital-pet-core/application/ports/partner-lifecycle.d.ts +5 -0
- package/dist/digital-pet-core/application/ports/sidebar-snapshot.d.ts +13 -0
- package/dist/digital-pet-core/application/ports/usage-ledger.d.ts +5 -0
- package/dist/digital-pet-core/application/use-cases/freeze-digital-pet.d.ts +3 -0
- package/dist/digital-pet-core/application/use-cases/get-sidebar-card-inputs.d.ts +4 -0
- package/dist/digital-pet-core/application/use-cases/reconcile-usage.d.ts +14 -0
- package/dist/digital-pet-core/application/use-cases/record-usage.d.ts +14 -0
- package/dist/digital-pet-core/application/use-cases/resolve-evolution-battle.d.ts +8 -0
- package/dist/digital-pet-core/application/use-cases/set-digital-pet-cheat-node.d.ts +3 -0
- package/dist/digital-pet-core/application/use-cases/spawn-partner.d.ts +3 -0
- package/dist/digital-pet-core/application/use-cases/unfreeze-digital-pet.d.ts +3 -0
- package/dist/digital-pet-core/config/defaults.d.ts +68 -0
- package/dist/digital-pet-core/config/normalize.d.ts +2 -0
- package/dist/digital-pet-core/config/types.d.ts +13 -0
- package/dist/digital-pet-core/data/catalog.d.ts +14 -0
- package/dist/digital-pet-core/data/digimon-data.d.ts +12 -0
- package/dist/digital-pet-core/data/monster-frame-catalog.d.ts +16 -0
- package/dist/digital-pet-core/data/monster-frame-data.d.ts +2 -0
- package/dist/digital-pet-core/data/stages.d.ts +16 -0
- package/dist/digital-pet-core/domain/digimon-node.d.ts +14 -0
- package/dist/digital-pet-core/domain/evolution-battle.d.ts +4 -0
- package/dist/digital-pet-core/domain/evolution.d.ts +23 -0
- package/dist/digital-pet-core/domain/partner.d.ts +18 -0
- package/dist/digital-pet-core/domain/stage.d.ts +3 -0
- package/dist/digital-pet-core/ports/sqlite-executor.d.ts +7 -0
- package/dist/digital-pet-core/view-models/dex-view-model.d.ts +19 -0
- package/dist/digital-pet-core/view-models/history-view-model.d.ts +20 -0
- package/dist/digital-pet-core/view-models/sidebar-view-model.d.ts +20 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +7461 -0
- package/dist/tui/digital-pet-command-layer.d.ts +20 -0
- package/dist/tui/digital-pet-dex-dialog.d.ts +11 -0
- package/dist/tui/digital-pet-history-dialog.d.ts +11 -0
- package/dist/tui/open-in-browser.d.ts +2 -0
- package/dist/tui/sidebar-card.d.ts +10 -0
- package/dist/tui/sidebar-poll-loop.d.ts +13 -0
- package/dist/tui.d.ts +56 -0
- package/dist/tui.js +9720 -0
- package/package.json +106 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Sidebar monster animation tick interval. */
|
|
2
|
+
export declare const SIDEBAR_VISUAL_INTERVAL_MS = 500;
|
|
3
|
+
/** Idle time before the partner enters the sleep animation. */
|
|
4
|
+
export declare const MONSTER_SLEEP_AFTER_MS = 300000;
|
|
5
|
+
/** Pause before the evolution reveal sequence starts. */
|
|
6
|
+
export declare const EVOLUTION_PRE_ANIMATION_MS = 400;
|
|
7
|
+
export declare const EVOLUTION_GLOW_MS = 700;
|
|
8
|
+
export declare const EVOLUTION_MORPH_MS = 1300;
|
|
9
|
+
export declare const EVOLUTION_REVEAL_MS = 1500;
|
|
10
|
+
export declare const EVOLUTION_TICK_MS = 70;
|
|
11
|
+
export declare const EVOLUTION_BATTLE_INTRO_MS = 1600;
|
|
12
|
+
export declare const EVOLUTION_BATTLE_TRAVEL_MS = 900;
|
|
13
|
+
export declare const EVOLUTION_BATTLE_PAUSE_MS = 550;
|
|
14
|
+
export declare const EVOLUTION_BATTLE_IMPACT_MS = 650;
|
|
15
|
+
export declare const EVOLUTION_BATTLE_OUTCOME_MS = 1400;
|
|
16
|
+
export declare const EVOLUTION_BATTLE_TICK_MS = 70;
|
|
17
|
+
export declare const DEFEAT_CYCLE_MS = 550;
|
|
18
|
+
export declare const DEFEAT_CYCLES = 5;
|
|
19
|
+
export declare const DEFEAT_PRE_ANIMATION_MS = 300;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MonsterFrameCatalog, MonsterFrameName } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
export type CosmeticActionClip = readonly [MonsterFrameName, MonsterFrameName];
|
|
3
|
+
export type SleepClip = readonly [MonsterFrameName, MonsterFrameName];
|
|
4
|
+
export declare const resolveCosmeticActions: (sprite: string, catalog: MonsterFrameCatalog) => readonly CosmeticActionClip[];
|
|
5
|
+
export declare const selectCosmeticAction: (actions: readonly CosmeticActionClip[], random: () => number) => CosmeticActionClip | undefined;
|
|
6
|
+
export declare const resolveEatClip: (sprite: string, catalog: MonsterFrameCatalog) => CosmeticActionClip | undefined;
|
|
7
|
+
export declare const resolveSleepClip: (sprite: string, fallback: MonsterFrameName, catalog: MonsterFrameCatalog) => SleepClip;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { MonsterFrame, MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
import { type WalkingFacing } from "./monster-walking-policy.js";
|
|
3
|
+
export type MonsterAnimationIdentity = {
|
|
4
|
+
readonly sprite: string;
|
|
5
|
+
readonly isDigitama: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type MonsterAnimationEvent = {
|
|
8
|
+
readonly kind: "partner_changed";
|
|
9
|
+
readonly partner: MonsterAnimationIdentity | undefined;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "tick";
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "activity";
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: "feed";
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "viewport_resized";
|
|
18
|
+
readonly width: number;
|
|
19
|
+
};
|
|
20
|
+
export type MonsterAnimationResult = {
|
|
21
|
+
readonly kind: "blank";
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "frame";
|
|
24
|
+
readonly frame: MonsterFrame;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "unavailable";
|
|
27
|
+
readonly sprite: string;
|
|
28
|
+
};
|
|
29
|
+
export type MonsterFacing = WalkingFacing;
|
|
30
|
+
type PositionedOutput = {
|
|
31
|
+
readonly offset: number;
|
|
32
|
+
readonly facing: MonsterFacing;
|
|
33
|
+
};
|
|
34
|
+
export type MonsterAnimationOutput = ({
|
|
35
|
+
readonly kind: "blank";
|
|
36
|
+
readonly result: {
|
|
37
|
+
readonly kind: "blank";
|
|
38
|
+
};
|
|
39
|
+
} & PositionedOutput) | ({
|
|
40
|
+
readonly kind: "unavailable";
|
|
41
|
+
readonly result: {
|
|
42
|
+
readonly kind: "unavailable";
|
|
43
|
+
readonly sprite: string;
|
|
44
|
+
};
|
|
45
|
+
} & PositionedOutput) | ({
|
|
46
|
+
readonly kind: "digitama";
|
|
47
|
+
readonly result: {
|
|
48
|
+
readonly kind: "frame";
|
|
49
|
+
readonly frame: MonsterFrame;
|
|
50
|
+
};
|
|
51
|
+
} & PositionedOutput) | ({
|
|
52
|
+
readonly kind: "walking";
|
|
53
|
+
readonly result: {
|
|
54
|
+
readonly kind: "frame";
|
|
55
|
+
readonly frame: MonsterFrame;
|
|
56
|
+
};
|
|
57
|
+
} & PositionedOutput) | ({
|
|
58
|
+
readonly kind: "action" | "sleeping";
|
|
59
|
+
readonly result: {
|
|
60
|
+
readonly kind: "frame";
|
|
61
|
+
readonly frame: MonsterFrame;
|
|
62
|
+
};
|
|
63
|
+
} & PositionedOutput);
|
|
64
|
+
export declare class MonsterAnimationController {
|
|
65
|
+
#private;
|
|
66
|
+
constructor(catalog: MonsterFrameCatalog, random?: () => number, nowMs?: () => number);
|
|
67
|
+
dispatch(event: MonsterAnimationEvent): MonsterAnimationOutput;
|
|
68
|
+
output(): MonsterAnimationOutput;
|
|
69
|
+
setSprite(sprite: string | undefined): void;
|
|
70
|
+
advance(): void;
|
|
71
|
+
get(): MonsterAnimationResult;
|
|
72
|
+
}
|
|
73
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MonsterFrame } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
export type MalformedMonsterFrameReason = {
|
|
3
|
+
readonly kind: "row_count";
|
|
4
|
+
readonly actual: number;
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: "column_count";
|
|
7
|
+
readonly row: number;
|
|
8
|
+
readonly actual: number;
|
|
9
|
+
};
|
|
10
|
+
export declare class MalformedMonsterFrameError extends Error {
|
|
11
|
+
readonly reason: MalformedMonsterFrameReason;
|
|
12
|
+
readonly name = "MalformedMonsterFrameError";
|
|
13
|
+
constructor(reason: MalformedMonsterFrameReason);
|
|
14
|
+
}
|
|
15
|
+
export type MirrorMonsterFrameResult = {
|
|
16
|
+
readonly kind: "mirrored";
|
|
17
|
+
readonly frame: MonsterFrame;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "invalid";
|
|
20
|
+
readonly error: MalformedMonsterFrameError;
|
|
21
|
+
};
|
|
22
|
+
export declare const mirrorMonsterFrame: (frame: MonsterFrame) => MirrorMonsterFrameResult;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { MonsterFrameCatalog, MonsterFrameName } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
export type WalkingFacing = "left" | "right";
|
|
3
|
+
export type WalkFrame = "walk_1" | "walk_2";
|
|
4
|
+
type MovementBounds = {
|
|
5
|
+
readonly left: number;
|
|
6
|
+
readonly right: number;
|
|
7
|
+
};
|
|
8
|
+
type WalkingBout = {
|
|
9
|
+
readonly kind: "suspended";
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "moving";
|
|
12
|
+
readonly remaining: number;
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: "boundary_hold" | "queued_action";
|
|
15
|
+
};
|
|
16
|
+
export type WalkingPolicyState = {
|
|
17
|
+
readonly frameName: WalkFrame;
|
|
18
|
+
readonly offset: number;
|
|
19
|
+
readonly facing: WalkingFacing;
|
|
20
|
+
readonly bounds: MovementBounds | undefined;
|
|
21
|
+
readonly bout: WalkingBout;
|
|
22
|
+
};
|
|
23
|
+
export type ActionBoundaryState = {
|
|
24
|
+
readonly frameName: MonsterFrameName;
|
|
25
|
+
readonly offset: number;
|
|
26
|
+
readonly facing: WalkingFacing;
|
|
27
|
+
readonly bounds: MovementBounds | undefined;
|
|
28
|
+
};
|
|
29
|
+
export type WalkingPolicyTick = {
|
|
30
|
+
readonly kind: "walking";
|
|
31
|
+
readonly walking: WalkingPolicyState;
|
|
32
|
+
} | {
|
|
33
|
+
readonly kind: "action";
|
|
34
|
+
readonly action: ActionBoundaryState;
|
|
35
|
+
};
|
|
36
|
+
export declare const initialWalkingPolicy: (frameName: WalkFrame) => WalkingPolicyState;
|
|
37
|
+
export declare const tickWalkingPolicy: (state: WalkingPolicyState, sprite: string, catalog: MonsterFrameCatalog) => WalkingPolicyTick;
|
|
38
|
+
export declare const resizeWalkingPolicy: (state: WalkingPolicyState, width: number, random: () => number) => WalkingPolicyState;
|
|
39
|
+
export declare const resizeActionBoundary: (state: ActionBoundaryState, width: number) => ActionBoundaryState;
|
|
40
|
+
export declare const resumeWalkingPolicy: (state: ActionBoundaryState, random: () => number) => WalkingPolicyState;
|
|
41
|
+
export declare const restartWalkingPolicy: (state: ActionBoundaryState, frameName: WalkFrame, random: () => number) => WalkingPolicyState;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MonsterAnimationOutput, MonsterAnimationResult } from "../idle/monster-animation.js";
|
|
2
|
+
export declare const renderPositionedArtworkRows: (animation: MonsterAnimationOutput | MonsterAnimationResult, viewportWidth: number) => readonly string[];
|
|
3
|
+
export declare const renderPositionedArtwork: (animation: MonsterAnimationOutput | MonsterAnimationResult, viewportWidth: number) => string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
export type DefeatArtworkScene = {
|
|
3
|
+
readonly sad: boolean;
|
|
4
|
+
readonly sadAlt: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const renderDefeatArtwork: (catalog: MonsterFrameCatalog, sprite: string, scene: DefeatArtworkScene, viewportWidth: number) => string;
|
|
7
|
+
export declare const runDefeatAnimation: (catalog: MonsterFrameCatalog, sprite: string, viewportWidth: number, onFrame: (artwork: string) => Promise<void>) => Promise<void>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
export type EvolutionArtworkPhase = "glow" | "morph" | "reveal";
|
|
3
|
+
export type EvolutionArtworkScene = {
|
|
4
|
+
readonly phase: EvolutionArtworkPhase;
|
|
5
|
+
readonly progress: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const renderEvolutionArtwork: (catalog: MonsterFrameCatalog, fromSprite: string, toSprite: string, scene: EvolutionArtworkScene, viewportWidth: number, tick?: number) => string;
|
|
8
|
+
export declare const runEvolutionAnimation: (catalog: MonsterFrameCatalog, fromSprite: string, toSprite: string, viewportWidth: number, onFrame: (artwork: string) => Promise<void>) => Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
2
|
+
/** FIGlet-style BATTLE banner. */
|
|
3
|
+
export declare const BATTLE_FIGLET_LINES: readonly string[];
|
|
4
|
+
export declare const buildBattleIntroTextLines: () => readonly string[];
|
|
5
|
+
/** Block-style flame sprite matching Digimon ASCII art. */
|
|
6
|
+
export declare const FIREBALL_LINES: readonly string[];
|
|
7
|
+
export type EvolutionBattleShooter = "player" | "opponent";
|
|
8
|
+
export type EvolutionBattleOutcome = EvolutionBattleShooter;
|
|
9
|
+
export type BattleSpritePose = "attack" | "injured" | "happy" | "idle";
|
|
10
|
+
export type EvolutionBattleResultLabel = "hit" | "miss" | null;
|
|
11
|
+
export type EvolutionBattleShot = {
|
|
12
|
+
readonly shooter: EvolutionBattleShooter;
|
|
13
|
+
readonly hit: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type EvolutionBattleScene = {
|
|
16
|
+
readonly shooter: EvolutionBattleShooter | null;
|
|
17
|
+
readonly progress: number;
|
|
18
|
+
readonly playerPose: BattleSpritePose;
|
|
19
|
+
readonly opponentPose: BattleSpritePose;
|
|
20
|
+
readonly playerInjuredAlt: boolean;
|
|
21
|
+
readonly opponentInjuredAlt: boolean;
|
|
22
|
+
readonly playerHits: number;
|
|
23
|
+
readonly opponentHits: number;
|
|
24
|
+
readonly lastResult: EvolutionBattleResultLabel;
|
|
25
|
+
readonly outcomeLabel: string | null;
|
|
26
|
+
};
|
|
27
|
+
export declare const buildBattleScorePips: (hits: number, total?: number) => string;
|
|
28
|
+
export declare const buildBattleScoreRow: (playerHits: number, opponentHits: number, width?: number) => string;
|
|
29
|
+
export declare const planEvolutionBattle: (outcome: EvolutionBattleOutcome, random?: () => number) => readonly EvolutionBattleShot[];
|
|
30
|
+
export declare const defaultBattleScene: (overrides?: Partial<EvolutionBattleScene>) => EvolutionBattleScene;
|
|
31
|
+
export declare const renderBattleIntroArtwork: (viewportWidth: number, _progress: number, tick?: number) => string;
|
|
32
|
+
export declare const renderEvolutionBattleArtwork: (catalog: MonsterFrameCatalog, playerSprite: string, opponentSprite: string, scene: EvolutionBattleScene, viewportWidth: number) => string;
|
|
33
|
+
export declare const runEvolutionBattleAnimation: (catalog: MonsterFrameCatalog, playerSprite: string, opponentSprite: string, viewportWidth: number, outcome: EvolutionBattleOutcome, onFrame: (artwork: string) => Promise<void>, random?: () => number) => Promise<EvolutionBattleOutcome>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ResolveEvolutionBattleOutcome } from "../../digital-pet-core/application/models/usage.js";
|
|
2
|
+
import type { SidebarSnapshot } from "../../digital-pet-core/application/ports/sidebar-snapshot.js";
|
|
3
|
+
import { type EvolutionBattleRepository } from "../../digital-pet-core/application/use-cases/resolve-evolution-battle.js";
|
|
4
|
+
import type { DigimonCatalog } from "../../digital-pet-core/data/catalog.js";
|
|
5
|
+
import type { MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
6
|
+
export type EvolutionBattleSessionDependencies = {
|
|
7
|
+
readonly frameCatalog: MonsterFrameCatalog;
|
|
8
|
+
readonly digimonCatalog: DigimonCatalog;
|
|
9
|
+
readonly repository: EvolutionBattleRepository;
|
|
10
|
+
readonly random?: () => number;
|
|
11
|
+
readonly onArtwork: (artwork: string) => Promise<void>;
|
|
12
|
+
readonly onResolved?: (result: ResolveEvolutionBattleOutcome) => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export declare const runEvolutionBattleSession: (snapshot: SidebarSnapshot, viewportWidth: number, dependencies: EvolutionBattleSessionDependencies) => Promise<boolean>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UsageEvolutionTransition } from "../../digital-pet-core/application/models/usage.js";
|
|
2
|
+
import type { DigimonCatalog } from "../../digital-pet-core/data/catalog.js";
|
|
3
|
+
import type { MonsterFrameCatalog } from "../../digital-pet-core/data/monster-frame-catalog.js";
|
|
4
|
+
export type EvolutionRevealSessionDependencies = {
|
|
5
|
+
readonly frameCatalog: MonsterFrameCatalog;
|
|
6
|
+
readonly digimonCatalog: DigimonCatalog;
|
|
7
|
+
readonly onArtwork: (artwork: string) => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare const runEvolutionRevealSession: (evolution: UsageEvolutionTransition, viewportWidth: number, dependencies: EvolutionRevealSessionDependencies) => Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const assertNever: (value: never) => never;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Partner } from "../../domain/partner.js";
|
|
2
|
+
import type { PersistedPartnerEvent, PersistedPartnerEventKind, UsageReceiptRecord } from "./sqlite-digital-pet-types.js";
|
|
3
|
+
export type PersistedPartnerRow = {
|
|
4
|
+
readonly partner_id: string;
|
|
5
|
+
readonly generation: number;
|
|
6
|
+
readonly current_node_id: string;
|
|
7
|
+
readonly gauge: number;
|
|
8
|
+
readonly is_terminal: number;
|
|
9
|
+
readonly pending_evolution_target_id: string | null;
|
|
10
|
+
readonly battle_opponent_node_id: string | null;
|
|
11
|
+
readonly created_at: string;
|
|
12
|
+
readonly retired_at: string | null;
|
|
13
|
+
};
|
|
14
|
+
export type PersistedPartnerEventRow = {
|
|
15
|
+
readonly event_id: string;
|
|
16
|
+
readonly partner_id: string;
|
|
17
|
+
readonly kind: PersistedPartnerEventKind;
|
|
18
|
+
readonly current_node_id: string;
|
|
19
|
+
readonly gauge: number;
|
|
20
|
+
readonly is_terminal: number;
|
|
21
|
+
readonly token_delta: number | null;
|
|
22
|
+
readonly receipt_key: string | null;
|
|
23
|
+
readonly created_at: string;
|
|
24
|
+
};
|
|
25
|
+
export type UsageReceiptRow = {
|
|
26
|
+
readonly receipt_key: string;
|
|
27
|
+
readonly partner_id: string;
|
|
28
|
+
readonly event_id: string;
|
|
29
|
+
readonly token_delta: number;
|
|
30
|
+
readonly cost: number | null;
|
|
31
|
+
readonly created_at: string;
|
|
32
|
+
};
|
|
33
|
+
export type TrainerStateRow = {
|
|
34
|
+
readonly total_tokens: number;
|
|
35
|
+
};
|
|
36
|
+
export type MigrationRow = {
|
|
37
|
+
readonly version: number;
|
|
38
|
+
};
|
|
39
|
+
export declare const ACTIVE_PARTNER_SELECT = "\n SELECT\n \n partner_id,\n generation,\n current_node_id,\n gauge,\n is_terminal,\n pending_evolution_target_id,\n battle_opponent_node_id,\n created_at,\n retired_at\n\n FROM partners\n WHERE retired_at IS NULL\n LIMIT 1\n";
|
|
40
|
+
export declare const PARTNERS_SELECT = "\n SELECT\n \n partner_id,\n generation,\n current_node_id,\n gauge,\n is_terminal,\n pending_evolution_target_id,\n battle_opponent_node_id,\n created_at,\n retired_at\n\n FROM partners\n ORDER BY generation ASC, created_at ASC, partner_id ASC\n";
|
|
41
|
+
export declare const ARCHIVE_PARTNERS_SELECT = "\n SELECT\n \n partner_id,\n generation,\n current_node_id,\n gauge,\n is_terminal,\n pending_evolution_target_id,\n battle_opponent_node_id,\n created_at,\n retired_at\n\n FROM partners\n ORDER BY partner_id ASC\n";
|
|
42
|
+
export declare const PARTNER_BY_GENERATION_SELECT = "\n SELECT\n \n partner_id,\n generation,\n current_node_id,\n gauge,\n is_terminal,\n pending_evolution_target_id,\n battle_opponent_node_id,\n created_at,\n retired_at\n\n FROM partners\n WHERE generation = ?\n LIMIT 1\n";
|
|
43
|
+
export declare const PARTNER_EVENTS_SELECT = "\n SELECT\n event_id,\n partner_id,\n kind,\n current_node_id,\n gauge,\n is_terminal,\n token_delta,\n receipt_key,\n created_at\n FROM partner_events\n WHERE partner_id = ?\n ORDER BY created_at ASC, event_id ASC\n";
|
|
44
|
+
export declare const ARCHIVE_PARTNER_EVENTS_SELECT = "\n SELECT\n event_id,\n partner_id,\n kind,\n current_node_id,\n gauge,\n is_terminal,\n token_delta,\n receipt_key,\n created_at\n FROM partner_events\n ORDER BY partner_id ASC, created_at ASC, event_id ASC\n";
|
|
45
|
+
export declare const USAGE_RECEIPTS_SELECT = "\n SELECT receipt_key, partner_id, event_id, token_delta, cost, created_at\n FROM usage_receipts\n ORDER BY created_at ASC, receipt_key ASC\n";
|
|
46
|
+
export declare const toPartner: (row: PersistedPartnerRow) => Partner;
|
|
47
|
+
export declare const toPersistedPartnerEvent: (row: PersistedPartnerEventRow) => PersistedPartnerEvent;
|
|
48
|
+
export declare const toUsageReceiptRecord: (row: UsageReceiptRow) => UsageReceiptRecord;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Partner, PartnerProgression } from "../../domain/partner.js";
|
|
2
|
+
import type { SpawnPartnerInput } from "../../application/models/spawn-partner.js";
|
|
3
|
+
import type { ApplyUsageReceiptOutcome, ResolveEvolutionBattleOutcome, UsageReceiptMetadata } from "../../application/models/usage.js";
|
|
4
|
+
import type { PartnerLifecycle } from "../../application/ports/partner-lifecycle.js";
|
|
5
|
+
import type { UsageLedger } from "../../application/ports/usage-ledger.js";
|
|
6
|
+
import type { DigitalPetControl } from "../../application/ports/digital-pet-control.js";
|
|
7
|
+
export type PersistedPartner = Partner;
|
|
8
|
+
export type PersistedPartnerEventKind = "spawned" | "usage_applied" | "retired";
|
|
9
|
+
export type PersistedPartnerEvent = {
|
|
10
|
+
readonly eventId: string;
|
|
11
|
+
readonly partnerId: string;
|
|
12
|
+
readonly kind: PersistedPartnerEventKind;
|
|
13
|
+
readonly currentNodeId: string;
|
|
14
|
+
readonly gauge: number;
|
|
15
|
+
readonly isTerminal: boolean;
|
|
16
|
+
readonly tokenDelta: number | null;
|
|
17
|
+
readonly receiptKey: string | null;
|
|
18
|
+
readonly createdAt: string;
|
|
19
|
+
};
|
|
20
|
+
export type UsageReceiptRecord = {
|
|
21
|
+
readonly receiptKey: string;
|
|
22
|
+
readonly partnerId: string;
|
|
23
|
+
readonly eventId: string;
|
|
24
|
+
readonly tokenDelta: number;
|
|
25
|
+
readonly createdAt: string;
|
|
26
|
+
};
|
|
27
|
+
export type TrainerState = {
|
|
28
|
+
readonly totalTokens: number;
|
|
29
|
+
};
|
|
30
|
+
export type PersistedPartnerSummary = Partner;
|
|
31
|
+
export type SqliteDigitalPetWriteStore = PartnerLifecycle & UsageLedger & DigitalPetControl & {
|
|
32
|
+
close: () => Promise<void>;
|
|
33
|
+
readonly databasePath: string;
|
|
34
|
+
getAppliedMigrations: () => readonly number[];
|
|
35
|
+
getTrainerState: () => TrainerState;
|
|
36
|
+
getActivePartner: () => PersistedPartner | null;
|
|
37
|
+
listPartners: () => readonly PersistedPartnerSummary[];
|
|
38
|
+
getPartnerByGeneration: (generation: number) => PersistedPartnerSummary | null;
|
|
39
|
+
listPartnerEvents: (partnerId: string) => readonly PersistedPartnerEvent[];
|
|
40
|
+
listUsageReceipts: () => readonly UsageReceiptRecord[];
|
|
41
|
+
resolveEvolutionBattle: (nextState: PartnerProgression, createdAt: string) => ResolveEvolutionBattleOutcome;
|
|
42
|
+
};
|
|
43
|
+
export type { ApplyUsageReceiptOutcome, PartnerProgression, SpawnPartnerInput, UsageReceiptMetadata };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SqliteExecutor } from "../../ports/sqlite-executor.js";
|
|
2
|
+
import type { SqliteDigitalPetWriteStore } from "./sqlite-digital-pet-types.js";
|
|
3
|
+
export type CreateSqliteDigitalPetWriteStoreOptions = {
|
|
4
|
+
readonly databasePath: string;
|
|
5
|
+
readonly executor: SqliteExecutor;
|
|
6
|
+
readonly close: () => Promise<void> | void;
|
|
7
|
+
};
|
|
8
|
+
export declare const createSqliteDigitalPetWriteStore: (options: CreateSqliteDigitalPetWriteStoreOptions) => SqliteDigitalPetWriteStore;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type DigitalPetArchiveEvent = {
|
|
2
|
+
readonly eventId: string;
|
|
3
|
+
readonly currentNodeId: string;
|
|
4
|
+
readonly createdAt: string;
|
|
5
|
+
};
|
|
6
|
+
export type DigitalPetArchivePartner = {
|
|
7
|
+
readonly partnerId: string;
|
|
8
|
+
readonly generation: number;
|
|
9
|
+
readonly createdAt: string;
|
|
10
|
+
readonly retiredAt: string | null;
|
|
11
|
+
readonly events: readonly DigitalPetArchiveEvent[];
|
|
12
|
+
};
|
|
13
|
+
export type DigitalPetArchiveResult = {
|
|
14
|
+
readonly kind: "available";
|
|
15
|
+
readonly partners: readonly DigitalPetArchivePartner[];
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "empty";
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "unavailable";
|
|
20
|
+
readonly message: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type FreezeDigitalPetOutcome = {
|
|
2
|
+
readonly kind: "frozen";
|
|
3
|
+
} | {
|
|
4
|
+
readonly kind: "already_frozen";
|
|
5
|
+
};
|
|
6
|
+
export type UnfreezeDigitalPetOutcome = {
|
|
7
|
+
readonly kind: "unfrozen";
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "already_unfrozen";
|
|
10
|
+
};
|
|
11
|
+
export type SetCheatNodeOutcome = {
|
|
12
|
+
readonly kind: "set";
|
|
13
|
+
readonly cheatNodeId: string;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: "already_set";
|
|
16
|
+
readonly cheatNodeId: string;
|
|
17
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DigimonNode } from "../../domain/digimon-node.js";
|
|
2
|
+
export type SidebarCardInputs = {
|
|
3
|
+
readonly kind: "no_partner";
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: "partner";
|
|
6
|
+
readonly node: DigimonNode;
|
|
7
|
+
readonly gauge: number;
|
|
8
|
+
readonly isTerminal: boolean;
|
|
9
|
+
readonly frozen: boolean;
|
|
10
|
+
readonly isSetOverride: boolean;
|
|
11
|
+
readonly trainerTotalTokens: number;
|
|
12
|
+
readonly evolutionBattlePending: boolean;
|
|
13
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type UsageReceiptMetadata = {
|
|
2
|
+
readonly receiptKey: string;
|
|
3
|
+
readonly eventId: string;
|
|
4
|
+
readonly tokenDelta: number;
|
|
5
|
+
readonly cost?: number | null;
|
|
6
|
+
readonly createdAt: string;
|
|
7
|
+
};
|
|
8
|
+
export type ApplyUsageReceiptOutcome = {
|
|
9
|
+
readonly kind: "applied";
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "duplicate";
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "no_active_partner";
|
|
14
|
+
};
|
|
15
|
+
export type UsageEvolutionTransition = {
|
|
16
|
+
readonly fromNodeId: string;
|
|
17
|
+
readonly toNodeId: string;
|
|
18
|
+
};
|
|
19
|
+
export type EvolutionBattlePending = {
|
|
20
|
+
readonly opponentNodeId: string;
|
|
21
|
+
readonly targetNodeId: string;
|
|
22
|
+
};
|
|
23
|
+
export type UsageProcessingResult = {
|
|
24
|
+
readonly kind: "applied";
|
|
25
|
+
readonly receiptKey: string;
|
|
26
|
+
readonly evolution?: UsageEvolutionTransition;
|
|
27
|
+
readonly evolutionBattlePending?: EvolutionBattlePending;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: "duplicate";
|
|
30
|
+
readonly receiptKey: string;
|
|
31
|
+
} | {
|
|
32
|
+
readonly kind: "no_active_partner";
|
|
33
|
+
readonly receiptKey: string;
|
|
34
|
+
};
|
|
35
|
+
export type ResolveEvolutionBattleOutcome = {
|
|
36
|
+
readonly kind: "won";
|
|
37
|
+
readonly evolution: UsageEvolutionTransition;
|
|
38
|
+
} | {
|
|
39
|
+
readonly kind: "lost";
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: "no_pending_battle";
|
|
42
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FreezeDigitalPetOutcome, SetCheatNodeOutcome, UnfreezeDigitalPetOutcome } from "../models/digital-pet-control.js";
|
|
2
|
+
export type DigitalPetControl = {
|
|
3
|
+
freeze: () => FreezeDigitalPetOutcome;
|
|
4
|
+
unfreeze: () => UnfreezeDigitalPetOutcome;
|
|
5
|
+
setCheatNode: (validatedNodeId: string) => SetCheatNodeOutcome;
|
|
6
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type SidebarSnapshot = {
|
|
2
|
+
readonly currentNodeId: string;
|
|
3
|
+
readonly gauge: number;
|
|
4
|
+
readonly isTerminal: boolean;
|
|
5
|
+
readonly frozen: boolean;
|
|
6
|
+
readonly isSetOverride: boolean;
|
|
7
|
+
readonly trainerTotalTokens: number;
|
|
8
|
+
readonly pendingEvolutionTargetId: string | null;
|
|
9
|
+
readonly battleOpponentNodeId: string | null;
|
|
10
|
+
};
|
|
11
|
+
export type SidebarSnapshotReader = {
|
|
12
|
+
getSidebarSnapshot: () => SidebarSnapshot | null;
|
|
13
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Partner, PartnerProgression } from "../../domain/partner.js";
|
|
2
|
+
import type { ApplyUsageReceiptOutcome, UsageReceiptMetadata } from "../models/usage.js";
|
|
3
|
+
export type UsageLedger = {
|
|
4
|
+
applyUsageReceipt: (metadata: UsageReceiptMetadata, evolve: (partner: Partner) => PartnerProgression) => ApplyUsageReceiptOutcome;
|
|
5
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DigimonCatalog } from "../../domain/digimon-node.js";
|
|
2
|
+
import type { SidebarCardInputs } from "../models/sidebar-card-inputs.js";
|
|
3
|
+
import type { SidebarSnapshotReader } from "../ports/sidebar-snapshot.js";
|
|
4
|
+
export declare const getSidebarCardInputs: (reader: SidebarSnapshotReader, catalog: DigimonCatalog) => SidebarCardInputs;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DigimonNode } from "../../domain/digimon-node.js";
|
|
2
|
+
import type { EvolutionSelector, StageThresholds } from "../../domain/evolution.js";
|
|
3
|
+
import type { UsageProcessingResult } from "../models/usage.js";
|
|
4
|
+
import type { UsageLedger } from "../ports/usage-ledger.js";
|
|
5
|
+
import { type CompletedUsage } from "./record-usage.js";
|
|
6
|
+
export type ReconcileUsageInput = {
|
|
7
|
+
readonly usages: readonly CompletedUsage[];
|
|
8
|
+
readonly ledger: UsageLedger;
|
|
9
|
+
readonly digimonById: ReadonlyMap<string, DigimonNode>;
|
|
10
|
+
readonly catalogNodes: readonly DigimonNode[];
|
|
11
|
+
readonly selector: EvolutionSelector;
|
|
12
|
+
readonly thresholds: StageThresholds;
|
|
13
|
+
};
|
|
14
|
+
export declare const reconcileUsage: ({ usages, ledger, digimonById, catalogNodes, selector, thresholds, }: ReconcileUsageInput) => readonly UsageProcessingResult[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DigimonNode } from "../../domain/digimon-node.js";
|
|
2
|
+
import { type EvolutionSelector, type StageThresholds } from "../../domain/evolution.js";
|
|
3
|
+
import type { UsageProcessingResult, UsageReceiptMetadata } from "../models/usage.js";
|
|
4
|
+
import type { UsageLedger } from "../ports/usage-ledger.js";
|
|
5
|
+
export type CompletedUsage = UsageReceiptMetadata;
|
|
6
|
+
export type RecordUsageInput = {
|
|
7
|
+
readonly usage: CompletedUsage;
|
|
8
|
+
readonly ledger: UsageLedger;
|
|
9
|
+
readonly digimonById: ReadonlyMap<string, DigimonNode>;
|
|
10
|
+
readonly catalogNodes: readonly DigimonNode[];
|
|
11
|
+
readonly selector: EvolutionSelector;
|
|
12
|
+
readonly thresholds: StageThresholds;
|
|
13
|
+
};
|
|
14
|
+
export declare const recordUsage: ({ usage, ledger, digimonById, catalogNodes, selector, thresholds, }: RecordUsageInput) => UsageProcessingResult;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DigimonNode } from "../../domain/digimon-node.js";
|
|
2
|
+
import type { Partner } from "../../domain/partner.js";
|
|
3
|
+
import type { ResolveEvolutionBattleOutcome } from "../models/usage.js";
|
|
4
|
+
export type EvolutionBattleRepository = {
|
|
5
|
+
getActivePartner: () => Partner | null;
|
|
6
|
+
resolveEvolutionBattle: (nextState: import("../../domain/partner.js").PartnerProgression, createdAt: string) => ResolveEvolutionBattleOutcome;
|
|
7
|
+
};
|
|
8
|
+
export declare const resolveEvolutionBattleForPartner: (repository: EvolutionBattleRepository, won: boolean, digimonById: ReadonlyMap<string, DigimonNode>, createdAt: string) => ResolveEvolutionBattleOutcome;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SetCheatNodeOutcome } from "../models/digital-pet-control.js";
|
|
2
|
+
import type { DigitalPetControl } from "../ports/digital-pet-control.js";
|
|
3
|
+
export declare const setDigitalPetCheatNode: (control: Pick<DigitalPetControl, "setCheatNode">, validatedNodeId: string) => SetCheatNodeOutcome;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { UnfreezeDigitalPetOutcome } from "../models/digital-pet-control.js";
|
|
2
|
+
import type { DigitalPetControl } from "../ports/digital-pet-control.js";
|
|
3
|
+
export declare const unfreezeDigitalPet: (control: Pick<DigitalPetControl, "unfreeze">) => UnfreezeDigitalPetOutcome;
|