-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathutils.ts
143 lines (128 loc) · 4.2 KB
/
utils.ts
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import { createReadStream, existsSync, readFileSync } from 'fs';
import { load } from 'js-yaml';
import pWaitFor from 'p-wait-for';
const dateformat = require('dateformat');
const CsvReadableStream = require('csv-reader');
export function readFileAsObj(path: string) {
if (!existsSync(path)) {
return null;
}
const content = readFileSync(path).toString();
if (path.toLocaleLowerCase().endsWith('.json')) {
// json format
try {
return JSON.parse(content);
} catch (e) {
console.log(`Parse JSON content failed, e=${e}`);
return null;
}
} else if (path.toLocaleLowerCase().endsWith('.yaml') || path.toLocaleLowerCase().endsWith('.yml')) {
// yaml format
try {
return load(content, { json: true });
} catch (e) {
console.log(`Parse YAML content failed, e=${e}`);
return null;
}
}
return null;
}
export async function readCsvLine(path: string, online: (row: string[]) => any): Promise<void> {
return new Promise(resolve => {
const inputStream = createReadStream(path, 'utf-8');
inputStream
.pipe(new CsvReadableStream({ trim: true, skipHeader: true }))
.on('data', (row: string[]) => {
online(row);
})
.on('end', () => {
resolve();
});
});
}
export async function waitFor(mill: number): Promise<void> {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, mill);
});
}
export async function waitUntil(func: () => boolean, options?: object): Promise<void> {
if (func()) return;
return pWaitFor(func, Object.assign({ interval: 1000 }, options));
}
interface rankDataResultItem<T> {
item: T;
rank: number;
value: number;
rankDelta: number;
valueDelta: number;
};
export function rankData<T = any>(data: T[], iterArr: any[], getter: (item: T, iterItem: any, iterIndex: number) => number, itemIdentifiterGetter: (item: T, iterIndex: number) => any): Map<any, rankDataResultItem<T>[]> {
const result = new Map<any, rankDataResultItem<T>[]>();
const lastRankMap = new Map<any, { rank: number; value: number; }>();
data.forEach(i => lastRankMap.set(i, { rank: -1, value: 0 }));
for (let iterIndex = 0; iterIndex < iterArr.length; iterIndex++) {
const iterItem = iterArr[iterIndex];
const iterResult: any[] = [];
data = data.sort((a, b) => (getter(b, iterItem, iterIndex) ?? 0) - (getter(a, iterItem, iterIndex) ?? 0));
data.forEach((i: any, index) => {
const rank = getter(i, iterItem, iterIndex) ? index + 1 : -1;
const value = parseFloat((getter(i, iterItem, iterIndex) ?? 0).toFixed(2));
const lastRank = lastRankMap.get(i)!;
lastRankMap.set(i, { rank, value });
if (rank === -1) return;
iterResult.push({
item: itemIdentifiterGetter(i, iterIndex),
rank,
value,
rankDelta: lastRank.rank === -1 ? 0 : lastRank.rank - rank,
valueDelta: parseFloat((value - lastRank.value).toFixed(2)),
});
});
result.set(iterItem, iterResult);
}
return result;
}
export const getLogger = (tag: string) => {
const log = (level: string, ...args: any[]) =>
console.log(`${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')} ${level} [${tag}]`, ...args);
return {
info: (...args: any[]) => log('INFO', ...args),
warn: (...args: any[]) => log('WARN', ...args),
error: (...args: any[]) => log('ERROR', ...args),
};
};
export class ArrayMap<T> {
private array: T[];
private map: Map<any, number>;
private keyGetter: (item: T) => any;
constructor(arr: T[], keyGetter?: (item: T) => any) {
this.array = [];
this.map = new Map();
this.keyGetter = keyGetter ?? (i => i);
arr.forEach(i => this.add(i));
}
public get length() {
return this.array.length;
}
public get(key: any): T | undefined {
const index = this.map.get(key);
return index === undefined ? undefined : this.array[index];
}
public getIndex(key: any): number {
return this.map.get(key) ?? -1;
}
public add(item: T) {
const key = this.keyGetter(item);
if (this.map.has(key)) {
this.array[this.map.get(key)!] = item;
} else {
this.map.set(key, this.array.length);
this.array.push(item);
}
}
public getArray(): T[] {
return [...this.array];
}
}