File size: 2,283 Bytes
8969f81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import * as util from 'util';
import * as child_process from 'child_process';
import { ObjectID } from 'mongodb';
const __exec = util.promisify(child_process.exec);


export namespace Utils {
	/**
	 * Return a random integer between min and max (upper bound is exclusive).
	 */
	export function randomInt(maxOrMin: number, max?: number): number {
		return (max)
			? maxOrMin + Math.floor(Math.random() * (max - maxOrMin))
			: Math.floor(Math.random() * maxOrMin);
	}
	
	/**
	 * Random element from array (usually not needed b/c we extend Array in Extensions.ts).
	 */
	export function randomItem<T>(arr: T[]): T {
		return arr[Math.floor(Math.random()*arr.length)];
	}

	/**
	 * Return copy of object, only keeping whitelisted properties.
	 */
	export function pick<T, K extends keyof T>(o: T, props: K[]): Pick<T, K> {
		// inspired by stackoverflow.com/questions/25553910/one-liner-to-take-some-properties-from-object-in-es-6
		// Warning: this adds {p: undefined} for props not in the o object.
		return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
	}
	/**
	 * One param:  create list of integers from 0 (inclusive) to n (exclusive)
	 * Two params: create list of integers from a (inclusive) to b (exclusive)
	 */
	export function range(n: number, b?: number): number[] {
		return (b)
			? Array(b - n).fill(0).map((_, i) => n + i)
			: Array(n).fill(0).map((_, i) => i);
	}
	
	/**
	 * Gets the value at path of object, or undefined.
	 */
	export function get(o: any, path: string | string[]) {
		const properties = Array.isArray(path) ? path : path.split('.');
		let x = o;
		for (const p of properties) {
			x = x[p];
			if (x === undefined) {
				return undefined;
			}
		}
		return x;
	}
	
	/**
	 * Asynchronously filter on the given array
	 */
	export async function filter<T>(array: T[], __filter: (element: T, index: number, array: T[]) => Promise<boolean>, thisArg?: any): Promise<T[]> {
		const keeps = await Promise.all(array.map(__filter));
		return array.filter((e, i) => keeps[i], thisArg);
	}
	
	export function randomStr(length: number): string {
		const chars = range(97, 123).map(x => String.fromCharCode(x));
		return Array(length).fill(0)
			.map(x => randomInt(2) ? randomItem(chars) : randomItem(chars).toUpperCase())
			.join("")
		;
	}
}