Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
To be released
--------------

* Added ``client.broadcasts.get_team_standings`` to get the team leaderboard of a broadcast.

* Deprecate Python 3.9 support - minimum required version is now Python 3.10+. This does not mean the library will not work with Python 3.9, but it will not be tested against it anymore.

Expand All @@ -23,6 +24,7 @@ To be released


Thanks to all the contributors who helped to this release:
- Nick Stillman
- @hsheth2
- @DoraFgr
- @MrElyazid
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Most of the API is available:
client.broadcasts.get_top
client.broadcasts.search
client.broadcasts.get_by_user
client.broadcasts.get_team_standings

client.bulk_pairings.get_upcoming
client.bulk_pairings.create
Expand Down
12 changes: 12 additions & 0 deletions berserk/clients/broadcasts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from ..types.broadcast import (
BroadcastPlayer,
BroadcastTeamStandingsItem,
BroadcastTop,
PaginatedBroadcasts,
BroadcastsByUser,
Expand Down Expand Up @@ -296,3 +297,14 @@ def get_by_user(
path = f"/api/broadcast/by/{username}"
params = {"page": page, "html": html}
return cast(BroadcastsByUser, self._r.get(path, params=params))

def get_team_standings(
self, broadcast_tournament_id: str
) -> List[BroadcastTeamStandingsItem]:
"""Get the team leaderboard of a broadcast.

:param broadcast_tournament_id: ID of the broadcast tournament
:return: list of teams with name, match/board points, matches, and players
"""
path = f"/broadcast/{broadcast_tournament_id}/teams/standings"
return cast(List[BroadcastTeamStandingsItem], self._r.get(path))
2 changes: 2 additions & 0 deletions berserk/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
)
from .broadcast import (
BroadcastPlayer,
BroadcastTeamStandingsItem,
BroadcastTop,
PaginatedBroadcasts,
BroadcastsByUser,
Expand All @@ -37,6 +38,7 @@
"ArenaResult",
"BroadcastPlayer",
"BroadcastsByUser",
"BroadcastTeamStandingsItem",
"BroadcastTop",
"BulkPairing",
"BulkPairingGame",
Expand Down
31 changes: 31 additions & 0 deletions berserk/types/broadcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,34 @@ class BroadcastsByUser(TypedDict):
previousPage: int | None
nextPage: int | None
nbPages: int


# Types for GET /broadcast/{id}/teams/standings (team leaderboard of a broadcast)


class BroadcastTeamStandingsMatch(TypedDict):
roundId: str
opponent: str
points: str
mp: int | float
gp: int | float


class BroadcastTeamStandingsPlayer(TypedDict):
name: str
score: int | float
title: NotRequired[Title]
rating: NotRequired[int]
fideId: NotRequired[int]
team: NotRequired[str]
fed: NotRequired[str]
played: NotRequired[int]


class BroadcastTeamStandingsItem(TypedDict):
name: str
mp: int | float
gp: int | float
matches: List[BroadcastTeamStandingsMatch]
players: List[BroadcastTeamStandingsPlayer]
averageRating: NotRequired[int]

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion tests/clients/test_broadcasts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import pytest

from typing import List

from berserk import Client
from berserk.types import BroadcastTop, PaginatedBroadcasts, BroadcastsByUser
from berserk.types import (
BroadcastTeamStandingsItem,
BroadcastTop,
PaginatedBroadcasts,
BroadcastsByUser,
)
from utils import skip_if_older_3_dot_10, validate


Expand All @@ -23,3 +30,21 @@ def test_search(self):
def test_get_by_user(self):
res = Client().broadcasts.get_by_user(username="lichess", page=1)
validate(BroadcastsByUser, res)

@skip_if_older_3_dot_10
@pytest.mark.vcr
def test_get_team_standings(self):
"""Get team leaderboard for a broadcast.

A broadcast is a Lichess relay of an external chess event (OTB/online);
it has a tour (tournament) and rounds with games. Standings exist when
the tour is a team event (tour.teamTable is true) and teams are assigned
(e.g. via WhiteTeam/BlackTeam in PGN or manual assignment). To find
broadcasts with non-empty standings: get_top() or search(), filter for
tour.teamTable, then call get_team_standings(tour.id) until len > 0.
This test uses a broadcast that has team standings (e.g. German
Bundesliga). Re-record if it later returns [] (delete cassette, make
test_record, or pick another tour.id from get_top with teamTable).
"""
res = Client().broadcasts.get_team_standings("Y9YjcDKG")
validate(List[BroadcastTeamStandingsItem], res)