@media-quest/engine 0.0.21 → 0.0.23

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 (51) hide show
  1. package/package.json +1 -1
  2. package/src/Delement/DElement.dto.ts +5 -5
  3. package/src/Delement/DElement.ts +88 -88
  4. package/src/Delement/DImg.ts +39 -39
  5. package/src/Delement/DStyle-utils.ts +616 -616
  6. package/src/Delement/DStyle.ts +165 -165
  7. package/src/Delement/DText.ts +13 -13
  8. package/src/Delement/Ddiv.ts +25 -25
  9. package/src/Delement/button-click-action.ts +35 -35
  10. package/src/Delement/css.spec.ts +36 -36
  11. package/src/Delement/css.ts +46 -46
  12. package/src/Delement/element-factory.ts +40 -40
  13. package/src/common/DMaybe.ts +46 -46
  14. package/src/common/DTimestamp.ts +20 -20
  15. package/src/common/DTmestamp.spec.ts +11 -11
  16. package/src/common/result.ts +41 -41
  17. package/src/engine/SchemaDto.ts +24 -24
  18. package/src/engine/SchemaEngine.ts +150 -150
  19. package/src/engine/SchemaResult.ts +10 -10
  20. package/src/engine/dplayer.spec.ts +91 -91
  21. package/src/engine/dplayer.ts +104 -104
  22. package/src/engine/history-que.spec.ts +67 -67
  23. package/src/engine/history-que.ts +17 -17
  24. package/src/engine/next-que.spec.ts +121 -121
  25. package/src/engine/next-que.ts +101 -101
  26. package/src/engine/page-que-ruleengine-action.ts +6 -6
  27. package/src/engine/scale.spec.ts +38 -38
  28. package/src/engine/scale.ts +70 -70
  29. package/src/events/mq-events.ts +63 -63
  30. package/src/page/Page.ts +182 -182
  31. package/src/page/media-player.ts +117 -117
  32. package/src/page/page-component.ts +113 -113
  33. package/src/page/page-result.ts +11 -11
  34. package/src/page/task-manager.ts +240 -240
  35. package/src/page/task-state.ts +55 -55
  36. package/src/page/task.ts +90 -90
  37. package/src/public-api.ts +26 -26
  38. package/src/rules/__test__/complex-condition.spec.ts +15 -15
  39. package/src/rules/__test__/conditon.spec.ts +124 -124
  40. package/src/rules/__test__/numeric-condition.spec.ts +84 -84
  41. package/src/rules/__test__/rule-engine.spec.ts +348 -348
  42. package/src/rules/__test__/rule-evaluation.spec.ts +140 -140
  43. package/src/rules/__test__/string-condition.spec.ts +41 -41
  44. package/src/rules/condition.ts +191 -191
  45. package/src/rules/fact.ts +18 -18
  46. package/src/rules/rule-engine.ts +45 -45
  47. package/src/rules/rule.ts +40 -40
  48. package/src/utils/DUtil.ts +116 -116
  49. package/src/utils/ID.spec.ts +39 -39
  50. package/src/utils/ID.ts +73 -73
  51. package/tsconfig.json +19 -19
@@ -1,40 +1,40 @@
1
- import { DElement } from "./DElement";
2
- import { DDiv, DDivDto } from "./Ddiv";
3
- import { DImg } from "./DImg";
4
- import { DText } from "./DText";
5
- import { ScaleService } from "../engine/scale";
6
- import { DElementDto } from "./DElement.dto";
7
-
8
- export const createDElement = (dto: DElementDto, scale: ScaleService): DElement<any> => {
9
- switch (dto._tag) {
10
- case "div":
11
- const childEls = createChildrenForDiv(dto, scale);
12
- const newDiv = new DDiv(dto, scale, childEls);
13
- return newDiv;
14
- case "img":
15
- return new DImg(dto, scale);
16
- case "p":
17
- return new DText(dto, scale);
18
- default:
19
- const check: never = dto;
20
- throw new Error("Unknown dto given to the createDElement function.");
21
- // TODO LOGGING or create any HTML-ELEMENT??
22
- }
23
- };
24
-
25
- const createChildrenForDiv = (dto: DDivDto, scale: ScaleService): DDiv["children"] => {
26
- const childDto = dto.children;
27
- const childEls: Array<DImg | DText> = [];
28
- // console.log(childElements);
29
- childDto.forEach((dto) => {
30
- if (dto._tag === "p") {
31
- const newText = new DText(dto, scale);
32
- childEls.push(newText);
33
- }
34
- if (dto._tag === "img") {
35
- const newImage = new DImg(dto, scale);
36
- childEls.push(newImage);
37
- }
38
- });
39
- return childEls;
40
- };
1
+ import { DElement } from "./DElement";
2
+ import { DDiv, DDivDto } from "./Ddiv";
3
+ import { DImg } from "./DImg";
4
+ import { DText } from "./DText";
5
+ import { ScaleService } from "../engine/scale";
6
+ import { DElementDto } from "./DElement.dto";
7
+
8
+ export const createDElement = (dto: DElementDto, scale: ScaleService): DElement<any> => {
9
+ switch (dto._tag) {
10
+ case "div":
11
+ const childEls = createChildrenForDiv(dto, scale);
12
+ const newDiv = new DDiv(dto, scale, childEls);
13
+ return newDiv;
14
+ case "img":
15
+ return new DImg(dto, scale);
16
+ case "p":
17
+ return new DText(dto, scale);
18
+ default:
19
+ const check: never = dto;
20
+ throw new Error("Unknown dto given to the createDElement function.");
21
+ // TODO LOGGING or create any HTML-ELEMENT??
22
+ }
23
+ };
24
+
25
+ const createChildrenForDiv = (dto: DDivDto, scale: ScaleService): DDiv["children"] => {
26
+ const childDto = dto.children;
27
+ const childEls: Array<DImg | DText> = [];
28
+ // console.log(childElements);
29
+ childDto.forEach((dto) => {
30
+ if (dto._tag === "p") {
31
+ const newText = new DText(dto, scale);
32
+ childEls.push(newText);
33
+ }
34
+ if (dto._tag === "img") {
35
+ const newImage = new DImg(dto, scale);
36
+ childEls.push(newImage);
37
+ }
38
+ });
39
+ return childEls;
40
+ };
@@ -1,46 +1,46 @@
1
- export type Maybe<T> = Just<T> | None<T>;
2
-
3
- class Just<T> {
4
- isJust(): this is Just<T> {
5
- return true;
6
- }
7
- constructor(readonly value: T) {}
8
- isNone(): this is None<T> {
9
- return false;
10
- }
11
-
12
- map<A>(f: (t: T) => A) {
13
- const newValue = f(this.value);
14
- return new Just<A>(newValue);
15
- }
16
- }
17
-
18
- class None<T> {
19
- readonly kind: "none" = "none";
20
- isJust(): this is Just<T> {
21
- return false;
22
- }
23
- isNone(): this is None<T> {
24
- return false;
25
- }
26
-
27
- // @ts-ignore
28
- map<A>(f: (t: T) => A) {
29
- return new None<A>();
30
- }
31
- }
32
-
33
- export namespace Maybe {
34
- export const none = () => new None();
35
- export const just = <T>(value: T) => new Just(value);
36
-
37
- export const isNone = <T>(value?: Maybe<T>): value is None<T> =>
38
- value instanceof None;
39
- export const isJust = <T>(value?: Maybe<T>): value is Just<T> =>
40
- value instanceof Just;
41
-
42
- export const is = <T>(value: unknown): value is Maybe<T> => {
43
- const casted = value as any as Maybe<T>;
44
- return isNone(casted) || isJust(casted);
45
- };
46
- }
1
+ export type Maybe<T> = Just<T> | None<T>;
2
+
3
+ class Just<T> {
4
+ isJust(): this is Just<T> {
5
+ return true;
6
+ }
7
+ constructor(readonly value: T) {}
8
+ isNone(): this is None<T> {
9
+ return false;
10
+ }
11
+
12
+ map<A>(f: (t: T) => A) {
13
+ const newValue = f(this.value);
14
+ return new Just<A>(newValue);
15
+ }
16
+ }
17
+
18
+ class None<T> {
19
+ readonly kind: "none" = "none";
20
+ isJust(): this is Just<T> {
21
+ return false;
22
+ }
23
+ isNone(): this is None<T> {
24
+ return false;
25
+ }
26
+
27
+ // @ts-ignore
28
+ map<A>(f: (t: T) => A) {
29
+ return new None<A>();
30
+ }
31
+ }
32
+
33
+ export namespace Maybe {
34
+ export const none = () => new None();
35
+ export const just = <T>(value: T) => new Just(value);
36
+
37
+ export const isNone = <T>(value?: Maybe<T>): value is None<T> =>
38
+ value instanceof None;
39
+ export const isJust = <T>(value?: Maybe<T>): value is Just<T> =>
40
+ value instanceof Just;
41
+
42
+ export const is = <T>(value: unknown): value is Maybe<T> => {
43
+ const casted = value as any as Maybe<T>;
44
+ return isNone(casted) || isJust(casted);
45
+ };
46
+ }
@@ -1,20 +1,20 @@
1
- export type DTimestamp = number & { __timestamp__: true };
2
- export namespace DTimestamp {
3
- export const now = () => Date.now() as DTimestamp;
4
- export type Diff = number & { __diff__: true };
5
-
6
- export const addMills = (t: DTimestamp, ms: number): DTimestamp => {
7
- const res = t + Math.abs(ms);
8
- return res as DTimestamp;
9
- };
10
-
11
- export const diff = (t1: DTimestamp, t2: DTimestamp): Diff => {
12
- const t1Abs = Math.abs(t1);
13
- const t2Abs = Math.abs(t2);
14
- return Math.abs(t1Abs - t2Abs) as Diff;
15
- };
16
-
17
- export const diffNow = (t: DTimestamp): Diff => {
18
- return diff(t, now());
19
- };
20
- }
1
+ export type DTimestamp = number & { __timestamp__: true };
2
+ export namespace DTimestamp {
3
+ export const now = () => Date.now() as DTimestamp;
4
+ export type Diff = number & { __diff__: true };
5
+
6
+ export const addMills = (t: DTimestamp, ms: number): DTimestamp => {
7
+ const res = t + Math.abs(ms);
8
+ return res as DTimestamp;
9
+ };
10
+
11
+ export const diff = (t1: DTimestamp, t2: DTimestamp): Diff => {
12
+ const t1Abs = Math.abs(t1);
13
+ const t2Abs = Math.abs(t2);
14
+ return Math.abs(t1Abs - t2Abs) as Diff;
15
+ };
16
+
17
+ export const diffNow = (t: DTimestamp): Diff => {
18
+ return diff(t, now());
19
+ };
20
+ }
@@ -1,11 +1,11 @@
1
- import { DTimestamp } from "./DTimestamp";
2
-
3
- describe("DTimestamp works", () => {
4
- test("Can add milliseconds to timestamp", () => {
5
- const t0 = DTimestamp.now();
6
- const plus1000 = DTimestamp.addMills(t0, 1000);
7
- const diff = DTimestamp.diff(t0, plus1000);
8
- // const pageDto: PageDto = {id}
9
- expect(diff).toBe(1000);
10
- });
11
- });
1
+ import { DTimestamp } from "./DTimestamp";
2
+
3
+ describe("DTimestamp works", () => {
4
+ test("Can add milliseconds to timestamp", () => {
5
+ const t0 = DTimestamp.now();
6
+ const plus1000 = DTimestamp.addMills(t0, 1000);
7
+ const diff = DTimestamp.diff(t0, plus1000);
8
+ // const pageDto: PageDto = {id}
9
+ expect(diff).toBe(1000);
10
+ });
11
+ });
@@ -1,41 +1,41 @@
1
- export class Ok<T> implements IResult<T> {
2
- constructor(readonly value: T) {}
3
- isOk(): this is Ok<T> {
4
- return true;
5
- }
6
- isFailure(): this is Failure<T> {
7
- return false;
8
- }
9
-
10
- map<A>(f: (t: T) => A): IResult<A> {
11
- const value = f(this.value);
12
- return new Ok<A>(value);
13
- }
14
- }
15
-
16
- export class Failure<T> implements IResult<T> {
17
- constructor(readonly message: string) {}
18
- isFailure(): this is Failure<T> {
19
- return true;
20
- }
21
-
22
- isOk(): this is Ok<T> {
23
- return false;
24
- }
25
-
26
- map<A>(_f: (t: T) => A): IResult<A> {
27
- return new Failure<A>(this.message);
28
- }
29
- }
30
-
31
- interface IResult<T> {
32
- isOk(): this is Ok<T>;
33
- isFailure(): this is Failure<T>;
34
- map<A>(f: (t: T) => A): IResult<A>;
35
- }
36
-
37
- export type Result<T> = Failure<T> | Ok<T>;
38
- export namespace Result {
39
- export const ok = <T>(value: T) => new Ok<T>(value);
40
- export const failure = <T>(message: string) => new Failure<T>(message);
41
- }
1
+ export class Ok<T> implements IResult<T> {
2
+ constructor(readonly value: T) {}
3
+ isOk(): this is Ok<T> {
4
+ return true;
5
+ }
6
+ isFailure(): this is Failure<T> {
7
+ return false;
8
+ }
9
+
10
+ map<A>(f: (t: T) => A): IResult<A> {
11
+ const value = f(this.value);
12
+ return new Ok<A>(value);
13
+ }
14
+ }
15
+
16
+ export class Failure<T> implements IResult<T> {
17
+ constructor(readonly message: string) {}
18
+ isFailure(): this is Failure<T> {
19
+ return true;
20
+ }
21
+
22
+ isOk(): this is Ok<T> {
23
+ return false;
24
+ }
25
+
26
+ map<A>(_f: (t: T) => A): IResult<A> {
27
+ return new Failure<A>(this.message);
28
+ }
29
+ }
30
+
31
+ interface IResult<T> {
32
+ isOk(): this is Ok<T>;
33
+ isFailure(): this is Failure<T>;
34
+ map<A>(f: (t: T) => A): IResult<A>;
35
+ }
36
+
37
+ export type Result<T> = Failure<T> | Ok<T>;
38
+ export namespace Result {
39
+ export const ok = <T>(value: T) => new Ok<T>(value);
40
+ export const failure = <T>(message: string) => new Failure<T>(message);
41
+ }
@@ -1,24 +1,24 @@
1
- import { Rule } from "../rules/rule";
2
- import { Fact } from "../rules/fact";
3
- import { RuleActionPageQue } from "./page-que-ruleengine-action";
4
- import { SchemaID } from "../utils/ID";
5
- import { PageDto } from "../page/Page";
6
-
7
- export type PageQueRules = Rule<RuleActionPageQue, never>;
8
-
9
- export interface PageSequenceDto {
10
- readonly id: string;
11
- readonly rules: Array<PageQueRules>;
12
- readonly pages: Array<PageDto>;
13
- }
14
-
15
- export interface SchemaDto {
16
- readonly id: SchemaID;
17
- readonly baseHeight: number;
18
- readonly baseWidth: number;
19
- readonly backgroundColor: string;
20
- readonly pages: Array<PageDto>;
21
- readonly rules: Array<PageQueRules>;
22
- readonly pageSequences?: Array<PageSequenceDto>;
23
- readonly predefinedFacts?: ReadonlyArray<Fact>;
24
- }
1
+ import { Rule } from "../rules/rule";
2
+ import { Fact } from "../rules/fact";
3
+ import { RuleActionPageQue } from "./page-que-ruleengine-action";
4
+ import { SchemaID } from "../utils/ID";
5
+ import { PageDto } from "../page/Page";
6
+
7
+ export type PageQueRules = Rule<RuleActionPageQue, never>;
8
+
9
+ export interface PageSequenceDto {
10
+ readonly id: string;
11
+ readonly rules: Array<PageQueRules>;
12
+ readonly pages: Array<PageDto>;
13
+ }
14
+
15
+ export interface SchemaDto {
16
+ readonly id: SchemaID;
17
+ readonly baseHeight: number;
18
+ readonly baseWidth: number;
19
+ readonly backgroundColor: string;
20
+ readonly pages: Array<PageDto>;
21
+ readonly rules: Array<PageQueRules>;
22
+ readonly pageSequences?: Array<PageSequenceDto>;
23
+ readonly predefinedFacts?: ReadonlyArray<Fact>;
24
+ }
@@ -1,150 +1,150 @@
1
- import { SchemaDto } from "./SchemaDto";
2
- import { DPlayer } from "./dplayer";
3
- import { ScaleService } from "./scale";
4
- import { Page } from "../page/Page";
5
- import { TaskManager } from "../page/task-manager";
6
- import { PageResult } from "../page/page-result";
7
- import { SchemaResult } from "./SchemaResult";
8
- export interface EngineLogger {
9
- info(message: string): void;
10
- error(message: string): void;
11
- warn(message: string): void;
12
- }
13
-
14
- const voidLogger: EngineLogger = {
15
- info: (message: string) => {},
16
- error: (message: string) => {},
17
- warn: (message: string) => {},
18
- };
19
-
20
- export interface ISchemaEngine {
21
- onProgress(handler: (result: SchemaResult) => void): void;
22
- onFatalError(handler: (error: { message: string }) => void): void;
23
- setLogger(logger: EngineLogger): void;
24
- }
25
-
26
- export class SchemaEngine implements ISchemaEngine {
27
- private readonly TAG = "[ SCHEMA_ENGINE ] :";
28
- private readonly scale: ScaleService;
29
- private readonly hostElement: HTMLDivElement;
30
- private readonly taskManager: TaskManager;
31
- private logger: EngineLogger = voidLogger;
32
- private readonly uiLayer: HTMLDivElement = document.createElement("div");
33
- private readonly mediaLayer: HTMLDivElement = document.createElement("div");
34
- private player: DPlayer;
35
- private currentPage: Page | false = false;
36
- private readonly tickerRef: number | false = false;
37
- constructor(
38
- hostEl: HTMLDivElement,
39
- private readonly height: number,
40
- private readonly width: number,
41
- private readonly schema: SchemaDto,
42
- ) {
43
- this.tickerRef = window.setInterval(() => {
44
- if (this.currentPage) {
45
- this.currentPage.tick();
46
- }
47
- }, 100);
48
- this.hostElement = hostEl;
49
- this.hostElement.appendChild(this.mediaLayer);
50
- this.hostElement.appendChild(this.uiLayer);
51
- this.scale = new ScaleService({
52
- baseHeight: schema.baseHeight,
53
- baseWidth: schema.baseWidth,
54
- containerWidth: width,
55
- containerHeight: height,
56
- });
57
- this.logger.info(this.TAG + "Scale: " + JSON.stringify(this.scale));
58
- this.player = new DPlayer(this.schema);
59
- this.taskManager = new TaskManager(this.mediaLayer, this.scale, (error) => {
60
- console.log(error);
61
- });
62
-
63
- this.styleSelf();
64
- this.handlePageCompleted = this.handlePageCompleted.bind(this);
65
- this.nextPage();
66
- }
67
-
68
- private handlePageCompleted(result: PageResult) {
69
- // 1 Save data from last page
70
- this.player.saveHistory(result);
71
-
72
- // 2 Emit progress
73
- const currentResults = this.player.getResults();
74
- const a: SchemaResult = {
75
- schemaId: this.schema.id,
76
- pagesLeft: currentResults.pagesLeft,
77
- predefinedFacts: currentResults.predefinedFacts,
78
- eventLog: currentResults.eventLog,
79
- answers: currentResults.answerFacts,
80
- };
81
- if (this._onProgress) {
82
- this._onProgress(a);
83
- }
84
-
85
- // 3. Next page
86
- this.nextPage();
87
- }
88
-
89
- private styleSelf() {
90
- this.hostElement.style.height = this.scale.pageHeight + "px";
91
- this.hostElement.style.width = this.scale.pageWidth + "px";
92
- this.hostElement.style.backgroundColor = this.schema.backgroundColor ?? "white";
93
- this.hostElement.style.position = "relative";
94
- // this.hostElement.style.overflow = "hidden";
95
- const makeStatic = (div: HTMLDivElement) => {
96
- div.style.height = "0px";
97
- div.style.width = "0px";
98
- div.style.position = "static";
99
- };
100
-
101
- makeStatic(this.uiLayer);
102
- this.uiLayer.style.zIndex = "10";
103
- this.mediaLayer.style.zIndex = "8";
104
- makeStatic(this.mediaLayer);
105
- }
106
-
107
- private nextPage() {
108
- const nextPage = this.player.getNextPage();
109
- if (this.currentPage) {
110
- this.currentPage.destroy();
111
- this.uiLayer.innerHTML = "";
112
- }
113
-
114
- if (!nextPage) {
115
- // TODO FIGURE OUT WHAQT TO DO AT END OF TEST!! Start over??
116
- this.player = new DPlayer(this.schema);
117
- if (this.player.pagesLeft > 0) {
118
- this.nextPage();
119
- }
120
- return false;
121
- }
122
-
123
- const newPage = new Page(nextPage, this.taskManager, this.scale, (result) => {
124
- this.handlePageCompleted(result);
125
- });
126
- this.currentPage = newPage;
127
- newPage.appendYourself(this.uiLayer);
128
- return true;
129
- }
130
-
131
- destroy() {
132
- if (this.currentPage) {
133
- this.currentPage.destroy();
134
- this.uiLayer.innerHTML = "";
135
- }
136
- }
137
-
138
- private _onProgress: ((result: SchemaResult) => void) | false = false;
139
- onProgress(handler: (result: SchemaResult) => void) {
140
- this._onProgress = handler;
141
- }
142
-
143
- private _onFatalError: ((error: { message: string }) => void) | false = false;
144
- onFatalError(handler: (error: { message: string }) => void): void {
145
- this._onFatalError = handler;
146
- }
147
- setLogger(logger: EngineLogger) {
148
- this.logger = logger;
149
- }
150
- }
1
+ import { SchemaDto } from "./SchemaDto";
2
+ import { DPlayer } from "./dplayer";
3
+ import { ScaleService } from "./scale";
4
+ import { Page } from "../page/Page";
5
+ import { TaskManager } from "../page/task-manager";
6
+ import { PageResult } from "../page/page-result";
7
+ import { SchemaResult } from "./SchemaResult";
8
+ export interface EngineLogger {
9
+ info(message: string): void;
10
+ error(message: string): void;
11
+ warn(message: string): void;
12
+ }
13
+
14
+ const voidLogger: EngineLogger = {
15
+ info: (message: string) => {},
16
+ error: (message: string) => {},
17
+ warn: (message: string) => {},
18
+ };
19
+
20
+ export interface ISchemaEngine {
21
+ onProgress(handler: (result: SchemaResult) => void): void;
22
+ onFatalError(handler: (error: { message: string }) => void): void;
23
+ setLogger(logger: EngineLogger): void;
24
+ }
25
+
26
+ export class SchemaEngine implements ISchemaEngine {
27
+ private readonly TAG = "[ SCHEMA_ENGINE ] :";
28
+ private readonly scale: ScaleService;
29
+ private readonly hostElement: HTMLDivElement;
30
+ private readonly taskManager: TaskManager;
31
+ private logger: EngineLogger = voidLogger;
32
+ private readonly uiLayer: HTMLDivElement = document.createElement("div");
33
+ private readonly mediaLayer: HTMLDivElement = document.createElement("div");
34
+ private player: DPlayer;
35
+ private currentPage: Page | false = false;
36
+ private readonly tickerRef: number | false = false;
37
+ constructor(
38
+ hostEl: HTMLDivElement,
39
+ private readonly height: number,
40
+ private readonly width: number,
41
+ private readonly schema: SchemaDto,
42
+ ) {
43
+ this.tickerRef = window.setInterval(() => {
44
+ if (this.currentPage) {
45
+ this.currentPage.tick();
46
+ }
47
+ }, 100);
48
+ this.hostElement = hostEl;
49
+ this.hostElement.appendChild(this.mediaLayer);
50
+ this.hostElement.appendChild(this.uiLayer);
51
+ this.scale = new ScaleService({
52
+ baseHeight: schema.baseHeight,
53
+ baseWidth: schema.baseWidth,
54
+ containerWidth: width,
55
+ containerHeight: height,
56
+ });
57
+ this.logger.info(this.TAG + "Scale: " + JSON.stringify(this.scale));
58
+ this.player = new DPlayer(this.schema);
59
+ this.taskManager = new TaskManager(this.mediaLayer, this.scale, (error) => {
60
+ console.log(error);
61
+ });
62
+
63
+ this.styleSelf();
64
+ this.handlePageCompleted = this.handlePageCompleted.bind(this);
65
+ this.nextPage();
66
+ }
67
+
68
+ private handlePageCompleted(result: PageResult) {
69
+ // 1 Save data from last page
70
+ this.player.saveHistory(result);
71
+
72
+ // 2 Emit progress
73
+ const currentResults = this.player.getResults();
74
+ const a: SchemaResult = {
75
+ schemaId: this.schema.id,
76
+ pagesLeft: currentResults.pagesLeft,
77
+ predefinedFacts: currentResults.predefinedFacts,
78
+ eventLog: currentResults.eventLog,
79
+ answers: currentResults.answerFacts,
80
+ };
81
+ if (this._onProgress) {
82
+ this._onProgress(a);
83
+ }
84
+
85
+ // 3. Next page
86
+ this.nextPage();
87
+ }
88
+
89
+ private styleSelf() {
90
+ this.hostElement.style.height = this.scale.pageHeight + "px";
91
+ this.hostElement.style.width = this.scale.pageWidth + "px";
92
+ this.hostElement.style.backgroundColor = this.schema.backgroundColor ?? "white";
93
+ this.hostElement.style.position = "relative";
94
+ // this.hostElement.style.overflow = "hidden";
95
+ const makeStatic = (div: HTMLDivElement) => {
96
+ div.style.height = "0px";
97
+ div.style.width = "0px";
98
+ div.style.position = "static";
99
+ };
100
+
101
+ makeStatic(this.uiLayer);
102
+ this.uiLayer.style.zIndex = "10";
103
+ this.mediaLayer.style.zIndex = "8";
104
+ makeStatic(this.mediaLayer);
105
+ }
106
+
107
+ private nextPage() {
108
+ const nextPage = this.player.getNextPage();
109
+ if (this.currentPage) {
110
+ this.currentPage.destroy();
111
+ this.uiLayer.innerHTML = "";
112
+ }
113
+
114
+ if (!nextPage) {
115
+ // TODO FIGURE OUT WHAQT TO DO AT END OF TEST!! Start over??
116
+ this.player = new DPlayer(this.schema);
117
+ if (this.player.pagesLeft > 0) {
118
+ this.nextPage();
119
+ }
120
+ return false;
121
+ }
122
+
123
+ const newPage = new Page(nextPage, this.taskManager, this.scale, (result) => {
124
+ this.handlePageCompleted(result);
125
+ });
126
+ this.currentPage = newPage;
127
+ newPage.appendYourself(this.uiLayer);
128
+ return true;
129
+ }
130
+
131
+ destroy() {
132
+ if (this.currentPage) {
133
+ this.currentPage.destroy();
134
+ this.uiLayer.innerHTML = "";
135
+ }
136
+ }
137
+
138
+ private _onProgress: ((result: SchemaResult) => void) | false = false;
139
+ onProgress(handler: (result: SchemaResult) => void) {
140
+ this._onProgress = handler;
141
+ }
142
+
143
+ private _onFatalError: ((error: { message: string }) => void) | false = false;
144
+ onFatalError(handler: (error: { message: string }) => void): void {
145
+ this._onFatalError = handler;
146
+ }
147
+ setLogger(logger: EngineLogger) {
148
+ this.logger = logger;
149
+ }
150
+ }