From 4a77e55a8ff0adba7cc7cf3d8d5263448ab94580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Sun, 24 Jan 2021 20:44:57 +0000 Subject: [PATCH] feat: Add delta and median function --- src/graphEntry.ts | 18 +++++++++++++++++- src/types-config-ti.ts | 2 +- src/types-config.ts | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/graphEntry.ts b/src/graphEntry.ts index 197a4cb..7ea3df3 100644 --- a/src/graphEntry.ts +++ b/src/graphEntry.ts @@ -48,6 +48,8 @@ export default class GraphEntry { first: this._first, last: this._last, sum: this._sum, + median: this._median, + delta: this._delta, }; this._index = index; this._cache = cache; @@ -177,7 +179,7 @@ export default class GraphEntry { this._history = history; if (this._config.group_by.func !== 'raw') { this._computedHistory = this._dataBucketer().map((bucket) => { - return [(new Date(bucket.timestamp) as any) as number, this._func(bucket.data)]; + return [(new Date(bucket.timestamp) as unknown) as number, this._func(bucket.data)]; }); } this._updating = false; @@ -295,6 +297,20 @@ export default class GraphEntry { return items[0][1]; } + private _median(items: EntityCachePoints) { + const itemsDup = this._filterNulls([...items]).sort((a, b) => a[1]! - b[1]!); + const mid = Math.floor((itemsDup.length - 1) / 2); + if (itemsDup.length % 2 === 1) return itemsDup[mid]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return (itemsDup[mid][1]! + itemsDup[mid + 1][1]!) / 2; + } + + private _delta(items: EntityCachePoints): number | null { + const max = this._maximum(items); + const min = this._minimum(items); + return max === null || min === null ? null : max - min; + } + private _filterNulls(items: EntityCachePoints): EntityCachePoints { return items.filter((item) => item[1] !== null); } diff --git a/src/types-config-ti.ts b/src/types-config-ti.ts index 78c7712..71804ba 100644 --- a/src/types-config-ti.ts +++ b/src/types-config-ti.ts @@ -34,7 +34,7 @@ export const ChartCardSeriesExternalConfig = t.iface([], { export const GroupByFill = t.union(t.lit('null'), t.lit('last'), t.lit('zero')); -export const GroupByFunc = t.union(t.lit('raw'), t.lit('avg'), t.lit('min'), t.lit('max'), t.lit('last'), t.lit('first'), t.lit('sum')); +export const GroupByFunc = t.union(t.lit('raw'), t.lit('avg'), t.lit('min'), t.lit('max'), t.lit('last'), t.lit('first'), t.lit('sum'), t.lit('median'), t.lit('delta')); export const ChartCardHeaderExternalConfig = t.iface([], { "show": t.opt("boolean"), diff --git a/src/types-config.ts b/src/types-config.ts index 9d49137..d7ab108 100644 --- a/src/types-config.ts +++ b/src/types-config.ts @@ -29,7 +29,7 @@ export interface ChartCardSeriesExternalConfig { export type GroupByFill = 'null' | 'last' | 'zero'; -export type GroupByFunc = 'raw' | 'avg' | 'min' | 'max' | 'last' | 'first' | 'sum'; +export type GroupByFunc = 'raw' | 'avg' | 'min' | 'max' | 'last' | 'first' | 'sum' | 'median' | 'delta'; export interface ChartCardHeaderExternalConfig { show?: boolean;