@uwrl/qc-utils 0.0.13 → 0.0.14

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.
@@ -0,0 +1,2 @@
1
+ import { ObservationRecord } from './utils/plotting/observationRecord';
2
+ export { ObservationRecord, };
package/dist/index.js CHANGED
@@ -1,119 +1,122 @@
1
- const D = `(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
2
- `, b = typeof self < "u" && self.Blob && new Blob([D], { type: "text/javascript;charset=utf-8" });
3
- function X(o) {
1
+ var f = /* @__PURE__ */ ((r) => (r.ADD_POINTS = "ADD_POINTS", r.CHANGE_VALUES = "CHANGE_VALUES", r.DELETE_POINTS = "DELETE_POINTS", r.DRIFT_CORRECTION = "DRIFT_CORRECTION", r.INTERPOLATE = "INTERPOLATE", r.SHIFT_DATETIMES = "SHIFT_DATETIMES", r.FILL_GAPS = "FILL_GAPS", r))(f || {}), _ = /* @__PURE__ */ ((r) => (r.FIND_GAPS = "FIND_GAPS", r.PERSISTENCE = "PERSISTENCE", r.RATE_OF_CHANGE = "RATE_OF_CHANGE", r.VALUE_THRESHOLD = "VALUE_THRESHOLD", r))(_ || {});
2
+ const X = {
3
+ "Less than": (r, t) => r < t,
4
+ "Less than or equal to": (r, t) => r <= t,
5
+ "Greater than": (r, t) => r > t,
6
+ "Greater than or equal to": (r, t) => r >= t,
7
+ Equal: (r, t) => r == t,
8
+ "Start datetime": (r, t) => r == t,
9
+ "End datetime": (r, t) => r == t
10
+ };
11
+ var E = /* @__PURE__ */ ((r) => (r.ADD = "ADD", r.SUB = "SUB", r.MULT = "MULT", r.DIV = "DIV", r.ASSIGN = "ASSIGN", r))(E || {});
12
+ const x = {
13
+ "Less than": (r, t) => r < t,
14
+ "Less than or equal to": (r, t) => r <= t,
15
+ "Greater than": (r, t) => r > t,
16
+ "Greater than or equal to": (r, t) => r >= t,
17
+ Equal: (r, t) => r == t
18
+ }, I = `(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
19
+ `, b = typeof self < "u" && self.Blob && new Blob([I], { type: "text/javascript;charset=utf-8" });
20
+ function U(r) {
4
21
  let t;
5
22
  try {
6
23
  if (t = b && (self.URL || self.webkitURL).createObjectURL(b), !t) throw "";
7
24
  const s = new Worker(t, {
8
- name: o?.name
25
+ name: r?.name
9
26
  });
10
27
  return s.addEventListener("error", () => {
11
28
  (self.URL || self.webkitURL).revokeObjectURL(t);
12
29
  }), s;
13
30
  } catch {
14
31
  return new Worker(
15
- "data:text/javascript;charset=utf-8," + encodeURIComponent(D),
32
+ "data:text/javascript;charset=utf-8," + encodeURIComponent(I),
16
33
  {
17
- name: o?.name
34
+ name: r?.name
18
35
  }
19
36
  );
20
37
  } finally {
21
38
  t && (self.URL || self.webkitURL).revokeObjectURL(t);
22
39
  }
23
40
  }
24
- const R = `(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
25
- `, A = typeof self < "u" && self.Blob && new Blob([R], { type: "text/javascript;charset=utf-8" });
26
- function x(o) {
41
+ const F = `(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
42
+ `, R = typeof self < "u" && self.Blob && new Blob([F], { type: "text/javascript;charset=utf-8" });
43
+ function M(r) {
27
44
  let t;
28
45
  try {
29
- if (t = A && (self.URL || self.webkitURL).createObjectURL(A), !t) throw "";
46
+ if (t = R && (self.URL || self.webkitURL).createObjectURL(R), !t) throw "";
30
47
  const s = new Worker(t, {
31
- name: o?.name
48
+ name: r?.name
32
49
  });
33
50
  return s.addEventListener("error", () => {
34
51
  (self.URL || self.webkitURL).revokeObjectURL(t);
35
52
  }), s;
36
53
  } catch {
37
54
  return new Worker(
38
- "data:text/javascript;charset=utf-8," + encodeURIComponent(R),
55
+ "data:text/javascript;charset=utf-8," + encodeURIComponent(F),
39
56
  {
40
- name: o?.name
57
+ name: r?.name
41
58
  }
42
59
  );
43
60
  } finally {
44
61
  t && (self.URL || self.webkitURL).revokeObjectURL(t);
45
62
  }
46
63
  }
47
- const M = (o, t) => {
48
- let s = 0, e = o.length;
64
+ const C = (r, t) => {
65
+ let s = 0, e = r.length;
49
66
  for (; s < e; ) {
50
- const r = s + e >> 1;
51
- o[r] < t ? s = r + 1 : e = r;
67
+ const n = s + e >> 1;
68
+ r[n] < t ? s = n + 1 : e = n;
52
69
  }
53
70
  return s;
54
- }, B = (o, t) => {
55
- let s = 0, e = o.length;
71
+ }, B = (r, t) => {
72
+ let s = 0, e = r.length;
56
73
  for (; s < e; ) {
57
- const r = s + e >> 1;
58
- o[r] > t ? e = r : s = r + 1;
74
+ const n = s + e >> 1;
75
+ r[n] > t ? e = n : s = n + 1;
59
76
  }
60
77
  return s - 1;
61
- }, w = async (o, t) => {
62
- const s = performance.now(), e = await o(), r = performance.now();
63
- console.log(` Done in ${(r - s).toFixed(2)} ms`);
64
- const a = +(r - s);
78
+ }, w = async (r, t) => {
79
+ const s = performance.now(), e = await r(), n = performance.now();
80
+ console.log(` Done in ${(n - s).toFixed(2)} ms`);
81
+ const a = +(n - s);
65
82
  return { response: e, duration: a };
66
- }, S = 1, Y = S * 60, _ = Y * 60, T = _ * 24, N = T * 7, U = _ * 30, I = T * 365, L = {
67
- s: S,
83
+ }, N = 1, Y = N * 60, S = Y * 60, D = S * 24, G = D * 7, O = S * 30, k = D * 365, A = {
84
+ s: N,
68
85
  m: Y,
69
- h: _,
70
- D: T,
71
- W: N,
72
- M: U,
73
- Y: I
74
- }, O = (o, t, s) => {
86
+ h: S,
87
+ D,
88
+ W: G,
89
+ M: O,
90
+ Y: k
91
+ }, H = (r, t, s) => {
75
92
  if (s === "M") {
76
- const e = new Date(o);
93
+ const e = new Date(r);
77
94
  return e.setMonth(e.getMonth() + t), e.getTime();
78
95
  } else if (s === "Y") {
79
- const e = new Date(o);
96
+ const e = new Date(r);
80
97
  return e.setFullYear(e.getFullYear() + t), e.getTime();
81
98
  } else
82
- return o + t * L[s] * 1e3;
83
- }, P = {
84
- "Less than": (o, t) => o < t,
85
- "Less than or equal to": (o, t) => o <= t,
86
- "Greater than": (o, t) => o > t,
87
- "Greater than or equal to": (o, t) => o >= t,
88
- Equal: (o, t) => o == t,
89
- "Start datetime": (o, t) => o == t,
90
- "End datetime": (o, t) => o == t
91
- }, k = {
92
- "Less than": (o, t) => o < t,
93
- "Less than or equal to": (o, t) => o <= t,
94
- "Greater than": (o, t) => o > t,
95
- "Greater than or equal to": (o, t) => o >= t,
96
- Equal: (o, t) => o == t
97
- }, g = 20 * 1e3, C = ["date", "value", "qualifier"];
98
- class G {
99
+ return r + t * A[s] * 1e3;
100
+ }, L = 20 * 1e3, v = ["date", "value", "qualifier"];
101
+ class V {
99
102
  /** The generated dataset to be used for plotting */
100
103
  dataset = {
101
- dimensions: C,
104
+ dimensions: v,
102
105
  source: {
103
106
  x: new Float64Array(
104
107
  new SharedArrayBuffer(
105
- g * Float64Array.BYTES_PER_ELEMENT,
108
+ L * Float64Array.BYTES_PER_ELEMENT,
106
109
  {
107
- maxByteLength: g * Float64Array.BYTES_PER_ELEMENT
110
+ maxByteLength: L * Float64Array.BYTES_PER_ELEMENT
108
111
  // Max size the array can reach
109
112
  }
110
113
  )
111
114
  ),
112
115
  y: new Float32Array(
113
116
  new SharedArrayBuffer(
114
- g * Float32Array.BYTES_PER_ELEMENT,
117
+ L * Float32Array.BYTES_PER_ELEMENT,
115
118
  {
116
- maxByteLength: g * Float32Array.BYTES_PER_ELEMENT
119
+ maxByteLength: L * Float32Array.BYTES_PER_ELEMENT
117
120
  // Max size the array can reach
118
121
  }
119
122
  )
@@ -162,9 +165,9 @@ class G {
162
165
  const s = t * Float64Array.BYTES_PER_ELEMENT;
163
166
  let e = this.dataX.buffer.byteLength;
164
167
  for (; s > e; )
165
- e += g * Float64Array.BYTES_PER_ELEMENT;
168
+ e += L * Float64Array.BYTES_PER_ELEMENT;
166
169
  if (e * Float64Array.BYTES_PER_ELEMENT > this.dataX.buffer.maxByteLength) {
167
- const r = new SharedArrayBuffer(
170
+ const n = new SharedArrayBuffer(
168
171
  this.dataX.buffer.byteLength,
169
172
  {
170
173
  maxByteLength: e * Float64Array.BYTES_PER_ELEMENT
@@ -174,8 +177,8 @@ class G {
174
177
  {
175
178
  maxByteLength: e * Float32Array.BYTES_PER_ELEMENT
176
179
  }
177
- ), n = new Float64Array(r), i = new Float32Array(a);
178
- n.set(this.dataX), i.set(this.dataY), this.dataset.source.x = n, this.dataset.source.y = i;
180
+ ), o = new Float64Array(n), i = new Float32Array(a);
181
+ o.set(this.dataX), i.set(this.dataY), this.dataset.source.x = o, this.dataset.source.y = i;
179
182
  }
180
183
  this.dataX.buffer.byteLength < t * Float64Array.BYTES_PER_ELEMENT && (this.dataX.buffer.grow(t * Float64Array.BYTES_PER_ELEMENT), this.dataY.buffer.grow(t * Float32Array.BYTES_PER_ELEMENT));
181
184
  }
@@ -210,36 +213,36 @@ class G {
210
213
  /** Dispatch an operation and log its signature in hisotry */
211
214
  async dispatch(t, ...s) {
212
215
  const e = {
213
- ADD_POINTS: this._addDataPoints,
214
- CHANGE_VALUES: this._changeValues,
215
- DELETE_POINTS: this._deleteDataPoints,
216
- DRIFT_CORRECTION: this._driftCorrection,
217
- INTERPOLATE: this._interpolate,
218
- SHIFT_DATETIMES: this._shift,
219
- FILL_GAPS: this._fillGaps
220
- }, r = {
221
- ADD_POINTS: "mdi-plus",
222
- CHANGE_VALUES: "mdi-pencil",
223
- DELETE_POINTS: "mdi-trash-can",
224
- DRIFT_CORRECTION: "mdi-chart-sankey",
225
- INTERPOLATE: "mdi-transit-connection-horizontal",
226
- SHIFT_DATETIMES: "mdi-calendar",
227
- FILL_GAPS: "mdi-keyboard-space"
216
+ [f.ADD_POINTS]: this._addDataPoints,
217
+ [f.CHANGE_VALUES]: this._changeValues,
218
+ [f.DELETE_POINTS]: this._deleteDataPoints,
219
+ [f.DRIFT_CORRECTION]: this._driftCorrection,
220
+ [f.INTERPOLATE]: this._interpolate,
221
+ [f.SHIFT_DATETIMES]: this._shift,
222
+ [f.FILL_GAPS]: this._fillGaps
223
+ }, n = {
224
+ [f.ADD_POINTS]: "mdi-plus",
225
+ [f.CHANGE_VALUES]: "mdi-pencil",
226
+ [f.DELETE_POINTS]: "mdi-trash-can",
227
+ [f.DRIFT_CORRECTION]: "mdi-chart-sankey",
228
+ [f.INTERPOLATE]: "mdi-transit-connection-horizontal",
229
+ [f.SHIFT_DATETIMES]: "mdi-calendar",
230
+ [f.FILL_GAPS]: "mdi-keyboard-space"
228
231
  };
229
232
  let a = [];
230
233
  try {
231
234
  if (Array.isArray(t)) {
232
- for (let n = 0; n < t.length; n++) {
233
- const i = t[n][0], h = t[n].slice(1, t[n].length), l = {
235
+ for (let o = 0; o < t.length; o++) {
236
+ const i = t[o][0], h = t[o].slice(1, t[o].length), l = {
234
237
  method: i,
235
238
  args: h,
236
- icon: r[i],
239
+ icon: n[i],
237
240
  isLoading: !1
238
241
  };
239
242
  this.history.push(l);
240
243
  }
241
- for (let n = this.history.length - t.length; n < this.history.length; n++) {
242
- const i = this.history[n];
244
+ for (let o = this.history.length - t.length; o < this.history.length; o++) {
245
+ const i = this.history[o];
243
246
  i.isLoading = !0;
244
247
  const h = await w(async () => await e[i.method].apply(
245
248
  this,
@@ -248,48 +251,48 @@ class G {
248
251
  i.duration = h.duration, i.isLoading = !1, a.push(h.response);
249
252
  }
250
253
  } else {
251
- const n = {
254
+ const o = {
252
255
  method: t,
253
256
  args: s,
254
- icon: r[t],
257
+ icon: n[t],
255
258
  isLoading: !0
256
259
  };
257
- this.history.push(n);
260
+ this.history.push(o);
258
261
  const i = await w(async () => await e[t].apply(this, s));
259
- a = i.response, n.duration = i.duration, n.isLoading = !1;
262
+ a = i.response, o.duration = i.duration, o.isLoading = !1;
260
263
  }
261
- } catch (n) {
264
+ } catch (o) {
262
265
  console.log(
263
266
  `Failed to execute operation: ${t} with arguments: `,
264
267
  s
265
- ), console.log(n);
268
+ ), console.log(o);
266
269
  }
267
270
  return a;
268
271
  }
269
272
  /** Filter operations do not transform the data and are not logged in history */
270
273
  async dispatchFilter(t, ...s) {
271
274
  const e = {
272
- FIND_GAPS: this._findGaps,
273
- VALUE_THRESHOLD: this._valueThreshold,
274
- PERSISTENCE: this._persistence,
275
- RATE_OF_CHANGE: this._rateOfChange
275
+ [_.FIND_GAPS]: this._findGaps,
276
+ [_.VALUE_THRESHOLD]: this._valueThreshold,
277
+ [_.PERSISTENCE]: this._persistence,
278
+ [_.RATE_OF_CHANGE]: this._rateOfChange
276
279
  };
277
- let r = [];
280
+ let n = [];
278
281
  try {
279
282
  if (Array.isArray(t))
280
283
  for (let a = 0; a < t.length; a++) {
281
- const n = t[a][0], i = t[a].slice(1, t[a].length), h = await e[n].apply(this, i);
282
- r.push(h);
284
+ const o = t[a][0], i = t[a].slice(1, t[a].length), h = await e[o].apply(this, i);
285
+ n.push(h);
283
286
  }
284
287
  else
285
- r = await e[t].apply(this, s);
288
+ n = await e[t].apply(this, s);
286
289
  } catch (a) {
287
290
  console.log(
288
291
  `Failed to execute filter operation: ${t} with arguments: `,
289
292
  s
290
293
  ), console.log(a);
291
294
  }
292
- return r;
295
+ return n;
293
296
  }
294
297
  /**
295
298
  * @param index An array containing the list of index of values to perform the operations on.
@@ -298,44 +301,44 @@ class G {
298
301
  * @returns The modified DataFrame
299
302
  */
300
303
  _changeValues(t, s, e) {
301
- const r = (a) => {
304
+ const n = (a) => {
302
305
  switch (s) {
303
- case "ADD":
306
+ case E.ADD:
304
307
  return a + e;
305
- case "ASSIGN":
308
+ case E.ASSIGN:
306
309
  return e;
307
- case "DIV":
310
+ case E.DIV:
308
311
  return a / e;
309
- case "MULT":
312
+ case E.MULT:
310
313
  return a * e;
311
- case "SUB":
314
+ case E.SUB:
312
315
  return a - e;
313
316
  default:
314
317
  return a;
315
318
  }
316
319
  };
317
320
  t.forEach((a) => {
318
- this.dataset.source.y[a] = r(this.dataset.source.y[a]);
321
+ this.dataset.source.y[a] = n(this.dataset.source.y[a]);
319
322
  });
320
323
  }
321
324
  _interpolate(t) {
322
325
  this._getConsecutiveGroups(t).forEach((e) => {
323
- const r = e[0], a = e[e.length - 1];
324
- let n = Math.max(0, r - 1), i = Math.min(this.dataset.source.y.length - 1, a + 1);
326
+ const n = e[0], a = e[e.length - 1];
327
+ let o = Math.max(0, n - 1), i = Math.min(this.dataset.source.y.length - 1, a + 1);
325
328
  const h = this.dataset.source.x, l = this.dataset.source.y;
326
- for (let c = 0; c < e.length; c++)
327
- this.dataset.source.y[e[c]] = this._interpolateLinear(
328
- h[e[c]],
329
- h[n],
330
- l[n],
329
+ for (let u = 0; u < e.length; u++)
330
+ this.dataset.source.y[e[u]] = this._interpolateLinear(
331
+ h[e[u]],
332
+ h[o],
333
+ l[o],
331
334
  h[i],
332
335
  l[i]
333
336
  );
334
337
  });
335
338
  }
336
339
  /** Interpolate existing values in the data source */
337
- _interpolateLinear(t, s, e, r, a) {
338
- return e + (t - s) * (a - e) / (r - s);
340
+ _interpolateLinear(t, s, e, n, a) {
341
+ return e + (t - s) * (a - e) / (n - s);
339
342
  }
340
343
  /**
341
344
  * Shifts the selected indexes by specified amount of units. Elements are reinserted according to their datetime.
@@ -345,33 +348,33 @@ class G {
345
348
  * @returns
346
349
  */
347
350
  async _shift(t, s, e) {
348
- const r = t.map((a) => [
349
- O(this.dataX[a], s, e),
351
+ const n = t.map((a) => [
352
+ H(this.dataX[a], s, e),
350
353
  this.dataY[a]
351
354
  ]);
352
- await this._deleteDataPoints(t), await this._addDataPoints(r);
355
+ await this._deleteDataPoints(t), await this._addDataPoints(n);
353
356
  }
354
- async _fillGapsV2(t, s, e, r) {
355
- const a = navigator.hardwareConcurrency || 1, n = [], i = [], h = this.dataX.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
357
+ async _fillGapsV2(t, s, e, n) {
358
+ const a = navigator.hardwareConcurrency || 1, o = [], i = [], h = this.dataX.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
356
359
  maxByteLength: this.dataX.buffer.maxByteLength
357
- }), c = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
360
+ }), u = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
358
361
  maxByteLength: this.dataY.buffer.maxByteLength
359
362
  });
360
- for (let u = 0; u < a; u++)
363
+ for (let c = 0; c < a; c++)
361
364
  i.push(
362
- new Promise((f) => {
363
- const d = new x();
364
- n.push(d), d.postMessage({
365
+ new Promise((d) => {
366
+ const y = new M();
367
+ o.push(y), y.postMessage({
365
368
  bufferX: this.dataX.buffer,
366
369
  bufferY: this.dataY.buffer,
367
370
  outputBufferX: l,
368
- outputBufferY: c
369
- }), d.onmessage = (y) => {
370
- f(y.data);
371
+ outputBufferY: u
372
+ }), y.onmessage = (g) => {
373
+ d(g.data);
371
374
  };
372
375
  })
373
376
  );
374
- await Promise.all(i), n.forEach((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
377
+ await Promise.all(i), o.forEach((c) => c.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(u), this._resizeTo(h);
375
378
  }
376
379
  /**
377
380
  * Find gaps and fill them with placeholder value
@@ -381,22 +384,22 @@ class G {
381
384
  * @returns
382
385
  */
383
386
  // TODO: this needs to be improved using web workers
384
- _fillGaps(t, s, e, r) {
385
- const a = this._findGaps(t[0], t[1], r);
386
- for (let n = a.length - 1; n >= 0; n--) {
387
- const i = a[n], h = this.dataX[i[0]], l = this.dataX[i[1]], c = [], u = s[0] * L[s[1]] * 1e3;
388
- let f = h + u;
389
- for (; f < l; ) {
390
- const d = e ? this._interpolateLinear(
391
- f,
387
+ _fillGaps(t, s, e, n) {
388
+ const a = this._findGaps(t[0], t[1], n);
389
+ for (let o = a.length - 1; o >= 0; o--) {
390
+ const i = a[o], h = this.dataX[i[0]], l = this.dataX[i[1]], u = [], c = s[0] * A[s[1]] * 1e3;
391
+ let d = h + c;
392
+ for (; d < l; ) {
393
+ const y = e ? this._interpolateLinear(
394
+ d,
392
395
  this.dataX[i[0]],
393
396
  this.dataY[i[0]],
394
397
  this.dataX[i[1]],
395
398
  this.dataY[i[1]]
396
399
  ) : -9999;
397
- c.push([f, d]), f += u;
400
+ u.push([d, y]), d += c;
398
401
  }
399
- this._addDataPoints(c);
402
+ this._addDataPoints(u);
400
403
  }
401
404
  }
402
405
  /**
@@ -409,40 +412,40 @@ class G {
409
412
  */
410
413
  // TODO: implement similar multithread solutions for other operations
411
414
  async _deleteDataPoints(t) {
412
- const s = navigator.hardwareConcurrency || 1, e = Math.ceil(this.dataX.length / s), r = [], a = [];
413
- for (let u = 0; u < s; u++) {
414
- const f = u * e, d = Math.min((u + 1) * e - 1, this.dataX.length - 1), y = M(t, f), p = B(t, d), m = t.slice(y, p + 1);
415
- a.push({ start: f, end: d, deleteSegment: m });
415
+ const s = navigator.hardwareConcurrency || 1, e = Math.ceil(this.dataX.length / s), n = [], a = [];
416
+ for (let c = 0; c < s; c++) {
417
+ const d = c * e, y = Math.min((c + 1) * e - 1, this.dataX.length - 1), g = C(t, d), p = B(t, y), m = t.slice(g, p + 1);
418
+ a.push({ start: d, end: y, deleteSegment: m });
416
419
  }
417
- const n = new Array(s).fill(0);
418
- for (let u = 1; u < s; u++)
419
- n[u] = n[u - 1] + a[u - 1].deleteSegment.length;
420
+ const o = new Array(s).fill(0);
421
+ for (let c = 1; c < s; c++)
422
+ o[c] = o[c - 1] + a[c - 1].deleteSegment.length;
420
423
  const i = [], h = this.dataX.length - t.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
421
424
  maxByteLength: this.dataX.buffer.maxByteLength
422
- }), c = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
425
+ }), u = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
423
426
  maxByteLength: this.dataY.buffer.maxByteLength
424
427
  });
425
- for (let u = 0; u < s; u++) {
426
- const { start: f, end: d, deleteSegment: y } = a[u], p = f - n[u];
428
+ for (let c = 0; c < s; c++) {
429
+ const { start: d, end: y, deleteSegment: g } = a[c], p = d - o[c];
427
430
  i.push(
428
431
  new Promise((m) => {
429
- const E = new X();
430
- r.push(E), E.postMessage({
432
+ const T = new U();
433
+ n.push(T), T.postMessage({
431
434
  bufferX: this.dataX.buffer,
432
435
  bufferY: this.dataY.buffer,
433
436
  outputBufferX: l,
434
- outputBufferY: c,
435
- start: f,
436
- end: d,
437
- deleteSegment: y,
437
+ outputBufferY: u,
438
+ start: d,
439
+ end: y,
440
+ deleteSegment: g,
438
441
  startTarget: p
439
- }), E.onmessage = (F) => {
440
- m(F.data);
442
+ }), T.onmessage = (P) => {
443
+ m(P.data);
441
444
  };
442
445
  })
443
446
  );
444
447
  }
445
- await Promise.all(i), r.forEach((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
448
+ await Promise.all(i), n.forEach((c) => c.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(u), this._resizeTo(h);
446
449
  }
447
450
  /**
448
451
  *
@@ -451,9 +454,9 @@ class G {
451
454
  * @param value The drift amount
452
455
  */
453
456
  _driftCorrection(t, s, e) {
454
- const r = this.dataset.source.x, a = this.dataset.source.y, n = r[t], h = r[s] - n;
457
+ const n = this.dataset.source.x, a = this.dataset.source.y, o = n[t], h = n[s] - o;
455
458
  for (let l = t; l < s; l++)
456
- this.dataset.source.y[l] = a[l] + e * ((r[l] - n) / h);
459
+ this.dataset.source.y[l] = a[l] + e * ((n[l] - o) / h);
457
460
  }
458
461
  /** Traverses the index array and returns groups of consecutive values.
459
462
  * i.e.: `[0, 1, 3, 4, 6] => [[0, 1], [3, 4], [6]]`
@@ -462,9 +465,9 @@ class G {
462
465
  */
463
466
  _getConsecutiveGroups(t) {
464
467
  const s = [[]];
465
- return t.reduce((e, r) => {
468
+ return t.reduce((e, n) => {
466
469
  const a = e[e.length - 1];
467
- return !a.length || r == a[a.length - 1] + 1 ? a.push(r) : e.push([r]), e;
470
+ return !a.length || n == a[a.length - 1] + 1 ? a.push(n) : e.push([n]), e;
468
471
  }, s), s;
469
472
  }
470
473
  /**
@@ -473,15 +476,15 @@ class G {
473
476
  */
474
477
  async _addDataPoints(t) {
475
478
  const s = this.dataX.length + t.length;
476
- this._growBuffer(s), t.sort((a, n) => a[0] - n[0]);
479
+ this._growBuffer(s), t.sort((a, o) => a[0] - o[0]);
477
480
  const e = t.map((a) => B(this.dataX, a[0]) + 1);
478
481
  this._resizeTo(s), e.push(this.dataX.length);
479
- let r = t.length;
482
+ let n = t.length;
480
483
  for (let a = e.length - 1; a > 0; a--) {
481
- const n = e[a - 1], i = e[a] - 1;
482
- for (let h = i; h >= n; h--)
483
- this.dataX[h + r] = this.dataX[h], this.dataY[h + r] = this.dataY[h];
484
- r--, this.dataX[n + r] = t[a - 1][0], this.dataY[n + r] = t[a - 1][1];
484
+ const o = e[a - 1], i = e[a] - 1;
485
+ for (let h = i; h >= o; h--)
486
+ this.dataX[h + n] = this.dataX[h], this.dataY[h + n] = this.dataY[h];
487
+ n--, this.dataX[o + n] = t[a - 1][0], this.dataY[o + n] = t[a - 1][1];
485
488
  }
486
489
  }
487
490
  // =======================
@@ -494,11 +497,11 @@ class G {
494
497
  */
495
498
  _valueThreshold(t) {
496
499
  const s = [];
497
- return this.dataset.source.y.forEach((e, r) => {
498
- Object.keys(t).some((a) => P[a]?.(
500
+ return this.dataset.source.y.forEach((e, n) => {
501
+ Object.keys(t).some((a) => X[a]?.(
499
502
  e,
500
503
  t[a]
501
- )) && s.push(r);
504
+ )) && s.push(n);
502
505
  }), s;
503
506
  }
504
507
  /**
@@ -508,10 +511,10 @@ class G {
508
511
  * @returns
509
512
  */
510
513
  _rateOfChange(t, s) {
511
- const e = [], r = this.dataset.source.y;
512
- for (let a = 1; a < r.length; a++) {
513
- const n = r[a - 1], h = (r[a] - n) / Math.abs(n);
514
- k[t]?.(
514
+ const e = [], n = this.dataset.source.y;
515
+ for (let a = 1; a < n.length; a++) {
516
+ const o = n[a - 1], h = (n[a] - o) / Math.abs(o);
517
+ x[t]?.(
515
518
  h,
516
519
  s
517
520
  ) && e.push(a);
@@ -526,15 +529,15 @@ class G {
526
529
  * @returns
527
530
  */
528
531
  _findGaps(t, s, e) {
529
- const r = [], a = this.dataset.source.x;
530
- let n = 0, i = a.length;
531
- e?.[0] && e?.[1] && (n = e[0], i = e[1]);
532
- let h = a[n];
533
- for (let l = n + 1; l <= i; l++) {
534
- const c = a[l];
535
- c - h > t * L[s] * 1e3 && r.push([l - 1, l]), h = c;
532
+ const n = [], a = this.dataset.source.x;
533
+ let o = 0, i = a.length;
534
+ e?.[0] && e?.[1] && (o = e[0], i = e[1]);
535
+ let h = a[o];
536
+ for (let l = o + 1; l <= i; l++) {
537
+ const u = a[l];
538
+ u - h > t * A[s] * 1e3 && n.push([l - 1, l]), h = u;
536
539
  }
537
- return r;
540
+ return n;
538
541
  }
539
542
  /**
540
543
  * Find points where the values are the same at least x times in a row
@@ -543,14 +546,14 @@ class G {
543
546
  * @returns
544
547
  */
545
548
  _persistence(t, s) {
546
- let e = [], r = this.dataset.source.y, a = 0, n = r.length;
547
- s?.[0] && s?.[1] && (a = s[0], n = s[1]);
548
- let i = r[a], h = [];
549
- for (let l = a + 1; l < n; l++)
550
- r[l] != i || l === n ? (h.length >= t && (e = [...e, ...h]), h = []) : h.push(l);
549
+ let e = [], n = this.dataset.source.y, a = 0, o = n.length;
550
+ s?.[0] && s?.[1] && (a = s[0], o = s[1]);
551
+ let i = n[a], h = [];
552
+ for (let l = a + 1; l < o; l++)
553
+ n[l] != i || l === o ? (h.length >= t && (e = [...e, ...h]), h = []) : h.push(l);
551
554
  return e;
552
555
  }
553
556
  }
554
557
  export {
555
- G as ObservationRecord
558
+ V as ObservationRecord
556
559
  };
@@ -1,3 +1,3 @@
1
- (function(y,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(y=typeof globalThis<"u"?globalThis:y||self,g(y["@uwrl/qc-utils"]={}))})(this,function(y){"use strict";const g=`(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
2
- `,B=typeof self<"u"&&self.Blob&&new Blob([g],{type:"text/javascript;charset=utf-8"});function x(o){let t;try{if(t=B&&(self.URL||self.webkitURL).createObjectURL(B),!t)throw"";const s=new Worker(t,{name:o?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(g),{name:o?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const D=`(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
3
- `,R=typeof self<"u"&&self.Blob&&new Blob([D],{type:"text/javascript;charset=utf-8"});function X(o){let t;try{if(t=R&&(self.URL||self.webkitURL).createObjectURL(R),!t)throw"";const s=new Worker(t,{name:o?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(D),{name:o?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const M=(o,t)=>{let s=0,e=o.length;for(;s<e;){const r=s+e>>1;o[r]<t?s=r+1:e=r}return s},S=(o,t)=>{let s=0,e=o.length;for(;s<e;){const r=s+e>>1;o[r]>t?e=r:s=r+1}return s-1},E=async(o,t)=>{const s=performance.now(),e=await o(),r=performance.now();console.log(` Done in ${(r-s).toFixed(2)} ms`);const a=+(r-s);return{response:e,duration:a}},Y=1,F=Y*60,w=F*60,L=w*24,N=L*7,O=w*30,U=L*365,_={s:Y,m:F,h:w,D:L,W:N,M:O,Y:U},I=(o,t,s)=>{if(s==="M"){const e=new Date(o);return e.setMonth(e.getMonth()+t),e.getTime()}else if(s==="Y"){const e=new Date(o);return e.setFullYear(e.getFullYear()+t),e.getTime()}else return o+t*_[s]*1e3},P={"Less than":(o,t)=>o<t,"Less than or equal to":(o,t)=>o<=t,"Greater than":(o,t)=>o>t,"Greater than or equal to":(o,t)=>o>=t,Equal:(o,t)=>o==t,"Start datetime":(o,t)=>o==t,"End datetime":(o,t)=>o==t},k={"Less than":(o,t)=>o<t,"Less than or equal to":(o,t)=>o<=t,"Greater than":(o,t)=>o>t,"Greater than or equal to":(o,t)=>o>=t,Equal:(o,t)=>o==t},p=20*1e3,C=["date","value","qualifier"];class v{dataset={dimensions:C,source:{x:new Float64Array(new SharedArrayBuffer(p*Float64Array.BYTES_PER_ELEMENT,{maxByteLength:p*Float64Array.BYTES_PER_ELEMENT})),y:new Float32Array(new SharedArrayBuffer(p*Float32Array.BYTES_PER_ELEMENT,{maxByteLength:p*Float32Array.BYTES_PER_ELEMENT}))}};history=[];loadingTime=null;isLoading=!0;rawData;constructor(t){this.history=[],this.rawData=t,this.loadData(this.rawData)}async loadData(t){if(!t)return;this.isLoading=!0;const s=await E(()=>{this._growBuffer(t.datetimes.length),this._resizeTo(t.datetimes.length),this.dataX.set(t.datetimes),this.dataY.set(t.dataValues)});this.loadingTime=s.duration,this.history.length=0,this.isLoading=!1}get dataX(){return this.dataset.source.x}get dataY(){return this.dataset.source.y}_resizeTo(t){this.dataset.source.x=new Float64Array(this.dataset.source.x.buffer).subarray(0,t),this.dataset.source.y=new Float32Array(this.dataset.source.y.buffer).subarray(0,t)}_growBuffer(t){const s=t*Float64Array.BYTES_PER_ELEMENT;let e=this.dataX.buffer.byteLength;for(;s>e;)e+=p*Float64Array.BYTES_PER_ELEMENT;if(e*Float64Array.BYTES_PER_ELEMENT>this.dataX.buffer.maxByteLength){const r=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:e*Float64Array.BYTES_PER_ELEMENT}),a=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:e*Float32Array.BYTES_PER_ELEMENT}),n=new Float64Array(r),i=new Float32Array(a);n.set(this.dataX),i.set(this.dataY),this.dataset.source.x=n,this.dataset.source.y=i}this.dataX.buffer.byteLength<t*Float64Array.BYTES_PER_ELEMENT&&(this.dataX.buffer.grow(t*Float64Array.BYTES_PER_ELEMENT),this.dataY.buffer.grow(t*Float32Array.BYTES_PER_ELEMENT))}async reload(){this.loadingTime=null,this.isLoading=!0,this.history.length=0,await this.loadData(this.rawData)}async reloadHistory(t){const s=this.history.slice(0,t+1);await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}async removeHistoryItem(t){const s=[...this.history];s.splice(t,1),await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}get beginTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[0]):null}get endTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[this.dataset.source.x.length-1]):null}async dispatch(t,...s){const e={ADD_POINTS:this._addDataPoints,CHANGE_VALUES:this._changeValues,DELETE_POINTS:this._deleteDataPoints,DRIFT_CORRECTION:this._driftCorrection,INTERPOLATE:this._interpolate,SHIFT_DATETIMES:this._shift,FILL_GAPS:this._fillGaps},r={ADD_POINTS:"mdi-plus",CHANGE_VALUES:"mdi-pencil",DELETE_POINTS:"mdi-trash-can",DRIFT_CORRECTION:"mdi-chart-sankey",INTERPOLATE:"mdi-transit-connection-horizontal",SHIFT_DATETIMES:"mdi-calendar",FILL_GAPS:"mdi-keyboard-space"};let a=[];try{if(Array.isArray(t)){for(let n=0;n<t.length;n++){const i=t[n][0],h=t[n].slice(1,t[n].length),l={method:i,args:h,icon:r[i],isLoading:!1};this.history.push(l)}for(let n=this.history.length-t.length;n<this.history.length;n++){const i=this.history[n];i.isLoading=!0;const h=await E(async()=>await e[i.method].apply(this,i.args));i.duration=h.duration,i.isLoading=!1,a.push(h.response)}}else{const n={method:t,args:s,icon:r[t],isLoading:!0};this.history.push(n);const i=await E(async()=>await e[t].apply(this,s));a=i.response,n.duration=i.duration,n.isLoading=!1}}catch(n){console.log(`Failed to execute operation: ${t} with arguments: `,s),console.log(n)}return a}async dispatchFilter(t,...s){const e={FIND_GAPS:this._findGaps,VALUE_THRESHOLD:this._valueThreshold,PERSISTENCE:this._persistence,RATE_OF_CHANGE:this._rateOfChange};let r=[];try{if(Array.isArray(t))for(let a=0;a<t.length;a++){const n=t[a][0],i=t[a].slice(1,t[a].length),h=await e[n].apply(this,i);r.push(h)}else r=await e[t].apply(this,s)}catch(a){console.log(`Failed to execute filter operation: ${t} with arguments: `,s),console.log(a)}return r}_changeValues(t,s,e){const r=a=>{switch(s){case"ADD":return a+e;case"ASSIGN":return e;case"DIV":return a/e;case"MULT":return a*e;case"SUB":return a-e;default:return a}};t.forEach(a=>{this.dataset.source.y[a]=r(this.dataset.source.y[a])})}_interpolate(t){this._getConsecutiveGroups(t).forEach(e=>{const r=e[0],a=e[e.length-1];let n=Math.max(0,r-1),i=Math.min(this.dataset.source.y.length-1,a+1);const h=this.dataset.source.x,l=this.dataset.source.y;for(let c=0;c<e.length;c++)this.dataset.source.y[e[c]]=this._interpolateLinear(h[e[c]],h[n],l[n],h[i],l[i])})}_interpolateLinear(t,s,e,r,a){return e+(t-s)*(a-e)/(r-s)}async _shift(t,s,e){const r=t.map(a=>[I(this.dataX[a],s,e),this.dataY[a]]);await this._deleteDataPoints(t),await this._addDataPoints(r)}async _fillGapsV2(t,s,e,r){const a=navigator.hardwareConcurrency||1,n=[],i=[],h=this.dataX.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),c=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<a;u++)i.push(new Promise(f=>{const d=new X;n.push(d),d.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:c}),d.onmessage=m=>{f(m.data)}}));await Promise.all(i),n.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(c),this._resizeTo(h)}_fillGaps(t,s,e,r){const a=this._findGaps(t[0],t[1],r);for(let n=a.length-1;n>=0;n--){const i=a[n],h=this.dataX[i[0]],l=this.dataX[i[1]],c=[],u=s[0]*_[s[1]]*1e3;let f=h+u;for(;f<l;){const d=e?this._interpolateLinear(f,this.dataX[i[0]],this.dataY[i[0]],this.dataX[i[1]],this.dataY[i[1]]):-9999;c.push([f,d]),f+=u}this._addDataPoints(c)}}async _deleteDataPoints(t){const s=navigator.hardwareConcurrency||1,e=Math.ceil(this.dataX.length/s),r=[],a=[];for(let u=0;u<s;u++){const f=u*e,d=Math.min((u+1)*e-1,this.dataX.length-1),m=M(t,f),T=S(t,d),b=t.slice(m,T+1);a.push({start:f,end:d,deleteSegment:b})}const n=new Array(s).fill(0);for(let u=1;u<s;u++)n[u]=n[u-1]+a[u-1].deleteSegment.length;const i=[],h=this.dataX.length-t.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),c=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<s;u++){const{start:f,end:d,deleteSegment:m}=a[u],T=f-n[u];i.push(new Promise(b=>{const A=new x;r.push(A),A.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:c,start:f,end:d,deleteSegment:m,startTarget:T}),A.onmessage=G=>{b(G.data)}}))}await Promise.all(i),r.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(c),this._resizeTo(h)}_driftCorrection(t,s,e){const r=this.dataset.source.x,a=this.dataset.source.y,n=r[t],h=r[s]-n;for(let l=t;l<s;l++)this.dataset.source.y[l]=a[l]+e*((r[l]-n)/h)}_getConsecutiveGroups(t){const s=[[]];return t.reduce((e,r)=>{const a=e[e.length-1];return!a.length||r==a[a.length-1]+1?a.push(r):e.push([r]),e},s),s}async _addDataPoints(t){const s=this.dataX.length+t.length;this._growBuffer(s),t.sort((a,n)=>a[0]-n[0]);const e=t.map(a=>S(this.dataX,a[0])+1);this._resizeTo(s),e.push(this.dataX.length);let r=t.length;for(let a=e.length-1;a>0;a--){const n=e[a-1],i=e[a]-1;for(let h=i;h>=n;h--)this.dataX[h+r]=this.dataX[h],this.dataY[h+r]=this.dataY[h];r--,this.dataX[n+r]=t[a-1][0],this.dataY[n+r]=t[a-1][1]}}_valueThreshold(t){const s=[];return this.dataset.source.y.forEach((e,r)=>{Object.keys(t).some(a=>P[a]?.(e,t[a]))&&s.push(r)}),s}_rateOfChange(t,s){const e=[],r=this.dataset.source.y;for(let a=1;a<r.length;a++){const n=r[a-1],h=(r[a]-n)/Math.abs(n);k[t]?.(h,s)&&e.push(a)}return e}_findGaps(t,s,e){const r=[],a=this.dataset.source.x;let n=0,i=a.length;e?.[0]&&e?.[1]&&(n=e[0],i=e[1]);let h=a[n];for(let l=n+1;l<=i;l++){const c=a[l];c-h>t*_[s]*1e3&&r.push([l-1,l]),h=c}return r}_persistence(t,s){let e=[],r=this.dataset.source.y,a=0,n=r.length;s?.[0]&&s?.[1]&&(a=s[0],n=s[1]);let i=r[a],h=[];for(let l=a+1;l<n;l++)r[l]!=i||l===n?(h.length>=t&&(e=[...e,...h]),h=[]):h.push(l);return e}}y.ObservationRecord=v,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
1
+ (function(E,c){typeof exports=="object"&&typeof module<"u"?c(exports):typeof define=="function"&&define.amd?define(["exports"],c):(E=typeof globalThis<"u"?globalThis:E||self,c(E["@uwrl/qc-utils"]={}))})(this,function(E){"use strict";var c=(r=>(r.ADD_POINTS="ADD_POINTS",r.CHANGE_VALUES="CHANGE_VALUES",r.DELETE_POINTS="DELETE_POINTS",r.DRIFT_CORRECTION="DRIFT_CORRECTION",r.INTERPOLATE="INTERPOLATE",r.SHIFT_DATETIMES="SHIFT_DATETIMES",r.FILL_GAPS="FILL_GAPS",r))(c||{}),p=(r=>(r.FIND_GAPS="FIND_GAPS",r.PERSISTENCE="PERSISTENCE",r.RATE_OF_CHANGE="RATE_OF_CHANGE",r.VALUE_THRESHOLD="VALUE_THRESHOLD",r))(p||{});const x={"Less than":(r,t)=>r<t,"Less than or equal to":(r,t)=>r<=t,"Greater than":(r,t)=>r>t,"Greater than or equal to":(r,t)=>r>=t,Equal:(r,t)=>r==t,"Start datetime":(r,t)=>r==t,"End datetime":(r,t)=>r==t};var g=(r=>(r.ADD="ADD",r.SUB="SUB",r.MULT="MULT",r.DIV="DIV",r.ASSIGN="ASSIGN",r))(g||{});const X={"Less than":(r,t)=>r<t,"Less than or equal to":(r,t)=>r<=t,"Greater than":(r,t)=>r>t,"Greater than or equal to":(r,t)=>r>=t,Equal:(r,t)=>r==t},R=`(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
2
+ `,B=typeof self<"u"&&self.Blob&&new Blob([R],{type:"text/javascript;charset=utf-8"});function U(r){let t;try{if(t=B&&(self.URL||self.webkitURL).createObjectURL(B),!t)throw"";const s=new Worker(t,{name:r?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(R),{name:r?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const I=`(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
3
+ `,F=typeof self<"u"&&self.Blob&&new Blob([I],{type:"text/javascript;charset=utf-8"});function M(r){let t;try{if(t=F&&(self.URL||self.webkitURL).createObjectURL(F),!t)throw"";const s=new Worker(t,{name:r?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(I),{name:r?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const C=(r,t)=>{let s=0,e=r.length;for(;s<e;){const n=s+e>>1;r[n]<t?s=n+1:e=n}return s},N=(r,t)=>{let s=0,e=r.length;for(;s<e;){const n=s+e>>1;r[n]>t?e=n:s=n+1}return s-1},_=async(r,t)=>{const s=performance.now(),e=await r(),n=performance.now();console.log(` Done in ${(n-s).toFixed(2)} ms`);const a=+(n-s);return{response:e,duration:a}},Y=1,P=Y*60,T=P*60,w=T*24,O=w*7,G=T*30,k=w*365,A={s:Y,m:P,h:T,D:w,W:O,M:G,Y:k},v=(r,t,s)=>{if(s==="M"){const e=new Date(r);return e.setMonth(e.getMonth()+t),e.getTime()}else if(s==="Y"){const e=new Date(r);return e.setFullYear(e.getFullYear()+t),e.getTime()}else return r+t*A[s]*1e3},L=20*1e3,H=["date","value","qualifier"];class j{dataset={dimensions:H,source:{x:new Float64Array(new SharedArrayBuffer(L*Float64Array.BYTES_PER_ELEMENT,{maxByteLength:L*Float64Array.BYTES_PER_ELEMENT})),y:new Float32Array(new SharedArrayBuffer(L*Float32Array.BYTES_PER_ELEMENT,{maxByteLength:L*Float32Array.BYTES_PER_ELEMENT}))}};history=[];loadingTime=null;isLoading=!0;rawData;constructor(t){this.history=[],this.rawData=t,this.loadData(this.rawData)}async loadData(t){if(!t)return;this.isLoading=!0;const s=await _(()=>{this._growBuffer(t.datetimes.length),this._resizeTo(t.datetimes.length),this.dataX.set(t.datetimes),this.dataY.set(t.dataValues)});this.loadingTime=s.duration,this.history.length=0,this.isLoading=!1}get dataX(){return this.dataset.source.x}get dataY(){return this.dataset.source.y}_resizeTo(t){this.dataset.source.x=new Float64Array(this.dataset.source.x.buffer).subarray(0,t),this.dataset.source.y=new Float32Array(this.dataset.source.y.buffer).subarray(0,t)}_growBuffer(t){const s=t*Float64Array.BYTES_PER_ELEMENT;let e=this.dataX.buffer.byteLength;for(;s>e;)e+=L*Float64Array.BYTES_PER_ELEMENT;if(e*Float64Array.BYTES_PER_ELEMENT>this.dataX.buffer.maxByteLength){const n=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:e*Float64Array.BYTES_PER_ELEMENT}),a=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:e*Float32Array.BYTES_PER_ELEMENT}),o=new Float64Array(n),i=new Float32Array(a);o.set(this.dataX),i.set(this.dataY),this.dataset.source.x=o,this.dataset.source.y=i}this.dataX.buffer.byteLength<t*Float64Array.BYTES_PER_ELEMENT&&(this.dataX.buffer.grow(t*Float64Array.BYTES_PER_ELEMENT),this.dataY.buffer.grow(t*Float32Array.BYTES_PER_ELEMENT))}async reload(){this.loadingTime=null,this.isLoading=!0,this.history.length=0,await this.loadData(this.rawData)}async reloadHistory(t){const s=this.history.slice(0,t+1);await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}async removeHistoryItem(t){const s=[...this.history];s.splice(t,1),await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}get beginTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[0]):null}get endTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[this.dataset.source.x.length-1]):null}async dispatch(t,...s){const e={[c.ADD_POINTS]:this._addDataPoints,[c.CHANGE_VALUES]:this._changeValues,[c.DELETE_POINTS]:this._deleteDataPoints,[c.DRIFT_CORRECTION]:this._driftCorrection,[c.INTERPOLATE]:this._interpolate,[c.SHIFT_DATETIMES]:this._shift,[c.FILL_GAPS]:this._fillGaps},n={[c.ADD_POINTS]:"mdi-plus",[c.CHANGE_VALUES]:"mdi-pencil",[c.DELETE_POINTS]:"mdi-trash-can",[c.DRIFT_CORRECTION]:"mdi-chart-sankey",[c.INTERPOLATE]:"mdi-transit-connection-horizontal",[c.SHIFT_DATETIMES]:"mdi-calendar",[c.FILL_GAPS]:"mdi-keyboard-space"};let a=[];try{if(Array.isArray(t)){for(let o=0;o<t.length;o++){const i=t[o][0],h=t[o].slice(1,t[o].length),l={method:i,args:h,icon:n[i],isLoading:!1};this.history.push(l)}for(let o=this.history.length-t.length;o<this.history.length;o++){const i=this.history[o];i.isLoading=!0;const h=await _(async()=>await e[i.method].apply(this,i.args));i.duration=h.duration,i.isLoading=!1,a.push(h.response)}}else{const o={method:t,args:s,icon:n[t],isLoading:!0};this.history.push(o);const i=await _(async()=>await e[t].apply(this,s));a=i.response,o.duration=i.duration,o.isLoading=!1}}catch(o){console.log(`Failed to execute operation: ${t} with arguments: `,s),console.log(o)}return a}async dispatchFilter(t,...s){const e={[p.FIND_GAPS]:this._findGaps,[p.VALUE_THRESHOLD]:this._valueThreshold,[p.PERSISTENCE]:this._persistence,[p.RATE_OF_CHANGE]:this._rateOfChange};let n=[];try{if(Array.isArray(t))for(let a=0;a<t.length;a++){const o=t[a][0],i=t[a].slice(1,t[a].length),h=await e[o].apply(this,i);n.push(h)}else n=await e[t].apply(this,s)}catch(a){console.log(`Failed to execute filter operation: ${t} with arguments: `,s),console.log(a)}return n}_changeValues(t,s,e){const n=a=>{switch(s){case g.ADD:return a+e;case g.ASSIGN:return e;case g.DIV:return a/e;case g.MULT:return a*e;case g.SUB:return a-e;default:return a}};t.forEach(a=>{this.dataset.source.y[a]=n(this.dataset.source.y[a])})}_interpolate(t){this._getConsecutiveGroups(t).forEach(e=>{const n=e[0],a=e[e.length-1];let o=Math.max(0,n-1),i=Math.min(this.dataset.source.y.length-1,a+1);const h=this.dataset.source.x,l=this.dataset.source.y;for(let f=0;f<e.length;f++)this.dataset.source.y[e[f]]=this._interpolateLinear(h[e[f]],h[o],l[o],h[i],l[i])})}_interpolateLinear(t,s,e,n,a){return e+(t-s)*(a-e)/(n-s)}async _shift(t,s,e){const n=t.map(a=>[v(this.dataX[a],s,e),this.dataY[a]]);await this._deleteDataPoints(t),await this._addDataPoints(n)}async _fillGapsV2(t,s,e,n){const a=navigator.hardwareConcurrency||1,o=[],i=[],h=this.dataX.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),f=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<a;u++)i.push(new Promise(d=>{const y=new M;o.push(y),y.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f}),y.onmessage=m=>{d(m.data)}}));await Promise.all(i),o.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(f),this._resizeTo(h)}_fillGaps(t,s,e,n){const a=this._findGaps(t[0],t[1],n);for(let o=a.length-1;o>=0;o--){const i=a[o],h=this.dataX[i[0]],l=this.dataX[i[1]],f=[],u=s[0]*A[s[1]]*1e3;let d=h+u;for(;d<l;){const y=e?this._interpolateLinear(d,this.dataX[i[0]],this.dataY[i[0]],this.dataX[i[1]],this.dataY[i[1]]):-9999;f.push([d,y]),d+=u}this._addDataPoints(f)}}async _deleteDataPoints(t){const s=navigator.hardwareConcurrency||1,e=Math.ceil(this.dataX.length/s),n=[],a=[];for(let u=0;u<s;u++){const d=u*e,y=Math.min((u+1)*e-1,this.dataX.length-1),m=C(t,d),S=N(t,y),D=t.slice(m,S+1);a.push({start:d,end:y,deleteSegment:D})}const o=new Array(s).fill(0);for(let u=1;u<s;u++)o[u]=o[u-1]+a[u-1].deleteSegment.length;const i=[],h=this.dataX.length-t.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),f=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<s;u++){const{start:d,end:y,deleteSegment:m}=a[u],S=d-o[u];i.push(new Promise(D=>{const b=new U;n.push(b),b.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f,start:d,end:y,deleteSegment:m,startTarget:S}),b.onmessage=V=>{D(V.data)}}))}await Promise.all(i),n.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(f),this._resizeTo(h)}_driftCorrection(t,s,e){const n=this.dataset.source.x,a=this.dataset.source.y,o=n[t],h=n[s]-o;for(let l=t;l<s;l++)this.dataset.source.y[l]=a[l]+e*((n[l]-o)/h)}_getConsecutiveGroups(t){const s=[[]];return t.reduce((e,n)=>{const a=e[e.length-1];return!a.length||n==a[a.length-1]+1?a.push(n):e.push([n]),e},s),s}async _addDataPoints(t){const s=this.dataX.length+t.length;this._growBuffer(s),t.sort((a,o)=>a[0]-o[0]);const e=t.map(a=>N(this.dataX,a[0])+1);this._resizeTo(s),e.push(this.dataX.length);let n=t.length;for(let a=e.length-1;a>0;a--){const o=e[a-1],i=e[a]-1;for(let h=i;h>=o;h--)this.dataX[h+n]=this.dataX[h],this.dataY[h+n]=this.dataY[h];n--,this.dataX[o+n]=t[a-1][0],this.dataY[o+n]=t[a-1][1]}}_valueThreshold(t){const s=[];return this.dataset.source.y.forEach((e,n)=>{Object.keys(t).some(a=>x[a]?.(e,t[a]))&&s.push(n)}),s}_rateOfChange(t,s){const e=[],n=this.dataset.source.y;for(let a=1;a<n.length;a++){const o=n[a-1],h=(n[a]-o)/Math.abs(o);X[t]?.(h,s)&&e.push(a)}return e}_findGaps(t,s,e){const n=[],a=this.dataset.source.x;let o=0,i=a.length;e?.[0]&&e?.[1]&&(o=e[0],i=e[1]);let h=a[o];for(let l=o+1;l<=i;l++){const f=a[l];f-h>t*A[s]*1e3&&n.push([l-1,l]),h=f}return n}_persistence(t,s){let e=[],n=this.dataset.source.y,a=0,o=n.length;s?.[0]&&s?.[1]&&(a=s[0],o=s[1]);let i=n[a],h=[];for(let l=a+1;l<o;l++)n[l]!=i||l===o?(h.length>=t&&(e=[...e,...h]),h=[]):h.push(l);return e}}E.ObservationRecord=j,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,51 @@
1
+ export declare enum EnumEditOperations {
2
+ ADD_POINTS = "ADD_POINTS",
3
+ CHANGE_VALUES = "CHANGE_VALUES",
4
+ DELETE_POINTS = "DELETE_POINTS",
5
+ DRIFT_CORRECTION = "DRIFT_CORRECTION",
6
+ INTERPOLATE = "INTERPOLATE",
7
+ SHIFT_DATETIMES = "SHIFT_DATETIMES",
8
+ FILL_GAPS = "FILL_GAPS"
9
+ }
10
+ export declare enum EnumFilterOperations {
11
+ FIND_GAPS = "FIND_GAPS",
12
+ PERSISTENCE = "PERSISTENCE",
13
+ RATE_OF_CHANGE = "RATE_OF_CHANGE",
14
+ VALUE_THRESHOLD = "VALUE_THRESHOLD"
15
+ }
16
+ export type HistoryItem = {
17
+ method: EnumEditOperations;
18
+ icon: string;
19
+ isLoading: boolean;
20
+ args?: any[];
21
+ duration?: number;
22
+ status?: 'success' | 'failed';
23
+ };
24
+ export type EnumDictionary<T extends string | symbol | number, U> = {
25
+ [K in T]: U;
26
+ };
27
+ export declare enum FilterOperation {
28
+ LT = "Less than",
29
+ LTE = "Less than or equal to",
30
+ GT = "Greater than",
31
+ GTE = "Greater than or equal to",
32
+ E = "Equal",
33
+ START = "Start datetime",
34
+ END = "End datetime"
35
+ }
36
+ export declare const FilterOperationFn: EnumDictionary<FilterOperation, (value: number, toCompare: number) => boolean>;
37
+ export declare enum Operator {
38
+ ADD = "ADD",
39
+ SUB = "SUB",
40
+ MULT = "MULT",
41
+ DIV = "DIV",
42
+ ASSIGN = "ASSIGN"
43
+ }
44
+ export declare enum RateOfChangeOperation {
45
+ LT = "Less than",
46
+ LTE = "Less than or equal to",
47
+ GT = "Greater than",
48
+ GTE = "Greater than or equal to",
49
+ E = "Equal"
50
+ }
51
+ export declare const RateOfChangeComparator: EnumDictionary<RateOfChangeOperation, (value: number, toCompare: number) => boolean>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
File without changes
File without changes
@@ -0,0 +1,46 @@
1
+ export declare const DEFAULT_SNACK_DURATION = 3000;
2
+ export declare enum SnackColor {
3
+ Warning = "warning",
4
+ Success = "success",
5
+ Error = "error",
6
+ Info = "info"
7
+ }
8
+ export declare enum SnackIcon {
9
+ Success = "mdi-checkbox-marked-circle",
10
+ Warning = "mdi-alert",
11
+ Error = "mdi-alert-circle",
12
+ Info = "mdi-information",
13
+ None = "none"
14
+ }
15
+ export declare enum SnackTitle {
16
+ Warning = "Warning",
17
+ Success = "Success",
18
+ Error = "Error",
19
+ Info = "Info"
20
+ }
21
+ export declare enum Position {
22
+ Center = "center",
23
+ Left = "left",
24
+ Right = "right",
25
+ Bottom = "bottom",
26
+ Top = "top"
27
+ }
28
+ export declare class Snack {
29
+ message: string;
30
+ color: SnackColor;
31
+ icon: SnackIcon;
32
+ title: SnackTitle;
33
+ timeout: number;
34
+ position: Position;
35
+ visible: boolean;
36
+ constructor(message?: string, color?: SnackColor, icon?: SnackIcon, title?: SnackTitle, timeout?: number, position?: Position, visible?: boolean);
37
+ }
38
+ export declare class Snackbar {
39
+ private static subject;
40
+ static get snack$(): import("rxjs").Observable<Snack>;
41
+ private static createSnackbar;
42
+ static success(message: string): void;
43
+ static warn(message: string): void;
44
+ static error(message: string): void;
45
+ static info(message: string): void;
46
+ }
File without changes
@@ -0,0 +1,4 @@
1
+ export declare const mockDatastream: {
2
+ phenomenon_time: string[];
3
+ result: number[];
4
+ };
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,170 @@
1
+ import { EnumDictionary, EnumEditOperations, EnumFilterOperations, HistoryItem } from '../../types';
2
+ export declare function subtractHours(timestamp: string, hours: number): string;
3
+ /** Returns the index of the first value that is greater or equal to the target value */
4
+ export declare const findFirstGreaterOrEqual: (array: number[] | Float64Array<SharedArrayBuffer>, target: number) => number;
5
+ /** Returns the index of the last value that is lesser or equal to the target value */
6
+ export declare const findLastLessOrEqual: (array: number[] | Float64Array<SharedArrayBuffer>, target: number) => number;
7
+ export declare const measureEllapsedTime: (fn: () => any, message?: string) => Promise<{
8
+ response: any;
9
+ duration: number;
10
+ }>;
11
+ export declare enum TimeUnit {
12
+ SECOND = "s",
13
+ MINUTE = "m",
14
+ HOUR = "h",
15
+ DAY = "D",
16
+ WEEK = "W",
17
+ MONTH = "M",
18
+ YEAR = "Y"
19
+ }
20
+ export declare const timeUnitMultipliers: EnumDictionary<TimeUnit, number>;
21
+ export declare const formatDate: (date: Date) => string;
22
+ export declare const formatDuration: (duration: number) => string;
23
+ export declare const shiftDatetime: (datetime: number, amount: number, unit: TimeUnit) => number;
24
+ /**
25
+ * This number should approximate the number of observations that a dataset could increase by during a session.
26
+ * The lower this number, the less memory the entire app uses.
27
+ * Note that when a dataset number of data points increases by more than `INCREASE_AMOUNT`,
28
+ * the `_growBuffer()` method will allocate a new buffer, and the data will be copied into it.
29
+ */
30
+ export declare const INCREASE_AMOUNT: number;
31
+ export declare class ObservationRecord {
32
+ /** The generated dataset to be used for plotting */
33
+ dataset: {
34
+ dimensions: string[];
35
+ source: {
36
+ x: Float64Array<SharedArrayBuffer>;
37
+ y: Float32Array<SharedArrayBuffer>;
38
+ };
39
+ };
40
+ history: HistoryItem[];
41
+ loadingTime: number | null;
42
+ isLoading: boolean;
43
+ rawData: {
44
+ datetimes: Float64Array<ArrayBuffer> | number[];
45
+ dataValues: Float32Array<ArrayBuffer> | number[];
46
+ };
47
+ constructor(dataArrays: {
48
+ datetimes: Float64Array<ArrayBuffer> | number[];
49
+ dataValues: Float32Array<ArrayBuffer> | number[];
50
+ });
51
+ loadData(dataArrays: {
52
+ datetimes: Float64Array<ArrayBuffer> | number[];
53
+ dataValues: Float32Array<ArrayBuffer> | number[];
54
+ }): Promise<void>;
55
+ get dataX(): Float64Array<SharedArrayBuffer>;
56
+ get dataY(): Float32Array<SharedArrayBuffer>;
57
+ /**
58
+ * Resizes the typed array
59
+ * @param length The total number of elements that the view will contain
60
+ */
61
+ private _resizeTo;
62
+ /**
63
+ * Buffer size is always in increments of `INCREASE_AMOUNT`.
64
+ * Grows the buffer by `INCREASE_AMOUNT` in bytes if the current data doesn't fit
65
+ * @param newLength The total number of elements that the view will contain
66
+ */
67
+ private _growBuffer;
68
+ /**
69
+ * Reloads the dataset with the raw data
70
+ */
71
+ reload(): Promise<void>;
72
+ /**
73
+ * @param index
74
+ * @returns
75
+ */
76
+ reloadHistory(index: number): Promise<void>;
77
+ /**
78
+ * Remove a history item
79
+ * @param index
80
+ */
81
+ removeHistoryItem(index: number): Promise<void>;
82
+ get beginTime(): Date | null;
83
+ get endTime(): Date | null;
84
+ /** Dispatch an operation and log its signature in hisotry */
85
+ dispatch(action: EnumEditOperations | [EnumEditOperations, ...any][], ...args: any): Promise<any[]>;
86
+ /** Filter operations do not transform the data and are not logged in history */
87
+ dispatchFilter(action: EnumFilterOperations | [EnumFilterOperations, ...any][], ...args: any): Promise<any>;
88
+ /**
89
+ * @param index An array containing the list of index of values to perform the operations on.
90
+ * @param operator The operator that will be applied
91
+ * @param value The value to use in the operation
92
+ * @returns The modified DataFrame
93
+ */
94
+ private _changeValues;
95
+ private _interpolate;
96
+ /** Interpolate existing values in the data source */
97
+ private _interpolateLinear;
98
+ /**
99
+ * Shifts the selected indexes by specified amount of units. Elements are reinserted according to their datetime.
100
+ * @param index The index of the elements to shift
101
+ * @param amount Number of {@link TimeUnit}
102
+ * @param unit {@link TimeUnit}
103
+ * @returns
104
+ */
105
+ private _shift;
106
+ private _fillGapsV2;
107
+ /**
108
+ * Find gaps and fill them with placeholder value
109
+ * @param gap Intervals to detect as gaps
110
+ * @param fill Interval used to fill the detected gaps
111
+ * @param interpolateValues If true, the new values will be linearly interpolated
112
+ * @returns
113
+ */
114
+ private _fillGaps;
115
+ /**
116
+ Deletes data points from a large array using worker threads.
117
+ 1. The main thread divides the original array into equal parts to distribute work among workers.
118
+ 2. For each segment, binary search locates the indexes to delete (deleteSegment), ensuring efficient lookups.
119
+ 3. The cumulative deletions before each segment help compute the starting index (startTarget) for each worker's output, ensuring no overlap.
120
+ 4. Each worker processes its segment linearly, skipping deletions and copying kept elements to their computed positions.
121
+ * @param deleteIndices
122
+ */
123
+ private _deleteDataPoints;
124
+ /**
125
+ *
126
+ * @param start The start index
127
+ * @param end The end index
128
+ * @param value The drift amount
129
+ */
130
+ private _driftCorrection;
131
+ /** Traverses the index array and returns groups of consecutive values.
132
+ * i.e.: `[0, 1, 3, 4, 6] => [[0, 1], [3, 4], [6]]`
133
+ * Assumes the input array is sorted.
134
+ * @param index: the index array (sorted)
135
+ */
136
+ private _getConsecutiveGroups;
137
+ /**
138
+ * Adds data points. Their insert index is determined using `findFirstGreaterOrEqual` in the x-axis.
139
+ * @param dataPoints
140
+ */
141
+ private _addDataPoints;
142
+ /**
143
+ * Filter by applying a set of logical operations
144
+ * @param appliedFilters
145
+ * @returns
146
+ */
147
+ private _valueThreshold;
148
+ /**
149
+ *
150
+ * @param comparator
151
+ * @param value
152
+ * @returns
153
+ */
154
+ private _rateOfChange;
155
+ /**
156
+ * Find gaps in the data
157
+ * @param value The time value
158
+ * @param unit The time unit (TimeUnit)
159
+ * @param range If specified, the gaps will be found only within the range
160
+ * @returns
161
+ */
162
+ private _findGaps;
163
+ /**
164
+ * Find points where the values are the same at least x times in a row
165
+ * @param times The number of times in a row that points can be equal
166
+ * @param range If specified, the points will be found only within the range
167
+ * @returns
168
+ */
169
+ private _persistence;
170
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwrl/qc-utils",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Quality Control Utilities",
5
5
  "homepage": "https://github.com/hydroserver2/qc-utils#readme",
6
6
  "bugs": {
@@ -12,7 +12,6 @@
12
12
  },
13
13
  "license": "ISC",
14
14
  "author": "Maurier Ramirez",
15
- "type": "module",
16
15
  "main": "./dist/index.cjs",
17
16
  "module": "./dist/index.js",
18
17
  "exports": {
@@ -21,11 +20,13 @@
21
20
  "import": "./dist/index.js"
22
21
  }
23
22
  },
23
+ "types": "./dist/types.d.ts",
24
24
  "files": [
25
25
  "dist"
26
26
  ],
27
+ "type": "module",
27
28
  "scripts": {
28
- "build": "npm run clean:dist && vite build --mode prod",
29
+ "build": "npm run clean:dist && vite build --mode prod && vue-tsc --declaration --emitDeclarationOnly",
29
30
  "pub": "npm publish --access public",
30
31
  "clean:dist": "rimraf dist",
31
32
  "clean:coverage": "rimraf coverage",
@@ -37,6 +38,7 @@
37
38
  "link": "npm link"
38
39
  },
39
40
  "dependencies": {
41
+ "rxjs": "^7.8.2",
40
42
  "vite": "^7.0.4"
41
43
  },
42
44
  "devDependencies": {
@@ -49,6 +51,7 @@
49
51
  "stylelint": "^16.20.0",
50
52
  "taze": "^19.1.0",
51
53
  "typescript": "latest",
52
- "vitest": "^3.2.4"
54
+ "vitest": "^3.2.4",
55
+ "vue-tsc": "^3.0.5"
53
56
  }
54
57
  }