1
|
|
|
/** |
2
|
|
|
* @file Module 'codingame/parsers/frames' |
3
|
|
|
* @author woshilapin <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
/** |
6
|
|
|
* Parse response with frames from Codingame. |
7
|
|
|
* |
8
|
|
|
* The typical response in this case if of the following form. |
9
|
|
|
* ```json |
10
|
|
|
* { |
11
|
|
|
* "success": { |
12
|
|
|
* "frames": [{ |
13
|
|
|
* "gameInformation": `Landing phase starting\nX=2500m, Y=2700m, HSpeed=0m/s VSpeed=0m/s\nFuel=550l, Angle=0°, Power=0 (0.0m/s2)\n`, |
14
|
|
|
* "stdout": "0 0", |
15
|
|
|
* "stderr": "debug: speed 0", |
16
|
|
|
* "view": ` 0\n7000 3000 3.711 1.0 1.0 1 0 4 -90 90\n20 40 10 20 DIRECT 15 1\n7\n0 100\n1000 500\n1500 1500\n3000 1000\n4000 150\n5500 150\n6999 800\n2500 2700 0 0 550 0 0\n`, |
17
|
|
|
* "keyframe": true |
18
|
|
|
* }], |
19
|
|
|
* "gameId": 154447808, |
20
|
|
|
* "scores": [ 1 ], |
21
|
|
|
* "metadata": { |
22
|
|
|
* "fuel": 0 |
23
|
|
|
* } |
24
|
|
|
* } |
25
|
|
|
* } |
26
|
|
|
* ``` |
27
|
|
|
* @module codingame/parsers/failexpected |
28
|
|
|
*/ |
29
|
|
|
import colors from 'colors/safe'; |
30
|
|
|
|
31
|
|
|
import CodingameError from '../error.js'; |
32
|
|
|
|
33
|
|
|
let name = `frames`; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Replace coloring tags from Codingame with ANSI colors for terminal |
37
|
|
|
* |
38
|
|
|
* @name colorize |
39
|
|
|
* @function |
40
|
|
|
* @param {String} message Input message with Codingame formatting |
41
|
|
|
* @returns {String} Output message with ANSI coloring format |
42
|
|
|
*/ |
43
|
|
|
let colorize = function colorize(message) { |
|
|
|
|
44
|
|
|
const colorlist = `(RED|GREEN)`; |
45
|
|
|
const beginchar = `¤`; |
46
|
|
|
const endchar = `§`; |
47
|
|
|
let regexp = new RegExp(`${beginchar}${colorlist}${beginchar}(.*)${endchar}${colorlist}${endchar}`) |
48
|
|
|
let pattern = regexp.exec(message); |
49
|
|
|
if (pattern !== null) { |
50
|
|
|
let text = pattern[0]; |
51
|
|
|
let color = pattern[1].toLowerCase(); |
52
|
|
|
let subtext = pattern[2]; |
53
|
|
|
message = message.replace(text, colors[color](subtext)) |
54
|
|
|
} |
55
|
|
|
return message; |
56
|
|
|
}; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Format the display of game frames |
60
|
|
|
* |
61
|
|
|
* @name formatFrames |
62
|
|
|
* @function |
63
|
|
|
* @param {Array} frames List of frames to display |
64
|
|
|
* @returns {String} Formatted string to display information about the frames |
65
|
|
|
*/ |
66
|
|
|
let formatFrames = function formatFrames(frames) { |
|
|
|
|
67
|
|
|
let message = ``; |
68
|
|
|
for(let frame of frames) { |
69
|
|
|
let { |
70
|
|
|
"gameInformation": gameInformation, |
71
|
|
|
"stdout": stdout, |
72
|
|
|
"stderr": stderr, |
73
|
|
|
"view": view, |
74
|
|
|
"keyframe": keyframe |
75
|
|
|
} = frame; |
76
|
|
|
if (stdout !== undefined) { |
|
|
|
|
77
|
|
|
message += colors.bold(`Standard Output\n`); |
78
|
|
|
message += stdout.trim(); |
79
|
|
|
message += `\n\n`; |
80
|
|
|
} |
81
|
|
|
if (stderr !== undefined) { |
|
|
|
|
82
|
|
|
message += colors.bold(`Standard Error\n`); |
83
|
|
|
message += colors.red(stderr.trim()); |
84
|
|
|
message += `\n\n`; |
85
|
|
|
} |
86
|
|
|
message += colors.bold(`Game Information\n`); |
87
|
|
|
message += colorize(gameInformation.trim()); |
|
|
|
|
88
|
|
|
message += `\n\n`; |
89
|
|
|
console.log(message); |
|
|
|
|
90
|
|
|
} |
91
|
|
|
return message; |
92
|
|
|
}; |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Attempt to parse the body of a successful request to Codingame test API. |
96
|
|
|
* This function will try to map a response with frames. |
97
|
|
|
* |
98
|
|
|
* @function parse |
99
|
|
|
* @param {Object} body Body of the response |
100
|
|
|
* @returns {Promise<CodingameError>} Reject with a CodingameError if parsing was successful |
101
|
|
|
* @throws {Error} Throw is parsing failed |
102
|
|
|
* @instance |
103
|
|
|
*/ |
104
|
|
|
let parse = function parse(body) { |
|
|
|
|
105
|
|
|
try { |
106
|
|
|
let { |
107
|
|
|
"frames": frames, |
108
|
|
|
"gameId": gameId, |
109
|
|
|
"scores": scores, |
110
|
|
|
"metadata": metadata |
111
|
|
|
} = body; |
112
|
|
|
if (Array.isArray(frames) && gameId !== undefined && Array.isArray(scores) && typeof metadata === `object`) { |
|
|
|
|
113
|
|
|
let message = formatFrames(frames); |
114
|
|
|
if (scores[0] === 1) { |
115
|
|
|
return Promise.resolve(message.trim()); |
116
|
|
|
} else { |
117
|
|
|
let error = new CodingameError(message.trim()); |
118
|
|
|
return Promise.reject(error); |
119
|
|
|
} |
120
|
|
|
} else { |
121
|
|
|
throw `Success value should be false when expected and found properties are provided`; |
122
|
|
|
} |
123
|
|
|
} catch (error) { |
124
|
|
|
let message = `The body is not of response type '${name}'\n`; |
125
|
|
|
message += error.message; |
126
|
|
|
throw new Error(message); |
127
|
|
|
} |
128
|
|
|
}; |
129
|
|
|
|
130
|
|
|
export default { |
131
|
|
|
"name": name, |
132
|
|
|
"parse": parse |
133
|
|
|
}; |
134
|
|
|
|
This check looks for variables that are declared in multiple lines. There may be several reasons for this.
In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.
If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.