Skip to content

Commit

Permalink
Updated Tournaments functionality
Browse files Browse the repository at this point in the history
Modified:
Tournaments.create() -> Tournaments.create_arena()
Tournaments.export_games() -> Tournaments.export_arena_games()
Added:
Tournaments.create_swiss()
Tournaments.export_swiss_games()
Tournaments.tournaments_by_user()
Tournaments.arena_by_team()
Tournaments.swiss_by_team()
  • Loading branch information
ZackClements committed Mar 18, 2021
1 parent 1b000a4 commit 86ffcfe
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 15 deletions.
166 changes: 152 additions & 14 deletions berserk/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from .formats import JSON, LIJSON, PGN, NDJSON, TEXT
from . import models


__all__ = [
'Client',
'Account',
Expand All @@ -23,7 +22,6 @@
'Users',
]


# Base URL for the API
API_URL = 'https://lichess.org/'

Expand Down Expand Up @@ -576,7 +574,7 @@ def create_ai(self, level=8, clock_limit=None, clock_increment=None,
:return: success indicator
:rtype: bool
"""
path = f'api/challenge/ai'
path = "api/challenge/ai"
payload = {
'level': level,
'clock.limit': clock_limit,
Expand All @@ -603,7 +601,7 @@ def create_open(self, clock_limit=None, clock_increment=None,
:return: challenge data
:rtype: dict
"""
path = f'api/challenge/open'
path = "api/challenge/open"
payload = {
'clock.limit': clock_limit,
'clock.increment': clock_increment,
Expand Down Expand Up @@ -886,10 +884,12 @@ def get(self):
path = 'api/tournament'
return self._r.get(path, converter=models.Tournaments.convert_values)

def create(self, clock_time, clock_increment, minutes, name=None,
wait_minutes=None, variant=None, berserkable=None, rated=None,
start_date=None, position=None, password=None, conditions=None):
"""Create a new tournament.
def create_arena(self, clock_time, clock_increment, minutes, name=None,
wait_minutes=None, start_date=None, variant=None,
rated=None, position=None, berserkable=None,
streakable=None, hasChat=None, description=None,
password=None, teambBattleByTeam=None, conditions=None):
"""Create a new arena tournament.
.. note::
Expand All @@ -900,17 +900,24 @@ def create(self, clock_time, clock_increment, minutes, name=None,
If ``name`` is left blank then one is automatically created.
:param int clock_time: intial clock time in minutes
:param int clock_time: initial clock time in minutes
:param int clock_increment: clock increment in seconds
:param int minutes: length of the tournament in minutes
:param str name: tournament name
:param int wait_minutes: future start time in minutes
:param str start_date: when to start the tournament
:param str variant: variant to use if other than standard
:param bool rated: whether the game affects player ratings
:param str berserkable: whether players can use berserk
:param str position: custom initial position in FEN
:param str password: password (makes the tournament private)
:param str berserkable: whether players can use berserk
:param bool streakable: whether players get streaks
:param bool hasChat: whether players can
discuss in a chat
:param string description: anything you want to
tell players about the tournament
:param str password: password
:param str teambBattleByTeam: Id of a team you lead
to create a team battle
:param dict conditions: conditions for participation
:return: created tournament info
:rtype: dict
Expand All @@ -927,15 +934,64 @@ def create(self, clock_time, clock_increment, minutes, name=None,
'rated': rated,
'position': position,
'berserkable': berserkable,
'streakable': streakable,
'hasChat': hasChat,
'description': description,
'password': password,
'teambBattleByTeam': teambBattleByTeam,
**{f'conditions.{c}': v for c, v in (conditions or {}).items()},
}
return self._r.post(path, json=payload,
converter=models.Tournament.convert)

def export_games(self, id_, as_pgn=False, moves=None, tags=None,
clocks=None, evals=None, opening=None):
"""Export games from a tournament.
def create_swiss(self, teamId_, clock_limit, clock_increment, nbRounds,
name=None, startsAt=None, roundInterval=None,
variant=None, description=None, rated=None, chatFor=None):
"""Create a new swiss tournament
.. note::
If ``name`` is left blank then one is automatically created.
.. note::
If ``startsAt`` is left blank then the
tournament begins 10 minutes after creation
:param string teamId_: team Id, required for swiss tournaments
:param int clock_limit: initial clock time in seconds
:param int clock_increment: clock increment in seconds
:param int nbRounds: maximum number of rounds to play
:param string name: tournament name
:param int startsAt: when to start tournament, in ms timestamp
:param int roundInterval: interval between rounds in seconds
:param string variant: variant to use if other than standard
:param string description: tournament description
:param bool rated: whether the game affects player ratings
:param int chatFor: who can read and write in the chat
:return: created tournament info
:rtype: dict
"""
path = f'api/swiss/new/{teamId_}'

payload = {
'name': name,
'clock.limit': clock_limit,
'clock.increment': clock_increment,
'nbRounds': nbRounds,
'startsAt': startsAt,
'roundInterval': roundInterval,
'variant': variant,
'description': description,
'rated': rated,
'chatFor': chatFor
}
return self._r.post(path, json=payload,
converter=models.Tournament.convert)

def export_arena_games(self, id_, as_pgn=False, moves=None, tags=None,
clocks=None, evals=None, opening=None):
"""Export games from a arena tournament.
:param str id_: tournament ID
:param bool as_pgn: whether to return PGN instead of JSON
Expand All @@ -961,6 +1017,88 @@ def export_games(self, id_, as_pgn=False, moves=None, tags=None,
return self._r.get(path, params=params, fmt=fmt,
converter=models.Game.convert)

def export_swiss_games(self, id_, as_pgn=False, moves=None, pgnInJson=None,
tags=None, clocks=None, evals=None, opening=None):
"""Export games from a swiss tournament
:param str id_: tournament id
:param bool as_pgn: whether to return pgn instead of JSON
:param bool moves: include moves
:param bool pgnInJson: include the full PGN within the
JSON response, in a pgn field
:param bool tags: include tags
:param bool clocks: include clock comments
:param bool evals: include analysis evaluation
comments in the PGN, when available
:param bool opening: include the opening name
:return: games
:rtype: list
"""
path = f'api/swiss/{id_}/games'
params = {
'moves:': moves,
'pgnInJson': pgnInJson,
'tags': tags,
'clocks': clocks,
'evals': evals,
'opening': opening,
}
fmt = PGN if self._use_pgn(as_pgn) else NDJSON
return self._r.get(path, params=params, fmt=fmt,
converter=models.Game.convert)

def tournaments_by_user(self, username, nb=None, as_pgn=False):
"""Get tournaments created by a user
:param string username: username
:param int nb: max number of tournaments to fetch
:param bool as_pgn: whether to return pgn instead of Json
:return: tournaments
:rtype: list
"""

path = f'api/user/{username}/tournament/created'
params = {
'nb': nb,
}
fmt = PGN if self._use_pgn(as_pgn) else NDJSON
return self._r.get(path, params=params, fmt=fmt,
converter=models.Game.convert)

def arenas_by_team(self, teamId, maxT=None, as_pgn=False):
"""Get arenas created for a team
:param string teamId: Id of the team
:param int maxT: how many tournaments to download
:param bool as_pgn: whether to return pgn instead of Json
:return: tournaments
:rtype: list
"""
path = f'api/team/{teamId}/arena'
params = {
'max': maxT,
}
fmt = PGN if self._use_pgn(as_pgn) else NDJSON
return self._r.get(path, params=params, fmt=fmt,
converter=models.Game.convert)

def swiss_by_team(self, teamId, maxT=None, as_pgn=False):
"""Get swiss tournaments created for a team
:param string teamId: Id of the team
:param int maxT: how many tournaments to download
:param bool as_pgn: whether to return pgn instead of Json
:return: tournaments
:rtype: list
"""
path = f'api/team/{teamId}/swiss'
params = {
'max': maxT,
}
fmt = PGN if self._use_pgn(as_pgn) else NDJSON
return self._r.get(path, params=params, fmt=fmt,
converter=models.Game.convert)

def stream_results(self, id_, limit=None):
"""Stream the results of a tournament.
Expand Down
27 changes: 26 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ tournament is easy:

.. code-block:: python
>>> client.tournaments.create(clock_time=10, clock_increment=3, minutes=180)
>>> client.tournaments.create_arena(clock_time=10, clock_increment=3, minutes=180)
{'berserkable': True,
'clock': {'increment': 3, 'limit': 600},
'createdBy': 'rhgrant10',
Expand Down Expand Up @@ -428,6 +428,31 @@ provided enum value in ``berserk.enums.Position``:
>>> client.tournaments.create(clock_time=10, clock_increment=3, minutes=180,
position=berserk.enums.Position.KINGS_PAWN)
You can also create Swiss tournaments easily, specifying the team id, clock time,
clock increment, and number of rounds.

.. code-block:: python
>>> client.tournaments.create_swiss(teamid_="coders", clock_limit=10,
clock_increment=0, nbRounds=5)
{'rated': true,
'clock': {'increment': 0, 'limit': 600},
'createdBy': "zccze",
'greatPlayer': {'name': "Wang',
'url':'https://wikipedia.org/wiki/Wang_Hao_(chess_player)' },
'id': '3uwyXjiC'
'name': 'Wang',
'nbOngoing': 0,
'nbPlayers': 0,
'nbRounds': 5,
'nextRound': { 'at': '2021-05-18T12:23:18.233-06:00', 'in': 600},
'quote': {'author': 'Bent Larsen',
'text': 'I often play a move I know how to refute.'},
'round': 0,
'startsAt': '2021-05-18T12:23:18.233-06:00',
'status': 'created',
'variant': 'standard'
}
Additionally you can see tournaments that have recently finished, are in
progress, and are about to start:
Expand Down

0 comments on commit 86ffcfe

Please sign in to comment.