Sports Standings and Scores

@jeffcrum and others, I have posted on flex-table-card GITHUB an enhancement request that IMHO would be killer. Please take a look at:

Read through to the end which has the current solution that works flawlessly in my setup. This enhancement would greatly enhance the use. It allows to import functions from a separate JS file that you can write to do very complex things. It is also especially useful in code repetition reduction so that changes can be made once to change many uses of the same pattern of JS snippets.

Please take a look, test if you like. Questions/comments always welcome.

I will never go back so if it is not put into the core product, I will just reimplement on each update to it. As an example for the Strength of Schedule post I did above. It reduces tons of repetitive JS to this:

      columns:
        - name: SOS
          data: '[[attribute]]'
          modify: |-
            if (x[8] > 3 ){
                '<div style="display:none;">'+ x[8] + '</div>' + '<div style="background-color:lightgreen;text-align:center">' + x[8] + '</div>'; }
            else if (x[8] < 3) {
                '<div style="display:none;">'+ x[8] + '</div>' + '<div style="background-color:lightcoral;text-align:center"">' + x[8] + '</div>'; }
            else {
                '<div style="display:none;">'+ x[8] + '</div>' + '<div style=";text-align:center">' + x[8] +'</div>'}
        - name: Team
          data: '[[attribute]]'
          modify: |
            plugin.sosteam(x)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,1)
        - name: Monday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,1)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,2)
        - name: Tuesday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,2)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,3)
        - name: Wednesday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,3)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,4)
        - name: Thursday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,4)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,5)
        - name: Friday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,5)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,6)
        - name: Saturday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,6)
        - name: ' '
          data: '[[attribute]]'
          modify: |
            plugin.sosind(x,7)
        - name: Sunday
          data: '[[attribute]]'
          modify: |
            plugin.sosopponent(x,7)
1 Like

Thanks. I think it is a great request. I have commented there supporting it!

1 Like

Thank you!

What I should really test is that if the import file does not exist, then does the JS fail?
If not, then the only change would be the ne command and the expected name of the file. I suppose that is not a hard test for me … a few hard refreshes should tell me.

Or some JS code magic.

1 Like

haha. I even came up with an issue that you already solved.

I didn’t read it all the way through and had to edit my response there.

While it isn;t a big code saver, this does provide value should we ever want logic in any of the columns for formatting or across the board changes for all sports:

        - name: <div>GP</div>
          data: '[[attribute]]'
          modify: plugin.sportstat(x,'GP','displayValue')

and

export function sportstat(x,abbr,field){
    return x.stats.find(y=>y.abbreviation == abbr)[field];
}

Note I pass in the name of the fieldname of interest because for some its ‘displayValue’, for some ‘summary’ and for some ‘value’

1 Like

For those that follow, I changed the Strength of Schedule and also the Starting Goalie Sensors because of the latest change in multiscrape supporting scraping JSON into attributes. THese are now created this way (so you can eliminate getting the buildid for starting goalies):

  - name: SOS scraper
    resource: https://www.dailyfaceoff.com/nhl-weekly-schedule
    scan_interval: 3600
    sensor:
      - unique_id: hockey_strength_of_schedule
        name: Hockey Strength of Schedule
        select: '#__NEXT_DATA__'
        value_template: '{{ now() }}'
        attributes:
          - name: sos
            select: '#__NEXT_DATA__'
            value_template: >
                {{ (value | from_json)['props']['pageProps'] }}
  - name: Goalie scraper
    resource: https://www.dailyfaceoff.com/starting-goalies
    scan_interval: 3600
    sensor:
      - unique_id: sensor.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'] }}

Using multiscrape and these in an included multiscrape YAML, you have the two sensors needed to render the tabs.

and

Hey,
I know you are throwing upgrade pieces here. But, are you changing your Github with all of these so someone can jump there and grab everything from scratch?

Just checking.

Thanks for all that you do!

@jeffcrum you are right on. I need to do exactly that …

BUT …

My implementation is already fill of using my “plugin” functionality that I hand-did in flex-table-card. It would be impossible to just upload without that functionaliy being implemented in flex-table-card.

I appreciate your promotion there, but so far I see crickets from the code owner. So I cannot just post it up for everyone because it requires a person to “hack” the source JS.

As I stated:

I will never go back so if it is not put into the core product, I will just reimplement on each update to it.

1 Like

firstly I’d like to say thanks for creating this. It’s pretty great!

the only issue I’m running into is that I can’t see any teams listed under pre, live, post. All the team sensors have been added and I can see them in their respective standings tabs, but I can’t see them in pre live or postgame. Any pointers?

Those are all from teamtracker, do you have all of that integration installed? Like you would have the teamtracker integration installed and have like this in an included sensor.yaml:

##
##  NFL Teams
##
- platform: teamtracker
  league_id: NFL
  team_id: DET
  name: Detroit Lions
- platform: teamtracker
  league_id: NFL
  team_id: GB
  name: Green Bay
- platform: teamtracker
  league_id: NFL
  team_id: CHI
  name: Chicago Bears
- platform: teamtracker
  league_id: NFL
  team_id: MIN
  name: Minnesota Vikings
- platform: teamtracker
  league_id: NFL
  team_id: BUF
  name: Buffalo Bills
- platform: teamtracker
  league_id: NFL
  team_id: MIA
  name: Miami Dolphins
- platform: teamtracker
  league_id: NFL
  team_id: NE
  name: New England Patriots
- platform: teamtracker
  league_id: NFL
  team_id: NYJ
  name: New York Jets
- platform: teamtracker
  league_id: NFL
  team_id: DAL
  name: Dallas Cowboys
- platform: teamtracker
  league_id: NFL
  team_id: NYG
  name: New York Giants
- platform: teamtracker
  league_id: NFL
  team_id: PHI
  name: Philadelphia Eagles
- platform: teamtracker
  league_id: NFL
  team_id: WSH
  name: Washington Commanders
- platform: teamtracker
  league_id: NFL
  team_id: BAL
  name: Baltimore Ravens
- platform: teamtracker
  league_id: NFL
  team_id: CIN
  name: Cincinnati Bengals
- platform: teamtracker
  league_id: NFL
  team_id: CLE
  name: Cleveland Browns
- platform: teamtracker
  league_id: NFL
  team_id: PIT
  name: Pittsburg Steelers
- platform: teamtracker
  league_id: NFL
  team_id: HOU
  name: Houston Texans
- platform: teamtracker
  league_id: NFL
  team_id: IND
  name: Indianapolis Colts
- platform: teamtracker
  league_id: NFL
  team_id: JAX
  name: Jacksonville Jaguars
- platform: teamtracker
  league_id: NFL
  team_id: TEN
  name: Tennessee Titans
- platform: teamtracker
  league_id: NFL
  team_id: ATL
  name: Atlanta Falcons
- platform: teamtracker
  league_id: NFL
  team_id: CAR
  name: Carolina Panthers
- platform: teamtracker
  league_id: NFL
  team_id: "NO"
  name: New Orleans Saints
- platform: teamtracker
  league_id: NFL
  team_id: TB
  name: Tampa Bay Buccaneers
- platform: teamtracker
  league_id: NFL
  team_id: DEN
  name: Denver Broncos
- platform: teamtracker
  league_id: NFL
  team_id: KC
  name: Kansas City Chiefs
- platform: teamtracker
  league_id: NFL
  team_id: LV
  name: Las Vegas Raiders
- platform: teamtracker
  league_id: NFL
  team_id: LAC
  name: Los Angeles Chargers
- platform: teamtracker
  league_id: NFL
  team_id: ARI
  name: Arizona Cardinals
- platform: teamtracker
  league_id: NFL
  team_id: LAR
  name: Los Angeles Rams
- platform: teamtracker
  league_id: NFL
  team_id: SF
  name: "San Francisco 49ers"
- platform: teamtracker
  league_id: NFL
  team_id: SEA
  name: "Seattle Seahawks"

I only piggy back PRE, POST, IN from teamtracker into those tabs with really minimal changes. All the standings are taken directly from ESPN with my code but not specific game information.

Teamtracker = Games
My stuff = Standings plus some enhancements (more to come) like NHL Strength of Schedule and NHL Starting Goalies.

If you do and still get errors then possibly you do not have the red zone installed like others and I can help you either have that or remove it (it is only for NFL anyway)

I modified the SOS multiscrape today as the system now requires an input date (it used to just default to the week’s Monday). This will append the Monday of the current week to the query:

  - name: SOS scraper
    resource_template: "https://www.dailyfaceoff.com/nhl-weekly-schedule/{{ (now().timestamp()+(0-now().weekday())*86400) | int | timestamp_custom('%Y-%m-%d') }}"
    scan_interval: 43200
    sensor:
      - unique_id: hockey_strength_of_schedule
        name: Hockey Strength of Schedule
        select: '#__NEXT_DATA__'
        value_template: '{{ now() }}'
        attributes:
          - name: sos
            select: '#__NEXT_DATA__'
            value_template: >
                {{ (value | from_json)['props']['pageProps'] }}

I am still a little new tp Home Assistant. Does anyone know how to turn off the rest sensors in the offseason?

For example, how would I turn off the nfl/football after the Super Bowl and turn it back on right before the pre-season? I would like to avoid the rest calls to ESPN in the off-season.

Do you pay for data on your internet? If so, I can see the need. If not, no need.

But, you need to remove the sensor in the yaml to ‘disable’ it as far as I know.

@jeffcrum is exactly right. But if you insist, you can set the scan interval to some huge number like 360000 or more. Then create an automation that executes updating the entity according to the schedule you want.

Of course it will update on every restart of Home Assistant, but this would give you total control to update only when you want it.

So the logic would be …

Set scan_interval to once every 6 months
Then an automation that executes (daily or whatever you choose) … check the month is sep, oct, nov, dec … if yes, update the entity.

1 Like

I asked because it seemed like Home Assistant was getting sluggish with my sports API calls on (along with other sensors) on a ESXi VM on a QNAP NAS. I just thought the REST calls could be a possible reason. I am enjoying Home Assistant, but still trying to tweak everything to run more efficiently. I wish there was a performance advice category, but there are so many nuances to HA.

What do you recommend for the scan interval settings for the REST calls to ESPN?

It depends on what you are talking about and what you are happy with (meaning do you want to see the standings accurate to the minute, hour, day, week?).

Standings only change weekly in NFL (could be Thur, Fri, Sat, Sun, Mon), but daily in NBA, NHL, MLB.
The customized one for NHL SOS changes on Monday every week during the season. Yet the customized one for Starting Goalies naturally changes every day.

The rest of the tabs are PRE, POST and IN game stats that all come from teamtracker which is not what I provide.

All I know is that a quick call to these services even hourly or daily is of no matter. You do more than that when you open the browser and go to the ESPN page or watch live stats on some fantasy league.

FOr instance … I have every team in NHL, MLB, NFL, NBA in both my stats and teamtracker (which in game is like every few seconds update). It does nothing to my system in terms of performance.

Now, I will also say this … I do not record any historical stats for this (and frankly most every) sensor. That IMHO is the killer. My recorder is like this which means I only include speedtests and my starlink for historical, nothing else.

recorder:
    include:
        entity_globs:
            - sensor.speedtest_*
            - sensor.starlink_*

You may have different needs but knowing that a light turned on or off 2 weeks ago is not relevant to me. Nor is historical stats of standings in sports. You could start by excluding things, but I felt it better to exclude everything and include only the few I want with 100s of sensors with no need for historical records it is much easier to exclude everything and include the few you want.

Like for instance this is my main stereo, likely on/off several times a day … and I look at the records and I see this:

image

Nada. Perfect. I could care less when it came on and off and store that for weeks on end. But my Starlink I watch:

image

1 Like

Perfect! I planned to exclude my sports trackers, but I like your idea to only include the right items. I am using teamtracker and your code as a baseline, with my own modifications. I rebuilt my HA VM a couple of months ago to incrementally add integrations and check the performance. Just added teamtracker/modified version of your sensors/dashboard for the NFL to track (and test) for the playoffs.

I am running on a QNAP TVS-h674 (i5-12400 - 6 cores, 12 threads) with 32 GB RAM, containers - mqtt, frigate, plex, etc. and the ESXi VM for HA (4 cores/16GB RAM). It should have PLENTY of horsepower, but I sometimes get out of memory due to python on QNAP. It seems like it is something in HA causing the python issue and it recently popped up again, but not sure the cause.

Thanks for the good work, sharing, and answering questions!

That should be plenty of power. I use an older gaming machine my son built with 12GB RAM, i7 Quad … but I use just Core with a virtual environment. I have a few other things on that machine but I like the control I get combined with using like Linux Mint Cinnamon. I have never noted any OOM conditions ever nor performance issues.

And there are no SSD drives even, it does have older drives totally about 5TB storage as I have a lot of other data like a huge music collection on it.

That is what I thought too. I assembled the new NAS to replace the old NAS that could not handle the camera my husband wanted to install. Yes, I have 2 SSDs (! TB each) and 25TB on HDDs (RAID 6) and a Coral card for frigate.

I consulted some people before buying/setting it up as my background is just programming/mgmt (rusty on some programming as spend years in mgmt until ‘retired’). Very familiar with Python (self taught), but networking and the layers with VMs can be challenging for me. I wish I knew how to troubleshoot the various layers of HA to pinpoint it better (besides the logger).

Back to finishing my playoff card before the games start! NFL json playoff data is very different from MLB.

Are you going to implement something for NFL playoffs? That would be great. I did one for Wildcard in NHL, should do the same or a specific card for the playoffs themselves like a bracket. Just have not had time, working on enhancing my Vizio TV/DIrecTV integration now and have to circle back to the Dayton Audio stuff.

I try to do some things on stats when I can, but I am an NHL lover first and foremost which is why there are Strength of Schedule and Starting Goalies and such.

Anything new, please share!

1 Like