Sports Standings and Scores

So the first CFP was posted yesterday. If you are using my Top 25 Code you probably saw the update.

Here are the rough matchups and playoff data: The top four conference champions in the final rankings will receive a bye. First-round games will be played on campus sites with No. 5 hosting No. 12, No. 6 facing No. 11, No. 7 meeting No. 10 and No. 8 squaring off with No. 9.

Winners of those games will advance to the quarterfinals at the Fiesta, Sugar, Peach and Rose bowls. Those games will be played either Dec. 31 or Jan. 1. The Orange Bowl and Cotton Bowl will host the semifinals on Jan. 9 and Jan. 10, respectively.

The championship game will be played on Jan. 20 in Atlanta at Mercedes-Benz Stadium.

For fun I applied what I did in the Soccer code to CFP.

  • Variables added for Bye and teams 5-12. Colors matchup to who would play each other if it ended today. I believe that there will be 5 CFP’s.
  • If the variable isn’t added or has a 0 nothing is applied.

Here is a quick snapshot and yes I will fix the color or @ehcah/anyone else which are more adept in that than I am. I’ll throw the code below as well.

Here are the changes to the Top 25 Decluttering Card

ncaa_top25_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 100%;border-collapse: collapse; margin-top:12px;'
        tbody tr td:first-child: 'width: 1%;'
        tbody tr td:nth-child(2): 'width: 2%;'
        tbody tr td:nth-child(3): 'width: 1%;'
        tbody tr td:nth-child(4): 'width: 2%;'
        tbody tr td:nth-child(n+5): 'width: .5%;'
        tbody tr:nth-child([[bye]]): 'border-bottom: 2px solid crimson!important;'
        tbody tr:nth-child([[team5]]): 'background-color: dodgerblue; color: white;'
        tbody tr:nth-child([[team6]]): 'background-color: navy; color: white;'
        tbody tr:nth-child([[team7]]): 'background-color: #43C6DB; color: white;'
        tbody tr:nth-child([[team8]]): 'background-color: #357EC7; color: white;'
        tbody tr:nth-child([[team9]]): 'background-color: #357EC7; color: white;'
        tbody tr:nth-child([[team10]]): 'background-color: #43C6DB; color: white;'
        tbody tr:nth-child([[team11]]): 'background-color: navy; color: white;'
        tbody tr:nth-child([[team12]]): 'background-color: dodgerblue; color: white;'
        tbody tr:hover: 'background-color: dimgrey!important; color:white!important;'
      card_mod:
        style:
          .: |
            ha-card {
              overflow: auto;
              }
          $: |
            .card-header {
               padding-top: 6px!important;
               padding-bottom: 4px!important;
               font-size: 14px!important;
               line-height: 14px!important;
               font-weight: bold!important;
             }
      sort_by: entries+
      entities:
        include: '[[entity]]'
        exclude: '[[excluded_entities]]'
      columns:
        - name: Rank
          data: '[[attribute]]'
          modify: x.current
        - name: Up-Down
          data: '[[attribute]]'
          modify: |-
            if (x.current == x.previous)
              '<ha-icon icon="mdi:minus" >'
            else if (x.current =="0")
              '<ha-icon icon="mdi:bomb" style="color:red;" >'
            else if (x.previous == "0")
              '<div><ha-icon icon="mdi:hand-clap" style="color:blue;"></ha-icon>&nbsp;' +  "New " + '</div>';
            else if (x.current > x.previous)
              '<div><ha-icon icon="mdi:arrow-down" style="color:red;"></ha-icon>&nbsp;' +  "Dn "+ (x.current - x.previous) + '</div>';
            else if (x.current < x.previous)
              '<div><ha-icon icon="mdi:arrow-up" style="color:green;"></ha-icon>&nbsp;' + "Up "+ (x.previous - x.current) + '</div>';
        - name: Record
          data: '[[attribute]]'
          modify: x.recordSummary
        - name: Team
          data: '[[attribute]]'
          modify: >-
            '<div><img src="' + x.team.logos[0].href + '" style="height:
            20px;vertical-align:middle;">&nbsp;' + x.team.nickname + '</div>'
        - name: 1st Place Votes
          data: '[[attribute]]'
          modify: x.firstPlaceVotes
        - name: Previous Rank
          data: '[[attribute]]'
          modify: x.previous
        - name: Points
          data: '[[attribute]]'
          modify: x.points

Here is what the card call looks like:

                            - attributes:
                                label: Top 25 Standings (AP-Coaches-FCS Polls)
                                icon: mdi:account-group
                              card:
                                type: horizontal-stack
                                cards:
                                  - type: vertical-stack
                                    cards:
                                      - type: markdown
                                        content: >
                                          <h4 style="text-align:center;"> {{
                                          state_attr('sensor.ncaaf_rank',
                                          'rankings')[0]['headline'] }}  {{
                                          state_attr('sensor.ncaaf_rank',
                                          'rankings')[0]['shortHeadline'] }}- 
                                          {{as_timestamp(state_attr('sensor.ncaaf_rank','rankings')[0]['date'])
                                          | timestamp_custom('%m/%d/%Y') }}  </h4>
                                      - type: custom:decluttering-card
                                        template: ncaa_top25_settings
                                        variables:
                                          - title: ''
                                          - entity: sensor.ncaaf_poll_ap_top_25_all
                                          - attribute: ranks
                                          - bye: 4
                                          - team5: 5
                                          - team6: 6
                                          - team7: 7
                                          - team8: 8
                                          - team9: 9
                                          - team10: 10
                                          - team11: 11
                                          - team12: 12

So I am hoping someone can help because my head hurts - I know this is a TL;DR sorry about that… I have been trying to figure out the playoffs for NCAAF since the CFP was released two weeks ago. My sensor above is incorrect. and I am trying to figure out how to create the code to grab the top 4 conference teams by rank (ESPN has a SEED variable but it doesn’t correspond to rankings which I was hoping it would). So the rankings now is broken into 6 sections - CFP, AP, Coaches,FCS Coaches, Div II and Div III.(0-5) So I created a new sensor specifically for the CFP

################################################ CFP Poll #####################################
##NCAA Men's Football CFP
- platform: rest
  scan_interval: 86400
  name: ncaaf_poll_cfp_top_25_all
  unique_id: sensor.ncaaf_poll_cfp_top_25_all
  resource: https://site.api.espn.com/apis/site/v2/sports/football/college-football/rankings?seasontype=2&type=0&level=3
  value_template: "{{ now() }}"
  json_attributes_path: "$.['rankings'][0]"
  json_attributes: 
   - ranks
   - droppedOut
   - others

I’ve created a playoff skeleton that will evolve but just starting out - here is the first pass

What I am having a heck of a time with is trying to stack rank the teams based on the CFP rankings and the CFP format which is this:

  • The 12 participating teams will be the five conference champions ranked highest by the CFP selection committee, plus the next seven highest-ranked teams.

  • The ranking of the teams will continue to be done by a selection committee.

  • The four highest-ranked conference champions will be seeded one through four and will receive a first-round bye. The fifth conference champion will be seeded where it was ranked or at No. 12 if it is outside the top 12 rankings. Non-conference champions ranked in the top four will be seeded beginning at No. 5. Because of this, the seeding, 1 through 12, could look different than the final rankings.

  • The eight teams seeded No. 5-12 will play in a first round with the higher seeds hosting the lower seeds either on campus or at other sites designated by the higher-seeded institution (No. 12 at No. 5, No. 11 at No. 6, No. 10 at No. 7 and No. 9 at No. 8.).

  • The selection committee will assign the four highest-ranked conference champions to Playoff Quarterfinals hosted by bowls. This will be done in consideration of historic bowl relationships, then in consideration of rankings. For example, if the Sugar Bowl hosts a Playoff Quarterfinal and the SEC champion is ranked No. 1 and the Big 12 champion is ranked No. 3, the SEC champion would be assigned to the Sugar Bowl and the Big 12 champion would be assigned elsewhere.

  • With the four highest-ranked conference champions assigned to bowls, their four Playoff Quarterfinal opponents will be dictated by the bracket (i.e., No. 1 vs. No. 8/9 winner, No. 4 vs. No. 5/12 winner, No. 2 vs. 7/10 winner; No. 3 vs. 6/11 winner.)

  • The College Football Playoff bracket will follow the selection committee’s rankings, with no modifications made to avoid rematches between teams that may have played during the regular season or are from the same conference.

  • The bracket will remain in effect throughout the playoff (i.e., no re-seeding).

  • The highest seed will receive preferential placement for the Playoff Semifinal bowl assignment.

I have created templates for each conference to grab any team that is in the top 25 in that conference - here is an example

- name: ncaaf_cfp_american_athletic 
  unique_id: sensor.ncaaf_cfp_american_athletic
  state: "{{ now() }}"
  attributes:
    cfp_eligible: > 
     {% set entries = state_attr('sensor.ncaaf_conference_american_athletic', 'entries') %}
     {% set result = namespace(teams=[]) %} 
     {% for entry in entries %} 
       {% if entry.team.rank is defined and entry.team.rank <= 25 %} 
         {% set seed = entry.stats | selectattr('name', 'equalto', 'playoffSeed') | map(attribute='displayValue') | first %}
         {% set team_data = { 
            'name': entry.team.name, 
            'abbreviation': entry.team.abbreviation, 
            'shortDisplayName': entry.team.shortDisplayName, 
            'logo': entry.team.logos[0].href, 
            'seed': seed,
            'rank': entry.team.rank 
         } %} 
         {% set result.teams = result.teams + [team_data] %} 
       {% endif %} 
     {% endfor %} 
     {{ result.teams| tojson }}

I was then thinking that I would put them in order and then just have the playoff bracket refer to this sensor but it hasn’t worked so far.

- name: ncaaf_cfp_top_teams
  unique_id: sensor.ncaaf_cfp_top_teams
  state: "{{ now() }}"
  attributes:
    cfp_order: >             
      {% set conferences = ['sensor.ncaaf_cfp_atlantic_coast', 'sensor.ncaaf_cfp_big_12', 'sensor.ncaaf_cfp_big_ten', 'sensor.ncaaf_cfp_southeastern'] %} 
      {% set other_conferences = ['sensor.ncaaf_cfp_atlantic_coast', 'sensor.ncaaf_cfp_big_12', 'sensor.ncaaf_cfp_big_ten', 'sensor.ncaaf_cfp_southeastern'] %} {% set other_conferences = ['sensor.ncaaf_cfp_american_athletic', 'sensor.ncaaf_conference_usa', 'sensor.ncaaf_cfp_fbs_independents', 'sensor.ncaaf_mid_american', 'sensor.ncaaf_mountain_west', 'sensor.ncaaf_pac12', 'sensor.ncaaf_sun_belt_west', 'sensor.ncaaf_sun_belt_east'] %}
      {% set top_teams = namespace(teams=[]) %} 
      {% for conference in conferences %}
        {% set entries = state_attr(conference, 'cfp_eligible') %}
        {% if entries %} 
          {% for entry in entries %} 
            {% if entry.seed == '1' %} 
              {% set team_data = { 
                'name': entry.name, 
                'abbreviation': entry.abbreviation, 
                'shortDisplayName': entry.shortDisplayName, 
                'logo': entry.logo, 
                'rank': entry.rank 
              } %} 
              {% set top_teams.teams = top_teams.teams + [team_data] %}
            {% endif %} 
          {% endfor %} 
        {% endif %} 
      {% endfor %} 
      {% set lowest_ranked_team = None %}
      {% for conference in other_conferences %}
        {% set entries = state_attr(conference, 'cfp_eligible') %}
        {% if entries %} 
         {% for entry in entries %} 
          {% if entry.seed == '1' and (lowest_ranked_team is none or entry.rank < lowest_ranked_team.rank) %} 
            {% set lowest_ranked_team = { 
              'name': entry.name, 
              'abbreviation': entry.abbreviation, 
              'shortDisplayName': entry.shortDisplayName, 
              'logo': entry.logo, 
              'rank': entry.rank 
            } %} 
          {% endif %} 
         {% endfor %} 
        {% endif %} 
      {% endfor %} 
      {% if lowest_ranked_team is not none %}
        {% set top_teams.teams = top_teams.teams + [lowest_ranked_team] %}
      {% endif %} 
      {% set sorted_teams = top_teams.teams | sort(attribute='rank') %} 
      {{ {'entries': sorted_teams} | tojson }}

I also toyed with using the conference Id’s and just focusing on the sensor.ncaaf_cfp_top_teams with something like this but hasn’t worked yet - just in the template tool for now

{% set groups = [4, 8, 1, 5] %} 
{% set entries = state_attr('sensor.ncaaf_poll_cfp_top_25_all', 'ranks') %} 
{% set result = namespace(teams=[]) %} 
{% for group in groups %} 
  {% set top_team = None %} 
  {% for entry in entries %}
    {% if entry.team.groups.id | int == group %}
      {% if top_team is none or entry.current < top_team.current %}
          {% set top_team = entry %} 
      {% endif %} 
      {{ entry }}
    {% endif %} 
  {% endfor %} 
   {% if top_team is not none %} 
      {% set team_data = { 
        'current_rank': top_team.current, 
        'team_name': top_team.team.name, 
        'team_nickname': top_team.team.nickname, 
        'team_abbreviation': top_team.team.abbreviation, 
        'team_color': top_team.team.color, 
        'team_logo': top_team.team.logos[0].href, 
        'team_conference': top_team.team.conference, 
        'team_group_id': top_team.team.groups.id 
        } %} 
       
        {% set result.teams = result.teams + [team_data] %} 
        
    {% endif %} 
    {% endfor %}

Is there an better approach that I have been blinded to by going down this rabbit hole?

Dude this is absolute crazy stuff right here!!
Sure it might not be easy to understand the code, but it seems to spit out the exact right information.

I’ll try to add it to my board within the next days, so I might find something :slight_smile:

Great - hope so. In the meantime I have written a quick python code to pull the teams and sort them based on the current rules. I would love to change it into Jinja2 and keep everything in HA but I don’t Jinja conversion very well.

So the code is processing everything correctly but will wait to see what breaks. Pretty straight forward. Call the python code, writes the top 12 teams into a json file in the www directory, rest grabs the data from the file and puts it into a sensor and then I call the sensor.

Here is the screen shot:

Adding the python code here:

import json
import requests

# Define the API URL
api_url = "https://site.api.espn.com/apis/site/v2/sports/football/college-football/rankings?seasontype=2&type=0&level=3"

# Fetch the data from the API
response = requests.get(api_url)
data = response.json()

# Extract the relevant data
rankings = data['rankings'][0]
teams = rankings['ranks']

# Extract the relevant data
# teams = data['rankings']['ranks']

# Define the conference IDs
main_conferences = [1, 4, 5, 8]
other_conferences = [151, 12, 15, 17, 9, 37, 176, 20, 40, 22, 24, 25, 26, 27, 28, 29, 31, 30, 16]

# Process the rankings according to the CFP rules
def process_rankings(teams):
    main_conference_teams = {1: None, 4: None, 5: None, 8: None}
    other_conference_teams = []
    remaining_teams = []


    for team in teams:
        conference_id = int(team['team']['groups']['id'])
        if conference_id in main_conferences:
            if main_conference_teams[conference_id] is None or team['current'] < main_conference_teams[conference_id]['current']:
                main_conference_teams[conference_id] = team
        elif conference_id in other_conferences:
            other_conference_teams.append(team)
        else:
            remaining_teams.append(team)

    # Filter out None values and sort the main conference teams by their current rank
    top_main_conference_teams = sorted([team for team in main_conference_teams.values() if team], key=lambda x: x['current'])

    # Ensure only one team from each main conference is in the top 4
    top_4_teams = []
    selected_conferences = set()
    for team in top_main_conference_teams:
        if team['team']['groups']['id'] not in selected_conferences:
            top_4_teams.append(team)
            selected_conferences.add(team['team']['groups']['id'])
        if len(top_4_teams) == 4:
            break

    # Collect the remaining teams that weren't selected in the top 4
    remaining_teams = [team for team in teams if team not in top_4_teams]

    # Sort the remaining teams by their current rank
    remaining_teams = sorted(remaining_teams, key=lambda x: x['current'])

    # Select the next highest-ranked teams from the remaining teams to fill positions 5-12
    next_highest_ranked_teams = []
    for team in remaining_teams:
        if team not in top_4_teams:
            next_highest_ranked_teams.append(team)
        if len(next_highest_ranked_teams) == 8:
            break

    # Select the lowest-seeded team from other conferences
    other_conference_teams = sorted(other_conference_teams, key=lambda x: x['current'])
    if other_conference_teams:
        lowest_other_conference_team = other_conference_teams[0]
        if 5 <= lowest_other_conference_team['current'] <= 12:
            next_highest_ranked_teams.append(lowest_other_conference_team)
        else:
            # Replace the #12 team on the list
            lowest_other_conference_team['current'] > 12
            next_highest_ranked_teams[-1] = lowest_other_conference_team

    # Combine the teams to form the final rankings
    final_rankings = top_4_teams + next_highest_ranked_teams

    # Add CFP_ranking to each team
    for rank, team in enumerate(final_rankings, start=1):
        team['CFP_ranking'] = rank

    return final_rankings

# Get the final rankings
final_rankings = process_rankings(teams)

# Wrap the final rankings in a dictionary with the key 'teams' 
output_data = {"teams": final_rankings}

# Print the final rankings
#print("Final Rankings:")
#for rank, team in enumerate(final_rankings, start=1):
#    print(f"{rank}. {team['team']['nickname']} (CFP Ranking: {team['CFP_ranking']})")

# Save the final rankings to a JSON file
with open('cfp_final_rankings.json', 'w') as f:
    json.dump(output_data, f, indent=4)


#print("Final rankings saved to final_rankings.json")

Here is the rest sensor:

- platform: rest
  name: NCAAF CFP rankings
  unique_id: sensor.ncaaf_cfp_rankings
  resource: http://192.168.100.226:8123/local/cfp_final_rankings.json
  value_template: "{{ now() }}"  
  json_attributes:
    - teams

I haven’t put cards into a decluttering template yet, just trying to see if things work. Here is a quick snippet of what I am doing:

                                      - square: false
                                        columns: 4
                                        type: grid
                                        cards:
                                          - type: custom:mushroom-template-card
                                            entity: sensor.ncaaf_poll_cfp_top_25_all
                                            primary: >
                                              {% set rankings =
                                              state_attr('sensor.ncaaf_cfp_rankings',
                                              'teams') %} {% for ranking in rankings
                                              %} {% if ranking.CFP_ranking == 1 %} 1. 
                                              {{ ranking.team.nickname }} {{
                                              ranking.team.name }} {% endif %} {%
                                              endfor %}
                                            card_mod:
                                              style: >
                                                ha-card { background: url({% set
                                                rankings =
                                                state_attr('sensor.ncaaf_cfp_rankings',
                                                'teams') %} {% for ranking in rankings
                                                %} {% if ranking.CFP_ranking == 1 %} {{
                                                ranking.team.logos[0].href }} {% endif
                                                %} {% endfor %}) no-repeat right center;
                                                background-size: contain; /* Adjust this
                                                value to scale the image */ color:
                                                white; /* Adjust text color for better
                                                visibility */ border: 2px solid {% set
                                                rankings =
                                                state_attr('sensor.ncaaf_cfp_rankings',
                                                'teams') %} {% for ranking in rankings
                                                %} {% if ranking.CFP_ranking == 1 %} #{{
                                                ranking.team.color }} {% endif %} {%
                                                endfor %}; border-radius: 10px; /*
                                                Optional: Add rounded corners */
                                                padding: 10px; /* Optional: Add padding
                                                inside the card */ }

As always hope this helps and looking for anything that improves what I am doing

1 Like

Hey bro @bburwell, where do you get this URL? I’m trying to see the starting goalies info, but I don´t know where to get that URL

Using multiscrape:

  - name: Goalie scraper
    resource: https://www.dailyfaceoff.com/starting-goalies
    scan_interval: 43200
    sensor:
      - unique_id: nhl_starting_goalies
        name: NHL Starting Goalies
        select: '#__NEXT_DATA__'
        value_template: '{{ now() }}'
        attributes:
          - name: data
            select: '#__NEXT_DATA__'
            value_template: >
                {{ (value | from_json)['props']['pageProps']['data'] }}
1 Like

So for anyone that used my python code for the CFP pull it was incorrect. I am hoping that this fixes it (seems to be correct) and will continue to refine. I am working on bowl games as well but I might need a Ouija board for that and honestly I am hoping that ESPN will add it to the api.

Here is the updated python code:

import json
import requests

# Define the API URL
api_url = "https://site.api.espn.com/apis/site/v2/sports/football/college-football/rankings?seasontype=2&type=0&level=3"

# Fetch the data from the API
response = requests.get(api_url)
data = response.json()

# Extract the relevant data
rankings = data['rankings'][0]
teams = rankings['ranks']

# Define the conference IDs
main_conferences = [1, 4, 5, 8, 12, 15, 17, 37, 151]

# Process the rankings according to the CFP rules
def process_rankings(teams):
    main_conference_teams = {1: None, 4: None, 5: None, 8: None, 12: None, 15: None, 17: None, 37: None, 151: None}
    remaining_teams = []

    for team in teams:
        conference_id = int(team['team']['groups']['id'])
        if conference_id in main_conferences:
            if main_conference_teams[conference_id] is None or team['current'] < main_conference_teams[conference_id]['current']:
                main_conference_teams[conference_id] = team
        else:
            remaining_teams.append(team)

    # Filter out None values and sort the main conference teams by their current rank
    top_main_conference_teams = sorted([team for team in main_conference_teams.values() if team], key=lambda x: x['current'])

    # Ensure only one team from each main conference is in the top 4
    top_4_teams = []
    selected_conferences = set()
    for team in top_main_conference_teams:
        if team['team']['groups']['id'] not in selected_conferences:
            top_4_teams.append(team)
            selected_conferences.add(team['team']['groups']['id'])
        if len(top_4_teams) == 4:
            break

    # Collect the remaining teams that weren't selected in the top 4
    remaining_teams = [team for team in teams if team not in top_4_teams]

    # Sort the remaining teams by their current rank
    remaining_teams = sorted(remaining_teams, key=lambda x: x['current'])

    # Select the next highest-ranked teams from the remaining teams to fill positions 5-12
    next_highest_ranked_teams = []
    for team in remaining_teams:
        if team not in top_4_teams:
            next_highest_ranked_teams.append(team)
        if len(next_highest_ranked_teams) == 8:
            break

    # Combine the teams to form the final rankings
    final_rankings = top_4_teams + next_highest_ranked_teams

    # Adjust the 5th highest-ranked conference winner if necessary
    if len(top_main_conference_teams) > 4:
        fifth_highest_conference_team = top_main_conference_teams[4]
        if fifth_highest_conference_team['current'] > 12:
            final_rankings = final_rankings[:-1] + [fifth_highest_conference_team]

    # Add CFP_ranking to each team
    for rank, team in enumerate(final_rankings, start=1):
        team['CFP_ranking'] = rank

    return final_rankings

# Get the final rankings
final_rankings = process_rankings(teams)

# Wrap the final rankings in a dictionary with the key 'teams'
output_data = {"teams": final_rankings}

# Save the final rankings to a JSON file
with open('/config/www/cfp_final_rankings.json', 'w') as f:
    json.dump(output_data, f, indent=4)

I just use a shell command to make the call Tuesday around 5pm EST.

shell_command:
  get_cfp: 'python /config/www/cfppull.py'

I will update the layout (pretty it up) later and will fix the top 25 colors but it gives you an idea of where I am heading.

First of all, thank you for this. This is amazing. I’m trying to get this up an running for myself, please forgive the lack of HA and coding knowledge, I’m trying to learn as I go. Here’s my current configuration.yaml:

template:
  - sensor:
      - name: "Visibility in Miles"
        unit_of_measurement: "mi"
        state: >
          {{ (states('sensor.openweathermap_visibility') | float / 1609.34) | round(1) }}

# Adding NHL Sensors
  - sensor:
      - platform: rest
        scan_interval: 3600
        name: NHL Standings
        unique_id: sensor.nhl_standings
        resource: https://site.web.api.espn.com/apis/v2/sports/hockey/nhl/standings?seasontype=2&type=0&level=3
        value_template: "{{ now() }}"
        json_attributes:
          - children

      - platform: rest
        scan_interval: 3600
        name: NHL Scores
        unique_id: sensor.nhl_scores
        resource: https://site.api.espn.com/apis/v2/scoreboard/header?sport=hockey&league=nhl
        value_template: "{{ now() }}"
        json_attributes:
          - sports

##  NHL Teams
##
      - platform: teamtracker
        league_id: NHL
        team_id: DET
        name: Detroit Red Wings
      - platform: teamtracker
        league_id: NHL
        team_id: NSH
        name: Nashville Predators
      - platform: teamtracker
        league_id: NHL
        team_id: FLA
        name: Florida Panthers
      - platform: teamtracker
        league_id: NHL
        team_id: STL
        name: St Louis Blues
      - platform: teamtracker
        league_id: NHL
        team_id: COL
        name: Colorado Avalanche
      - platform: teamtracker
        league_id: NHL
        team_id: BOS
        name: Boston Bruins
      - platform: teamtracker
        league_id: NHL
        team_id: NYI
        name: New York Islanders
      - platform: teamtracker
        league_id: NHL
        team_id: PIT
        name: Pittsburg Penguins
      - platform: teamtracker
        league_id: NHL
        team_id: NJ
        name: New Jersey Devils
      - platform: teamtracker
        league_id: NHL
        team_id: DAL
        name: Dallas Stars
      - platform: teamtracker
        league_id: NHL
        team_id: CBJ
        name: Columbus Blue Jackets
      - platform: teamtracker
        league_id: NHL
        team_id: TOR
        name: Toronto Maple Leafs
      - platform: teamtracker
        league_id: NHL
        team_id: MTL
        name: Montreal Canadians
      - platform: teamtracker
        league_id: NHL
        team_id: CAR
        name: Carolina Hurricanes
      - platform: teamtracker
        league_id: NHL
        team_id: WSH
        name: Washington Senators
      - platform: teamtracker
        league_id: NHL
        team_id: CGY
        name: Calgary Flames
      - platform: teamtracker
        league_id: NHL
        team_id: NYR
        name: New York Rangers
      - platform: teamtracker
        league_id: NHL
        team_id: VAN
        name: Vancouver Canucks
      - platform: teamtracker
        league_id: NHL
        team_id: PHI
        name: Philadelphia Fylers
      - platform: teamtracker
        league_id: NHL
        team_id: LA
        name: Los Angeles Kings
      - platform: teamtracker
        league_id: NHL
        team_id: ARI
        name: Arizona Coyotes
      - platform: teamtracker
        league_id: NHL
        team_id: SJ
        name: San Jose Sharks
      - platform: teamtracker
        league_id: NHL
        team_id: BUF
        name: Buffalo Sabres
      - platform: teamtracker
        league_id: NHL
        team_id: SEA
        name: Seattle Kraken
      - platform: teamtracker
        league_id: NHL
        team_id: VGK
        name: Los Vegas Golden Knights
      - platform: teamtracker
        league_id: NHL
        team_id: TB
        name: Tampa Bay Lightning
      - platform: teamtracker
        league_id: NHL
        team_id: OTT
        name: Ottawa Senators
      - platform: teamtracker
        league_id: NHL
        team_id: WPG
        name: Winnipeg Jets
      - platform: teamtracker
        league_id: NHL
        team_id: EDM
        name: Edmonton Oilers
      - platform: teamtracker
        league_id: NHL
        team_id: MIN
        name: Minnesota Wild
      - platform: teamtracker
        league_id: NHL
        team_id: ANA
        name: Anaheim Ducks
      - platform: teamtracker
        league_id: NHL
        team_id: CHI
        name: Chicago Blackhawks
  
### NHL Divisions
      - name: NHL East Atlantic
        unique_id: sensor.nhl_east_atlantic
        state: "{{ now() }}"
        attributes:
          entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][0]['standings']['entries'] }}"
      - name: NHL East Metropolitan
        unique_id: sensor.nhl_east_metropolitan
        state: "{{ now() }}"
        attributes:
          entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][1]['standings']['entries'] }}"
      - name: NHL West Central
        unique_id: sensor.nhl_west_central
        state: "{{ now() }}"
        attributes:
          entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][0]['standings']['entries'] }}"
      - name: NHL West Pacific
        unique_id: sensor.nhl_west_pacific
        state: "{{ now() }}"
        attributes:
          entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][1]['standings']['entries'] }}"
      
### NHL Wildcard
###
      - name: NHL Wildcard Standings
        unique_id: sensor.nhl_wildcard_standings
        state: "{{ now() }}"
        attributes:
          east_atlantic_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][0]['standings']['entries'] }}"
          east_metropolitan_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][1]['standings']['entries'] }}"
          east_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][:2] }}"
          east_hunt: >
              {% set hteams = namespace(hteam=[]) %}
              {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
                {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
                {% else %}
                      {% set hteams.hteam = hteams.hteam + [team] %}
                {% endfor %}
              {% endfor %}
              {{ hteams.hteam }}
          east_eliminated: >
            {% set eteams = namespace(eteam=[]) %}
            {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
              {% for stat in team['stats'] %}
                {% if stat.name == 'clincher' %}
                    {% set eteams.eteam = eteams.eteam + [team] %}
                {% endif %}
              {% endfor %}
            {% endfor %}
            {{ eteams.eteam }}
          west_central_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][0]['standings']['entries'] }}"
          west_pacific_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][1]['standings']['entries'] }}"
          west_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][:2] }}"
          west_hunt: >
              {% set hteams = namespace(hteam=[]) %}
              {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
                {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
                {% else %}
                      {% set hteams.hteam = hteams.hteam + [team] %}
                {% endfor %}
              {% endfor %}
              {{ hteams.hteam }}
          west_eliminated: >
            {% set eteams = namespace(eteam=[]) %}
            {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
              {% for stat in team['stats'] %}
                {% if stat.name == 'clincher' %}
                    {% set eteams.eteam = eteams.eteam + [team] %}
                {% endif %}
              {% endfor %}
            {% endfor %}
            {{ eteams.eteam }}      

And the errors that HA is throwing:

Logger: homeassistant.helpers.event
Source: helpers/template.py:635
First occurred: 9:41:48 PM (2 occurrences)
Last logged: 9:41:52 PM

Error while processing template: Template<template=({%- for team in integration_entities("teamtracker") -%} {%- if state_attr(team, "league") == "NHL" -%} {%- if states(team) == "PRE" -%} {%- if state_attr(team, "team_homeaway") == "home" -%} {%- if team in state_attr('sensor.nfl_red_zone','teams') -%} {{{"type": "custom:teamtracker-card", "entity": team, "card_mod": {"style": "ha-card {\n\n color: black; \n background-color: #ffcccc; \n box-shadow: 0 0 10px 5px red;\n}\n"}, "home_side": "right"}}}, {%- else -%} {{{"type": "custom:teamtracker-card", "entity": team, "home_side": "right"}}}, {%- endif -%} {%- endif -%} {%- endif -%} {%- endif -%} {%- endfor -%}) renders=2>
Error while processing template: Template<template=({%- for team in integration_entities("teamtracker") -%} {%- if state_attr(team, "league") == "NHL" -%} {%- if states(team) == "PRE" -%} {%- if state_attr(team, "team_homeaway") == "home" -%} {%- if team in state_attr('sensor.nfl_red_zone','teams') -%} {{{"type": "custom:teamtracker-card", "entity": team, "card_mod": {"style": "ha-card {\n\n color: black; \n background-color: #ffcccc; \n box-shadow: 0 0 10px 5px red;\n}\n"}, "home_side": "right"}}}, {%- else -%} {{{"type": "custom:teamtracker-card", "entity": team, "home_side": "right"}}}, {%- endif -%} {%- endif -%} {%- endif -%} {%- endif -%} {%- endfor -%}) renders=6>
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 633, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2735, in _render_with_context
    return template.render(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 5, in top-level template code
TypeError: argument of type 'NoneType' is not iterable

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 750, in async_render_to_info
    render_info._result = self.async_render(  # noqa: SLF001
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 635, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: TypeError: argument of type 'NoneType' is not iterable

And

Logger: homeassistant.config
Source: config.py:357
First occurred: 9:41:24 PM (1 occurrences)
Last logged: 9:41:24 PM

Invalid config for 'template' at configuration.yaml, line 31: 'platform' is an invalid option for 'template', check: sensor->0->platform Invalid config for 'template' at configuration.yaml, line 31: required key 'state' not provided Invalid config for 'template' at configuration.yaml, line 32: 'scan_interval' is an invalid option for 'template', check: sensor->0->scan_interval Invalid config for 'template' at configuration.yaml, line 35: 'resource' is an invalid option for 'template', check: sensor->0->resource Invalid config for 'template' at configuration.yaml, line 36: 'value_template' is an invalid option for 'template', check: sensor->0->value_template Invalid config for 'template' at configuration.yaml, line 37: 'json_attributes' is an invalid option for 'template', check: sensor->0->json_attributes

What am I missing or doing wrong? Any and all help is greatly appreciated.

Your errors are because the format for the data in configuration.yaml isn’t correct.

I’ll be honest I wouldn’t encourage you to put everything in the configuration.yaml. It will become a beast to manage if you do what some of us do and chase sports down the rabbit hole.

Others I am sure are different but in my configuration I separate the sensors out by sport. I bunch Template into a single file but I have moved almost everything to sensors.

Here is what I have in my configuration.yaml and the includes are pointing to directories I created in the config directory.

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
sensor: !include_dir_merge_list sensors/
template: !include template.yaml

You can see some of the different files here:

In NHL starting at the top this is how my file looks:

The top of my template file looks like this:

I would pop-over to @kbrown01 github here and copy what he has done
https://github.com/kbrown01/SportStandingsScores

1 Like

Appreciate you. I’m only looking to do only NHL stats. So, let me go a little further back. Running HA in virttualbox. So I’m going to need to create separate yaml files using file editor in the same location as my config.yaml? I like your organization, so I want to create a yaml for nhl sensors, sensors, groups and templates correct?

So basically adjust the sensor.yaml and the template yaml from the git directory and add those to the files I created? Then in my config.yaml, point it to the directories I created?

Or am i just overthinking this and there is an easier way to do it?

@kbrown01 github has the yaml’s you need - sensor, template and dashboard. You could just pull out the NHL stuff for Sensor/Template and then grab his code for an NHL dashboard in his dashboard.yaml.

ok I think i got that

sensor.yaml

# Adding NHL Sensors
  - sensor:
      - platform: rest
        scan_interval: 3600
        name: NHL Standings
        unique_id: sensor.nhl_standings
        resource: https://site.web.api.espn.com/apis/v2/sports/hockey/nhl/standings?seasontype=2&type=0&level=3
        value_template: "{{ now() }}"
        json_attributes:
          - children

      - platform: rest
        scan_interval: 3600
        name: NHL Scores
        unique_id: sensor.nhl_scores
        resource: https://site.api.espn.com/apis/v2/scoreboard/header?sport=hockey&league=nhl
        value_template: "{{ now() }}"
        json_attributes:
          - sports

##  NHL Teams
##
      - platform: teamtracker
        league_id: NHL
        team_id: DET
        name: Detroit Red Wings
      - platform: teamtracker
        league_id: NHL
        team_id: NSH
        name: Nashville Predators
      - platform: teamtracker
        league_id: NHL
        team_id: FLA
        name: Florida Panthers
      - platform: teamtracker
        league_id: NHL
        team_id: STL
        name: St Louis Blues
      - platform: teamtracker
        league_id: NHL
        team_id: COL
        name: Colorado Avalanche
      - platform: teamtracker
        league_id: NHL
        team_id: BOS
        name: Boston Bruins
      - platform: teamtracker
        league_id: NHL
        team_id: NYI
        name: New York Islanders
      - platform: teamtracker
        league_id: NHL
        team_id: PIT
        name: Pittsburg Penguins
      - platform: teamtracker
        league_id: NHL
        team_id: NJ
        name: New Jersey Devils
      - platform: teamtracker
        league_id: NHL
        team_id: DAL
        name: Dallas Stars
      - platform: teamtracker
        league_id: NHL
        team_id: CBJ
        name: Columbus Blue Jackets
      - platform: teamtracker
        league_id: NHL
        team_id: TOR
        name: Toronto Maple Leafs
      - platform: teamtracker
        league_id: NHL
        team_id: MTL
        name: Montreal Canadians
      - platform: teamtracker
        league_id: NHL
        team_id: CAR
        name: Carolina Hurricanes
      - platform: teamtracker
        league_id: NHL
        team_id: WSH
        name: Washington Senators
      - platform: teamtracker
        league_id: NHL
        team_id: CGY
        name: Calgary Flames
      - platform: teamtracker
        league_id: NHL
        team_id: NYR
        name: New York Rangers
      - platform: teamtracker
        league_id: NHL
        team_id: VAN
        name: Vancouver Canucks
      - platform: teamtracker
        league_id: NHL
        team_id: PHI
        name: Philadelphia Fylers
      - platform: teamtracker
        league_id: NHL
        team_id: LA
        name: Los Angeles Kings
      - platform: teamtracker
        league_id: NHL
        team_id: ARI
        name: Arizona Coyotes
      - platform: teamtracker
        league_id: NHL
        team_id: SJ
        name: San Jose Sharks
      - platform: teamtracker
        league_id: NHL
        team_id: BUF
        name: Buffalo Sabres
      - platform: teamtracker
        league_id: NHL
        team_id: SEA
        name: Seattle Kraken
      - platform: teamtracker
        league_id: NHL
        team_id: VGK
        name: Los Vegas Golden Knights
      - platform: teamtracker
        league_id: NHL
        team_id: TB
        name: Tampa Bay Lightning
      - platform: teamtracker
        league_id: NHL
        team_id: OTT
        name: Ottawa Senators
      - platform: teamtracker
        league_id: NHL
        team_id: WPG
        name: Winnipeg Jets
      - platform: teamtracker
        league_id: NHL
        team_id: EDM
        name: Edmonton Oilers
      - platform: teamtracker
        league_id: NHL
        team_id: MIN
        name: Minnesota Wild
      - platform: teamtracker
        league_id: NHL
        team_id: ANA
        name: Anaheim Ducks
      - platform: teamtracker
        league_id: NHL
        team_id: CHI
        name: Chicago Blackhawks

template.yaml

sensor:

### NHL Divisions
###
  - name: NHL East Atlantic
    unique_id: sensor.nhl_east_atlantic
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: NHL East Metropolitan
    unique_id: sensor.nhl_east_metropolitan
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: NHL West Central
    unique_id: sensor.nhl_west_central
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: NHL West Pacific
    unique_id: sensor.nhl_west_pacific
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][1]['standings']['entries'] }}"
###
### NHL Wildcard
###
  - name: NHL Wildcard Standings
    unique_id: sensor.nhl_wildcard_standings
    state: "{{ now() }}"
    attributes:
      east_atlantic_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][0]['standings']['entries'] }}"
      east_metropolitan_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][1]['standings']['entries'] }}"
      east_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][:2] }}"
      east_hunt: >
          {% set hteams = namespace(hteam=[]) %}
          {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
            {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
            {% else %}
                  {% set hteams.hteam = hteams.hteam + [team] %}
            {% endfor %}
          {% endfor %}
          {{ hteams.hteam }}
      east_eliminated: >
        {% set eteams = namespace(eteam=[]) %}
        {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
          {% for stat in team['stats'] %}
            {% if stat.name == 'clincher' %}
                {% set eteams.eteam = eteams.eteam + [team] %}
            {% endif %}
          {% endfor %}
        {% endfor %}
        {{ eteams.eteam }}
      west_central_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][0]['standings']['entries'] }}"
      west_pacific_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][1]['standings']['entries'] }}"
      west_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][:2] }}"
      west_hunt: >
          {% set hteams = namespace(hteam=[]) %}
          {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
            {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
            {% else %}
                  {% set hteams.hteam = hteams.hteam + [team] %}
            {% endfor %}
          {% endfor %}
          {{ hteams.hteam }}
      west_eliminated: >
        {% set eteams = namespace(eteam=[]) %}
        {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
          {% for stat in team['stats'] %}
            {% if stat.name == 'clincher' %}
                {% set eteams.eteam = eteams.eteam + [team] %}
            {% endif %}
          {% endfor %}
        {% endfor %}
        {{ eteams.eteam }}

con’t

dashboard adjusted to just NHL:

decluttering_templates:
  nhl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 1600px;'
        tbody tr td:first-child: 'width: 2%;'
        tbody tr td:nth-child(2): 'width: 20%;'
        tbody tr td:nth-child(n+3): 'width: 5%;'
        tbody tr:hover: 'background-color: green!important; color:white!important;'
        tbody tr td:nth-child(7): 'background-color: green; color: white;'
      card_mod:
        style:
          .: |
            ha-card {
              overflow: auto;
              }
          $: |
            .card-header {
               padding-top: 6px!important;
               padding-bottom: 4px!important;
               font-size: 14px!important;
               line-height: 14px!important;
               font-weight: bold!important;
             }
      entities:
        include: '[[entity]]'
        exclude: '[[excluded_entities]]'
      sort_by: entries-
      columns:
        - hidden: true
          data: '[[attribute]]'
          modify: '[[sort]]'
        - name: <div>C</div>
          data: '[[attribute]]'
          modify: >-
            if(typeof x.stats.find(y=>y.abbreviation == 'CLINCH') !==
            'undefined' ){x.stats.find(y=>y.abbreviation ==
            'CLINCH').displayValue}else{'-'}
        - name: Team
          data: '[[attribute]]'
          modify: >-
            '<div><a href="' + x.team.links[0].href + '" target="_blank"><img
            src="' + x.team.logos[0].href + '" style="height:
            20px;vertical-align:middle;"></a>&nbsp;' + x.team.displayName +
            '</div>'
        - name: <div>GP</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GP').displayValue
        - name: <div>W</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'W').displayValue
        - name: <div>L</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'L').displayValue
        - name: <div>OTL</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'OTL').displayValue
        - name: <div>PTS</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'PTS').displayValue
        - name: <div>RW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'RW').displayValue
        - name: <div>ROW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'ROW').displayValue
        - name: <div>SOW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'SOW').displayValue
        - name: <div>SOL</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'SOL').displayValue
        - name: <div>HOME</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'HOME').displayValue
        - name: <div>AWAY</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'AWAY').displayValue
        - name: <div>GF</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GF').displayValue
        - name: <div>GA</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GA').displayValue
        - name: <div>DIFF</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'DIFF').displayValue
        - name: <div>L10</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'L10').summary
        - name: <div>STRK</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'STRK').displayValue
  game_stats:
    card:
      type: custom:auto-entities
      unique: true
      show_empty: false
      card:
        type: custom:layout-card
        layout_type: masonry
        width: 200px
        max-columns: 5
      card_param: cards
      filter:
        template: |
          {%- for team in integration_entities("teamtracker") -%}
            {%- if state_attr(team, "league") == "[[sport]]" -%}
            {%- if states(team) == "[[status]]" -%}
            {%- if state_attr(team, "team_homeaway") == "home" -%}
            {%- if team in state_attr('sensor.nfl_red_zone','teams') -%}
              {{{"type": "custom:teamtracker-card",
                "entity": team,
                "card_mod": {"style": "ha-card {\n\n    color:  black; \n    background-color:  #ffcccc; \n    box-shadow: 0 0 10px 5px red;\n}\n"},
                "home_side": "right"}}},
            {%- else -%}
              {{{"type": "custom:teamtracker-card",
                "entity": team, 
                "home_side": "right"}}},
            {%- endif -%}
            {%- endif -%}
            {%- endif -%}
            {%- endif -%}
          {%- endfor -%}
        exclude:
          - entity_id: '*team_tracker*'
      sort:
        method: attribute
        attribute: date
views:
  - theme: Backend-selected
    title: Sports
    type: panel
    icon: mdi:strategy
    badges: []
    cards:
      - type: custom:mod-card
        card_mod:
          style:
            tabbed-card $: |
              mwc-tab {
                background: var(--ha-card-background, var(--card-background-color, white) );
                border-color: var(--ha-card-border-color, var(--divider-color, #e0e0e0) );
                border-width: 2px;
                border-top-left-radius: 20px;
                border-top-right-radius: 20px;
                border-style: solid;
                overflow: hidden;
                width: 25%;
              }
              mwc-tab[active] {
                background: #EBFFD8 !important;
              }
        card:
          type: custom:tabbed-card
          styles:
            '--mdc-theme-primary': green
            '--mdc-tab-text-label-color-default': silver
            '--mdc-typography-button-font-size': 12px
          tabs:
            - attributes:
                label: NHL
                icon: mdi:hockey-puck
              card:
                type: custom:mod-card
                card_mod:
                  style:
                    tabbed-card $: |
                      mwc-tab {
                        background: var(--ha-card-background, var(--card-background-color, white) );
                        border-color: var(--ha-card-border-color, var(--divider-color, #e0e0e0) );
                        border-width: 2px;
                        border-top-left-radius: 20px;
                        border-top-right-radius: 20px;
                        border-style: solid;
                        overflow: hidden;
                        width: 20%;
                      }
                      mwc-tab[active] {
                        background: #EBFFD8 !important;
                      }
                card:
                  type: custom:tabbed-card
                  styles:
                    '--mdc-theme-primary': green
                    '--mdc-tab-text-label-color-default': silver
                    '--mdc-typography-button-font-size': 12px
                  tabs:
                    - attributes:
                        label: Standings
                        icon: mdi:ballot
                      card:
                        type: custom:mod-card
                        card_mod:
                          style:
                            tabbed-card $: |
                              mwc-tab {
                                background: var(--ha-card-background, var(--card-background-color, white) );
                                border-color: var(--ha-card-border-color, var(--divider-color, #e0e0e0) );
                                border-width: 2px;
                                border-top-left-radius: 20px;
                                border-top-right-radius: 20px;
                                border-style: solid;
                                overflow: hidden;
                                width: 25%;
                              }
                              mwc-tab[active] {
                                background: #EBFFD8 !important;
                              }
                        card:
                          type: custom:tabbed-card
                          styles:
                            '--mdc-theme-primary': green
                            '--mdc-tab-text-label-color-default': silver
                            '--mdc-typography-button-font-size': 12px
                          tabs:
                            - attributes:
                                label: Divisional
                              card:
                                type: custom:stack-in-card
                                mode: vertical
                                cards:
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Eastern Atlantic
                                      - entity: sensor.nhl_east_atlantic
                                      - attribute: entries
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Eastern Metropolitan
                                      - entity: sensor.nhl_east_metropolitan
                                      - attribute: entries
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: West Central
                                      - entity: sensor.nhl_west_central
                                      - attribute: entries
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: West Pacific
                                      - entity: sensor.nhl_west_pacific
                                      - attribute: entries
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                            - attributes:
                                label: Conference
                              card:
                                type: custom:stack-in-card
                                mode: vertical
                                cards:
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Eastern
                                      - entity: sensor.nhl_east_*
                                      - attribute: entries
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Western
                                      - entity: sensor.nhl_west_*
                                      - attribute: entries
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                          - sensor.nhl_wildcard
                                          - sensor.nhl_wildcard_standings
                            - attributes:
                                label: Overall
                              card:
                                type: custom:decluttering-card
                                template: nhl_settings
                                variables:
                                  - title: Overall
                                  - entity: sensor.nhl_*_*
                                  - attribute: entries
                                  - excluded_entities:
                                      - sensor.nhl_starting_goalies
                                      - sensor.nhl_wildcard
                                      - sensor.nhl_wildcard_standings
                                  - sort: >-
                                      x.stats.find(y=>y.shortDisplayName ==
                                      'PTS').value
                            - attributes:
                                label: Wildcard
                              card:
                                type: custom:stack-in-card
                                mode: vertical
                                cards:
                                  - type: markdown
                                    content: |
                                      <h2>Eastern Conference</h2>
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Atlantic Leaders
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: east_atlantic_top
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Metropolitan Leaders
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: east_metropolitan_top
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Wildcards
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: east_wildcard
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: In The Hunt
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: east_hunt
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Eliminated
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: east_eliminated
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: markdown
                                    content: |
                                      <h2>Western Conference</h2>
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Central Leaders
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: west_central_top
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Pacific Leaders
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: west_pacific_top
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Wildcards
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: west_wildcard
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: In The Hunt
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: west_hunt
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: Eliminated
                                      - entity: sensor.nhl_wildcard_standings
                                      - attribute: west_eliminated
                                      - excluded_entities:
                                          - sensor.nhl_starting_goalies
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                    - attributes:
                        label: Postgame
                        icon: mdi:hockey-sticks
                      card:
                        type: custom:decluttering-card
                        template: game_stats
                        variables:
                          - sport: NHL
                          - status: POST
                    - attributes:
                        label: Live
                        icon: mdi:hockey-puck
                      card:
                        type: custom:decluttering-card
                        template: game_stats
                        variables:
                          - sport: NHL
                          - status: IN
                    - attributes:
                        label: Pregame
                        icon: mdi:blood-bag
                      card:
                        type: custom:decluttering-card
                        template: game_stats
                        variables:
                          - sport: NHL
                          - status: PRE
                    - attributes:
                        label: Starting Goalies
                        icon: mdi:strategy
                      card:
                        type: custom:flex-table-card
                        title: Starting Goalies
                        css:
                          table+: 'padding: 0px; width: 1600px;'
                          tbody tr:hover: >-
                            background-color: green!important;
                            color:white!important;
                          tbody tr td:nth-child(10): 'background-color: green; color: white;'
                        card_mod:
                          style: |
                            ha-card {
                                overflow: auto;
                            }
                            $: |
                                .card-header {
                                   padding: 12px 0px 8px 4px!important;
                                   font-size: 16px!important;
                                   line-height: 18px!important;
                                   font-weight: bold!important;
                                 }
                        entities:
                          include: sensor.nhl_starting_goalies
                        columns:
                          - name: HOME
                            data: data
                            modify: >-
                              '<div><img src="' + x.homeTeamLogoSvg + '"
                              style="height:
                              20px;vertical-align:middle;">&nbsp;' +
                              x.homeTeamName + '</div>'
                          - name: GOALIE
                            data: data
                            modify: x.homeGoalieName
                          - name: RANK
                            data: data
                            modify: >-
                              if(x.homeGoaliePositionRank === null
                              ){'None'}else{x.homeGoaliePositionRank}
                          - name: W
                            data: data
                            modify: >-
                              if(x.homeGoalieWins === null
                              ){'0'}else{x.homeGoalieWins}
                          - name: L
                            data: data
                            modify: >-
                              if(x.homeGoalieLosses === null
                              ){'0'}else{x.homeGoalieLosses}
                          - name: OTL
                            data: data
                            modify: >-
                              if(x.homeGoalieOvertimeLosses === null
                              ){'0'}else{x.homeGoalieOvertimeLosses}
                          - name: SO
                            data: data
                            modify: >-
                              if(x.homeGoalieShutouts === null
                              ){'0'}else{x.homeGoalieShutouts}
                          - name: SVP
                            data: data
                            modify: Number(x.homeGoalieSavePercentage).toFixed(3)
                          - name: GAA
                            data: data
                            modify: Number(x.homeGoalieGoalsAgainstAvg).toFixed(2)
                          - name: PICK
                            data: data
                            modify: |-
                              switch(true){
                                case (x.homeGoalieGoalsAgainstAvg == 0) || (x.awayGoalieGoalsAgainstAvg == 0) :
                                  '<div style="text-align:center;"><ha-icon icon="mdi:crosshairs-question"></div>';
                                  break;
                                case (x.homeGoalieGoalsAgainstAvg - x.awayGoalieGoalsAgainstAvg) > 0:
                                  '<div style="text-align:center;"><ha-icon icon="mdi:arrow-right"></div>';
                                  break;
                                case (x.homeGoalieGoalsAgainstAvg - x.awayGoalieGoalsAgainstAvg) < 0:
                                  '<div style="text-align:center;"><ha-icon icon="mdi:arrow-left"></div>';
                                  break;
                                default:
                                  '<div style="text-align:center;"><ha-icon icon="mdi:arrow-all"></div>';
                                }
                          - name: AWAY
                            data: data
                            modify: >-
                              '<div><img src="' + x.awayTeamLogoSvg + '"
                              style="height:
                              20px;vertical-align:middle;">&nbsp;' +
                              x.awayTeamName + '</div>'
                          - name: GOALIE
                            data: data
                            modify: x.awayGoalieName
                          - name: RANK
                            data: data
                            modify: >-
                              if(x.awayGoaliePositionRank == null
                              ){'None'}else{x.awayGoaliePositionRank}
                          - name: W
                            data: data
                            modify: >-
                              if(x.awayGoalieWins === null
                              ){'0'}else{x.awayGoalieWins}
                          - name: L
                            data: data
                            modify: >-
                              if(x.awayGoalieLosses === null
                              ){'0'}else{x.awayGoalieLosses}
                          - name: OTL
                            data: data
                            modify: >-
                              if(x.awayGoalieOvertimeLosses === null
                              ){'0'}else{x.awayGoalieOvertimeLosses}
                          - name: SO
                            data: data
                            modify: >-
                              if(x.awayGoalieShutouts === null
                              ){'0'}else{x.awayGoalieShutouts}
                          - name: SVP
                            data: data
                            modify: Number(x.awayGoalieSavePercentage).toFixed(3)
                          - name: GAA
                            data: data
                            modify: Number(x.awayGoalieGoalsAgainstAvg).toFixed(2)
title: Sports Standings and Scores

which gets me what I want…just now info. I have to hammer down the config directory navigation and figure out how to get the info loading. But it looks like this;

so progress lol

A couple points:

  • shouldn’t need that sensor: in sensor.yaml file as long as you are pointing to it in your configuration.yaml. Not sure HA will run without but honestly don’t know.

Also look at how @kbrown01 has the yaml’s formatted - they are to the left. Copy his code exactly.

Coding is very finicky about alignment, spacing, etc. I am always checking 2 places: log files for errors (search on NHL in your case) and the sensor themselves. If they are empty it is either a code issue or possibly an api pull issue.

@ehcah taught me this trick - uncheck the attributes box after your first load - makes searching much faster
image

When it is working You should see data in the sensor
image

will play around with it and report back…thanks brotha

ok, having issues with the template. Copied and pasted directly from the git file. HA is throwing these errors…thoughts?

Logger: homeassistant.helpers.event
Source: helpers/template.py:635
First occurred: 1:32:06 PM (2 occurrences)
Last logged: 1:32:06 PM

Error while processing template: Template<template=({%- for team in integration_entities("teamtracker") -%} {%- if state_attr(team, "league") == "NHL" -%} {%- if states(team) == "POST" -%} {%- if state_attr(team, "team_homeaway") == "home" -%} {%- if team in state_attr('sensor.nfl_red_zone','teams') -%} {{{"type": "custom:teamtracker-card", "entity": team, "card_mod": {"style": "ha-card {\n\n color: black; \n background-color: #ffcccc; \n box-shadow: 0 0 10px 5px red;\n}\n"}, "home_side": "right"}}}, {%- else -%} {{{"type": "custom:teamtracker-card", "entity": team, "home_side": "right"}}}, {%- endif -%} {%- endif -%} {%- endif -%} {%- endif -%} {%- endfor -%}) renders=2>
Error while processing template: Template<template=({%- for team in integration_entities("teamtracker") -%} {%- if state_attr(team, "league") == "NHL" -%} {%- if states(team) == "PRE" -%} {%- if state_attr(team, "team_homeaway") == "home" -%} {%- if team in state_attr('sensor.nfl_red_zone','teams') -%} {{{"type": "custom:teamtracker-card", "entity": team, "card_mod": {"style": "ha-card {\n\n color: black; \n background-color: #ffcccc; \n box-shadow: 0 0 10px 5px red;\n}\n"}, "home_side": "right"}}}, {%- else -%} {{{"type": "custom:teamtracker-card", "entity": team, "home_side": "right"}}}, {%- endif -%} {%- endif -%} {%- endif -%} {%- endif -%} {%- endfor -%}) renders=2>
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 633, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2735, in _render_with_context
    return template.render(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 5, in top-level template code
TypeError: argument of type 'NoneType' is not iterable

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 750, in async_render_to_info
    render_info._result = self.async_render(  # noqa: SLF001
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 635, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: TypeError: argument of type 'NoneType' is not iterable
Logger: homeassistant.config
Source: config.py:357
First occurred: 1:32:05 PM (5 occurrences)
Last logged: 1:32:05 PM

Invalid config for 'template' at template.yaml, line 4: 'name' is an invalid option for 'template', check: name Invalid config for 'template' at template.yaml, line 6: 'state' is an invalid option for 'template', check: state Invalid config for 'template' at template.yaml, line 7: 'attributes' is an invalid option for 'template', check: attributes
Invalid config for 'template' at template.yaml, line 11: 'state' is an invalid option for 'template', check: state Invalid config for 'template' at template.yaml, line 12: 'attributes' is an invalid option for 'template', check: attributes Invalid config for 'template' at template.yaml, line 9: 'name' is an invalid option for 'template', check: name
Invalid config for 'template' at template.yaml, line 14: 'name' is an invalid option for 'template', check: name Invalid config for 'template' at template.yaml, line 16: 'state' is an invalid option for 'template', check: state Invalid config for 'template' at template.yaml, line 17: 'attributes' is an invalid option for 'template', check: attributes
Invalid config for 'template' at template.yaml, line 19: 'name' is an invalid option for 'template', check: name Invalid config for 'template' at template.yaml, line 21: 'state' is an invalid option for 'template', check: state Invalid config for 'template' at template.yaml, line 22: 'attributes' is an invalid option for 'template', check: attributes
Invalid config for 'template' at template.yaml, line 27: 'name' is an invalid option for 'template', check: name Invalid config for 'template' at template.yaml, line 29: 'state' is an invalid option for 'template', check: state Invalid config for 'template' at template.yaml, line 30: 'attributes' is an invalid option for 'template', check: attributes

Both standing and wildcard now have info on the sensor…so again, progress

what do the first 30 lines of your template.yaml file look like? Is your template file identical to @kbrown01 template.yaml? Alignment and text?

###
### NHL Divisions
###
  - name: NHL East Atlantic
    unique_id: sensor.nhl_east_atlantic
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: NHL East Metropolitan
    unique_id: sensor.nhl_east_metropolitan
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: NHL West Central
    unique_id: sensor.nhl_west_central
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: NHL West Pacific
    unique_id: sensor.nhl_west_pacific
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.nhl_standings','children')[1]['children'][1]['standings']['entries'] }}"
###
### NHL Wildcard
###
  - name: NHL Wildcard Standings
    unique_id: sensor.nhl_wildcard_standings
    state: "{{ now() }}"
    attributes:
      east_atlantic_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][0]['standings']['entries'] }}"
      east_metropolitan_top: "{{ state_attr('sensor.nhl_wildcard','overall')[0]['children'][1]['standings']['entries'] }}"
      east_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][:2] }}"
      east_hunt: >
          {% set hteams = namespace(hteam=[]) %}
          {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
            {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
            {% else %}
                  {% set hteams.hteam = hteams.hteam + [team] %}
            {% endfor %}
          {% endfor %}
          {{ hteams.hteam }}
      east_eliminated: >
        {% set eteams = namespace(eteam=[]) %}
        {% for team in state_attr('sensor.nhl_wildcard','children')[0]['standings']['entries'][2:] %}
          {% for stat in team['stats'] %}
            {% if stat.name == 'clincher' %}
                {% set eteams.eteam = eteams.eteam + [team] %}
            {% endif %}
          {% endfor %}
        {% endfor %}
        {{ eteams.eteam }}
      west_central_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][0]['standings']['entries'] }}"
      west_pacific_top: "{{ state_attr('sensor.nhl_wildcard','overall')[1]['children'][1]['standings']['entries'] }}"
      west_wildcard: "{{ state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][:2] }}"
      west_hunt: >
          {% set hteams = namespace(hteam=[]) %}
          {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
            {% for stat in team['stats'] | selectattr('name','eq','clincher') %}
            {% else %}
                  {% set hteams.hteam = hteams.hteam + [team] %}
            {% endfor %}
          {% endfor %}
          {{ hteams.hteam }}
      west_eliminated: >
        {% set eteams = namespace(eteam=[]) %}
        {% for team in state_attr('sensor.nhl_wildcard','children')[1]['standings']['entries'][2:] %}
          {% for stat in team['stats'] %}
            {% if stat.name == 'clincher' %}
                {% set eteams.eteam = eteams.eteam + [team] %}
            {% endif %}
          {% endfor %}
        {% endfor %}
        {{ eteams.eteam }}

copy and pasted directly from the git file…nothing above the “###”

So my setup is different because I have pulled everything out, and because some of the NCAAF conferences broke the templates I have moved them to sensors.

Try this:
add
sensor: to the top of the template.yaml here is an example of the top of mine:
image

also I would move everything over 2 spaces so it lines up with the left like mine.

let me know if this fixes it.

Sensors look ok. Sometimes it takes a bit to populate.

well…the sensor flag in the template, seemingly worked.

it pulled in statistical data which is AWESOME.

do i have to do anything special for game cards?
is that the sensor.nhl_scores im guessing?