rstt.scheduler package

Subpackages

Module contents

Package for automated matches generation procedure

RSTT consider scheduler in competition as a large notion covering both sport tournaments and live-matchmaking.

class rstt.scheduler.Competition(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, cashprize: dict[int, float] | None = None)[source]

Bases: object

NOTE: In the future the competition class could evolve.
  • inherit from a Scheduler class

  • composition over inheritance:
    • PlayerManager -> dealing with seedings or ratings

    • GameManager -> dealing with Match types and matching

    • EventManager -> dealing with the event id, achivements of players, final standing

Tournament General Template & Workflow.

Abstract class handling specificity related to Competition.

In rstt Competition are ‘Scheduler bounded in time and space’. Unlike live matchmaking, it has a start, an end and a finite well defined amount of participants.

Competition generate automatically matches in a coehrent, meaningfull fashion.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding purposes.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

Attention

0.6.5 [attribute changes] the ‘participants’ attribute has been encapsulated, use the corresponding get method to access it. Reminder that to ‘set’ participants you can use the registration method.

edit(games: List[Duel])[source]

Handles competition state after each round

Do not use if you simply want to run the competition.

Parameters

gamesList[Duel]

The game splayed during the round.

Returns

bool

If True the round was the last one, no more game will be played and the competition will end.

games(by_rounds=False) List[Duel] | List[List[Duel]][source]

Getter for all matches played during the event.

In many Competition, matches are organized in ‘rounds’ and follow a chronological order. This method support two query with a return values respecting or not the round structure Parameters ———- by_rounds : bool, optional

Wether to return the matches grouped by rounds or not, by default False and a flat list is returned.

Returns

Union[List[Duel], List[List[Duel]]]

All matches played during the event.

abstract generate_games() List[Duel][source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

live() bool[source]

Indicate if a competition is being played

It means that games are being played and generated. Almost no operations are possible when live.

Returns

bool

True if competition is curretnly generating and playing matches.

name() str[source]

Getter for the name of the Competition

Returns

str

the name of the competition (used as identifier in the package)

over() bool[source]

Indicate that the competition has ended

When over, it means all games were played and player’s have collected their achievements.

Returns

bool

True if the competition is over, no more game will be played, the standing is final

participants() list[SPlayer][source]

Getter for SPlayer taking part in the Competition

Returns

list[SPlayer]

competitors playing game(s).

play()[source]

Plays the competition

Do not use if you simply want to run the competition.

Raises

RuntimeError

An error is raised if the competition is not in a suited state, if it has not started yet.

play_games(games: List[Duel]) List[Duel][source]

Assign scores to generated matches

Do not use if you simply want to run the competition.

Parameters

gamesList[Duel]

Unplayed/unsolved matches to assign a score to.

Returns

List[Duel]

the games with a scored.

registration(players: SPlayer | List[SPlayer] | Set[SPlayer])[source]

Add player to compete

The seedings do not define who participate in the event. You need to call registration to specify who plays. The method can be called anytime you want before the start of competition, but should not be called afterwards. A player can only participate once but multiple registration will have no effect for the said player. Unranked player will receive a seed corresponding to the default value - NOT ALWAYS lower seed. Unseeded player WILL NOT be added to the ranking.

Parameters

playersUnion[SPlayer, List[SPlayer], Set[SPlayer]]

Playrs taking part in the event’s matches.

run()[source]

Automated Competition execution

This is the magic methods that does all the works.

A Diagram will be added to the doc to illustrate the process better than words.

Raises

RuntimeError

An error is raised if the competition is not in a suited state, if it has already started.

standing() Dict[SPlayer, int][source]

Getter for the standing

The standing of a competition indicate where player have finished.

Returns

Dict[SPlayer, int]

Final standing of the event

start()[source]

Starts the competition

Do not use if you simply want to run the competition

started() bool[source]

Indicate if the competition started

Once a competition has started, calls on registration() and start() methods will have no effects.

Returns

bool

wheter the competition has started or not

top(place: int | None = None) Dict[int, List[SPlayer]] | List[SPlayer][source]

Getter for players by their final placement

Sugar method to access a player by his placement rather than dealing with a the standing.

Parameters

placeOptional[int], optional

The place that you want to know which player(s) ended at, by default None. If None, the return value is a Dictionary where keys are int and values list of players that finished at the ‘key place’.

Returns

Union[Dict[int, List[SPlayer]], List[SPlayer]]

Either a list of player placed at the ‘place’ position in the standing, or a full dictionary with all places as key.

trophies()[source]

Closure ceremony

Establish the final standing and reward players with their respective rstt.stypes.Achievement.

Do not use if you simply want to run the competition.

class rstt.scheduler.DoubleEliminationBracket(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, lower_policy: ~typing.Callable[[list[any]], list[any]] = <function DoubleEliminationBracket.<lambda>>, injector_policy: ~typing.Callable[[list[any], list[any]], list[any]] = <function riffle_shuffle>, cashprize: dict[int, float] = {})[source]

Bases: Competition

Double Elimination Bracket

Variation of the Single Elimination Bracket where participants have a 2nd chance after losing before elimination.

Tournament General Template & Workflow.

Abstract class handling specificity related to Competition.

In rstt Competition are ‘Scheduler bounded in time and space’. Unlike live matchmaking, it has a start, an end and a finite well defined amount of participants.

Competition generate automatically matches in a coehrent, meaningfull fashion.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding purposes.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

Attention

0.6.5 [attribute changes] the ‘participants’ attribute has been encapsulated, use the corresponding get method to access it. Reminder that to ‘set’ participants you can use the registration method.

games(by_rounds=False, upper=False, lower=False)[source]

Getter for all matches played during the event.

In many Competition, matches are organized in ‘rounds’ and follow a chronological order. This method support two query with a return values respecting or not the round structure Parameters ———- by_rounds : bool, optional

Wether to return the matches grouped by rounds or not, by default False and a flat list is returned.

Returns

Union[List[Duel], List[List[Duel]]]

All matches played during the event.

generate_games()[source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

class rstt.scheduler.RandomRound(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, cashprize: dict[int, float] = {}, rounds: int = 1, amount: int = 1)[source]

Bases: RoundRobin

Random tournament

Class to generate a bunch of arbitrary matches.

This is not a real ‘competition’ as it is not intended to determine a winner. But the class works as a competition and thus produces a final standing the same way a RoundRobin does - by summing matches scores. It is however ‘unfair’ in the sense that there is no guarantee that participants play the same amount of games. It is even possible some registered participant do not play a single match.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

roundsint, optional

Number of rounds to be played, by default 1. Participants play at most one match per rounds.

amount: int, optional

Number of game to produce by rounds, by default 1.

Note

Calling with amount=1 and rounds=n makes it a pure random scheduler that generates n matches.

class rstt.scheduler.RoundRobin(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, cashprize: ~typing.Dict[int, float] = {})[source]

Bases: Competition

Round-Robin Tournament

Implements the famous tournament system. The matching technique used to generate matches is the ‘circle’ algorithm illustrated here.

A simpl specification of the tournament reads like this:
  • a total of n x (n-1) matche is played in n-1 rounds.

  • each rounds every participants play exactly one opponent.

  • every players faces each others exactly once

  • standing is based on the player’s matches scores.

generate_games()[source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

next_round()[source]
class rstt.scheduler.SingleEliminationBracket(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, cashprize: dict[int, float] = {})[source]

Bases: Competition

Single Elimination Bracket or tournament

One of the most famous and used competition model, specialy in internationl events, Participants are placed in a binary tree where the winner of a confrontation advance to the next stage and the loser is eliminated.

More detail on the single-elimination-bracket wikipedia page.

Note

Currently the first round matching is the standard policy. for example with 8 participants: Seed1 versus Seed8; Seed4 versus Seed5; Seed2 versus Seed7; Seed3 versus Seed6.

Future version will support custom first round matching. In the mean time, to fine tune the first round, it is possible to reorder a ranking with a permutation using the rstt.ranking.ranking.Ranking.rerank() method. This needs to be called on a ranking before passing it to a competition.

Tournament General Template & Workflow.

Abstract class handling specificity related to Competition.

In rstt Competition are ‘Scheduler bounded in time and space’. Unlike live matchmaking, it has a start, an end and a finite well defined amount of participants.

Competition generate automatically matches in a coehrent, meaningfull fashion.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding purposes.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

Attention

0.6.5 [attribute changes] the ‘participants’ attribute has been encapsulated, use the corresponding get method to access it. Reminder that to ‘set’ participants you can use the registration method.

generate_games()[source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

class rstt.scheduler.Snake(*args, **kwars)[source]

Bases: Competition

The Snake Tournament

This format is not a standard one. It is a model I detail and justify the interest in my master thesis and should be the subject of a paper in an hopefully near future.

It does have some ressamblances with the Ladder tournament. I am aware of two practical instances of uses:

Quick Overview:
  • For n participants it produces n-1 matches.

  • Every participants plays at least one match.

  • The final standing is an untied ranking.

  • Matches are all ‘a priori balanced’.

Tournament General Template & Workflow.

Abstract class handling specificity related to Competition.

In rstt Competition are ‘Scheduler bounded in time and space’. Unlike live matchmaking, it has a start, an end and a finite well defined amount of participants.

Competition generate automatically matches in a coehrent, meaningfull fashion.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding purposes.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

Attention

0.6.5 [attribute changes] the ‘participants’ attribute has been encapsulated, use the corresponding get method to access it. Reminder that to ‘set’ participants you can use the registration method.

generate_games() List[Duel][source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

class rstt.scheduler.SwissBracket(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, matchings: ~typing.Dict[~typing.Tuple[int, int], ~rstt.stypes.Shuffler] | None = None, seeders: ~typing.Dict[~typing.Tuple[int, int], ~rstt.stypes.Seeder] | None = None, generators: ~typing.Dict[~typing.Tuple[int, int], ~rstt.stypes.Generator] | None = None, evaluators: ~typing.Dict[~typing.Tuple[int, int], ~rstt.stypes.Evaluator] | None = None, def_matching: ~rstt.stypes.Shuffler = <class 'rstt.scheduler.tournament.swissbracket.DummyParam'>, def_seeder: ~rstt.stypes.Seeder = <class 'rstt.scheduler.tournament.swissbracket.DummyParam'>, def_generator: ~rstt.stypes.Generator = <class 'rstt.scheduler.tournament.swissbracket.DummyParam'>, def_evaluator: ~rstt.stypes.Evaluator = <class 'rstt.scheduler.tournament.swissbracket.DummyParam'>, cashprize: ~typing.Dict[int, float] | None = None)[source]

Bases: Competition

The Swiss Bracket

The format is mention in the esports variation of the Swiss Round wikipedia page and was originaly introduce for Counter-Strike event in 2016. Hower both format differ drastically in many regards, one being their usage and output.

  • In Swiss Round there is a single undefeated participant, thus is great to crown a winner among many participants.

  • In Swiss Bracket, 16 teams are split into 8 qualified and 8 eliminated participants.

The name choice come from the Valve rule book for Counter-Strike major competition, that specify a matching policy.

Parameters

namestr

A unique name to identify the Event.

seedingRanking

A ranking used for seeding purposes.

solverSolver, optional

A Solver to generate match outcomes, by default BetterWin()

matchingsOptional[Dict[Tuple[int, int], Shuffler]], optional

A collection of matching strategy for rounds, by default None Keys are tuple (number of win, number of lose) to indicate when the strategy is used.

seedersOptional[Dict[Tuple[int, int], Seeder]], optional

A scollection of eeding strategy for rounds, by default None Keys are tuple (number of win, number of lose) to indicate when the strategy is used.

generatorsOptional[Dict[Tuple[int, int], Generator]], optional

A collection of generator for rounds, by default None Keys are tuple (number of win, number of lose) to indicate when the generator is used.

evaluatorsOptional[Dict[Tuple[int, int], Evaluator]], optional

A collection of evaluators for rounds, by default None Keys are tuple (number of win, number of lose) to indicate when the strategy is used.

def_matchingShuffler, optional

A default matching strategy for rounds where the matchings param does not provide one, by default DummyParam

def_seederSeeder, optional

A default seeding strategy for rounds where the seeders param does not provide one, by default DummyParam

def_generatorGenerator, optional

A default generator for rounds where the generator param does not provide one, by default DummyParam

def_evaluatorEvaluator, optional

A default evaluator for rounds where the evaluators param does not provide one, by default DummyParam

cashprizeOptional[Dict[int, float]], optional

A ‘prizepool’ rewarding player with ‘money’ for their success (placement in the final standing) during the Event, by default None

Note

The design of the class alows extreme customization on the matching at any point of the competition. If you do not provide a matching, seeders, genrators, evaluators and their associated default, the class uses a DummyParam for all.

Refer to the rstt.stypes documentation for the parameters type and impact on the tournament games.

draws(group: List[SPlayer]) List[List[Duel]][source]
generate_games()[source]

Function called every ‘round’ to generate games. Should return games WITHOUT scores assigned

results()[source]
round_scores() List[Tuple[int, int]][source]
score(player: SPlayer) Tuple[int, int][source]
class rstt.scheduler.SwissRound(name: str, seeding: ~rstt.ranking.ranking.Ranking, solver: ~rstt.stypes.Solver = <rstt.solver.solvers.BetterWin object>, cashprize: ~typing.Dict[int, float] = {})[source]

Bases: RoundRobin

Swiss Round

Also known as Swiss System.

It is a variation of the Round-Robin system, that fixes some issues:
  • ~ n X log2(n) matches played, which for large n (participants) is significantly faster than round-robin.

  • each rounds every participants play exactly one opponent with the same score. Which creates more interesting and balance game overall.

  • every players should face at most once other players (not always possible).

Warning

  • Undefined behaviour when the number of registered player is not a power of 2.

  • The current matching strategy (greedy) has some issues and may lead to errors, this has been observed for number of participants above 256.

draws(players)[source]
make_groups()[source]
next_round()[source]