- A player's deck for a night is edited in a single form and written to their match rows and their standings row, so the two can't disagree. Matches, standings and hand imports all fill blank decks from the decks already entered, whatever order the files are imported in. The imported standings table shows decks read-only. - Admins can rename a league. - test/e2e.sh runs end-to-end checks against the local podman stack (fixtures by default, or real exports: test/e2e.sh sampledata). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
2.9 KiB
Plaintext
35 lines
2.9 KiB
Plaintext
<%- include('head') %>
|
||
<% if (admin) { %><datalist id="decks"><% known.forEach(k => { %><option value="<%= k %>"><% }) %></datalist><% } %>
|
||
<h1><%= lg.name %> – Session <%= gs.number %> (<%= gs.date %>)</h1>
|
||
<p><a href="<%= base %>/league/<%= lg.id %>">← Standings</a></p>
|
||
<% rounds.forEach(r => { %><h2>Round <%= r.round %></h2><table>
|
||
<% r.matches.forEach(m => { %><tr>
|
||
<td><%= m.p1 %> <small>(<%= m.p1_deck || '?' %>)</small></td>
|
||
<td><% if (m.p2) { %><%= m.p2 %> <small>(<%= m.p2_deck || '?' %>)</small><% } else { %><i>BYE</i><% } %></td>
|
||
<td><b><%= m.p1_wins %>–<%= m.p2_wins %><%= m.draws ? '–' + m.draws : '' %></b></td></tr>
|
||
<% }) %></table><% }) %>
|
||
<% if (!rounds.length && !results.length) { %><p>No results yet.</p><% } %>
|
||
<% if (admin && players.length) { %><h2>Decks played</h2>
|
||
<form method="post" action="<%= base %>/admin/session/<%= gs.id %>/decks"><table><tr><th>Player</th><th>Deck</th></tr>
|
||
<% players.forEach(p => { %><tr><td><%= p.name %></td><td><input name="deck_<%= p.id %>" value="<%= p.deck || '' %>" list="decks"></td></tr><% }) %></table>
|
||
<button>Save decks</button></form><% } %>
|
||
<% if (results.length) { %><h2>Standings <small>(imported)</small></h2>
|
||
<table><tr><th>Player</th><th>Points</th><th>W-D-L</th><th>Deck</th></tr>
|
||
<% results.forEach(r => { %><tr><td><%= r.name %></td><td><b><%= r.points %></b></td><td><%= r.rec %></td><td><%= r.deck || '' %></td></tr><% }) %></table>
|
||
<p><small>If this session also has match rows, those are used for scoring instead.</small></p><% } %>
|
||
<% if (admin) { %>
|
||
<h2>Import Melee export</h2>
|
||
<p>Upload the night's Melee exports (JSON or CSV): select every round's <b>matches</b> export and/or the <b>standings</b> export at once, or paste one.
|
||
Re-importing a round replaces just that round; a standings export replaces the imported standings. Decks you've entered are kept.
|
||
If anything in the batch is invalid, nothing is imported. If a session has matches, they are used for scoring.</p>
|
||
<form method="post" enctype="multipart/form-data" action="<%= base %>/admin/session/<%= gs.id %>/import-melee">
|
||
<input type="file" name="files" accept=".csv,.json,.txt" multiple><br>
|
||
<textarea name="data" rows="5" style="width:100%;font-family:monospace" placeholder="...or paste here"></textarea><br><button>Import</button></form>
|
||
<h2>Import matches by hand</h2>
|
||
<p>One match per line: <code>round, player1, deck1, player2, deck2, p1 wins, p2 wins, draws</code>. Leave player 2 blank for a bye.
|
||
Comma- or tab-separated. Saving <b>replaces</b> this session's matches; a blank deck keeps the one already entered.</p>
|
||
<form method="post" action="<%= base %>/admin/session/<%= gs.id %>/import">
|
||
<textarea name="data" rows="12" style="width:100%;font-family:monospace"><%= csvtext %></textarea><br><button>Save matches</button></form>
|
||
<form method="post" action="<%= base %>/admin/session/<%= gs.id %>/delete" data-confirm="Delete this session and its results?"><button>Delete session</button></form>
|
||
<% } %>
|