commit d5ed5a9e86e8a23554044f1d49907cac9609ca9a
parent 445b263205d56388d7eede3de9fc60239f04acb0
Author: alex wennerberg <alex@alexwennerberg.com>
Date: Fri, 12 Sep 2025 13:21:11 -0400
vibe coding
Diffstat:
| M | main.rb | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
| M | views/round.erb | | | 179 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
2 files changed, 214 insertions(+), 19 deletions(-)
diff --git a/main.rb b/main.rb
@@ -15,10 +15,60 @@ end
get '/round/:id' do |id|
@round = db.execute("select * from round where id = ?", id)[0]
- @matches = db.execute "select * from round_score where round = ? order by final_score desc,prelim_score desc", id
+
+ # Get deck data for all players in this round
+ @player_decks = {}
+ deck_data = db.execute("SELECT player, card1, card2, card3 FROM deck WHERE round = ?", [id])
+ deck_data.each do |deck|
+ @player_decks[deck["player"]] = [deck["card1"], deck["card2"], deck["card3"]]
+ end
+
+ # Get group matches organized by group
+ @group_matches = {}
+ groups = db.execute("SELECT DISTINCT group_name FROM match WHERE round = ? AND group_name != 'final' AND group_name IS NOT NULL ORDER BY group_name", [id])
+
+ groups.each do |group|
+ group_name = group["group_name"]
+ players = db.execute("SELECT DISTINCT player FROM match WHERE round = ? AND group_name = ? ORDER BY player", [id, group_name])
+ matches_data = db.execute("SELECT player, opp_player, score FROM match WHERE round = ? AND group_name = ?", [id, group_name])
+
+ # Create grid structure
+ match_grid = {}
+ matches_data.each do |match|
+ player = match["player"]
+ opp = match["opp_player"]
+ score = match["score"]
+ match_grid[player] ||= {}
+ match_grid[player][opp] = score
+ end
+
+ @group_matches[group_name] = {
+ 'players' => players.map { |p| p["player"] },
+ 'matches' => match_grid
+ }
+ end
+
+ # Get finals matches
+ finals_players = db.execute("SELECT DISTINCT player FROM match WHERE round = ? AND group_name = 'final' ORDER BY player", [id])
+ @finals_matches = {}
+ @finals_players = []
+
+ if finals_players.length > 0
+ @finals_players = finals_players.map { |p| p["player"] }
+ finals_data = db.execute("SELECT player, opp_player, score FROM match WHERE round = ? AND group_name = 'final'", [id])
+
+ finals_data.each do |match|
+ player = match["player"]
+ opp = match["opp_player"]
+ score = match["score"]
+ @finals_matches[player] ||= {}
+ @finals_matches[player][opp] = score
+ end
+ end
+
@banned_cards = db.execute("select name from ban").map { |row| row["name"] }
@subtitle = "round " + id
- erb :matches
+ erb :round
end
get '/card' do
diff --git a/views/round.erb b/views/round.erb
@@ -1,21 +1,165 @@
<%= erb :header %>
- <% if @round %>
- <a href='https://docs.google.com/spreadsheets/d/<%= @round["fileid"] %>/'>Google Sheet</a><% end %>
-<div class="flextable">
- <% @matches.each do |match| %>
- <div class="deck-box"
- <% if match["final_score"] %> style="background:#ffffc5"<% end %>>
- <div style="width:160px">
- <b><a href='/player/<%= match["player"] %>'><%= match["player"] %></a></b><br>
- <a href="/round/<%= match["round"]%>"><%= match["round"] %></a>
- <a href="/deck?card=<%= match["card1"] %>&card=<%= match["card2"] %>card= <%= match["card3"]%>>deck</a><br>
- Group <%= match["prelim_group"] %>: <%=match["prelim_score"]%><br>
- <% if match["final_score"] %>Finals: <%= match["final_score"] %><% end %>
-</div>
-<div>
- <% [match["card1"], match["card2"], match["card3"]].each do |card| %><img alt='<%= card %>' width=146height=204px loading=lazy src="https://api.scryfall.com/cards/named?exact=<%= card %>&format=image&version=small" /><% end %>
-</div>
+<% if @round %>
+<a href='https://docs.google.com/spreadsheets/d/<%= @round["fileid"] %>/'>Google Sheet</a><% end %>
+
+<style>
+.match-grid {
+ margin-bottom: 30px;
+}
+.match-grid h2 {
+ margin-bottom: 10px;
+}
+.grid-table {
+ border-collapse: collapse;
+ margin-bottom: 20px;
+}
+.grid-table th, .grid-table td {
+ border: 1px solid #ccc;
+ padding: 8px;
+ text-align: center;
+ min-width: 80px;
+}
+.grid-table .opponent-header,
+.grid-table .score-cell:not(:last-child) {
+ width: 80px;
+ max-width: 80px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.grid-table th {
+ background-color: #f0f0f0;
+ font-weight: bold;
+}
+.grid-table .player-name {
+ background-color: #f8f8f8;
+ font-weight: bold;
+ text-align: left;
+ min-width: 120px;
+}
+.grid-table .diagonal {
+ background-color: #e0e0e0;
+}
+.score-cell {
+ font-weight: bold;
+}
+.score-0 { color: #ff0000; }
+.score-low { color: #ff6600; }
+.score-high { color: #0066ff; }
+.score-very-high { color: #00aa00; }
+</style>
+
+<% if @group_matches && @group_matches.length > 0 %>
+<h1>Group Stage</h1>
+<% @group_matches.each do |group_name, group_data| %>
+<div class="match-grid">
+ <h2>Group <%= group_name %></h2>
+ <table class="grid-table">
+ <thead>
+ <tr>
+ <th>vs</th>
+ <th>Cards</th>
+ <% group_data['players'].each do |opponent| %>
+ <th class="opponent-header"><%= opponent %></th>
+ <% end %>
+ <th>Total</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% group_data['players'].each do |player| %>
+ <tr>
+ <td class="player-name">
+ <a href="/player?name=<%= url_encode(player) %>"><%= player %></a>
+ </td>
+ <td class="hover_img">
+ <% if @player_decks[player] %>
+ <% @player_decks[player].each do |card| %>
+ <a href="/card?name=<%= url_encode(card) %>"><%= card %><span><img src="https://api.scryfall.com/cards/named?exact=<%= url_encode(card) %>&format=image&version=small" alt="<%= card %>" /></span></a><% unless card == @player_decks[player].last %>, <% end %>
+ <% end %>
+ <% end %>
+ </td>
+ <% player_total = 0 %>
+ <% group_data['players'].each do |opponent| %>
+ <% if player == opponent %>
+ <td class="diagonal">-</td>
+ <% else %>
+ <% score = group_data['matches'][player] && group_data['matches'][player][opponent] ? group_data['matches'][player][opponent] : 0 %>
+ <% player_total += score %>
+ <% score_class = case score
+ when 0 then 'score-0'
+ when 1..2 then 'score-low'
+ when 3..5 then 'score-high'
+ else 'score-very-high'
+ end %>
+ <td class="score-cell <%= score_class %>">
+ <%= score %>
+ </td>
+ <% end %>
+ <% end %>
+ <td class="score-cell"><strong><%= player_total %></strong></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
</div>
<% end %>
+<% end %>
+
+<% if @finals_matches && @finals_players.length > 0 %>
+<div class="match-grid">
+ <h1>Finals</h1>
+ <table class="grid-table">
+ <thead>
+ <tr>
+ <th>vs</th>
+ <th>Cards</th>
+ <% @finals_players.each do |opponent| %>
+ <th class="opponent-header"><%= opponent %></th>
+ <% end %>
+ <th>Total</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @finals_players.each do |player| %>
+ <tr>
+ <td class="player-name">
+ <a href="/player?name=<%= url_encode(player) %>"><%= player %></a>
+ </td>
+ <td class="hover_img">
+ <% if @player_decks[player] %>
+ <% @player_decks[player].each do |card| %>
+ <a href="/card?name=<%= url_encode(card) %>"><%= card %><span><img src="https://api.scryfall.com/cards/named?exact=<%= url_encode(card) %>&format=image&version=small" alt="<%= card %>" /></span></a><% unless card == @player_decks[player].last %>, <% end %>
+ <% end %>
+ <% end %>
+ </td>
+ <% player_total = 0 %>
+ <% @finals_players.each do |opponent| %>
+ <% if player == opponent %>
+ <td class="diagonal">-</td>
+ <% else %>
+ <% score = @finals_matches[player] && @finals_matches[player][opponent] ? @finals_matches[player][opponent] : 0 %>
+ <% player_total += score %>
+ <% score_class = case score
+ when 0 then 'score-0'
+ when 1..2 then 'score-low'
+ when 3..5 then 'score-high'
+ else 'score-very-high'
+ end %>
+ <td class="score-cell <%= score_class %>">
+ <%= score %>
+ </td>
+ <% end %>
+ <% end %>
+ <td class="score-cell"><strong><%= player_total %></strong></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
</div>
-<%= erb :footer %>
+<% end %>
+
+<% if (!@group_matches || @group_matches.length == 0) && (!@finals_matches || @finals_players.length == 0) %>
+ <p>No matches found for this round.</p>
+<% end %>
+
+<%= erb :footer %>
+\ No newline at end of file