@media-quest/engine 0.0.14 → 0.0.15
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/package.json +1 -2
- package/src/Delement/DElement.dto.ts +5 -0
- package/src/Delement/DElement.ts +78 -253
- package/src/Delement/DImg.ts +31 -70
- package/src/Delement/DStyle.ts +156 -156
- package/src/Delement/DText.ts +9 -25
- package/src/Delement/Ddiv.ts +10 -23
- package/src/Delement/button-click-action.ts +11 -0
- package/src/Delement/element-factory.ts +40 -0
- package/src/engine/DCommand.ts +21 -0
- package/src/engine/SchemaDto.ts +24 -0
- package/src/engine/SchemaEngine.ts +48 -120
- package/src/{player → engine}/dplayer.spec.ts +20 -17
- package/src/{player → engine}/dplayer.ts +29 -16
- package/src/engine/history-que.spec.ts +59 -0
- package/src/engine/history-que.ts +39 -0
- package/src/{player → engine}/next-que.spec.ts +19 -8
- package/src/engine/next-que.ts +93 -0
- package/src/page/Page.ts +160 -0
- package/src/page/media-player.ts +117 -0
- package/src/page/page-component.ts +113 -0
- package/src/page/page-result.ts +11 -0
- package/src/page/task-manager.ts +203 -0
- package/src/page/task-state.ts +55 -0
- package/src/page/task.ts +87 -0
- package/src/public-api.ts +17 -13
- package/src/rules/__test__/rule-engine.spec.ts +1 -1
- package/src/utils/DUtil.ts +110 -103
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/public-api.js +0 -2245
- package/dist/public-api.mjs +0 -2205
- package/src/Delement/AudioContainer.ts +0 -169
- package/src/Delement/DAuto-play.ts +0 -36
- package/src/Delement/VideoContainer.ts +0 -199
- package/src/commands/DCommand.ts +0 -63
- package/src/commands/DCommandBus.ts +0 -60
- package/src/dto/AnimationDto.ts +0 -4
- package/src/dto/DElement.dto.ts +0 -46
- package/src/dto/SchemaDto.ts +0 -65
- package/src/engine/DPage.ts +0 -60
- package/src/engine/element-factory.ts +0 -52
- package/src/event-handlers/DEventHandler.ts +0 -29
- package/src/events/DEvents.ts +0 -94
- package/src/events/event-bus.spec.ts +0 -21
- package/src/events/event-bus.ts +0 -81
- package/src/kladd/context-menu-manager.ts +0 -56
- package/src/player/history-que.spec.ts +0 -46
- package/src/player/history-que.ts +0 -38
- package/src/player/next-que.ts +0 -93
- package/src/services/DMedia-manager.spec.ts +0 -27
- package/src/services/DMedia-manager.ts +0 -179
- package/src/services/resource-provider.ts +0 -33
- package/src/services/sequence-manager.spec.ts +0 -168
- package/src/services/sequence-manager.ts +0 -133
- package/src/state/Dstate.spec.ts +0 -7
- package/src/state/Dstate.ts +0 -105
- package/src/state/boolean-property.ts +0 -69
- package/src/state/state-service.spec.ts +0 -307
- package/src/state/state-service.ts +0 -251
- package/src/state/state-testing-helpers.ts +0 -59
|
@@ -1,51 +1,39 @@
|
|
|
1
|
-
import { SchemaDto } from "
|
|
2
|
-
import {
|
|
3
|
-
import { DCommandBus } from "../commands/DCommandBus";
|
|
4
|
-
import { EventBus } from "../events/event-bus";
|
|
5
|
-
import { DPlayer } from "../player/dplayer";
|
|
6
|
-
import { AnsweredQuestion } from "../player/history-que";
|
|
7
|
-
import { DTimestamp } from "../common/DTimestamp";
|
|
8
|
-
import { DPage } from "./DPage";
|
|
1
|
+
import { SchemaDto } from "./SchemaDto";
|
|
2
|
+
import { DPlayer } from "./dplayer";
|
|
9
3
|
import { ScaleService } from "./scale";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
4
|
+
// import { DEvent } from "../events/DEvents";
|
|
5
|
+
import { Page } from "../page/Page";
|
|
6
|
+
import { TaskManager } from "../page/task-manager";
|
|
7
|
+
// import { AnsweredQuestion, PageHistory } from "./history-que";
|
|
8
|
+
import { PageResult } from "../page/page-result";
|
|
14
9
|
|
|
15
10
|
export interface EngineLogger {
|
|
16
11
|
error(message: string): void;
|
|
17
12
|
warn(message: string): void;
|
|
18
|
-
appEvent(event: DEvent): void;
|
|
19
|
-
appCommand(command: DCommand): void;
|
|
13
|
+
// appEvent(event: DEvent): void;
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
export interface SchemaResult {
|
|
23
|
-
readonly eventLog: ReadonlyArray<
|
|
24
|
-
readonly commandLog: ReadonlyArray<DCommand>;
|
|
17
|
+
readonly eventLog: ReadonlyArray<any>;
|
|
25
18
|
readonly answers: ReadonlyArray<any>;
|
|
26
19
|
}
|
|
27
20
|
export interface ISchemaEngine {
|
|
28
21
|
onComplete(handler: (result: SchemaResult) => void): void;
|
|
29
|
-
onCommandOrEvent(item: DEvent | DCommand): void;
|
|
22
|
+
// onCommandOrEvent(item: DEvent | DCommand): void;
|
|
30
23
|
setSchema(schema: SchemaDto): void;
|
|
31
24
|
onFatalError(handler: (error: { message: string }) => void): void;
|
|
32
25
|
}
|
|
33
26
|
|
|
34
27
|
export class SchemaEngine implements ISchemaEngine {
|
|
35
28
|
private readonly TAG = "[ SCHEMA_ENGINE ] :";
|
|
36
|
-
private readonly commandBus = new DCommandBus();
|
|
37
|
-
private readonly eventBus = new EventBus();
|
|
38
|
-
private readonly mediaManager: DMediaManager;
|
|
39
29
|
private readonly scale: ScaleService;
|
|
40
30
|
private readonly hostElement: HTMLDivElement;
|
|
41
|
-
private readonly
|
|
42
|
-
private readonly
|
|
43
|
-
private readonly
|
|
44
|
-
private readonly stateService: StateService;
|
|
45
|
-
private readonly globalEventToStateHandlers = new Map<string, ReadonlyArray<StateCommand>>();
|
|
31
|
+
private readonly taskManager: TaskManager;
|
|
32
|
+
private readonly uiLayer: HTMLDivElement = document.createElement("div");
|
|
33
|
+
private readonly mediaLayer: HTMLDivElement = document.createElement("div");
|
|
46
34
|
private player: DPlayer;
|
|
47
|
-
private currentPage:
|
|
48
|
-
private readonly
|
|
35
|
+
private currentPage: Page | false = false;
|
|
36
|
+
private readonly tickerRef: number | false = false;
|
|
49
37
|
|
|
50
38
|
constructor(
|
|
51
39
|
hostEl: HTMLDivElement,
|
|
@@ -53,79 +41,32 @@ export class SchemaEngine implements ISchemaEngine {
|
|
|
53
41
|
private readonly width: number,
|
|
54
42
|
private readonly schema: SchemaDto,
|
|
55
43
|
) {
|
|
44
|
+
this.tickerRef = window.setInterval(() => {
|
|
45
|
+
if (this.currentPage) {
|
|
46
|
+
this.currentPage.tick();
|
|
47
|
+
}
|
|
48
|
+
}, 100);
|
|
56
49
|
this.hostElement = hostEl;
|
|
57
|
-
this.hostElement.appendChild(this.
|
|
58
|
-
this.hostElement.appendChild(this.
|
|
59
|
-
const stateProps = this.schema.stateProps ?? [];
|
|
60
|
-
const stateQueries = this.schema.stateQueries ?? [];
|
|
61
|
-
this.stateService = new StateService(this.eventBus, this.commandBus, stateProps, stateQueries);
|
|
50
|
+
this.hostElement.appendChild(this.mediaLayer);
|
|
51
|
+
this.hostElement.appendChild(this.uiLayer);
|
|
62
52
|
this.scale = new ScaleService({
|
|
63
53
|
baseHeight: schema.baseHeight,
|
|
64
54
|
baseWidth: schema.baseWidth,
|
|
65
55
|
containerWidth: width,
|
|
66
56
|
containerHeight: height,
|
|
67
57
|
});
|
|
68
|
-
// this.commandBus.logCommands = true;
|
|
69
|
-
const globalEventHandlers = schema.stateFromEvent ?? [];
|
|
70
|
-
|
|
71
|
-
globalEventHandlers.forEach((h) => {
|
|
72
|
-
this.globalEventToStateHandlers.set(h.onEvent, h.thenExecute);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const resources = SchemaDto.getResources(this.schema);
|
|
76
|
-
this.resourceProvider = new ResourceProvider({ videos: resources.videoList, audio: resources.audioList });
|
|
77
|
-
this.mediaManager = new DMediaManager(
|
|
78
|
-
this.mediaContainer,
|
|
79
|
-
this.commandBus,
|
|
80
|
-
this.eventBus,
|
|
81
|
-
this.resourceProvider,
|
|
82
|
-
this.scale,
|
|
83
|
-
);
|
|
84
58
|
this.player = new DPlayer(this.schema);
|
|
59
|
+
this.taskManager = new TaskManager(this.mediaLayer, this.scale, (error) => {
|
|
60
|
+
console.log(error);
|
|
61
|
+
});
|
|
85
62
|
this.styleSelf();
|
|
63
|
+
this.handlePageCompleted = this.handlePageCompleted.bind(this);
|
|
86
64
|
this.nextPage();
|
|
87
|
-
this.hookUpListeners();
|
|
88
65
|
}
|
|
89
66
|
|
|
90
|
-
private
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const globalHandlers = this.globalEventToStateHandlers.get(ev.kind) ?? [];
|
|
94
|
-
globalHandlers.forEach((stateCommand) => {
|
|
95
|
-
this.commandBus.emit(stateCommand);
|
|
96
|
-
});
|
|
97
|
-
}, this.TAG + "HOOK_UP_LISTENERS");
|
|
98
|
-
const commandSubscription = this.commandBus.subscribe((command) => {
|
|
99
|
-
// switch (command.kind) {
|
|
100
|
-
//
|
|
101
|
-
// }
|
|
102
|
-
this.onCommandOrEvent(command);
|
|
103
|
-
if (command.kind === "PAGE_QUE_NEXT_PAGE_COMMAND") {
|
|
104
|
-
this.nextPage();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (command.kind === "ENGINE_LEAVE_PAGE_COMMAND") {
|
|
108
|
-
console.log(this.TAG + "SEQUENCE STARTED -- TODO EVENT FOR THIS??");
|
|
109
|
-
console.log(command);
|
|
110
|
-
const pageId = command.payload.pageId;
|
|
111
|
-
const facts = command.payload.factsCollected;
|
|
112
|
-
const timestamp = DTimestamp.now();
|
|
113
|
-
const ans: AnsweredQuestion[] = facts.map((f) => ({
|
|
114
|
-
timestamp,
|
|
115
|
-
fact: f,
|
|
116
|
-
}));
|
|
117
|
-
this.player.saveHistory({
|
|
118
|
-
answeredQuestions: ans,
|
|
119
|
-
pageId,
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
this.nextPage();
|
|
123
|
-
// const history: PageHistory = { page: {}, answeredQuestions: [] };
|
|
124
|
-
}
|
|
125
|
-
}, this.TAG);
|
|
126
|
-
|
|
127
|
-
this.subs.push(commandSubscription);
|
|
128
|
-
this.subs.push(eventSubscription);
|
|
67
|
+
private handlePageCompleted(result: PageResult) {
|
|
68
|
+
this.player.saveHistory(result);
|
|
69
|
+
this.nextPage();
|
|
129
70
|
}
|
|
130
71
|
|
|
131
72
|
private styleSelf() {
|
|
@@ -140,61 +81,48 @@ export class SchemaEngine implements ISchemaEngine {
|
|
|
140
81
|
div.style.position = "static";
|
|
141
82
|
};
|
|
142
83
|
|
|
143
|
-
makeStatic(this.
|
|
144
|
-
|
|
84
|
+
makeStatic(this.uiLayer);
|
|
85
|
+
this.uiLayer.style.zIndex = "10";
|
|
86
|
+
this.mediaLayer.style.zIndex = "8";
|
|
87
|
+
makeStatic(this.mediaLayer);
|
|
145
88
|
}
|
|
146
89
|
|
|
147
90
|
private nextPage() {
|
|
148
|
-
// TODO SHOULD THIS BE PART OF THE SCHEMA?? THIS IS CLEANUP LOGIC
|
|
149
|
-
// this.commandBus.emit({ kind: "VIDEO_PAUSE_COMMAND", target: "VIDEO", targetId: "VIDEO", payload: {} });
|
|
150
|
-
// this.commandBus.emit({ kind: "AUDIO_PAUSE_COMMAND", target: "AUDIO", targetId: "AUDIO", payload: {} });
|
|
151
|
-
// const currPageId = this.currentPage ? this.currentPage.id : "NO_PAGE";
|
|
152
|
-
// console.groupCollapsed("NEXT_PAGE FROM: " + currPageId);
|
|
153
|
-
// console.log(this.TAG + " NEXT_PAGE STARTED AT: " + currPageId);
|
|
154
|
-
this.mediaManager.clearAllMedia();
|
|
155
91
|
const nextPage = this.player.getNextPage();
|
|
156
|
-
// const state = this.stateService.getState();
|
|
157
|
-
// console.log(state);
|
|
158
|
-
// TODO CLEAN UP PAGE COMPONENTS this.page.CleanUp()
|
|
159
92
|
if (this.currentPage) {
|
|
160
93
|
this.currentPage.destroy();
|
|
161
|
-
|
|
94
|
+
|
|
95
|
+
this.uiLayer.innerHTML = "";
|
|
162
96
|
}
|
|
97
|
+
|
|
163
98
|
if (!nextPage) {
|
|
99
|
+
// console.log("NO MORE PAGES");
|
|
164
100
|
// TODO FIGURE OUT WHAQT TO DO AT END OF TEST!! Start over??
|
|
165
101
|
this.player = new DPlayer(this.schema);
|
|
166
|
-
if (this.
|
|
102
|
+
if (this.player.pageCount > 0) {
|
|
167
103
|
this.nextPage();
|
|
168
104
|
}
|
|
169
105
|
return false;
|
|
170
106
|
}
|
|
171
|
-
|
|
107
|
+
|
|
108
|
+
const newPage = new Page(nextPage, this.taskManager, this.scale, (result) => {
|
|
109
|
+
this.handlePageCompleted(result);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// console.log("APPENDING PAGE");
|
|
172
113
|
|
|
173
114
|
this.currentPage = newPage;
|
|
174
|
-
|
|
115
|
+
// this.uiContainer.innerHTML = "";
|
|
175
116
|
|
|
176
|
-
this.
|
|
177
|
-
const s1 = this.stateService.getState();
|
|
178
|
-
// console.log(s1);
|
|
179
|
-
// console.log("Next-page: " + newPage.id);
|
|
180
|
-
// console.groupEnd();
|
|
117
|
+
newPage.appendYourself(this.uiLayer);
|
|
181
118
|
return true;
|
|
182
119
|
}
|
|
183
120
|
|
|
184
121
|
destroy() {
|
|
185
122
|
if (this.currentPage) {
|
|
186
123
|
this.currentPage.destroy();
|
|
187
|
-
this.
|
|
124
|
+
this.uiLayer.innerHTML = "";
|
|
188
125
|
}
|
|
189
|
-
this.mediaManager.destroy();
|
|
190
|
-
this.stateService.destroy();
|
|
191
|
-
this.subs.forEach((sub) => {
|
|
192
|
-
sub();
|
|
193
|
-
});
|
|
194
|
-
const evStats = this.eventBus.getStats();
|
|
195
|
-
const cmdStats = this.commandBus.getStats();
|
|
196
|
-
console.assert(evStats.subscribersCount === 0, this.TAG + " Eventbus should have no subscribers ", evStats);
|
|
197
|
-
console.assert(cmdStats.subscribersCount === 0, this.TAG + "Commandbus should have no subscribers", cmdStats);
|
|
198
126
|
}
|
|
199
127
|
onComplete(handler: (result: SchemaResult) => void) {
|
|
200
128
|
console.log(handler);
|
|
@@ -204,7 +132,7 @@ export class SchemaEngine implements ISchemaEngine {
|
|
|
204
132
|
console.log(handler);
|
|
205
133
|
}
|
|
206
134
|
|
|
207
|
-
onCommandOrEvent(_event_or_command:
|
|
135
|
+
onCommandOrEvent(_event_or_command: any) {}
|
|
208
136
|
|
|
209
137
|
setSchema(schema: SchemaDto): void {
|
|
210
138
|
console.log(schema);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { DPlayer, DPlayerData } from "./dplayer";
|
|
2
|
-
import {
|
|
2
|
+
import { PageSequenceDto } from "./SchemaDto";
|
|
3
3
|
import { Rule } from "../rules/rule";
|
|
4
|
-
import { PageHistory } from "./history-que";
|
|
4
|
+
// import { PageHistory } from "./history-que";
|
|
5
5
|
import { DTimestamp } from "../common/DTimestamp";
|
|
6
|
-
import { PageQueCommand } from "
|
|
7
|
-
import {
|
|
6
|
+
import { PageQueCommand } from "./DCommand";
|
|
7
|
+
import { PageDto } from "../page/Page";
|
|
8
|
+
import { PageResult } from "../page/page-result";
|
|
8
9
|
|
|
9
10
|
const page = (id: number): PageDto => {
|
|
10
|
-
return
|
|
11
|
+
return PageDto.createDummy(id);
|
|
12
|
+
// return { id: PageID.create(), elements: [] };
|
|
11
13
|
};
|
|
12
14
|
const p1 = page(1);
|
|
13
15
|
const p2 = page(2);
|
|
@@ -31,7 +33,7 @@ const data = (
|
|
|
31
33
|
pages: PageDto[],
|
|
32
34
|
pageSequences: PageSequenceDto[] = [],
|
|
33
35
|
rules: Rule<PageQueCommand, never>[] = [],
|
|
34
|
-
): DPlayerData => ({ pages, pageSequences, rules });
|
|
36
|
+
): DPlayerData => ({ pages: pages, pageSequences, rules });
|
|
35
37
|
// const seq = (pages: PageDto[], rules: Rule[]) => {};
|
|
36
38
|
beforeEach(() => {
|
|
37
39
|
// data = { pages: [], rules: [], pageSequences: [] };
|
|
@@ -85,24 +87,25 @@ describe("DPlayer", () => {
|
|
|
85
87
|
|
|
86
88
|
it("Save history", () => {
|
|
87
89
|
const player = new DPlayer(data(all));
|
|
90
|
+
|
|
88
91
|
const curr = player.getNextPage() as PageDto;
|
|
89
92
|
|
|
90
|
-
const
|
|
93
|
+
const result: PageResult = {
|
|
91
94
|
pageId: curr.id,
|
|
92
|
-
|
|
95
|
+
pageEntered: DTimestamp.now(),
|
|
96
|
+
pageExited: DTimestamp.now(),
|
|
97
|
+
pageTime: DTimestamp.diff(DTimestamp.now(), DTimestamp.now()),
|
|
98
|
+
collectedFacts: [
|
|
93
99
|
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
label: "litt",
|
|
100
|
-
value: 2,
|
|
101
|
-
},
|
|
100
|
+
referenceId: "as",
|
|
101
|
+
referenceLabel: "as-label",
|
|
102
|
+
kind: "numeric-fact",
|
|
103
|
+
label: "litt",
|
|
104
|
+
value: 2,
|
|
102
105
|
},
|
|
103
106
|
],
|
|
104
107
|
};
|
|
105
|
-
player.saveHistory(
|
|
108
|
+
player.saveHistory(result);
|
|
106
109
|
expect(player.getNextPage()).toBe(p2);
|
|
107
110
|
expect(player.getResults().length).toBe(1);
|
|
108
111
|
});
|
|
@@ -1,31 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HistoryQue } from "./history-que";
|
|
2
2
|
import { RuleEngine } from "../rules/rule-engine";
|
|
3
3
|
import { NextQue } from "./next-que";
|
|
4
|
-
import {
|
|
5
|
-
import { NavigationCommand, PageQueCommand } from "
|
|
4
|
+
import { SchemaDto } from "./SchemaDto";
|
|
5
|
+
import { NavigationCommand, PageQueCommand } from "./DCommand";
|
|
6
6
|
import { DUtil } from "../utils/DUtil";
|
|
7
|
+
import { PageDto } from "../page/Page";
|
|
8
|
+
import { PageResult } from "../page/page-result";
|
|
9
|
+
import { Fact } from "../rules/fact";
|
|
7
10
|
|
|
8
11
|
export type DPlayerData = Pick<SchemaDto, "pages" | "pageSequences" | "rules">;
|
|
9
12
|
export class DPlayer {
|
|
10
13
|
private history = new HistoryQue();
|
|
11
|
-
private ruleEngine = new RuleEngine<PageQueCommand,
|
|
14
|
+
private ruleEngine = new RuleEngine<PageQueCommand, never>();
|
|
12
15
|
private nextQue = new NextQue();
|
|
13
16
|
private data: DPlayerData;
|
|
14
17
|
|
|
15
18
|
constructor(data: DPlayerData) {
|
|
16
19
|
this.data = data;
|
|
17
|
-
|
|
20
|
+
const pages = data.pages ?? [];
|
|
21
|
+
this.nextQue.resetQue(pages);
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
saveHistory(pageHistory:
|
|
21
|
-
console.log("SAVE HISTORY", pageHistory);
|
|
24
|
+
saveHistory(pageHistory: PageResult) {
|
|
25
|
+
// console.log("SAVE HISTORY", pageHistory);
|
|
22
26
|
this.history.addToHistory(pageHistory);
|
|
23
27
|
const facts = this.history.getFacts();
|
|
24
28
|
const result = this.ruleEngine.solveAll(this.data.rules, facts);
|
|
25
29
|
const matchingRules = result.matching;
|
|
26
30
|
const actions = matchingRules.map((r) => r.actionList).flat(1);
|
|
27
31
|
actions.forEach((a) => {
|
|
28
|
-
console.log(a.payload);
|
|
32
|
+
// console.log(a.payload);
|
|
29
33
|
switch (a.kind) {
|
|
30
34
|
case "PAGE_QUE_JUMP_TO_PAGE_COMMAND":
|
|
31
35
|
this.nextQue.jumpToPageById(a.payload.pageId);
|
|
@@ -41,11 +45,11 @@ export class DPlayer {
|
|
|
41
45
|
const check: never = a;
|
|
42
46
|
}
|
|
43
47
|
});
|
|
44
|
-
console.log(actions);
|
|
48
|
+
// console.log(actions);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
getResults():
|
|
48
|
-
return this.history.
|
|
51
|
+
getResults(): Fact[] {
|
|
52
|
+
return this.history.getFacts();
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
private goToPageById(pageId: string) {
|
|
@@ -54,9 +58,6 @@ export class DPlayer {
|
|
|
54
58
|
|
|
55
59
|
handleNavigationCommand(command: NavigationCommand) {
|
|
56
60
|
switch (command.kind) {
|
|
57
|
-
case "PAGE_QUE_NEXT_PAGE_COMMAND":
|
|
58
|
-
// NO NEED TO DO ANYTHING
|
|
59
|
-
break;
|
|
60
61
|
case "PAGE_QUE_GO_TO_PAGE_COMMAND":
|
|
61
62
|
this.goToPageById(command.payload.pageId);
|
|
62
63
|
break;
|
|
@@ -69,9 +70,21 @@ export class DPlayer {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
// getNextPage():
|
|
74
|
+
// | { kind: "first-page"; readonly page: PageDto }
|
|
75
|
+
// | { kind: "next-page"; readonly page: PageDto }
|
|
76
|
+
// | { kind: "no-more-pages" } {
|
|
77
|
+
// const next = this.nextQue.pop();
|
|
78
|
+
// const a = this.nextQue.
|
|
79
|
+
// if (next) {
|
|
80
|
+
// return { kind: "next-page", page: next };
|
|
81
|
+
// }
|
|
82
|
+
// return { kind: "no-more-pages" };
|
|
83
|
+
// }
|
|
84
|
+
|
|
72
85
|
getNextPage(): PageDto | false {
|
|
73
|
-
|
|
74
|
-
return
|
|
86
|
+
const next = this.nextQue.pop();
|
|
87
|
+
return next ?? false;
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
private insertSequenceById(id: string) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { HistoryQue } from "./history-que";
|
|
2
|
+
import { DTimestamp } from "../common/DTimestamp";
|
|
3
|
+
import { PageID } from "../utils/ID";
|
|
4
|
+
import { PageDto } from "../page/Page";
|
|
5
|
+
import { PageResult } from "../page/page-result";
|
|
6
|
+
|
|
7
|
+
const p = (id: number): PageDto => {
|
|
8
|
+
return { id: PageID.create(), components: [], initialTasks: [], staticElements: [], background: "", tags: [] };
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const pageResult = (id: number, value: number): PageResult => {
|
|
12
|
+
const pageEntered = DTimestamp.now();
|
|
13
|
+
const pageExited = DTimestamp.addMills(pageEntered, 1000);
|
|
14
|
+
const pageTime = DTimestamp.diff(pageEntered, pageExited);
|
|
15
|
+
|
|
16
|
+
const result: PageResult = {
|
|
17
|
+
pageId: "_dummyId" + id,
|
|
18
|
+
pageEntered,
|
|
19
|
+
pageExited,
|
|
20
|
+
pageTime,
|
|
21
|
+
collectedFacts: [
|
|
22
|
+
{
|
|
23
|
+
referenceId: "" + id,
|
|
24
|
+
referenceLabel: "label-for-" + id,
|
|
25
|
+
value,
|
|
26
|
+
label: "value-label " + value,
|
|
27
|
+
kind: "numeric-fact",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
// const h = (page: PageDto, answeredQuestions: AnsweredQuestion[]): PageResult => ({
|
|
34
|
+
// pageId: page.id,
|
|
35
|
+
// answeredQuestions,
|
|
36
|
+
// });
|
|
37
|
+
const p1 = p(1);
|
|
38
|
+
const p2 = p(2);
|
|
39
|
+
const p3 = p(3);
|
|
40
|
+
const p4 = p(4);
|
|
41
|
+
const p5 = p(5);
|
|
42
|
+
const p6 = p(6);
|
|
43
|
+
const all = [p1, p2, p3, p4, p5, p6];
|
|
44
|
+
|
|
45
|
+
let history = new HistoryQue();
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
history = new HistoryQue();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("HistoryQue", () => {
|
|
51
|
+
it("should create an instance", () => {
|
|
52
|
+
expect(history).toBeTruthy();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("Can add history, and get facts back", () => {
|
|
56
|
+
history.addToHistory(pageResult(1, 2));
|
|
57
|
+
expect(history.getFacts().length).toBe(1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Fact } from "../rules/fact";
|
|
2
|
+
import { DTimestamp } from "../common/DTimestamp";
|
|
3
|
+
import { PageResult } from "../page/page-result";
|
|
4
|
+
|
|
5
|
+
// export interface AnsweredQuestion {
|
|
6
|
+
// readonly timestamp: DTimestamp;
|
|
7
|
+
// readonly fact: Fact;
|
|
8
|
+
// }
|
|
9
|
+
|
|
10
|
+
// export namespace AnsweredQuestion {
|
|
11
|
+
// export const eq = (a: AnsweredQuestion, b: AnsweredQuestion): boolean => {
|
|
12
|
+
// return a.fact === b.fact;
|
|
13
|
+
// };
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
// export interface PageHistory {
|
|
17
|
+
// readonly pageId: string;
|
|
18
|
+
// readonly answeredQuestions: AnsweredQuestion[];
|
|
19
|
+
// }
|
|
20
|
+
|
|
21
|
+
export class HistoryQue {
|
|
22
|
+
private history: PageResult[] = [];
|
|
23
|
+
|
|
24
|
+
getFacts(): Array<Fact> {
|
|
25
|
+
const answers = this.history.map((h) => h.collectedFacts).flat(1);
|
|
26
|
+
// const facts = answers.map((a) => a.fact);
|
|
27
|
+
// TODO FIND LATEST FACT (answer) if have multiple.
|
|
28
|
+
return answers;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// get(): Array<AnsweredQuestion> {
|
|
32
|
+
// const answers = this.history.map((h) => h.answeredQuestions).flat(1);
|
|
33
|
+
// return answers;
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
addToHistory(result: PageResult) {
|
|
37
|
+
this.history.push(result);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
import { NextQue } from "./next-que";
|
|
2
|
-
import { PageDto } from "../dto/SchemaDto";
|
|
3
2
|
import { PageID } from "../utils/ID";
|
|
3
|
+
import { PageDto } from "../page/Page";
|
|
4
4
|
|
|
5
5
|
const tag1 = "tag1";
|
|
6
6
|
const tag2 = "tag2";
|
|
7
7
|
const tag3 = "tag3";
|
|
8
8
|
|
|
9
9
|
let que = new NextQue();
|
|
10
|
-
const createPage = () => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
const createPage = (tags: string[]): PageDto => {
|
|
11
|
+
const dto: PageDto = {
|
|
12
|
+
id: PageID.create(),
|
|
13
|
+
staticElements: [],
|
|
14
|
+
background: "white",
|
|
15
|
+
components: [],
|
|
16
|
+
initialTasks: [],
|
|
17
|
+
tags,
|
|
18
|
+
};
|
|
19
|
+
return dto;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const p1 = createPage([tag1]);
|
|
23
|
+
const p2 = createPage([]);
|
|
24
|
+
const p3 = createPage([tag2]);
|
|
25
|
+
const p4 = createPage([]);
|
|
26
|
+
const p5 = createPage([tag3, tag2]);
|
|
27
|
+
const p6 = createPage([tag3]);
|
|
17
28
|
const all = [p1, p2, p3, p4, p5, p6];
|
|
18
29
|
|
|
19
30
|
beforeEach(() => {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { PageDto } from "../page/Page";
|
|
2
|
+
|
|
3
|
+
export class NextQue {
|
|
4
|
+
private originalOrder: ReadonlyArray<string> = [];
|
|
5
|
+
private allPages: PageDto[] = [];
|
|
6
|
+
private excludedTags = new Set<string>();
|
|
7
|
+
private excludedByPageId = new Set<string>();
|
|
8
|
+
private remaining: PageDto[] = [];
|
|
9
|
+
constructor(pages: PageDto[] = []) {
|
|
10
|
+
this.resetQue(pages);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Will reset que with the new pages.
|
|
15
|
+
* @param pages
|
|
16
|
+
*/
|
|
17
|
+
resetQue(pages: PageDto[]) {
|
|
18
|
+
this.allPages = [...pages];
|
|
19
|
+
this.remaining = [...pages];
|
|
20
|
+
this.excludedTags = new Set();
|
|
21
|
+
this.excludedByPageId = new Set();
|
|
22
|
+
this.originalOrder = this.allPages.map((p) => p.id);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pop(): PageDto | false {
|
|
26
|
+
const next = this.remaining.shift();
|
|
27
|
+
// TODO CLONE??
|
|
28
|
+
return next ?? false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
peek(): PageDto | false {
|
|
32
|
+
const next = this.remaining[0];
|
|
33
|
+
return next ?? false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
jumpToPageById(pageId: string): boolean {
|
|
37
|
+
const index = this.remaining.findIndex((p) => p.id === pageId);
|
|
38
|
+
if (index < 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
this.remaining = this.remaining.slice(index);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
removeByTag(tag: string | string[]) {
|
|
46
|
+
if (Array.isArray(tag)) {
|
|
47
|
+
tag.forEach((tag) => {
|
|
48
|
+
this.excludedTags.add(tag);
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
this.excludedTags.add(tag);
|
|
52
|
+
}
|
|
53
|
+
this.filterRemaining();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Will not be included
|
|
58
|
+
* @param pages
|
|
59
|
+
*/
|
|
60
|
+
insertAsNextByForce(pages: PageDto[]) {
|
|
61
|
+
this.remaining.unshift(...pages);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
removeByPageId(pageId: string | string[]) {
|
|
65
|
+
if (Array.isArray(pageId)) {
|
|
66
|
+
pageId.forEach((id) => {
|
|
67
|
+
this.excludedByPageId.add(id);
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
this.excludedByPageId.add(pageId);
|
|
71
|
+
}
|
|
72
|
+
this.filterRemaining();
|
|
73
|
+
// this.excludedByPageId.add(pageId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private filterRemaining() {
|
|
77
|
+
this.remaining = this.remaining.filter((p) => {
|
|
78
|
+
const tags = p.tags ?? [];
|
|
79
|
+
const isIncluededByTag = !tags.some((tag) => this.excludedTags.has(tag));
|
|
80
|
+
const isIncludedByPageId = !this.excludedByPageId.has(p.id);
|
|
81
|
+
return isIncludedByPageId && isIncluededByTag;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
get isEmpty(): boolean {
|
|
85
|
+
return this.remaining.length === 0;
|
|
86
|
+
}
|
|
87
|
+
get size(): number {
|
|
88
|
+
return this.remaining.length;
|
|
89
|
+
}
|
|
90
|
+
get pageCount(): number {
|
|
91
|
+
return this.originalOrder.length;
|
|
92
|
+
}
|
|
93
|
+
}
|