collapse PlayerLog entries
This commit is contained in:
parent
d140759ea5
commit
b0530be501
6 changed files with 211 additions and 166 deletions
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import PlayerLog from "./PlayerLog.svelte";
|
||||
import PlayerLog from "./log_viewer/PlayerLog.svelte";
|
||||
|
||||
export let matchLog: string;
|
||||
</script>
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { parsePlayerLog, PlayerLog } from "$lib/log_parser";
|
||||
|
||||
export let matchLog: string;
|
||||
export let playerId: number;
|
||||
export let showStdErr: boolean = true;
|
||||
|
||||
let playerLog: PlayerLog;
|
||||
|
||||
let showRawStderr = false;
|
||||
|
||||
const PLURAL_MAP = {
|
||||
dispatch: "dispatches",
|
||||
ship: "ships",
|
||||
};
|
||||
|
||||
function pluralize(num: number, word: string): string {
|
||||
if (num == 1) {
|
||||
return `1 ${word}`;
|
||||
} else {
|
||||
return `${num} ${PLURAL_MAP[word]}`;
|
||||
}
|
||||
}
|
||||
|
||||
$: if (matchLog) {
|
||||
playerLog = parsePlayerLog(playerId, matchLog);
|
||||
} else {
|
||||
playerLog = [];
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="output">
|
||||
{#if showRawStderr}
|
||||
<div class="output-text stderr-text">
|
||||
{playerLog.flatMap((turn) => turn.stderr).join("\n")}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="output-text">
|
||||
{#each playerLog as logTurn, i}
|
||||
<div class="turn">
|
||||
<div class="turn-header">
|
||||
<span class="turn-header-text">Turn {i}</span>
|
||||
{#if logTurn.action?.type === "dispatches"}
|
||||
{pluralize(logTurn.action.dispatches.length, "dispatch")}
|
||||
{:else if logTurn.action?.type === "timeout"}
|
||||
<span class="turn-error">timeout</span>
|
||||
{:else if logTurn.action?.type === "bad_command"}
|
||||
<span class="turn-error">invalid command</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if logTurn.action?.type === "dispatches"}
|
||||
<div class="dispatches-container">
|
||||
{#each logTurn.action.dispatches as dispatch}
|
||||
<div class="dispatch">
|
||||
<div class="dispatch-text">
|
||||
{pluralize(dispatch.ship_count, "ship")} from {dispatch.origin} to {dispatch.destination}
|
||||
</div>
|
||||
{#if dispatch.error}
|
||||
<span class="dispatch-error">{dispatch.error}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if logTurn.action?.type === "bad_command"}
|
||||
<div class="bad-command-container">
|
||||
<div class="bad-command-text">{logTurn.action.command}</div>
|
||||
<div class="bad-command-error">Parse error: {logTurn.action.error}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if showStdErr && logTurn.stderr.length > 0}
|
||||
<div class="stderr-header">stderr</div>
|
||||
<div class="stderr-text-box">
|
||||
{#each logTurn.stderr as stdErrMsg}
|
||||
<div class="stderr-text">{stdErrMsg}</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.output {
|
||||
background-color: rgb(41, 41, 41);
|
||||
}
|
||||
|
||||
.turn {
|
||||
margin: 16px 4px;
|
||||
}
|
||||
|
||||
.output-text {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.turn-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.turn-header-text {
|
||||
color: #eee;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.turn-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.dispatch {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dispatch-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.bad-command-container {
|
||||
border-left: 1px solid red;
|
||||
margin-left: 4px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.bad-command-text {
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.bad-command-error {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.stderr-text {
|
||||
// font-family: monospace;
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.stderr-header {
|
||||
color: #eee;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.stderr-text-box {
|
||||
border-left: 1px solid #ccc;
|
||||
margin-left: 4px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,160 @@
|
|||
<script lang="ts">
|
||||
import type { PlayerLogTurn } from "$lib/log_parser";
|
||||
import Fa from "svelte-fa";
|
||||
import { faAngleRight, faAngleDown } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export let turnNum: number;
|
||||
export let logTurn: PlayerLogTurn;
|
||||
let expanded = false;
|
||||
|
||||
const PLURAL_MAP = {
|
||||
dispatch: "dispatches",
|
||||
ship: "ships",
|
||||
};
|
||||
|
||||
function pluralize(num: number, word: string): string {
|
||||
if (num == 1) {
|
||||
return `1 ${word}`;
|
||||
} else {
|
||||
return `${num} ${PLURAL_MAP[word]}`;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleExpand() {
|
||||
expanded = !expanded;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="turn">
|
||||
<div class="turn-header" on:click={toggleExpand}>
|
||||
<span>
|
||||
<span class="turn-header-icon">
|
||||
{#if expanded}
|
||||
<Fa icon={faAngleDown} />
|
||||
{:else}
|
||||
<Fa icon={faAngleRight} />
|
||||
{/if}
|
||||
</span>
|
||||
<span class="turn-header-text">
|
||||
Turn {turnNum}
|
||||
</span>
|
||||
</span>
|
||||
{#if logTurn.action?.type === "dispatches"}
|
||||
{pluralize(logTurn.action.dispatches.length, "dispatch")}
|
||||
{:else if logTurn.action?.type === "timeout"}
|
||||
<span class="turn-error">timeout</span>
|
||||
{:else if logTurn.action?.type === "bad_command"}
|
||||
<span class="turn-error">invalid command</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if expanded}
|
||||
<div class="turn-content">
|
||||
{#if logTurn.action?.type === "dispatches"}
|
||||
<div class="dispatches-container">
|
||||
{#each logTurn.action.dispatches as dispatch}
|
||||
<div class="dispatch">
|
||||
<div class="dispatch-text">
|
||||
{pluralize(dispatch.ship_count, "ship")} from {dispatch.origin} to {dispatch.destination}
|
||||
</div>
|
||||
{#if dispatch.error}
|
||||
<span class="dispatch-error">{dispatch.error}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if logTurn.action?.type === "bad_command"}
|
||||
<div class="bad-command-container">
|
||||
<div class="bad-command-text">{logTurn.action.command}</div>
|
||||
<div class="bad-command-error">Parse error: {logTurn.action.error}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if logTurn.stderr.length > 0}
|
||||
<div class="stderr-header">stderr</div>
|
||||
<div class="stderr-text-box">
|
||||
{#each logTurn.stderr as stdErrMsg}
|
||||
<div class="stderr-text">{stdErrMsg}</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.turn {
|
||||
// padding: 4px 2px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.turn-header-icon {
|
||||
// padding-right: 0.2em;
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.turn-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.turn-header:hover {
|
||||
cursor: pointer;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.turn-header-text {
|
||||
color: #eee;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.turn-content {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.turn-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.dispatch {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dispatch-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.bad-command-container {
|
||||
border-left: 1px solid red;
|
||||
margin-left: 4px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.bad-command-text {
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.bad-command-error {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.stderr-text {
|
||||
// font-family: monospace;
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.stderr-header {
|
||||
color: #eee;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.stderr-text-box {
|
||||
border-left: 1px solid #ccc;
|
||||
margin-left: 4px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
</style>
|
39
web/pw-server/src/lib/components/log_viewer/PlayerLog.svelte
Normal file
39
web/pw-server/src/lib/components/log_viewer/PlayerLog.svelte
Normal file
|
@ -0,0 +1,39 @@
|
|||
<script lang="ts">
|
||||
import { parsePlayerLog, PlayerLog } from "$lib/log_parser";
|
||||
import LogTurn from "./LogTurn.svelte";
|
||||
|
||||
export let matchLog: string;
|
||||
export let playerId: number;
|
||||
|
||||
let playerLog: PlayerLog;
|
||||
let showRawStderr = false;
|
||||
|
||||
$: if (matchLog) {
|
||||
playerLog = parsePlayerLog(playerId, matchLog);
|
||||
} else {
|
||||
playerLog = [];
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="output">
|
||||
{#if showRawStderr}
|
||||
<div class="output-text stderr-text">
|
||||
{playerLog.flatMap((turn) => turn.stderr).join("\n")}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- The log should be rerendered when playerId changes -->
|
||||
{#key playerId}
|
||||
<div class="log-contents">
|
||||
{#each playerLog as logTurn, turnNum}
|
||||
<LogTurn {logTurn} {turnNum} />
|
||||
{/each}
|
||||
</div>
|
||||
{/key}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.output {
|
||||
background-color: rgb(41, 41, 41);
|
||||
}
|
||||
</style>
|
|
@ -22,7 +22,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import Visualizer from "$lib/components/Visualizer.svelte";
|
||||
import PlayerLog from "$lib/components/PlayerLog.svelte";
|
||||
import PlayerLog from "$lib/components/log_viewer/PlayerLog.svelte";
|
||||
import Select from "svelte-select";
|
||||
import { PLAYER_COLORS } from "$lib/constants";
|
||||
import { currentUser } from "$lib/stores/current_user";
|
||||
|
|
|
@ -51,6 +51,15 @@ export function set_loading(loading: boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
// this function should be called after resizes happen
|
||||
function do_resize() {
|
||||
resizeCanvasToDisplaySize(CANVAS);
|
||||
|
||||
if (game_instance) {
|
||||
game_instance.on_resize();
|
||||
}
|
||||
}
|
||||
|
||||
function clamp(min: number, max: number, value: number): number {
|
||||
if (value < min) {
|
||||
return min;
|
||||
|
@ -103,17 +112,7 @@ export function init() {
|
|||
GL.enable(GL.BLEND);
|
||||
GL.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
function () {
|
||||
resizeCanvasToDisplaySize(CANVAS);
|
||||
|
||||
if (game_instance) {
|
||||
game_instance.on_resize();
|
||||
}
|
||||
},
|
||||
{ capture: false, passive: true }
|
||||
);
|
||||
new ResizeObserver(do_resize).observe(ELEMENTS["canvas"]);
|
||||
|
||||
ELEMENTS["turnSlider"].oninput = function () {
|
||||
if (game_instance) {
|
||||
|
|
Loading…
Reference in a new issue