Change the bulk test results into a (slightly more compact) table

This commit is contained in:
Eevee (Evelyn Woods) 2021-01-03 13:48:11 -07:00
parent d1646532d5
commit 9cf2b82c8e
2 changed files with 118 additions and 55 deletions

View File

@ -2480,12 +2480,21 @@ class PackTestDialog extends DialogOverlay {
this.current_status = mk('p', "Ready"); this.current_status = mk('p', "Ready");
this.results = mk('ol.packtest-results.packtest-colorcoded'); this.results = mk('table.packtest-results.packtest-colorcoded',
mk('thead', mk('tr',
mk('th.-level', "Level"),
mk('th.-result', "Result"),
mk('th.-clock', "Play time"),
mk('th.-delta', "Replay delta"),
mk('th.-speed', "Run speed"),
)),
mk('tbody'),
);
this.results.addEventListener('click', ev => { this.results.addEventListener('click', ev => {
let li = ev.target.closest('li'); let tbody = ev.target.closest('tbody');
if (! li) if (! tbody)
return; return;
let index = li.getAttribute('data-index'); let index = tbody.getAttribute('data-index');
if (index === undefined) if (index === undefined)
return; return;
this.close(); this.close();
@ -2521,6 +2530,7 @@ class PackTestDialog extends DialogOverlay {
async run(handle) { async run(handle) {
let pack = this.conductor.stored_game; let pack = this.conductor.stored_game;
let tileset = this.conductor.tileset;
let dummy_sfx = { let dummy_sfx = {
set_player_position() {}, set_player_position() {},
play() {}, play() {},
@ -2540,7 +2550,9 @@ class PackTestDialog extends DialogOverlay {
} }
} }
this.results.textContent = ''; for (let tbody of this.results.querySelectorAll('tbody')) {
tbody.remove();
}
for (let li of this.results_summary.childNodes) { for (let li of this.results_summary.childNodes) {
li.removeAttribute('data-status'); li.removeAttribute('data-status');
} }
@ -2553,28 +2565,55 @@ class PackTestDialog extends DialogOverlay {
for (let i = 0; i < num_levels; i++) { for (let i = 0; i < num_levels; i++) {
let stored_level, level; let stored_level, level;
let status_li = this.results_summary.childNodes[i]; let status_li = this.results_summary.childNodes[i];
let record_result = (token, short_status, comment, include_canvas) => { let level_start_time = performance.now();
let record_result = (token, short_status, include_canvas, comment) => {
let level_title = stored_level ? stored_level.title : "???"; let level_title = stored_level ? stored_level.title : "???";
status_li.setAttribute('data-status', token); status_li.setAttribute('data-status', token);
status_li.setAttribute('title', `${short_status} (#${i + 1} ${level_title})`); status_li.setAttribute('title', `${short_status} (#${i + 1} ${level_title})`);
let li = mk( let tbody = mk('tbody', {'data-status': token, 'data-index': i});
'li', {'data-status': token, 'data-index': i}, status_li.addEventListener('click', () => {
`#${i + 1} ${level_title}: `, tbody.scrollIntoView();
comment); });
status_li.onclick = () => {
li.scrollIntoView(); let tr = mk('tr',
}; mk('td.-level', `#${i + 1} ${level_title}`),
mk('td.-result', short_status),
);
if (level) {
tr.append(
mk('td.-clock', util.format_duration(level.tic_counter / TICS_PER_SECOND)),
mk('td.-delta', util.format_duration((level.tic_counter - stored_level.replay.duration) / TICS_PER_SECOND, 2)),
mk('td.-speed', ((level.tic_counter / TICS_PER_SECOND) / (performance.now() - level_start_time) * 1000).toFixed(2) + '×'),
);
}
else {
tr.append(mk('td.-clock'), mk('td.-delta'), mk('td.-speed'));
}
tbody.append(tr);
if (comment) {
tbody.append(mk('tr', mk('td.-full', {colspan: 5}, comment)));
}
if (include_canvas && level) { if (include_canvas && level) {
try {
let canvas = mk('canvas', { let canvas = mk('canvas', {
width: this.renderer.canvas.width, width: Math.min(this.renderer.canvas.width, level.size_x * tileset.size_x),
height: this.renderer.canvas.height, height: Math.min(this.renderer.canvas.height, level.size_y * tileset.size_y),
}); });
this.renderer.set_level(level); this.renderer.set_level(level);
this.renderer.draw(); this.renderer.draw();
canvas.getContext('2d').drawImage(this.renderer.canvas, 0, 0, canvas.width, canvas.height); canvas.getContext('2d').drawImage(
li.append(canvas); this.renderer.canvas, 0, 0,
this.renderer.canvas.width, this.renderer.canvas.height);
tbody.append(mk('tr', mk('td.-full', {colspan: 5}, canvas)));
} }
this.results.append(li); catch (e) {
console.error(e);
tbody.append(mk('tr', mk('td.-full', {colspan: 5},
`Internal error while trying to capture screenshot: ${e}`)));
}
}
this.results.append(tbody);
if (level) { if (level) {
total_tics += level.tic_counter; total_tics += level.tic_counter;
@ -2584,7 +2623,7 @@ class PackTestDialog extends DialogOverlay {
try { try {
stored_level = pack.load_level(i); stored_level = pack.load_level(i);
if (! stored_level.has_replay) { if (! stored_level.has_replay) {
record_result('no-replay', "N/A", "No replay available"); record_result('no-replay', "No replay");
continue; continue;
} }
@ -2605,39 +2644,26 @@ class PackTestDialog extends DialogOverlay {
if (level.tic_counter < replay.duration - 10) { if (level.tic_counter < replay.duration - 10) {
// Early exit is dubious (e.g. this happened sometimes before multiple // Early exit is dubious (e.g. this happened sometimes before multiple
// players were implemented correctly) // players were implemented correctly)
record_result( record_result('early', "Won early", true);
'early', "Won early",
`Exited early after ${util.format_duration(level.tic_counter / TICS_PER_SECOND)} with ${util.format_duration((replay.duration - level.tic_counter) / TICS_PER_SECOND)} left in the replay`,
true);
} }
else { else {
record_result( record_result('success', "Won");
'success', "Won",
`Exited successfully after ${util.format_duration(level.tic_counter / TICS_PER_SECOND)} (delta ${level.tic_counter - replay.duration})`);
} }
num_passed += 1; num_passed += 1;
break; break;
} }
else if (level.state === 'failure') { else if (level.state === 'failure') {
record_result( record_result('failure', "Lost", true);
'failure', "Lost",
`Died at ${util.format_duration(level.tic_counter / TICS_PER_SECOND)} (tic ${level.tic_counter}/${replay.duration}, ${Math.floor(level.tic_counter / replay.duration * 100)}%)`,
true);
break; break;
} }
else if (level.tic_counter >= replay.duration + 200) { else if (level.tic_counter >= replay.duration + 200) {
record_result( record_result('short', "Out of input", true);
'short', "Out of input",
`Replay completed without exiting; ran for ${util.format_duration(replay.duration / TICS_PER_SECOND)}, gave up after 10 more seconds`,
true);
break; break;
} }
if (level.tic_counter % 20 === 1) { if (level.tic_counter % 20 === 1) {
if (handle.cancel) { if (handle.cancel) {
record_result( record_result('interrupted', "Interrupted");
'interrupted', "Interrupted",
"Interrupted");
this.current_status.textContent = `Interrupted on level ${i + 1}/${num_levels}; ${num_passed} passed`; this.current_status.textContent = `Interrupted on level ${i + 1}/${num_levels}; ${num_passed} passed`;
return; return;
} }
@ -2656,7 +2682,7 @@ class PackTestDialog extends DialogOverlay {
catch (e) { catch (e) {
console.error(e); console.error(e);
record_result( record_result(
'error', "Error", 'error', "Error", true,
`Replay failed due to internal error (see console for traceback): ${e}`); `Replay failed due to internal error (see console for traceback): ${e}`);
} }
} }
@ -2687,7 +2713,13 @@ class PackTestDialog extends DialogOverlay {
} }
} }
let final_status = `Finished! Simulated ${util.format_duration(total_tics / TICS_PER_SECOND)} of play time in ${util.format_duration((performance.now() - t0) / 1000)}; ${num_passed}/${num_levels} levels passed`; let total_game_time = total_tics / TICS_PER_SECOND;
let total_wall_time = (performance.now() - t0) / 1000;
let final_status = `Finished!
Simulated ${util.format_duration(total_game_time)} of play time
in ${util.format_duration(total_wall_time)}
(${(total_game_time / total_wall_time).toFixed(2)}×);
${num_passed}/${num_levels} levels passed`;
if (num_passed === num_levels) { if (num_passed === num_levels) {
final_status += "! Congratulations! 🎆"; final_status += "! Congratulations! 🎆";
} else { } else {

View File

@ -808,35 +808,66 @@ ol.packtest-summary > li {
flex: 1; flex: 1;
} }
.packtest-results { .packtest-results {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
margin-bottom: 1em; margin-bottom: 1em;
} }
.packtest-results > li { .packtest-results th {
padding: 0.25em; font-weight: normal;
margin: 0.25em 0;
} }
.packtest-results > li > canvas { .packtest-results tbody {
cursor: pointer;
border-top: 1px solid #0004;
}
.packtest-results tbody:hover {
outline: 2px solid #000;
}
.packtest-results td {
padding: 0.25em;
}
.packtest-results .-level {
text-align: left;
}
.packtest-results .-result {
width: 8em;
text-align: center;
}
.packtest-results .-clock {
width: 6em;
text-align: right;
}
.packtest-results .-delta {
width: 8em;
text-align: right;
}
.packtest-results .-speed {
width: 8em;
text-align: right;
}
.packtest-results canvas {
display: block; display: block;
margin: 0.5em auto; margin: 0.5em auto;
} }
ol.packtest-colorcoded > li[data-status=no-replay] { .packtest-colorcoded [data-status=no-replay] {
background: hsl(0, 0%, 25%); background: hsl(0, 0%, 25%);
} }
ol.packtest-colorcoded > li[data-status=running] { .packtest-colorcoded [data-status=running] {
background: hsl(30, 100%, 75%); background: hsl(30, 100%, 75%);
} }
ol.packtest-colorcoded > li[data-status=success] { .packtest-colorcoded [data-status=success] {
background: hsl(120, 60%, 75%); background: hsl(120, 60%, 75%);
} }
ol.packtest-colorcoded > li[data-status=early] { .packtest-colorcoded [data-status=early] {
background: hsl(75, 60%, 75%); background: hsl(75, 60%, 75%);
} }
ol.packtest-colorcoded > li[data-status=failure] { .packtest-colorcoded [data-status=failure] {
background: hsl(0, 60%, 60%); background: hsl(0, 60%, 60%);
} }
ol.packtest-colorcoded > li[data-status=short] { .packtest-colorcoded [data-status=short] {
background: hsl(330, 60%, 75%); background: hsl(330, 60%, 75%);
} }
ol.packtest-colorcoded > li[data-status=error] { .packtest-colorcoded [data-status=error] {
background: black; background: black;
color: white; color: white;
} }