Sports Standings and Scores

The error you are getting with no images I can explain and am working on changing the JS.
It is because there is only 1 logo in your teams. Home assistant does some funky JSON to YAML conversion even though it is a array, it maps it incorrectly.

Now, I am really confused.

Can you show your YAML for the sensor that gets the data please?

This is my sensor:

- platform: rest
  scan_interval: 36000
  name: Belgium Pro League Ranking
  unique_id: Belgium Pro League Ranking
  resource: https://site.web.api.espn.com/apis/v2/sports/soccer/bel.1/standings
  value_template: "{{ now() }}"
  json_attributes:
    - children

this is my template:

    - name: soccer_belgium_pro_league
      state: "standing"
      attributes:
        standings: >-
          {{ state_attr('sensor.belgium_pro_league_ranking','children')[0].standings.entries }}

And this is my card:

type: custom:tabbed-card
tabs:
  - card:
      type: custom:flex-table-card
      title: Jupiler Pro League
      css:
        table+: 'padding: 0px; width: 100%;'
      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;
              }
      sort_by: entries-
      entities:
        include: sensor.soccer_belgium_pro_league
      columns:
        - name: P.
          data: standings
          modify: x.stats[10].displayValue
        - name: Team
          data: standings
          modify: x.team.displayName
        - name: G
          data: standings
          modify: |
            x.stats.find(y=>y.abbreviation == 'F').displayValue
        - name: DIFF
          data: standings
          modify: x.stats[2].displayValue
        - name: Pts.
          data: standings
          modify: x.stats[3].displayValue
    attributes:
      label: Belgique
      icon: mdi:soccer
  - card:
      type: iframe
      title: Week-End
      url: https://sports.lesoir.be/sport/football/division-1a/resultats
      aspect_ratio: 300%
    attributes:
      label: Resultats
      icon: mdi:soccer-field
  - card:
      type: custom:flex-table-card
      title: Bundesliga
      css:
        table+: 'padding: 0px; width: 100%;'
      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;
          }
      sort_by: entries-
      entities:
        include: sensor.soccer_german_bundesliga
      columns:
        - name: P.
          data: standings
          modify: |
            x.stats[10].displayValue
        - name: Team
          data: standings
          modify: >-
            '<div><img src="' + x.team.logos[0].href + '" style="height:
            20px;vertical-align:middle;">&nbsp;' + x.team.displayName + '</div>'
        - name: G
          data: standings
          modify: |
            x.stats[0].displayValue
        - name: DIFF
          data: standings
          modify: |
            x.stats[8].displayValue   
        - name: Pts.
          data: standings
          modify: |
            x.stats[2].displayValue
    attributes:
      label: Allemangne
      icon: mdi:soccer
  - card:
      type: vertical-stack
      cards:
        - type: custom:teamtracker-card
          entity: sensor.nadal
          outline: true
          outline_color: lightgray
          show_timeouts: false
          show_rank: true
        - type: custom:teamtracker-card
          entity: sensor.djokovic
          outline: true
          outline_color: lightgray
          show_timeouts: false
          show_rank: true
        - type: custom:teamtracker-card
          entity: sensor.murray2
          outline: true
          outline_color: lightgray
          show_timeouts: false
          show_rank: true
        - type: custom:teamtracker-card
          entity: sensor.tsitsipas
          outline: true
          outline_color: lightgray
          show_timeouts: false
          show_rank: true
    attributes:
      label: Tennis
      icon: mdi:tennis

Thanks. I thought it was due to using the rest sensor instead of the templated sensors from the rest sensor.

I was just trying to prove that out. I think I failed :slight_smile:

Okay. You did template it. I thought maybe not. And, I see you did remove the extra children from the examples.

I see kbrown01 is working on it.

I would always use templated sensors. I have everything done except the logos.

Sensor (should be in sensor.yaml if included or start with sensor: ):

##
## Belgium Football
## 
- platform: rest
  scan_interval: 36000
  name: Belgian Pro League Standings
  unique_id: sensor.belgian_pro_league_standings
  resource: https://site.web.api.espn.com/apis/v2/sports/soccer/bel.1/standings
  value_template: "{{ now() }}"
  json_attributes:

Template (should be in template.yaml if included or start with template: ):

###
### Belgian Pro League
###
  - name: Belgian Pro League
    unique_id: sensor.belgian_pro_league
    state: "{{ now() }}"
    attributes:
      entries: "{{ state_attr('sensor.belgian_pro_league_standings','children')[0]['standings']['entries'] }}"

Sample Dashboard (obviously requires decluttering templates and flex-table):

decluttering_templates:
  bpl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 1600px;'
        tbody tr td:first-child: 'width: 5%;'
        tbody tr td:nth-child(2): 'width: 40%;'
        tbody tr td:nth-child(n+3): 'width: 5%;'
        tbody tr:hover: 'background-color: green!important; color:white!important;'
        tbody tr td:nth-child(5): '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]]'
      sort_by: entries
      columns:
        - name: Rank
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'R').displayValue
        - name: Team
          data: entries
          modify: x.team.displayName
        - name: G
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'F').displayValue
        - name: DIFF
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'GD').displayValue
        - name: Pts
          data: entries
          modify: x.stats.find(y=>y.shortDisplayName == 'P').displayValue
views:
  - title: Belgian Pro League Standings
    icon: mdi:soccer
    type: panel
    badges: []
    cards:
      - type: custom:decluttering-card
        template: bpl_settings
        variables:
          - title: Belgian Pro League
          - entity: sensor.belgian_pro_league

I will work on the image for you.

Looking good. I am sure schumi will be glad to get it working.

Thank you for all of your contributions!

1 Like

I will test this tomorrow, because I have to leave urgently.
I’ll let you know the outcome tomorrow.

Thank you very much for your help and I hope for your solution.

And I have now found the source for your error.
As the logic is written it assumes that at least one logo exists.

Here I just output an object of the logos and voila:

The team RWDM has no logo so the “modify” needs to change with if logic, if no logos, then show nothing … else show the logo.

And the final result is:

The modify for that element is:

        - name: Team
          data: entries
          modify: |-
            if (typeof x.team.logos !== 'undefined')
              '<div><img src="' + x.team.logos[0].href + '" style="height:20px;vertical-align:middle;">&nbsp;' + x.team.displayName + '</div>'
            else
              '<div>' + x.team.displayName + '</div>'

What this does. If a team has logos it will use the first logo, if a team does not have a logo it will not show the logo (just the team name) and not yield an error that blocks the whole table. Feel free to adjust if you know HTML. You could use the fixed width of the image and put in a span of that width to align team names if you wish.

NOTE:

I will leave this in my Devleopment environment for a few weeks and then delete it. If you have questions/issues feel free to ask. (What kind of team has no logo??? If it does, don’t call me … call ESPN … :slight_smile: )

How about:

            else
              '<div>img src="//:0" style="height:20px;vertical-align:middle;">&nbsp;' + x.team.displayName + '</div>'

Not tested. Just googling.

Thoughts?

Possibly when you add the “<” before img. I tested.

It shows the “broken image” logo which is not square.

image

Because the ESPN logos are squares, this works (no logo, but correct spacing):

'<div><span style="display: inline-block;width: 20px;"></span>&nbsp;' + x.team.displayName + '</div>'

image

I love the correct spacing!!! Just saying.

And someone should flush that out if they like, The ESPN official view is this which contains many more columns:

GP (Games Played)
W (Wins)
D (Draws)
L (Losses)
F (Goals For)
A (Goals against)
GD (Goal Differential)
P (Points)

All those are easy to implement

Agree. Just throwing it out there for the masses.

Really great job. Thanks for your time on fixing this!

Here ya go, matches ESPN:

decluttering_templates:
  bpl_settings:
    card:
      type: custom:flex-table-card
      title: '[[title]]'
      css:
        table+: 'padding: 0px; width: 1600px;'
        tbody tr td:first-child: 'width: 5%;'
        tbody tr td:nth-child(2): 'width: 30%;'
        tbody tr td:nth-child(n+3): 'width: 5%;'
        tbody tr:hover: 'background-color: green!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;
             }
      entities:
        include: '[[entity]]'
      sort_by: entries
      columns:
        - name: Rank
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'R').displayValue
        - name: Team
          data: entries
          modify: |-
            if (typeof x.team.logos !== 'undefined')
              '<div><img src="' + x.team.logos[0].href + '" style="height:20px;vertical-align:middle;">&nbsp;' + x.team.displayName + '</div>'
            else
              '<div><span style="display: inline-block;width: 20px;"></span>&nbsp;' + x.team.displayName + '</div>'
        - name: GP
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'GP').displayValue
        - name: W
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'W').displayValue
        - name: D
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'D').displayValue
        - name: L
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'L').displayValue
        - name: G
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'F').displayValue
        - name: A
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'A').displayValue
        - name: GD
          data: entries
          modify: x.stats.find(y=>y.abbreviation == 'GD').displayValue
        - name: P
          data: entries
          modify: x.stats.find(y=>y.shortDisplayName == 'P').displayValue
views:
  - title: Belgian Pro League Standings
    icon: mdi:soccer
    type: panel
    badges: []
    cards:
      - type: custom:decluttering-card
        template: bpl_settings
        variables:
          - title: Belgian Pro League
          - entity: sensor.belgian_pro_league

1 Like

In case anyone wants to know, heres how I look at the data (using oXygen Editor which is my favorite tool for XML, JSON, YAML):

Took me while to figure out “RWDM” has no logos

You can turn on JSON viewer in Microsoft Edge.
View formatted JSON - Microsoft Edge Development | Microsoft Learn

This is what I use.

Sure. I have the luxury of owning a software company and have oXygen Editor installed. Much the same BUT I can test search and path expressions and doing much more than just seeing it. And seamless convert XML-JSON-YAML to eachother and see what is going on.

When I edit YAML dashboards, I copy the YAML to it and collapse/expand/easily move things. I have it on my laptop and the .homeassistant directory is mounted so I can edit and test live.

Just a total time saver.

Absolutely.

I have been a developer and analyzing data for 35 years. I can often catch that stuff.

But, cool tools are awesome :wink: