@things-factory/dataset 8.0.0-beta.1 → 8.0.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. package/package.json +13 -13
  2. package/client/activities/activity-data-collect-edit.ts +0 -105
  3. package/client/activities/activity-data-collect-view.ts +0 -91
  4. package/client/activities/activity-data-review-edit.ts +0 -133
  5. package/client/activities/activity-data-review-view.ts +0 -145
  6. package/client/activities/activity-ooc-resolve-edit.ts +0 -195
  7. package/client/activities/activity-ooc-resolve-view.ts +0 -143
  8. package/client/activities/activity-ooc-review-edit.ts +0 -173
  9. package/client/activities/activity-ooc-review-view.ts +0 -129
  10. package/client/bootstrap.ts +0 -35
  11. package/client/components/data-entry-form.ts +0 -109
  12. package/client/index.ts +0 -1
  13. package/client/pages/data-archive/data-archive-list-page.ts +0 -277
  14. package/client/pages/data-archive/data-archive-request-popup.ts +0 -177
  15. package/client/pages/data-entry/data-entry-list-page.ts +0 -464
  16. package/client/pages/data-key-set/data-key-item-list.ts +0 -183
  17. package/client/pages/data-key-set/data-key-set-importer.ts +0 -89
  18. package/client/pages/data-key-set/data-key-set-list-page.ts +0 -413
  19. package/client/pages/data-ooc/data-ooc-list-page.ts +0 -549
  20. package/client/pages/data-ooc/data-ooc-page.ts +0 -164
  21. package/client/pages/data-ooc/data-ooc-view.ts +0 -236
  22. package/client/pages/data-ooc/data-oocs-page.ts +0 -200
  23. package/client/pages/data-report/data-report-embed-page.ts +0 -108
  24. package/client/pages/data-report/data-report-list-page.ts +0 -454
  25. package/client/pages/data-report/data-report-samples-page.ts +0 -174
  26. package/client/pages/data-report/jasper-report-oocs-page.ts +0 -110
  27. package/client/pages/data-report/jasper-report-samples-crosstab-page.ts +0 -110
  28. package/client/pages/data-report/jasper-report-samples-page.ts +0 -110
  29. package/client/pages/data-sample/data-sample-list-page.ts +0 -442
  30. package/client/pages/data-sample/data-sample-page.ts +0 -55
  31. package/client/pages/data-sample/data-sample-search-page.ts +0 -424
  32. package/client/pages/data-sample/data-sample-view.ts +0 -292
  33. package/client/pages/data-sample/data-samples-page.ts +0 -249
  34. package/client/pages/data-sensor/data-sensor-list-page.ts +0 -456
  35. package/client/pages/data-set/data-item-list.ts +0 -304
  36. package/client/pages/data-set/data-set-importer.ts +0 -89
  37. package/client/pages/data-set/data-set-list-page.ts +0 -1078
  38. package/client/pages/data-summary/data-summary-list-page.ts +0 -363
  39. package/client/pages/data-summary/data-summary-period-page.ts +0 -439
  40. package/client/pages/data-summary/data-summary-search-page.ts +0 -426
  41. package/client/pages/data-summary/data-summary-view.ts +0 -133
  42. package/client/route.ts +0 -91
  43. package/client/tsconfig.json +0 -13
  44. package/server/activities/activity-data-collect.ts +0 -100
  45. package/server/activities/activity-data-review.ts +0 -82
  46. package/server/activities/activity-ooc-resolve.ts +0 -123
  47. package/server/activities/activity-ooc-review.ts +0 -144
  48. package/server/activities/index.ts +0 -11
  49. package/server/controllers/create-data-sample.ts +0 -426
  50. package/server/controllers/data-use-case.ts +0 -98
  51. package/server/controllers/finalize-data-collection.ts +0 -388
  52. package/server/controllers/index.ts +0 -3
  53. package/server/controllers/issue-data-collection-task.ts +0 -70
  54. package/server/controllers/jasper-report.ts +0 -186
  55. package/server/controllers/query-data-summary-by-period.ts +0 -178
  56. package/server/controllers/shiny-report.ts +0 -54
  57. package/server/engine/index.ts +0 -1
  58. package/server/engine/task/create-data-sample.ts +0 -100
  59. package/server/engine/task/index.ts +0 -2
  60. package/server/engine/task/issue-collect-data.ts +0 -45
  61. package/server/index.ts +0 -8
  62. package/server/routes.ts +0 -188
  63. package/server/service/data-archive/data-archive-mutation.ts +0 -273
  64. package/server/service/data-archive/data-archive-query.ts +0 -58
  65. package/server/service/data-archive/data-archive-type.ts +0 -48
  66. package/server/service/data-archive/data-archive.ts +0 -69
  67. package/server/service/data-archive/index.ts +0 -6
  68. package/server/service/data-key-set/data-key-item-type.ts +0 -31
  69. package/server/service/data-key-set/data-key-set-mutation.ts +0 -201
  70. package/server/service/data-key-set/data-key-set-query.ts +0 -68
  71. package/server/service/data-key-set/data-key-set-type.ts +0 -70
  72. package/server/service/data-key-set/data-key-set.ts +0 -86
  73. package/server/service/data-key-set/index.ts +0 -6
  74. package/server/service/data-ooc/data-ooc-mutation.ts +0 -154
  75. package/server/service/data-ooc/data-ooc-query.ts +0 -106
  76. package/server/service/data-ooc/data-ooc-subscription.ts +0 -48
  77. package/server/service/data-ooc/data-ooc-type.ts +0 -71
  78. package/server/service/data-ooc/data-ooc.ts +0 -259
  79. package/server/service/data-ooc/index.ts +0 -7
  80. package/server/service/data-sample/data-sample-mutation.ts +0 -18
  81. package/server/service/data-sample/data-sample-query.ts +0 -215
  82. package/server/service/data-sample/data-sample-type.ts +0 -47
  83. package/server/service/data-sample/data-sample.ts +0 -193
  84. package/server/service/data-sample/index.ts +0 -6
  85. package/server/service/data-sensor/data-sensor-mutation.ts +0 -116
  86. package/server/service/data-sensor/data-sensor-query.ts +0 -76
  87. package/server/service/data-sensor/data-sensor-type.ts +0 -104
  88. package/server/service/data-sensor/data-sensor.ts +0 -126
  89. package/server/service/data-sensor/index.ts +0 -6
  90. package/server/service/data-set/data-item-type.ts +0 -155
  91. package/server/service/data-set/data-set-mutation.ts +0 -552
  92. package/server/service/data-set/data-set-query.ts +0 -461
  93. package/server/service/data-set/data-set-type.ts +0 -204
  94. package/server/service/data-set/data-set.ts +0 -326
  95. package/server/service/data-set/index.ts +0 -6
  96. package/server/service/data-set-history/data-set-history-query.ts +0 -126
  97. package/server/service/data-set-history/data-set-history-type.ts +0 -12
  98. package/server/service/data-set-history/data-set-history.ts +0 -217
  99. package/server/service/data-set-history/event-subscriber.ts +0 -17
  100. package/server/service/data-set-history/index.ts +0 -7
  101. package/server/service/data-spec/data-spec-manager.ts +0 -21
  102. package/server/service/data-spec/data-spec-query.ts +0 -21
  103. package/server/service/data-spec/data-spec.ts +0 -45
  104. package/server/service/data-spec/index.ts +0 -5
  105. package/server/service/data-summary/data-summary-mutation.ts +0 -45
  106. package/server/service/data-summary/data-summary-query.ts +0 -179
  107. package/server/service/data-summary/data-summary-type.ts +0 -86
  108. package/server/service/data-summary/data-summary.ts +0 -170
  109. package/server/service/data-summary/index.ts +0 -7
  110. package/server/service/index.ts +0 -57
  111. package/server/tsconfig.json +0 -10
  112. package/server/utils/config-resolver.ts +0 -29
  113. package/server/utils/index.ts +0 -1
@@ -1,426 +0,0 @@
1
- import moment from 'moment-timezone'
2
- import { In } from 'typeorm'
3
-
4
- import { Attachment, createAttachment } from '@things-factory/attachment-base'
5
- import { Role } from '@things-factory/auth-base'
6
- import { logger } from '@things-factory/env'
7
- import { getRedirectSubdomainPath, pubsub } from '@things-factory/shell'
8
- import { getWorkDateAndShift } from '@things-factory/work-shift'
9
- import { Scenario, publishData } from '@things-factory/integration-base'
10
- import { Activity } from '@things-factory/worklist'
11
- import { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'
12
-
13
- import { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc'
14
- import { DataSample } from '../service/data-sample/data-sample'
15
- import { NewDataSample } from '../service/data-sample/data-sample-type'
16
- import { DataSet } from '../service/data-set/data-set'
17
- import { DataUseCase } from './data-use-case'
18
-
19
- // See README.md at ## Data Samples
20
- process.env.TZ = 'UTC'
21
-
22
- const fillDataKeys = (dataKeySet, data = {}) => {
23
- const keys = dataKeySet?.dataKeyItems || []
24
- return keys.reduce((sum, key, index) => {
25
- const value = data[key.dataKey]
26
- if (value != null) {
27
- sum[`key0${index + 1}`] = value instanceof Array ? value[0] : value
28
- }
29
- return sum
30
- }, {})
31
- }
32
-
33
- // parse variable javascript string pattern
34
- const replaceVariables = (keys, dic) => {
35
- for (const k in keys) {
36
- const matches = keys[k].match(/\$\{\w*\}/g)
37
- matches &&
38
- matches.forEach(m => {
39
- keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])
40
- })
41
- }
42
- return keys
43
- }
44
-
45
- // It is required UTC date for Partitioning File System like AWS S3 from Athena.
46
- // ex) %YYYY, %MM, %DD
47
- const formatDate = (keys, _moment) => {
48
- for (const k in keys) {
49
- const matches = keys[k].match(/%\w*/g)
50
- matches &&
51
- matches.forEach(m => {
52
- keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))
53
- })
54
- }
55
- return keys
56
- }
57
-
58
- export async function createDataSample(newDataSample: NewDataSample, context: ResolverContext): Promise<DataSample> {
59
- const { domain, user, tx } = context.state
60
-
61
- const dataSet = await tx.getRepository(DataSet).findOne({
62
- where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: newDataSample.dataSet.id },
63
- relations: ['dataKeySet']
64
- })
65
-
66
- const { dataItems = [], tag: publishTag, normalScenarioId, outlierScenarioId } = dataSet
67
- const collectedAt = newDataSample.collectedAt || new Date()
68
-
69
- const timezone = dataSet.timezone || domain.timezone || 'UTC'
70
- const format = 'YYYY-MM-DD'
71
-
72
- // workDate ex) 2022-04-04
73
- const { workDate, workShift } = await getWorkDateAndShift(domain, collectedAt, { timezone, format })
74
-
75
- // local time dataSet timezone or domain timezone or default 'UTC'
76
-
77
- const localDateTz = moment(collectedAt).tz(timezone)
78
- const defaultPartitionKeys = {
79
- domain: domain.subdomain,
80
- datasetid: newDataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,
81
- date: localDateTz.format(format) /* local time date */,
82
- workdate: workDate /* working date */,
83
- workshift: workShift
84
- }
85
-
86
- var partitionKeys = {
87
- ...defaultPartitionKeys,
88
- ...dataSet.partitionKeys
89
- }
90
-
91
- partitionKeys = formatDate(partitionKeys, localDateTz)
92
- partitionKeys = replaceVariables(partitionKeys, newDataSample.data)
93
-
94
- const dataKeys = fillDataKeys(dataSet?.dataKeySet, newDataSample.data)
95
-
96
- const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems, newDataSample.data) || {}
97
-
98
- const old = await tx.getRepository(DataSample).findOne({
99
- where: {
100
- domain: { id: domain.id },
101
- dataSet: { id: dataSet.id },
102
- collectedAt,
103
- ...dataKeys
104
- }
105
- })
106
-
107
- /*
108
- pre-processing for file attachment.
109
- currently only support type of [FileUpload].
110
- If [FileUpload[]] type needed, add 'files' type for dataset
111
- */
112
-
113
- const data = newDataSample.data
114
- const attachments = []
115
-
116
- for (let dataItem of dataItems) {
117
- if (dataItem.type == 'file') {
118
- const tag = dataItem.tag
119
- const filesArray = data[tag]
120
-
121
- if (tag && filesArray && filesArray.length > 0) {
122
- let pathsArray = []
123
-
124
- for (let files of filesArray) {
125
- let paths = []
126
-
127
- if (files instanceof Array) {
128
- for (let file of files) {
129
- if (file) {
130
- const attachment = await createAttachment(
131
- null,
132
- {
133
- attachment: {
134
- file: file.file,
135
- refType: DataSample.name
136
- }
137
- },
138
- context
139
- )
140
-
141
- const fetched = await tx.getRepository(Attachment).findOneBy({ id: attachment.id })
142
- if (fetched) {
143
- attachments.push(fetched)
144
- paths.push({
145
- id: fetched.id,
146
- mimetype: fetched.mimetype,
147
- name: fetched.name,
148
- fullpath: fetched.fullpath
149
- })
150
- } else {
151
- throw `Failed to save file(${attachment.name})`
152
- }
153
- } else {
154
- paths.push(null)
155
- }
156
- }
157
- }
158
-
159
- pathsArray.push(paths)
160
- }
161
-
162
- data[tag] = pathsArray
163
- }
164
- }
165
- }
166
-
167
- const dataSample = await tx.getRepository(DataSample).save({
168
- ...old,
169
- name: dataSet.name,
170
- description: dataSet.description,
171
- useCase: dataSet.useCase,
172
- type: dataSet.type,
173
- ...newDataSample,
174
- ...dataKeys,
175
- dataSetVersion: dataSet.version,
176
- domain,
177
- partitionKeys,
178
- ooc,
179
- oos,
180
- judgment,
181
- collectedAt,
182
- workDate,
183
- workShift,
184
- creator: user,
185
- updater: user
186
- })
187
-
188
- if (publishTag) {
189
- publishData(publishTag, data, { domain, user })
190
- }
191
-
192
- /* post-process for for file attachment. */
193
- if (attachments.length > 0) {
194
- attachments.forEach(attachment => (attachment.refId = dataSample.id))
195
- tx.getRepository(Attachment).save(attachments)
196
- }
197
-
198
- if (ooc || oos) {
199
- const dataOoc = await tx.getRepository(DataOoc).save({
200
- ...dataSample,
201
- history: [
202
- {
203
- user: {
204
- id: user?.id,
205
- name: user?.name
206
- },
207
- state: DataOocStatus.ISSUED,
208
- timestamp: collectedAt
209
- }
210
- ],
211
- state: DataOocStatus.ISSUED,
212
- dataSample: dataSample
213
- })
214
-
215
- if (outlierScenarioId) {
216
- const scenario = await tx.getRepository(Scenario).findOne({
217
- where: {
218
- domain: domain.parentId ? { id: In([domain.id, domain.parentId]) } : { id: domain.id },
219
- id: outlierScenarioId
220
- },
221
- relations: ['domain', 'steps', 'updater']
222
- })
223
-
224
- if (scenario) {
225
- scenario.start({
226
- instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,
227
- domain,
228
- user,
229
- variables: {
230
- dataOocId: dataOoc.id,
231
- dataSampleId: dataSample.id,
232
- dataSet: dataSet.id,
233
- data,
234
- ooc,
235
- oos,
236
- judgment,
237
- collectedAt,
238
- workDate,
239
- workShift,
240
- domain: {
241
- id: domain.id,
242
- subdomain: domain.subdomain,
243
- name: domain.name
244
- },
245
- updator: {
246
- id: user.id,
247
- email: user.email,
248
- name: user.name
249
- }
250
- }
251
- })
252
- } else {
253
- console.error(`Cannot find the set outlier-scenario for the dataset(${dataSet.name}).`)
254
- }
255
- }
256
-
257
- const activity = (await tx.getRepository(Activity).findOneBy({
258
- domain: domain.parentId ? { id: In([domain.id, domain.parentId]) } : { id: domain.id },
259
- name: 'OOC Review'
260
- })) as Activity
261
-
262
- if (activity) {
263
- const assigneeRole =
264
- dataSet.supervisoryRoleId &&
265
- (await tx.getRepository(Role).findOneBy({
266
- domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },
267
- id: dataSet.supervisoryRoleId
268
- }))
269
-
270
- // const assignees = dataSet.supervisoryRoleId
271
- // ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assigneeRole }]
272
- // : []
273
-
274
- /* 해당 dataset의 supervisor로 하여금, OOC를 리뷰하고 instruction을 작성해서, OOC 해결을 위한 태스크를 dataset assignees에게 지시하도록 한다. */
275
- if (assigneeRole) {
276
- const activityInstance = {
277
- name: `[OOC 검토] ${dataSet.name}`,
278
- description: dataSet.description,
279
- activityId: activity.id,
280
- dueAt: new Date(collectedAt.getTime() + (activity.standardTime || 24 * 60 * 60) * 1000),
281
- input: {
282
- dataOocId: dataOoc.id
283
- },
284
- assigneeRole,
285
- threadsMin: 1,
286
- threadsMax: 1,
287
- approvalLine: []
288
- }
289
-
290
- dataOoc.reviewActivityInstance = await issue(activityInstance as any, context)
291
- await tx.getRepository(DataOoc).save(dataOoc)
292
- } else {
293
- console.error(
294
- `Assignees are not set. So Data OOC Review task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`
295
- )
296
- }
297
- } else {
298
- console.warn('OOC Review Activity not installed.')
299
- }
300
-
301
- try {
302
- // pubsub.publish('data-ooc', {
303
- // dataOoc,
304
- // supervisoryRoleId: dataSet.supervisoryRoleId
305
- // })
306
-
307
- pubsub.publish('notification', {
308
- notification: {
309
- domain,
310
- type: 'error',
311
- title: `[OOC] ${dataSet.name}`,
312
- body: `Data OOC occurred on '${dataSet.name}'`,
313
- url: getRedirectSubdomainPath(context, domain.subdomain, `/data-ooc/${dataOoc.id}`),
314
- timestamp: collectedAt
315
- }
316
- })
317
- } catch (err) {
318
- logger.error('Notification', err)
319
- }
320
- } else {
321
- if (normalScenarioId) {
322
- const scenario = await tx.getRepository(Scenario).findOne({
323
- where: {
324
- domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },
325
- id: normalScenarioId
326
- },
327
- relations: ['domain', 'steps', 'updater']
328
- })
329
-
330
- if (scenario) {
331
- scenario.start({
332
- instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,
333
- domain,
334
- user,
335
- variables: {
336
- dataSampleId: dataSample.id,
337
- dataSet: dataSet.id,
338
- data,
339
- ooc,
340
- oos,
341
- judgment,
342
- collectedAt,
343
- workDate,
344
- workShift,
345
- domain: {
346
- id: domain.id,
347
- subdomain: domain.subdomain,
348
- name: domain.name
349
- },
350
- updator: {
351
- id: user.id,
352
- email: user.email,
353
- name: user.name
354
- }
355
- }
356
- })
357
- } else {
358
- console.error(`Cannot find the set normal-scenario for the dataset(${dataSet.name}).`)
359
- }
360
- }
361
-
362
- if (dataSet.requiresReview) {
363
- const activity = (await tx.getRepository(Activity).findOneBy({
364
- domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },
365
- name: 'Data Review'
366
- })) as Activity
367
-
368
- if (activity) {
369
- const assigneeRole =
370
- dataSet.supervisoryRoleId &&
371
- (await tx.getRepository(Role).findOneBy({
372
- domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },
373
- id: dataSet.supervisoryRoleId
374
- }))
375
-
376
- // const assignees = dataSet.supervisoryRoleId
377
- // ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assigneeRole }]
378
- // : []
379
-
380
- /* 해당 dataset의 supervisor로 하여금, data를 리뷰하고 instruction을 작성해서, approvalLine을 이용해서 승인을 한다. */
381
- if (assigneeRole) {
382
- dataSample.dataItems = dataItems
383
- const activityInstance = {
384
- name: `[Data 검토] ${dataSet.name}`,
385
- description: dataSet.description,
386
- activityId: activity.id,
387
- dueAt: new Date(collectedAt.getTime() + (activity.standardTime || 24 * 60 * 60) * 1000),
388
- input: {
389
- dataSampleId: dataSample.id
390
- },
391
- assigneeRole,
392
- threadsMin: 1,
393
- threadsMax: 1,
394
- approvalLine: dataSet.reviewApprovalLine
395
- }
396
-
397
- dataSample.reviewActivityInstance = await issue(activityInstance as any, context)
398
- await tx.getRepository(DataSample).save(dataSample)
399
-
400
- try {
401
- pubsub.publish('notification', {
402
- notification: {
403
- domain,
404
- type: 'info',
405
- title: `[Data Review] ${dataSet.name}`,
406
- body: `Data Review occurred on '${dataSet.name}'`,
407
- url: getRedirectSubdomainPath(context, domain.subdomain, `/data-sample/${dataSample.id}`),
408
- timestamp: collectedAt
409
- }
410
- })
411
- } catch (err) {
412
- logger.error('Notification', err)
413
- }
414
- } else {
415
- console.error(
416
- `Assignees are not set. So Data Review task for ${dataSet.name}(${dataSet.id}) could not be issued.`
417
- )
418
- }
419
- } else {
420
- console.error('Data Review Activity not installed.')
421
- }
422
- }
423
- }
424
-
425
- return dataSample
426
- }
@@ -1,98 +0,0 @@
1
- import { DataItem } from '../service/data-set/data-item-type'
2
- import { DataSet } from '../service/data-set/data-set'
3
-
4
- export type DataItemSpec = {
5
- type: string
6
- label: string
7
- name: string
8
- property?: { [option: string]: any }
9
- }
10
-
11
- export type DataItemSpecSet = {
12
- name: string
13
- description: string
14
- help?: string
15
- specs: DataItemSpec[]
16
- }
17
-
18
- export type EvaluationResult = {
19
- oos: boolean
20
- ooc: boolean
21
- judgment?: { [tag: string]: { ooc: boolean; oos: boolean } }
22
- }
23
-
24
- export abstract class DataUseCase {
25
- static registry: { [name: string]: DataUseCase } = {}
26
-
27
- public static registerUseCase(name: string, provider: DataUseCase) {
28
- DataUseCase.registry[name] = provider
29
- }
30
-
31
- public static getUseCaseNames() {
32
- return Object.keys(DataUseCase.registry)
33
- }
34
-
35
- public static getUseCase(name: string): DataUseCase | undefined {
36
- return DataUseCase.registry[name]
37
- }
38
-
39
- public static evaluate(dataSet: DataSet, dataItems: DataItem[], data: any): EvaluationResult {
40
- var ooc = false
41
- var oos = false
42
- var judgment: { [tag: string]: { ooc: boolean; oos: boolean } } = {}
43
-
44
- if (!dataSet.useCase) {
45
- return { ooc, oos }
46
- }
47
-
48
- const useCaseNames = dataSet.useCase.split(',').map(useCaseName => useCaseName.trim())
49
- const useCases = useCaseNames.map(useCaseName => DataUseCase.getUseCase(useCaseName)).filter(useCase => !!useCase)
50
-
51
- for (let i = 0; i < dataItems.length; i++) {
52
- const dataItem = dataItems[i]
53
- const { active, tag } = dataItem
54
- if (!active || !tag) {
55
- continue
56
- }
57
-
58
- let values: any | any[] = data && data[tag]
59
- if (values == null) {
60
- continue // TODO what if in case no value ?
61
- }
62
-
63
- if (!(values instanceof Array)) {
64
- values = [values]
65
- }
66
-
67
- let oocForTag = false
68
- let oosForTag = false
69
-
70
- for (let j = 0; j < useCases.length; j++) {
71
- const useCase = useCases[j]
72
-
73
- const specs = dataItem.spec?.[dataSet.useCase]
74
- if (!specs) {
75
- continue
76
- }
77
-
78
- const result = useCase.evaluate(specs, values)
79
-
80
- if (result) {
81
- oocForTag ||= result.ooc
82
- oosForTag ||= result.oos
83
- ooc ||= result.ooc
84
- oos ||= result.oos
85
- }
86
- }
87
-
88
- judgment[tag] = {
89
- ooc: oocForTag,
90
- oos: oosForTag
91
- }
92
- }
93
-
94
- return { ooc, oos, judgment }
95
- }
96
-
97
- public abstract evaluate(specs: any, values: any[]): EvaluationResult
98
- }