rustat-python-api 0.4.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rustat_python_api/__init__.py +4 -0
- rustat_python_api/config.py +37 -0
- rustat_python_api/models_api.py +58 -0
- rustat_python_api/parser.py +226 -0
- rustat_python_api/processing.py +89 -0
- rustat_python_api/urls.py +8 -0
- rustat_python_api-0.4.11.dist-info/LICENSE +1 -0
- rustat_python_api-0.4.11.dist-info/METADATA +49 -0
- rustat_python_api-0.4.11.dist-info/RECORD +11 -0
- rustat_python_api-0.4.11.dist-info/WHEEL +5 -0
- rustat_python_api-0.4.11.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
columns = [
|
|
2
|
+
'player_name', 'team_name', 'half', 'second', 'action_id', 'action_name',
|
|
3
|
+
'position_name', 'possession_number', 'pos_x', 'pos_y', 'pos_dest_x', 'pos_dest_y',
|
|
4
|
+
'player_id', 'number', 'team_id', 'standart_name', 'possession_time',
|
|
5
|
+
'opponent_id', 'opponent_name', 'opponent_team_id', 'opponent_team_name',
|
|
6
|
+
'opponent_position_name', 'zone_name', 'zone_dest_name', 'len',
|
|
7
|
+
'possession_team_id', 'possession_team_name', 'possession_name',
|
|
8
|
+
'attack_status_name', 'attack_type_name', 'attack_flang_name',
|
|
9
|
+
'attack_team_id', 'attack_team_name', 'attack_number',
|
|
10
|
+
'body_name', 'gate_x', 'gate_y', 'assistant_id',
|
|
11
|
+
'assistant_name', 'shot_type', 'touches', 'xg',
|
|
12
|
+
'shot_handling', 'match_id', 'receiver_id', 'receiver_name'
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
numeric_columns = [
|
|
16
|
+
'id', 'number', 'player_id', 'team_id', 'half', 'second',
|
|
17
|
+
'pos_x', 'pos_y', 'pos_dest_x', 'pos_dest_y', 'len', 'possession_id', 'possession_team_id',
|
|
18
|
+
'opponent_id', 'opponent_team_id', 'zone_id', 'zone_dest_id',
|
|
19
|
+
'possession_number', 'attack_status_id', 'attack_team_id', 'assistant_id', 'touches', 'xg'
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
id2type = {
|
|
23
|
+
1: 'pass', 2: 'duel', 3: 'foul',
|
|
24
|
+
4: 'shot', 5: 'free kick', 6: 'interception',
|
|
25
|
+
7: 'rebound', 8: 'goal', 9: 'clearance',
|
|
26
|
+
10: 'bad ball control', 11: 'control', 12: 'attack',
|
|
27
|
+
13: 'keeper', 14: 'substitution', 15: 'formation',
|
|
28
|
+
16: 'player position', 17: 'ball off', 18: 'match status',
|
|
29
|
+
19: 'mistake', 20: 'translation problem', 21: 'carry',
|
|
30
|
+
22: 'receive', 23: 'goal attack involvement', 24: 'rating',
|
|
31
|
+
25: 'average position', 26: 'cross', 27: 'ball out',
|
|
32
|
+
28: 'other', 29: 'video', 30: 'bad mistake',
|
|
33
|
+
31: 'bad keeper mistake', 32: 'goal moment', 33: 'team pressing',
|
|
34
|
+
34: 'line up', 35: 'sync', 36: 'referee',
|
|
35
|
+
37: 'insurance', 38: 'injury',
|
|
36
|
+
128: 'staff', 161: 'sub player'
|
|
37
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DynamoLab:
|
|
7
|
+
def __init__(self, host: str = "http://localhost:8000/"):
|
|
8
|
+
self.host = host
|
|
9
|
+
|
|
10
|
+
def get_active_models(self):
|
|
11
|
+
url = self.host + "models"
|
|
12
|
+
response = requests.get(url)
|
|
13
|
+
return response.json()
|
|
14
|
+
|
|
15
|
+
def run_model(
|
|
16
|
+
self,
|
|
17
|
+
model: str,
|
|
18
|
+
data: pd.DataFrame,
|
|
19
|
+
return_type: str = "json",
|
|
20
|
+
inplace: bool = False,
|
|
21
|
+
return_df: bool = False,
|
|
22
|
+
inplace_column: str = None
|
|
23
|
+
):
|
|
24
|
+
"""
|
|
25
|
+
model: str
|
|
26
|
+
The name of the model to run
|
|
27
|
+
return_type: str
|
|
28
|
+
One of: "json", "list", "numpy"
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
url = self.host + "predict"
|
|
32
|
+
csv_string = data.to_csv(index=False)
|
|
33
|
+
|
|
34
|
+
body = {
|
|
35
|
+
"model": model,
|
|
36
|
+
"data": csv_string,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
response = requests.post(url, json=body)
|
|
40
|
+
|
|
41
|
+
if return_df or inplace:
|
|
42
|
+
if inplace_column is None:
|
|
43
|
+
raise ValueError("inplace_column must be specified if inplace is True")
|
|
44
|
+
if inplace:
|
|
45
|
+
data[inplace_column] = np.array(response.json()["prediction"])
|
|
46
|
+
else:
|
|
47
|
+
df = data.copy()
|
|
48
|
+
df[inplace_column] = np.array(response.json()["prediction"])
|
|
49
|
+
return df
|
|
50
|
+
else:
|
|
51
|
+
if return_type == "json":
|
|
52
|
+
return response.json()
|
|
53
|
+
elif return_type == "list":
|
|
54
|
+
return response.json()["prediction"]
|
|
55
|
+
elif return_type == "numpy":
|
|
56
|
+
return np.array(response.json()["prediction"])
|
|
57
|
+
else:
|
|
58
|
+
raise ValueError("return_type must be one of: json, list, numpy")
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from tqdm import tqdm
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from .urls import URLs
|
|
8
|
+
from .config import numeric_columns
|
|
9
|
+
from .processing import processing
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RuStatParser:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
user: str,
|
|
16
|
+
password: str,
|
|
17
|
+
urls: dict = URLs,
|
|
18
|
+
sleep: int = -1
|
|
19
|
+
):
|
|
20
|
+
self.user = user
|
|
21
|
+
self.password = password
|
|
22
|
+
self.urls = urls
|
|
23
|
+
self.sleep = sleep
|
|
24
|
+
|
|
25
|
+
self.cached_info = {}
|
|
26
|
+
|
|
27
|
+
def resp2data(self, query: str) -> dict:
|
|
28
|
+
|
|
29
|
+
if self.sleep > 0:
|
|
30
|
+
time.sleep(self.sleep)
|
|
31
|
+
|
|
32
|
+
response = requests.get(query)
|
|
33
|
+
return response.json()
|
|
34
|
+
|
|
35
|
+
def get_rpl_info(self):
|
|
36
|
+
for season_id in tqdm(range(1, 36)):
|
|
37
|
+
data = self.resp2data(
|
|
38
|
+
self.urls["tournament_teams"].format(
|
|
39
|
+
user=self.user,
|
|
40
|
+
password=self.password,
|
|
41
|
+
season_id=season_id
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if data:
|
|
46
|
+
first_team_id = data["data"]["row"][0]["id"]
|
|
47
|
+
first_team_schedule = self.resp2data(
|
|
48
|
+
self.urls["schedule"].format(
|
|
49
|
+
user=self.user,
|
|
50
|
+
password=self.password,
|
|
51
|
+
team_id=first_team_id,
|
|
52
|
+
season_id=season_id
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if first_team_schedule:
|
|
57
|
+
last_match = first_team_schedule["data"]["row"][0]
|
|
58
|
+
season_name = f'{last_match["tournament_name"]} {last_match["season_name"]}'
|
|
59
|
+
else:
|
|
60
|
+
season_name = ""
|
|
61
|
+
|
|
62
|
+
self.cached_info[season_id] = {
|
|
63
|
+
"season_name": season_name,
|
|
64
|
+
"season_teams": data["data"]["row"]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return self.cached_info
|
|
68
|
+
|
|
69
|
+
def get_schedule(self, team_id: str, season_id: str) -> dict:
|
|
70
|
+
data = self.resp2data(
|
|
71
|
+
self.urls["schedule"].format(
|
|
72
|
+
user=self.user,
|
|
73
|
+
password=self.password,
|
|
74
|
+
team_id=team_id,
|
|
75
|
+
season_id=season_id
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if not data:
|
|
80
|
+
return {}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
int(row["id"]): {
|
|
84
|
+
"match_date": row["match_date"],
|
|
85
|
+
"team1_id": int(row["team1_id"]),
|
|
86
|
+
"team2_id": int(row["team2_id"]),
|
|
87
|
+
"team1_name": row["team1_name"],
|
|
88
|
+
"team2_name": row["team2_name"],
|
|
89
|
+
"round_name": (row["round_name"] if "round_name" in row else None),
|
|
90
|
+
"tournament_name": (row["tournament_name"] if "tournament_name" in row else None),
|
|
91
|
+
"season_name": (row["season_name"] if "season_name" in row else None)
|
|
92
|
+
}
|
|
93
|
+
for row in data["data"]["row"]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
def get_events(
|
|
97
|
+
self,
|
|
98
|
+
match_id: int,
|
|
99
|
+
process: bool = True,
|
|
100
|
+
return_subs: bool = True
|
|
101
|
+
) -> pd.DataFrame | None | tuple[pd.DataFrame, pd.DataFrame]:
|
|
102
|
+
data = self.resp2data(
|
|
103
|
+
self.urls["events"].format(
|
|
104
|
+
user=self.user,
|
|
105
|
+
password=self.password,
|
|
106
|
+
match_id=match_id
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not data:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
df = pd.json_normalize(data["data"]["row"])
|
|
114
|
+
|
|
115
|
+
current_numeric_columns = [column for column in numeric_columns if column in df.columns]
|
|
116
|
+
df[current_numeric_columns] = df[current_numeric_columns].apply(pd.to_numeric, errors='coerce')
|
|
117
|
+
|
|
118
|
+
if process:
|
|
119
|
+
df['match_id'] = match_id
|
|
120
|
+
|
|
121
|
+
if return_subs:
|
|
122
|
+
subs = df[df['action_id'] == '14000'][[
|
|
123
|
+
'match_id', 'half', 'second',
|
|
124
|
+
'team_id', 'team_name',
|
|
125
|
+
'opponent_id', 'opponent_name',
|
|
126
|
+
'player_id', 'player_name'
|
|
127
|
+
]].rename(columns={
|
|
128
|
+
'player_id': 'player_id_out',
|
|
129
|
+
'opponent_id': 'player_id_in',
|
|
130
|
+
'player_name': 'player_name_out',
|
|
131
|
+
'opponent_name': 'player_name_in'
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
df = processing(df)
|
|
135
|
+
|
|
136
|
+
return (df, subs) if return_subs else df
|
|
137
|
+
|
|
138
|
+
def get_tracking(self, match_id: int) -> pd.DataFrame | None:
|
|
139
|
+
data = self.resp2data(
|
|
140
|
+
self.urls["tracking"].format(
|
|
141
|
+
user=self.user,
|
|
142
|
+
password=self.password,
|
|
143
|
+
match_id=match_id
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if not data:
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
data = data["data"]["team"]
|
|
151
|
+
df = pd.DataFrame(columns=["half", "second", "pos_x", "pos_y", "team_id", "player_id", "player_name", "side_1h"])
|
|
152
|
+
|
|
153
|
+
for team_data in tqdm(data):
|
|
154
|
+
team_id = team_data["id"]
|
|
155
|
+
side_1h = team_data["gate_position_half_1"]
|
|
156
|
+
|
|
157
|
+
for player_data in team_data["player"]:
|
|
158
|
+
player_id = player_data["id"]
|
|
159
|
+
player_name = player_data["name"]
|
|
160
|
+
|
|
161
|
+
cur_df = pd.json_normalize(player_data["row"])
|
|
162
|
+
cur_df = cur_df.apply(pd.to_numeric, errors='coerce')
|
|
163
|
+
cur_df["team_id"] = team_id
|
|
164
|
+
cur_df["player_id"] = player_id
|
|
165
|
+
cur_df["player_name"] = player_name
|
|
166
|
+
cur_df["side_1h"] = side_1h
|
|
167
|
+
|
|
168
|
+
df = pd.concat([df, cur_df], ignore_index=True)
|
|
169
|
+
|
|
170
|
+
return df.sort_values(by=["second", "team_id", "player_id"])
|
|
171
|
+
|
|
172
|
+
def get_match_stats(self, match_id: int) -> dict:
|
|
173
|
+
data = self.resp2data(
|
|
174
|
+
self.urls["match_stats"].format(
|
|
175
|
+
user=self.user,
|
|
176
|
+
password=self.password,
|
|
177
|
+
match_id=match_id
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if not data:
|
|
182
|
+
return {}
|
|
183
|
+
|
|
184
|
+
stats = defaultdict(dict)
|
|
185
|
+
|
|
186
|
+
for row in data['data']['row']:
|
|
187
|
+
team_id = int(row['team_id'])
|
|
188
|
+
param_name = row['param_name']
|
|
189
|
+
|
|
190
|
+
param_value = float(row['value'])
|
|
191
|
+
|
|
192
|
+
stats[param_name][team_id] = param_value
|
|
193
|
+
|
|
194
|
+
return stats
|
|
195
|
+
|
|
196
|
+
def get_players_match_stats(self, match_id: int) -> dict:
|
|
197
|
+
data = self.resp2data(
|
|
198
|
+
self.urls["player_match_stats"].format(
|
|
199
|
+
user=self.user,
|
|
200
|
+
password=self.password,
|
|
201
|
+
match_id=match_id
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if not data:
|
|
206
|
+
return {}
|
|
207
|
+
|
|
208
|
+
return data['data']['team']
|
|
209
|
+
|
|
210
|
+
def get_players_minutes_in_match(self, match_id: int) -> dict:
|
|
211
|
+
data = self.get_players_match_stats(match_id)
|
|
212
|
+
|
|
213
|
+
if not data:
|
|
214
|
+
return {}
|
|
215
|
+
|
|
216
|
+
players_minutes = {}
|
|
217
|
+
|
|
218
|
+
for team_data in data:
|
|
219
|
+
for player_data in team_data['player']:
|
|
220
|
+
player_id = int(player_data['id'])
|
|
221
|
+
|
|
222
|
+
minutes = [float(metric['value']) for metric in player_data['param'] if metric['id'] == '288'][0]
|
|
223
|
+
|
|
224
|
+
players_minutes[player_id] = minutes
|
|
225
|
+
|
|
226
|
+
return players_minutes
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from .config import columns, id2type
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def process_list(x: pd.Series):
|
|
8
|
+
lst = x.dropna().unique().tolist()
|
|
9
|
+
if len(lst) == 1:
|
|
10
|
+
return lst[0]
|
|
11
|
+
elif len(lst) == 0:
|
|
12
|
+
return np.nan
|
|
13
|
+
else:
|
|
14
|
+
return lst
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def gluing(df: pd.DataFrame) -> pd.DataFrame:
|
|
18
|
+
cols = ['player_id', 'half', 'second', 'pos_x', 'pos_y']
|
|
19
|
+
|
|
20
|
+
df_gb = df.groupby(cols).agg(process_list).reset_index()
|
|
21
|
+
df_gb['possession_number'] = df_gb['possession_number'].apply(
|
|
22
|
+
lambda x: max(x) if isinstance(x, list) else x
|
|
23
|
+
)
|
|
24
|
+
df_gb['pos_dest_x'] = df_gb['pos_dest_x'].apply(
|
|
25
|
+
lambda x: x[0] if isinstance(x, list) else x
|
|
26
|
+
)
|
|
27
|
+
df_gb['pos_dest_y'] = df_gb['pos_dest_y'].apply(
|
|
28
|
+
lambda x: x[0] if isinstance(x, list) else x
|
|
29
|
+
)
|
|
30
|
+
df_gb['pos_dest_nan'] = (df_gb['pos_dest_x'].isna() & df_gb['pos_dest_y'].isna()).astype(int)
|
|
31
|
+
df_gb = df_gb.sort_values(by=['half', 'second', 'possession_number', 'pos_dest_nan']).reset_index(drop=True)
|
|
32
|
+
return df_gb
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def add_reciever(glued_df: pd.DataFrame) -> pd.DataFrame:
|
|
36
|
+
df = glued_df.copy()
|
|
37
|
+
df['receiver_id'] = df['player_id'].shift(-1)
|
|
38
|
+
df['receiver_name'] = df['player_name'].shift(-1)
|
|
39
|
+
|
|
40
|
+
mask = (
|
|
41
|
+
(df['action_name'] == 'Ball receiving')
|
|
42
|
+
& (df['pos_x'] == df['pos_dest_x'].shift(1))
|
|
43
|
+
& (df['pos_y'] == df['pos_dest_y'].shift(1))
|
|
44
|
+
& (df['team_id'] == df['team_id'].shift(1))
|
|
45
|
+
& (df['player_id'] != df['player_id'].shift(1))
|
|
46
|
+
& (df['possession_number'] == df['possession_number'].shift(1))
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
idx = df[mask].index
|
|
50
|
+
remaining_idx = df.drop(idx-1).index
|
|
51
|
+
|
|
52
|
+
df.loc[remaining_idx, 'receiver_id'] = np.nan
|
|
53
|
+
df.loc[remaining_idx, 'receiver_name'] = np.nan
|
|
54
|
+
|
|
55
|
+
df = df[df['action_name'] != 'Ball receiving'].reset_index(drop=True)
|
|
56
|
+
|
|
57
|
+
return df
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def filter_data(df: pd.DataFrame) -> pd.DataFrame:
|
|
61
|
+
for column in columns:
|
|
62
|
+
if column not in df.columns:
|
|
63
|
+
df[column] = np.nan
|
|
64
|
+
|
|
65
|
+
return df[(~df['possession_number'].isna()) | (df['second'] != 0)][columns].reset_index(drop=True)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def tagging(df: pd.DataFrame) -> pd.DataFrame:
|
|
69
|
+
df = df.rename(columns={'action_name': 'sub_tags', 'action_id': 'sub_tags_ids'})
|
|
70
|
+
df['sub_tags'] = df['sub_tags'].apply(lambda x: x if isinstance(x, list) else [x])
|
|
71
|
+
df['sub_tags_ids'] = df['sub_tags_ids'].apply(
|
|
72
|
+
lambda x:
|
|
73
|
+
list(set([int(t) // 1000 for t in x]))
|
|
74
|
+
if isinstance(x, list)
|
|
75
|
+
else [int(x) // 1000]
|
|
76
|
+
)
|
|
77
|
+
df['sub_tags_ids'] = df['sub_tags_ids'].apply(lambda x: [id2type[t] for t in x])
|
|
78
|
+
df = df.rename(columns={'sub_tags_ids': 'tags'})
|
|
79
|
+
|
|
80
|
+
return df
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def processing(df: pd.DataFrame) -> pd.DataFrame:
|
|
84
|
+
df = gluing(df)
|
|
85
|
+
df = add_reciever(df)
|
|
86
|
+
df = filter_data(df)
|
|
87
|
+
df = tagging(df)
|
|
88
|
+
|
|
89
|
+
return df
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
URLs = {
|
|
2
|
+
"schedule": "http://feeds.rustatsport.ru/?tpl=35&user={user}&key={password}&team_id={team_id}&season_id={season_id}&date_start=&date_end=&format=json",
|
|
3
|
+
"events": "http://feeds.rustatsport.ru/?tpl=36&user={user}&key={password}&match_id={match_id}&start_ms=0&dl=0&lang_id=1&format=json",
|
|
4
|
+
"match_stats": "http://feeds.rustatsport.ru/?tpl=207&user={user}&key={password}&match_id={match_id}&lang_id=1&format=json",
|
|
5
|
+
"tournament_teams": "http://feeds.rustatsport.ru/?tpl=32&user={user}&key={password}&tournament_id=2&season_id={season_id}&date_start=&date_end=&lang_id=1&format=json",
|
|
6
|
+
"tracking": "https://feeds.rustatsport.ru/?tpl=274&user={user}&key={password}&match_id={match_id}&lang_id=0&format=json",
|
|
7
|
+
"player_match_stats": "http://feeds.rustatsport.ru/?tpl=227&user={user}&key={password}&match_id={match_id}&lang_id=1&format=json"
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Делайте че хотите с этим кодом.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: rustat-python-api
|
|
3
|
+
Version: 0.4.11
|
|
4
|
+
Summary: A Python wrapper for RuStat API
|
|
5
|
+
Home-page: https://github.com/dailydaniel/rustat-python-api
|
|
6
|
+
Author: Daniel Zholkovsky
|
|
7
|
+
Author-email: daniel@zholkovsky.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests==2.32.3
|
|
16
|
+
Requires-Dist: pandas==2.2.3
|
|
17
|
+
Requires-Dist: tqdm==4.66.5
|
|
18
|
+
|
|
19
|
+
# rustat-python-api
|
|
20
|
+
|
|
21
|
+
### Python wrapper for the Rustat API
|
|
22
|
+
### Example of usage:
|
|
23
|
+
0. Install the package:
|
|
24
|
+
```bash
|
|
25
|
+
pip install rustat-python-api
|
|
26
|
+
```
|
|
27
|
+
1. Usage:
|
|
28
|
+
```python
|
|
29
|
+
from rustat_python_api import RuStatParser
|
|
30
|
+
|
|
31
|
+
user = "your_login"
|
|
32
|
+
password = "your_password"
|
|
33
|
+
|
|
34
|
+
parser = RuStatParser(user, password)
|
|
35
|
+
|
|
36
|
+
info = parser.get_rpl_info()
|
|
37
|
+
keys = list(info.keys())
|
|
38
|
+
season_id, team_id = keys[-1], info[keys[-1]]["season_teams"][0]["id"]
|
|
39
|
+
|
|
40
|
+
schedule = parser.get_schedule(team_id, season_id)
|
|
41
|
+
keys = list(schedule.keys())
|
|
42
|
+
match_id = keys[-1]
|
|
43
|
+
|
|
44
|
+
events, subs = parser.get_events(match_id, process=True, return_subs=True)
|
|
45
|
+
|
|
46
|
+
stats = parser.get_match_stats(match_id)
|
|
47
|
+
|
|
48
|
+
tracking = parser.get_tracking(match_id)
|
|
49
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
rustat_python_api/__init__.py,sha256=kjE2XCKbWzIIJ__xY2aoIj5aB6um197lgMlaaZ15iJ4,108
|
|
2
|
+
rustat_python_api/config.py,sha256=eMvi1p8Cfvnbp6Cd4bBOwgehVN7thKnaQV5uzWyGZXM,1844
|
|
3
|
+
rustat_python_api/models_api.py,sha256=oHXEqeCupvZwjVEdoxf7W9LP7ELFKA8-9DuRXpQHLno,1701
|
|
4
|
+
rustat_python_api/parser.py,sha256=kCKvpHYB8eNvrq64mEpGhWdUnJN8neMBFdwMbGAKWso,6913
|
|
5
|
+
rustat_python_api/processing.py,sha256=46O7wUGv5boWf4A38zYinbtqEC7ke-BwTdEg589XQaw,2816
|
|
6
|
+
rustat_python_api/urls.py,sha256=MIUDXq5QFacyVWbrIIuMbwf-WRARsxb32kFY97zw4OQ,865
|
|
7
|
+
rustat_python_api-0.4.11.dist-info/LICENSE,sha256=4Cohqg5p6Mq1xyrzdEX8AvFSA62GSVvapEOr2xK_tgY,57
|
|
8
|
+
rustat_python_api-0.4.11.dist-info/METADATA,sha256=4a4tT5JQ7YaMkocnPZnx3GQoGEo2Swya2FS3O0qdiR0,1248
|
|
9
|
+
rustat_python_api-0.4.11.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
|
10
|
+
rustat_python_api-0.4.11.dist-info/top_level.txt,sha256=VK0hmkKZE9YThxolUcoE6JtGI67NFeKJMBLuet8kI4w,18
|
|
11
|
+
rustat_python_api-0.4.11.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rustat_python_api
|