function.ts 7.91 KB
Newer Older
chicm-ms's avatar
chicm-ms committed
1
import * as JSON5 from 'json5';
Lijiao's avatar
Lijiao committed
2
3
import axios from 'axios';
import { MANAGER_IP } from './const';
4
import { MetricDataRecord, FinalType, TableObj } from './interface';
Lijiao's avatar
Lijiao committed
5

6
async function requestAxios(url: string): Promise<any> {
Lijiaoa's avatar
Lijiaoa committed
7
8
9
10
11
12
13
14
15
16
17
18
    const response = await axios.get(url);
    if (response.status === 200) {
        if (response.data.error !== undefined) {
            throw new Error(`API ${url} ${response.data.error}`);
        } else {
            return response.data as any;
        }
    } else {
        throw new Error(`API ${url} ${response.status} error`);
    }
}

Lijiao's avatar
Lijiao committed
19
const convertTime = (num: number): string => {
20
21
22
    if (num <= 0) {
        return '0';
    }
Lijiao's avatar
Lijiao committed
23
24
25
26
    if (num % 3600 === 0) {
        return num / 3600 + 'h';
    } else {
        const hour = Math.floor(num / 3600);
27
        const min = Math.floor((num / 60) % 60);
Lijiao's avatar
Lijiao committed
28
29
30
31
        return hour > 0 ? `${hour}h ${min}min` : `${min}min`;
    }
};

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
const convertTimeToSecond = (str: string): number => {
    let seconds = 0;
    let d, h, m;
    if (str.includes('d')) {
        [d, str] = str.split('d');
        seconds += parseInt(d) * 24 * 3600;
    }
    if (str.includes('h')) {
        [h, str] = str.split('h');
        seconds += parseInt(h) * 3600;
    }
    if (str.includes('m')) {
        [m, str] = str.split('m');
        seconds += parseInt(m) * 60;
    }
    if (str) {
        seconds += parseInt(str.split('s')[0]);
    }
    return seconds;
};

Lijiao's avatar
Lijiao committed
53
// trial's duration, accurate to seconds for example 10min 30s
54
55
56
57
58
59
const convertDuration = (seconds: number): string => {
    let str = '';

    const d = Math.floor(seconds / (24 * 3600));
    if (d > 0) {
        str += `${d}d `;
60
    }
61
62
63
64
65
    seconds -= d * 24 * 3600;

    const h = Math.floor(seconds / 3600);
    if (h > 0) {
        str += `${h}h `;
66
    }
67
68
69
70
71
    seconds -= h * 3600;

    const m = Math.floor(seconds / 60);
    if (m > 0) {
        str += `${m}m `;
72
    }
73
74
75
76
    seconds -= m * 60;

    if (seconds > 0) {
        str += `${Math.floor(seconds)}s`;
Lijiao's avatar
Lijiao committed
77
    }
78
    return str ? str : '0s';
Lijiao's avatar
Lijiao committed
79
80
};

81
function parseMetrics(metricData: string): any {
Lijiaoa's avatar
Lijiaoa committed
82
    if (metricData.includes('NaN') || metricData.includes('Infinity')) {
83
84
85
86
87
88
        return JSON5.parse(JSON5.parse(metricData));
    } else {
        return JSON.parse(JSON.parse(metricData));
    }
}

89
90
const isArrayType = (list: any): boolean | undefined => {
    return Array.isArray(list);
91
};
92

Lijiao's avatar
Lijiao committed
93
// get final result value
94
// draw Accuracy point graph
Lijiao's avatar
Lijiao committed
95
const getFinalResult = (final?: MetricDataRecord[]): number => {
Lijiao's avatar
Lijiao committed
96
97
98
    let acc;
    let showDefault = 0;
    if (final) {
99
        acc = parseMetrics(final[final.length - 1].data);
100
        if (typeof acc === 'object' && !isArrayType(acc)) {
Lijiao's avatar
Lijiao committed
101
102
103
            if (acc.default) {
                showDefault = acc.default;
            }
104
        } else if (typeof acc === 'number') {
Lijiao's avatar
Lijiao committed
105
            showDefault = acc;
106
107
        } else {
            showDefault = NaN;
Lijiao's avatar
Lijiao committed
108
109
110
111
112
113
        }
        return showDefault;
    } else {
        return 0;
    }
};
114

Lijiaoa's avatar
Lijiaoa committed
115
116
117
118
function isNaNorInfinity(val: number): boolean {
    return Object.is(val, NaN) || Object.is(val, Infinity);
}

119
// get final result value // acc obj
120
const getFinal = (final?: MetricDataRecord[]): FinalType | undefined => {
121
122
    let showDefault: FinalType;
    if (final) {
123
        showDefault = parseMetrics(final[final.length - 1].data);
124
        if (typeof showDefault === 'number') {
125
            if (!isNaNorInfinity(showDefault)) {
Lijiaoa's avatar
Lijiaoa committed
126
                return { default: showDefault };
127
            }
128
129
130
131
132
        } else if (isArrayType(showDefault)) {
            // not support final type
            return undefined;
        } else if (typeof showDefault === 'object' && showDefault.hasOwnProperty('default')) {
            return showDefault;
133
134
135
136
137
138
        }
    } else {
        return undefined;
    }
};

Lijiao's avatar
Lijiao committed
139
// detail page table intermediate button
Lijiao's avatar
Lijiao committed
140
const intermediateGraphOption = (intermediateArr: number[], id: string): any => {
Lijiao's avatar
Lijiao committed
141
142
143
144
145
146
147
148
149
150
151
    const sequence: number[] = [];
    const lengthInter = intermediateArr.length;
    for (let i = 1; i <= lengthInter; i++) {
        sequence.push(i);
    }
    return {
        title: {
            text: id,
            left: 'center',
            textStyle: {
                fontSize: 16,
152
                color: '#333'
Lijiao's avatar
Lijiao committed
153
154
155
156
157
158
            }
        },
        tooltip: {
            trigger: 'item'
        },
        xAxis: {
159
            // name: '#Intermediate result',
Lijiao's avatar
Lijiao committed
160
161
162
            data: sequence
        },
        yAxis: {
Lijiao's avatar
Lijiao committed
163
            name: 'Default metric',
Lijiao's avatar
Lijiao committed
164
            type: 'value',
Lijiaoa's avatar
Lijiaoa committed
165
166
            data: intermediateArr,
            scale: true
Lijiao's avatar
Lijiao committed
167
        },
168
169
170
171
172
173
174
        series: [
            {
                symbolSize: 6,
                type: 'scatter',
                data: intermediateArr
            }
        ]
Lijiao's avatar
Lijiao committed
175
176
177
178
    };
};

// kill job
Lijiao's avatar
Lijiao committed
179
const killJob = (key: number, id: string, status: string, updateList?: Function): void => {
Lijiao's avatar
Lijiao committed
180
181
182
183
184
185
186
187
    axios(`${MANAGER_IP}/trial-jobs/${id}`, {
        method: 'DELETE',
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        }
    })
        .then(res => {
            if (res.status === 200) {
188
189
                // TODO: use Message.txt to tooltip
                alert('Cancel the job successfully');
Lijiao's avatar
Lijiao committed
190
                // render the table
191
                if (updateList) {
192
                    updateList(); // FIXME
193
                }
Lijiao's avatar
Lijiao committed
194
            } else {
195
                alert('fail to cancel the job');
Lijiao's avatar
Lijiao committed
196
197
198
199
200
            }
        })
        .catch(error => {
            if (error.response.status === 500) {
                if (error.response.data.error) {
Lijiaoa's avatar
Lijiaoa committed
201
                    alert(error.response.data.error);
Lijiao's avatar
Lijiao committed
202
                } else {
Lijiaoa's avatar
Lijiaoa committed
203
                    alert('500 error, fail to cancel the job');
Lijiao's avatar
Lijiao committed
204
205
206
207
208
                }
            }
        });
};

209
const filterByStatus = (item: TableObj): boolean => {
210
211
212
    return item.status === 'SUCCEEDED';
};

213
// a waittiong trial may havn't start time
214
const filterDuration = (item: TableObj): boolean => {
215
216
217
    return item.status !== 'WAITING';
};

Lijiao's avatar
Lijiao committed
218
const downFile = (content: string, fileName: string): void => {
v-liguo's avatar
v-liguo committed
219
220
221
222
223
224
225
226
227
228
229
    const aTag = document.createElement('a');
    const isEdge = navigator.userAgent.indexOf('Edge') !== -1 ? true : false;
    const file = new Blob([content], { type: 'application/json' });
    aTag.download = fileName;
    aTag.href = URL.createObjectURL(file);
    aTag.click();
    if (!isEdge) {
        URL.revokeObjectURL(aTag.href);
    }
    if (navigator.userAgent.indexOf('Firefox') > -1) {
        const downTag = document.createElement('a');
230
        downTag.addEventListener('click', function() {
v-liguo's avatar
v-liguo committed
231
232
233
            downTag.download = fileName;
            downTag.href = URL.createObjectURL(file);
        });
chicm-ms's avatar
chicm-ms committed
234
        const eventMouse = document.createEvent('MouseEvents');
v-liguo's avatar
v-liguo committed
235
236
237
238
239
        eventMouse.initEvent('click', false, false);
        downTag.dispatchEvent(eventMouse);
    }
};

240
241
242
243
244
// function formatTimestamp(timestamp?: number, placeholder?: string = 'N/A'): string {
function formatTimestamp(timestamp?: number, placeholder?: string): string {
    if (placeholder === undefined) {
        placeholder = 'N/A';
    }
245
246
247
248
    return timestamp ? new Date(timestamp).toLocaleString('en-US') : placeholder;
}

function metricAccuracy(metric: MetricDataRecord): number {
chicm-ms's avatar
chicm-ms committed
249
    const data = parseMetrics(metric.data);
250
251
252
253
254
255
    // return typeof data === 'number' ? data : NaN;
    if (typeof data === 'number') {
        return data;
    } else {
        return data.default;
    }
256
257
258
259
}

function formatAccuracy(accuracy: number): string {
    // TODO: how to format NaN?
260
261
262
263
    return accuracy
        .toFixed(6)
        .replace(/0+$/, '')
        .replace(/\.$/, '');
264
265
}

Lijiaoa's avatar
Lijiaoa committed
266
267
268
269
270
271
272
273
function formatComplexTypeValue(value: any): string | number {
    if (['number', 'string'].includes(typeof value)) {
        return value;
    } else {
        return value.toString();
    }
}

274
export {
275
276
    convertTime,
    convertDuration,
277
    convertTimeToSecond,
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    getFinalResult,
    getFinal,
    downFile,
    intermediateGraphOption,
    killJob,
    filterByStatus,
    filterDuration,
    formatAccuracy,
    formatTimestamp,
    metricAccuracy,
    parseMetrics,
    isArrayType,
    requestAxios,
    isNaNorInfinity,
    formatComplexTypeValue
293
};