@@ -31,6 +31,24 @@ type FilterData = {
31
31
} ;
32
32
export type FilterFn = ( p : FilterData ) => Partial < FilterData > ;
33
33
34
+ type FilterParam < K extends keyof typeof filters > = Parameters <
35
+ ( typeof filters ) [ K ]
36
+ > [ 0 ] ;
37
+
38
+ export type FilterInput = {
39
+ [ K in keyof typeof filters ] : FilterParam < K > extends undefined
40
+ ? // Case 1: Function accepts `undefined` only, return the key as a string literal
41
+ K
42
+ : undefined extends FilterParam < K >
43
+ ? object extends FilterParam < K >
44
+ ? // Case 2: Function accepts `object | undefined`, return union of the key or the object
45
+ { [ P in K ] : Exclude < FilterParam < K > , undefined > } | K
46
+ : // Case 3: Function accepts only `undefined`, return the key as a string literal
47
+ K
48
+ : // Case 4: Function accepts only an `object`, return object type
49
+ { [ P in K ] : FilterParam < K > } ;
50
+ } [ keyof typeof filters ] ;
51
+
34
52
const mapNumbers = ( ys : YValue [ ] , fn : ( y : number , i : number ) => number ) =>
35
53
ys . map ( ( y , i ) => {
36
54
const n = castFloat ( y ) ;
@@ -79,7 +97,7 @@ const filters = {
79
97
const mapping = mappingStr . map ( ( str ) => str . split ( "->" ) . map ( parseFloat ) ) ;
80
98
const regression = new LinearRegression (
81
99
mapping . map ( ( [ x , _y ] ) => x ) ,
82
- mapping . map ( ( [ _x , y ] ) => y )
100
+ mapping . map ( ( [ _x , y ] ) => y ) ,
83
101
) ;
84
102
return {
85
103
ys : regression . predict ( ys . map ( castFloat ) ) ,
@@ -150,7 +168,7 @@ const filters = {
150
168
unit ?: keyof typeof timeUnits ;
151
169
reset_every ?: TimeDurationStr ;
152
170
offset ?: TimeDurationStr ;
153
- } = "h"
171
+ } = "h" ,
154
172
) => {
155
173
const param =
156
174
typeof unitOrObject == "string" ? { unit : unitOrObject } : unitOrObject ;
@@ -197,7 +215,11 @@ const filters = {
197
215
} ;
198
216
} ,
199
217
sliding_window_moving_average :
200
- ( { window_size = 10 , extended = false , centered = true } = { } ) =>
218
+ ( {
219
+ window_size = 10 ,
220
+ extended = false ,
221
+ centered = true ,
222
+ } : { window_size ?: number ; extended ?: boolean ; centered ?: boolean } = { } ) =>
201
223
( params ) => {
202
224
const { xs, ys, ...rest } = force_numeric ( params ) ;
203
225
const ys2 : number [ ] = [ ] ;
@@ -227,7 +249,11 @@ const filters = {
227
249
return { xs : xs2 , ys : ys2 , ...rest } ;
228
250
} ,
229
251
median :
230
- ( { window_size = 10 , extended = false , centered = true } = { } ) =>
252
+ ( {
253
+ window_size = 10 ,
254
+ extended = false ,
255
+ centered = true ,
256
+ } : { window_size ?: number ; extended ?: boolean ; centered ?: boolean } = { } ) =>
231
257
( params ) => {
232
258
const { xs, ys, ...rest } = force_numeric ( params ) ;
233
259
const ys2 : number [ ] = [ ] ;
@@ -257,7 +283,7 @@ const filters = {
257
283
return { ys : ys2 , xs : xs2 , ...rest } ;
258
284
} ,
259
285
exponential_moving_average :
260
- ( { alpha = 0.1 } = { } ) =>
286
+ ( { alpha = 0.1 } : { alpha ?: number } = { } ) =>
261
287
( params ) => {
262
288
const { ys, ...rest } = force_numeric ( params ) ;
263
289
let last = ys [ 0 ] ;
@@ -268,37 +294,37 @@ const filters = {
268
294
} ,
269
295
map_y_numbers : ( fnStr : string ) => {
270
296
const fn = myEval (
271
- `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } `
297
+ `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } ` ,
272
298
) ;
273
299
return ( { xs, ys, states, statistics, meta, vars, hass } ) => ( {
274
300
xs,
275
301
ys : mapNumbers ( ys , ( _ , i ) =>
276
302
// prettier-ignore
277
- fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass )
303
+ fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass ) ,
278
304
) ,
279
305
} ) ;
280
306
} ,
281
307
map_y : ( fnStr : string ) => {
282
308
const fn = myEval (
283
- `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } `
309
+ `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } ` ,
284
310
) ;
285
311
return ( { xs, ys, states, statistics, meta, vars, hass } ) => ( {
286
312
xs,
287
313
ys : ys . map ( ( _ , i ) =>
288
314
// prettier-ignore
289
- fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass )
315
+ fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass ) ,
290
316
) ,
291
317
} ) ;
292
318
} ,
293
319
map_x : ( fnStr : string ) => {
294
320
const fn = myEval (
295
- `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } `
321
+ `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } ` ,
296
322
) ;
297
323
return ( { xs, ys, states, statistics, meta, vars, hass } ) => ( {
298
324
ys,
299
325
xs : xs . map ( ( _ , i ) =>
300
326
// prettier-ignore
301
- fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass )
327
+ fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass ) ,
302
328
) ,
303
329
} ) ;
304
330
} ,
@@ -357,31 +383,31 @@ const filters = {
357
383
throw new Error (
358
384
`Trendline '${ p . type } ' doesn't exist. Did you mean <b>${ propose (
359
385
p . type ,
360
- Object . keys ( trendlineTypes )
361
- ) } <b>?\nOthers: ${ Object . keys ( trendlineTypes ) } `
386
+ Object . keys ( trendlineTypes ) ,
387
+ ) } <b>?\nOthers: ${ Object . keys ( trendlineTypes ) } `,
362
388
) ;
363
389
}
364
390
const regression : BaseRegression = new RegressionClass (
365
391
xs_numbers ,
366
392
ys ,
367
- p . degree
393
+ p . degree ,
368
394
) ;
369
395
let extras : string [ ] = [ ] ;
370
396
if ( p . show_r2 )
371
397
extras . push (
372
- `r²=${ maxDecimals ( regression . score ( xs_numbers , ys ) . r2 , 2 ) } `
398
+ `r²=${ maxDecimals ( regression . score ( xs_numbers , ys ) . r2 , 2 ) } ` ,
373
399
) ;
374
400
375
401
if ( forecast > 0 ) {
376
402
const N = Math . round (
377
403
( xs_numbers . length /
378
404
( xs_numbers [ xs_numbers . length - 1 ] - xs_numbers [ 0 ] ) ) *
379
- forecast
405
+ forecast ,
380
406
) ;
381
407
xs_numbers . push (
382
408
...Array . from ( { length : N } ) . map (
383
- ( _ , i ) => t1 - t0 + ( forecast / N ) * i
384
- )
409
+ ( _ , i ) => t1 - t0 + ( forecast / N ) * i ,
410
+ ) ,
385
411
) ;
386
412
}
387
413
const ys_out = regression . predict ( xs_numbers ) ;
@@ -405,12 +431,12 @@ const filters = {
405
431
*/
406
432
filter : ( fnStr : string ) => {
407
433
const fn = myEval (
408
- `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } `
434
+ `(i, x, y, state, statistic, xs, ys, states, statistics, meta, vars, hass) => ${ fnStr } ` ,
409
435
) ;
410
436
return ( { xs, ys, states, statistics, meta, vars, hass } ) => {
411
437
const mask = ys . map ( ( _ , i ) =>
412
438
// prettier-ignore
413
- fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass )
439
+ fn ( i , xs [ i ] , ys [ i ] , states [ i ] , statistics [ i ] , xs , ys , states , statistics , meta , vars , hass ) ,
414
440
) ;
415
441
return {
416
442
ys : ys . filter ( ( _ , i ) => mask [ i ] ) ,
@@ -425,7 +451,7 @@ export default filters;
425
451
function checkTimeUnits ( unit : string ) {
426
452
if ( ! timeUnits [ unit ] ) {
427
453
throw new Error (
428
- `Unit '${ unit } ' is not valid, use ${ Object . keys ( timeUnits ) } `
454
+ `Unit '${ unit } ' is not valid, use ${ Object . keys ( timeUnits ) } ` ,
429
455
) ;
430
456
}
431
457
}
0 commit comments