Factor out rendering of game participants

This commit is contained in:
Jack Jackson 2024-06-26 19:23:04 -07:00
parent 61078f0201
commit 01e4c5e36b
5 changed files with 37 additions and 15 deletions

View File

@ -20,6 +20,7 @@
- [ ] "Display components" like "a tables of games" that can be inserted into multiple pages - [ ] "Display components" like "a tables of games" that can be inserted into multiple pages
* Oh no, did I just re-invent React? :P * Oh no, did I just re-invent React? :P
- [ ] Data presentation methods like "translating a list of Deck IDs into Deck Names" - [ ] Data presentation methods like "translating a list of Deck IDs into Deck Names"
- [X] Externalize datastorage (currently)
... ...
- [ ] Authentication (will need to link `user` table to `player`) - [ ] Authentication (will need to link `user` table to `player`)
... ...

View File

@ -10,6 +10,7 @@ from ..sql import crud, schemas
from ..sql.database import get_db from ..sql.database import get_db
from .players import list_players from .players import list_players
from .games import _render_game_participants
api_router = APIRouter(prefix="/deck", tags=["deck"]) api_router = APIRouter(prefix="/deck", tags=["deck"])
html_router = APIRouter( html_router = APIRouter(
@ -115,6 +116,7 @@ def _build_deck_score_history(deck_id: str, db: Session):
) )
.first() .first()
.score, .score,
"game_participants": _render_game_participants(game, db),
} }
for game in games_involving_this_deck for game in games_involving_this_deck
] ]

View File

@ -1,14 +1,13 @@
import json import json
import logging import logging
from functional import seq from functional import seq
from typing import List, Mapping from typing import List, Mapping, Union
from fastapi import APIRouter, Depends, HTTPException, Request from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.routers.decks import list_decks
from app.sql import models from app.sql import models
from .players import list_players from .players import list_players
from ..elo import rerank from ..elo import rerank
@ -117,7 +116,7 @@ def games_html(request: Request, db=Depends(get_db)):
games = list_games(db=db) games = list_games(db=db)
# TODO - a more "data-intensive application" implementation would fetch only the decks involved in the games for # TODO - a more "data-intensive application" implementation would fetch only the decks involved in the games for
# this page # this page
decks = list_decks(db=db, limit=-1) decks = crud.get_decks(db=db, limit=-1)
decks_by_id = {deck.id: deck for deck in decks} decks_by_id = {deck.id: deck for deck in decks}
game_names = {game.id: _build_game_deck_names(game, decks_by_id) for game in games} game_names = {game.id: _build_game_deck_names(game, decks_by_id) for game in games}
return jinja_templates.TemplateResponse( return jinja_templates.TemplateResponse(
@ -127,6 +126,25 @@ def games_html(request: Request, db=Depends(get_db)):
) )
# Although this is underscore-prefixed, it _is_ intentionally called from `decks.py`, since that logic
# is used there, too.
# Maybe this should be extracted to a file that's appropriate for "logic that's to do with games, but which is not a
# router"?
# Still learning my way around FastAPI project structure!
def _render_game_participants(
game: models.Game, db: Session
) -> List[Mapping[str, Union[str, int]]]:
return (
seq(range(6))
.map(lambda i: i + 1)
.map(lambda i: f"deck_id_{i}")
.map(lambda key: getattr(game, key))
.filter(lambda x: x) # Not every game has 6 participants!
.map(lambda deck_id: crud.get_deck_by_id(db, deck_id))
.map(lambda deck: {"owner": deck.owner.name, "name": deck.name, "id": deck.id})
)
def _build_game_deck_names( def _build_game_deck_names(
game: models.Game, decks_by_id: Mapping[int, models.Deck] game: models.Game, decks_by_id: Mapping[int, models.Deck]
) -> List[str]: ) -> List[str]:
@ -146,7 +164,7 @@ def _build_game_deck_names(
def game_html(request: Request, game_id: str, db=Depends(get_db)): def game_html(request: Request, game_id: str, db=Depends(get_db)):
game = read_game(game_id, db) game = read_game(game_id, db)
decks = list_decks(db=db, limit=-1) decks = crud.get_decks(db=db, limit=-1)
decks_by_id = {deck.id: deck for deck in decks} decks_by_id = {deck.id: deck for deck in decks}
game_deck_names = _build_game_deck_names(game, decks_by_id) game_deck_names = _build_game_deck_names(game, decks_by_id)

View File

@ -7,9 +7,12 @@ SQLALCHEMY_DATABASE_URL = os.environ.get(
"DATABASE_URL", "sqlite:///database/sql_app.db" "DATABASE_URL", "sqlite:///database/sql_app.db"
) )
engine = create_engine( if SQLALCHEMY_DATABASE_URL.startswith("sqlite"):
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} engine = create_engine(
) SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
else:
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base() Base = declarative_base()

View File

@ -15,8 +15,6 @@
<h2>Game history</h2> <h2>Game history</h2>
{% if game_history %} {% if game_history %}
(TODO - extract a translation-from-deckid-to-names method)
(Or...just link them as a relationship/ForeignKey)
<table> <table>
<tr> <tr>
<th>Date</th> <th>Date</th>
@ -28,12 +26,12 @@
<tr> <tr>
<td><a href="/game/{{ entry.game.id }}">{{ entry.game.date.strftime('%Y-%m-%d') }}</a></td> <td><a href="/game/{{ entry.game.id }}">{{ entry.game.date.strftime('%Y-%m-%d') }}</a></td>
<td> <td>
{% for participant_id in range(6) %} <ul>
{% set deck_id = entry.game['deck_id_' ~ (participant_id+1)] %} {% for participant in entry.game_participants %}
{% if deck_id is not none %} <li><a href="/deck/{{ participant.id }}">{{ participant.owner }} ({{ participant.name }})</a></li>
<a href="/deck/{{ deck_id }}">{{ deck_id }}</a> {% endfor %}
{% endif %} </ul>
{% endfor %}</td> </td>
<td>{{ "Win" if entry.game.winning_deck_id == deck.id else "Loss" }}</td> <td>{{ "Win" if entry.game.winning_deck_id == deck.id else "Loss" }}</td>
<td>{{ entry.score|int }}</td> <td>{{ entry.score|int }}</td>
</tr> </tr>