Sports Standings and Scores

A note to everyone. This weekend I am going to perform a major update to make things a bit easier to manage. I just did some testing and had no idea that decluttering templates can include a card that includes decluttering templates.

To start with, this will make things much easier to manage with Pre/Post/In game stats by using a decluttering template that can use card_mod in a more straghtforward edit and not trying to use jinja to make the cards with auto_entities.

as in this works:

decluttering_templates:
  test1:
    card:
      type: vertical-stack
      cards:
        - type: custom:decluttering-card
          template: test2
          variables:
            - teststring1: '[[teststring]] which is modified'
  test2:
    card:
      type: markdown
      content: '[[teststring1]]'
views:
  - title: Home
    cards:
      - type: custom:decluttering-card
        template: test1
        variables:
          - teststring: this is a test
title: Regular Playground

So the Teamtracker scoring built by auto-entities can just call appropriate decluttering templates for red zone, overtime, etc.

image

This may not work with filters and auto-entities. We shall see.

Hello @kbrown01 just wanted to say this is great. I’ve got this setup locally and also helped set it up for others. I know you mentioned about a major upgrade over the weekend. I went ahead and submitted a PR to you if you’d like. One of the things I thought was to make this easier to add a full sport and remove would be to use built in packages. I also did some updating to the dashboard as a lot of them were using index and not searching based off type which was causing wrong values to be displayed in the dash. Feel free to use what I’ve done in the PR if you’d like. The only other thing I made a change to was the ordering of the tabs to do Pre/In/Post. Again love this setup!

2 Likes

Thanks! I will take a look … packages are perfect. I did not get around this weekend to doing anything however I would note that it looks like you grabbed code prior to me updating it to use (mostly) named based lookups.

Things I would like to do:

  1. Implement something for Playoff NFL, NHL then MLB and NBA
  2. Figure out if it is possible to send a YouTube change channel command. Would be real cool to see Red Zone in the GUI, click and tune to that station (assuming of course the game is on YouTube). I can do it with my DirecTV integration and plan to implement that for local games and those on DirecTV channels.
  3. Red Zone-like implementation for MLB (Bases Loaded?), Hockey, Basketball (Overtime?)
  4. March Madness???
  5. Try to improve NHL Starting Goalies as it’s running key method isn’t working well

The change channel thing will be dependent on not just the service (YouTubeTV), but the device (Roku).

I use those examples because it is what we are using.

The Roku api does not allow for that granular control. You can change to a Roku Channel (service). But, cannot change the channel in that service. So, that part will be very specific to each users’ setup.

Agreed and understood. My huge DirecTV + Vizio TV integration has customized things just like that. I keep a JSON file around with station vs. number and do a favorites view where you click one to change the channel (sent through REST).

Now I am sure noting like that exists generically for YouTube (aka … REST command to pick the channel). Because I use Vizio and Vizio publishes every command to launch an app, I also wrote the App plugin:

Logo app … one click to get to a channel.
I could log key strokes or searches or maybe even Alexa stuff but yes, it would be custom.

1 Like

Happy note. Am heading out to Sharks v Golden Nights so I checked the “Starting Goalies” tab to see whose in net and it is working! Maybe the grabbing of the ever-changing key works?

What’s the latest for NBA? I have scores showing but no standings in Divisional, conference, overall etc…

NBA is preseason. The current setup from @kbrown01 is for regular season.

With no changes to anything, they should start showing up when the season starts.

ah yes of course it’s pre-season! duh…my bad! Got excited when I saw games coming up!

1 Like

You can change the REST query string for preseason. I am not in front of my computer to know which parameter it is.

Of course you would need to reload or create a set of sensors for that.

I can patiently wait for the regular season now…LOL…thanks again!

1 Like

@kbrown01 not sure what happened but only the NHL standings are not showing for me. NFL, MLB, and NBA are working fine.

EDIT: Here’s the relevant card code

decluttering_templates:
  nhl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px;'
        tbody tr td:first-child: 'width: 2%;'
        tbody tr td:nth-child(2): 'width: 15%;'
        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 title="Clinch Indicator:&#10; * : Clinched Presidents' Trophy
            (Best Regular-Season Record)&#10; x : Clinched Playoff Berth&#10; -
            : In The Hunt&#10; e : Eliminated from Playoff Contention">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 title="Games Played">GP</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GP').displayValue
        - name: <div title="Wins (worth two points)">W</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'W').displayValue
        - name: <div title="Losses (worth zero points)">L</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'L').displayValue
        - name: <div title="OT/Shootout losses (worth one point)">OTL</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'OTL').displayValue
        - name: <div title="Points">PTS</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'PTS').displayValue
        - name: <div title="Regulation Wins">RW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'RW').displayValue
        - name: <div title="Regulation and Overtime Wins">ROW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'ROW').displayValue
        - name: <div title="Shootout Wins">SOW</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'SOW').displayValue
        - name: <div title="Shootout Losses">SOL</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'SOL').displayValue
        - name: <div title="Home Record">HOME</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'HOME').displayValue
        - name: <div title="Away Record">AWAY</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'AWAY').displayValue
        - name: <div title="Goals For">GF</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GF').displayValue
        - name: <div title="Goals Against">GA</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'GA').displayValue
        - name: <div title="Goal Differential">DIFF</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.type == 'pointsdiff').displayValue
        - name: <div title="Last 10 Games">L10</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'L10').summary
        - name: <div title="Current Streak">STRK</div>
          data: '[[attribute]]'
          modify: x.stats.find(y=>y.abbreviation == 'STRK').displayValue
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: 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: 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: markdown
                                    content: |
                                      <h2>Eastern Conference</h2>
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: 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: Metropolitan
                                      - entity: sensor.nhl_east_metropolitan
                                      - attribute: entries
                                      - 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
                                      - entity: sensor.nhl_west_central
                                      - attribute: entries
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: 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
                            - attributes:
                                label: Conference
                              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: null
                                      - 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: markdown
                                    content: |
                                      <h2>Western Conference</h2>
                                  - type: custom:decluttering-card
                                    template: nhl_settings
                                    variables:
                                      - title: null
                                      - entity: sensor.nhl_west_*
                                      - attribute: entries
                                      - sort: >-
                                          x.stats.find(y=>y.shortDisplayName ==
                                          'PTS').value
                            - attributes:
                                label: Overall
                              card:
                                type: custom:decluttering-card
                                template: nhl_settings
                                variables:
                                  - title: null
                                  - 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: Playoffs
                              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
                                      - 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
                                      - 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: Wildcard
                                      - 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
                                      - 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
                                      - 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: Wildcard
                                      - 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

NHL is broken here as well

I have the same, flex-table card was updated and it breaks NHL because I have the “title” attribute. I removed the “title” attribute from all the headings and it works again.

  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

It has been reported in GITHUB.

Update: Dev says it is fixed and will support the title attribute again, you can replace the JS or wait for the update.

1 Like

Would like to attempt to install this but it seems a little unclear to me. Is it just a matter of downloading the code and placing everything in my config/ folder? I’ve installed all the required cards. Just not sure where to go from there.

Have you looked here? GitHub - kbrown01/SportStandingsScores: Sports Standings and Scores Sensors and Dashboard for Home Assistant

Do you have the sensors created? This is not an integration. It relies on many sensors that are REST calls to the ESPN api

Yes I created them through the teamtracker integration by adding all the teams one by one. It’s just unclear to me where to place everything else from the github page. Sorry mostly use integrations but this looks like something i’ve been looking for inside of HA and wanted to try it out

Ah, there are more than teamtracker. You need the sensors that gets the stats. Let’s start with what you are most interested in … NFL? NBA? NHL? Let me know and I will post the sensors for that sport and then you will be closer

I would want to see NHL, NFL, MLB

OK, so lets start with NFL. Now … I use includes for most all my sensors. How do you do your YAML? Are they just one large configuration.yaml or includes?

If you use includes, then in configuration.yaml you would have:

template: !include template.yaml
sensor: !include sensor.yaml

and in sensor.yaml you need:

##
## NFL Standings
##
- platform: rest
  scan_interval: 36000
  name: NFL Standings
  unique_id: sensor.nfl_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/football/nfl/standings?seasontype=2&type=0&level=3
  value_template: "{{ now() }}"
  json_attributes:
      - children

and in template.yaml you need:

sensor:

###
### NFL Divisions
###
  - name: NFL AFC East
    unique_id: sensor.nfl_afc_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][0]['standings']['entries'] }}"
  - name: NFL AFC North
    unique_id: sensor.nfl_afc_north
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][1]['standings']['entries'] }}"
  - name: NFL AFC South
    unique_id: sensor.nfl_afc_south
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][2]['standings']['entries'] }}"
  - name: NFL AFC West
    unique_id: sensor.nfl_afc_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[0]['children'][3]['standings']['entries'] }}"
  - name: NFL NFC East
    unique_id: sensor.nfl_nfc_east
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][0]['standings']['entries'] }}"
  - name: NFL NFC North
    unique_id: sensor.nfl_nfc_north
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][1]['standings']['entries'] }}"
  - name: NFL NFC South
    unique_id: sensor.nfl_nfc_south
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][2]['standings']['entries'] }}"
  - name: NFL NFC West
    unique_id: sensor.nfl_nfc_west
    state: "{{ now() }}"
    attributes:
        entries: "{{ state_attr('sensor.nfl_standings','children')[1]['children'][3]['standings']['entries'] }}"
  - name: NFL Red Zone
    unique_id: sensor.nfl_red_zone
    state: |
            {% set redzone = namespace(teams=[]) %}
            {%- for team in integration_entities("teamtracker") -%}
            {%- if states(team) == "IN" and state_attr(team, "league") == "NFL" and state_attr(team, "team_homeaway") == "home" and state_attr(team,'possession') is not none -%}
            {% set possession = state_attr(team,'possession') %}
            {% set team_id = state_attr(team,'team_id') %}
            {% set opponent_id = state_attr(team,'opponent_id') %}
            {% set team_abbr = state_attr(team,'team_abbr') %}
            {% set opponent_abbr = state_attr(team,'opponent_abbr') %}
            {% if state_attr(team,'down_distance_text') is not none %}
            {% set down_distance_text = state_attr(team,'down_distance_text') %}
            {% set down_distance_endzone = state_attr(team,'down_distance_text').split(' ')[4] %}
            {% set down_distance_yardline = state_attr(team,'down_distance_text').split(' ')[5] %}
            {% set possession_abbr = opponent_abbr if opponent_id == possession else team_abbr %}
            {% set non_possession_abbr = opponent_abbr if opponent_id != possession else team_abbr %}
            {%- if (possession_abbr != down_distance_endzone) and (down_distance_yardline | int) <= 20 %}
            {% set redzone.teams = redzone.teams + [team] %}
            {% endif %}
            {% endif %}
            {% endif %}
            {% endfor %}
            {{ redzone.teams | count }}
    attributes:
        teams: |
            {% set redzone = namespace(teams=[]) %}
            {%- for team in integration_entities("teamtracker") -%}
            {%- if states(team) == "IN" and state_attr(team, "league") == "NFL" and state_attr(team,'possession') is not none -%}
            {% set possession = state_attr(team,'possession') %}
            {% set team_id = state_attr(team,'team_id') %}
            {% set opponent_id = state_attr(team,'opponent_id') %}
            {% set team_abbr = state_attr(team,'team_abbr') %}
            {% set opponent_abbr = state_attr(team,'opponent_abbr') %}
            {% if state_attr(team,'down_distance_text') is not none %}
            {% set down_distance_text = state_attr(team,'down_distance_text') %}
            {% set down_distance_endzone = state_attr(team,'down_distance_text').split(' ')[4] %}
            {% set down_distance_yardline = state_attr(team,'down_distance_text').split(' ')[5] %}
            {% set possession_abbr = opponent_abbr if opponent_id == possession else team_abbr %}
            {% set non_possession_abbr = opponent_abbr if opponent_id != possession else team_abbr %}
            {%- if (possession_abbr != down_distance_endzone) and (down_distance_yardline | int) <= 20 %}
            {% set redzone.teams = redzone.teams + [team] %}
            {% endif %}
            {% endif %}
            {% endif %}
            {% endfor %}
            {{ redzone.teams }}

These will create a REST sensor called sensor.nfl_standings and the template sensors then will break that into the AFC and NFC divisions.

If you don’t have any includes yet, you create those files at the same level as the configuration.yaml (although you can place them elsewhere and organize differently). This is just my way of doing it.

The last template is a specialized one that maintains a sensor with teams in the red zone that is used to colorize the teamtracker cards.

Of course, once you have this setup you can reload the REST and then the Template Entities or just restart HA.

Once you get this, circle back and we’ll set up the flex-table cards for standings