human/src/util/util.ts

73 lines
3.2 KiB
TypeScript
Raw Normal View History

2021-12-27 16:59:56 +01:00
import type { Config } from '../exports';
2021-05-25 14:58:20 +02:00
/**
* Simple helper functions used accross codebase
*/
2021-03-21 12:49:55 +01:00
// helper function: wrapper around console output
2021-06-03 15:41:53 +02:00
export function log(...msg): void {
2021-03-21 12:49:55 +01:00
const dt = new Date();
const ts = `${dt.getHours().toString().padStart(2, '0')}:${dt.getMinutes().toString().padStart(2, '0')}:${dt.getSeconds().toString().padStart(2, '0')}.${dt.getMilliseconds().toString().padStart(3, '0')}`;
2022-08-21 19:34:51 +02:00
if (msg) console.log(ts, 'Human:', ...msg); // eslint-disable-line no-console
2021-03-21 12:49:55 +01:00
}
2021-11-14 17:22:52 +01:00
// helper function: join two paths
export function join(folder: string, file: string): string {
const separator = folder.endsWith('/') ? '' : '/';
const skipJoin = file.startsWith('.') || file.startsWith('/') || file.startsWith('http:') || file.startsWith('https:') || file.startsWith('file:');
const path = skipJoin ? `${file}` : `${folder}${separator}${file}`;
if (!path.toLocaleLowerCase().includes('.json')) throw new Error(`modelpath error: expecting json file: ${path}`);
return path;
}
2021-03-21 12:49:55 +01:00
// helper function: gets elapsed time on both browser and nodejs
export const now = () => {
if (typeof performance !== 'undefined') return performance.now();
return parseInt((Number(process.hrtime.bigint()) / 1000 / 1000).toString());
};
2021-09-19 20:07:53 +02:00
// helper function: checks current config validity
2022-08-21 19:34:51 +02:00
export function validate(defaults: Partial<Config>, config: Partial<Config>, parent = 'config', msgs: { reason: string, where: string, expected?: string }[] = []) {
2021-09-19 20:07:53 +02:00
for (const key of Object.keys(config)) {
if (typeof config[key] === 'object') {
validate(defaults[key], config[key], key, msgs);
} else {
2021-09-19 20:20:22 +02:00
const defined = defaults && (typeof defaults[key] !== 'undefined');
2021-09-19 20:07:53 +02:00
if (!defined) msgs.push({ reason: 'unknown property', where: `${parent}.${key} = ${config[key]}` });
2021-09-19 20:20:22 +02:00
const same = defaults && typeof defaults[key] === typeof config[key];
2021-09-19 20:07:53 +02:00
if (defined && !same) msgs.push({ reason: 'property type mismatch', where: `${parent}.${key} = ${config[key]}`, expected: typeof defaults[key] });
}
// ok = ok && defined && same;
}
if (config.debug && parent === 'config' && msgs.length > 0) log('invalid configuration', msgs);
return msgs;
}
2021-12-28 10:34:24 +01:00
// helper function: perform deep merge of multiple objects so it allows full inheritance with overrides
2021-03-21 12:49:55 +01:00
export function mergeDeep(...objects) {
const isObject = (obj) => obj && typeof obj === 'object';
return objects.reduce((prev, obj) => {
Object.keys(obj || {}).forEach((key) => {
const pVal = prev[key];
const oVal = obj[key];
if (Array.isArray(pVal) && Array.isArray(oVal)) prev[key] = pVal.concat(...oVal);
else if (isObject(pVal) && isObject(oVal)) prev[key] = mergeDeep(pVal, oVal);
else prev[key] = oVal;
});
return prev;
}, {});
}
2021-06-05 02:22:05 +02:00
// helper function: return min and max from input array
2022-08-21 19:34:51 +02:00
export const minmax = (data: number[]) => data.reduce((acc: number[], val) => {
2021-06-05 02:22:05 +02:00
acc[0] = (acc[0] === undefined || val < acc[0]) ? val : acc[0];
acc[1] = (acc[1] === undefined || val > acc[1]) ? val : acc[1];
return acc;
}, []);
2021-09-20 23:17:13 +02:00
// helper function: async wait
2021-11-17 22:50:21 +01:00
export async function wait(time: number) {
2021-11-10 18:21:45 +01:00
const waiting = new Promise((resolve) => { setTimeout(() => resolve(true), time); });
2021-09-20 23:17:13 +02:00
await waiting;
}