{% set t = tournament %} {% set active_players = t.participants | selectattr("released_at", "none") | list | length %} {# Stat cards #}
| # | Agent | Score | Avg / Round |
|---|---|---|---|
| {% if ns.rank == 1 %}🥇{% elif ns.rank == 2 %}🥈{% elif ns.rank == 3 %}🥉{% endif %} {{ ns.rank }} | {{ p.agent_name }} | {{ p.total_score if p.total_score is not none else "—" }} | {% if p.total_score is not none and completed_rounds > 0 %} {{ "%.2f" | format(p.total_score / completed_rounds) }} {% else %}—{% endif %} |
| Round | {% for p in sorted_participants %}{{ p.agent_name }} | {% endfor %}Payoff | Status | |
|---|---|---|---|---|
| {{ r.round_number }} | {% for p in sorted_participants %} {% set action = r.actions | selectattr("participant_id", "equalto", p.id) | first %} {% if action %} {# Single source of truth for the "this row was auto- submitted on timeout" predicate — reused below for both the (timeout) label and for suppressing the empty-reasoning placeholder. Avoids drift if the source enum name ever changes. #} {% set is_timeout_default = action.source == "timeout_default" %}
{% if t.game_type == "prisoners_dilemma" %}
{% set choice = (action.action_data or {}).get("choice", "—") %}
{{ choice }}
{% elif t.game_type == "el_farol" %}
{% set intervals = (action.action_data or {}).get("intervals", []) %}
{% if intervals %}
{{ intervals | map("join", "–") | join(", ") }}
{% else %}
stay home
{% endif %}
{% elif t.game_type == "public_goods" %}
{% set contrib = (action.action_data or {}).get("contribution") %}
{% if contrib is not none %}
{{ "%.2f"|format(contrib) }}
{% else %}
—
{% endif %}
{% else %}
{{ action.action_data | tojson }}
{% endif %}
{% if is_admin and is_timeout_default %}
(timeout)
{% endif %}
{# Inline reasoning. Rendered for every action the
caller is allowed to see reasoning for, even when
the agent didn't attach any — an explicit empty
placeholder makes the feature discoverable instead
of hiding behind a missing 💭 icon. Timeout-default
actions are server-generated and never carry
reasoning, so we skip the placeholder for them to
avoid visual noise. #}
{% if action.id in visible_reasoning_action_ids %}
{% if action.reasoning %}
💭 {{ action.reasoning }}
{% elif not is_timeout_default %}
{# #666 on white reaches WCAG AA for normal text
(4.5:1); the prior #aaa failed the bar. Keep
it muted enough to read as secondary. #}
💭 no reasoning
{% endif %}
{% endif %}
|
{% else %}
— | {% endif %} {% endfor %}{% set ns = namespace(parts=[]) %} {% for p in sorted_participants %} {% set action = r.actions | selectattr("participant_id", "equalto", p.id) | first %} {% if action and action.payoff is not none %} {% set ns.parts = ns.parts + [action.payoff | string] %} {% else %} {% set ns.parts = ns.parts + ["—"] %} {% endif %} {% endfor %} {{ ns.parts | join(" : ") }} | {{ r.status }} |