@uwrl/qc-utils 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import { ObservationRecord } from './utils/plotting/observationRecord';
2
+ export { ObservationRecord, };
3
+ export * from './types';
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__ */ ((s) => (s.ADD_POINTS = "ADD_POINTS", s.CHANGE_VALUES = "CHANGE_VALUES", s.DELETE_POINTS = "DELETE_POINTS", s.DRIFT_CORRECTION = "DRIFT_CORRECTION", s.INTERPOLATE = "INTERPOLATE", s.SHIFT_DATETIMES = "SHIFT_DATETIMES", s.FILL_GAPS = "FILL_GAPS", s))(f || {}), T = /* @__PURE__ */ ((s) => (s.FIND_GAPS = "FIND_GAPS", s.PERSISTENCE = "PERSISTENCE", s.RATE_OF_CHANGE = "RATE_OF_CHANGE", s.VALUE_THRESHOLD = "VALUE_THRESHOLD", s))(T || {}), X = /* @__PURE__ */ ((s) => (s.LT = "Less than", s.LTE = "Less than or equal to", s.GT = "Greater than", s.GTE = "Greater than or equal to", s.E = "Equal", s.START = "Start datetime", s.END = "End datetime", s))(X || {});
2
+ const x = {
3
+ "Less than": (s, t) => s < t,
4
+ "Less than or equal to": (s, t) => s <= t,
5
+ "Greater than": (s, t) => s > t,
6
+ "Greater than or equal to": (s, t) => s >= t,
7
+ Equal: (s, t) => s == t,
8
+ "Start datetime": (s, t) => s == t,
9
+ "End datetime": (s, t) => s == t
10
+ };
11
+ var y = /* @__PURE__ */ ((s) => (s.ADD = "ADD", s.SUB = "SUB", s.MULT = "MULT", s.DIV = "DIV", s.ASSIGN = "ASSIGN", s))(y || {}), G = /* @__PURE__ */ ((s) => (s.LT = "Less than", s.LTE = "Less than or equal to", s.GT = "Greater than", s.GTE = "Greater than or equal to", s.E = "Equal", s))(G || {});
12
+ const U = {
13
+ "Less than": (s, t) => s < t,
14
+ "Less than or equal to": (s, t) => s <= t,
15
+ "Greater than": (s, t) => s > t,
16
+ "Greater than or equal to": (s, t) => s >= t,
17
+ Equal: (s, t) => s == 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 M(s) {
4
21
  let t;
5
22
  try {
6
23
  if (t = b && (self.URL || self.webkitURL).createObjectURL(b), !t) throw "";
7
- const s = new Worker(t, {
8
- name: o?.name
24
+ const a = new Worker(t, {
25
+ name: s?.name
9
26
  });
10
- return s.addEventListener("error", () => {
27
+ return a.addEventListener("error", () => {
11
28
  (self.URL || self.webkitURL).revokeObjectURL(t);
12
- }), s;
29
+ }), a;
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: s?.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 N = `(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([N], { type: "text/javascript;charset=utf-8" });
43
+ function C(s) {
27
44
  let t;
28
45
  try {
29
- if (t = A && (self.URL || self.webkitURL).createObjectURL(A), !t) throw "";
30
- const s = new Worker(t, {
31
- name: o?.name
46
+ if (t = R && (self.URL || self.webkitURL).createObjectURL(R), !t) throw "";
47
+ const a = new Worker(t, {
48
+ name: s?.name
32
49
  });
33
- return s.addEventListener("error", () => {
50
+ return a.addEventListener("error", () => {
34
51
  (self.URL || self.webkitURL).revokeObjectURL(t);
35
- }), s;
52
+ }), a;
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(N),
39
56
  {
40
- name: o?.name
57
+ name: s?.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;
49
- for (; s < e; ) {
50
- const r = s + e >> 1;
51
- o[r] < t ? s = r + 1 : e = r;
64
+ const k = (s, t) => {
65
+ let a = 0, e = s.length;
66
+ for (; a < e; ) {
67
+ const n = a + e >> 1;
68
+ s[n] < t ? a = n + 1 : e = n;
52
69
  }
53
- return s;
54
- }, B = (o, t) => {
55
- let s = 0, e = o.length;
56
- for (; s < e; ) {
57
- const r = s + e >> 1;
58
- o[r] > t ? e = r : s = r + 1;
70
+ return a;
71
+ }, B = (s, t) => {
72
+ let a = 0, e = s.length;
73
+ for (; a < e; ) {
74
+ const n = a + e >> 1;
75
+ s[n] > t ? e = n : a = n + 1;
59
76
  }
60
- 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);
65
- 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,
68
- m: Y,
69
- h: _,
70
- D: T,
71
- W: N,
72
- M: U,
73
- Y: I
74
- }, O = (o, t, s) => {
75
- if (s === "M") {
76
- const e = new Date(o);
77
+ return a - 1;
78
+ }, p = async (s, t) => {
79
+ const a = performance.now(), e = await s(), n = performance.now();
80
+ console.log(` Done in ${(n - a).toFixed(2)} ms`);
81
+ const r = +(n - a);
82
+ return { response: e, duration: r };
83
+ }, Y = 1, F = Y * 60, S = F * 60, D = S * 24, v = D * 7, H = S * 30, O = D * 365, A = {
84
+ s: Y,
85
+ m: F,
86
+ h: S,
87
+ D,
88
+ W: v,
89
+ M: H,
90
+ Y: O
91
+ }, V = (s, t, a) => {
92
+ if (a === "M") {
93
+ const e = new Date(s);
77
94
  return e.setMonth(e.getMonth() + t), e.getTime();
78
- } else if (s === "Y") {
79
- const e = new Date(o);
95
+ } else if (a === "Y") {
96
+ const e = new Date(s);
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 s + t * A[a] * 1e3;
100
+ }, L = 20 * 1e3, j = ["date", "value", "qualifier"];
101
+ class q {
99
102
  /** The generated dataset to be used for plotting */
100
103
  dataset = {
101
- dimensions: C,
104
+ dimensions: j,
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
  )
@@ -131,10 +134,10 @@ class G {
131
134
  if (!t)
132
135
  return;
133
136
  this.isLoading = !0;
134
- const s = await w(() => {
137
+ const a = await p(() => {
135
138
  this._growBuffer(t.datetimes.length), this._resizeTo(t.datetimes.length), this.dataX.set(t.datetimes), this.dataY.set(t.dataValues);
136
139
  });
137
- this.loadingTime = s.duration, this.history.length = 0, this.isLoading = !1;
140
+ this.loadingTime = a.duration, this.history.length = 0, this.isLoading = !1;
138
141
  }
139
142
  get dataX() {
140
143
  return this.dataset.source.x;
@@ -159,23 +162,23 @@ class G {
159
162
  * @param newLength The total number of elements that the view will contain
160
163
  */
161
164
  _growBuffer(t) {
162
- const s = t * Float64Array.BYTES_PER_ELEMENT;
165
+ const a = t * Float64Array.BYTES_PER_ELEMENT;
163
166
  let e = this.dataX.buffer.byteLength;
164
- for (; s > e; )
165
- e += g * Float64Array.BYTES_PER_ELEMENT;
167
+ for (; a > e; )
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
171
174
  }
172
- ), a = new SharedArrayBuffer(
175
+ ), r = new SharedArrayBuffer(
173
176
  this.dataY.buffer.byteLength,
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(r);
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
  }
@@ -190,16 +193,16 @@ class G {
190
193
  * @returns
191
194
  */
192
195
  async reloadHistory(t) {
193
- const s = this.history.slice(0, t + 1);
194
- await this.reload(), await this.dispatch(s.map((e) => [e.method, ...e.args || []]));
196
+ const a = this.history.slice(0, t + 1);
197
+ await this.reload(), await this.dispatch(a.map((e) => [e.method, ...e.args || []]));
195
198
  }
196
199
  /**
197
200
  * Remove a history item
198
201
  * @param index
199
202
  */
200
203
  async removeHistoryItem(t) {
201
- const s = [...this.history];
202
- s.splice(t, 1), await this.reload(), await this.dispatch(s.map((e) => [e.method, ...e.args || []]));
204
+ const a = [...this.history];
205
+ a.splice(t, 1), await this.reload(), await this.dispatch(a.map((e) => [e.method, ...e.args || []]));
203
206
  }
204
207
  get beginTime() {
205
208
  return this.dataset.source.x.length ? new Date(this.dataset.source.x[0]) : null;
@@ -208,88 +211,88 @@ class G {
208
211
  return this.dataset.source.x.length ? new Date(this.dataset.source.x[this.dataset.source.x.length - 1]) : null;
209
212
  }
210
213
  /** Dispatch an operation and log its signature in hisotry */
211
- async dispatch(t, ...s) {
214
+ async dispatch(t, ...a) {
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
- let a = [];
232
+ let r = [];
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
- const h = await w(async () => await e[i.method].apply(
247
+ const h = await p(async () => await e[i.method].apply(
245
248
  this,
246
249
  i.args
247
250
  ));
248
- i.duration = h.duration, i.isLoading = !1, a.push(h.response);
251
+ i.duration = h.duration, i.isLoading = !1, r.push(h.response);
249
252
  }
250
253
  } else {
251
- const n = {
254
+ const o = {
252
255
  method: t,
253
- args: s,
254
- icon: r[t],
256
+ args: a,
257
+ icon: n[t],
255
258
  isLoading: !0
256
259
  };
257
- this.history.push(n);
258
- const i = await w(async () => await e[t].apply(this, s));
259
- a = i.response, n.duration = i.duration, n.isLoading = !1;
260
+ this.history.push(o);
261
+ const i = await p(async () => await e[t].apply(this, a));
262
+ r = 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
- s
265
- ), console.log(n);
267
+ a
268
+ ), console.log(o);
266
269
  }
267
- return a;
270
+ return r;
268
271
  }
269
272
  /** Filter operations do not transform the data and are not logged in history */
270
- async dispatchFilter(t, ...s) {
273
+ async dispatchFilter(t, ...a) {
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
+ [T.FIND_GAPS]: this._findGaps,
276
+ [T.VALUE_THRESHOLD]: this._valueThreshold,
277
+ [T.PERSISTENCE]: this._persistence,
278
+ [T.RATE_OF_CHANGE]: this._rateOfChange
276
279
  };
277
- let r = [];
280
+ let n = [];
278
281
  try {
279
282
  if (Array.isArray(t))
280
- 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);
283
+ for (let r = 0; r < t.length; r++) {
284
+ const o = t[r][0], i = t[r].slice(1, t[r].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);
286
- } catch (a) {
288
+ n = await e[t].apply(this, a);
289
+ } catch (r) {
287
290
  console.log(
288
291
  `Failed to execute filter operation: ${t} with arguments: `,
289
- s
290
- ), console.log(a);
292
+ a
293
+ ), console.log(r);
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.
@@ -297,45 +300,45 @@ class G {
297
300
  * @param value The value to use in the operation
298
301
  * @returns The modified DataFrame
299
302
  */
300
- _changeValues(t, s, e) {
301
- const r = (a) => {
302
- switch (s) {
303
- case "ADD":
304
- return a + e;
305
- case "ASSIGN":
303
+ _changeValues(t, a, e) {
304
+ const n = (r) => {
305
+ switch (a) {
306
+ case y.ADD:
307
+ return r + e;
308
+ case y.ASSIGN:
306
309
  return e;
307
- case "DIV":
308
- return a / e;
309
- case "MULT":
310
- return a * e;
311
- case "SUB":
312
- return a - e;
310
+ case y.DIV:
311
+ return r / e;
312
+ case y.MULT:
313
+ return r * e;
314
+ case y.SUB:
315
+ return r - e;
313
316
  default:
314
- return a;
317
+ return r;
315
318
  }
316
319
  };
317
- t.forEach((a) => {
318
- this.dataset.source.y[a] = r(this.dataset.source.y[a]);
320
+ t.forEach((r) => {
321
+ this.dataset.source.y[r] = n(this.dataset.source.y[r]);
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], r = e[e.length - 1];
327
+ let o = Math.max(0, n - 1), i = Math.min(this.dataset.source.y.length - 1, r + 1);
325
328
  const h = this.dataset.source.x, l = this.dataset.source.y;
326
329
  for (let c = 0; c < e.length; c++)
327
330
  this.dataset.source.y[e[c]] = this._interpolateLinear(
328
331
  h[e[c]],
329
- h[n],
330
- l[n],
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, a, e, n, r) {
341
+ return e + (t - a) * (r - e) / (n - a);
339
342
  }
340
343
  /**
341
344
  * Shifts the selected indexes by specified amount of units. Elements are reinserted according to their datetime.
@@ -344,34 +347,34 @@ class G {
344
347
  * @param unit {@link TimeUnit}
345
348
  * @returns
346
349
  */
347
- async _shift(t, s, e) {
348
- const r = t.map((a) => [
349
- O(this.dataX[a], s, e),
350
- this.dataY[a]
350
+ async _shift(t, a, e) {
351
+ const n = t.map((r) => [
352
+ V(this.dataX[r], a, e),
353
+ this.dataY[r]
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, a, e, n) {
358
+ const r = navigator.hardwareConcurrency || 1, o = [], i = [], h = this.dataX.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
356
359
  maxByteLength: this.dataX.buffer.maxByteLength
357
360
  }), c = 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 u = 0; u < r; u++)
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 E = new C();
367
+ o.push(E), E.postMessage({
365
368
  bufferX: this.dataX.buffer,
366
369
  bufferY: this.dataY.buffer,
367
370
  outputBufferX: l,
368
371
  outputBufferY: c
369
- }), d.onmessage = (y) => {
370
- f(y.data);
372
+ }), E.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((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
375
378
  }
376
379
  /**
377
380
  * Find gaps and fill them with placeholder value
@@ -381,20 +384,20 @@ 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, a, e, n) {
388
+ const r = this._findGaps(t[0], t[1], n);
389
+ for (let o = r.length - 1; o >= 0; o--) {
390
+ const i = r[o], h = this.dataX[i[0]], l = this.dataX[i[1]], c = [], u = a[0] * A[a[1]] * 1e3;
391
+ let d = h + u;
392
+ for (; d < l; ) {
393
+ const E = 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
+ c.push([d, E]), d += u;
398
401
  }
399
402
  this._addDataPoints(c);
400
403
  }
@@ -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 a = navigator.hardwareConcurrency || 1, e = Math.ceil(this.dataX.length / a), n = [], r = [];
416
+ for (let u = 0; u < a; u++) {
417
+ const d = u * e, E = Math.min((u + 1) * e - 1, this.dataX.length - 1), g = k(t, d), _ = B(t, E), m = t.slice(g, _ + 1);
418
+ r.push({ start: d, end: E, 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(a).fill(0);
421
+ for (let u = 1; u < a; u++)
422
+ o[u] = o[u - 1] + r[u - 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
425
  }), c = 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 u = 0; u < a; u++) {
429
+ const { start: d, end: E, deleteSegment: g } = r[u], _ = d - o[u];
427
430
  i.push(
428
431
  new Promise((m) => {
429
- const E = new X();
430
- r.push(E), E.postMessage({
432
+ const w = new M();
433
+ n.push(w), w.postMessage({
431
434
  bufferX: this.dataX.buffer,
432
435
  bufferY: this.dataY.buffer,
433
436
  outputBufferX: l,
434
437
  outputBufferY: c,
435
- start: f,
436
- end: d,
437
- deleteSegment: y,
438
- startTarget: p
439
- }), E.onmessage = (F) => {
440
- m(F.data);
438
+ start: d,
439
+ end: E,
440
+ deleteSegment: g,
441
+ startTarget: _
442
+ }), w.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((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
446
449
  }
447
450
  /**
448
451
  *
@@ -450,10 +453,10 @@ class G {
450
453
  * @param end The end index
451
454
  * @param value The drift amount
452
455
  */
453
- _driftCorrection(t, s, e) {
454
- const r = this.dataset.source.x, a = this.dataset.source.y, n = r[t], h = r[s] - n;
455
- for (let l = t; l < s; l++)
456
- this.dataset.source.y[l] = a[l] + e * ((r[l] - n) / h);
456
+ _driftCorrection(t, a, e) {
457
+ const n = this.dataset.source.x, r = this.dataset.source.y, o = n[t], h = n[a] - o;
458
+ for (let l = t; l < a; l++)
459
+ this.dataset.source.y[l] = r[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]]`
@@ -461,27 +464,27 @@ class G {
461
464
  * @param index: the index array (sorted)
462
465
  */
463
466
  _getConsecutiveGroups(t) {
464
- const s = [[]];
465
- return t.reduce((e, r) => {
466
- const a = e[e.length - 1];
467
- return !a.length || r == a[a.length - 1] + 1 ? a.push(r) : e.push([r]), e;
468
- }, s), s;
467
+ const a = [[]];
468
+ return t.reduce((e, n) => {
469
+ const r = e[e.length - 1];
470
+ return !r.length || n == r[r.length - 1] + 1 ? r.push(n) : e.push([n]), e;
471
+ }, a), a;
469
472
  }
470
473
  /**
471
474
  * Adds data points. Their insert index is determined using `findFirstGreaterOrEqual` in the x-axis.
472
475
  * @param dataPoints
473
476
  */
474
477
  async _addDataPoints(t) {
475
- const s = this.dataX.length + t.length;
476
- this._growBuffer(s), t.sort((a, n) => a[0] - n[0]);
477
- const e = t.map((a) => B(this.dataX, a[0]) + 1);
478
- this._resizeTo(s), e.push(this.dataX.length);
479
- let r = t.length;
480
- 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];
478
+ const a = this.dataX.length + t.length;
479
+ this._growBuffer(a), t.sort((r, o) => r[0] - o[0]);
480
+ const e = t.map((r) => B(this.dataX, r[0]) + 1);
481
+ this._resizeTo(a), e.push(this.dataX.length);
482
+ let n = t.length;
483
+ for (let r = e.length - 1; r > 0; r--) {
484
+ const o = e[r - 1], i = e[r] - 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[r - 1][0], this.dataY[o + n] = t[r - 1][1];
485
488
  }
486
489
  }
487
490
  // =======================
@@ -493,13 +496,13 @@ class G {
493
496
  * @returns
494
497
  */
495
498
  _valueThreshold(t) {
496
- const s = [];
497
- return this.dataset.source.y.forEach((e, r) => {
498
- Object.keys(t).some((a) => P[a]?.(
499
+ const a = [];
500
+ return this.dataset.source.y.forEach((e, n) => {
501
+ Object.keys(t).some((r) => x[r]?.(
499
502
  e,
500
- t[a]
501
- )) && s.push(r);
502
- }), s;
503
+ t[r]
504
+ )) && a.push(n);
505
+ }), a;
503
506
  }
504
507
  /**
505
508
  *
@@ -507,14 +510,14 @@ class G {
507
510
  * @param value
508
511
  * @returns
509
512
  */
510
- _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]?.(
513
+ _rateOfChange(t, a) {
514
+ const e = [], n = this.dataset.source.y;
515
+ for (let r = 1; r < n.length; r++) {
516
+ const o = n[r - 1], h = (n[r] - o) / Math.abs(o);
517
+ U[t]?.(
515
518
  h,
516
- s
517
- ) && e.push(a);
519
+ a
520
+ ) && e.push(r);
518
521
  }
519
522
  return e;
520
523
  }
@@ -525,16 +528,16 @@ class G {
525
528
  * @param range If specified, the gaps will be found only within the range
526
529
  * @returns
527
530
  */
528
- _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;
531
+ _findGaps(t, a, e) {
532
+ const n = [], r = this.dataset.source.x;
533
+ let o = 0, i = r.length;
534
+ e?.[0] && e?.[1] && (o = e[0], i = e[1]);
535
+ let h = r[o];
536
+ for (let l = o + 1; l <= i; l++) {
537
+ const c = r[l];
538
+ c - h > t * A[a] * 1e3 && n.push([l - 1, l]), h = c;
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
@@ -542,15 +545,22 @@ class G {
542
545
  * @param range If specified, the points will be found only within the range
543
546
  * @returns
544
547
  */
545
- _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);
548
+ _persistence(t, a) {
549
+ let e = [], n = this.dataset.source.y, r = 0, o = n.length;
550
+ a?.[0] && a?.[1] && (r = a[0], o = a[1]);
551
+ let i = n[r], h = [];
552
+ for (let l = r + 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
+ f as EnumEditOperations,
559
+ T as EnumFilterOperations,
560
+ X as FilterOperation,
561
+ x as FilterOperationFn,
562
+ q as ObservationRecord,
563
+ y as Operator,
564
+ U as RateOfChangeComparator,
565
+ G as RateOfChangeOperation
556
566
  };
@@ -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(d,c){typeof exports=="object"&&typeof module<"u"?c(exports):typeof define=="function"&&define.amd?define(["exports"],c):(d=typeof globalThis<"u"?globalThis:d||self,c(d["@uwrl/qc-utils"]={}))})(this,function(d){"use strict";var c=(s=>(s.ADD_POINTS="ADD_POINTS",s.CHANGE_VALUES="CHANGE_VALUES",s.DELETE_POINTS="DELETE_POINTS",s.DRIFT_CORRECTION="DRIFT_CORRECTION",s.INTERPOLATE="INTERPOLATE",s.SHIFT_DATETIMES="SHIFT_DATETIMES",s.FILL_GAPS="FILL_GAPS",s))(c||{}),L=(s=>(s.FIND_GAPS="FIND_GAPS",s.PERSISTENCE="PERSISTENCE",s.RATE_OF_CHANGE="RATE_OF_CHANGE",s.VALUE_THRESHOLD="VALUE_THRESHOLD",s))(L||{}),R=(s=>(s.LT="Less than",s.LTE="Less than or equal to",s.GT="Greater than",s.GTE="Greater than or equal to",s.E="Equal",s.START="Start datetime",s.END="End datetime",s))(R||{});const B={"Less than":(s,t)=>s<t,"Less than or equal to":(s,t)=>s<=t,"Greater than":(s,t)=>s>t,"Greater than or equal to":(s,t)=>s>=t,Equal:(s,t)=>s==t,"Start datetime":(s,t)=>s==t,"End datetime":(s,t)=>s==t};var g=(s=>(s.ADD="ADD",s.SUB="SUB",s.MULT="MULT",s.DIV="DIV",s.ASSIGN="ASSIGN",s))(g||{}),I=(s=>(s.LT="Less than",s.LTE="Less than or equal to",s.GT="Greater than",s.GTE="Greater than or equal to",s.E="Equal",s))(I||{});const N={"Less than":(s,t)=>s<t,"Less than or equal to":(s,t)=>s<=t,"Greater than":(s,t)=>s>t,"Greater than or equal to":(s,t)=>s>=t,Equal:(s,t)=>s==t},F=`(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
+ `,Y=typeof self<"u"&&self.Blob&&new Blob([F],{type:"text/javascript;charset=utf-8"});function x(s){let t;try{if(t=Y&&(self.URL||self.webkitURL).createObjectURL(Y),!t)throw"";const a=new Worker(t,{name:s?.name});return a.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),a}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(F),{name:s?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const P=`(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
3
+ `,X=typeof self<"u"&&self.Blob&&new Blob([P],{type:"text/javascript;charset=utf-8"});function C(s){let t;try{if(t=X&&(self.URL||self.webkitURL).createObjectURL(X),!t)throw"";const a=new Worker(t,{name:s?.name});return a.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),a}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(P),{name:s?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const k=(s,t)=>{let a=0,e=s.length;for(;a<e;){const n=a+e>>1;s[n]<t?a=n+1:e=n}return a},G=(s,t)=>{let a=0,e=s.length;for(;a<e;){const n=a+e>>1;s[n]>t?e=n:a=n+1}return a-1},_=async(s,t)=>{const a=performance.now(),e=await s(),n=performance.now();console.log(` Done in ${(n-a).toFixed(2)} ms`);const r=+(n-a);return{response:e,duration:r}},U=1,M=U*60,p=M*60,w=p*24,O=w*7,v=p*30,H=w*365,A={s:U,m:M,h:p,D:w,W:O,M:v,Y:H},j=(s,t,a)=>{if(a==="M"){const e=new Date(s);return e.setMonth(e.getMonth()+t),e.getTime()}else if(a==="Y"){const e=new Date(s);return e.setFullYear(e.getFullYear()+t),e.getTime()}else return s+t*A[a]*1e3},T=20*1e3,q=["date","value","qualifier"];class V{dataset={dimensions:q,source:{x:new Float64Array(new SharedArrayBuffer(T*Float64Array.BYTES_PER_ELEMENT,{maxByteLength:T*Float64Array.BYTES_PER_ELEMENT})),y:new Float32Array(new SharedArrayBuffer(T*Float32Array.BYTES_PER_ELEMENT,{maxByteLength:T*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 a=await _(()=>{this._growBuffer(t.datetimes.length),this._resizeTo(t.datetimes.length),this.dataX.set(t.datetimes),this.dataY.set(t.dataValues)});this.loadingTime=a.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 a=t*Float64Array.BYTES_PER_ELEMENT;let e=this.dataX.buffer.byteLength;for(;a>e;)e+=T*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}),r=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:e*Float32Array.BYTES_PER_ELEMENT}),o=new Float64Array(n),i=new Float32Array(r);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 a=this.history.slice(0,t+1);await this.reload(),await this.dispatch(a.map(e=>[e.method,...e.args||[]]))}async removeHistoryItem(t){const a=[...this.history];a.splice(t,1),await this.reload(),await this.dispatch(a.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,...a){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 r=[];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,r.push(h.response)}}else{const o={method:t,args:a,icon:n[t],isLoading:!0};this.history.push(o);const i=await _(async()=>await e[t].apply(this,a));r=i.response,o.duration=i.duration,o.isLoading=!1}}catch(o){console.log(`Failed to execute operation: ${t} with arguments: `,a),console.log(o)}return r}async dispatchFilter(t,...a){const e={[L.FIND_GAPS]:this._findGaps,[L.VALUE_THRESHOLD]:this._valueThreshold,[L.PERSISTENCE]:this._persistence,[L.RATE_OF_CHANGE]:this._rateOfChange};let n=[];try{if(Array.isArray(t))for(let r=0;r<t.length;r++){const o=t[r][0],i=t[r].slice(1,t[r].length),h=await e[o].apply(this,i);n.push(h)}else n=await e[t].apply(this,a)}catch(r){console.log(`Failed to execute filter operation: ${t} with arguments: `,a),console.log(r)}return n}_changeValues(t,a,e){const n=r=>{switch(a){case g.ADD:return r+e;case g.ASSIGN:return e;case g.DIV:return r/e;case g.MULT:return r*e;case g.SUB:return r-e;default:return r}};t.forEach(r=>{this.dataset.source.y[r]=n(this.dataset.source.y[r])})}_interpolate(t){this._getConsecutiveGroups(t).forEach(e=>{const n=e[0],r=e[e.length-1];let o=Math.max(0,n-1),i=Math.min(this.dataset.source.y.length-1,r+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,a,e,n,r){return e+(t-a)*(r-e)/(n-a)}async _shift(t,a,e){const n=t.map(r=>[j(this.dataX[r],a,e),this.dataY[r]]);await this._deleteDataPoints(t),await this._addDataPoints(n)}async _fillGapsV2(t,a,e,n){const r=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<r;u++)i.push(new Promise(E=>{const y=new C;o.push(y),y.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f}),y.onmessage=m=>{E(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,a,e,n){const r=this._findGaps(t[0],t[1],n);for(let o=r.length-1;o>=0;o--){const i=r[o],h=this.dataX[i[0]],l=this.dataX[i[1]],f=[],u=a[0]*A[a[1]]*1e3;let E=h+u;for(;E<l;){const y=e?this._interpolateLinear(E,this.dataX[i[0]],this.dataY[i[0]],this.dataX[i[1]],this.dataY[i[1]]):-9999;f.push([E,y]),E+=u}this._addDataPoints(f)}}async _deleteDataPoints(t){const a=navigator.hardwareConcurrency||1,e=Math.ceil(this.dataX.length/a),n=[],r=[];for(let u=0;u<a;u++){const E=u*e,y=Math.min((u+1)*e-1,this.dataX.length-1),m=k(t,E),S=G(t,y),D=t.slice(m,S+1);r.push({start:E,end:y,deleteSegment:D})}const o=new Array(a).fill(0);for(let u=1;u<a;u++)o[u]=o[u-1]+r[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<a;u++){const{start:E,end:y,deleteSegment:m}=r[u],S=E-o[u];i.push(new Promise(D=>{const b=new x;n.push(b),b.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f,start:E,end:y,deleteSegment:m,startTarget:S}),b.onmessage=W=>{D(W.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,a,e){const n=this.dataset.source.x,r=this.dataset.source.y,o=n[t],h=n[a]-o;for(let l=t;l<a;l++)this.dataset.source.y[l]=r[l]+e*((n[l]-o)/h)}_getConsecutiveGroups(t){const a=[[]];return t.reduce((e,n)=>{const r=e[e.length-1];return!r.length||n==r[r.length-1]+1?r.push(n):e.push([n]),e},a),a}async _addDataPoints(t){const a=this.dataX.length+t.length;this._growBuffer(a),t.sort((r,o)=>r[0]-o[0]);const e=t.map(r=>G(this.dataX,r[0])+1);this._resizeTo(a),e.push(this.dataX.length);let n=t.length;for(let r=e.length-1;r>0;r--){const o=e[r-1],i=e[r]-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[r-1][0],this.dataY[o+n]=t[r-1][1]}}_valueThreshold(t){const a=[];return this.dataset.source.y.forEach((e,n)=>{Object.keys(t).some(r=>B[r]?.(e,t[r]))&&a.push(n)}),a}_rateOfChange(t,a){const e=[],n=this.dataset.source.y;for(let r=1;r<n.length;r++){const o=n[r-1],h=(n[r]-o)/Math.abs(o);N[t]?.(h,a)&&e.push(r)}return e}_findGaps(t,a,e){const n=[],r=this.dataset.source.x;let o=0,i=r.length;e?.[0]&&e?.[1]&&(o=e[0],i=e[1]);let h=r[o];for(let l=o+1;l<=i;l++){const f=r[l];f-h>t*A[a]*1e3&&n.push([l-1,l]),h=f}return n}_persistence(t,a){let e=[],n=this.dataset.source.y,r=0,o=n.length;a?.[0]&&a?.[1]&&(r=a[0],o=a[1]);let i=n[r],h=[];for(let l=r+1;l<o;l++)n[l]!=i||l===o?(h.length>=t&&(e=[...e,...h]),h=[]):h.push(l);return e}}d.EnumEditOperations=c,d.EnumFilterOperations=L,d.FilterOperation=R,d.FilterOperationFn=B,d.ObservationRecord=V,d.Operator=g,d.RateOfChangeComparator=N,d.RateOfChangeOperation=I,Object.defineProperty(d,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.15",
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
  }