impectPy 2.4.4__tar.gz → 2.5.1__tar.gz

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.
Files changed (28) hide show
  1. {impectPy-2.4.4 → impectPy-2.5.1}/PKG-INFO +63 -39
  2. {impectPy-2.4.4 → impectPy-2.5.1}/README.md +62 -38
  3. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/__init__.py +2 -1
  4. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/events.py +58 -19
  5. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/helpers.py +9 -4
  6. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/impect.py +11 -5
  7. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/iteration_averages.py +22 -11
  8. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/matchsums.py +100 -10
  9. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/player_scores.py +268 -120
  10. impectPy-2.5.1/impectPy/squad_coefficients.py +135 -0
  11. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/squad_scores.py +78 -33
  12. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy.egg-info/PKG-INFO +63 -39
  13. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy.egg-info/SOURCES.txt +1 -0
  14. {impectPy-2.4.4 → impectPy-2.5.1}/setup.py +1 -1
  15. {impectPy-2.4.4 → impectPy-2.5.1}/LICENSE.md +0 -0
  16. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/access_token.py +0 -0
  17. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/config.py +0 -0
  18. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/iterations.py +0 -0
  19. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/match_info.py +0 -0
  20. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/matches.py +0 -0
  21. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/player_profile_scores.py +0 -0
  22. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/set_pieces.py +0 -0
  23. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/squad_ratings.py +0 -0
  24. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy/xml.py +0 -0
  25. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy.egg-info/dependency_links.txt +0 -0
  26. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy.egg-info/requires.txt +0 -0
  27. {impectPy-2.4.4 → impectPy-2.5.1}/impectPy.egg-info/top_level.txt +0 -0
  28. {impectPy-2.4.4 → impectPy-2.5.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: impectPy
3
- Version: 2.4.4
3
+ Version: 2.5.1
4
4
  Summary: A Python package to facilitate interaction with the Impect customer API
5
5
  Home-page: https://github.com/ImpectAPI/impectPy
6
6
  Author: Impect
@@ -16,9 +16,9 @@ Requires-Dist: numpy<2.0,>=1.24.2
16
16
 
17
17
  A package provided by: Impect GmbH
18
18
 
19
- Version: v2.4.4
19
+ Version: v2.5.1
20
20
 
21
- **Updated: June 5th 2025**
21
+ **Updated: October 17th 2025**
22
22
 
23
23
  ---
24
24
 
@@ -40,11 +40,16 @@ match and season level.
40
40
 
41
41
  ## Installation
42
42
 
43
- You can install the latest version of impectPy from
44
- [GitHub](https://github.com/) with:
43
+ You can install the latest version of impectPy from PyPi with:
45
44
 
46
- ``` cmd
47
- pip install git+https://github.com/ImpectAPI/impectPy.git@v2.4.4
45
+ ```cmd
46
+ pip install impectPy
47
+ ```
48
+
49
+ You can also install it from [GitHub](https://github.com/) with:
50
+
51
+ ```cmd
52
+ pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.1
48
53
  ```
49
54
 
50
55
  ## Usage
@@ -55,7 +60,7 @@ Before accessing any data via our API, you will need to request a bearer
55
60
  token for authorization. You can get this authorization token using the
56
61
  following code snippet:
57
62
 
58
- ``` python
63
+ ```python
59
64
  import impectPy as ip
60
65
  import pandas as pd
61
66
 
@@ -73,7 +78,7 @@ competition iterations that are enabled for your account.
73
78
 
74
79
  ### Retrieve Basic Information
75
80
 
76
- ``` python
81
+ ```python
77
82
  # get list of iterations
78
83
  iterations = ip.getIterations(token=token)
79
84
 
@@ -86,7 +91,7 @@ your sales representative. Now let’s assume you are interested in data
86
91
  for 2022/23 season of the 1. Bundesliga (iteration = 518). The following
87
92
  snippet gets you a list of matches for this iteration:
88
93
 
89
- ``` python
94
+ ```python
90
95
  # get matches for iteration
91
96
  matchplan = ip.getMatches(iteration=518, token=token)
92
97
 
@@ -105,7 +110,7 @@ as team formation, starting position and substitution data. As the functions all
105
110
  for multiple games to be requested at once, we need to wrap the matchId into a list.
106
111
  Hence, to request data for this game, run the following code snippet:
107
112
 
108
- ``` python
113
+ ```python
109
114
  # define matches to get event data for
110
115
  matches = [84344]
111
116
 
@@ -134,7 +139,7 @@ Scouting and Analysis portals. On player level, these are calculated across
134
139
  positions which is why you have to supply the function with a list of positions
135
140
  your want to retrieve data for:
136
141
 
137
- ``` python
142
+ ```python
138
143
  # define matches to get further data for
139
144
  matches = [84344]
140
145
 
@@ -166,7 +171,7 @@ the following method to do so in order to minimize the amount of
166
171
  requests sent to the API. Let’s also get the event data for the RB
167
172
  Leipzig vs FSV Mainz 05 game (matchId = 84350) from the same day:
168
173
 
169
- ``` python
174
+ ```python
170
175
  # define list of matches
171
176
  matches = [84344, 84350]
172
177
 
@@ -193,8 +198,8 @@ positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
193
198
  # get player scores and ratios for match and positions per player
194
199
  playerMatchScores = ip.getPlayerMatchScores(
195
200
  matches=matches,
196
- positions=positions,
197
- token=token
201
+ token=token,
202
+ positions=positions # optional
198
203
  )
199
204
 
200
205
  # get squad scores and ratios for match per squad
@@ -215,7 +220,7 @@ your want to retrieve data for.
215
220
  Let's assume you were interested in wing backs in the 2022/2023 Bundesliga season,
216
221
  then you could use this code snippet:
217
222
 
218
- ``` python
223
+ ```python
219
224
  # define iteration ID
220
225
  iteration = 518
221
226
 
@@ -237,8 +242,8 @@ squadIterationAverages = ip.getSquadIterationAverages(
237
242
  # get player scores and ratios for iteration and positions
238
243
  playerIterationScores = ip.getPlayerIterationScores(
239
244
  iteration=iteration,
240
- positions=positions,
241
- token=token
245
+ token=token,
246
+ positions=positions # optional
242
247
  )
243
248
 
244
249
  # get squad scores and ratios for iteration
@@ -246,9 +251,19 @@ squadIterationScores = ip.getSquadIterationScores(
246
251
  iteration=iteration,
247
252
  token=token
248
253
  )
254
+ ```
255
+
256
+ The squad rating values that you can find on the league ranking in the Scouting portal can
257
+ also be retrieved from the API. In addition, we also provide you with the more detailed squad
258
+ coefficients that can be used to make match predictions. See [this example script](https://github.com/ImpectAPI/impectPy/blob/release/examples/predict_matches.ipynb)
259
+ for further details.
249
260
 
261
+ ```python
250
262
  # get squad rating for iteration
251
- squadRatings = ip.getSquadRatings(iteration=iteration, token=token
263
+ squadRatings = ip.getSquadRatings(iteration=iteration, token=token)
264
+
265
+ # get squad coefficients for iteration
266
+ squadCoefficients = ip.getSquadCoefficients(iteration=iteration, token=token)
252
267
  ```
253
268
 
254
269
  You can now also retrieve the positional profile scores for players via our API. This
@@ -257,7 +272,7 @@ positional input that determines which matchShares to consider when computing th
257
272
  In the below example, all matchShares that a player played as either a left back or a right
258
273
  back are included for profile score calculation.
259
274
 
260
- ``` python
275
+ ```python
261
276
  # define iteration ID
262
277
  iteration = 518
263
278
 
@@ -265,7 +280,11 @@ iteration = 518
265
280
  positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
266
281
 
267
282
  # get player profile scores
268
- playerProfileScores = getPlayerProfileScores(iteration, positions, token)
283
+ playerProfileScores = ip.getPlayerProfileScores(
284
+ iteration=iteration,
285
+ positions=positions,
286
+ token=token
287
+ )
269
288
  ```
270
289
 
271
290
  Please keep in mind that Impect enforces a rate limit of 10 requests per second
@@ -292,7 +311,7 @@ please see the beginning of the [function definition](https://github.com/ImpectA
292
311
  Please make sure to only retrieve event data for
293
312
  one game at a time. Let's use the Bayern vs Dortmund game from earlier as an example:
294
313
 
295
- ``` python
314
+ ```python
296
315
  # define matchId
297
316
  matches = [84344]
298
317
 
@@ -374,51 +393,56 @@ positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
374
393
  iterations = api.getIterations()
375
394
 
376
395
  # get squad ratings
377
- ratings = api.getSquadRatings(iteration)
396
+ ratings = api.getSquadRatings(iteration=iteration)
397
+
398
+ # get squad coefficients
399
+ coefficients = api.getSquadCoefficients(iteration=iteration)
378
400
 
379
401
  # get matches
380
- matchplan = api.getMatches(iteration)
402
+ matchplan = api.getMatches(iteration=iteration)
381
403
 
382
404
  # get match info
383
- formations = api.getFormations(matches)
384
- substitutions = api.getSubstitutions(matches)
385
- startingPositions = api.getStartingPositions(matches)
405
+ formations = api.getFormations(matches=matches)
406
+ substitutions = api.getSubstitutions(matches=matches)
407
+ startingPositions = api.getStartingPositions(matches=matches)
386
408
 
387
409
  # get match events
388
- events = api.getEvents(matches, include_kpis=True, include_set_pieces=True)
410
+ events = api.getEvents(matches=matches, include_kpis=False, include_set_pieces=False)
389
411
 
390
412
  # get set pieces
391
- setPieces = api.getSetPieces(matches)
413
+ set_pieces = api.getSetPieces(matches=matches)
392
414
 
393
415
  # get player iteration averages
394
- playerIterationAverages = api.getPlayerIterationAverages(iteration)
416
+ playerIterationAverages = api.getPlayerIterationAverages(iteration=iteration)
395
417
 
396
418
  # get player matchsums
397
- playerMatchsums = api.getPlayerMatchsums(matches)
419
+ playerMatchsums = api.getPlayerMatchsums(matches=matches)
398
420
 
399
421
  # get squad iteration averages
400
- squadIterationAverages = api.getSquadIterationAverages(iteration)
422
+ squadIterationAverages = api.getSquadIterationAverages(iteration=iteration)
401
423
 
402
424
  # get squad matchsums
403
- squadMatchsums = api.getSquadMatchsums(matches)
425
+ squadMatchsums = api.getSquadMatchsums(matches=matches)
404
426
 
405
427
  # get player match scores
406
- playerMatchScores = api.getPlayerMatchScores(matches, positions)
428
+ playerMatchScores = api.getPlayerMatchScores(matches=matches, positions=positions) # specific positions
429
+ playerMatchScoresAll = api.getPlayerMatchScores(matches=matches) # all positions
407
430
 
408
431
  # get squad match scores
409
- squadMatchScores = api.getSquadMatchScores(matches)
432
+ squadMatchScores = api.getSquadMatchScores(matches=matches)
410
433
 
411
434
  # get player iteration scores
412
- playerIterationScores = api.getPlayerIterationScores(iteration, positions)
435
+ playerIterationScores = api.getPlayerIterationScores(iteration=iteration, positions=positions) # specific positions
436
+ playerIterationScoresAll = api.getPlayerIterationScores(iteration=iteration) # all positions
413
437
 
414
438
  # get squad iteration scores
415
- squadIterationScores = api.getSquadIterationScores(iteration)
439
+ squadIterationScores = api.getSquadIterationScores(iteration=iteration)
416
440
 
417
441
  # get player profile scores
418
- playerProfileScores = api.getPlayerProfileScores(iteration, positions)
442
+ playerProfileScores = api.getPlayerProfileScores(iteration=iteration, positions=positions)
419
443
  ```
420
444
 
421
445
  ## Final Notes
422
446
 
423
447
  Further documentation on the data and explanations of variables can be
424
- found in our [glossary](https://glossary.impect.com/).
448
+ found in our [Glossary](https://glossary.impect.com/).
@@ -2,9 +2,9 @@
2
2
 
3
3
  A package provided by: Impect GmbH
4
4
 
5
- Version: v2.4.4
5
+ Version: v2.5.1
6
6
 
7
- **Updated: June 5th 2025**
7
+ **Updated: October 17th 2025**
8
8
 
9
9
  ---
10
10
 
@@ -26,11 +26,16 @@ match and season level.
26
26
 
27
27
  ## Installation
28
28
 
29
- You can install the latest version of impectPy from
30
- [GitHub](https://github.com/) with:
29
+ You can install the latest version of impectPy from PyPi with:
31
30
 
32
- ``` cmd
33
- pip install git+https://github.com/ImpectAPI/impectPy.git@v2.4.4
31
+ ```cmd
32
+ pip install impectPy
33
+ ```
34
+
35
+ You can also install it from [GitHub](https://github.com/) with:
36
+
37
+ ```cmd
38
+ pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.1
34
39
  ```
35
40
 
36
41
  ## Usage
@@ -41,7 +46,7 @@ Before accessing any data via our API, you will need to request a bearer
41
46
  token for authorization. You can get this authorization token using the
42
47
  following code snippet:
43
48
 
44
- ``` python
49
+ ```python
45
50
  import impectPy as ip
46
51
  import pandas as pd
47
52
 
@@ -59,7 +64,7 @@ competition iterations that are enabled for your account.
59
64
 
60
65
  ### Retrieve Basic Information
61
66
 
62
- ``` python
67
+ ```python
63
68
  # get list of iterations
64
69
  iterations = ip.getIterations(token=token)
65
70
 
@@ -72,7 +77,7 @@ your sales representative. Now let’s assume you are interested in data
72
77
  for 2022/23 season of the 1. Bundesliga (iteration = 518). The following
73
78
  snippet gets you a list of matches for this iteration:
74
79
 
75
- ``` python
80
+ ```python
76
81
  # get matches for iteration
77
82
  matchplan = ip.getMatches(iteration=518, token=token)
78
83
 
@@ -91,7 +96,7 @@ as team formation, starting position and substitution data. As the functions all
91
96
  for multiple games to be requested at once, we need to wrap the matchId into a list.
92
97
  Hence, to request data for this game, run the following code snippet:
93
98
 
94
- ``` python
99
+ ```python
95
100
  # define matches to get event data for
96
101
  matches = [84344]
97
102
 
@@ -120,7 +125,7 @@ Scouting and Analysis portals. On player level, these are calculated across
120
125
  positions which is why you have to supply the function with a list of positions
121
126
  your want to retrieve data for:
122
127
 
123
- ``` python
128
+ ```python
124
129
  # define matches to get further data for
125
130
  matches = [84344]
126
131
 
@@ -152,7 +157,7 @@ the following method to do so in order to minimize the amount of
152
157
  requests sent to the API. Let’s also get the event data for the RB
153
158
  Leipzig vs FSV Mainz 05 game (matchId = 84350) from the same day:
154
159
 
155
- ``` python
160
+ ```python
156
161
  # define list of matches
157
162
  matches = [84344, 84350]
158
163
 
@@ -179,8 +184,8 @@ positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
179
184
  # get player scores and ratios for match and positions per player
180
185
  playerMatchScores = ip.getPlayerMatchScores(
181
186
  matches=matches,
182
- positions=positions,
183
- token=token
187
+ token=token,
188
+ positions=positions # optional
184
189
  )
185
190
 
186
191
  # get squad scores and ratios for match per squad
@@ -201,7 +206,7 @@ your want to retrieve data for.
201
206
  Let's assume you were interested in wing backs in the 2022/2023 Bundesliga season,
202
207
  then you could use this code snippet:
203
208
 
204
- ``` python
209
+ ```python
205
210
  # define iteration ID
206
211
  iteration = 518
207
212
 
@@ -223,8 +228,8 @@ squadIterationAverages = ip.getSquadIterationAverages(
223
228
  # get player scores and ratios for iteration and positions
224
229
  playerIterationScores = ip.getPlayerIterationScores(
225
230
  iteration=iteration,
226
- positions=positions,
227
- token=token
231
+ token=token,
232
+ positions=positions # optional
228
233
  )
229
234
 
230
235
  # get squad scores and ratios for iteration
@@ -232,9 +237,19 @@ squadIterationScores = ip.getSquadIterationScores(
232
237
  iteration=iteration,
233
238
  token=token
234
239
  )
240
+ ```
241
+
242
+ The squad rating values that you can find on the league ranking in the Scouting portal can
243
+ also be retrieved from the API. In addition, we also provide you with the more detailed squad
244
+ coefficients that can be used to make match predictions. See [this example script](https://github.com/ImpectAPI/impectPy/blob/release/examples/predict_matches.ipynb)
245
+ for further details.
235
246
 
247
+ ```python
236
248
  # get squad rating for iteration
237
- squadRatings = ip.getSquadRatings(iteration=iteration, token=token
249
+ squadRatings = ip.getSquadRatings(iteration=iteration, token=token)
250
+
251
+ # get squad coefficients for iteration
252
+ squadCoefficients = ip.getSquadCoefficients(iteration=iteration, token=token)
238
253
  ```
239
254
 
240
255
  You can now also retrieve the positional profile scores for players via our API. This
@@ -243,7 +258,7 @@ positional input that determines which matchShares to consider when computing th
243
258
  In the below example, all matchShares that a player played as either a left back or a right
244
259
  back are included for profile score calculation.
245
260
 
246
- ``` python
261
+ ```python
247
262
  # define iteration ID
248
263
  iteration = 518
249
264
 
@@ -251,7 +266,11 @@ iteration = 518
251
266
  positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
252
267
 
253
268
  # get player profile scores
254
- playerProfileScores = getPlayerProfileScores(iteration, positions, token)
269
+ playerProfileScores = ip.getPlayerProfileScores(
270
+ iteration=iteration,
271
+ positions=positions,
272
+ token=token
273
+ )
255
274
  ```
256
275
 
257
276
  Please keep in mind that Impect enforces a rate limit of 10 requests per second
@@ -278,7 +297,7 @@ please see the beginning of the [function definition](https://github.com/ImpectA
278
297
  Please make sure to only retrieve event data for
279
298
  one game at a time. Let's use the Bayern vs Dortmund game from earlier as an example:
280
299
 
281
- ``` python
300
+ ```python
282
301
  # define matchId
283
302
  matches = [84344]
284
303
 
@@ -360,51 +379,56 @@ positions = ["LEFT_WINGBACK_DEFENDER", "RIGHT_WINGBACK_DEFENDER"]
360
379
  iterations = api.getIterations()
361
380
 
362
381
  # get squad ratings
363
- ratings = api.getSquadRatings(iteration)
382
+ ratings = api.getSquadRatings(iteration=iteration)
383
+
384
+ # get squad coefficients
385
+ coefficients = api.getSquadCoefficients(iteration=iteration)
364
386
 
365
387
  # get matches
366
- matchplan = api.getMatches(iteration)
388
+ matchplan = api.getMatches(iteration=iteration)
367
389
 
368
390
  # get match info
369
- formations = api.getFormations(matches)
370
- substitutions = api.getSubstitutions(matches)
371
- startingPositions = api.getStartingPositions(matches)
391
+ formations = api.getFormations(matches=matches)
392
+ substitutions = api.getSubstitutions(matches=matches)
393
+ startingPositions = api.getStartingPositions(matches=matches)
372
394
 
373
395
  # get match events
374
- events = api.getEvents(matches, include_kpis=True, include_set_pieces=True)
396
+ events = api.getEvents(matches=matches, include_kpis=False, include_set_pieces=False)
375
397
 
376
398
  # get set pieces
377
- setPieces = api.getSetPieces(matches)
399
+ set_pieces = api.getSetPieces(matches=matches)
378
400
 
379
401
  # get player iteration averages
380
- playerIterationAverages = api.getPlayerIterationAverages(iteration)
402
+ playerIterationAverages = api.getPlayerIterationAverages(iteration=iteration)
381
403
 
382
404
  # get player matchsums
383
- playerMatchsums = api.getPlayerMatchsums(matches)
405
+ playerMatchsums = api.getPlayerMatchsums(matches=matches)
384
406
 
385
407
  # get squad iteration averages
386
- squadIterationAverages = api.getSquadIterationAverages(iteration)
408
+ squadIterationAverages = api.getSquadIterationAverages(iteration=iteration)
387
409
 
388
410
  # get squad matchsums
389
- squadMatchsums = api.getSquadMatchsums(matches)
411
+ squadMatchsums = api.getSquadMatchsums(matches=matches)
390
412
 
391
413
  # get player match scores
392
- playerMatchScores = api.getPlayerMatchScores(matches, positions)
414
+ playerMatchScores = api.getPlayerMatchScores(matches=matches, positions=positions) # specific positions
415
+ playerMatchScoresAll = api.getPlayerMatchScores(matches=matches) # all positions
393
416
 
394
417
  # get squad match scores
395
- squadMatchScores = api.getSquadMatchScores(matches)
418
+ squadMatchScores = api.getSquadMatchScores(matches=matches)
396
419
 
397
420
  # get player iteration scores
398
- playerIterationScores = api.getPlayerIterationScores(iteration, positions)
421
+ playerIterationScores = api.getPlayerIterationScores(iteration=iteration, positions=positions) # specific positions
422
+ playerIterationScoresAll = api.getPlayerIterationScores(iteration=iteration) # all positions
399
423
 
400
424
  # get squad iteration scores
401
- squadIterationScores = api.getSquadIterationScores(iteration)
425
+ squadIterationScores = api.getSquadIterationScores(iteration=iteration)
402
426
 
403
427
  # get player profile scores
404
- playerProfileScores = api.getPlayerProfileScores(iteration, positions)
428
+ playerProfileScores = api.getPlayerProfileScores(iteration=iteration, positions=positions)
405
429
  ```
406
430
 
407
431
  ## Final Notes
408
432
 
409
433
  Further documentation on the data and explanations of variables can be
410
- found in our [glossary](https://glossary.impect.com/).
434
+ found in our [Glossary](https://glossary.impect.com/).
@@ -1,5 +1,5 @@
1
1
  # define version attribute
2
- __version__ = "2.4.4"
2
+ __version__ = "2.5.1"
3
3
 
4
4
  # import modules
5
5
  from .access_token import getAccessToken
@@ -14,6 +14,7 @@ from .player_profile_scores import getPlayerProfileScores
14
14
  from .xml import generateXML
15
15
  from .set_pieces import getSetPieces
16
16
  from .squad_ratings import getSquadRatings
17
+ from .squad_coefficients import getSquadCoefficients
17
18
  from .match_info import getFormations, getSubstitutions, getStartingPositions
18
19
  from .config import Config as Config
19
20
  from .impect import Impect as Impect
@@ -2,10 +2,10 @@
2
2
  import numpy as np
3
3
  import pandas as pd
4
4
  import requests
5
- from impectPy.helpers import RateLimitedAPI
5
+ import re
6
+ from impectPy.helpers import RateLimitedAPI, ForbiddenError
6
7
  from .matches import getMatchesFromHost
7
8
  from .iterations import getIterationsFromHost
8
- import re
9
9
 
10
10
  ######
11
11
  #
@@ -38,18 +38,18 @@ def getEventsFromHost(
38
38
  raise Exception("Argument 'matches' must be a list of integers.")
39
39
 
40
40
  # get match info
41
- iterations = pd.concat(
41
+ match_data = pd.concat(
42
42
  map(lambda match: connection.make_api_request_limited(
43
43
  url=f"{host}/v5/customerapi/matches/{match}",
44
44
  method="GET"
45
45
  ).process_response(
46
- endpoint="Iterations"
46
+ endpoint="Match Info"
47
47
  ),
48
48
  matches),
49
49
  ignore_index=True)
50
50
 
51
51
  # filter for matches that are unavailable
52
- fail_matches = iterations[iterations.lastCalculationDate.isnull()].id.drop_duplicates().to_list()
52
+ fail_matches = match_data[match_data.lastCalculationDate.isnull()].id.drop_duplicates().to_list()
53
53
 
54
54
  # drop matches that are unavailable from list of matches
55
55
  matches = [match for match in matches if match not in fail_matches]
@@ -62,7 +62,7 @@ def getEventsFromHost(
62
62
  print(f"The following matches are not available yet and were ignored:\n{fail_matches}")
63
63
 
64
64
  # extract iterationIds
65
- iterations = list(iterations[iterations.lastCalculationDate.notnull()].iterationId.unique())
65
+ iterations = list(match_data[match_data.lastCalculationDate.notnull()].iterationId.unique())
66
66
 
67
67
  # get match events
68
68
  events = pd.concat(
@@ -118,6 +118,25 @@ def getEventsFromHost(
118
118
  iterations),
119
119
  ignore_index=True)[["id", "name"]].drop_duplicates()
120
120
 
121
+ # get coaches
122
+ coaches_blacklisted = False
123
+ try:
124
+ coaches = pd.concat(
125
+ map(lambda iteration: connection.make_api_request_limited(
126
+ url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
127
+ method="GET"
128
+ ).process_response(
129
+ endpoint="Coaches",
130
+ raise_exception=False
131
+ ),
132
+ iterations),
133
+ ignore_index=True)[["id", "name"]].drop_duplicates()
134
+ except KeyError:
135
+ # no coaches found, create empty df
136
+ coaches = pd.DataFrame(columns=["id", "name"])
137
+ except ForbiddenError:
138
+ coaches_blacklisted = True
139
+
121
140
  # get matches
122
141
  matchplan = pd.concat(
123
142
  map(lambda iteration: getMatchesFromHost(
@@ -188,7 +207,7 @@ def getEventsFromHost(
188
207
 
189
208
  # start merging dfs
190
209
 
191
- # merge events with squads
210
+ # merge events with secondary data
192
211
  events = events.merge(
193
212
  squads[["id", "name"]].rename(columns={"id": "squadId", "name": "squadName"}),
194
213
  left_on="squadId",
@@ -201,10 +220,7 @@ def getEventsFromHost(
201
220
  right_on="squadId",
202
221
  how="left",
203
222
  suffixes=("", "_away")
204
- )
205
-
206
- # merge events with players
207
- events = events.merge(
223
+ ).merge(
208
224
  players[["id", "commonname"]].rename(columns={"id": "playerId", "commonname": "playerName"}),
209
225
  left_on="playerId",
210
226
  right_on="playerId",
@@ -243,19 +259,20 @@ def getEventsFromHost(
243
259
  right_on="dribbleOpponentPlayerId",
244
260
  how="left",
245
261
  suffixes=("", "_right")
246
- )
247
-
248
- # merge with matches info
249
- events = events.merge(
262
+ ).merge(
250
263
  matchplan,
251
264
  left_on="matchId",
252
265
  right_on="id",
253
266
  how="left",
254
267
  suffixes=("", "_right")
255
- )
256
-
257
- # merge with competition info
258
- events = events.merge(
268
+ ).merge(
269
+ match_data[["id", "squadHomeCoachId", "squadAwayCoachId"]].rename(
270
+ columns={"squadHomeCoachId": "homeSquadCoachId", "squadAwayCoachId": "awaySquadCoachId"}),
271
+ left_on="matchId",
272
+ right_on="id",
273
+ how="left",
274
+ suffixes=("", "_right")
275
+ ).merge(
259
276
  iterations,
260
277
  left_on="iterationId",
261
278
  right_on="id",
@@ -263,6 +280,21 @@ def getEventsFromHost(
263
280
  suffixes=("", "_right")
264
281
  )
265
282
 
283
+ if not coaches_blacklisted:
284
+ events = events.merge(
285
+ coaches[["id", "name"]].rename(columns={"id": "homeCoachId", "name": "homeCoachName"}),
286
+ left_on="homeSquadCoachId",
287
+ right_on="homeCoachId",
288
+ how="left",
289
+ suffixes=("", "_right")
290
+ ).merge(
291
+ coaches[["id", "name"]].rename(columns={"id": "awayCoachId", "name": "awayCoachName"}),
292
+ left_on="awaySquadCoachId",
293
+ right_on="awayCoachId",
294
+ how="left",
295
+ suffixes=("", "_right")
296
+ )
297
+
266
298
  if include_kpis:
267
299
  # unnest scorings and full join with kpi list to ensure all kpis are present
268
300
  scorings = scorings.merge(kpis, left_on="kpiId", right_on="id", how="outer") \
@@ -374,12 +406,16 @@ def getEventsFromHost(
374
406
  "homeSquadName",
375
407
  "homeSquadCountryId",
376
408
  "homeSquadCountryName",
409
+ "homeCoachId",
410
+ "homeCoachName",
377
411
  "homeSquadType",
378
412
  "awaySquadId",
379
413
  "awaySquadName",
380
414
  "awaySquadCountryId",
381
415
  "awaySquadCountryName",
382
416
  "awaySquadType",
417
+ "awayCoachId",
418
+ "awayCoachName",
383
419
  "eventId",
384
420
  "eventNumber",
385
421
  "sequenceIndex",
@@ -506,6 +542,9 @@ def getEventsFromHost(
506
542
  # add kpis
507
543
  order = order + kpi_cols
508
544
 
545
+ if coaches_blacklisted:
546
+ order = [col for col in order if col not in ["homeCoachId", "homeCoachName", "awayCoachId", "awayCoachName"]]
547
+
509
548
  # reorder data
510
549
  events = events[order]
511
550