@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.
Files changed (60) hide show
  1. package/package.json +1 -2
  2. package/src/Delement/DElement.dto.ts +5 -0
  3. package/src/Delement/DElement.ts +78 -253
  4. package/src/Delement/DImg.ts +31 -70
  5. package/src/Delement/DStyle.ts +156 -156
  6. package/src/Delement/DText.ts +9 -25
  7. package/src/Delement/Ddiv.ts +10 -23
  8. package/src/Delement/button-click-action.ts +11 -0
  9. package/src/Delement/element-factory.ts +40 -0
  10. package/src/engine/DCommand.ts +21 -0
  11. package/src/engine/SchemaDto.ts +24 -0
  12. package/src/engine/SchemaEngine.ts +48 -120
  13. package/src/{player → engine}/dplayer.spec.ts +20 -17
  14. package/src/{player → engine}/dplayer.ts +29 -16
  15. package/src/engine/history-que.spec.ts +59 -0
  16. package/src/engine/history-que.ts +39 -0
  17. package/src/{player → engine}/next-que.spec.ts +19 -8
  18. package/src/engine/next-que.ts +93 -0
  19. package/src/page/Page.ts +160 -0
  20. package/src/page/media-player.ts +117 -0
  21. package/src/page/page-component.ts +113 -0
  22. package/src/page/page-result.ts +11 -0
  23. package/src/page/task-manager.ts +203 -0
  24. package/src/page/task-state.ts +55 -0
  25. package/src/page/task.ts +87 -0
  26. package/src/public-api.ts +17 -13
  27. package/src/rules/__test__/rule-engine.spec.ts +1 -1
  28. package/src/utils/DUtil.ts +110 -103
  29. package/tsconfig.tsbuildinfo +1 -0
  30. package/dist/public-api.js +0 -2245
  31. package/dist/public-api.mjs +0 -2205
  32. package/src/Delement/AudioContainer.ts +0 -169
  33. package/src/Delement/DAuto-play.ts +0 -36
  34. package/src/Delement/VideoContainer.ts +0 -199
  35. package/src/commands/DCommand.ts +0 -63
  36. package/src/commands/DCommandBus.ts +0 -60
  37. package/src/dto/AnimationDto.ts +0 -4
  38. package/src/dto/DElement.dto.ts +0 -46
  39. package/src/dto/SchemaDto.ts +0 -65
  40. package/src/engine/DPage.ts +0 -60
  41. package/src/engine/element-factory.ts +0 -52
  42. package/src/event-handlers/DEventHandler.ts +0 -29
  43. package/src/events/DEvents.ts +0 -94
  44. package/src/events/event-bus.spec.ts +0 -21
  45. package/src/events/event-bus.ts +0 -81
  46. package/src/kladd/context-menu-manager.ts +0 -56
  47. package/src/player/history-que.spec.ts +0 -46
  48. package/src/player/history-que.ts +0 -38
  49. package/src/player/next-que.ts +0 -93
  50. package/src/services/DMedia-manager.spec.ts +0 -27
  51. package/src/services/DMedia-manager.ts +0 -179
  52. package/src/services/resource-provider.ts +0 -33
  53. package/src/services/sequence-manager.spec.ts +0 -168
  54. package/src/services/sequence-manager.ts +0 -133
  55. package/src/state/Dstate.spec.ts +0 -7
  56. package/src/state/Dstate.ts +0 -105
  57. package/src/state/boolean-property.ts +0 -69
  58. package/src/state/state-service.spec.ts +0 -307
  59. package/src/state/state-service.ts +0 -251
  60. package/src/state/state-testing-helpers.ts +0 -59
@@ -1,179 +0,0 @@
1
- import { PageDto } from "../dto/SchemaDto";
2
- import { VideoContainer } from "../Delement/VideoContainer";
3
- import { AudioContainer } from "../Delement/AudioContainer";
4
- import { AutoPlayElement, DAutoPlaySequence } from "../Delement/DAuto-play";
5
- import { DCommandBus } from "../commands/DCommandBus";
6
- import { DCommand } from "../commands/DCommand";
7
- import { DTimestamp } from "../common/DTimestamp";
8
- import { EventBus } from "../events/event-bus";
9
- import { ScaleService } from "../engine/scale";
10
- import { ResourceProvider } from "./resource-provider";
11
- import { AutoplayTask, SequenceManager } from "./sequence-manager";
12
-
13
- export interface IMediaManager {
14
- setPage(page: PageDto): void;
15
- destroy(): void;
16
- }
17
-
18
- export class DMediaManager implements IMediaManager {
19
- private static INSTANCE_COUNT = 0;
20
- private readonly instanceNumber: number;
21
- private readonly TAG = "[ MEDIA_MANAGER ] : ";
22
- private readonly videoContainer: VideoContainer;
23
- private readonly audioContainer: AudioContainer;
24
- private pageEnter: DTimestamp;
25
- private sincePageEnter: DTimestamp.Diff;
26
- private currentPage: PageDto | null = null;
27
- private readonly unsubscribeCommands: () => void;
28
- private readonly tickerRef: number;
29
- private readonly sequenceManager: SequenceManager | false = false;
30
- constructor(
31
- private hostEl: HTMLDivElement,
32
- private readonly commandBus: DCommandBus,
33
- private readonly eventBus: EventBus,
34
- private readonly resourceProvider: ResourceProvider,
35
- private readonly scale: ScaleService,
36
- ) {
37
- DMediaManager.INSTANCE_COUNT = DMediaManager.INSTANCE_COUNT + 1;
38
- this.instanceNumber = DMediaManager.INSTANCE_COUNT;
39
- const videoEl = document.createElement("video");
40
- this.hostEl.append(videoEl);
41
- this.videoContainer = new VideoContainer(videoEl, eventBus, this.scale);
42
- this.audioContainer = new AudioContainer(this.eventBus);
43
- this.tick = this.tick.bind(this);
44
- this.videoContainer.setStyle({ visibility: "hidden" });
45
- const now = DTimestamp.now();
46
- this.pageEnter = now;
47
- this.sincePageEnter = DTimestamp.diff(now, now);
48
- this.unsubscribeCommands = this.commandBus.subscribe((action) => {
49
- this.commandHandler(action);
50
- }, this.TAG);
51
-
52
- this.tickerRef = window.setInterval(() => {}, 1000);
53
- }
54
-
55
- /**
56
- * Stop all media that is playing
57
- */
58
- clearAllMedia() {
59
- this.videoContainer.pause();
60
- this.audioContainer.pause();
61
- }
62
- destroy() {
63
- console.log("TODO DESTROY ALL MEDIA");
64
- this.unsubscribeCommands();
65
- // console.log(this.tickerRef);
66
- window.clearInterval(this.tickerRef);
67
- this.audioContainer.destroy();
68
- this.videoContainer.destroy();
69
- }
70
-
71
- setPage(page: PageDto) {
72
- // TODO STOP VIDEO/AUDIO THAT MIGHT BE PLAYING IN THE DOM??
73
- this.currentPage = page;
74
- this.videoContainer.pause();
75
- this.pageEnter = DTimestamp.now();
76
- // TODO THis might be a bug if someone
77
-
78
- const seq = page.autoPlaySequence;
79
- // this.sequence = seq ? [...seq.items] : [];
80
- const { mainVideoId, audio } = page;
81
- const audioElements = page.audio;
82
-
83
- if (mainVideoId) {
84
- const dto = this.resourceProvider.getVideoById(mainVideoId);
85
- if (dto) {
86
- this.videoContainer.setDto(dto);
87
- this.videoContainer.setStyle({ ...dto.style, visibility: "visible" });
88
- }
89
- // this.videoContainer.playToEnd();
90
- } else {
91
- this.videoContainer.setStyle({ visibility: "hidden" });
92
- // HIDE?
93
- }
94
- if (audioElements) {
95
- const first = audioElements[0];
96
- if (first) {
97
- this.audioContainer.setAudio(first);
98
- }
99
- }
100
- if (seq) {
101
- this.playSequence(seq);
102
- }
103
- // const hasVideo =
104
- }
105
-
106
- private commandHandler(command: DCommand) {
107
- if (command.kind === "VIDEO_PLAY_COMMAND") {
108
- const video = command.targetId;
109
- const dto = this.videoContainer.getCurrentDto();
110
-
111
- if (dto && dto.id === command.targetId) {
112
- console.log(video);
113
- this.videoContainer.play(dto.url);
114
- }
115
- }
116
- if (command.kind === "VIDEO_PAUSE_COMMAND") {
117
- this.videoContainer.pause();
118
- }
119
- if (command.kind === "AUDIO_PLAY_COMMAND") {
120
- this.audioContainer
121
- .playToEnd()
122
- .then(() => {})
123
- .catch()
124
- .finally(() => {});
125
- }
126
-
127
- if (command.kind === "AUDIO_PAUSE_COMMAND") {
128
- // this.audioContainer.
129
- }
130
- }
131
-
132
- private async playSequence(seq: DAutoPlaySequence) {
133
- // console.log(this.TAG + "SEQUENCE STARTED -- TODO EVENT FOR THIS??");
134
-
135
- const elements = seq.items;
136
- const testClone = [...elements];
137
- const first = testClone.pop();
138
-
139
- if (!first) {
140
- return false;
141
- }
142
- const now = DTimestamp.now();
143
- seq.startCommands.forEach((c) => {
144
- console.log(c);
145
- this.commandBus.emit(c);
146
- });
147
- // this.commandBus.emit(DStateProps.mediaBlockedBySequence.setTrueCommand);
148
- // if (seq.blockUserInput) {
149
- // this.commandBus.emit(DStateProps.inputBlockingBySequence.getSetTrueCommand());
150
- // }
151
- for (let i = 0; i < elements.length; i++) {
152
- const item = elements[i];
153
- if (item.kind === "autoplay-video") {
154
- const dto = this.resourceProvider.getVideoById(item.videoId);
155
- if (dto) this.videoContainer.setDto(dto);
156
- await this.videoContainer.playToEnd();
157
- }
158
- if (item.kind === "autoplay-audio") {
159
- console.log(item);
160
- const dto = this.resourceProvider.getAudioById(item.audioId);
161
- if (dto) this.audioContainer.setAudio(dto);
162
- await this.audioContainer.playToEnd();
163
- }
164
- }
165
- seq.endCommands.forEach((c) => {
166
- this.commandBus.emit(c);
167
- });
168
- // this.actionService.emit(DStateProps.mediaBlockedBySequence.setFalseCommand);
169
- // this.actionService.emit(DStateProps.inputBlockingBySequence.setFalseCommand);
170
- console.log(this.TAG + "SEQUENCE ENDED");
171
- return true;
172
- }
173
-
174
- // setPage()
175
-
176
- private tick() {
177
- // console.log(this.video1.getStats());
178
- }
179
- }
@@ -1,33 +0,0 @@
1
- import { DAudioDto, DImgDto, DVideoDto } from "../dto/DElement.dto";
2
-
3
- export class ResourceProvider {
4
- private readonly TAG = "[ RESOURCE_PROVIDER ]: ";
5
- private readonly videoMap = new Map<string, DVideoDto>();
6
- private readonly audioMap = new Map<string, DAudioDto>();
7
- constructor(data: { videos: ReadonlyArray<DVideoDto>; audio: ReadonlyArray<DAudioDto> }) {
8
- // console.log(this.TAG + "VIDEO_COUNT " + data.videos.length);
9
- // console.log(this.TAG + "AUDIO_COUNT " + data.audio.length);
10
- data.videos.forEach((video) => {
11
- this.videoMap.set(video.id, video);
12
- });
13
- data.audio.forEach((audio) => {
14
- this.audioMap.set(audio.id, audio);
15
- });
16
- }
17
-
18
- getAudioById(id: string): DAudioDto | false {
19
- const maybeAudio = this.audioMap.get(id);
20
- if (!maybeAudio) {
21
- console.error(this.TAG + "Audio by id " + id + " dont exist");
22
- }
23
- return maybeAudio ?? false;
24
- }
25
-
26
- getVideoById(id: string): DVideoDto | false {
27
- const maybeVideo = this.videoMap.get(id);
28
- if (!maybeVideo) {
29
- console.error(this.TAG + "Video by id " + id + " dont exist");
30
- }
31
- return maybeVideo ?? false;
32
- }
33
- }
@@ -1,168 +0,0 @@
1
- import { AudioTask, DelayTask, NoopTask, SequenceManager, VideoTask } from "./sequence-manager";
2
- import { DTimestamp } from "../common/DTimestamp";
3
-
4
- const delayTask = (duration: number): DelayTask => {
5
- return { kind: "delay-task", duration };
6
- };
7
- const createTimestamps = () => {
8
- const t0 = DTimestamp.now();
9
- const add = (ms: number) => DTimestamp.addMills(t0, ms);
10
- return {
11
- t0,
12
- t100: add(100),
13
- t500: add(500),
14
- t600: add(600),
15
- t900: add(900),
16
- t1000: add(1000),
17
- t1020: add(1020),
18
- t1100: add(1100),
19
- t1200: add(1200),
20
- t1500: add(1500),
21
- t2000: add(2000),
22
- t2100: add(2100),
23
- t2500: add(2500),
24
- t3000: add(3000),
25
- t3001: add(3001),
26
- t5000: add(5000),
27
- t6000: add(6000),
28
- t7000: add(7000),
29
- t8000: add(8000),
30
- t8500: add(8500),
31
- t9000: add(9000),
32
- t9500: add(9500),
33
- };
34
- };
35
- const audioTask = (url: string): AudioTask => {
36
- return { kind: "autoplay-audio-task", url, audioId: "id_" + url };
37
- };
38
- const videoTask = (url: string): VideoTask => {
39
- return { kind: "autoplay-video-task", url, videoId: "id_" + url };
40
- };
41
-
42
- const noopTask: NoopTask = { kind: "noop-task" };
43
- const delay1000 = delayTask(1000);
44
- const delay2000 = delayTask(2000);
45
- const video1 = videoTask("video_1_url");
46
- const audio1 = audioTask("audio_1_url");
47
- const sequence1 = [delay1000, video1, delay2000, audio1];
48
- const manager = (tasks: Array<DelayTask | AudioTask | VideoTask>) => new SequenceManager(tasks);
49
- describe("Media manager state", () => {
50
- test("Empty task array is completed at once:", () => {
51
- const m = manager([]);
52
- expect(m.isCompleted).toBeTruthy();
53
- });
54
-
55
- test("Non empty task-array will be running at creation-time", () => {
56
- const m = manager([delayTask(1000), audioTask("url1")]);
57
- expect(m.isRunning).toBeTruthy();
58
- });
59
-
60
- test("After abort the task", () => {
61
- const sm = manager(sequence1);
62
- expect(sm.isRunning).toBeTruthy();
63
- sm.abort();
64
- const nextTask = sm.nextTask(DTimestamp.now());
65
- expect(sm.isRunning).toBeFalsy();
66
- expect(nextTask).toStrictEqual(noopTask);
67
- });
68
- test("Fist task will be returned after construction", () => {
69
- const sm = manager([video1]);
70
- const firstTask = sm.nextTask(DTimestamp.now());
71
- expect(firstTask).toStrictEqual(video1);
72
- // expect(firstTask).toStrictEqual(noopTask);
73
- });
74
- test("A task will only be returned once!", () => {
75
- const sm = manager([video1, audio1]);
76
- const firstTask = sm.nextTask(DTimestamp.now());
77
-
78
- expect(sm.isRunning);
79
- expect(firstTask).toStrictEqual(video1);
80
- const secondTask = sm.nextTask(DTimestamp.now());
81
- expect(secondTask).toStrictEqual(noopTask);
82
- expect(sm.isRunning);
83
- });
84
- test("A delayTask will block other tasks from running.", () => {
85
- const t = createTimestamps();
86
- const sm = manager([delayTask(1000), video1, audio1]);
87
- expect(sm.isRunning);
88
- const task0 = sm.nextTask(DTimestamp.now());
89
- expect(task0).toStrictEqual(noopTask);
90
-
91
- expect(sm.nextTask(t.t500)).toStrictEqual(noopTask);
92
- expect(sm.nextTask(t.t600)).toStrictEqual(noopTask);
93
- expect(sm.nextTask(t.t900)).toStrictEqual(noopTask);
94
-
95
- // AFTER DELAY
96
- expect(sm.nextTask(t.t1020)).toStrictEqual(video1);
97
- expect(sm.nextTask(t.t5000)).toStrictEqual(noopTask);
98
- });
99
- test("A video-task can ble completed.", () => {
100
- const t = createTimestamps();
101
- const sm = manager([video1, audio1]);
102
- expect(sm.isRunning);
103
- expect(sm.nextTask(t.t100)).toStrictEqual(video1);
104
- expect(sm.nextTask(t.t500)).toStrictEqual(noopTask);
105
- expect(sm.nextTask(t.t2100)).toStrictEqual(noopTask);
106
- sm.videoCompleted({ videoId: video1.videoId, url: video1.url });
107
- const after = sm.nextTask(t.t3001);
108
- expect(after).toStrictEqual(audio1);
109
- });
110
- test("Many delays can be placed and block on every step.", () => {
111
- const t = createTimestamps();
112
- const sm = manager([delayTask(1000), video1, delay2000, audio1]);
113
- expect(sm.isRunning);
114
-
115
- // FIRST DELAY.
116
- expect(sm.nextTask(t.t100)).toStrictEqual(noopTask);
117
- expect(sm.nextTask(t.t600)).toStrictEqual(noopTask);
118
- expect(sm.nextTask(t.t900)).toStrictEqual(noopTask);
119
- expect(sm.nextTask(t.t1020)).toStrictEqual(video1);
120
- expect(sm.nextTask(t.t1100)).toStrictEqual(noopTask);
121
- expect(sm.nextTask(t.t1500)).toStrictEqual(noopTask);
122
-
123
- // DELAY 2 -> start at approximately 1500
124
- sm.videoCompleted({ videoId: video1.videoId, url: video1.url });
125
- expect(sm.nextTask(t.t2100)).toStrictEqual(noopTask);
126
- expect(sm.nextTask(t.t3000)).toStrictEqual(noopTask);
127
- expect(sm.nextTask(t.t5000)).toStrictEqual(audio1);
128
- expect(sm.nextTask(t.t6000)).toStrictEqual(noopTask);
129
- expect(sm.nextTask(t.t7000)).toStrictEqual(noopTask);
130
- expect(sm.isCompleted).toStrictEqual(false);
131
- sm.audioCompleted({ audioId: audio1.audioId, url: audio1.url });
132
- expect(sm.isCompleted).toStrictEqual(true);
133
- });
134
- test("Can complete audio", () => {
135
- const t = createTimestamps();
136
- const sm = manager([audio1]);
137
- expect(sm.isRunning);
138
- // FIRST DELAY.
139
- expect(sm.nextTask(t.t100)).toStrictEqual(audio1);
140
- expect(sm.nextTask(t.t500)).toStrictEqual(noopTask);
141
- expect(sm.nextTask(t.t600)).toStrictEqual(noopTask);
142
- expect(sm.isCompleted).toStrictEqual(false);
143
- sm.audioCompleted({ audioId: audio1.audioId, url: audio1.url });
144
- expect(sm.isCompleted).toStrictEqual(true);
145
- });
146
- test("Can only complete audio with correct url.", () => {
147
- const t = createTimestamps();
148
- const sm = manager([audio1]);
149
- expect(sm.isRunning);
150
- // FIRST DELAY.
151
- const first = sm.nextTask(t.t100);
152
- expect(first).toStrictEqual(audio1);
153
- expect(sm.isCompleted).toStrictEqual(false);
154
- sm.audioCompleted({ audioId: "bullshit", url: "bullshit" });
155
- expect(sm.isCompleted).toStrictEqual(false);
156
- });
157
- test("Can only complete video with correct url.", () => {
158
- const t = createTimestamps();
159
- const sm = manager([video1]);
160
- expect(sm.isRunning);
161
- // FIRST DELAY.
162
- const first = sm.nextTask(t.t100);
163
- expect(first).toStrictEqual(video1);
164
- expect(sm.isCompleted).toStrictEqual(false);
165
- sm.videoCompleted({ videoId: "bullshit", url: "bullshit" });
166
- expect(sm.isCompleted).toStrictEqual(false);
167
- });
168
- });
@@ -1,133 +0,0 @@
1
- import { DTimestamp } from "../common/DTimestamp";
2
-
3
- export interface DelayTask {
4
- readonly kind: "delay-task";
5
- readonly duration: number;
6
- }
7
-
8
- export interface NoopTask {
9
- readonly kind: "noop-task";
10
- }
11
-
12
- export interface AudioTask {
13
- readonly kind: "autoplay-audio-task";
14
- readonly url: string;
15
- readonly audioId: string;
16
- }
17
-
18
- export interface VideoTask {
19
- readonly kind: "autoplay-video-task";
20
- readonly url: string;
21
- readonly videoId: string;
22
- }
23
-
24
- export type AutoplayTask = VideoTask | AudioTask | DelayTask;
25
- type TaskHistory = {
26
- readonly startedAt: DTimestamp;
27
- readonly completedAt: DTimestamp;
28
- readonly task: AutoplayTask;
29
- };
30
- class SequenceHistory {
31
- private taskHistory: Array<TaskHistory> = [];
32
- constructor(private readonly startedAt: DTimestamp) {}
33
-
34
- add(task: TaskHistory) {
35
- this.taskHistory.push(task);
36
- }
37
- }
38
-
39
- export class SequenceManager {
40
- private runningTask: { task: AutoplayTask; startedAt: DTimestamp } | false;
41
- private taskList: Array<DelayTask | AudioTask | VideoTask>;
42
- private readonly t0: DTimestamp;
43
- private readonly history: SequenceHistory;
44
-
45
- constructor(private readonly tasks: ReadonlyArray<AudioTask | DelayTask | VideoTask>) {
46
- this.t0 = DTimestamp.now();
47
- const [first, ...rest] = tasks;
48
- if (first && first.kind === "delay-task") {
49
- this.runningTask = { task: first, startedAt: this.t0 };
50
- this.taskList = [...rest];
51
- } else {
52
- this.runningTask = false;
53
- this.taskList = [...tasks];
54
- }
55
- this.history = new SequenceHistory(this.t0);
56
- }
57
-
58
- audioCompleted(audio: { audioId: string; url: string }) {
59
- const curr = this.runningTask;
60
- if (curr && curr.task.kind === "autoplay-audio-task") {
61
- const { audioId, url } = curr.task;
62
- if (url === audio.url) {
63
- this.runningTask = false;
64
- } else {
65
- // WARN ABOUT UNEXPECTED AUDIO ID && URL ??
66
- console.warn("Unexpected audio completed url.");
67
- }
68
- }
69
- }
70
-
71
- videoCompleted(video: { videoId: string; url: string }) {
72
- const curr = this.runningTask;
73
- if (curr && curr.task.kind === "autoplay-video-task") {
74
- const { url } = curr.task;
75
- if (url === video.url) {
76
- this.runningTask = false;
77
- } else {
78
- // WARN ABOUT UNEXPECTED AUDIO ID && URL ??
79
- console.warn("Unexpected video completed url.");
80
- }
81
- }
82
- }
83
-
84
- abort() {
85
- this.taskList = [];
86
- this.runningTask = false;
87
- }
88
- get isCompleted() {
89
- return !this.isRunning;
90
- }
91
- get isRunning() {
92
- return this.runningTask || this.taskList.length;
93
- }
94
-
95
- nextTask(now: DTimestamp): NoopTask | AudioTask | VideoTask {
96
- const curr = this.runningTask;
97
-
98
- if (curr && curr.task.kind === "delay-task") {
99
- const progress = DTimestamp.diff(curr.startedAt, now);
100
- // DELAY COMPLETED.
101
- if (progress >= curr.task.duration) {
102
- this.runningTask = false;
103
- }
104
- }
105
-
106
- // RETURN IF A TASK IS RUNNING.
107
- if (this.runningTask) {
108
- return { kind: "noop-task" };
109
- }
110
-
111
- const first = this.taskList.shift();
112
- if (!first) {
113
- return { kind: "noop-task" };
114
- }
115
-
116
- if (first.kind === "delay-task") {
117
- this.runningTask = { task: first, startedAt: now };
118
- return { kind: "noop-task" };
119
- }
120
-
121
- if (first.kind === "autoplay-video-task") {
122
- this.runningTask = { task: first, startedAt: now };
123
- return first;
124
- }
125
-
126
- if (first.kind === "autoplay-audio-task") {
127
- this.runningTask = { task: first, startedAt: now };
128
- return first;
129
- }
130
-
131
- return { kind: "noop-task" };
132
- }
133
- }
@@ -1,7 +0,0 @@
1
- import { DState } from "./Dstate";
2
-
3
- describe("Prop-utils work", () => {
4
- it("isMutation works", () => {
5
- expect(DState.isStringMutation({ propName: "", value: 2, kind: "set-number" })).toBe(false);
6
- });
7
- });
@@ -1,105 +0,0 @@
1
- import { Fact } from "../rules/fact";
2
- import { Condition } from "../rules/condition";
3
- import { DEvent } from "../events/DEvents";
4
- import { StateCommand } from "../commands/DCommand";
5
-
6
- export namespace DState {
7
- interface PropDefinition<TypeName, Type extends string | number> {
8
- readonly _type: TypeName;
9
- readonly propName: string;
10
- readonly propDescription: string;
11
- readonly initialValue?: Type;
12
- readonly options?: ReadonlyArray<PropValue<Type>>;
13
- }
14
-
15
- export type NumericProp = PropDefinition<"number", number>;
16
- export type StringProp = PropDefinition<"string", string>;
17
-
18
- export interface fromEventHandler {
19
- readonly onEvent: DEvent["kind"];
20
- readonly thenExecute: ReadonlyArray<StateCommand>;
21
- }
22
-
23
- export interface PropValue<T> {
24
- readonly value: T;
25
- readonly valueLabel: string;
26
- }
27
- export type Prop = NumericProp | StringProp;
28
-
29
- export interface SetStringMutation {
30
- readonly kind: "set-string";
31
- readonly propName: string;
32
- readonly value: string;
33
- }
34
-
35
- export interface IncrementNumberMutation {
36
- readonly kind: "increment-number";
37
- readonly propName: string;
38
- readonly stepSize: number;
39
- readonly ifNotExistThenSetTo: number;
40
- }
41
- export interface DecrementNumberMutation {
42
- readonly kind: "decrement-number";
43
- readonly propName: string;
44
- readonly stepSize: number;
45
- readonly ifNotExistThenSetTo: number;
46
- }
47
-
48
- export interface SetNumberMutation {
49
- readonly kind: "set-number";
50
- readonly propName: string;
51
- readonly value: number;
52
- }
53
- export type NumberMutations = IncrementNumberMutation | DecrementNumberMutation | SetNumberMutation;
54
-
55
- export type StateMutation = SetStringMutation | NumberMutations;
56
-
57
- export const isNumberMutation = (mutations: StateMutation): mutations is NumberMutations => {
58
- if (!mutations) {
59
- return false;
60
- }
61
-
62
- return (
63
- mutations.kind === "set-number" ||
64
- mutations.kind === "decrement-number" ||
65
- mutations.kind === "increment-number"
66
- );
67
- };
68
-
69
- export const isStringMutation = (mutation: StateMutation): mutation is SetStringMutation => {
70
- return mutation && mutation.kind === "set-string";
71
- };
72
-
73
- export interface StateQuery {
74
- readonly name: string;
75
- readonly condition: Condition;
76
- }
77
-
78
- export interface StateQueryResult {
79
- readonly queryName: string;
80
- readonly prev: boolean;
81
- readonly curr: boolean;
82
- }
83
-
84
- export const numericPropToFact = (prop: NumericProp, value: number) => {
85
- const fact: Fact.Numeric = {
86
- kind: "numeric-fact",
87
- referenceId: prop.propName,
88
- referenceLabel: prop.propDescription ?? " [STATE_PROPERTY] : " + prop.propName,
89
- value,
90
- label: " [VALUE] : " + value,
91
- };
92
- return fact;
93
- };
94
-
95
- export const stringPropToFact = (prop: StringProp, value: string) => {
96
- const fact: Fact.String = {
97
- kind: "string-fact",
98
- referenceId: prop.propName,
99
- referenceLabel: " [STATE_PROPERTY] : " + prop.propName,
100
- value,
101
- label: " [VALUE] : " + value,
102
- };
103
- return fact;
104
- };
105
- }
@@ -1,69 +0,0 @@
1
- import { DState } from "./Dstate";
2
- import { Condition } from "../rules/condition";
3
- import { StateCommand } from "../commands/DCommand";
4
-
5
- export class BooleanStateProperty<PropName extends string> {
6
- readonly propName: PropName;
7
- private static readonly TRUE = { value: 1, label: "TRUE" };
8
- private static readonly FALSE = { value: 0, label: "FALSE" };
9
- readonly propDefinition: DState.NumericProp;
10
-
11
- getIsTrueCondition(): Condition.Numeric {
12
- return {
13
- kind: "numeric-condition",
14
- referenceId: this.propName,
15
- referenceLabel: this.propName + "[ BOOLEAN ]",
16
- valueLabel: BooleanStateProperty.TRUE.label,
17
- value: BooleanStateProperty.TRUE.value,
18
- operator: "eq",
19
- };
20
- }
21
- getIsFalseCondition(): Condition.Numeric {
22
- return {
23
- kind: "numeric-condition",
24
- referenceId: this.propName,
25
- referenceLabel: this.propName + "[ BOOLEAN ]",
26
- valueLabel: BooleanStateProperty.FALSE.label,
27
- value: BooleanStateProperty.FALSE.value,
28
- operator: "eq",
29
- };
30
- }
31
-
32
- getSetTrueCommand(): StateCommand {
33
- return {
34
- kind: "STATE_MUTATE_COMMAND",
35
- target: "STATE",
36
- targetId: "STATE",
37
- payload: {
38
- mutation: { propName: this.propName, kind: "set-number", value: 1 },
39
- },
40
- };
41
- }
42
-
43
- getSetFalseCommand(): StateCommand {
44
- return {
45
- kind: "STATE_MUTATE_COMMAND",
46
- target: "STATE",
47
- targetId: "STATE",
48
- payload: {
49
- mutation: { propName: this.propName, kind: "set-number", value: 0 },
50
- },
51
- };
52
- }
53
-
54
- constructor(propName: PropName, private readonly initialValue: boolean, description: string) {
55
- this.propName = propName;
56
- const initial = initialValue ? 1 : 0;
57
- const propDescription = description ? description : "No description given";
58
- this.propDefinition = {
59
- propDescription,
60
- propName: propName,
61
- initialValue: initial,
62
- options: [
63
- { value: BooleanStateProperty.FALSE.value, valueLabel: BooleanStateProperty.FALSE.label },
64
- { value: BooleanStateProperty.TRUE.value, valueLabel: BooleanStateProperty.TRUE.label },
65
- ],
66
- _type: "number",
67
- };
68
- }
69
- }