  1. Helpers (configuration.yaml, or create them in the UI)

  input_button:
    station_game_start:
      name: Start station game
      icon: mdi:bus-clock

  # One dropdown per player. Options = "-" (no pick) + station names.
  # Station names must match the keys in the automation's `stations` map.
  input_select:
    station_game_alice:
      name: Alice's station
      icon: mdi:account
      options: ["-", "Stratford", "Hackney Wick", "Canning Town", "Bow Road"]
    station_game_bob:
      name: Bob's station
      icon: mdi:account
      options: ["-", "Stratford", "Hackney Wick", "Canning Town", "Bow Road"]
    station_game_carol:
      name: Carol's station
      icon: mdi:account
      options: ["-", "Stratford", "Hackney Wick", "Canning Town", "Bow Road"]

  2. Automation

  alias: Station arrival game
  description: Everyone picks a station; soonest next arrival wins.
  mode: single
  triggers:
    - trigger: state
      entity_id: input_button.station_game_start
      not_from: [unavailable, unknown]
  variables:
    pick_timeout: 60            # seconds players get to choose
    departures_attr: departures # attribute holding the arrivals list
    notify_action: notify.notify
    stations:
      Stratford: sensor.stratford_departures
      Hackney Wick: sensor.hackney_wick_departures
      Canning Town: sensor.canning_town_departures
      Bow Road: sensor.bow_road_departures
    players:
      Alice: input_select.station_game_alice
      Bob: input_select.station_game_bob
      Carol: input_select.station_game_carol
  actions:
    # Reset everyone's pick
    - action: input_select.select_option
      target:
        entity_id: "{{ players.values() | list }}"
      data:
        option: "-"

    - action: "{{ notify_action }}"
      data:
        title: "🚌 Station game!"
        message: >
          Pick your station within {{ pick_timeout }}s.
          Soonest arrival wins. Options: {{ stations.keys() | join(', ') }}

    # Wait until everyone has picked, or time runs out
    - wait_template: >
        {{ players.values() | map('states') | select('eq', '-') | list | count == 0 }}
      timeout:
        seconds: "{{ pick_timeout }}"
      continue_on_timeout: true

    # Find each player's soonest future arrival
    - variables:
        results: >
          {% set ns = namespace(r=[]) %}
          {% for player, sel in players.items() %}
            {% set station = states(sel) %}
            {% set sensor = stations.get(station) %}
            {% if sensor %}
              {% set best = namespace(t=none, d=none) %}
              {% for d in state_attr(sensor, departures_attr) or [] %}
                {% set t = as_datetime(d.expected) if d.expected else none %}
                {% if t and t > now() and (best.t is none or t < best.t) %}
                  {% set best.t = t %}
                  {% set best.d = d %}
                {% endif %}
              {% endfor %}
              {% if best.t is not none %}
                {% set ns.r = ns.r + [{
                  'player': player,
                  'station': station,
                  'secs': (best.t - now()).total_seconds() | int,
                  'line': best.d.line.designation if best.d.line is mapping else '?',
                  'mode': best.d.line.transport_mode if best.d.line is mapping else '',
                  'dest': best.d.destination
                }] %}
              {% endif %}
            {% endif %}
          {% endfor %}
          {{ ns.r | sort(attribute='secs') }}
        no_pick: >
          {{ players.items() | selectattr('1', 'is_state', '-') | map(attribute='0') | list }}
        winners: >
          {% if results | count > 0 %}
            {{ results | selectattr('secs', 'eq', results[0].secs) | map(attribute='player') | list }}
          {% else %}[]{% endif %}

    - choose:
        - conditions: "{{ winners | count > 0 }}"
          sequence:
            - action: "{{ notify_action }}"
              data:
                title: >
                  🏆 {{ winners | join(' & ') }} win{{ 's' if winners | count == 1 }}!
                message: >
                  {% for r in results -%}
                  {{ loop.index }}. {{ r.player }} – {{ r.station }}:
                  {{ r.mode | lower }} {{ r.line }} → {{ r.dest }}
                  in {{ r.secs // 60 }}m {{ '%02d' % (r.secs % 60) }}s
                  {% endfor -%}
                  {% if no_pick %}Didn't pick: {{ no_pick | join(', ') }}{% endif %}
      default:
        - action: "{{ notify_action }}"
          data:
            title: "🚌 Station game"
            message: "No valid picks or no upcoming arrivals. Nobody wins."

  3. Dashboard card (optional)

  type: entities
  title: Station game
  entities:
    - input_button.station_game_start
    - input_select.station_game_alice
    - input_select.station_game_bob
    - input_select.station_game_carol

  How it works

  - Start: press the button. Everyone's pick resets to - and a notification goes out.
  - Picking: each player sets their own dropdown. The game ends early once all players have picked, otherwise after 60s. Anyone who didn't
    pick is left out and named in the results.
  - Winner: for each pick, the automation takes the earliest expected time that is still in the future (it skips past arrivals). The lowest
    wait wins.
  - Ties: if two players pick the same station or get identical times, they share the win.
  - Results: the notification shows the full ranking with mode, line, destination and countdown.