@sharpee/engine 1.0.8 → 1.1.1
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/README.md +73 -72
- package/package.json +12 -12
- package/scene-evaluation-plugin.d.ts +11 -3
- package/scene-evaluation-plugin.d.ts.map +1 -1
- package/scene-evaluation-plugin.js +67 -5
- package/scene-evaluation-plugin.js.map +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Runtime engine for the Sharpee IF Platform. This package provides the core game loop, command execution, and turn management.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @sharpee/engine
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> **Architecture note**: The CommandExecutor is a thin orchestrator. Actions own their complete event lifecycle through the four-phase pattern (validate/execute/report/blocked, ADR-051).
|
|
6
12
|
|
|
7
13
|
## Overview
|
|
8
14
|
|
|
@@ -32,42 +38,32 @@ User Input
|
|
|
32
38
|
Turn Result
|
|
33
39
|
```
|
|
34
40
|
|
|
35
|
-
### Action
|
|
41
|
+
### Action Four-Phase Pattern
|
|
36
42
|
|
|
37
|
-
Actions follow a strict
|
|
43
|
+
Actions follow a strict four-phase pattern (ADR-051) for clean separation of concerns:
|
|
38
44
|
|
|
39
45
|
1. **Validate Phase**: Check if the action can be performed (no mutations)
|
|
40
46
|
2. **Execute Phase**: Perform state mutations only (no events)
|
|
41
47
|
3. **Report Phase**: Generate events based on final state (no mutations)
|
|
48
|
+
4. **Blocked Phase**: Generate events when validation fails
|
|
42
49
|
|
|
43
50
|
The CommandExecutor simply orchestrates these phases, delegating all responsibility to the appropriate components. Actions own their complete event lifecycle, including error events.
|
|
44
51
|
|
|
45
52
|
## Basic Usage
|
|
46
53
|
|
|
47
54
|
```typescript
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
55
|
+
import { GameEngine } from '@sharpee/engine';
|
|
56
|
+
import { EnglishParser } from '@sharpee/parser-en-us';
|
|
57
|
+
import { EnglishLanguageProvider } from '@sharpee/lang-en-us';
|
|
50
58
|
|
|
51
|
-
//
|
|
52
|
-
const
|
|
59
|
+
// Build the world and player (typically via your story's setup)
|
|
60
|
+
const language = new EnglishLanguageProvider();
|
|
61
|
+
const parser = new EnglishParser(language);
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
await engine.setLanguage('en-US');
|
|
63
|
+
const engine = new GameEngine({ world, player, parser, language });
|
|
56
64
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
config: {
|
|
60
|
-
id: 'my-story',
|
|
61
|
-
title: 'My Adventure',
|
|
62
|
-
author: 'Me',
|
|
63
|
-
version: '1.0.0',
|
|
64
|
-
language: 'en-US' // Language automatically loaded
|
|
65
|
-
},
|
|
66
|
-
initializeWorld: (world) => { /* ... */ },
|
|
67
|
-
createPlayer: (world) => { /* ... */ }
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
await engine.setStory(story); // Automatically sets up language
|
|
65
|
+
// Register a story (configures world, player, grammar, channels)
|
|
66
|
+
engine.setStory(story);
|
|
71
67
|
|
|
72
68
|
// Start the engine
|
|
73
69
|
engine.start();
|
|
@@ -81,30 +77,28 @@ const context = engine.getContext();
|
|
|
81
77
|
console.log(`Current turn: ${context.currentTurn}`);
|
|
82
78
|
|
|
83
79
|
// Access parser and language provider if needed
|
|
84
|
-
const
|
|
80
|
+
const activeParser = engine.getParser();
|
|
85
81
|
const languageProvider = engine.getLanguageProvider();
|
|
86
82
|
```
|
|
87
83
|
|
|
88
|
-
|
|
84
|
+
> In most cases you don't construct the engine by hand — the build toolchain and
|
|
85
|
+
> the browser/CLI clients assemble the parser, language provider, and story for
|
|
86
|
+
> you from the story's config (`language: 'en-US'`).
|
|
87
|
+
|
|
88
|
+
## Engine Configuration
|
|
89
|
+
|
|
90
|
+
The optional `config` field on the constructor options tunes engine behavior:
|
|
89
91
|
|
|
90
92
|
```typescript
|
|
91
93
|
import { GameEngine, EngineConfig } from '@sharpee/engine';
|
|
92
|
-
import { IWorldModel, IFEntity } from '@sharpee/world-model';
|
|
93
94
|
|
|
94
|
-
// Create your world
|
|
95
|
-
const world: IWorldModel = createMyWorld();
|
|
96
|
-
const player: IFEntity = createPlayer();
|
|
97
|
-
|
|
98
|
-
// Configure engine
|
|
99
95
|
const config: EngineConfig = {
|
|
100
96
|
maxHistory: 50,
|
|
101
97
|
collectTiming: true,
|
|
102
|
-
|
|
103
|
-
onError: (error, context) => console.error(`Error at turn ${context.currentTurn}:`, error)
|
|
98
|
+
validateEvents: true
|
|
104
99
|
};
|
|
105
100
|
|
|
106
|
-
|
|
107
|
-
const engine = new GameEngine(world, player, config);
|
|
101
|
+
const engine = new GameEngine({ world, player, parser, language, config });
|
|
108
102
|
|
|
109
103
|
// Listen to engine events
|
|
110
104
|
engine.on('turn:complete', (result) => {
|
|
@@ -140,7 +134,7 @@ Events are self-contained with all necessary data embedded at creation time:
|
|
|
140
134
|
|
|
141
135
|
This enables:
|
|
142
136
|
- **Historical Replay**: Events contain complete state at that moment
|
|
143
|
-
- **No World Queries**:
|
|
137
|
+
- **No World Queries**: The prose pipeline renders from embedded event data, not world lookups
|
|
144
138
|
- **Consistency**: Entity state is captured after all mutations complete
|
|
145
139
|
|
|
146
140
|
## Event Sequencing
|
|
@@ -163,20 +157,15 @@ Events are automatically sequenced within turns:
|
|
|
163
157
|
|
|
164
158
|
## Language Management
|
|
165
159
|
|
|
166
|
-
The
|
|
160
|
+
The parser and language provider are supplied to the engine at construction
|
|
161
|
+
time (see Basic Usage). A story declares which language it expects via its
|
|
162
|
+
config; the build toolchain and clients pick the matching packages by code.
|
|
167
163
|
|
|
168
164
|
```typescript
|
|
169
|
-
// Set language directly
|
|
170
|
-
await engine.setLanguage('en-US'); // Loads @sharpee/lang-en-us and @sharpee/parser-en-us
|
|
171
|
-
|
|
172
|
-
// Change language at runtime
|
|
173
|
-
await engine.setLanguage('es'); // Switches to Spanish
|
|
174
|
-
|
|
175
|
-
// Language from story config
|
|
176
165
|
const story = {
|
|
177
|
-
config: { language: '
|
|
166
|
+
config: { id: 'my-story', title: '…', language: 'en-US', /* ... */ },
|
|
167
|
+
// ...
|
|
178
168
|
};
|
|
179
|
-
await engine.setStory(story); // Automatically uses Japanese
|
|
180
169
|
```
|
|
181
170
|
|
|
182
171
|
### Naming Convention
|
|
@@ -192,33 +181,44 @@ For example:
|
|
|
192
181
|
|
|
193
182
|
## Save/Load
|
|
194
183
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
localStorage.setItem('save', JSON.stringify(saveData));
|
|
184
|
+
Save and restore are driven by platform events and host-supplied hooks rather
|
|
185
|
+
than direct method calls. The host (CLI, browser client, server) registers
|
|
186
|
+
hooks that persist and reload the engine's save data:
|
|
199
187
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
188
|
+
```typescript
|
|
189
|
+
engine.registerSaveRestoreHooks({
|
|
190
|
+
onSaveRequested: async (saveData) => {
|
|
191
|
+
localStorage.setItem('save', JSON.stringify(saveData));
|
|
192
|
+
},
|
|
193
|
+
onRestoreRequested: async () => {
|
|
194
|
+
const raw = localStorage.getItem('save');
|
|
195
|
+
return raw ? JSON.parse(raw) : null;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
203
198
|
```
|
|
204
199
|
|
|
200
|
+
The standard `save` / `restore` meta-actions emit the platform events that
|
|
201
|
+
trigger these hooks.
|
|
202
|
+
|
|
205
203
|
## Integration with Story Files
|
|
206
204
|
|
|
207
|
-
The engine
|
|
205
|
+
The engine works with TypeScript story files implementing the `Story` interface:
|
|
208
206
|
|
|
209
207
|
```typescript
|
|
210
208
|
// my-story.ts
|
|
211
|
-
import { Story } from '@sharpee/
|
|
212
|
-
|
|
213
|
-
export
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
209
|
+
import { Story, StoryConfig } from '@sharpee/engine';
|
|
210
|
+
|
|
211
|
+
export const story: Story = {
|
|
212
|
+
config: {
|
|
213
|
+
id: 'my-story',
|
|
214
|
+
title: 'My Adventure',
|
|
215
|
+
author: 'Me',
|
|
216
|
+
version: '1.0.0',
|
|
217
|
+
language: 'en-US'
|
|
218
|
+
},
|
|
219
|
+
initializeWorld(world) { /* create rooms, objects, NPCs */ },
|
|
220
|
+
createPlayer(world) { /* create and place the player */ }
|
|
221
|
+
};
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
## API Reference
|
|
@@ -226,18 +226,16 @@ export default new Story()
|
|
|
226
226
|
### GameEngine
|
|
227
227
|
|
|
228
228
|
- `start()`: Start the engine
|
|
229
|
-
- `stop()`: Stop the engine
|
|
230
|
-
- `executeTurn(input: string)`: Execute a turn with user input
|
|
229
|
+
- `stop(reason?)`: Stop the engine
|
|
230
|
+
- `executeTurn(input: string)`: Execute a turn with user input (async)
|
|
231
231
|
- `getContext()`: Get current game context
|
|
232
232
|
- `getWorld()`: Get world model
|
|
233
|
-
- `saveState()`: Save game state
|
|
234
|
-
- `loadState(state)`: Load game state
|
|
235
233
|
- `getHistory()`: Get turn history
|
|
236
234
|
- `getRecentEvents(count)`: Get recent events
|
|
237
|
-
- `
|
|
238
|
-
- `setStory(story: Story)`: Set story (automatically configures language from story config)
|
|
235
|
+
- `setStory(story: Story)`: Register a story (configures world, player, grammar, channels)
|
|
239
236
|
- `getParser()`: Get current parser instance
|
|
240
237
|
- `getLanguageProvider()`: Get current language provider instance
|
|
238
|
+
- `registerSaveRestoreHooks(hooks)`: Register save/restore persistence hooks
|
|
241
239
|
|
|
242
240
|
### Events
|
|
243
241
|
|
|
@@ -305,7 +303,6 @@ The engine package includes comprehensive test coverage:
|
|
|
305
303
|
- `command-executor.test.ts` - Command parsing and execution
|
|
306
304
|
- `event-sequencer.test.ts` - Event ordering and utilities
|
|
307
305
|
- `story.test.ts` - Story interface and configuration
|
|
308
|
-
- `text-service.test.ts` - Text output formatting
|
|
309
306
|
- `types.test.ts` - Type definitions and contracts
|
|
310
307
|
|
|
311
308
|
### Integration Tests
|
|
@@ -326,3 +323,7 @@ pnpm test game-engine
|
|
|
326
323
|
# Generate coverage report
|
|
327
324
|
pnpm test:coverage
|
|
328
325
|
```
|
|
326
|
+
|
|
327
|
+
## License
|
|
328
|
+
|
|
329
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sharpee/engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Runtime engine for Sharpee IF Platform - game loop, command execution, and turn management",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@sharpee/channel-service": "^1.
|
|
16
|
-
"@sharpee/core": "^1.
|
|
17
|
-
"@sharpee/event-processor": "^1.
|
|
18
|
-
"@sharpee/plugins": "^1.
|
|
19
|
-
"@sharpee/if-domain": "^1.
|
|
20
|
-
"@sharpee/if-services": "^1.
|
|
21
|
-
"@sharpee/lang-en-us": "^1.
|
|
22
|
-
"@sharpee/parser-en-us": "^1.
|
|
23
|
-
"@sharpee/stdlib": "^1.
|
|
24
|
-
"@sharpee/text-blocks": "^1.
|
|
25
|
-
"@sharpee/world-model": "^1.
|
|
15
|
+
"@sharpee/channel-service": "^1.1.1",
|
|
16
|
+
"@sharpee/core": "^1.1.1",
|
|
17
|
+
"@sharpee/event-processor": "^1.1.1",
|
|
18
|
+
"@sharpee/plugins": "^1.1.1",
|
|
19
|
+
"@sharpee/if-domain": "^1.1.1",
|
|
20
|
+
"@sharpee/if-services": "^1.1.1",
|
|
21
|
+
"@sharpee/lang-en-us": "^1.1.1",
|
|
22
|
+
"@sharpee/parser-en-us": "^1.1.1",
|
|
23
|
+
"@sharpee/stdlib": "^1.1.1",
|
|
24
|
+
"@sharpee/text-blocks": "^1.1.1",
|
|
25
|
+
"@sharpee/world-model": "^1.1.1",
|
|
26
26
|
"fflate": "^0.8.2"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Scene evaluation turn plugin (ADR-149).
|
|
2
|
+
* Scene evaluation turn plugin (ADR-149, ADR-186).
|
|
3
3
|
*
|
|
4
4
|
* Evaluates scene begin/end conditions each turn. Runs after NPC turns
|
|
5
5
|
* and state machines, before daemons/fuses (priority 60).
|
|
6
6
|
*
|
|
7
7
|
* For each registered scene:
|
|
8
|
-
* - If state='waiting' and begin() returns true → activate, emit scene_began
|
|
9
|
-
*
|
|
8
|
+
* - If state='waiting' and begin() returns true → activate, emit scene_began,
|
|
9
|
+
* then invoke the scene's onBegin reaction (ADR-186)
|
|
10
|
+
* - If state='active' and end() returns true → end (or reset if recurring),
|
|
11
|
+
* emit scene_ended, then invoke the scene's onEnd reaction (ADR-186)
|
|
10
12
|
* - If state='active' → increment activeTurns
|
|
11
13
|
*
|
|
14
|
+
* scene_began / scene_ended are emitted as observable facts (perception,
|
|
15
|
+
* tooling, transcripts). Author-visible reactions come from the typed
|
|
16
|
+
* onBegin/onEnd callbacks, translated here into game.message events — the
|
|
17
|
+
* event the prose pipeline renders — so reactions are visible by construction
|
|
18
|
+
* (ADR-186).
|
|
19
|
+
*
|
|
12
20
|
* Public interface: SceneEvaluationPlugin (TurnPlugin implementation).
|
|
13
21
|
* Owner context: @sharpee/engine — turn cycle
|
|
14
22
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-evaluation-plugin.d.ts","sourceRoot":"","sources":["../../../../../../repos/sharpee/packages/engine/src/scene-evaluation-plugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scene-evaluation-plugin.d.ts","sourceRoot":"","sources":["../../../../../../repos/sharpee/packages/engine/src/scene-evaluation-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAQ/C,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AA2DtE,qBAAa,qBAAsB,YAAW,UAAU;IACtD,EAAE,SAA8B;IAChC,QAAQ,SAAM;IAEd;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,EAAE;CAqF5D"}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Scene evaluation turn plugin (ADR-149).
|
|
3
|
+
* Scene evaluation turn plugin (ADR-149, ADR-186).
|
|
4
4
|
*
|
|
5
5
|
* Evaluates scene begin/end conditions each turn. Runs after NPC turns
|
|
6
6
|
* and state machines, before daemons/fuses (priority 60).
|
|
7
7
|
*
|
|
8
8
|
* For each registered scene:
|
|
9
|
-
* - If state='waiting' and begin() returns true → activate, emit scene_began
|
|
10
|
-
*
|
|
9
|
+
* - If state='waiting' and begin() returns true → activate, emit scene_began,
|
|
10
|
+
* then invoke the scene's onBegin reaction (ADR-186)
|
|
11
|
+
* - If state='active' and end() returns true → end (or reset if recurring),
|
|
12
|
+
* emit scene_ended, then invoke the scene's onEnd reaction (ADR-186)
|
|
11
13
|
* - If state='active' → increment activeTurns
|
|
12
14
|
*
|
|
15
|
+
* scene_began / scene_ended are emitted as observable facts (perception,
|
|
16
|
+
* tooling, transcripts). Author-visible reactions come from the typed
|
|
17
|
+
* onBegin/onEnd callbacks, translated here into game.message events — the
|
|
18
|
+
* event the prose pipeline renders — so reactions are visible by construction
|
|
19
|
+
* (ADR-186).
|
|
20
|
+
*
|
|
13
21
|
* Public interface: SceneEvaluationPlugin (TurnPlugin implementation).
|
|
14
22
|
* Owner context: @sharpee/engine — turn cycle
|
|
15
23
|
*/
|
|
@@ -19,16 +27,54 @@ const world_model_1 = require("@sharpee/world-model");
|
|
|
19
27
|
let eventCounter = 0;
|
|
20
28
|
/**
|
|
21
29
|
* Creates a minimal ISemanticEvent with the given type and data.
|
|
30
|
+
*
|
|
31
|
+
* The id is made unique by a monotonic counter — no wall-clock is stamped in
|
|
32
|
+
* (deterministic replay, ADR-186). timestamp is left as a 0 sentinel; the
|
|
33
|
+
* engine's turn-event-processor backfills it at the single normalization point
|
|
34
|
+
* (`event.timestamp || Date.now()`).
|
|
22
35
|
*/
|
|
23
36
|
function sceneEvent(type, data) {
|
|
24
37
|
return {
|
|
25
|
-
id: `scene-${++eventCounter}
|
|
38
|
+
id: `scene-${++eventCounter}`,
|
|
26
39
|
type,
|
|
27
|
-
timestamp:
|
|
40
|
+
timestamp: 0,
|
|
28
41
|
entities: {},
|
|
29
42
|
data,
|
|
30
43
|
};
|
|
31
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Translates the return of a scene reaction callback into game.message events.
|
|
47
|
+
*
|
|
48
|
+
* Invokes the callback under try/catch (parity with the begin/end condition
|
|
49
|
+
* guards): a throwing callback is swallowed and produces no events, the
|
|
50
|
+
* transition having already completed. Normalizes the return (undefined → none,
|
|
51
|
+
* a single reaction → one event) and maps each SceneReaction to a game.message
|
|
52
|
+
* carrying either direct text or a messageId + params.
|
|
53
|
+
*/
|
|
54
|
+
function reactionEvents(callback, ctx) {
|
|
55
|
+
if (!callback)
|
|
56
|
+
return [];
|
|
57
|
+
let result;
|
|
58
|
+
try {
|
|
59
|
+
result = callback(ctx);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Callback threw — transition already happened; emit no reaction events.
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
if (!result)
|
|
66
|
+
return [];
|
|
67
|
+
const reactions = Array.isArray(result) ? result : [result];
|
|
68
|
+
return reactions.map((reaction) => {
|
|
69
|
+
if ('text' in reaction) {
|
|
70
|
+
return sceneEvent('game.message', { text: reaction.text });
|
|
71
|
+
}
|
|
72
|
+
return sceneEvent('game.message', {
|
|
73
|
+
messageId: reaction.messageId,
|
|
74
|
+
params: reaction.params,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
32
78
|
class SceneEvaluationPlugin {
|
|
33
79
|
id = 'sharpee.scene-evaluation';
|
|
34
80
|
priority = 60;
|
|
@@ -60,6 +106,13 @@ class SceneEvaluationPlugin {
|
|
|
60
106
|
sceneName: trait.name,
|
|
61
107
|
turn,
|
|
62
108
|
}));
|
|
109
|
+
// Author-visible reaction (ADR-186)
|
|
110
|
+
events.push(...reactionEvents(conds.onBegin, {
|
|
111
|
+
world,
|
|
112
|
+
sceneId,
|
|
113
|
+
sceneName: trait.name,
|
|
114
|
+
turn,
|
|
115
|
+
}));
|
|
63
116
|
}
|
|
64
117
|
}
|
|
65
118
|
catch {
|
|
@@ -91,6 +144,15 @@ class SceneEvaluationPlugin {
|
|
|
91
144
|
turn,
|
|
92
145
|
totalTurns,
|
|
93
146
|
}));
|
|
147
|
+
// Author-visible reaction (ADR-186). totalTurns is captured before
|
|
148
|
+
// the activeTurns reset above.
|
|
149
|
+
events.push(...reactionEvents(conds.onEnd, {
|
|
150
|
+
world,
|
|
151
|
+
sceneId,
|
|
152
|
+
sceneName: trait.name,
|
|
153
|
+
turn,
|
|
154
|
+
totalTurns,
|
|
155
|
+
}));
|
|
94
156
|
}
|
|
95
157
|
else {
|
|
96
158
|
// Scene still active — increment turn counter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-evaluation-plugin.js","sourceRoot":"","sources":["../../../../../../repos/sharpee/packages/engine/src/scene-evaluation-plugin.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"scene-evaluation-plugin.js","sourceRoot":"","sources":["../../../../../../repos/sharpee/packages/engine/src/scene-evaluation-plugin.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AAGH,sDAM8B;AAG9B,IAAI,YAAY,GAAG,CAAC,CAAC;AAErB;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,IAA6B;IAC7D,OAAO;QACL,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE;QAC7B,IAAI;QACJ,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,EAAE;QACZ,IAAI;KACL,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,cAAc,CACrB,QAAmC,EACnC,GAAsB;IAEtB,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzB,IAAI,MAA8C,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE5D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChC,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;YACvB,OAAO,UAAU,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,UAAU,CAAC,cAAc,EAAE;YAChC,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAa,qBAAqB;IAChC,EAAE,GAAG,0BAA0B,CAAC;IAChC,QAAQ,GAAG,EAAE,CAAC;IAEd;;OAEG;IACH,aAAa,CAAC,OAA0B;QACtC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QAChC,MAAM,UAAU,GAAG,KAAK,CAAC,qBAAqB,EAAE,CAAC;QACjD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAErC,MAAM,MAAM,GAAqB,EAAE,CAAC;QAEpC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAa,uBAAS,CAAC,KAAK,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,2BAA2B;gBAC3B,IAAI,CAAC;oBACH,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;wBACvB,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC;wBACvB,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;wBACtB,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;wBAEzB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,sBAAsB,EAAE;4BAC7C,OAAO;4BACP,SAAS,EAAE,KAAK,CAAC,IAAI;4BACrB,IAAI;yBACL,CAAC,CAAC,CAAC;wBAEJ,oCAAoC;wBACpC,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE;4BAC3C,KAAK;4BACL,OAAO;4BACP,SAAS,EAAE,KAAK,CAAC,IAAI;4BACrB,IAAI;yBACL,CAAC,CAAC,CAAC;oBACN,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,iDAAiD;gBACnD,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACpC,yBAAyB;gBACzB,IAAI,KAAK,GAAG,KAAK,CAAC;gBAClB,IAAI,CAAC;oBACH,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC3B,CAAC;gBAAC,MAAM,CAAC;oBACP,wCAAwC;gBAC1C,CAAC;gBAED,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;oBACrC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;oBAEzB,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;wBACpB,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;oBAC1B,CAAC;yBAAM,CAAC;wBACN,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;oBACxB,CAAC;oBACD,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;oBAEtB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,sBAAsB,EAAE;wBAC7C,OAAO;wBACP,SAAS,EAAE,KAAK,CAAC,IAAI;wBACrB,IAAI;wBACJ,UAAU;qBACX,CAAC,CAAC,CAAC;oBAEJ,mEAAmE;oBACnE,+BAA+B;oBAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE;wBACzC,KAAK;wBACL,OAAO;wBACP,SAAS,EAAE,KAAK,CAAC,IAAI;wBACrB,IAAI;wBACJ,UAAU;qBACX,CAAC,CAAC,CAAC;gBACN,CAAC;qBAAM,CAAC;oBACN,8CAA8C;oBAC9C,KAAK,CAAC,WAAW,EAAE,CAAC;gBACtB,CAAC;YACH,CAAC;YACD,4CAA4C;QAC9C,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA5FD,sDA4FC"}
|