@media-quest/builder 0.0.4 → 0.0.5
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/dist/public-api.d.mts +6 -6
- package/dist/public-api.d.ts +6 -6
- package/dist/public-api.js +33 -277
- package/dist/public-api.mjs +24 -268
- package/package.json +3 -3
- package/src/Builder-schema.ts +2 -3
- package/src/rulebuilder/Builder-rule.ts +4 -9
- package/src/rulebuilder/condition/Builder-condition-group.ts +3 -3
- package/src/rulebuilder/condition/Builder-condition.ts +2 -2
- package/src/rulebuilder/condition/Builder-operator.ts +3 -3
- package/src/rulebuilder/rule2/Rule2.ts +211 -0
- package/src/theme/default-theme-compiler.ts +9 -8
- package/tsconfig.json +2 -2
- package/src/rulebuilder/Rule2.ts +0 -87
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@media-quest/builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Builder library for Media-quest schemas",
|
|
5
5
|
"main": "dist/public-api.js",
|
|
6
6
|
"module": "dist/public-api.mjs",
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"check": "tsc --watch --noEmit",
|
|
11
11
|
"clean": "rimraf dist",
|
|
12
|
-
"build": "npm run clean && tsup src/public-api.ts --format cjs,esm --dts",
|
|
12
|
+
"build": "npm run clean && tsup src/public-api.ts --sourcemap inline --format cjs,esm --dts",
|
|
13
13
|
"prepublishOnly": "npm run build"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@media-quest/engine": "0.0.
|
|
16
|
+
"@media-quest/engine": "0.0.5"
|
|
17
17
|
}
|
|
18
18
|
}
|
package/src/Builder-schema.ts
CHANGED
|
@@ -192,17 +192,16 @@ export class BuilderSchema {
|
|
|
192
192
|
this.pages.forEach((page, index) => {
|
|
193
193
|
const pageVariables = page.getQuestionVariables(prefix, index);
|
|
194
194
|
qVars.push(...pageVariables);
|
|
195
|
-
const pageId = page.prefix;
|
|
196
195
|
const mainText = page.mainText.text;
|
|
197
196
|
const jumpAction: JumpToPageAction = {
|
|
198
197
|
kind: "jump-to-page",
|
|
199
|
-
pageId:
|
|
198
|
+
pageId: page.id,
|
|
200
199
|
pageNumber: index,
|
|
201
200
|
mainText: page.mainText.text,
|
|
202
201
|
};
|
|
203
202
|
const excludePageAction: ExcludeByPageAction = {
|
|
204
203
|
kind: "exclude-by-pageId",
|
|
205
|
-
pageId,
|
|
204
|
+
pageId: page.id,
|
|
206
205
|
pageNumber: index,
|
|
207
206
|
mainText,
|
|
208
207
|
};
|
|
@@ -9,10 +9,7 @@ import { BuilderObject } from "../BuilderObject";
|
|
|
9
9
|
import { TagActionManager } from "./tag-action-manager";
|
|
10
10
|
import { PageActionManager } from "./page-action-manager";
|
|
11
11
|
import { JumpToActionManager } from "./jump-to-action-manager";
|
|
12
|
-
import { Condition,
|
|
13
|
-
import { ExcludeByPageAction, ExcludeByTagAction, JumpToPageAction } from "./RuleAction";
|
|
14
|
-
import { RuleBuilderTestUtils } from "./RuleBuilder-test-utils";
|
|
15
|
-
import jumpToPageAction = RuleBuilderTestUtils.jumpToPageAction;
|
|
12
|
+
import { Condition, PageQueCommand, PageQueRules } from "@media-quest/engine";
|
|
16
13
|
|
|
17
14
|
export interface BuilderRuleDto {
|
|
18
15
|
readonly type: ConditionGroupType;
|
|
@@ -135,18 +132,18 @@ export class BuilderRule extends BuilderObject<"builder-rule", BuilderRuleDto> {
|
|
|
135
132
|
};
|
|
136
133
|
return dto;
|
|
137
134
|
}
|
|
138
|
-
toEngineRule(): PageQueRules {
|
|
135
|
+
toEngineRule(modulePrefix: string): PageQueRules {
|
|
139
136
|
const conditions: Condition[] = [];
|
|
140
137
|
this._conditions.forEach((c) => {
|
|
141
138
|
if (c) {
|
|
142
139
|
if (c instanceof BuilderCondition) {
|
|
143
|
-
const simpleCondition = c.toEngineCondition();
|
|
140
|
+
const simpleCondition = c.toEngineCondition(modulePrefix);
|
|
144
141
|
if (simpleCondition) {
|
|
145
142
|
conditions.push(simpleCondition);
|
|
146
143
|
}
|
|
147
144
|
}
|
|
148
145
|
if (c instanceof BuilderConditionGroup) {
|
|
149
|
-
const complexCondition = c.toEngineConditionComplex();
|
|
146
|
+
const complexCondition = c.toEngineConditionComplex(modulePrefix);
|
|
150
147
|
if (complexCondition) conditions.push(complexCondition);
|
|
151
148
|
}
|
|
152
149
|
}
|
|
@@ -190,9 +187,7 @@ export class BuilderRule extends BuilderObject<"builder-rule", BuilderRuleDto> {
|
|
|
190
187
|
pageQueCommands.push(excludeTagsCommand);
|
|
191
188
|
}
|
|
192
189
|
|
|
193
|
-
const id = DUtil.randomObjectId();
|
|
194
190
|
const rule: PageQueRules = {
|
|
195
|
-
id: "",
|
|
196
191
|
description: this.name,
|
|
197
192
|
all,
|
|
198
193
|
some,
|
|
@@ -7,13 +7,13 @@ const ConditionGroupType = {
|
|
|
7
7
|
all: true,
|
|
8
8
|
any: true,
|
|
9
9
|
count: true,
|
|
10
|
-
range: true,
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
export type ConditionGroupType = keyof typeof ConditionGroupType;
|
|
14
13
|
export interface BuilderConditionGroupDto {
|
|
15
14
|
readonly kind: "condition-group";
|
|
16
15
|
readonly name: string;
|
|
16
|
+
readonly count?: number;
|
|
17
17
|
readonly type: ConditionGroupType;
|
|
18
18
|
readonly conditions: ReadonlyArray<BuilderConditionDto>;
|
|
19
19
|
}
|
|
@@ -82,7 +82,7 @@ export class BuilderConditionGroup extends BuilderObject<"builder-condition-grou
|
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
toEngineConditionComplex(): Condition.Complex | false {
|
|
85
|
+
toEngineConditionComplex(modulePrefix: string): Condition.Complex | false {
|
|
86
86
|
const comp: Condition.Complex = {
|
|
87
87
|
kind: "complex-condition",
|
|
88
88
|
all: [],
|
|
@@ -91,7 +91,7 @@ export class BuilderConditionGroup extends BuilderObject<"builder-condition-grou
|
|
|
91
91
|
};
|
|
92
92
|
const conditions: Condition.Simple[] = [];
|
|
93
93
|
this.conditions.forEach((c) => {
|
|
94
|
-
const maybeSimple = c.toEngineCondition();
|
|
94
|
+
const maybeSimple = c.toEngineCondition(modulePrefix);
|
|
95
95
|
if (maybeSimple) {
|
|
96
96
|
conditions.push(maybeSimple);
|
|
97
97
|
}
|
|
@@ -103,7 +103,7 @@ export class BuilderCondition extends BuilderObject<"builder-condition", Builder
|
|
|
103
103
|
return { isValid: true };
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
toEngineCondition(): Condition.Simple | false {
|
|
106
|
+
toEngineCondition(modulePrefix: string): Condition.Simple | false {
|
|
107
107
|
const val = this.value;
|
|
108
108
|
const op = this._operator;
|
|
109
109
|
const v = this._variable;
|
|
@@ -115,7 +115,7 @@ export class BuilderCondition extends BuilderObject<"builder-condition", Builder
|
|
|
115
115
|
kind: "numeric-condition",
|
|
116
116
|
value: val.value,
|
|
117
117
|
valueLabel: val.label,
|
|
118
|
-
referenceId: v.varId,
|
|
118
|
+
referenceId: modulePrefix + "_" + v.varId,
|
|
119
119
|
referenceLabel: v.label,
|
|
120
120
|
operator: "eq",
|
|
121
121
|
};
|
|
@@ -16,14 +16,14 @@ const BuilderOperatorSymbols = {
|
|
|
16
16
|
empty: true,
|
|
17
17
|
notEmpty: true,
|
|
18
18
|
startsWith: true,
|
|
19
|
-
endsWith: true
|
|
19
|
+
endsWith: true,
|
|
20
20
|
} as const;
|
|
21
21
|
|
|
22
22
|
export type BuilderOperator = keyof typeof BuilderOperatorSymbols;
|
|
23
23
|
|
|
24
24
|
export namespace BuilderOperator {
|
|
25
|
-
export const is = (symbol
|
|
26
|
-
if (typeof symbol !==
|
|
25
|
+
export const is = (symbol?: string): symbol is BuilderOperator => {
|
|
26
|
+
if (typeof symbol !== "string") {
|
|
27
27
|
return false;
|
|
28
28
|
}
|
|
29
29
|
return Object.keys(BuilderOperatorSymbols).includes(symbol);
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { BuilderOperator } from "../condition/Builder-operator";
|
|
2
|
+
import { BuilderConditionDto } from "../condition/Builder-condition";
|
|
3
|
+
import { BuilderConditionGroupDto, ConditionGroupType } from "../condition/Builder-condition-group";
|
|
4
|
+
import { BuilderRuleDto } from "../Builder-rule";
|
|
5
|
+
|
|
6
|
+
type SolveErrorReason =
|
|
7
|
+
| "INVALID_FACT_TYPE"
|
|
8
|
+
| "INVALID_OPERATOR"
|
|
9
|
+
| "INVALID_VALUE"
|
|
10
|
+
| "INVALID_VARIABLE"
|
|
11
|
+
| "UNIMPLEMENTED_VARIABLE_TYPE"
|
|
12
|
+
| "UNIMPLEMENTED_OPERATOR";
|
|
13
|
+
|
|
14
|
+
type TrueResult = { readonly type: "IS_TRUE" };
|
|
15
|
+
type FalseResult = { readonly type: "IS_FALSE" };
|
|
16
|
+
type MissingFactsResult = { readonly type: "MISSING_FACTS"; readonly missingVariables: ReadonlyArray<string> };
|
|
17
|
+
type ErrorResult = {
|
|
18
|
+
readonly type: "HAS_ERROR";
|
|
19
|
+
readonly reason: SolveErrorReason;
|
|
20
|
+
readonly data: Record<string, string>;
|
|
21
|
+
};
|
|
22
|
+
export type EvalResult = FalseResult | TrueResult | MissingFactsResult | ErrorResult;
|
|
23
|
+
|
|
24
|
+
export interface Fact2 {
|
|
25
|
+
readonly variableType: "numeric";
|
|
26
|
+
readonly value: number;
|
|
27
|
+
readonly valueLabel: string;
|
|
28
|
+
readonly variableId: string;
|
|
29
|
+
readonly variableLabel: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class FactCollection {
|
|
33
|
+
public static isFact = (value: unknown): value is Fact2 => {
|
|
34
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const fact = value as Partial<Fact2>;
|
|
38
|
+
if (typeof fact.variableId !== "string" || fact.variableId.length === 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (typeof fact.variableLabel !== "string") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (typeof fact.value !== "number") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (typeof fact.valueLabel !== "string") {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// NB: This is a temporary check until we have more variable types.
|
|
51
|
+
if (typeof fact.variableType !== "string" || fact.variableType !== "numeric") {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return true;
|
|
56
|
+
};
|
|
57
|
+
public static create = (facts: ReadonlyArray<Fact2>): FactCollection => {
|
|
58
|
+
return new FactCollection(facts);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
private readonly _facts: ReadonlyArray<Fact2>;
|
|
62
|
+
|
|
63
|
+
private constructor(facts: ReadonlyArray<Fact2>) {
|
|
64
|
+
if (!Array.isArray(facts)) {
|
|
65
|
+
console.log("Invalid facts", facts);
|
|
66
|
+
this._facts = [];
|
|
67
|
+
} else {
|
|
68
|
+
this._facts = [...facts];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
byId(variableId: string): Fact2 | false {
|
|
72
|
+
const result = this._facts.find((fact) => fact.variableId === variableId);
|
|
73
|
+
if (!result) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return { ...result };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
interface FactEvaluator {
|
|
80
|
+
isTrue(facts: FactCollection): boolean;
|
|
81
|
+
evaluate(facts: FactCollection): EvalResult;
|
|
82
|
+
}
|
|
83
|
+
interface IsValid {
|
|
84
|
+
isValid(): boolean;
|
|
85
|
+
}
|
|
86
|
+
export class Condition implements FactEvaluator, IsValid {
|
|
87
|
+
public static create = (dto: BuilderConditionDto): Condition => {
|
|
88
|
+
return new Condition(dto);
|
|
89
|
+
};
|
|
90
|
+
private constructor(private readonly dto: BuilderConditionDto) {}
|
|
91
|
+
isTrue(facts: FactCollection): boolean {
|
|
92
|
+
const dto = this.dto;
|
|
93
|
+
const op = dto.operator;
|
|
94
|
+
const value = dto.value;
|
|
95
|
+
const varId = dto.variableId;
|
|
96
|
+
if (!BuilderOperator.is(op)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof value !== "number") {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const fact = facts.byId(this.dto.variableId);
|
|
105
|
+
|
|
106
|
+
if (!FactCollection.isFact(fact)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (fact.variableType !== "numeric" && typeof fact.value !== "number") {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (op === "equal") {
|
|
115
|
+
return fact.value === value;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (op === "notEqual") {
|
|
119
|
+
return fact.value !== value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
isValid(): boolean {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
evaluate(facts: FactCollection): EvalResult {
|
|
129
|
+
return { type: "HAS_ERROR", reason: "UNIMPLEMENTED_VARIABLE_TYPE", data: {} }; // TODO
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export class ConditionGroup implements FactEvaluator, IsValid {
|
|
133
|
+
public static readonly create = (dto: BuilderConditionGroupDto): ConditionGroup => {
|
|
134
|
+
return new ConditionGroup(dto);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
private readonly _conditions: ReadonlyArray<Condition>;
|
|
138
|
+
private constructor(private readonly dto: BuilderConditionGroupDto) {
|
|
139
|
+
this._conditions = dto.conditions.map(Condition.create);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
isTrue(facts: FactCollection): boolean {
|
|
143
|
+
const results = this._conditions.map((condition) => condition.isTrue(facts));
|
|
144
|
+
let trueCount = 0;
|
|
145
|
+
let falseCount = 0;
|
|
146
|
+
results.forEach((results) => {
|
|
147
|
+
if (results) {
|
|
148
|
+
trueCount++;
|
|
149
|
+
} else {
|
|
150
|
+
falseCount++;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (trueCount === 0 || falseCount === 0) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const type = this.dto.type;
|
|
157
|
+
|
|
158
|
+
if (type === "all" && trueCount === this._conditions.length) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (type === "any" && trueCount > 0) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const minLimit = this.dto.count;
|
|
167
|
+
if (type === "count" && typeof minLimit === "number" && trueCount >= minLimit) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
isValid(): boolean {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
evaluate(facts: FactCollection): EvalResult {
|
|
179
|
+
return { type: "HAS_ERROR", reason: "UNIMPLEMENTED_VARIABLE_TYPE", data: {} }; // TODO
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export class Rule2 implements FactEvaluator {
|
|
183
|
+
readonly name: string;
|
|
184
|
+
private readonly _conditions: ReadonlyArray<Condition | ConditionGroup>;
|
|
185
|
+
public static readonly create = (dto: BuilderRuleDto): Rule2 => {
|
|
186
|
+
return new Rule2(dto);
|
|
187
|
+
};
|
|
188
|
+
private _count = -1;
|
|
189
|
+
constructor(private readonly dto: BuilderRuleDto) {
|
|
190
|
+
this.name = dto.name;
|
|
191
|
+
const conditions: Array<Condition | ConditionGroup> = [];
|
|
192
|
+
dto.conditions.forEach((condition) => {
|
|
193
|
+
if (condition.kind === "condition-group") {
|
|
194
|
+
conditions.push(ConditionGroup.create(condition));
|
|
195
|
+
} else if (condition.kind === "condition") {
|
|
196
|
+
conditions.push(Condition.create(condition));
|
|
197
|
+
} else {
|
|
198
|
+
console.log("Unknown condition", condition);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
this._conditions = conditions;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
isTrue(facts: FactCollection): boolean {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
evaluate(facts: FactCollection): EvalResult {
|
|
209
|
+
return { type: "HAS_ERROR", reason: "UNIMPLEMENTED_VARIABLE_TYPE", data: {} }; // TODO
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AbstractThemeCompiler } from "./AbstractThemeCompiler";
|
|
2
2
|
import type { BuilderSchemaDto } from "../Builder-schema";
|
|
3
|
+
import { BuilderSchema } from "../Builder-schema";
|
|
3
4
|
import type { BuilderPageDto } from "../Builder-page";
|
|
4
5
|
import { DStateProps } from "./standard-props";
|
|
5
6
|
import { ThemeUtils } from "./theme-utils";
|
|
@@ -19,12 +20,10 @@ import {
|
|
|
19
20
|
Fact,
|
|
20
21
|
PageDto,
|
|
21
22
|
PageQueCommand,
|
|
22
|
-
PageQueRules,
|
|
23
23
|
Rule,
|
|
24
24
|
SchemaDto,
|
|
25
25
|
} from "@media-quest/engine";
|
|
26
26
|
import { AudioFile } from "../media-files";
|
|
27
|
-
import { BuilderSchema } from "../Builder-schema";
|
|
28
27
|
import { BuilderRule } from "../rulebuilder";
|
|
29
28
|
|
|
30
29
|
const U = DUtil;
|
|
@@ -41,7 +40,7 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
41
40
|
const ruleInput = builderSchema.getRuleInput();
|
|
42
41
|
const pageQueRules: Rule<PageQueCommand, never>[] = [];
|
|
43
42
|
source.rules.forEach((rule) => {
|
|
44
|
-
const engineRule = BuilderRule.fromDto(rule, ruleInput).toEngineRule();
|
|
43
|
+
const engineRule = BuilderRule.fromDto(rule, ruleInput).toEngineRule(source.prefix);
|
|
45
44
|
if (!Rule.isEmpty(engineRule)) {
|
|
46
45
|
pageQueRules.push(engineRule);
|
|
47
46
|
} else {
|
|
@@ -55,7 +54,7 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
compile(source: BuilderSchemaDto): SchemaDto {
|
|
58
|
-
const pages = source.pages.map((p) => this.compilePage(p, source.
|
|
57
|
+
const pages = source.pages.map((p) => this.compilePage(p, source.prefix));
|
|
59
58
|
const rules = this.compileRules(source);
|
|
60
59
|
const dto: SchemaDto = {
|
|
61
60
|
backgroundColor: source.backgroundColor,
|
|
@@ -117,8 +116,8 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
117
116
|
};
|
|
118
117
|
return dto;
|
|
119
118
|
}
|
|
120
|
-
private compilePage(page: BuilderPageDto,
|
|
121
|
-
// console.log(
|
|
119
|
+
private compilePage(page: BuilderPageDto, modulePrefix: string): PageDto {
|
|
120
|
+
// console.log(_moduleId);
|
|
122
121
|
// const textElement
|
|
123
122
|
const { nextButton, mainText, id, mainMedia, _type } = page;
|
|
124
123
|
const elements: DElementDto[] = [];
|
|
@@ -135,7 +134,8 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
if (_type === "question") {
|
|
138
|
-
const
|
|
137
|
+
const variableId = modulePrefix + "_" + page.prefix;
|
|
138
|
+
const { buttons, question } = this.compileQuestion(id, page, variableId);
|
|
139
139
|
// console.log(question);
|
|
140
140
|
elements.push(...buttons, question);
|
|
141
141
|
}
|
|
@@ -331,6 +331,7 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
331
331
|
private compileQuestion(
|
|
332
332
|
pageId: string,
|
|
333
333
|
page: BuilderPageDto,
|
|
334
|
+
variableId: string,
|
|
334
335
|
): {
|
|
335
336
|
question: DTextDto;
|
|
336
337
|
buttons: DDivDto[];
|
|
@@ -352,7 +353,7 @@ export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
|
352
353
|
const buttons = q.options.map((o) => {
|
|
353
354
|
const btns = this.compileButton(pageId, o, {
|
|
354
355
|
kind: "response-button",
|
|
355
|
-
questionId:
|
|
356
|
+
questionId: variableId,
|
|
356
357
|
});
|
|
357
358
|
return btns;
|
|
358
359
|
});
|
package/tsconfig.json
CHANGED
package/src/rulebuilder/Rule2.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { BuilderVariableType } from "./RuleVariable";
|
|
2
|
-
import { BuilderOperator } from "./condition/Builder-operator";
|
|
3
|
-
import { BuilderConditionDto } from "./condition/Builder-condition";
|
|
4
|
-
|
|
5
|
-
type ConditionType = "all" | "any" | "";
|
|
6
|
-
|
|
7
|
-
type SolveResultType = "TRUE" | "FALSE" | "NOT_ENOUGH_DATA" | "ERROR";
|
|
8
|
-
|
|
9
|
-
type SolveErrorReason =
|
|
10
|
-
| "INVALID_FACT_TYPE"
|
|
11
|
-
| "INVALID_OPERATOR"
|
|
12
|
-
| "INVALID_VALUE"
|
|
13
|
-
| "INVALID_VARIABLE"
|
|
14
|
-
| "UNIMPLEMENTED_VARIABLE_TYPE"
|
|
15
|
-
| "UNIMPLEMENTED_OPERATOR";
|
|
16
|
-
|
|
17
|
-
type IsTrue = { readonly type: "IS_TRUE" };
|
|
18
|
-
type IsFalse = { readonly type: "IS_FALSE" };
|
|
19
|
-
type IsMissingFacts = { readonly type: "MISSING_FACTS"; readonly missingVariables: ReadonlyArray<string> };
|
|
20
|
-
type HasError = {
|
|
21
|
-
readonly type: "HAS_ERROR";
|
|
22
|
-
readonly reason: SolveErrorReason;
|
|
23
|
-
readonly data: Record<string, string>;
|
|
24
|
-
};
|
|
25
|
-
export type SolveResult = IsFalse | IsTrue | IsMissingFacts | HasError;
|
|
26
|
-
|
|
27
|
-
export interface Fact2 {
|
|
28
|
-
readonly variableType: "numeric";
|
|
29
|
-
readonly value: number;
|
|
30
|
-
readonly valueLabel: string;
|
|
31
|
-
readonly variableId: string;
|
|
32
|
-
readonly variableLabel: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
class FactCollection {
|
|
36
|
-
constructor(private readonly facts: ReadonlyArray<Fact2>) {}
|
|
37
|
-
byId(variableId: string): Fact2 | false {
|
|
38
|
-
const result = this.facts.find((fact) => fact.variableId === variableId);
|
|
39
|
-
if (!result) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
interface Solvable {
|
|
46
|
-
isTrue(facts: FactCollection): boolean;
|
|
47
|
-
solve(facts: FactCollection): SolveResult;
|
|
48
|
-
}
|
|
49
|
-
interface IsValid {
|
|
50
|
-
isValid(): boolean;
|
|
51
|
-
}
|
|
52
|
-
export class Condition implements Solvable, IsValid {
|
|
53
|
-
constructor(private readonly dto: BuilderConditionDto) {}
|
|
54
|
-
isTrue(facts: FactCollection): boolean {
|
|
55
|
-
const op = this.dto.operator;
|
|
56
|
-
if (!BuilderOperator.is(op)) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const fact = facts.byId(this.dto.variableId);
|
|
61
|
-
|
|
62
|
-
if (!fact) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (fact.variableType !== "numeric" && typeof fact.value !== "number") {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
isValid(): boolean {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
solve(facts: FactCollection): SolveResult {
|
|
77
|
-
return { type: "HAS_ERROR", reason: "UNIMPLEMENTED_VARIABLE_TYPE", data: {} }; // TODO
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export class ConditionGroup {}
|
|
81
|
-
export class Rule2 {
|
|
82
|
-
private _count = -1;
|
|
83
|
-
constructor(
|
|
84
|
-
private readonly dto: any,
|
|
85
|
-
private readonly _ruleInput: any,
|
|
86
|
-
) {}
|
|
87
|
-
}
|