Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
feat: display stdout and stderr in log
Browse files Browse the repository at this point in the history
improve output display with 'stdout', 'stderr' and better coloring system

closes #37
  • Loading branch information
woshilapin committed Nov 11, 2016
1 parent 6b79a76 commit dbfd164
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/codingame/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let parse = function parse(response) {
for (let parser of parsers) {
try {
let promise = parser.parse(body);
return Promise.resolve(promise); // Resume loop if not Error has been thrown
return Promise.resolve(promise); // Resume loop if no Error has been thrown
} catch (error) {
continue;
}
Expand Down
77 changes: 63 additions & 14 deletions src/codingame/parsers/frames.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* "success": {
* "frames": [{
* "gameInformation": `Landing phase starting\nX=2500m, Y=2700m, HSpeed=0m/s VSpeed=0m/s\nFuel=550l, Angle=0°, Power=0 (0.0m/s2)\n`,
* "stdout": "0 0",
* "stderr": "debug: speed 0",
* "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`,
* "keyframe": true
* }],
Expand All @@ -30,6 +32,65 @@ import CodingameError from '../error.js';

let name = `frames`;

/**
* Replace coloring tags from Codingame with ANSI colors for terminal
*
* @name colorize
* @function
* @param {String} message Input message with Codingame formatting
* @returns {String} Output message with ANSI coloring format
*/
let colorize = function colorize(message) {
const colorlist = `(RED|GREEN)`;
const beginchar = `¤`;
const endchar = `§`;
let regexp = new RegExp(`${beginchar}${colorlist}${beginchar}(.*)${endchar}${colorlist}${endchar}`)
let pattern = regexp.exec(message);
if (pattern !== null) {
let text = pattern[0];
let color = pattern[1].toLowerCase();
let subtext = pattern[2];
message = message.replace(text, colors[color](subtext))
}
return message;
};

/**
* Format the display of game frames
*
* @name formatFrames
* @function
* @param {Array} frames List of frames to display
* @returns {String} Formatted string to display information about the frames
*/
let formatFrames = function formatFrames(frames) {
let message = ``;
for(let frame of frames) {
let {
"gameInformation": gameInformation,
"stdout": stdout,
"stderr": stderr,
"view": view,
"keyframe": keyframe
} = frame;
if (stdout !== undefined) {
message += colors.bold(`Standard Output\n`);
message += stdout.trim();
message += `\n\n`;
}
if (stderr !== undefined) {
message += colors.bold(`Standard Error\n`);
message += colors.red(stderr.trim());
message += `\n\n`;
}
message += colors.bold(`Game Information\n`);
message += colorize(gameInformation.trim());
message += `\n\n`;
console.log(message);
}
return message;
};

/**
* Attempt to parse the body of a successful request to Codingame test API.
* This function will try to map a response with frames.
Expand All @@ -49,22 +110,10 @@ let parse = function parse(body) {
"metadata": metadata
} = body;
if (Array.isArray(frames) && gameId !== undefined && Array.isArray(scores) && typeof metadata === `object`) {
let message = formatFrames(frames);
if (scores[0] === 1) {
let message = frames[frames.length - 1].gameInformation;
return Promise.resolve(message);
return Promise.resolve(message.trim());
} else {
let message = ``;
for(let frame of frames) {
let gi = frame.gameInformation.trim();
let pattern = /¤RED¤.*§RED§/.exec(gi);
if (pattern !== null) {
let r = colors.red(pattern);
gi = gi.replace(pattern, r);
gi = gi.replace(/(¤|§)RED\1/g, '');
}
message += gi;
message += `\n\n`;
}
let error = new CodingameError(message.trim());
return Promise.reject(error);
}
Expand Down
26 changes: 20 additions & 6 deletions test/codingame/parse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,16 @@ describe(`[module] codingame/parse`, function() {
});
it(`should resolve with last information when frames are arriving`, function() {
let infos = `Landing phase starting\nX=2500m, Y=2700m, HSpeed=0m/s VSpeed=0m/s\nFuel=550l, Angle=0°, Power=0 (0.0m/s2)\n`;
let stdout = `0 0`;
let stderr = `debug information`;
let 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`;
let response = {
"success": {
"frames": [{
"gameInformation": infos,
"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`,
"stdout": stdout,
"stderr": stderr,
"view": view,
"keyframe": true
}],
"gameId": 154447808,
Expand All @@ -90,16 +95,23 @@ describe(`[module] codingame/parse`, function() {
};
let parse = cgparse.parse(response);
return expect(parse).to.be.fulfilled
.and.to.eventually.be.a.string(infos);
.and.to.eventually.be.with.a.string(infos.trim())
.and.with.a.string(stdout)
.and.with.a.string(stderr);
})
it(`should reject when frames are arriving but score is 0`, function() {
let subinfo = `Failure: Mars Lander crashed on non-flat ground. Opportunity has been destroyed.`;
let infos = `¤RED¤${subinfo}§RED§\nX=2500m, Y=1167m, HSpeed=0m/s VSpeed=-47m/s\nFuel=456l, Angle=0°, Power=4 (4.0m/s2)\n`;
let subinfo = `Success: Mars Lander landed hard but Opportunity is ok!`;
let infos = `¤GREEN¤${subinfo}§GREEN§\nX=2500m, Y=1167m, HSpeed=0m/s VSpeed=-47m/s\nFuel=456l, Angle=0°, Power=4 (4.0m/s2)\n`;
let stdout = `0 0`;
let stderr = `debug information`;
let 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`;
let response = {
"success": {
"frames": [{
"gameInformation": infos,
"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`,
"stdout": stdout,
"stderr": stderr,
"view": view,
"keyframe": true
}],
"gameId": 154447808,
Expand All @@ -112,7 +124,9 @@ describe(`[module] codingame/parse`, function() {
let parse = cgparse.parse(response);
return expect(parse).to.be.rejected
.and.to.eventually.have.a.property(`message`)
.with.string(subinfo);
.with.string(subinfo)
.and.with.a.string(stdout)
.and.with.a.string(stderr);
})
it(`should reject when bundle cannot compile`, function() {
let message = `SyntaxError: EOL while scanning string literal`;
Expand Down

0 comments on commit dbfd164

Please sign in to comment.