Welcome to pyETT’s documentation!
Python API for Eleven VR Table Tennis data.

Getting Started
pyETT: Python library for Eleven VR Table Tennis data.
[1]:
from pyETT import ett
import pandas as pd
Player and user search
In order to get player’s information we first need to uniquely identify a player. We can use the user_search()
method of an object of the class ETT
to search players by username, as follows:
[2]:
eleven = ett.ETT()
eleven.user_search_dataframe('Highlander').head()
[2]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 248681 | Highlandersge | 1488.0 | 361225 | 0 | 1 | 2021-03-30T17:29:28.963Z |
1 | 246892 | mwwhighlander | 1500.0 | 222424 | 0 | 0 | 2021-01-02T23:00:36.762Z |
2 | 218318 | .::Highlander::. | 1500.0 | 179327 | 0 | 0 | 2021-01-07T00:52:31.209Z |
3 | 166876 | The Highlander | 1530.0 | 16962 | 4 | 1 | 2020-12-01T20:22:39.752Z |
4 | 384291 | highlander10 | 1500.0 | 71453 | 0 | 0 | 2021-04-16T22:18:26.874Z |
Here, the function returns all players that contain the input username string ‘Highlander’. To search for a perfect match, we can pass the argument perfect_match=True
:
[3]:
eleven.user_search_dataframe('highlanderNJ', perfect_match=True)
[3]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 348353 | highlanderNJ | 2013.5 | 2042 | 475 | 372 | 2021-06-30T01:53:32.742Z |
In this search, we were able to find the player with username ‘highlanderNJ’ which turns out to be me. We can now instantiate a Player
object to obtain his information:
[4]:
print(p:=ett.Player(348353))
highlanderNJ
[5]:
print(f"username:{p.name}\n elo:{p.elo}\n rank:{p.rank}\n wins:{p.wins}\n losses:{p.losses}\n")
username:highlanderNJ
elo:2013.5
rank:2042
wins:475
losses:372
We can see I have an Elo number of 2013.5, which puts me ranked in number 2042 in the world with 475 ranked wins and 372 losses. That’s not entirely bad as the total number of users around 500,000 players!
Matches and rounds
Now that we have instantiated a Player
object, we can obtain his matches using the method get_matches()
or get_matches_dataframe()
to obtain the data in a nice pandas dataframe. These methods return ranked matches by default but you can pass the parameters unranked=True
to obtain unranked matches.
[6]:
m = p.get_matches_dataframe()
m.head()
[6]:
created_at | id | ranked | number_of_rounds | state | winning_team | losing_team | home_score | away_score | home_player | away_player | rounds | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021-06-30T01:34:17.740Z | 9837423 | True | 3 | 1 | 0 | 1 | 2 | 1 | highlanderNJ | RandomPerson0504 | [<pyETT.ett.Match.Round object at 0x7fcc741398... |
1 | 2021-06-24T15:19:50.324Z | 9652764 | True | 3 | 1 | 0 | 1 | 2 | 0 | highlanderNJ | ZombieEngineerz8 | [<pyETT.ett.Match.Round object at 0x7fcc3cdcfe... |
2 | 2021-06-24T15:09:48.858Z | 9652464 | True | 3 | 1 | 0 | 1 | 2 | 0 | highlanderNJ | mcstives | [<pyETT.ett.Match.Round object at 0x7fcc3cdcf7... |
3 | 2021-06-23T22:33:16.914Z | 9631520 | True | 3 | 1 | 0 | 1 | 2 | 1 | ilyap | highlanderNJ | [<pyETT.ett.Match.Round object at 0x7fcc3ce160... |
4 | 2021-06-23T22:26:44.411Z | 9631342 | True | 3 | 1 | 0 | 1 | 2 | 0 | LearnerForever | highlanderNJ | [<pyETT.ett.Match.Round object at 0x7fcc3ce164... |
We can see that my latest ranked match was against the player with username ‘RandomPerson0504’ and I won the match 2 x 1. In order to obtain the rounds information, we can use the method get_rounds_dataframe
from the class Match, as follows:
[7]:
ett.Match.get_rounds_dataframe(m.rounds[0])
[7]:
id | round_number | state | away_score | home_score | winner | created_at | |
---|---|---|---|---|---|---|---|
0 | 22061114 | 0 | 0 | 8 | 11 | 0 | 2021-06-30T01:37:16.546Z |
1 | 22061034 | 0 | 0 | 11 | 7 | 1 | 2021-06-30T01:35:59.004Z |
2 | 22060923 | 0 | 0 | 9 | 11 | 0 | 2021-06-30T01:34:17.740Z |
Friends list, leaderboard and elo history
From the library, we can also obtain a player’s friends list with the method get_friends()
from an object of the Class Player, which also has a corresponding method that returns a list of friends in a pandas dataframe:
[8]:
p.get_friends_dataframe().head()
[8]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 35497 | perseph | 1626.0 | 13492 | 1208 | 1883 | 2021-06-20T22:50:59.471Z |
1 | 431729 | JoeSixPaK | 1804.5 | 5542 | 389 | 654 | 2021-06-30T02:15:30.270Z |
2 | 495551 | 77696c6c | 1500.0 | 165378 | 0 | 0 | 2021-06-14T16:21:31.027Z |
3 | 456082 | pete_ed5 | 1796.0 | 5807 | 123 | 128 | 2021-06-29T22:45:05.229Z |
4 | 249045 | Buttersmier | 1897.0 | 3601 | 80 | 74 | 2021-06-28T21:37:01.090Z |
I’m interested in comparing my Elo score with my friends’. For that purpose, we can get a player’s elo history with the method get_elo_history()
:
[9]:
p_elo = p.get_elo_history()
p_elo.head()
[9]:
elo | |
---|---|
2021-02-20T21:13:12.497Z | 1500.0 |
2021-02-24T03:06:30.809Z | 1513.0 |
2021-02-24T03:13:06.512Z | 1502.0 |
2021-02-24T03:16:20.774Z | 1489.0 |
2021-02-24T03:19:46.168Z | 1482.0 |
Let’s now pull the Elo history from 5 of my friends and put it all together in a dataframe including my own elo history and then plot them all:
[10]:
from functools import reduce
n_friends = 5
friends_elo = [f.get_elo_history().rename(columns={"elo":f.name}) for f in
p.get_friends()[-n_friends:] if f.get_elo_history() is not None]
friends_elo.append(p.get_elo_history().rename(columns={"elo":p.name}))
group_elo_df = reduce(lambda df1,df2: pd.merge(df1,df2,how='outer', left_index=True, right_index=True),
friends_elo).ffill(axis = 0)
[11]:
group_elo_df
[11]:
Konowl77 | belmont | Plipplopplip | olofaa | Kennatius | highlanderNJ | |
---|---|---|---|---|---|---|
2020-12-31T01:14:04.984Z | 1500.0 | NaN | NaN | NaN | NaN | NaN |
2020-12-31T18:45:27.553Z | 1493.0 | NaN | NaN | NaN | NaN | NaN |
2020-12-31T18:50:46.088Z | 1476.0 | NaN | NaN | NaN | NaN | NaN |
2021-01-01T00:34:21.158Z | 1468.0 | NaN | NaN | NaN | NaN | NaN |
2021-01-01T02:38:08.062Z | 1453.0 | NaN | NaN | NaN | NaN | NaN |
... | ... | ... | ... | ... | ... | ... |
2021-06-30T01:34:17.740Z | 1763.8 | 1907.2 | 1728.0 | 1506.0 | 1652.0 | 2005.5 |
2021-06-30T01:37:59.877Z | 1763.8 | 1907.2 | 1733.0 | 1506.0 | 1652.0 | 2005.5 |
2021-06-30T01:44:09.865Z | 1763.8 | 1907.2 | 1733.0 | 1506.0 | 1636.0 | 2005.5 |
2021-06-30T01:44:57.569Z | 1763.8 | 1907.2 | 1736.0 | 1506.0 | 1636.0 | 2005.5 |
2021-06-30T01:49:24.921Z | 1763.8 | 1907.2 | 1749.0 | 1506.0 | 1636.0 | 2005.5 |
4852 rows × 6 columns
[12]:
group_elo_df.plot(figsize=(10,8))
[12]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fcc36dcd850>

Overall, my friends are making some good progress. Everyone seems to be improving over time.
Now let’s take a look at the leaderboard by using the method get_leaderboard_dataframe()
from our eleven
object. By default, this method returns the top 10 players. You can pas
[13]:
eleven.get_leaderboard_dataframe()
https://www.elevenvr.club/leaderboards/?start=0
https://www.elevenvr.club/leaderboards/?start=10
[13]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 385684 | yedat | 3258.2 | 0 | 967 | 258 | 2021-06-28T19:21:18.464Z |
1 | 347650 | PROTT_VR | 3095.0 | 1 | 662 | 119 | 2021-06-22T19:37:25.710Z |
2 | 234850 | lapoctopus90 | 3087.1 | 2 | 712 | 246 | 2021-06-28T17:55:13.346Z |
3 | 289382 | gselvas92 | 3034.0 | 3 | 947 | 347 | 2021-06-28T18:12:51.853Z |
4 | 372961 | sunking73 | 2995.5 | 4 | 599 | 251 | 2021-06-20T11:44:49.214Z |
5 | 428341 | NPiet | 2995.0 | 5 | 979 | 193 | 2021-06-25T07:22:35.945Z |
6 | 4410 | wurstfriedl | 2987.0 | 6 | 2208 | 932 | 2021-06-28T14:49:11.031Z |
7 | 3831 | alexttbcn | 2980.0 | 7 | 1303 | 618 | 2021-06-27T18:11:37.414Z |
8 | 11002 | twISTer1979 | 2978.6 | 8 | 2411 | 931 | 2021-06-28T17:13:18.551Z |
9 | 20585 | fmwallin | 2960.0 | 9 | 1553 | 931 | 2021-06-15T08:53:41.094Z |
[14]:
lb_elo = [f.get_elo_history().rename(columns={"elo":f.name}) for f in
eleven.get_leaderboard() if f.get_elo_history() is not None]
lb_elo.append(p.get_elo_history().rename(columns={"elo":p.name}))
lb_elo_df = reduce(lambda df1,df2: pd.merge(df1,df2,how='outer', left_index=True, right_index=True),
lb_elo).ffill(axis = 0)
[15]:
lb_elo_df.plot(figsize=(10,8))
[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fcc34838100>

The dynamics are quite different compared to the one from my cohort of friends. At the top of the leaderboard, we observe rapid Elo growth across the board. The Top 2 player (PROTT_VR), for instance, moved from a 1500 Elo to an impressive 3000+ Elo in a very short period of time. The number 1 player (yedat) has recently surpassed PROTT_VR also showing an amazing Elo growth. I have added my Elo evolution for comparison (the little blue curve at the bottom) to give a perspective on how competitive the game is at the highest level.
Matchup and Cohort Analysis
[1]:
from pyETT import ett
The ett Class Cohort manages state, logic and analytics for a cohort of players (instances of the Class Player). Let’s take a look at how the top ETT players in the world match up against each other. First, we create a cohort with the top 10 players from the leaderboard:
[2]:
lb_cohort = ett.Cohort(ett.ETT().get_leaderboard(num_players=10))
lb_cohort.size
[2]:
10
[3]:
lb_cohort.players_dataframe()
[3]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 315909 | Aiphaton | 3204.0 | 1 | 550 | 70 | 2021-08-26T18:33:35.943Z |
1 | 347650 | PROTT_VR | 3134.0 | 2 | 715 | 142 | 2021-08-28T16:14:23.328Z |
2 | 484532 | Seldon36 | 3114.3 | 3 | 699 | 241 | 2021-08-30T15:48:03.137Z |
3 | 20585 | fmwallin | 3072.0 | 4 | 1669 | 971 | 2021-08-30T12:41:21.933Z |
4 | 234850 | Lapoctopus | 3069.1 | 5 | 759 | 268 | 2021-08-20T18:36:38.299Z |
5 | 4410 | wurstfriedl | 3028.0 | 6 | 2364 | 954 | 2021-08-27T12:16:32.301Z |
6 | 372961 | sunking73 | 2995.5 | 7 | 599 | 251 | 2021-06-20T11:44:49.214Z |
7 | 385684 | yedat | 2994.2 | 10 | 1037 | 297 | 2021-08-07T05:47:36.647Z |
8 | 11002 | twISTer1979 | 2960.6 | 9 | 2542 | 972 | 2021-08-28T16:53:27.962Z |
9 | 3831 | alexttbcn | 2958.0 | 12 | 1327 | 625 | 2021-08-26T14:10:40.840Z |
By accessing the attribute size
and calling the methods players_dataframe()
from the Cohort object, we obtain the cohort size (10) and the list of players in the cohort. We can get the Elo history of the players in the cohort with the method get_elo_history()
:
[4]:
lb_cohort_elo = lb_cohort.get_elo_history()
lb_cohort_elo
[4]:
Aiphaton | PROTT_VR | Seldon36 | fmwallin | Lapoctopus | wurstfriedl | sunking73 | yedat | twISTer1979 | alexttbcn | |
---|---|---|---|---|---|---|---|---|---|---|
2020-02-29T13:03:53.451Z | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1500.0 |
2020-02-29T13:09:19.941Z | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1527.0 |
2020-02-29T13:18:01.313Z | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1521.0 |
2020-02-29T13:20:46.824Z | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1536.0 |
2020-02-29T13:27:06.816Z | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1550.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2021-08-30T12:11:47.612Z | 3200.0 | 3138.0 | 3114.3 | 3072.0 | 3074.1 | 3028.0 | 3001.5 | 2995.2 | 2954.6 | 2955.0 |
2021-08-30T12:16:45.042Z | 3200.0 | 3138.0 | 3117.3 | 3069.0 | 3074.1 | 3028.0 | 3001.5 | 2995.2 | 2954.6 | 2955.0 |
2021-08-30T12:23:36.680Z | 3200.0 | 3138.0 | 3113.3 | 3073.0 | 3074.1 | 3028.0 | 3001.5 | 2995.2 | 2954.6 | 2955.0 |
2021-08-30T12:30:05.759Z | 3200.0 | 3138.0 | 3110.3 | 3076.0 | 3074.1 | 3028.0 | 3001.5 | 2995.2 | 2954.6 | 2955.0 |
2021-08-30T12:37:25.487Z | 3200.0 | 3138.0 | 3112.3 | 3074.0 | 3074.1 | 3028.0 | 3001.5 | 2995.2 | 2954.6 | 2955.0 |
14358 rows × 10 columns
[5]:
lb_cohort_elo.plot(figsize=(10,8))
[5]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f27d2d5b640>
We can obtain the full list of matches played within the cohort, i.e., match ups, by accessing the method get_matches()
or get_matches_dataframe()
to obtain results in a pandas DataFrame:
[6]:
lb_cohort.get_matches_dataframe()
[6]:
created_at | id | ranked | number_of_rounds | state | winning_team | losing_team | home_score | away_score | elo_change | home_elo_avg | away_elo_avg | home_player | away_player | rounds | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021-07-25T15:03:46.195Z | 10674157 | True | 3 | 1 | 1 | 0 | 0 | 0 | 19.0 | 3107.0 | 3038.0 | PROTT_VR | Aiphaton | [<pyETT.ett.Match.Round object at 0x7f27d00c09... |
1 | 2021-07-25T15:11:19.296Z | 10674382 | True | 3 | 1 | 1 | 0 | 0 | 0 | 9.0 | 3088.0 | 3057.0 | PROTT_VR | Aiphaton | [<pyETT.ett.Match.Round object at 0x7f27d00c0b... |
2 | 2021-07-25T15:17:52.938Z | 10674591 | True | 3 | 1 | 1 | 0 | 0 | 0 | 5.0 | 3079.0 | 3066.0 | PROTT_VR | Aiphaton | [<pyETT.ett.Match.Round object at 0x7f27d00d97... |
3 | 2021-07-25T15:25:15.522Z | 10674804 | True | 3 | 1 | 1 | 0 | 0 | 0 | 2.0 | 3074.0 | 3071.0 | PROTT_VR | Aiphaton | [<pyETT.ett.Match.Round object at 0x7f27d00d9f... |
4 | 2021-08-25T18:06:09.908Z | 11753227 | True | 3 | 1 | 1 | 0 | 0 | 0 | 13.0 | 3138.0 | 3200.0 | PROTT_VR | Aiphaton | [<pyETT.ett.Match.Round object at 0x7f27d00d14... |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
911 | 2021-01-22T13:49:59.089Z | 3694516 | True | 3 | 1 | 0 | 1 | 0 | 0 | 11.0 | 2816.0 | 2883.0 | twISTer1979 | alexttbcn | [<pyETT.ett.Match.Round object at 0x7f27ca6aa6... |
912 | 2021-02-20T18:38:54.237Z | 4832703 | True | 3 | 1 | 0 | 1 | 0 | 0 | 15.0 | 2905.0 | 2943.0 | twISTer1979 | alexttbcn | [<pyETT.ett.Match.Round object at 0x7f27ca6aa6... |
913 | 2021-02-20T18:45:13.317Z | 4832978 | True | 3 | 1 | 1 | 0 | 0 | 0 | 8.0 | 2920.0 | 2928.0 | twISTer1979 | alexttbcn | [<pyETT.ett.Match.Round object at 0x7f27ca6aa7... |
914 | 2021-02-20T18:53:27.768Z | 4833346 | False | 3 | 1 | 1 | 0 | 0 | 0 | 0.0 | 2912.0 | 2936.0 | twISTer1979 | alexttbcn | [<pyETT.ett.Match.Round object at 0x7f27ca6aa8... |
915 | 2021-02-20T18:53:48.819Z | 4833362 | True | 3 | 1 | 1 | 0 | 0 | 0 | 6.0 | 2912.0 | 2936.0 | twISTer1979 | alexttbcn | [<pyETT.ett.Match.Round object at 0x7f27ca6aa9... |
916 rows × 15 columns
We observed the the top 10 players played an impressive 916 number of matches among each other. To obtain match up analytics of players in the cohort, we can call the method describe()
:
[7]:
lb_cohort.describe()
[7]:
index | num_matches | wins | losses | win_rate | num_matches_ranked | wins_ranked | losses_ranked | win_rate_ranked | elo | rank | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Aiphaton | 311 | 208 | 103 | 67.0 | 143 | 98 | 45 | 69.0 | 3204.0 | 1 |
1 | yedat | 202 | 125 | 77 | 62.0 | 179 | 110 | 69 | 61.0 | 2994.2 | 10 |
2 | wurstfriedl | 112 | 38 | 74 | 34.0 | 23 | 12 | 11 | 52.0 | 3028.0 | 6 |
3 | PROTT_VR | 227 | 116 | 111 | 51.0 | 222 | 115 | 107 | 52.0 | 3134.0 | 2 |
4 | Seldon36 | 87 | 38 | 49 | 44.0 | 34 | 17 | 17 | 50.0 | 3114.3 | 3 |
5 | Lapoctopus | 242 | 120 | 122 | 50.0 | 175 | 80 | 95 | 46.0 | 3069.1 | 5 |
6 | sunking73 | 63 | 31 | 32 | 49.0 | 50 | 21 | 29 | 42.0 | 2995.5 | 7 |
7 | fmwallin | 212 | 90 | 122 | 42.0 | 147 | 59 | 88 | 40.0 | 3072.0 | 4 |
8 | twISTer1979 | 249 | 98 | 151 | 39.0 | 110 | 39 | 71 | 35.0 | 2960.6 | 9 |
9 | alexttbcn | 127 | 52 | 75 | 41.0 | 43 | 12 | 31 | 28.0 | 2958.0 | 12 |
We observe that the player PROTTVR
(ranked 2) played the most ranked matches against Top 10 ranked players with a total of 222 matches followed by yedat
with 179 matches. The player with the highest win rate when playing against other Top 10 ranked players is Aiphaton
, the current World’s number 1, followed by yedat
, formerly ranked number 1.
Official Tournament
[1]:
from pyETT import ett
Eleven has been running monthly official tournaments since April/2021. The tournaments draw interest from top players as well as upcoming ones who are looking to become more competitive. After each tournament, each player may gain rankings points and at the end of the year the top ranked players will compete on an year-end tournament to determine who’s the best player of the year. We can obtain the current standinds of the rankings points as follows:
[4]:
ett.official_tournament_leaderboard_dataframe().head(10)
[4]:
Ranking | Player | April | May | June | July | Aug | Total | |
---|---|---|---|---|---|---|---|---|
0 | 1 | Aiphaton | 175.0 | 40.0 | 90.0 | NaN | NaN | 305 |
1 | 2 | lapoctopus90 | NaN | 90.0 | 125.0 | NaN | NaN | 215 |
2 | 3 | ProTTVR | 125.0 | 60.0 | 15.0 | NaN | NaN | 200 |
3 | 4 | yedat | 15.0 | 125.0 | NaN | NaN | NaN | 140 |
4 | 5 | porter | 40.0 | 15.0 | 60.0 | NaN | NaN | 115 |
5 | 6 | ALIASREK | 90.0 | NaN | 10.0 | NaN | NaN | 100 |
6 | 7 | twISTer1979 | 25.0 | 25.0 | 40.0 | NaN | NaN | 90 |
7 | 8 | PixelFire | 60.0 | 10.0 | 15.0 | NaN | NaN | 85 |
8 | 9 | l4mbo | 40.0 | 15.0 | 10.0 | NaN | NaN | 65 |
9 | 9 | fmwallin | 25.0 | 25.0 | 15.0 | NaN | NaN | 65 |
Not surprisingly, the highest ranked players are at the top of ETT’s leaderboard:
[3]:
ett.ETT().get_leaderboard_dataframe()
[3]:
id | name | elo | rank | wins | losses | last_online | |
---|---|---|---|---|---|---|---|
0 | 385684 | yedat | 3135.2 | 0 | 1001 | 275 | 2021-07-08T21:55:09.544Z |
1 | 183811 | PROTTVR | 3095.0 | 1 | 877 | 165 | 2021-07-07T17:28:18.291Z |
2 | 234850 | lapoctopus90 | 3087.1 | 2 | 723 | 250 | 2021-07-06T18:19:59.324Z |
3 | 20585 | fmwallin | 3018.0 | 3 | 1603 | 943 | 2021-07-08T20:14:53.095Z |
4 | 289382 | gselvas92 | 3002.0 | 4 | 986 | 364 | 2021-07-08T18:02:14.002Z |
5 | 372961 | sunking73 | 2995.5 | 5 | 599 | 251 | 2021-06-20T11:44:49.214Z |
6 | 428341 | NPiet | 2995.0 | 6 | 979 | 193 | 2021-06-25T07:22:35.945Z |
7 | 11002 | twISTer1979 | 2990.6 | 7 | 2455 | 941 | 2021-07-08T18:27:03.773Z |
8 | 4410 | wurstfriedl | 2989.0 | 8 | 2212 | 932 | 2021-07-08T16:24:15.480Z |
9 | 3831 | alexttbcn | 2980.0 | 9 | 1303 | 618 | 2021-07-02T09:41:40.627Z |
Players with an Elo rating greater than 2000 at any day of the preceding month have direct entry to the tournament. Players who had an Elo under 2000 at any point in the previous month, can qualify by entering a qualifying tournament. We can verify if a player have direct entry or can qualify by instantiating an object of the Class Tournament as follows:
[5]:
players = [ett.Player(id) for id in [357217, 348353, 12345]]
ett.Tournament(players).qualify(elo_min=2000, start="2021-06-01", end="2021-06-30")
[5]:
mean | min | max | direct_entry | can_qualify | id | name | |
---|---|---|---|---|---|---|---|
0 | 1863.069231 | 1743.8 | 1974.8 | 0 | 1 | 357217 | Cyrillus82 |
1 | 1984.258741 | 1923.5 | 2019.5 | 1 | 1 | 348353 | highlanderNJ |
2 | 1500.000000 | 1500.0 | 1500.0 | 0 | 1 | 12345 | PastaAndPasta |
We observe that the player highlanderNJ
have direct entry to July’s official tournament as his max Elo within June is over 2000. He also has the option to play in the qualifying tournament as his min Elo rating in June is under 2000. The players Cyrillus82
and PastaAndPasta
can only enter the qualifying tournament as their max Elo in June did not surpass the 2000 threshold.
An app is available at https://ett-monthly.herokuapp.com/ offering an easy to use UI constructed on top of this library, currently in use by the organizers of the official tournament when validating player entry.
pyETT
pyETT package
Submodules
pyETT.ett module
- class pyETT.ett.Cohort(players)[source]
Bases:
object
A Class to represent a cohort of players
- describe() pandas.core.frame.DataFrame [source]
Returns a dataframe with descriptive statistics of the players in the cohort considering only matches among themselves, such as win, losses and win rate. Additional player specific attributes are added to the dataframe, such as name, elo and rank.
- Returns
Players matchup stats in the cohort.
- Return type
pd.DataFrame
- get_matches(unranked: bool = False) List[pyETT.ett.Match] [source]
Returns matches among players in the cohort
- class pyETT.ett.ETT[source]
Bases:
object
A class to represent Eleven Table Tennis (ETT).
- get_leaderboard(num_players: int = 10) List[pyETT.ett.Player] [source]
Returns a list of players from the leaderboard.
- Parameters
num_players (int, optional) – Max number of players to return. Defaults to 10.
- Returns
Top players in ETT’s leaderboard.
- Return type
List[Player]
- get_leaderboard_dataframe(num_players: int = 10) pandas.core.frame.DataFrame [source]
Returns a pandas dataframe with players from the leaderboard.
- Parameters
num_players (int, optional) – Max number of players to return. Defaults to 10.
- Returns
Top players in ETT’s leaderboard.
- Return type
pd.DataFrame
- user_search(username: str, perfect_match: bool = False) List[pyETT.ett.Player] [source]
Returns a list of players whose name contains
username
, ifperfect_match
is False. Otherwise, it returns a list of players whose username is a perfect match withusername
.- Parameters
username (str) – Username
perfect_match (bool, optional) – Whether to perform perfect match in string matching. Defaults to False.
- Returns
List of players whose names match with username.
- Return type
List[Player]
- user_search_dataframe(username: str, perfect_match: bool = False) pandas.core.frame.DataFrame [source]
Returns a list of players whose name contains username, if perfect_match is False. Otherwise, it returns a list of players whose usernames is a perfect match with username.
- Parameters
username (str) – Username
perfect_match (bool, optional) – Whether to perform perfect match in string matching. Defaults to False.
- Returns
A dataframe of players whose names match with username.
- Return type
pd.DataFrame
- class pyETT.ett.Match(match_id, match)[source]
Bases:
object
A class to represent a Match.
- class pyETT.ett.Player(user_id, player=None, legacy_api=False)[source]
Bases:
object
A class to represent a Player.
- AWAY = 1
- HOME = 0
- get_elo_history() pandas.core.frame.DataFrame [source]
Returns player’s elo score history.
- Returns
[description]
- Return type
pd.DataFrame
- get_friends() List[pyETT.ett.Player] [source]
Return a player’s friends list
- get_friends_dataframe() pandas.core.frame.DataFrame [source]
Return a player’s friends list in a dataframe
- get_matches(unranked: bool = False) List[pyETT.ett.Match] [source]
Return player’s matches.
- get_matches_dataframe(unranked: bool = False) pandas.core.frame.DataFrame [source]
Return player’s matches in a pandas dataframe.
- get_matches_revertible() List[numpy.int64] [source]
Returns player’s lost matches that are eligible to be reverted/cancelled. If you have an incomplete match because of connection issues or because your opponent left in the middle of the play, you can request an Eleven Moderator (Discord) to revert/cancel the match and hence update your Elo rating.
- Returns
List of matches ids that are eligible to be reverted/cancelled.
- Return type
List[np.int64]
- print_matches_revertible()[source]
Pretty print player’s lost matches that are eligible to be reverted/cancelled. If you have an incomplete match because of connection issues or because your opponent left in the middle of the play, you can request an Eleven Moderator (Discord) to revert/cancel the match and hence update your Elo rating
- class pyETT.ett.Tournament(players)[source]
Bases:
object
A Class to handle ETT official tournaments
- qualify(elo_min: float, start: str, end: str) pandas.core.frame.DataFrame [source]
Implements logic to enter or qualify to ETT’s official monthly tournament. Players with an Elo rating exceeding
elo_min
at any point betweenstart
andend
date have direct entry to the tournament. Otherwise, they can enter a Qualifying Tournament to try and qualify. This method returns a dataframe indicating which players have direct entry or can qualify.- Parameters
elo_min (float) – Elo threshold to have direct entry to the Tournament.
start (str) – Start date (YYYY-MM-DD)
end (str) – End date (YYYY-MM-DD)
- Returns
- Data frame of players with the following information:
mean: Player’s mean Elo between
start
andend
min: Player’s min Elo between
start
and end`max: Player’s max Elo between
start
and end`direct_entry: Boolean indicating whether player have direct entry to the Tournament
can_qualify: Boolean indicating whether player can enter Qualifying Tournament
id: Player’s id
name: Player’s username
- Return type
pd.DataFrame
- pyETT.ett.official_tournament_leaderboard_dataframe() pandas.core.frame.DataFrame [source]
Returns a pandas dataframe with the leaderboard of the Eleven official tournaments available at http://lavadesignstudio.co.uk/eleven-rankings/.
- Returns
A dataframe with the leaderboard of Eleven official tournaments.
- Return type
pd.DataFrame
- pyETT.ett.print_match(match: pyETT.ett.Match)[source]
Pretty print a match with rounds.
- Parameters
match (Match) – A match.
pyETT.ett_parser module
Module contents
Installation
From PyPI
$ pip install pyETT
Collaborate
Fork me at https://github.com/souzatharsis/pyETT.
Indices and tables
Licensed under Attribution-NonCommercial-ShareAlike 4.0 International.