script-engine-lib 0.4.3 → 1.0.0-rc1

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.
Files changed (62) hide show
  1. package/dist/index.d.mts +191 -0
  2. package/dist/index.d.ts +191 -5
  3. package/dist/index.js +21 -29
  4. package/dist/index.mjs +21 -0
  5. package/package.json +56 -52
  6. package/src/index.ts +10 -0
  7. package/dist/decorators/action-before-testing.d.ts +0 -2
  8. package/dist/decorators/action-before-testing.js +0 -23
  9. package/dist/decorators/action-before-testing.test.d.ts +0 -1
  10. package/dist/decorators/action-before-testing.test.js +0 -82
  11. package/dist/engine/script-engine.d.ts +0 -35
  12. package/dist/engine/script-engine.js +0 -175
  13. package/dist/engine/script-engine.test.d.ts +0 -1
  14. package/dist/engine/script-engine.test.js +0 -1277
  15. package/dist/engine/story-engine.d.ts +0 -35
  16. package/dist/engine/story-engine.js +0 -175
  17. package/dist/engine/story-engine.test.d.ts +0 -1
  18. package/dist/engine/story-engine.test.js +0 -1277
  19. package/dist/interfaces.d.ts +0 -51
  20. package/dist/interfaces.js +0 -27
  21. package/dist/simulator/decorators.d.ts +0 -2
  22. package/dist/simulator/decorators.js +0 -23
  23. package/dist/simulator/decorators.test.d.ts +0 -1
  24. package/dist/simulator/decorators.test.js +0 -81
  25. package/dist/simulator/event-branches-map.d.ts +0 -16
  26. package/dist/simulator/event-branches-map.js +0 -114
  27. package/dist/simulator/event-branches-map.test.d.ts +0 -1
  28. package/dist/simulator/event-branches-map.test.js +0 -120
  29. package/dist/simulator/event-test-simulator.d.ts +0 -42
  30. package/dist/simulator/event-test-simulator.js +0 -373
  31. package/dist/simulator/event-test-simulator.test.d.ts +0 -1
  32. package/dist/simulator/event-test-simulator.test.js +0 -1960
  33. package/dist/simulator/execution-history.d.ts +0 -6
  34. package/dist/simulator/execution-history.js +0 -22
  35. package/dist/simulator/helpers/event-branches-map.d.ts +0 -16
  36. package/dist/simulator/helpers/event-branches-map.js +0 -114
  37. package/dist/simulator/helpers/event-branches-map.test.d.ts +0 -1
  38. package/dist/simulator/helpers/event-branches-map.test.js +0 -120
  39. package/dist/simulator/helpers/execution-history.d.ts +0 -6
  40. package/dist/simulator/helpers/execution-history.js +0 -22
  41. package/dist/simulator/helpers/script-branches-map.d.ts +0 -16
  42. package/dist/simulator/helpers/script-branches-map.js +0 -114
  43. package/dist/simulator/helpers/script-branches-map.test.d.ts +0 -1
  44. package/dist/simulator/helpers/script-branches-map.test.js +0 -120
  45. package/dist/simulator/script-test-simulator.d.ts +0 -42
  46. package/dist/simulator/script-test-simulator.js +0 -373
  47. package/dist/simulator/script-test-simulator.test.d.ts +0 -1
  48. package/dist/simulator/script-test-simulator.test.js +0 -2013
  49. package/dist/structured-text/index.d.ts +0 -9
  50. package/dist/structured-text/index.js +0 -8
  51. package/dist/structured-text/rich-text-separator.d.ts +0 -48
  52. package/dist/structured-text/rich-text-separator.js +0 -146
  53. package/dist/structured-text/rich-text-separator.test.d.ts +0 -1
  54. package/dist/structured-text/rich-text-separator.test.js +0 -166
  55. package/dist/structured-text/rich-text-validator.d.ts +0 -19
  56. package/dist/structured-text/rich-text-validator.js +0 -73
  57. package/dist/structured-text/rich-text-validator.test.d.ts +0 -1
  58. package/dist/structured-text/rich-text-validator.test.js +0 -59
  59. package/dist/test.spec.d.ts +0 -0
  60. package/dist/test.spec.js +0 -7
  61. package/dist/test.test.d.ts +0 -1
  62. package/dist/test.test.js +0 -9
@@ -1,373 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EventTestSimulator = exports.StoryEngineSimulatorFunctions = void 0;
4
- const helpers_lib_1 = require("helpers-lib");
5
- const action_before_testing_1 = require("../decorators/action-before-testing");
6
- const interfaces_1 = require("../interfaces");
7
- const structured_text_1 = require("../structured-text");
8
- const event_branches_map_1 = require("./helpers/event-branches-map");
9
- const execution_history_1 = require("./helpers/execution-history");
10
- class StoryEngineSimulatorFunctions {
11
- }
12
- exports.StoryEngineSimulatorFunctions = StoryEngineSimulatorFunctions;
13
- const MAX_CALL_STACK_DEPTH = 100;
14
- class EventTestSimulator {
15
- constructor(eventDefinitions, options = { preventTypeChanges: true, richTextTags: undefined }) {
16
- this.eventDefinitions = eventDefinitions;
17
- this.options = options;
18
- this.visitedBranchStates = new Map();
19
- this.eventBranchesMap = new event_branches_map_1.EventBranchesMap(this.eventDefinitions);
20
- if (this.options.preventTypeChanges) {
21
- this.globalNameSpace = new Map();
22
- }
23
- }
24
- /**
25
- * @throws SimulationError, ActionsBeforeTestingError, BranchingBeforeTestingError
26
- */
27
- simulateEvent(eventDefinition, jsEngine, actionsBeforeTesting) {
28
- if (this.options.preventTypeChanges) {
29
- jsEngine.globalNameSpace = this.globalNameSpace;
30
- }
31
- let initialContext = {
32
- executionHistory: new execution_history_1.ExecutionHistory(),
33
- stack: new helpers_lib_1.Stack(),
34
- jsEngine,
35
- depth: 0,
36
- lastExecutedAction: undefined
37
- };
38
- let allPossibleStates = [initialContext];
39
- this.processActionsBeforeTesting(actionsBeforeTesting, allPossibleStates);
40
- this.visitedBranchStates.clear();
41
- this.executeEvent(eventDefinition, allPossibleStates);
42
- this.visitedBranchStates.clear();
43
- }
44
- getUnvisitedBranchLocations() {
45
- return this.eventBranchesMap.getUnvisitedBranchLocations();
46
- }
47
- processActionsBeforeTesting(actionsBeforeTesting, allPossibleStates) {
48
- actionsBeforeTesting.forEach((action, index) => {
49
- switch (action.type) {
50
- case 'command':
51
- this.executeActionBeforeTesting(action, allPossibleStates, index);
52
- break;
53
- case 'runEvent':
54
- this.branchOutFromEvent(action, allPossibleStates, index);
55
- break;
56
- default:
57
- throw new Error(`Unknown action before testing type: ${action.type}`);
58
- }
59
- });
60
- }
61
- executeActionBeforeTesting(action, allPossibleStates, index) {
62
- try {
63
- allPossibleStates.forEach(state => {
64
- Reflect.defineMetadata(action_before_testing_1.ActionBeforeTestingFlag, true, state.jsEngine.functions);
65
- state.jsEngine.execute(action.value);
66
- });
67
- }
68
- catch (e) {
69
- let errorMessage = this.prepareErrorMessage(`${e}`, allPossibleStates[0].executionHistory);
70
- throw new interfaces_1.ActionsBeforeTestingError(errorMessage, index);
71
- }
72
- }
73
- branchOutFromEvent(action, allPossibleStates, index) {
74
- let allPossibleEndings = [];
75
- let targetEvent = this.eventBranchesMap.getEvent(action.value);
76
- if (!targetEvent) {
77
- throw new Error(`Target event is not found: ${action.value}`);
78
- }
79
- try {
80
- this.visitedBranchStates.clear();
81
- allPossibleStates.forEach(state => {
82
- state.executionHistory.addEntry(`Branching out from event: ${action.value}`);
83
- state.depth = 0;
84
- Reflect.defineMetadata(action_before_testing_1.ActionBeforeTestingFlag, false, state.jsEngine.functions);
85
- let executionResult = this.executeBranch(targetEvent, state, false);
86
- if (!executionResult.exitFound) {
87
- let errorMessage = this.prepareErrorMessage(`All possible paths are creating infinite loops, no exit found while executing: ${action.value}`, state.executionHistory);
88
- throw new interfaces_1.SimulationError(errorMessage, this.eventBranchesMap.getRootBranchLocation(targetEvent));
89
- }
90
- executionResult.allEndings.forEach(ending => {
91
- allPossibleEndings.push(ending);
92
- });
93
- });
94
- let uniqueEndings = this.removeDuplicateEndings(allPossibleEndings);
95
- allPossibleStates.length = 0;
96
- allPossibleStates.push(...uniqueEndings);
97
- allPossibleStates.forEach(ending => {
98
- ending.executionHistory
99
- .addEntry(`${uniqueEndings.length} unique ending${uniqueEndings.length > 1 ? 's' : ''} generated.`)
100
- .addEntry('');
101
- if (!ending.lastExecutedAction) {
102
- throw new Error('Event execution is ended without executing any command!');
103
- }
104
- else {
105
- try {
106
- ending.jsEngine.functions.onEventBranchingEnd();
107
- }
108
- catch (e) {
109
- let path = this.eventBranchesMap.getActionLocation(ending.lastExecutedAction);
110
- let errorMessage = this.prepareErrorMessage(`${e}`, ending.executionHistory);
111
- throw new interfaces_1.SimulationError(errorMessage, path);
112
- }
113
- }
114
- });
115
- }
116
- catch (e) {
117
- if (e instanceof interfaces_1.SimulationError) {
118
- throw new interfaces_1.BranchingBeforeTestingError(`${e.message}`, index, e.location);
119
- }
120
- else {
121
- throw e;
122
- }
123
- }
124
- }
125
- executeEvent(eventDefinition, allPossibleStates) {
126
- allPossibleStates.forEach(state => {
127
- state.executionHistory.addEntry(`Running event: ${eventDefinition.id}`);
128
- state.depth = 0;
129
- Reflect.defineMetadata(action_before_testing_1.ActionBeforeTestingFlag, false, state.jsEngine.functions);
130
- let executionResult = this.executeBranch(eventDefinition, state, true);
131
- if (!executionResult.exitFound) {
132
- let errorMessage = this.prepareErrorMessage(`All possible paths are creating infinite loops, no exit found while executing: ${eventDefinition.id}`, state.executionHistory);
133
- throw new interfaces_1.SimulationError(errorMessage, this.eventBranchesMap.getRootBranchLocation(eventDefinition));
134
- }
135
- executionResult.allEndings.forEach(ending => {
136
- if (!ending.lastExecutedAction) {
137
- throw new Error('Event execution is ended without executing any command!');
138
- }
139
- else {
140
- try {
141
- ending.jsEngine.functions.onEnd();
142
- }
143
- catch (e) {
144
- let path = this.eventBranchesMap.getActionLocation(ending.lastExecutedAction);
145
- let errorMessage = this.prepareErrorMessage(`${e}`, ending.executionHistory);
146
- throw new interfaces_1.SimulationError(errorMessage, path);
147
- }
148
- }
149
- });
150
- });
151
- }
152
- executeBranch(branch, context, registerVisitedBranches) {
153
- if (!this.isBranchVisitedAndRegister(branch, context)) {
154
- return {
155
- allEndings: [],
156
- exitFound: false
157
- };
158
- }
159
- let allPossibleEndings = [];
160
- let exitFound = true;
161
- if (registerVisitedBranches) {
162
- this.eventBranchesMap.setVisited(branch);
163
- }
164
- context.depth++;
165
- if (context.depth > MAX_CALL_STACK_DEPTH) {
166
- let errorMessage = this.prepareErrorMessage(`Maximum depth "${MAX_CALL_STACK_DEPTH}" is reached. Try to reduce the event branching tree or check infinite loops with trivial state changes.`, context.executionHistory);
167
- throw new interfaces_1.SimulationError(errorMessage, this.eventBranchesMap.getRootBranchLocation(branch));
168
- }
169
- context.stack.add(...branch.actions);
170
- while (!context.stack.isEmpty) {
171
- let action = context.stack.pop();
172
- let executionResult = this.executeAction(action, context, registerVisitedBranches);
173
- if (context.stack.isEmpty) {
174
- allPossibleEndings.push(...executionResult.allEndings);
175
- exitFound = executionResult.exitFound && exitFound;
176
- }
177
- }
178
- allPossibleEndings = allPossibleEndings.length > 0 ? this.removeDuplicateEndings(allPossibleEndings) : [];
179
- return {
180
- allEndings: allPossibleEndings,
181
- exitFound
182
- };
183
- }
184
- executeAction(action, context, registerVisitedBranches) {
185
- context.lastExecutedAction = action;
186
- switch (action.type) {
187
- case 'command':
188
- return this.executeActionCommand(action, context);
189
- case 'dialog':
190
- return this.executeDialogCommand(action, context);
191
- case 'jumpToEvent':
192
- return this.executeActionJumpToEvent(action, context, registerVisitedBranches);
193
- case 'branchByCondition':
194
- return this.executeActionBranchByCondition(action, context, registerVisitedBranches);
195
- case 'branchByChance':
196
- return this.executeActionBranchByChance(action, context, registerVisitedBranches);
197
- case 'branchByPlayerChoice':
198
- return this.executeActionBranchByPlayerChoice(action, context, registerVisitedBranches);
199
- default:
200
- throw new Error(`Unknown action type: ${action.type}`);
201
- }
202
- }
203
- executeActionCommand(action, context) {
204
- try {
205
- context.jsEngine.execute(action.value);
206
- }
207
- catch (e) {
208
- let path = this.eventBranchesMap.getActionLocation(action);
209
- let errorMessage = this.prepareErrorMessage(`${e}`, context.executionHistory);
210
- throw new interfaces_1.SimulationError(errorMessage, path);
211
- }
212
- return {
213
- allEndings: [context],
214
- exitFound: true
215
- };
216
- }
217
- executeDialogCommand(action, context) {
218
- let dialogItem = action.value;
219
- let text;
220
- try {
221
- text = context.jsEngine.string(dialogItem.text);
222
- this.options.richTextTags && structured_text_1.RichTextValidator.validate(text, this.options.richTextTags);
223
- context.jsEngine.functions.onDialog(text, dialogItem.speaker);
224
- }
225
- catch (e) {
226
- let path = this.eventBranchesMap.getActionLocation(action);
227
- let errorMessage = this.prepareErrorMessage(`${e}`, context.executionHistory);
228
- throw new interfaces_1.SimulationError(errorMessage, path);
229
- }
230
- return {
231
- allEndings: [context],
232
- exitFound: true
233
- };
234
- }
235
- executeActionJumpToEvent(action, context, registerVisitedBranches) {
236
- let targetEvent = this.eventBranchesMap.getEvent(action.value);
237
- context.executionHistory.addEntry(`Jumping to event: ${action.value}`);
238
- return this.executeBranch(targetEvent, context, registerVisitedBranches);
239
- }
240
- executeActionBranchByCondition(action, context, registerVisitedBranches) {
241
- let subBranches = action.value;
242
- let validBranch = subBranches.find(subBranch => this.checkBranchCondition(subBranch, context));
243
- if (!validBranch) {
244
- let path = this.eventBranchesMap.getActionLocation(action);
245
- let errorMessage = this.prepareErrorMessage(`No option is fulfilled the condition during branching.`, context.executionHistory);
246
- throw new interfaces_1.SimulationError(errorMessage, path);
247
- }
248
- context.executionHistory.addEntry(`Branching by condition: ${validBranch.condition ? validBranch.condition : 'default'}`);
249
- return this.executeBranch(validBranch, context, registerVisitedBranches);
250
- }
251
- executeActionBranchByChance(action, context, registerVisitedBranches) {
252
- let subBranches = action.value;
253
- let validItems = subBranches
254
- .map((subBranch, index) => ({ index, subBranch }))
255
- .filter(item => this.checkBranchCondition(item.subBranch, context));
256
- if (validItems.length === 0) {
257
- let path = this.eventBranchesMap.getActionLocation(action);
258
- let errorMessage = this.prepareErrorMessage(`No option is fulfilled the condition during branching.`, context.executionHistory);
259
- throw new interfaces_1.SimulationError(errorMessage, path);
260
- }
261
- let allExecutionResults = validItems.map(item => {
262
- try {
263
- let weight = helpers_lib_1.Comparator.isString(item.subBranch.weight)
264
- ? context.jsEngine.number(item.subBranch.weight)
265
- : item.subBranch.weight;
266
- if (!helpers_lib_1.Comparator.isNumber(weight) || weight < 0) {
267
- throw new Error(`Weight of branch ${item.index} is not a valid number: "${item.subBranch.weight}" -> ${weight}.`);
268
- }
269
- }
270
- catch (e) {
271
- let path = this.eventBranchesMap.getActionLocation(action);
272
- let errorMessage = this.prepareErrorMessage(`${e}`, context.executionHistory);
273
- throw new interfaces_1.SimulationError(errorMessage, path);
274
- }
275
- let newContext = this.duplicateContext(context);
276
- newContext.executionHistory.addEntry(`Branching by chance: ${item.index}`);
277
- return this.executeBranch(item.subBranch, newContext, registerVisitedBranches);
278
- });
279
- return {
280
- allEndings: allExecutionResults.flatMap(result => result.allEndings),
281
- exitFound: allExecutionResults.some(result => result.exitFound)
282
- };
283
- }
284
- executeActionBranchByPlayerChoice(action, context, registerVisitedBranches) {
285
- let subBranches = action.value;
286
- let validBranches = subBranches.filter(subBranch => this.checkBranchCondition(subBranch, context));
287
- if (validBranches.length === 0) {
288
- let path = this.eventBranchesMap.getActionLocation(action);
289
- let errorMessage = this.prepareErrorMessage(`No option is fulfilled the condition during branching.`, context.executionHistory);
290
- throw new interfaces_1.SimulationError(errorMessage, path);
291
- }
292
- try {
293
- context.jsEngine.functions.onPlayerChoice(validBranches.map(branch => context.jsEngine.string(branch.text)));
294
- }
295
- catch (e) {
296
- let path = this.eventBranchesMap.getActionLocation(action);
297
- let errorMessage = this.prepareErrorMessage(`${e}`, context.executionHistory);
298
- throw new interfaces_1.SimulationError(errorMessage, path);
299
- }
300
- let allExecutionResults = validBranches.map(subBranch => {
301
- let newContext = this.duplicateContext(context);
302
- newContext.executionHistory.addEntry(`Player choice: ${subBranch.text}`);
303
- return this.executeBranch(subBranch, newContext, registerVisitedBranches);
304
- });
305
- return {
306
- allEndings: allExecutionResults.flatMap(result => result.allEndings),
307
- exitFound: allExecutionResults.some(result => result.exitFound)
308
- };
309
- }
310
- checkBranchCondition(branch, context) {
311
- if (!branch.condition) {
312
- return true;
313
- }
314
- else {
315
- try {
316
- return context.jsEngine.boolean(branch.condition);
317
- }
318
- catch (e) {
319
- let path = this.eventBranchesMap.getBranchLocation(branch);
320
- let errorMessage = this.prepareErrorMessage(`${e}`, context.executionHistory);
321
- throw new interfaces_1.SimulationError(errorMessage, path);
322
- }
323
- }
324
- }
325
- removeDuplicateEndings(allPossibleEndings) {
326
- let uniqueEndings = [];
327
- let processedEndings = allPossibleEndings.map(ending => ({
328
- ending: ending,
329
- variablesString: JSON.stringify(ending.jsEngine.variables),
330
- functionsString: JSON.stringify(ending.jsEngine.functions)
331
- }));
332
- processedEndings.forEach(data => {
333
- let isUnique = uniqueEndings.every(uniqueEnding => data.functionsString !== uniqueEnding.functionsString || data.variablesString !== uniqueEnding.variablesString);
334
- if (isUnique) {
335
- uniqueEndings.push({
336
- ending: data.ending,
337
- variablesString: data.variablesString,
338
- functionsString: data.functionsString
339
- });
340
- }
341
- });
342
- return uniqueEndings.map(data => data.ending);
343
- }
344
- isBranchVisitedAndRegister(branch, context) {
345
- let stateString = JSON.stringify(context.jsEngine.variables) + JSON.stringify(context.jsEngine.functions);
346
- let branchStates = this.visitedBranchStates.get(branch);
347
- if (!branchStates) {
348
- branchStates = new Set();
349
- this.visitedBranchStates.set(branch, branchStates);
350
- }
351
- if (branchStates.has(stateString)) {
352
- return false;
353
- }
354
- else {
355
- branchStates.add(stateString);
356
- return true;
357
- }
358
- }
359
- duplicateContext(context) {
360
- return {
361
- executionHistory: context.executionHistory.duplicate(),
362
- stack: context.stack.duplicate(),
363
- jsEngine: context.jsEngine.duplicate(),
364
- depth: context.depth,
365
- lastExecutedAction: context.lastExecutedAction
366
- };
367
- }
368
- prepareErrorMessage(errorMessage, executionHistory) {
369
- return `${errorMessage}\n\n----Execution history----\n${executionHistory.toString()}`;
370
- }
371
- }
372
- exports.EventTestSimulator = EventTestSimulator;
373
- //# sourceMappingURL=event-test-simulator.js.map
@@ -1 +0,0 @@
1
- export {};