qnce-engine 0.1.0 → 1.2.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 +959 -5
- package/dist/cli/audit.js +6 -4
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/init.js +11 -9
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/perf.d.ts +30 -0
- package/dist/cli/perf.d.ts.map +1 -0
- package/dist/cli/perf.js +220 -0
- package/dist/cli/perf.js.map +1 -0
- package/dist/cli/play.d.ts +4 -0
- package/dist/cli/play.d.ts.map +1 -0
- package/dist/cli/play.js +259 -0
- package/dist/cli/play.js.map +1 -0
- package/dist/engine/condition.d.ts +69 -0
- package/dist/engine/condition.d.ts.map +1 -0
- package/dist/engine/condition.js +195 -0
- package/dist/engine/condition.js.map +1 -0
- package/dist/engine/core.d.ts +378 -11
- package/dist/engine/core.d.ts.map +1 -1
- package/dist/engine/core.js +1433 -13
- package/dist/engine/core.js.map +1 -1
- package/dist/engine/demo-story.d.ts.map +1 -1
- package/dist/engine/demo-story.js +103 -14
- package/dist/engine/demo-story.js.map +1 -1
- package/dist/engine/errors.d.ts +76 -0
- package/dist/engine/errors.d.ts.map +1 -0
- package/dist/engine/errors.js +178 -0
- package/dist/engine/errors.js.map +1 -0
- package/dist/engine/types.d.ts +445 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +9 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/validation.d.ts +110 -0
- package/dist/engine/validation.d.ts.map +1 -0
- package/dist/engine/validation.js +261 -0
- package/dist/engine/validation.js.map +1 -0
- package/dist/examples/examples/autosave-undo-demo.js +248 -0
- package/dist/examples/examples/persistence-demo.js +63 -0
- package/dist/examples/src/engine/condition.js +194 -0
- package/dist/examples/src/engine/core.js +1382 -0
- package/dist/examples/src/engine/demo-story.js +200 -0
- package/dist/examples/src/engine/types.js +8 -0
- package/dist/examples/src/index.js +35 -0
- package/dist/examples/src/integrations/react.js +322 -0
- package/dist/examples/src/narrative/branching/engine-simple.js +348 -0
- package/dist/examples/src/narrative/branching/index.js +55 -0
- package/dist/examples/src/narrative/branching/models.js +5 -0
- package/dist/examples/src/performance/ObjectPool.js +296 -0
- package/dist/examples/src/performance/PerfReporter.js +280 -0
- package/dist/examples/src/performance/ThreadPool.js +347 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -3
- package/dist/index.js.map +1 -1
- package/dist/integrations/react.d.ts +200 -0
- package/dist/integrations/react.d.ts.map +1 -0
- package/dist/integrations/react.js +365 -0
- package/dist/integrations/react.js.map +1 -0
- package/dist/narrative/branching/engine-simple.d.ts +84 -0
- package/dist/narrative/branching/engine-simple.d.ts.map +1 -0
- package/dist/narrative/branching/engine-simple.js +349 -0
- package/dist/narrative/branching/engine-simple.js.map +1 -0
- package/dist/narrative/branching/engine.d.ts +1 -0
- package/dist/narrative/branching/engine.d.ts.map +1 -0
- package/dist/narrative/branching/engine.js +2 -0
- package/dist/narrative/branching/engine.js.map +1 -0
- package/dist/narrative/branching/index.d.ts +12 -0
- package/dist/narrative/branching/index.d.ts.map +1 -0
- package/dist/narrative/branching/index.js +56 -0
- package/dist/narrative/branching/index.js.map +1 -0
- package/dist/narrative/branching/models.d.ts +223 -0
- package/dist/narrative/branching/models.d.ts.map +1 -0
- package/dist/narrative/branching/models.js +6 -0
- package/dist/narrative/branching/models.js.map +1 -0
- package/dist/performance/HotReloadDelta.d.ts +124 -0
- package/dist/performance/HotReloadDelta.d.ts.map +1 -0
- package/dist/performance/HotReloadDelta.js +328 -0
- package/dist/performance/HotReloadDelta.js.map +1 -0
- package/dist/performance/ObjectPool.d.ts +150 -0
- package/dist/performance/ObjectPool.d.ts.map +1 -0
- package/dist/performance/ObjectPool.js +297 -0
- package/dist/performance/ObjectPool.js.map +1 -0
- package/dist/performance/PerfReporter.d.ts +123 -0
- package/dist/performance/PerfReporter.d.ts.map +1 -0
- package/dist/performance/PerfReporter.js +281 -0
- package/dist/performance/PerfReporter.js.map +1 -0
- package/dist/performance/ThreadPool.d.ts +107 -0
- package/dist/performance/ThreadPool.d.ts.map +1 -0
- package/dist/performance/ThreadPool.js +348 -0
- package/dist/performance/ThreadPool.js.map +1 -0
- package/dist/ui/__tests__/AutosaveIndicator.test.d.ts +2 -0
- package/dist/ui/__tests__/AutosaveIndicator.test.d.ts.map +1 -0
- package/dist/ui/__tests__/AutosaveIndicator.test.js +329 -0
- package/dist/ui/__tests__/AutosaveIndicator.test.js.map +1 -0
- package/dist/ui/__tests__/UndoRedoControls.test.d.ts +2 -0
- package/dist/ui/__tests__/UndoRedoControls.test.d.ts.map +1 -0
- package/dist/ui/__tests__/UndoRedoControls.test.js +245 -0
- package/dist/ui/__tests__/UndoRedoControls.test.js.map +1 -0
- package/dist/ui/__tests__/autosave-simple.test.d.ts +2 -0
- package/dist/ui/__tests__/autosave-simple.test.d.ts.map +1 -0
- package/dist/ui/__tests__/autosave-simple.test.js +29 -0
- package/dist/ui/__tests__/autosave-simple.test.js.map +1 -0
- package/dist/ui/__tests__/setup.d.ts +2 -0
- package/dist/ui/__tests__/setup.d.ts.map +1 -0
- package/dist/ui/__tests__/setup.js +40 -0
- package/dist/ui/__tests__/setup.js.map +1 -0
- package/dist/ui/__tests__/smoke-test.d.ts +2 -0
- package/dist/ui/__tests__/smoke-test.d.ts.map +1 -0
- package/dist/ui/__tests__/smoke-test.js +18 -0
- package/dist/ui/__tests__/smoke-test.js.map +1 -0
- package/dist/ui/__tests__/smoke-test.test.d.ts +2 -0
- package/dist/ui/__tests__/smoke-test.test.d.ts.map +1 -0
- package/dist/ui/__tests__/smoke-test.test.js +18 -0
- package/dist/ui/__tests__/smoke-test.test.js.map +1 -0
- package/dist/ui/__tests__/useKeyboardShortcuts.test.d.ts +2 -0
- package/dist/ui/__tests__/useKeyboardShortcuts.test.d.ts.map +1 -0
- package/dist/ui/__tests__/useKeyboardShortcuts.test.js +374 -0
- package/dist/ui/__tests__/useKeyboardShortcuts.test.js.map +1 -0
- package/dist/ui/components/AutosaveIndicator.d.ts +18 -0
- package/dist/ui/components/AutosaveIndicator.d.ts.map +1 -0
- package/dist/ui/components/AutosaveIndicator.js +175 -0
- package/dist/ui/components/AutosaveIndicator.js.map +1 -0
- package/dist/ui/components/UndoRedoControls.d.ts +16 -0
- package/dist/ui/components/UndoRedoControls.d.ts.map +1 -0
- package/dist/ui/components/UndoRedoControls.js +144 -0
- package/dist/ui/components/UndoRedoControls.js.map +1 -0
- package/dist/ui/hooks/useKeyboardShortcuts.d.ts +22 -0
- package/dist/ui/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/dist/ui/hooks/useKeyboardShortcuts.js +162 -0
- package/dist/ui/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +14 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/types.d.ts +141 -0
- package/dist/ui/types.d.ts.map +1 -0
- package/dist/ui/types.js +51 -0
- package/dist/ui/types.js.map +1 -0
- package/docs/PERFORMANCE.md +355 -0
- package/docs/branching/ERD.md +214 -0
- package/docs/branching/PDM.md +443 -0
- package/docs/branching/RELEASE-v1.2.0.md +169 -0
- package/examples/autosave-undo-demo.ts +306 -0
- package/examples/branching-advanced-demo.ts +339 -0
- package/examples/branching-demo-simple.ts +0 -0
- package/examples/branching-demo.ts +0 -0
- package/examples/branching-quickstart.ts +314 -0
- package/examples/persistence-demo.ts +84 -0
- package/examples/quickstart-demo.js +82 -0
- package/examples/tsconfig.json +13 -0
- package/examples/ui-components-demo.tsx +320 -0
- package/examples/validation-demo-story.json +177 -0
- package/examples/validation-demo.js +163 -0
- package/package.json +41 -8
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// QNCE Choice Validation Demo
|
|
4
|
+
// Demonstrates the choice validation system with various error scenarios
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createQNCEEngine,
|
|
8
|
+
ChoiceValidationError,
|
|
9
|
+
isChoiceValidationError,
|
|
10
|
+
createChoiceValidator,
|
|
11
|
+
StandardValidationRules
|
|
12
|
+
} from '../src/engine/core.js';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import { fileURLToPath } from 'url';
|
|
16
|
+
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
|
|
19
|
+
// Load the validation demo story
|
|
20
|
+
const storyPath = path.join(__dirname, 'validation-demo-story.json');
|
|
21
|
+
const storyData = JSON.parse(fs.readFileSync(storyPath, 'utf8'));
|
|
22
|
+
|
|
23
|
+
console.log('🛡️ QNCE Choice Validation Demo');
|
|
24
|
+
console.log('=====================================\n');
|
|
25
|
+
|
|
26
|
+
// Create engine with demo story
|
|
27
|
+
const engine = createQNCEEngine(storyData);
|
|
28
|
+
|
|
29
|
+
function displayCurrentState() {
|
|
30
|
+
const currentNode = engine.getCurrentNode();
|
|
31
|
+
const availableChoices = engine.getAvailableChoices();
|
|
32
|
+
|
|
33
|
+
console.log(`\n📍 Current Location: ${currentNode.id}`);
|
|
34
|
+
console.log(`📝 ${currentNode.text}\n`);
|
|
35
|
+
|
|
36
|
+
console.log('✅ Available Choices:');
|
|
37
|
+
availableChoices.forEach((choice, index) => {
|
|
38
|
+
console.log(` ${index + 1}. ${choice.text}`);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (availableChoices.length === 0) {
|
|
42
|
+
console.log(' (No choices available - story complete)');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Show current state
|
|
46
|
+
const state = engine.getState();
|
|
47
|
+
console.log(`\n🏷️ Current Flags: ${JSON.stringify(state.flags, null, 2)}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function demonstrateValidationError(choiceIndex, errorType) {
|
|
51
|
+
console.log(`\n❌ Testing ${errorType}...`);
|
|
52
|
+
try {
|
|
53
|
+
engine.makeChoice(choiceIndex);
|
|
54
|
+
console.log('✅ Choice executed successfully (unexpected!)');
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (isChoiceValidationError(error)) {
|
|
57
|
+
console.log(`🚫 ChoiceValidationError caught: ${error.message}`);
|
|
58
|
+
console.log(`📋 Failed conditions: ${error.validationResult.failedConditions?.join(', ') || 'none'}`);
|
|
59
|
+
|
|
60
|
+
const userMessage = error.getUserFriendlyMessage();
|
|
61
|
+
console.log(`👤 User-friendly message:\n${userMessage}`);
|
|
62
|
+
|
|
63
|
+
const debugInfo = error.getDebugInfo();
|
|
64
|
+
console.log(`🔧 Debug info: ${JSON.stringify(debugInfo, null, 2)}`);
|
|
65
|
+
} else {
|
|
66
|
+
console.log(`❗ Other error: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function runDemo() {
|
|
72
|
+
try {
|
|
73
|
+
// Display initial state
|
|
74
|
+
displayCurrentState();
|
|
75
|
+
|
|
76
|
+
// Test 1: Try a valid choice first
|
|
77
|
+
console.log('\n🧪 Test 1: Valid Choice');
|
|
78
|
+
console.log('Attempting choice 1 (Try to force the door open)...');
|
|
79
|
+
engine.makeChoice(0);
|
|
80
|
+
displayCurrentState();
|
|
81
|
+
|
|
82
|
+
// Reset to entrance
|
|
83
|
+
engine.goToNodeById('entrance');
|
|
84
|
+
displayCurrentState();
|
|
85
|
+
|
|
86
|
+
// Test 2: Flag requirement failure
|
|
87
|
+
console.log('\n🧪 Test 2: Flag Requirement Failure');
|
|
88
|
+
demonstrateValidationError(1, 'missing flag requirement (hasGoldenKey)');
|
|
89
|
+
|
|
90
|
+
// Test 3: Disabled choice
|
|
91
|
+
console.log('\n🧪 Test 3: Disabled Choice');
|
|
92
|
+
demonstrateValidationError(2, 'disabled choice');
|
|
93
|
+
|
|
94
|
+
// Test 4: Inventory requirement failure
|
|
95
|
+
console.log('\n🧪 Test 4: Inventory Requirement Failure');
|
|
96
|
+
demonstrateValidationError(3, 'insufficient inventory (gold and reputation)');
|
|
97
|
+
|
|
98
|
+
// Test 5: Time requirement failure
|
|
99
|
+
console.log('\n🧪 Test 5: Time Requirement Failure');
|
|
100
|
+
demonstrateValidationError(4, 'time condition not met');
|
|
101
|
+
|
|
102
|
+
// Test 6: Out of bounds choice
|
|
103
|
+
console.log('\n🧪 Test 6: Out of Bounds Choice');
|
|
104
|
+
try {
|
|
105
|
+
engine.makeChoice(99);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.log(`🚫 Navigation error: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Test 7: Add custom validation rule
|
|
111
|
+
console.log('\n🧪 Test 7: Custom Validation Rule');
|
|
112
|
+
const validator = engine.getChoiceValidator();
|
|
113
|
+
validator.addRule({
|
|
114
|
+
name: 'weather-safety',
|
|
115
|
+
priority: 10,
|
|
116
|
+
validate: (choice, context) => {
|
|
117
|
+
if (choice.text.includes('outside') && !context.state.flags.hasUmbrella) {
|
|
118
|
+
return {
|
|
119
|
+
isValid: false,
|
|
120
|
+
reason: 'Too dangerous to go outside without an umbrella!',
|
|
121
|
+
failedConditions: ['no-umbrella'],
|
|
122
|
+
suggestedChoices: context.currentNode.choices.filter(c => !c.text.includes('outside'))
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return { isValid: true };
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// This should now fail our custom rule
|
|
130
|
+
console.log('Added custom weather-safety validation rule...');
|
|
131
|
+
demonstrateValidationError(2, 'custom weather rule failure');
|
|
132
|
+
|
|
133
|
+
// Test 8: Show successful path with proper flags
|
|
134
|
+
console.log('\n🧪 Test 8: Successful Path with Flags');
|
|
135
|
+
|
|
136
|
+
// Set up proper flags for success
|
|
137
|
+
const state = engine.getState();
|
|
138
|
+
state.flags.hasGoldenKey = true;
|
|
139
|
+
state.flags.inventory = { gold: 100, reputation: 10 };
|
|
140
|
+
|
|
141
|
+
console.log('Set hasGoldenKey=true and sufficient inventory...');
|
|
142
|
+
displayCurrentState();
|
|
143
|
+
|
|
144
|
+
console.log('Now attempting choice 2 (Use the golden key)...');
|
|
145
|
+
engine.makeChoice(1); // This should work now
|
|
146
|
+
displayCurrentState();
|
|
147
|
+
|
|
148
|
+
console.log('\n✅ Demo completed successfully!');
|
|
149
|
+
console.log('\nKey takeaways:');
|
|
150
|
+
console.log('- ChoiceValidationError provides rich error information');
|
|
151
|
+
console.log('- Multiple validation rules can be applied in priority order');
|
|
152
|
+
console.log('- Custom validation rules can be added for game-specific logic');
|
|
153
|
+
console.log('- Flag, inventory, time, and enabled state validation work seamlessly');
|
|
154
|
+
console.log('- Error messages are both user-friendly and developer-friendly');
|
|
155
|
+
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error('Demo failed:', error);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Run the demo
|
|
163
|
+
runDemo();
|
package/package.json
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qnce-engine",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine with performance optimization",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"type": "module",
|
|
8
7
|
"bin": {
|
|
9
8
|
"qnce-audit": "dist/cli/audit.js",
|
|
10
|
-
"qnce-init": "dist/cli/init.js"
|
|
9
|
+
"qnce-init": "dist/cli/init.js",
|
|
10
|
+
"qnce-perf": "dist/cli/perf.js",
|
|
11
|
+
"qnce-play": "dist/cli/play.js"
|
|
11
12
|
},
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsc",
|
|
14
15
|
"build:watch": "tsc --watch",
|
|
16
|
+
"build:examples": "tsc --outDir dist/examples --target ES2022 --module CommonJS --moduleResolution Node --strict --esModuleInterop --skipLibCheck --declaration false examples/persistence-demo.ts examples/autosave-undo-demo.ts",
|
|
15
17
|
"lint": "eslint .",
|
|
16
|
-
"test": "
|
|
17
|
-
"
|
|
18
|
+
"test": "./node_modules/.bin/jest",
|
|
19
|
+
"test:watch": "./node_modules/.bin/jest --watch",
|
|
20
|
+
"test:coverage": "./node_modules/.bin/jest --coverage",
|
|
21
|
+
"test:performance": "node scripts/performance-tests.js",
|
|
22
|
+
"demo:performance": "npm run build && node scripts/performance-demo.js",
|
|
23
|
+
"demo:quickstart": "npm run build && node examples/quickstart-demo.js",
|
|
24
|
+
"demo:persistence": "npm run build:examples && node dist/examples/examples/persistence-demo.js",
|
|
25
|
+
"demo:autosave": "npm run build:examples && node dist/examples/examples/autosave-undo-demo.js",
|
|
26
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
18
27
|
},
|
|
19
28
|
"keywords": [
|
|
20
29
|
"narrative",
|
|
@@ -30,15 +39,39 @@
|
|
|
30
39
|
"type": "git",
|
|
31
40
|
"url": "https://github.com/ByteSower/qnce-engine.git"
|
|
32
41
|
},
|
|
33
|
-
"
|
|
42
|
+
"homepage": "https://github.com/ByteSower/qnce-engine#readme",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/ByteSower/qnce-engine/issues"
|
|
45
|
+
},
|
|
34
46
|
"devDependencies": {
|
|
47
|
+
"@testing-library/dom": "^10.4.0",
|
|
48
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
49
|
+
"@testing-library/react": "^15.0.7",
|
|
50
|
+
"@testing-library/user-event": "^14.6.1",
|
|
51
|
+
"@types/jest": "^29.5.14",
|
|
35
52
|
"@types/node": "^20.0.0",
|
|
53
|
+
"@types/react": "^18.0.0",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
55
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
56
|
+
"eslint": "^8.57.1",
|
|
57
|
+
"eslint-plugin-react": "^7.33.0",
|
|
58
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
59
|
+
"jest": "^29.7.0",
|
|
60
|
+
"jest-environment-jsdom": "^30.0.4",
|
|
61
|
+
"react": "^18.0.0",
|
|
62
|
+
"react-dom": "^18.3.1",
|
|
63
|
+
"ts-jest": "^29.4.0",
|
|
36
64
|
"typescript": "~5.8.3"
|
|
37
65
|
},
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"react": ">=16.8.0"
|
|
68
|
+
},
|
|
38
69
|
"files": [
|
|
39
70
|
"dist/**/*",
|
|
40
71
|
"README.md",
|
|
41
72
|
"LICENSE",
|
|
42
|
-
"examples/**/*"
|
|
73
|
+
"examples/**/*",
|
|
74
|
+
"docs/branching/**/*",
|
|
75
|
+
"docs/PERFORMANCE.md"
|
|
43
76
|
]
|
|
44
77
|
}
|