Function bodies 688 total
format_response_mock function · python · L859-L1011 (153 LOC)src/pinwheel/ai/search.py
def format_response_mock(question: str, result: QueryResult) -> str:
"""Format a QueryResult into a readable Discord message string.
No AI call. Produces structured, plain-language responses.
"""
if result.error:
return result.error
data = result.data
if result.query_type == "standings":
standings = data.get("standings", [])
if not standings:
return "No games have been played yet."
lines = ["**League Standings**"]
for i, s in enumerate(standings, 1):
name = s.get("team_name", s.get("team_id", "???"))
w = s.get("wins", 0)
lo = s.get("losses", 0)
lines.append(f"{i}. **{name}** ({w}W-{lo}L)")
return "\n".join(lines)
elif result.query_type == "team_record":
name = data.get("team_name", "Unknown")
w = data.get("wins", 0)
lo = data.get("losses", 0)
return f"**{name}** are {w}-{lo} this season."
elif result.query_type format_response_ai function · python · L1033-L1063 (31 LOC)src/pinwheel/ai/search.py
async def format_response_ai(
question: str,
result: QueryResult,
api_key: str,
) -> str:
"""Format a QueryResult using Claude API. Falls back to mock on failure."""
if result.error:
return result.error
user_msg = (
f"Original question: {question}\n\n"
f"Query type: {result.query_type}\n\n"
f"Raw data:\n{json.dumps(result.data, indent=2, default=str)}"
)
from pinwheel.ai.usage import cacheable_system
model = "claude-sonnet-4-6"
try:
client = anthropic.AsyncAnthropic(api_key=api_key)
response = await client.messages.create(
model=model,
max_tokens=500,
system=cacheable_system(SEARCH_FORMATTER_SYSTEM_PROMPT),
messages=[{"role": "user", "content": user_msg}],
)
return response.content[0].text.strip()
except (anthropic.APIError, KeyError, IndexError) as e:
logger.warning("AI response format failed, using mock: %s", e)
compute_cost function · python · L72-L91 (20 LOC)src/pinwheel/ai/usage.py
def compute_cost(
model: str,
input_tokens: int,
output_tokens: int,
cache_read_tokens: int = 0,
cache_creation_tokens: int = 0,
) -> float:
"""Compute estimated cost in USD for a single API call.
Includes cache creation tokens (25% premium on first cache write)
and cache read tokens (90% discount on subsequent reads).
"""
rates = PRICING.get(model, _DEFAULT_PRICING)
cost = (
input_tokens * rates["input_per_mtok"]
+ output_tokens * rates["output_per_mtok"]
+ cache_read_tokens * rates["cache_read_per_mtok"]
+ cache_creation_tokens * rates["cache_write_per_mtok"]
) / 1_000_000
return round(cost, 8)record_ai_usage function · python · L94-L171 (78 LOC)src/pinwheel/ai/usage.py
async def record_ai_usage(
*,
session: AsyncSession,
call_type: str,
model: str,
input_tokens: int,
output_tokens: int,
cache_read_tokens: int = 0,
cache_creation_tokens: int = 0,
latency_ms: float = 0.0,
season_id: str = "",
round_number: int | None = None,
) -> AIUsageLogRow:
"""Record an AI API call to the usage log.
Parameters
----------
session : AsyncSession
The SQLAlchemy async session to use for the insert.
call_type : str
Identifier for the call site, e.g. "report.simulation",
"commentary.game", "interpreter.v2", "classifier".
model : str
The model name, e.g. "claude-sonnet-4-5-20250929".
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens : int
Token counts from the API response.
latency_ms : float
Wall-clock time of the API call in milliseconds.
season_id : str
Current season ID (empty string if unavailable).
round_numtrack_latency function · python · L175-L189 (15 LOC)src/pinwheel/ai/usage.py
async def track_latency() -> AsyncGenerator[dict[str, float], None]:
"""Context manager that yields a dict; after exit, 'latency_ms' is set.
Usage::
async with track_latency() as timing:
response = await client.messages.create(...)
latency = timing["latency_ms"]
"""
timing: dict[str, float] = {"latency_ms": 0.0}
start = time.monotonic()
try:
yield timing
finally:
timing["latency_ms"] = (time.monotonic() - start) * 1000extract_usage function · python · L192-L210 (19 LOC)src/pinwheel/ai/usage.py
def extract_usage(response: object) -> tuple[int, int, int, int]:
"""Extract token counts from an API response.
Returns (input_tokens, output_tokens, cache_read_tokens,
cache_creation_tokens). Works with the Anthropic SDK ``Message``
objects.
``cache_creation_input_tokens`` is populated on the first request
that creates a cache entry (charged at a 25% premium). Subsequent
requests return ``cache_read_input_tokens`` instead (90% discount).
"""
usage = getattr(response, "usage", None)
if usage is None:
return (0, 0, 0, 0)
input_tokens = getattr(usage, "input_tokens", 0) or 0
output_tokens = getattr(usage, "output_tokens", 0) or 0
cache_read = getattr(usage, "cache_read_input_tokens", 0) or 0
cache_creation = getattr(usage, "cache_creation_input_tokens", 0) or 0
return (input_tokens, output_tokens, cache_read, cache_creation)cacheable_system function · python · L218-L229 (12 LOC)src/pinwheel/ai/usage.py
def cacheable_system(text: str) -> list[dict[str, object]]:
"""Wrap a system prompt string as a cacheable content block.
The Messages API accepts ``system`` as either a string or a list of
content blocks. To enable prompt caching, we use the block format
with ``cache_control: {"type": "ephemeral"}``. Cached content costs
90% less on subsequent reads within a 5-minute TTL.
Prompts below the 1,024-token minimum cacheable size will simply
not be cached (no error).
"""
return [{"type": "text", "text": text, "cache_control": {"type": "ephemeral"}}]Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
pydantic_to_response_format function · python · L232-L252 (21 LOC)src/pinwheel/ai/usage.py
def pydantic_to_response_format(
model_class: type[BaseModel], name: str
) -> dict[str, object]:
"""Convert a Pydantic model to a Messages API ``output_config`` dict.
Uses ``anthropic.transform_schema()`` to sanitize Pydantic's JSON schema
(adds ``additionalProperties: false``, strips unsupported constraints like
``minimum``/``maximum``, etc.). The API guarantees the response conforms
to the schema, eliminating JSON parsing failures.
Returns a dict suitable for the ``output_config`` parameter
(SDK v0.79+ uses ``output_config.format``).
"""
from anthropic import transform_schema
return {
"format": {
"type": "json_schema",
"schema": transform_schema(model_class),
},
}costs_dashboard function · python · L32-L166 (135 LOC)src/pinwheel/api/admin_costs.py
async def costs_dashboard(
request: Request, repo: RepoDep, current_user: OptionalUser
) -> HTMLResponse:
"""AI costs dashboard — token usage, cost breakdown, per-round trends.
Auth-gated: redirects to login if OAuth is enabled and user is not
authenticated. In dev mode without OAuth credentials the page is
accessible to support local testing.
"""
if denied := check_admin_access(current_user, request):
return denied
season_id = await _get_active_season_id(repo)
session = repo.session
# --- Summary totals ---
total_calls = 0
total_input_tokens = 0
total_output_tokens = 0
total_cache_read_tokens = 0
total_cost = 0.0
avg_latency = 0.0
if season_id:
stmt = select(
func.count(AIUsageLogRow.id),
func.coalesce(func.sum(AIUsageLogRow.input_tokens), 0),
func.coalesce(func.sum(AIUsageLogRow.output_tokens), 0),
func.coalesce(func.sum(AIUsageLogRow.cache_read_toke_format_duration function · python · L42-L53 (12 LOC)src/pinwheel/api/admin_perf.py
def _format_duration(seconds: float) -> str:
"""Format seconds into a human-readable duration string."""
if seconds < 60:
return f"{seconds:.0f}s"
if seconds < 3600:
minutes = seconds / 60
return f"{minutes:.0f}m"
hours = seconds / 3600
if hours < 24:
return f"{hours:.1f}h"
days = hours / 24
return f"{days:.1f}d"_compute_percentiles function · python · L56-L76 (21 LOC)src/pinwheel/api/admin_perf.py
def _compute_percentiles(values: list[float]) -> dict[str, float]:
"""Compute P50, P95, P99 from a sorted list of values.
Returns a dict with keys 'p50', 'p95', 'p99'. Returns zeros if the
list is empty.
"""
if not values:
return {"p50": 0.0, "p95": 0.0, "p99": 0.0}
values_sorted = sorted(values)
n = len(values_sorted)
def _pct(p: float) -> float:
idx = int(p / 100.0 * (n - 1))
idx = max(0, min(idx, n - 1))
return values_sorted[idx]
return {
"p50": round(_pct(50), 1),
"p95": round(_pct(95), 1),
"p99": round(_pct(99), 1),
}_build_review_queue function · python · L29-L103 (75 LOC)src/pinwheel/api/admin_review.py
async def _build_review_queue(
repo: RepoDep,
season_id: str,
) -> list[dict]:
"""Build the proposal review queue from governance events.
Finds proposals flagged for review that haven't been cleared or vetoed.
Returns a list of proposal dicts with all relevant metadata.
"""
# Get all flagged proposals
flagged_events = await repo.get_events_by_type(
season_id=season_id,
event_types=["proposal.flagged_for_review"],
)
# Get cleared/vetoed proposals to filter them out
resolved_events = await repo.get_events_by_type(
season_id=season_id,
event_types=["proposal.review_cleared", "proposal.vetoed"],
)
resolved_ids = {e.aggregate_id for e in resolved_events}
# Get proposal outcomes (passed/failed) -- these are also resolved
outcome_events = await repo.get_events_by_type(
season_id=season_id,
event_types=["proposal.passed", "proposal.failed"],
)
outcome_map: dict[str, str] = {}
admin_review function · python · L107-L155 (49 LOC)src/pinwheel/api/admin_review.py
async def admin_review(request: Request, repo: RepoDep, current_user: OptionalUser) -> HTMLResponse:
"""Admin proposal review queue.
Shows proposals flagged for admin review. In dev mode without OAuth,
the page is accessible to support local testing.
"""
if denied := check_admin_access(current_user, request):
return denied
season_id = await _get_active_season_id(repo)
queue: list[dict] = []
pending_count = 0
total_flagged = 0
if season_id:
queue = await _build_review_queue(repo, season_id)
total_flagged = len(queue)
pending_count = sum(1 for p in queue if p["status"] == "pending")
# Also get injection classifications for context
from pinwheel.evals.injection import get_injection_classifications
injection_classifications: list[dict] = []
if season_id:
raw_classifications = await get_injection_classifications(repo, season_id, limit=10)
for c in raw_classifications:
if admin_roster function · python · L29-L147 (119 LOC)src/pinwheel/api/admin_roster.py
async def admin_roster(request: Request, repo: RepoDep, current_user: OptionalUser) -> HTMLResponse:
"""Admin roster -- table of all enrolled governors.
Auth-gated: requires admin Discord ID match when OAuth is enabled.
In dev mode without OAuth credentials the page is accessible to support
local testing.
"""
if denied := check_admin_access(current_user, request):
return denied
# Show ALL players, regardless of season enrollment
all_players = await repo.get_all_players()
governors: list[dict] = []
# Token balances are scoped to the active season (current state).
# Proposals and votes aggregate across ALL seasons (lifetime record).
active_season = await repo.get_active_season()
active_season_id = active_season.id if active_season else None
all_seasons = await repo.get_all_seasons()
for player in all_players:
team = await repo.get_team(player.team_id) if player.team_id else None
team_name = team.name admin_season function · python · L26-L130 (105 LOC)src/pinwheel/api/admin_season.py
async def admin_season(request: Request, repo: RepoDep, current_user: OptionalUser) -> HTMLResponse:
"""Admin season dashboard -- current config, past seasons, new season form."""
if denied := check_admin_access(current_user, request):
return denied
settings = request.app.state.settings
# Current season
active_season = await repo.get_active_season()
current_season_data: dict | None = None
current_round = 0
team_count = 0
governor_count = 0
games_played = 0
if active_season:
teams = await repo.get_teams_for_season(active_season.id)
team_count = len(teams)
players = await repo.get_players_for_season(active_season.id)
governor_count = len(players)
# Count completed games
game_count_result = await repo.session.execute(
select(sa_func.count(GameResultRow.id)).where(
GameResultRow.season_id == active_season.id,
)
)
games_played = gamSource: Repobility analyzer · https://repobility.com
admin_workbench function · python · L76-L156 (81 LOC)src/pinwheel/api/admin_workbench.py
async def admin_workbench(request: Request, current_user: OptionalUser) -> HTMLResponse:
"""Admin safety workbench -- injection classifier test bench and config.
Auth-gated: requires admin Discord ID match when OAuth is enabled.
In dev mode without OAuth credentials the page is accessible.
"""
if denied := check_admin_access(current_user, request):
return denied
settings = request.app.state.settings
# Classifier config info
from pinwheel.ai.classifier import CLASSIFIER_MODEL, CLASSIFIER_PROMPT
classifier_config = {
"model": CLASSIFIER_MODEL,
"prompt_preview": (
CLASSIFIER_PROMPT[:300] + "..."
if len(CLASSIFIER_PROMPT) > 300
else CLASSIFIER_PROMPT
),
"api_key_set": bool(settings.anthropic_api_key),
}
# Defense stack summary
defense_layers = [
{
"name": "Input Sanitization",
"description": "Strips invisible Unicode, HTML, prompt test_classifier function · python · L160-L258 (99 LOC)src/pinwheel/api/admin_workbench.py
async def test_classifier(
request: Request,
current_user: OptionalUser,
body: ClassifierTestRequest | None = None,
) -> HTMLResponse:
"""Test the injection classifier with arbitrary text.
Returns an HTML fragment (HTMX partial) showing the classification
result. Accepts JSON body with ``{"text": "..."}`` or form-encoded
data. Runs sanitize_text first, then the classifier.
"""
if denied := check_admin_access(current_user, request):
return denied
settings = request.app.state.settings
# Accept either JSON body or form-encoded data
raw_text = ""
if body is not None:
raw_text = body.text.strip()
else:
# Fallback: try to read JSON from request body
try:
data = await request.json()
raw_text = str(data.get("text", "")).strip()
except (ValueError, AttributeError):
raw_text = ""
if not raw_text:
return HTMLResponse(
'<div class="workbenc_escape_html function · python · L261-L269 (9 LOC)src/pinwheel/api/admin_workbench.py
def _escape_html(text: str) -> str:
"""Escape HTML special characters in text for safe rendering."""
return (
text.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace('"', """)
.replace("'", "'")
)_point function · python · L42-L48 (7 LOC)src/pinwheel/api/charts.py
def _point(center: float, radius: float, index: int) -> tuple[float, float]:
"""Compute (x, y) for the given axis index at the given radius."""
angle_deg = index * ANGLE_STEP - 90 # start from top
angle_rad = math.radians(angle_deg)
x = center + radius * math.cos(angle_rad)
y = center + radius * math.sin(angle_rad)
return (round(x, 2), round(y, 2))spider_chart_data function · python · L51-L85 (35 LOC)src/pinwheel/api/charts.py
def spider_chart_data(
attributes: dict[str, float],
center: float = 150,
max_radius: float = 120,
) -> list[dict]:
"""Compute SVG coordinates for each attribute vertex.
Returns a list of 9 dicts with keys:
x, y — vertex position
lx, ly — label position (slightly beyond vertex)
attr — attribute name
label — 3-char abbreviation
value — numeric value (0–100)
color — hex color for this attribute
"""
points = []
for i, attr in enumerate(ATTRIBUTE_ORDER):
value = max(0, min(100, float(attributes.get(attr, 0))))
r = (value / 100) * max_radius
x, y = _point(center, r, i)
# Label position: push out beyond the max radius
lx, ly = _point(center, max_radius + 18, i)
points.append(
{
"x": x,
"y": y,
"lx": lx,
"ly": ly,
"attr": attr,
"compute_grid_rings function · python · L88-L101 (14 LOC)src/pinwheel/api/charts.py
def compute_grid_rings(
center: float = 150,
max_radius: float = 120,
) -> list[str]:
"""Compute SVG polygon point-strings for 4 concentric grid rings (25/50/75/100%)."""
rings = []
for pct in (0.25, 0.50, 0.75, 1.0):
r = max_radius * pct
coords = []
for i in range(NUM_AXES):
x, y = _point(center, r, i)
coords.append(f"{x},{y}")
rings.append(" ".join(coords))
return ringsaxis_lines function · python · L109-L118 (10 LOC)src/pinwheel/api/charts.py
def axis_lines(
center: float = 150,
max_radius: float = 120,
) -> list[dict]:
"""Compute axis line endpoints from center to outer ring."""
lines = []
for i in range(NUM_AXES):
x, y = _point(center, max_radius, i)
lines.append({"x1": center, "y1": center, "x2": x, "y2": y})
return linescompute_season_averages function · python · L121-L160 (40 LOC)src/pinwheel/api/charts.py
def compute_season_averages(
box_scores: list[dict],
) -> dict[str, float | int]:
"""Compute season averages from a list of box score dicts.
Each dict should have keys matching BoxScoreRow fields:
points, assists, steals, turnovers,
field_goals_made, field_goals_attempted,
three_pointers_made, three_pointers_attempted,
free_throws_made, free_throws_attempted
Returns dict with ppg, apg, spg, topg, fg_pct, three_pct, ft_pct, games_played.
Returns empty dict if no box scores.
"""
if not box_scores:
return {}
games = len(box_scores)
total_pts = sum(bs.get("points", 0) for bs in box_scores)
total_ast = sum(bs.get("assists", 0) for bs in box_scores)
total_stl = sum(bs.get("steals", 0) for bs in box_scores)
total_to = sum(bs.get("turnovers", 0) for bs in box_scores)
total_fgm = sum(bs.get("field_goals_made", 0) for bs in box_scores)
total_fga = sum(bs.get("field_goals_attempted", 0) for bs in bSame scanner, your repo: https://repobility.com — Repobility
get_session function · python · L20-L31 (12 LOC)src/pinwheel/api/deps.py
async def get_session(
engine: Annotated[AsyncEngine, Depends(get_engine)],
) -> AsyncGenerator[AsyncSession, None]:
"""Yield an async session."""
factory = create_session_factory(engine)
async with factory() as session:
try:
yield session
await session.commit()
except Exception: # Re-raise pattern — must catch all to ensure rollback on any error
await session.rollback()
raisecompute_safety_summary function · python · L26-L116 (91 LOC)src/pinwheel/api/eval_dashboard.py
def compute_safety_summary(
*,
grounding_rate: float,
grounding_total: int,
prescriptive_flagged: int,
injection_attempts: int,
active_flags: list[dict],
gqi_trend: list[dict],
golden_pass_rate: float,
) -> dict:
"""Compute the traffic-light safety summary from eval metrics.
Returns a dict with:
- status: "green" | "yellow" | "red"
- label: human-readable status label
- total_evaluated: total reports/proposals evaluated
- injection_attempts: number of injection attempts detected
- eval_coverage_pct: percentage of eval types that have data
- gqi_score: latest GQI composite score (0.0 if unavailable)
- concerns: list of short concern strings
"""
concerns: list[str] = []
# Count critical and warning flags
critical_flags = sum(1 for f in active_flags if f.get("severity") == "critical")
warning_flags = sum(1 for f in active_flags if f.get("severity") == "warning")
if critical_flags >_get_available_rounds function · python · L125-L138 (14 LOC)src/pinwheel/api/eval_dashboard.py
async def _get_available_rounds(repo: RepoDep, season_id: str) -> list[int]:
"""Return sorted list of distinct round numbers that have eval results."""
from sqlalchemy import select
from pinwheel.db.models import EvalResultRow
stmt = (
select(EvalResultRow.round_number)
.where(EvalResultRow.season_id == season_id)
.distinct()
.order_by(EvalResultRow.round_number)
)
result = await repo.session.execute(stmt)
return [row[0] for row in result.all() if row[0] is not None]_parse_round_param function · python · L141-L152 (12 LOC)src/pinwheel/api/eval_dashboard.py
def _parse_round_param(request: Request) -> int | None:
"""Extract and validate the ``round`` query parameter."""
raw = request.query_params.get("round")
if raw is None:
return None
try:
value = int(raw)
except (ValueError, TypeError):
return None
if value < 0:
return None
return valuesse_stream function · python · L74-L142 (69 LOC)src/pinwheel/api/events.py
async def sse_stream(
request: Request,
event_type: str | None = None,
) -> StreamingResponse:
"""Server-Sent Events stream.
Query params:
event_type: optional filter — must be one of the known event types
(e.g. "game.completed", "report.generated").
If omitted, receives all events.
Returns an SSE stream that stays open until the client disconnects.
Sends an initial comment to flush proxy buffers and periodic heartbeats
to keep the connection alive through reverse proxies.
Errors:
400 — unknown event_type value
429 — global connection limit reached
"""
# Validate event_type against the allowlist
if event_type is not None and event_type not in ALLOWED_EVENT_TYPES:
raise HTTPException(
status_code=400,
detail=(
f"Unknown event_type {event_type!r}. "
f"Valid values: {sorted(ALLOWED_EVENT_TYPES)}"
),
events_health function · python · L146-L154 (9 LOC)src/pinwheel/api/events.py
async def events_health(request: Request) -> dict:
"""Check EventBus health, subscriber count, and SSE connection stats."""
bus = _get_bus(request)
return {
"status": "ok",
"subscribers": bus.subscriber_count,
"active_sse_connections": _MAX_SSE_CONNECTIONS - _connection_semaphore._value, # noqa: SLF001
"max_sse_connections": _MAX_SSE_CONNECTIONS,
}get_followed_team_id function · python · L23-L28 (6 LOC)src/pinwheel/api/follow.py
def get_followed_team_id(request: Request) -> str | None:
"""Read the followed team ID from the cookie. Returns None if unset."""
value = request.cookies.get(FOLLOW_COOKIE_NAME)
if value and len(value) == 36:
return value
return Nonefollow_team function · python · L32-L63 (32 LOC)src/pinwheel/api/follow.py
async def follow_team(
request: Request,
team_id: str,
repo: RepoDep,
current_user: OptionalUser,
) -> HTMLResponse | JSONResponse:
"""Set the followed team cookie. Returns an HTMX partial or JSON.
Works for both logged-in and anonymous users — the cookie is
independent of the session. This keeps the MVP simple.
"""
# Validate team exists
team = await repo.get_team(team_id)
if team is None:
return JSONResponse({"error": "Team not found"}, status_code=404)
is_htmx = request.headers.get("HX-Request") == "true"
if is_htmx:
html = _follow_button_html(team_id, team.name, following=True)
response = HTMLResponse(html)
else:
response = JSONResponse({"status": "following", "team_id": team_id}) # type: ignore[assignment]
response.set_cookie(
FOLLOW_COOKIE_NAME,
team_id,
max_age=FOLLOW_COOKIE_MAX_AGE,
httponly=True,
samesite="lax",
)
return responseRepobility analyzer · published findings · https://repobility.com
unfollow_team function · python · L67-L86 (20 LOC)src/pinwheel/api/follow.py
async def unfollow_team(
request: Request,
team_id: str,
repo: RepoDep,
current_user: OptionalUser,
) -> HTMLResponse | JSONResponse:
"""Clear the followed team cookie. Returns an HTMX partial or JSON."""
team = await repo.get_team(team_id)
team_name = team.name if team else "this team"
is_htmx = request.headers.get("HX-Request") == "true"
if is_htmx:
html = _follow_button_html(team_id, team_name, following=False)
response = HTMLResponse(html)
else:
response = JSONResponse({"status": "unfollowed", "team_id": team_id}) # type: ignore[assignment]
response.delete_cookie(FOLLOW_COOKIE_NAME)
return response_follow_button_html function · python · L89-L111 (23 LOC)src/pinwheel/api/follow.py
def _follow_button_html(team_id: str, team_name: str, *, following: bool) -> str:
"""Render the follow/unfollow button as an HTMX-swappable fragment."""
if following:
return (
f'<div id="follow-btn-container">'
f'<button class="follow-btn follow-btn--following"'
f' hx-delete="/api/teams/{team_id}/follow"'
f' hx-target="#follow-btn-container"'
f' hx-swap="outerHTML"'
f' title="Unfollow {team_name}">'
f"Following</button>"
f"</div>"
)
return (
f'<div id="follow-btn-container">'
f'<button class="follow-btn"'
f' hx-post="/api/teams/{team_id}/follow"'
f' hx-target="#follow-btn-container"'
f' hx-swap="outerHTML"'
f' title="Follow {team_name} to prioritize their games">'
f"Follow</button>"
f"</div>"
)get_playoff_bracket function · python · L223-L229 (7 LOC)src/pinwheel/api/games.py
async def get_playoff_bracket(repo: RepoDep) -> dict:
"""Get structured playoff bracket data.
Returns bracket with semifinals, finals, series records, and champion.
"""
bracket = await _build_bracket_data(repo)
return {"data": bracket}get_game function · python · L233-L251 (19 LOC)src/pinwheel/api/games.py
async def get_game(game_id: str, repo: RepoDep) -> dict:
"""Get a game result by ID."""
game = await repo.get_game_result(game_id)
if not game:
raise HTTPException(404, "Game not found")
return {
"data": {
"id": game.id,
"home_team_id": game.home_team_id,
"away_team_id": game.away_team_id,
"home_score": game.home_score,
"away_score": game.away_score,
"winner_team_id": game.winner_team_id,
"total_possessions": game.total_possessions,
"elam_target": game.elam_target,
"quarter_scores": game.quarter_scores,
"seed": game.seed,
},
}get_boxscore function · python · L255-L276 (22 LOC)src/pinwheel/api/games.py
async def get_boxscore(game_id: str, repo: RepoDep) -> dict:
"""Get box scores for a game."""
game = await repo.get_game_result(game_id)
if not game:
raise HTTPException(404, "Game not found")
return {
"data": [
{
"hooper_id": bs.hooper_id,
"team_id": bs.team_id,
"points": bs.points,
"field_goals_made": bs.field_goals_made,
"field_goals_attempted": bs.field_goals_attempted,
"three_pointers_made": bs.three_pointers_made,
"three_pointers_attempted": bs.three_pointers_attempted,
"assists": bs.assists,
"steals": bs.steals,
"turnovers": bs.turnovers,
}
for bs in game.box_scores
],
}api_list_proposals function · python · L18-L29 (12 LOC)src/pinwheel/api/governance.py
async def api_list_proposals(season_id: str, repo: RepoDep) -> dict:
"""List all proposals for a season."""
events = await repo.get_events_by_type(
season_id=season_id,
event_types=["proposal.submitted"],
)
proposals = []
for e in events:
proposal_data = e.payload
if "id" in proposal_data and "raw_text" in proposal_data:
proposals.append(Proposal(**proposal_data))
return {"data": [p.model_dump(mode="json") for p in proposals]}api_current_rules function · python · L33-L55 (23 LOC)src/pinwheel/api/governance.py
async def api_current_rules(season_id: str, repo: RepoDep) -> dict:
"""Get the current ruleset for a season."""
season = await repo.get_season(season_id)
if not season:
raise HTTPException(status_code=404, detail="Season not found")
ruleset = RuleSet(**(season.current_ruleset or {}))
defaults = RuleSet()
# Highlight non-default values
changes = {}
for param in RuleSet.model_fields:
current = getattr(ruleset, param)
default = getattr(defaults, param)
if current != default:
changes[param] = {"current": current, "default": default}
return {
"data": {
"ruleset": ruleset.model_dump(),
"changes_from_default": changes,
}
}api_rule_history function · python · L59-L65 (7 LOC)src/pinwheel/api/governance.py
async def api_rule_history(season_id: str, repo: RepoDep) -> dict:
"""Get all rule changes for a season."""
events = await repo.get_events_by_type(
season_id=season_id,
event_types=["rule.enacted"],
)
return {"data": [e.payload for e in events]}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
get_pace function · python · L51-L59 (9 LOC)src/pinwheel/api/pace.py
async def get_pace(request: Request) -> PaceResponse:
"""Return the current presentation pace and derived cron expression."""
settings = _get_settings(request)
cron = settings.effective_game_cron()
return PaceResponse(
pace=settings.pinwheel_presentation_pace,
cron=cron,
auto_advance=cron is not None,
)set_pace function · python · L63-L87 (25 LOC)src/pinwheel/api/pace.py
async def set_pace(
body: PaceRequest,
request: Request,
_: Annotated[None, Depends(require_api_admin)],
) -> PaceResponse:
"""Change the presentation pace in memory (not persisted to env).
Admin-only: requires authenticated admin in production/staging.
This is a demo convenience endpoint — not meant for production use.
"""
if body.pace not in VALID_PACES:
raise HTTPException(
status_code=422,
detail=f"Invalid pace '{body.pace}'. Must be one of: {sorted(VALID_PACES)}",
)
settings = _get_settings(request)
settings.pinwheel_presentation_pace = body.pace
cron = PACE_CRON_MAP[body.pace]
return PaceResponse(
pace=body.pace,
cron=cron,
auto_advance=cron is not None,
)advance_round function · python · L91-L129 (39 LOC)src/pinwheel/api/pace.py
async def advance_round(
request: Request,
_: Annotated[None, Depends(require_api_admin)],
quarter_seconds: int = 300,
game_gap_seconds: int = 0,
) -> AdvanceResponse:
"""Trigger a round advance within the server process.
Admin-only: requires authenticated admin in production/staging.
Forces presentation_mode="replay" with demo-friendly timing defaults.
Returns 409 if a presentation is already active.
"""
from pinwheel.core.presenter import PresentationState
from pinwheel.core.scheduler_runner import tick_round
presentation_state: PresentationState = request.app.state.presentation_state
if presentation_state.is_active:
raise HTTPException(
status_code=409,
detail="A presentation is already active. Wait for it to finish.",
)
engine = request.app.state.engine
event_bus = request.app.state.event_bus
settings = _get_settings(request)
asyncio.create_task(
tick_round(
pace_status function · python · L133-L142 (10 LOC)src/pinwheel/api/pace.py
async def pace_status(request: Request) -> PaceStatusResponse:
"""Return current presentation state."""
from pinwheel.core.presenter import PresentationState
presentation_state: PresentationState = request.app.state.presentation_state
return PaceStatusResponse(
is_active=presentation_state.is_active,
current_round=presentation_state.current_round,
current_game_index=presentation_state.current_game_index,
)_get_slot_start_times function · python · L39-L59 (21 LOC)src/pinwheel/api/pages.py
def _get_slot_start_times(
request: Request,
slot_count: int,
) -> list[str]:
"""Compute formatted start times for the next *slot_count* time slots.
Each slot fires on the cron cadence (e.g. every 30 min). A slot is
a set of games where no team plays twice — they tip off simultaneously.
Returns an empty list if the cron is unavailable.
"""
if slot_count <= 0:
return []
settings: Settings = request.app.state.settings
cron_expr = settings.effective_game_cron()
if not cron_expr:
return []
try:
times = compute_round_start_times(cron_expr, slot_count)
return [format_game_time(t) for t in times]
except (ValueError, TypeError):
return []_light_safe function · python · L65-L86 (22 LOC)src/pinwheel/api/pages.py
def _light_safe(hex_color: str) -> str:
"""Darken high-luminance hex colors for readability on light backgrounds.
Colors with relative luminance > 0.5 (e.g. gold #FFD700, light blue
#88BBDD) get darkened ~40% and saturation-boosted. All other colors
pass through unchanged.
"""
c = hex_color.lstrip("#")
if len(c) != 6:
return hex_color
try:
r, g, b = int(c[0:2], 16), int(c[2:4], 16), int(c[4:6], 16)
except ValueError:
return hex_color
# Relative luminance (sRGB)
luminance = 0.2126 * (r / 255) + 0.7152 * (g / 255) + 0.0722 * (b / 255)
if luminance <= 0.5:
return hex_color
# Darken by 40%
factor = 0.6
rd, gd, bd = int(r * factor), int(g * factor), int(b * factor)
return f"#{rd:02x}{gd:02x}{bd:02x}"_prose_to_html function · python · L92-L104 (13 LOC)src/pinwheel/api/pages.py
def _prose_to_html(text: str) -> str:
"""Convert markdown/prose text to HTML.
Uses the markdown library to render headings, bold, italic, lists, etc.
Sanitizes the resulting HTML with nh3 to prevent XSS from AI-generated
content that may include raw HTML or script tags.
"""
import markdown
import nh3
text = text.strip()
raw_html = markdown.markdown(text, extensions=["nl2br", "smarty"])
return nh3.clean(raw_html)_auth_context function · python · L110-L125 (16 LOC)src/pinwheel/api/pages.py
def _auth_context(request: Request, current_user: SessionUser | None) -> dict:
"""Build auth-related template context available on every page."""
settings = request.app.state.settings
oauth_enabled = bool(settings.discord_client_id and settings.discord_client_secret)
admin_id = settings.pinwheel_admin_discord_id
is_admin = current_user is not None and bool(admin_id) and current_user.discord_id == admin_id
followed_team_id = request.cookies.get("pinwheel_followed_team")
return {
"current_user": current_user,
"oauth_enabled": oauth_enabled,
"pinwheel_env": settings.pinwheel_env,
"app_version": APP_VERSION,
"discord_invite_url": settings.discord_invite_url,
"is_admin": is_admin,
"followed_team_id": followed_team_id,
}Source: Repobility analyzer · https://repobility.com
_get_active_season function · python · L134-L139 (6 LOC)src/pinwheel/api/pages.py
async def _get_active_season(repo: RepoDep) -> tuple[str | None, str | None]:
"""Get (season_id, season_name) for the active season."""
row = await repo.get_active_season()
if row:
return row.id, row.name
return None, None_get_standings function · python · L142-L181 (40 LOC)src/pinwheel/api/pages.py
async def _get_standings(
repo: RepoDep,
season_id: str,
phase_filter: str | None = None,
) -> list[dict]:
"""Compute standings for a season.
Args:
phase_filter: When ``"regular"``, include only regular-season games
(phase is ``None`` or ``"regular"``). When ``"playoff"``, include
only post-season games (phase in ``"playoff"``, ``"semifinal"``,
``"finals"``). ``None`` includes all games (original behaviour).
"""
games = await repo.get_all_games(season_id)
if phase_filter == "regular":
games = [g for g in games if getattr(g, "phase", None) in (None, "regular")]
elif phase_filter == "playoff":
games = [
g for g in games if getattr(g, "phase", None) in ("playoff", "semifinal", "finals")
]
all_results: list[dict] = [
{
"home_team_id": g.home_team_id,
"away_team_id": g.away_team_id,
"home_score": g.home_score,
"a_get_season_phase function · python · L184-L205 (22 LOC)src/pinwheel/api/pages.py
async def _get_season_phase(repo: RepoDep, season_id: str) -> str:
"""Get the current season phase as a display label.
Returns one of: 'regular', 'tiebreakers', 'playoffs', 'championship',
'offseason'. Used to drive phase-aware badges in templates.
"""
season = await repo.get_season(season_id)
if not season:
return "regular"
phase_map: dict[str, str] = {
"setup": "regular",
"active": "regular",
"tiebreaker_check": "regular",
"tiebreakers": "tiebreakers",
"regular_season_complete": "regular",
"playoffs": "playoffs",
"championship": "championship",
"offseason": "offseason",
"completed": "offseason",
"complete": "offseason",
}
return phase_map.get(season.status or "", "regular")