@f1studio/form-spec 5.0.0-alpha.101 → 5.0.0-alpha.103

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 (161) hide show
  1. package/Components/HelloComponent.d.ts +20 -0
  2. package/Components/HelloComponent.d.ts.map +1 -0
  3. package/Designer.d.ts.map +1 -0
  4. package/FormSpec.TS/Designer.js +2 -2
  5. package/FormSpec.TS/Designer.js.map +1 -1
  6. package/FormSpec.TS/Designer.ts.map +1 -1
  7. package/FormSpec.TS/FormSpec.js +210 -143
  8. package/FormSpec.TS/FormSpec.js.map +1 -1
  9. package/FormSpec.TS/FormSpec.ts.map +1 -1
  10. package/FormSpec.TS/FormSpecHelpers.js +62 -40
  11. package/FormSpec.TS/FormSpecHelpers.js.map +1 -1
  12. package/FormSpec.TS/FormSpecHelpers.ts.map +1 -1
  13. package/FormSpec.TS/FormSpecValues.js +207 -0
  14. package/FormSpec.TS/FormSpecValues.js.map +1 -0
  15. package/FormSpec.TS/FormSpecValues.ts.map +1 -0
  16. package/FormSpec.TS/Helpers.js +26 -25
  17. package/FormSpec.TS/Helpers.js.map +1 -1
  18. package/FormSpec.TS/Helpers.ts.map +1 -1
  19. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js +85 -125
  20. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js.map +1 -1
  21. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.ts.map +1 -1
  22. package/FormSpec.TS/Interop/FormSpec.Api.Option.js +37 -7
  23. package/FormSpec.TS/Interop/FormSpec.Api.Option.js.map +1 -1
  24. package/FormSpec.TS/Interop/FormSpec.Api.Option.ts.map +1 -1
  25. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js +103 -80
  26. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js.map +1 -1
  27. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.ts.map +1 -1
  28. package/FormSpec.TS/PathwayExecutor.js +371 -125
  29. package/FormSpec.TS/PathwayExecutor.js.map +1 -1
  30. package/FormSpec.TS/PathwayExecutor.ts.map +1 -1
  31. package/FormSpec.TS/PathwayValidator.js +14 -26
  32. package/FormSpec.TS/PathwayValidator.js.map +1 -1
  33. package/FormSpec.TS/PathwayValidator.ts.map +1 -1
  34. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.ts.map +1 -1
  35. package/FormSpec.TS/Renderers/PathwayRenderers.js +35 -26
  36. package/FormSpec.TS/Renderers/PathwayRenderers.js.map +1 -1
  37. package/FormSpec.TS/Renderers/PathwayRenderers.ts.map +1 -1
  38. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs +0 -0
  39. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs +0 -0
  40. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs +0 -0
  41. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Fable.Form.fableproj +0 -0
  42. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs +0 -0
  43. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Fable.Form.Simple.fableproj +0 -0
  44. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs +0 -0
  45. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Extensions.fs +0 -0
  46. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs +0 -0
  47. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Types.fableproj +0 -0
  48. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs +0 -0
  49. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.Types.fableproj +0 -0
  50. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs +0 -0
  51. package/FormSpec.TS/fable_modules/Feliz.2.7.0/BorderStyle.fs +0 -0
  52. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs +0 -0
  53. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Feliz.fableproj +0 -0
  54. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Fonts.fs +0 -0
  55. package/FormSpec.TS/fable_modules/Feliz.2.7.0/GridTypes.fs +0 -0
  56. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Html.fs +0 -0
  57. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs +0 -0
  58. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs +0 -0
  59. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Length.fs +0 -0
  60. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Locale.fs +0 -0
  61. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs +0 -0
  62. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs +0 -0
  63. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs +0 -0
  64. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js +0 -0
  65. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js.map +0 -0
  66. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs +0 -0
  67. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs +0 -0
  68. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Styles.fs +0 -0
  69. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs +0 -0
  70. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationLine.fs +0 -0
  71. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationStyle.fs +0 -0
  72. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Transform.fs +0 -0
  73. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransformOrigin.fs +0 -0
  74. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransitionProperty.fs +0 -0
  75. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs +0 -0
  76. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs +0 -0
  77. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs +0 -0
  78. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js.map +1 -1
  79. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.ts.map +1 -1
  80. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs +0 -0
  81. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Thoth.Json.fableproj +0 -0
  82. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs +0 -0
  83. package/FormSpec.TS/fable_modules/project_cracked.json +1 -1
  84. package/FormSpec.d.ts +56 -43
  85. package/FormSpec.d.ts.map +1 -0
  86. package/FormSpecHelpers.d.ts +18 -12
  87. package/FormSpecHelpers.d.ts.map +1 -0
  88. package/FormSpecValues.d.ts +62 -0
  89. package/FormSpecValues.d.ts.map +1 -0
  90. package/Helpers.d.ts +11 -10
  91. package/Helpers.d.ts.map +1 -0
  92. package/Interfaces.d.ts.map +1 -0
  93. package/Interop/FormSpec.Api.Helpers.d.ts +25 -28
  94. package/Interop/FormSpec.Api.Helpers.d.ts.map +1 -1
  95. package/Interop/FormSpec.Api.Option.d.ts +10 -6
  96. package/Interop/FormSpec.Api.Option.d.ts.map +1 -1
  97. package/Interop/FormSpec.Values.Api.Option.d.ts +35 -22
  98. package/Interop/FormSpec.Values.Api.Option.d.ts.map +1 -1
  99. package/Logging/LogTypes.d.ts +112 -0
  100. package/Logging/LogTypes.d.ts.map +1 -0
  101. package/Migrator.d.ts.map +1 -0
  102. package/PathwayDataExtractor.d.ts.map +1 -0
  103. package/PathwayExecutor.d.ts +63 -33
  104. package/PathwayExecutor.d.ts.map +1 -0
  105. package/PathwayValidator.d.ts.map +1 -0
  106. package/PluginInterface.d.ts.map +1 -0
  107. package/Prelude.d.ts.map +1 -0
  108. package/README.TS.md +621 -621
  109. package/README.md +98 -85
  110. package/Renderers/FormSpecMarkdownRenderer.d.ts +11 -0
  111. package/Renderers/FormSpecMarkdownRenderer.d.ts.map +1 -0
  112. package/Renderers/MermaidRenderer.d.ts +48 -0
  113. package/Renderers/MermaidRenderer.d.ts.map +1 -0
  114. package/Renderers/PathwayRenderers.d.ts +59 -0
  115. package/Renderers/PathwayRenderers.d.ts.map +1 -0
  116. package/fable_modules/Thoth.Json.10.4.1/Decode.fs.d.ts +126 -0
  117. package/fable_modules/Thoth.Json.10.4.1/Decode.fs.d.ts.map +1 -0
  118. package/fable_modules/Thoth.Json.10.4.1/Encode.fs.d.ts +163 -0
  119. package/fable_modules/Thoth.Json.10.4.1/Encode.fs.d.ts.map +1 -0
  120. package/fable_modules/Thoth.Json.10.4.1/Types.fs.d.ts +66 -0
  121. package/fable_modules/Thoth.Json.10.4.1/Types.fs.d.ts.map +1 -0
  122. package/package.json +53 -39
  123. package/src/Components/HelloComponent.ts +48 -48
  124. package/src/Designer.ts +389 -389
  125. package/src/FormSpec.ts +3154 -3114
  126. package/src/FormSpecHelpers.ts +397 -374
  127. package/src/FormSpecValues.ts +158 -0
  128. package/src/Helpers.ts +766 -765
  129. package/src/Interfaces.ts +166 -166
  130. package/src/Interop/FormSpec.Api.Helpers.ts +835 -872
  131. package/src/Interop/FormSpec.Api.Option.ts +1637 -1618
  132. package/src/Interop/FormSpec.Values.Api.Option.ts +1241 -1214
  133. package/src/Logging/LogTypes.ts +212 -212
  134. package/src/Migrator.ts +156 -156
  135. package/src/PathwayDataExtractor.ts +290 -290
  136. package/src/PathwayExecutor.ts +1379 -1102
  137. package/src/PathwayValidator.ts +238 -244
  138. package/src/PluginInterface.ts +79 -79
  139. package/src/Prelude.ts +21 -21
  140. package/src/Renderers/FormSpecMarkdownRenderer.ts +875 -874
  141. package/src/Renderers/MermaidRenderer.ts +218 -218
  142. package/src/Renderers/PathwayRenderers.ts +208 -200
  143. package/src/Components/HelloComponent.ts.map +0 -1
  144. package/src/Designer.ts.map +0 -1
  145. package/src/FormSpec.ts.map +0 -1
  146. package/src/FormSpecHelpers.ts.map +0 -1
  147. package/src/Helpers.ts.map +0 -1
  148. package/src/Interfaces.ts.map +0 -1
  149. package/src/Interop/FormSpec.Api.Helpers.ts.map +0 -1
  150. package/src/Interop/FormSpec.Api.Option.ts.map +0 -1
  151. package/src/Interop/FormSpec.Values.Api.Option.ts.map +0 -1
  152. package/src/Logging/LogTypes.ts.map +0 -1
  153. package/src/Migrator.ts.map +0 -1
  154. package/src/PathwayDataExtractor.ts.map +0 -1
  155. package/src/PathwayExecutor.ts.map +0 -1
  156. package/src/PathwayValidator.ts.map +0 -1
  157. package/src/PluginInterface.ts.map +0 -1
  158. package/src/Prelude.ts.map +0 -1
  159. package/src/Renderers/FormSpecMarkdownRenderer.ts.map +0 -1
  160. package/src/Renderers/MermaidRenderer.ts.map +0 -1
  161. package/src/Renderers/PathwayRenderers.ts.map +0 -1
@@ -1,244 +1,238 @@
1
- import { Record } from "@fable-org/fable-library-js/Types.js";
2
- import { tryFind, toList, ofList, FSharpMap } from "@fable-org/fable-library-js/Map.js";
3
- import { ClinicalPathway_StateDefinition, Values_DynamicFormResultData$1, Values_FieldDetails$1, Values_StepOrder, Values_DynamicFormSpecDetails, Values_Signature, Values_FormStatus_Complete, Spec_MatrixInfo, Shared_FieldValue_$union, Shared_FieldValue_Single, Shared_FieldAnswer, Shared_FieldValue_Matrix, Shared_MatrixAnswer, Shared_MatrixItemKey, Spec_FormSpec$1, Spec_FormStep$1, ClinicalPathway_ClinicalPathwaySpec, ClinicalPathway_TransitionDefinition, ClinicalPathway_TransitionCondition_$union, Spec_FormField$1, Shared_FieldOption, Spec_FieldType_$union, Shared_StateKey_$reflection, Shared_StateKey, Shared_FieldKey_$reflection, Shared_FieldKey } from "./FormSpec.js";
4
- import { stringHash, safeHash, compare, equals, IComparable, IEquatable } from "@fable-org/fable-library-js/Util.js";
5
- import { option_type, list_type, int32_type, bool_type, record_type, class_type, string_type, TypeInfo } from "@fable-org/fable-library-js/Reflection.js";
6
- import { ofList as ofList_1, intersect, isEmpty as isEmpty_1, empty as empty_1, FSharpSet } from "@fable-org/fable-library-js/Set.js";
7
- import { int32 } from "@fable-org/fable-library-js/Int32.js";
8
- import { reverse, choose, take, length, zip, mapIndexed, head as head_1, cons, tail as tail_1, collect, isEmpty, filter, exists, empty, singleton, ofArray, map, FSharpList } from "@fable-org/fable-library-js/List.js";
9
- import { isExecutionComplete, ExecutionContext$1, initializeExecution, executeStep, ExecutionLogEntry_$reflection, ExecutionLogEntry } from "./PathwayExecutor.js";
10
- import { map as map_1, value as value_2, Option } from "@fable-org/fable-library-js/Option.js";
11
- import { substring, join } from "@fable-org/fable-library-js/String.js";
12
- import { newGuid } from "@fable-org/fable-library-js/Guid.js";
13
- import { List_distinct, List_groupBy } from "@fable-org/fable-library-js/Seq2.js";
14
- import { min } from "@fable-org/fable-library-js/Double.js";
15
-
16
- export class TestScenario extends Record implements IEquatable<TestScenario>, IComparable<TestScenario> {
17
- readonly ScenarioId: string;
18
- readonly FieldValues: FSharpMap<Shared_FieldKey, string>;
19
- readonly Description: string;
20
- constructor(ScenarioId: string, FieldValues: FSharpMap<Shared_FieldKey, string>, Description: string) {
21
- super();
22
- this.ScenarioId = ScenarioId;
23
- this.FieldValues = FieldValues;
24
- this.Description = Description;
25
- }
26
- }
27
-
28
- export function TestScenario_$reflection(): TypeInfo {
29
- return record_type("F1.Studio.PathwayValidator.TestScenario", [], TestScenario, () => [["ScenarioId", string_type], ["FieldValues", class_type("Microsoft.FSharp.Collections.FSharpMap`2", [Shared_FieldKey_$reflection(), string_type])], ["Description", string_type]]);
30
- }
31
-
32
- export class ScenarioValidationResult extends Record implements IEquatable<ScenarioValidationResult>, IComparable<ScenarioValidationResult> {
33
- readonly Scenario: TestScenario;
34
- readonly ReachedTerminal: boolean;
35
- readonly FinalStates: FSharpSet<Shared_StateKey>;
36
- readonly ExecutionComplete: boolean;
37
- readonly DeadEndDetected: boolean;
38
- readonly InfiniteLoopDetected: boolean;
39
- readonly MaxDepthExceeded: boolean;
40
- readonly ExecutionIterations: int32;
41
- readonly ExecutionLog: FSharpList<ExecutionLogEntry>;
42
- readonly Error: Option<string>;
43
- constructor(Scenario: TestScenario, ReachedTerminal: boolean, FinalStates: FSharpSet<Shared_StateKey>, ExecutionComplete: boolean, DeadEndDetected: boolean, InfiniteLoopDetected: boolean, MaxDepthExceeded: boolean, ExecutionIterations: int32, ExecutionLog: FSharpList<ExecutionLogEntry>, Error$: Option<string>) {
44
- super();
45
- this.Scenario = Scenario;
46
- this.ReachedTerminal = ReachedTerminal;
47
- this.FinalStates = FinalStates;
48
- this.ExecutionComplete = ExecutionComplete;
49
- this.DeadEndDetected = DeadEndDetected;
50
- this.InfiniteLoopDetected = InfiniteLoopDetected;
51
- this.MaxDepthExceeded = MaxDepthExceeded;
52
- this.ExecutionIterations = (ExecutionIterations | 0);
53
- this.ExecutionLog = ExecutionLog;
54
- this.Error = Error$;
55
- }
56
- }
57
-
58
- export function ScenarioValidationResult_$reflection(): TypeInfo {
59
- return record_type("F1.Studio.PathwayValidator.ScenarioValidationResult", [], ScenarioValidationResult, () => [["Scenario", TestScenario_$reflection()], ["ReachedTerminal", bool_type], ["FinalStates", class_type("Microsoft.FSharp.Collections.FSharpSet`1", [Shared_StateKey_$reflection()])], ["ExecutionComplete", bool_type], ["DeadEndDetected", bool_type], ["InfiniteLoopDetected", bool_type], ["MaxDepthExceeded", bool_type], ["ExecutionIterations", int32_type], ["ExecutionLog", list_type(ExecutionLogEntry_$reflection())], ["Error", option_type(string_type)]]);
60
- }
61
-
62
- export class PathwayValidationResult extends Record implements IEquatable<PathwayValidationResult>, IComparable<PathwayValidationResult> {
63
- readonly TotalScenarios: int32;
64
- readonly ValidScenarios: int32;
65
- readonly DeadEndScenarios: FSharpList<ScenarioValidationResult>;
66
- readonly InfiniteLoopScenarios: FSharpList<ScenarioValidationResult>;
67
- readonly OverComplexScenarios: FSharpList<ScenarioValidationResult>;
68
- readonly Errors: FSharpList<string>;
69
- constructor(TotalScenarios: int32, ValidScenarios: int32, DeadEndScenarios: FSharpList<ScenarioValidationResult>, InfiniteLoopScenarios: FSharpList<ScenarioValidationResult>, OverComplexScenarios: FSharpList<ScenarioValidationResult>, Errors: FSharpList<string>) {
70
- super();
71
- this.TotalScenarios = (TotalScenarios | 0);
72
- this.ValidScenarios = (ValidScenarios | 0);
73
- this.DeadEndScenarios = DeadEndScenarios;
74
- this.InfiniteLoopScenarios = InfiniteLoopScenarios;
75
- this.OverComplexScenarios = OverComplexScenarios;
76
- this.Errors = Errors;
77
- }
78
- }
79
-
80
- export function PathwayValidationResult_$reflection(): TypeInfo {
81
- return record_type("F1.Studio.PathwayValidator.PathwayValidationResult", [], PathwayValidationResult, () => [["TotalScenarios", int32_type], ["ValidScenarios", int32_type], ["DeadEndScenarios", list_type(ScenarioValidationResult_$reflection())], ["InfiniteLoopScenarios", list_type(ScenarioValidationResult_$reflection())], ["OverComplexScenarios", list_type(ScenarioValidationResult_$reflection())], ["Errors", list_type(string_type)]]);
82
- }
83
-
84
- function getFieldPossibleValues(field: Spec_FormField$1<Spec_FieldType_$union>): FSharpList<string> {
85
- const matchValue: Spec_FieldType_$union = field.FieldType;
86
- switch (matchValue.tag) {
87
- case /* SingleChoice */ 13:
88
- return map<Shared_FieldOption, string>((opt: Shared_FieldOption): string => opt.Value, matchValue.fields[0].Options);
89
- case /* MultiChoice */ 15:
90
- return map<Shared_FieldOption, string>((opt_1: Shared_FieldOption): string => opt_1.Value, matchValue.fields[0].Options);
91
- case /* CheckboxList */ 16:
92
- return map<Shared_FieldOption, string>((opt_2: Shared_FieldOption): string => opt_2.Value, matchValue.fields[0].Options);
93
- case /* Dropdown */ 14:
94
- return map<Shared_FieldOption, string>((opt_3: Shared_FieldOption): string => opt_3.Value, matchValue.fields[0].Options);
95
- case /* Radio */ 12:
96
- return map<Shared_FieldOption, string>((opt_4: Shared_FieldOption): string => opt_4.Value, matchValue.fields[0].Options);
97
- case /* Matrix */ 19:
98
- return map<Shared_FieldOption, string>((opt_5: Shared_FieldOption): string => opt_5.Value, matchValue.fields[0].Options);
99
- case /* Checkbox */ 11:
100
- return ofArray(["true", "false"]);
101
- case /* Number */ 6:
102
- return ofArray(["0", "1", "10", "100"]);
103
- case /* Text */ 0:
104
- case /* TextArea */ 1:
105
- return singleton("");
106
- default:
107
- return empty<string>();
108
- }
109
- }
110
-
111
- function isFieldRelevantForPathway(field: Spec_FormField$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec): boolean {
112
- const fieldKey: Shared_FieldKey = field.FieldKey;
113
- return exists<ClinicalPathway_TransitionDefinition>((trans: ClinicalPathway_TransitionDefinition): boolean => {
114
- const conditionUsesField = (cond: ClinicalPathway_TransitionCondition_$union): boolean => {
115
- switch (cond.tag) {
116
- case /* FieldCondition */ 0:
117
- return equals(cond.fields[0], fieldKey);
118
- case /* FieldOptionCondition */ 1:
119
- return equals(cond.fields[0], fieldKey);
120
- case /* PluginPropertyCondition */ 2:
121
- return equals(cond.fields[0], fieldKey);
122
- case /* StateCondition */ 3:
123
- return false;
124
- case /* CompositeCondition */ 4:
125
- return exists<ClinicalPathway_TransitionCondition_$union>(conditionUsesField, cond.fields[1]);
126
- case /* TestResultCondition */ 5:
127
- return false;
128
- default:
129
- return false;
130
- }
131
- };
132
- return conditionUsesField(trans.Condition);
133
- }, pathway.Transitions);
134
- }
135
-
136
- /**
137
- * Generate test scenarios for pathway validation
138
- * Strategy: Only generate scenarios for fields that are actually used in pathway conditions
139
- * For Likert fields, generate scenarios for each item independently
140
- */
141
- export function generateTestScenarios(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, maxScenarios: Option<int32>): FSharpList<TestScenario> {
142
- let max: int32, max_1: int32;
143
- const fieldValueOptions: FSharpList<[Shared_FieldKey, FSharpList<string>]> = filter<[Shared_FieldKey, FSharpList<string>]>((tupledArg: [Shared_FieldKey, FSharpList<string>]): boolean => !isEmpty(tupledArg[1]), map<Spec_FormField$1<Spec_FieldType_$union>, [Shared_FieldKey, FSharpList<string>]>((field_1: Spec_FormField$1<Spec_FieldType_$union>): [Shared_FieldKey, FSharpList<string>] => ([field_1.FieldKey, getFieldPossibleValues(field_1)] as [Shared_FieldKey, FSharpList<string>]), filter<Spec_FormField$1<Spec_FieldType_$union>>((field: Spec_FormField$1<Spec_FieldType_$union>): boolean => isFieldRelevantForPathway(field, pathway), collect<Spec_FormStep$1<Spec_FieldType_$union>, Spec_FormField$1<Spec_FieldType_$union>>((step: Spec_FormStep$1<Spec_FieldType_$union>): FSharpList<Spec_FormField$1<Spec_FieldType_$union>> => step.Fields, formSpec.Steps))));
144
- const cartesianProduct = <a>(lists: FSharpList<FSharpList<a>>): FSharpList<FSharpList<a>> => {
145
- if (!isEmpty(lists)) {
146
- const tailProducts: FSharpList<FSharpList<a>> = cartesianProduct(tail_1(lists));
147
- return collect<a, FSharpList<a>>((h: a): FSharpList<FSharpList<a>> => map<FSharpList<a>, FSharpList<a>>((t: FSharpList<a>): FSharpList<a> => cons(h, t), tailProducts), head_1(lists));
148
- }
149
- else {
150
- return singleton(empty<a>());
151
- }
152
- };
153
- const allCombinations: FSharpList<FSharpList<string>> = cartesianProduct(map<[Shared_FieldKey, FSharpList<string>], FSharpList<string>>((tuple: [Shared_FieldKey, FSharpList<string>]): FSharpList<string> => tuple[1], fieldValueOptions));
154
- return mapIndexed<FSharpList<string>, TestScenario>((index: int32, combination: FSharpList<string>): TestScenario => {
155
- const fieldValues: FSharpMap<Shared_FieldKey, string> = ofList<Shared_FieldKey, string>(map<[[Shared_FieldKey, FSharpList<string>], string], [Shared_FieldKey, string]>((tupledArg_1: [[Shared_FieldKey, FSharpList<string>], string]): [Shared_FieldKey, string] => ([tupledArg_1[0][0], tupledArg_1[1]] as [Shared_FieldKey, string]), zip<[Shared_FieldKey, FSharpList<string>], string>(fieldValueOptions, combination)), {
156
- Compare: compare,
157
- });
158
- return new TestScenario(`scenario_${index + 1}`, fieldValues, join(", ", map<[Shared_FieldKey, string], string>((tupledArg_2: [Shared_FieldKey, string]): string => (`${substring(tupledArg_2[0].fields[0], 0, 8)}=${tupledArg_2[1]}`), toList<Shared_FieldKey, string>(fieldValues))));
159
- }, (maxScenarios != null) ? (((max = (value_2(maxScenarios) | 0), length(allCombinations) > max)) ? ((max_1 = (value_2(maxScenarios) | 0), take<FSharpList<string>>(max_1, allCombinations))) : allCombinations) : allCombinations);
160
- }
161
-
162
- function scenarioToFormData(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, scenario: TestScenario): Values_DynamicFormResultData$1<Spec_FieldType_$union> {
163
- const fieldValues: FSharpMap<Shared_FieldKey, Shared_FieldValue_$union> = ofList<Shared_FieldKey, Shared_FieldValue_$union>(choose<Spec_FormField$1<Spec_FieldType_$union>, [Shared_FieldKey, Shared_FieldValue_$union]>((field: Spec_FormField$1<Spec_FieldType_$union>): Option<[Shared_FieldKey, Shared_FieldValue_$union]> => map_1<string, [Shared_FieldKey, Shared_FieldValue_$union]>((value: string): [Shared_FieldKey, Shared_FieldValue_$union] => {
164
- let matchValue: Spec_FieldType_$union, info: Spec_MatrixInfo;
165
- return [field.FieldKey, (matchValue = field.FieldType, (matchValue.tag === /* Matrix */ 19) ? ((info = matchValue.fields[0], Shared_FieldValue_Matrix(new Shared_MatrixAnswer(field.FieldKey, field.Label, ofList<Shared_MatrixItemKey, string>(map<Shared_MatrixItemKey, [Shared_MatrixItemKey, string]>((itemKey: Shared_MatrixItemKey): [Shared_MatrixItemKey, string] => ([itemKey, value] as [Shared_MatrixItemKey, string]), singleton(new Shared_MatrixItemKey(newGuid()))), {
166
- Compare: compare,
167
- }))))) : Shared_FieldValue_Single(new Shared_FieldAnswer(field.FieldKey, field.Label, value)))] as [Shared_FieldKey, Shared_FieldValue_$union];
168
- }, tryFind<Shared_FieldKey, string>(field.FieldKey, scenario.FieldValues)), collect<Spec_FormStep$1<Spec_FieldType_$union>, Spec_FormField$1<Spec_FieldType_$union>>((step: Spec_FormStep$1<Spec_FieldType_$union>): FSharpList<Spec_FormField$1<Spec_FieldType_$union>> => step.Fields, formSpec.Steps)), {
169
- Compare: compare,
170
- });
171
- return new Values_DynamicFormResultData$1(new Values_DynamicFormSpecDetails(formSpec.Id, formSpec.Code, formSpec.FormSpecVersion, formSpec.Version, formSpec.Score, Values_FormStatus_Complete(), empty<Values_Signature>()), ofList<Values_StepOrder, FSharpMap<Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>>>(map<Spec_FormStep$1<Spec_FieldType_$union>, [Values_StepOrder, FSharpMap<Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>>]>((step_1: Spec_FormStep$1<Spec_FieldType_$union>): [Values_StepOrder, FSharpMap<Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>>] => ([new Values_StepOrder(step_1.StepOrder), ofList<Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>>(choose<Spec_FormField$1<Spec_FieldType_$union>, [Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>]>((field_1: Spec_FormField$1<Spec_FieldType_$union>): Option<[Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>]> => map_1<Shared_FieldValue_$union, [Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>]>((value_1: Shared_FieldValue_$union): [Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>] => {
172
- let matchValue_1: Spec_FieldType_$union;
173
- return [field_1.FieldKey, new Values_FieldDetails$1(field_1.FieldOrder, field_1.FieldKey, field_1.Label, value_1, field_1.FieldType, (matchValue_1 = field_1.FieldType, (matchValue_1.tag === /* SingleChoice */ 13) ? matchValue_1.fields[0].Options : ((matchValue_1.tag === /* MultiChoice */ 15) ? matchValue_1.fields[0].Options : ((matchValue_1.tag === /* CheckboxList */ 16) ? matchValue_1.fields[0].Options : ((matchValue_1.tag === /* Dropdown */ 14) ? matchValue_1.fields[0].Options : ((matchValue_1.tag === /* Radio */ 12) ? matchValue_1.fields[0].Options : ((matchValue_1.tag === /* Matrix */ 19) ? matchValue_1.fields[0].Options : empty<Shared_FieldOption>())))))))] as [Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>];
174
- }, tryFind<Shared_FieldKey, Shared_FieldValue_$union>(field_1.FieldKey, fieldValues)), step_1.Fields), {
175
- Compare: compare,
176
- })] as [Values_StepOrder, FSharpMap<Shared_FieldKey, Values_FieldDetails$1<Spec_FieldType_$union>>]), formSpec.Steps), {
177
- Compare: compare,
178
- }));
179
- }
180
-
181
- function isTerminalState(state: ClinicalPathway_StateDefinition): boolean {
182
- if (state.StateType.tag === /* Terminal */ 5) {
183
- return true;
184
- }
185
- else {
186
- return false;
187
- }
188
- }
189
-
190
- function detectInfiniteLoop(executionLog: FSharpList<ExecutionLogEntry>, maxDepth: int32): boolean {
191
- let list_1: FSharpList<ExecutionLogEntry>;
192
- if (length(executionLog) > maxDepth) {
193
- return exists<[Shared_StateKey, int32]>((tupledArg_1: [Shared_StateKey, int32]): boolean => (tupledArg_1[1] >= 3), map<[Shared_StateKey, FSharpList<Shared_StateKey>], [Shared_StateKey, int32]>((tupledArg: [Shared_StateKey, FSharpList<Shared_StateKey>]): [Shared_StateKey, int32] => ([tupledArg[0], length(tupledArg[1])] as [Shared_StateKey, int32]), List_groupBy<Shared_StateKey, Shared_StateKey>((x: Shared_StateKey): Shared_StateKey => x, map<ExecutionLogEntry, Shared_StateKey>((log: ExecutionLogEntry): Shared_StateKey => log.StateKey, (list_1 = reverse<ExecutionLogEntry>(executionLog), take<ExecutionLogEntry>(min(20, length(executionLog)), list_1))), {
194
- Equals: equals,
195
- GetHashCode: safeHash,
196
- })));
197
- }
198
- else {
199
- return false;
200
- }
201
- }
202
-
203
- function validateScenario(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, scenario: TestScenario, maxDepth: int32): ScenarioValidationResult {
204
- try {
205
- const finalContext: ExecutionContext$1<Spec_FieldType_$union> = executeStep<Spec_FieldType_$union>(initializeExecution<Spec_FieldType_$union>(formSpec, scenarioToFormData(formSpec, scenario)), maxDepth);
206
- const reachedTerminal: boolean = !isEmpty_1<Shared_StateKey>(intersect<Shared_StateKey>(ofList_1<Shared_StateKey>(map<ClinicalPathway_StateDefinition, Shared_StateKey>((s: ClinicalPathway_StateDefinition): Shared_StateKey => s.StateKey, filter<ClinicalPathway_StateDefinition>(isTerminalState, pathway.States)), {
207
- Compare: compare,
208
- }), finalContext.CurrentStates));
209
- const isComplete: boolean = isExecutionComplete<Spec_FieldType_$union>(finalContext);
210
- const infiniteLoopDetected: boolean = detectInfiniteLoop(finalContext.ExecutionLog, maxDepth);
211
- return new ScenarioValidationResult(scenario, reachedTerminal, finalContext.CurrentStates, isComplete, (((!isComplete && !reachedTerminal) && isEmpty(finalContext.ActiveTransitions)) && isEmpty(finalContext.PendingTransitions)) && !infiniteLoopDetected, infiniteLoopDetected, (length(finalContext.ExecutionLog) >= maxDepth) && !isComplete, length(finalContext.ExecutionLog), finalContext.ExecutionLog, undefined);
212
- }
213
- catch (ex: any) {
214
- return new ScenarioValidationResult(scenario, false, empty_1<Shared_StateKey>({
215
- Compare: compare,
216
- }), false, true, false, false, 0, empty<ExecutionLogEntry>(), ex.message);
217
- }
218
- }
219
-
220
- /**
221
- * Validate pathway for dead-end scenarios, infinite loops, and overcomplexity
222
- */
223
- export function validatePathwayCompleteness(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, maxScenarios: Option<int32>, maxDepth: int32): PathwayValidationResult {
224
- const scenarios: FSharpList<TestScenario> = generateTestScenarios(formSpec, pathway, maxScenarios);
225
- const results: FSharpList<ScenarioValidationResult> = map<TestScenario, ScenarioValidationResult>((scenario: TestScenario): ScenarioValidationResult => validateScenario(formSpec, pathway, scenario, maxDepth), scenarios);
226
- const deadEnds: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r: ScenarioValidationResult): boolean => r.DeadEndDetected, results);
227
- const infiniteLoops: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_1: ScenarioValidationResult): boolean => r_1.InfiniteLoopDetected, results);
228
- const overComplex: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_2: ScenarioValidationResult): boolean => r_2.MaxDepthExceeded, results);
229
- const valid: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_3: ScenarioValidationResult): boolean => {
230
- if (!r_3.DeadEndDetected && !r_3.InfiniteLoopDetected) {
231
- return !r_3.MaxDepthExceeded;
232
- }
233
- else {
234
- return false;
235
- }
236
- }, results);
237
- const errors: FSharpList<string> = List_distinct<string>(choose<ScenarioValidationResult, string>((r_4: ScenarioValidationResult): Option<string> => r_4.Error, results), {
238
- Equals: (x: string, y: string): boolean => (x === y),
239
- GetHashCode: stringHash,
240
- });
241
- return new PathwayValidationResult(length(scenarios), length(valid), deadEnds, infiniteLoops, overComplex, errors);
242
- }
243
-
244
- //# sourceMappingURL=PathwayValidator.ts.map
1
+ import { Record } from "@fable-org/fable-library-js/Types.js";
2
+ import { tryFind, fold, toList, ofList, FSharpMap } from "@fable-org/fable-library-js/Map.js";
3
+ import { ClinicalPathway_StateDefinition, Shared_FieldValue_Single, Shared_FieldAnswer, Shared_FieldValue_Matrix, Shared_MatrixAnswer, Shared_MatrixItemKey, Shared_FieldValue_$union, Spec_FormSpec$1, Spec_FormStep$1, ClinicalPathway_ClinicalPathwaySpec, ClinicalPathway_TransitionDefinition, ClinicalPathway_TransitionCondition_$union, Spec_FormField$1, Shared_FieldOption, Spec_FieldType_$union, Shared_StateKey_$reflection, Shared_StateKey, Shared_FieldKey_$reflection, Shared_FieldKey } from "./FormSpec.js";
4
+ import { stringHash, safeHash, compare, equals, IComparable, IEquatable } from "@fable-org/fable-library-js/Util.js";
5
+ import { option_type, list_type, int32_type, bool_type, record_type, class_type, string_type, TypeInfo } from "@fable-org/fable-library-js/Reflection.js";
6
+ import { ofList as ofList_1, intersect, isEmpty as isEmpty_1, empty as empty_1, FSharpSet } from "@fable-org/fable-library-js/Set.js";
7
+ import { int32 } from "@fable-org/fable-library-js/Int32.js";
8
+ import { reverse, choose, take, length, zip, mapIndexed, head as head_1, cons, tail as tail_1, collect, isEmpty, filter, exists, empty, singleton, ofArray, map, FSharpList } from "@fable-org/fable-library-js/List.js";
9
+ import { isExecutionComplete, ExecutionContext, initializeExecution, executeStep, ExecutionLogEntry_$reflection, ExecutionLogEntry } from "./PathwayExecutor.js";
10
+ import { map as map_1, defaultArg, value as value_2, Option } from "@fable-org/fable-library-js/Option.js";
11
+ import { substring, join } from "@fable-org/fable-library-js/String.js";
12
+ import { findStepIndexForField, updateField } from "./FormSpecValues.js";
13
+ import { newGuid } from "@fable-org/fable-library-js/Guid.js";
14
+ import { List_distinct, List_groupBy } from "@fable-org/fable-library-js/Seq2.js";
15
+ import { min } from "@fable-org/fable-library-js/Double.js";
16
+
17
+ export class TestScenario extends Record implements IEquatable<TestScenario>, IComparable<TestScenario> {
18
+ readonly ScenarioId: string;
19
+ readonly FieldValues: FSharpMap<Shared_FieldKey, string>;
20
+ readonly Description: string;
21
+ constructor(ScenarioId: string, FieldValues: FSharpMap<Shared_FieldKey, string>, Description: string) {
22
+ super();
23
+ this.ScenarioId = ScenarioId;
24
+ this.FieldValues = FieldValues;
25
+ this.Description = Description;
26
+ }
27
+ }
28
+
29
+ export function TestScenario_$reflection(): TypeInfo {
30
+ return record_type("F1.Studio.PathwayValidator.TestScenario", [], TestScenario, () => [["ScenarioId", string_type], ["FieldValues", class_type("Microsoft.FSharp.Collections.FSharpMap`2", [Shared_FieldKey_$reflection(), string_type])], ["Description", string_type]]);
31
+ }
32
+
33
+ export class ScenarioValidationResult extends Record implements IEquatable<ScenarioValidationResult>, IComparable<ScenarioValidationResult> {
34
+ readonly Scenario: TestScenario;
35
+ readonly ReachedTerminal: boolean;
36
+ readonly FinalStates: FSharpSet<Shared_StateKey>;
37
+ readonly ExecutionComplete: boolean;
38
+ readonly DeadEndDetected: boolean;
39
+ readonly InfiniteLoopDetected: boolean;
40
+ readonly MaxDepthExceeded: boolean;
41
+ readonly ExecutionIterations: int32;
42
+ readonly ExecutionLog: FSharpList<ExecutionLogEntry>;
43
+ readonly Error: Option<string>;
44
+ constructor(Scenario: TestScenario, ReachedTerminal: boolean, FinalStates: FSharpSet<Shared_StateKey>, ExecutionComplete: boolean, DeadEndDetected: boolean, InfiniteLoopDetected: boolean, MaxDepthExceeded: boolean, ExecutionIterations: int32, ExecutionLog: FSharpList<ExecutionLogEntry>, Error$: Option<string>) {
45
+ super();
46
+ this.Scenario = Scenario;
47
+ this.ReachedTerminal = ReachedTerminal;
48
+ this.FinalStates = FinalStates;
49
+ this.ExecutionComplete = ExecutionComplete;
50
+ this.DeadEndDetected = DeadEndDetected;
51
+ this.InfiniteLoopDetected = InfiniteLoopDetected;
52
+ this.MaxDepthExceeded = MaxDepthExceeded;
53
+ this.ExecutionIterations = (ExecutionIterations | 0);
54
+ this.ExecutionLog = ExecutionLog;
55
+ this.Error = Error$;
56
+ }
57
+ }
58
+
59
+ export function ScenarioValidationResult_$reflection(): TypeInfo {
60
+ return record_type("F1.Studio.PathwayValidator.ScenarioValidationResult", [], ScenarioValidationResult, () => [["Scenario", TestScenario_$reflection()], ["ReachedTerminal", bool_type], ["FinalStates", class_type("Microsoft.FSharp.Collections.FSharpSet`1", [Shared_StateKey_$reflection()])], ["ExecutionComplete", bool_type], ["DeadEndDetected", bool_type], ["InfiniteLoopDetected", bool_type], ["MaxDepthExceeded", bool_type], ["ExecutionIterations", int32_type], ["ExecutionLog", list_type(ExecutionLogEntry_$reflection())], ["Error", option_type(string_type)]]);
61
+ }
62
+
63
+ export class PathwayValidationResult extends Record implements IEquatable<PathwayValidationResult>, IComparable<PathwayValidationResult> {
64
+ readonly TotalScenarios: int32;
65
+ readonly ValidScenarios: int32;
66
+ readonly DeadEndScenarios: FSharpList<ScenarioValidationResult>;
67
+ readonly InfiniteLoopScenarios: FSharpList<ScenarioValidationResult>;
68
+ readonly OverComplexScenarios: FSharpList<ScenarioValidationResult>;
69
+ readonly Errors: FSharpList<string>;
70
+ constructor(TotalScenarios: int32, ValidScenarios: int32, DeadEndScenarios: FSharpList<ScenarioValidationResult>, InfiniteLoopScenarios: FSharpList<ScenarioValidationResult>, OverComplexScenarios: FSharpList<ScenarioValidationResult>, Errors: FSharpList<string>) {
71
+ super();
72
+ this.TotalScenarios = (TotalScenarios | 0);
73
+ this.ValidScenarios = (ValidScenarios | 0);
74
+ this.DeadEndScenarios = DeadEndScenarios;
75
+ this.InfiniteLoopScenarios = InfiniteLoopScenarios;
76
+ this.OverComplexScenarios = OverComplexScenarios;
77
+ this.Errors = Errors;
78
+ }
79
+ }
80
+
81
+ export function PathwayValidationResult_$reflection(): TypeInfo {
82
+ return record_type("F1.Studio.PathwayValidator.PathwayValidationResult", [], PathwayValidationResult, () => [["TotalScenarios", int32_type], ["ValidScenarios", int32_type], ["DeadEndScenarios", list_type(ScenarioValidationResult_$reflection())], ["InfiniteLoopScenarios", list_type(ScenarioValidationResult_$reflection())], ["OverComplexScenarios", list_type(ScenarioValidationResult_$reflection())], ["Errors", list_type(string_type)]]);
83
+ }
84
+
85
+ function getFieldPossibleValues(field: Spec_FormField$1<Spec_FieldType_$union>): FSharpList<string> {
86
+ const matchValue: Spec_FieldType_$union = field.FieldType;
87
+ switch (matchValue.tag) {
88
+ case /* SingleChoice */ 13:
89
+ return map<Shared_FieldOption, string>((opt: Shared_FieldOption): string => opt.Value, matchValue.fields[0].Options);
90
+ case /* MultiChoice */ 15:
91
+ return map<Shared_FieldOption, string>((opt_1: Shared_FieldOption): string => opt_1.Value, matchValue.fields[0].Options);
92
+ case /* CheckboxList */ 16:
93
+ return map<Shared_FieldOption, string>((opt_2: Shared_FieldOption): string => opt_2.Value, matchValue.fields[0].Options);
94
+ case /* Dropdown */ 14:
95
+ return map<Shared_FieldOption, string>((opt_3: Shared_FieldOption): string => opt_3.Value, matchValue.fields[0].Options);
96
+ case /* Radio */ 12:
97
+ return map<Shared_FieldOption, string>((opt_4: Shared_FieldOption): string => opt_4.Value, matchValue.fields[0].Options);
98
+ case /* Matrix */ 19:
99
+ return map<Shared_FieldOption, string>((opt_5: Shared_FieldOption): string => opt_5.Value, matchValue.fields[0].Options);
100
+ case /* Checkbox */ 11:
101
+ return ofArray(["true", "false"]);
102
+ case /* Number */ 6:
103
+ return ofArray(["0", "1", "10", "100"]);
104
+ case /* Text */ 0:
105
+ case /* TextArea */ 1:
106
+ return singleton("");
107
+ default:
108
+ return empty<string>();
109
+ }
110
+ }
111
+
112
+ function isFieldRelevantForPathway(field: Spec_FormField$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec): boolean {
113
+ const fieldKey: Shared_FieldKey = field.FieldKey;
114
+ return exists<ClinicalPathway_TransitionDefinition>((trans: ClinicalPathway_TransitionDefinition): boolean => {
115
+ const conditionUsesField = (cond: ClinicalPathway_TransitionCondition_$union): boolean => {
116
+ switch (cond.tag) {
117
+ case /* FieldCondition */ 0:
118
+ return equals(cond.fields[0], fieldKey);
119
+ case /* FieldOptionCondition */ 1:
120
+ return equals(cond.fields[0], fieldKey);
121
+ case /* PluginPropertyCondition */ 2:
122
+ return equals(cond.fields[0], fieldKey);
123
+ case /* ScoreInRange */ 3:
124
+ return false;
125
+ case /* FieldScoreInRange */ 4:
126
+ return equals(cond.fields[0], fieldKey);
127
+ case /* StateCondition */ 5:
128
+ return false;
129
+ case /* CompositeCondition */ 6:
130
+ return exists<ClinicalPathway_TransitionCondition_$union>(conditionUsesField, cond.fields[1]);
131
+ case /* TestResultCondition */ 7:
132
+ return false;
133
+ default:
134
+ return false;
135
+ }
136
+ };
137
+ return conditionUsesField(trans.Condition);
138
+ }, pathway.Transitions);
139
+ }
140
+
141
+ /**
142
+ * Generate test scenarios for pathway validation
143
+ * Strategy: Only generate scenarios for fields that are actually used in pathway conditions
144
+ * For Likert fields, generate scenarios for each item independently
145
+ */
146
+ export function generateTestScenarios(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, maxScenarios: Option<int32>): FSharpList<TestScenario> {
147
+ let max: int32, max_1: int32;
148
+ const fieldValueOptions: FSharpList<[Shared_FieldKey, FSharpList<string>]> = filter<[Shared_FieldKey, FSharpList<string>]>((tupledArg: [Shared_FieldKey, FSharpList<string>]): boolean => !isEmpty(tupledArg[1]), map<Spec_FormField$1<Spec_FieldType_$union>, [Shared_FieldKey, FSharpList<string>]>((field_1: Spec_FormField$1<Spec_FieldType_$union>): [Shared_FieldKey, FSharpList<string>] => ([field_1.FieldKey, getFieldPossibleValues(field_1)] as [Shared_FieldKey, FSharpList<string>]), filter<Spec_FormField$1<Spec_FieldType_$union>>((field: Spec_FormField$1<Spec_FieldType_$union>): boolean => isFieldRelevantForPathway(field, pathway), collect<Spec_FormStep$1<Spec_FieldType_$union>, Spec_FormField$1<Spec_FieldType_$union>>((step: Spec_FormStep$1<Spec_FieldType_$union>): FSharpList<Spec_FormField$1<Spec_FieldType_$union>> => step.Fields, formSpec.Steps))));
149
+ const cartesianProduct = <a>(lists: FSharpList<FSharpList<a>>): FSharpList<FSharpList<a>> => {
150
+ if (!isEmpty(lists)) {
151
+ const tailProducts: FSharpList<FSharpList<a>> = cartesianProduct(tail_1(lists));
152
+ return collect<a, FSharpList<a>>((h: a): FSharpList<FSharpList<a>> => map<FSharpList<a>, FSharpList<a>>((t: FSharpList<a>): FSharpList<a> => cons(h, t), tailProducts), head_1(lists));
153
+ }
154
+ else {
155
+ return singleton(empty<a>());
156
+ }
157
+ };
158
+ const allCombinations: FSharpList<FSharpList<string>> = cartesianProduct(map<[Shared_FieldKey, FSharpList<string>], FSharpList<string>>((tuple: [Shared_FieldKey, FSharpList<string>]): FSharpList<string> => tuple[1], fieldValueOptions));
159
+ return mapIndexed<FSharpList<string>, TestScenario>((index: int32, combination: FSharpList<string>): TestScenario => {
160
+ const fieldValues: FSharpMap<Shared_FieldKey, string> = ofList<Shared_FieldKey, string>(map<[[Shared_FieldKey, FSharpList<string>], string], [Shared_FieldKey, string]>((tupledArg_1: [[Shared_FieldKey, FSharpList<string>], string]): [Shared_FieldKey, string] => ([tupledArg_1[0][0], tupledArg_1[1]] as [Shared_FieldKey, string]), zip<[Shared_FieldKey, FSharpList<string>], string>(fieldValueOptions, combination)), {
161
+ Compare: compare,
162
+ });
163
+ return new TestScenario(`scenario_${index + 1}`, fieldValues, join(", ", map<[Shared_FieldKey, string], string>((tupledArg_2: [Shared_FieldKey, string]): string => (`${substring(tupledArg_2[0].fields[0], 0, 8)}=${tupledArg_2[1]}`), toList<Shared_FieldKey, string>(fieldValues))));
164
+ }, (maxScenarios != null) ? (((max = (value_2(maxScenarios) | 0), length(allCombinations) > max)) ? ((max_1 = (value_2(maxScenarios) | 0), take<FSharpList<string>>(max_1, allCombinations))) : allCombinations) : allCombinations);
165
+ }
166
+
167
+ function scenarioToFormSpec(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, scenario: TestScenario): Spec_FormSpec$1<Spec_FieldType_$union> {
168
+ return fold<Shared_FieldKey, Shared_FieldValue_$union, Spec_FormSpec$1<Spec_FieldType_$union>>((spec: Spec_FormSpec$1<Spec_FieldType_$union>, fieldKey: Shared_FieldKey, fieldValue_1: Shared_FieldValue_$union): Spec_FormSpec$1<Spec_FieldType_$union> => defaultArg(map_1<int32, Spec_FormSpec$1<Spec_FieldType_$union>>((stepIdx: int32): Spec_FormSpec$1<Spec_FieldType_$union> => updateField<Spec_FieldType_$union>(spec, fieldKey, fieldValue_1, stepIdx), findStepIndexForField<Spec_FieldType_$union>(spec, fieldKey)), spec), formSpec, ofList<Shared_FieldKey, Shared_FieldValue_$union>(choose<Spec_FormField$1<Spec_FieldType_$union>, [Shared_FieldKey, Shared_FieldValue_$union]>((field: Spec_FormField$1<Spec_FieldType_$union>): Option<[Shared_FieldKey, Shared_FieldValue_$union]> => map_1<string, [Shared_FieldKey, Shared_FieldValue_$union]>((value: string): [Shared_FieldKey, Shared_FieldValue_$union] => ([field.FieldKey, (field.FieldType.tag === /* Matrix */ 19) ? Shared_FieldValue_Matrix(new Shared_MatrixAnswer(field.FieldKey, field.Label, ofList<Shared_MatrixItemKey, string>(map<Shared_MatrixItemKey, [Shared_MatrixItemKey, string]>((itemKey: Shared_MatrixItemKey): [Shared_MatrixItemKey, string] => ([itemKey, value] as [Shared_MatrixItemKey, string]), singleton(new Shared_MatrixItemKey(newGuid()))), {
169
+ Compare: compare,
170
+ }))) : Shared_FieldValue_Single(new Shared_FieldAnswer(field.FieldKey, field.Label, value))] as [Shared_FieldKey, Shared_FieldValue_$union]), tryFind<Shared_FieldKey, string>(field.FieldKey, scenario.FieldValues)), collect<Spec_FormStep$1<Spec_FieldType_$union>, Spec_FormField$1<Spec_FieldType_$union>>((step: Spec_FormStep$1<Spec_FieldType_$union>): FSharpList<Spec_FormField$1<Spec_FieldType_$union>> => step.Fields, formSpec.Steps)), {
171
+ Compare: compare,
172
+ }));
173
+ }
174
+
175
+ function isTerminalState(state: ClinicalPathway_StateDefinition): boolean {
176
+ if (state.StateType.tag === /* Terminal */ 5) {
177
+ return true;
178
+ }
179
+ else {
180
+ return false;
181
+ }
182
+ }
183
+
184
+ function detectInfiniteLoop(executionLog: FSharpList<ExecutionLogEntry>, maxDepth: int32): boolean {
185
+ let list_1: FSharpList<ExecutionLogEntry>;
186
+ if (length(executionLog) > maxDepth) {
187
+ return exists<[Shared_StateKey, int32]>((tupledArg_1: [Shared_StateKey, int32]): boolean => (tupledArg_1[1] >= 3), map<[Shared_StateKey, FSharpList<Shared_StateKey>], [Shared_StateKey, int32]>((tupledArg: [Shared_StateKey, FSharpList<Shared_StateKey>]): [Shared_StateKey, int32] => ([tupledArg[0], length(tupledArg[1])] as [Shared_StateKey, int32]), List_groupBy<Shared_StateKey, Shared_StateKey>((x: Shared_StateKey): Shared_StateKey => x, map<ExecutionLogEntry, Shared_StateKey>((log: ExecutionLogEntry): Shared_StateKey => log.StateKey, (list_1 = reverse<ExecutionLogEntry>(executionLog), take<ExecutionLogEntry>(min(20, length(executionLog)), list_1))), {
188
+ Equals: equals,
189
+ GetHashCode: safeHash,
190
+ })));
191
+ }
192
+ else {
193
+ return false;
194
+ }
195
+ }
196
+
197
+ function validateScenario(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, scenario: TestScenario, maxDepth: int32): ScenarioValidationResult {
198
+ try {
199
+ const finalContext: ExecutionContext = executeStep(initializeExecution(scenarioToFormSpec(formSpec, scenario)), maxDepth);
200
+ const reachedTerminal: boolean = !isEmpty_1<Shared_StateKey>(intersect<Shared_StateKey>(ofList_1<Shared_StateKey>(map<ClinicalPathway_StateDefinition, Shared_StateKey>((s: ClinicalPathway_StateDefinition): Shared_StateKey => s.StateKey, filter<ClinicalPathway_StateDefinition>(isTerminalState, pathway.States)), {
201
+ Compare: compare,
202
+ }), finalContext.CurrentStates));
203
+ const isComplete: boolean = isExecutionComplete(finalContext);
204
+ const infiniteLoopDetected: boolean = detectInfiniteLoop(finalContext.ExecutionLog, maxDepth);
205
+ return new ScenarioValidationResult(scenario, reachedTerminal, finalContext.CurrentStates, isComplete, (((!isComplete && !reachedTerminal) && isEmpty(finalContext.ActiveTransitions)) && isEmpty(finalContext.PendingTransitions)) && !infiniteLoopDetected, infiniteLoopDetected, (length(finalContext.ExecutionLog) >= maxDepth) && !isComplete, length(finalContext.ExecutionLog), finalContext.ExecutionLog, undefined);
206
+ }
207
+ catch (ex: any) {
208
+ return new ScenarioValidationResult(scenario, false, empty_1<Shared_StateKey>({
209
+ Compare: compare,
210
+ }), false, true, false, false, 0, empty<ExecutionLogEntry>(), ex.message);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Validate pathway for dead-end scenarios, infinite loops, and overcomplexity
216
+ */
217
+ export function validatePathwayCompleteness(formSpec: Spec_FormSpec$1<Spec_FieldType_$union>, pathway: ClinicalPathway_ClinicalPathwaySpec, maxScenarios: Option<int32>, maxDepth: int32): PathwayValidationResult {
218
+ const scenarios: FSharpList<TestScenario> = generateTestScenarios(formSpec, pathway, maxScenarios);
219
+ const results: FSharpList<ScenarioValidationResult> = map<TestScenario, ScenarioValidationResult>((scenario: TestScenario): ScenarioValidationResult => validateScenario(formSpec, pathway, scenario, maxDepth), scenarios);
220
+ const deadEnds: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r: ScenarioValidationResult): boolean => r.DeadEndDetected, results);
221
+ const infiniteLoops: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_1: ScenarioValidationResult): boolean => r_1.InfiniteLoopDetected, results);
222
+ const overComplex: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_2: ScenarioValidationResult): boolean => r_2.MaxDepthExceeded, results);
223
+ const valid: FSharpList<ScenarioValidationResult> = filter<ScenarioValidationResult>((r_3: ScenarioValidationResult): boolean => {
224
+ if (!r_3.DeadEndDetected && !r_3.InfiniteLoopDetected) {
225
+ return !r_3.MaxDepthExceeded;
226
+ }
227
+ else {
228
+ return false;
229
+ }
230
+ }, results);
231
+ const errors: FSharpList<string> = List_distinct<string>(choose<ScenarioValidationResult, string>((r_4: ScenarioValidationResult): Option<string> => r_4.Error, results), {
232
+ Equals: (x: string, y: string): boolean => (x === y),
233
+ GetHashCode: stringHash,
234
+ });
235
+ return new PathwayValidationResult(length(scenarios), length(valid), deadEnds, infiniteLoops, overComplex, errors);
236
+ }
237
+
238
+ //# sourceMappingURL=PathwayValidator.ts.map