Skip to content

Commit

Permalink
Merge pull request #343 from my-game-plan/bugfix/wyscout-blocked-cross
Browse files Browse the repository at this point in the history
[Wyscout v3] fix location for blocked crosses
  • Loading branch information
koenvo authored Oct 23, 2024
2 parents 9063cbc + 198c64b commit a2112f8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 9 deletions.
31 changes: 25 additions & 6 deletions kloppy/infra/serializers/event/wyscout/deserializer_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@
}


def _flip_point(point: Point) -> Point:
return Point(x=100 - point.x, y=100 - point.y)


def _parse_team(raw_events, wyId: str, ground: Ground) -> Team:
team = Team(
team_id=wyId,
Expand Down Expand Up @@ -177,6 +181,13 @@ def _pass_qualifiers(raw_event) -> List[Qualifier]:
def _parse_pass(raw_event: Dict, next_event: Dict, team: Team) -> Dict:
pass_result = None
receiver_player = None
if len(raw_event["pass"]["endLocation"]) > 1:
receiver_coordinates = Point(
x=float(raw_event["pass"]["endLocation"]["x"]),
y=float(raw_event["pass"]["endLocation"]["y"]),
)
else:
receiver_coordinates = None

if raw_event["pass"]["accurate"] is True:
pass_result = PassResult.COMPLETE
Expand All @@ -186,24 +197,32 @@ def _parse_pass(raw_event: Dict, next_event: Dict, team: Team) -> Dict:
elif raw_event["pass"]["accurate"] is False:
pass_result = PassResult.INCOMPLETE

if raw_event["pass"].get("height") == "blocked":
receiver_coordinates = None

if next_event:
if next_event["type"]["primary"] == "offside":
pass_result = PassResult.OFFSIDE
if next_event["type"]["primary"] == "game_interruption":
if "ball_out" in next_event["type"]["secondary"]:
pass_result = PassResult.OUT
# Set end coordinates of blocked pass to start coordinates of next event if it is not a game interruption
if raw_event["pass"].get("height") == "blocked":
next_event_location = Point(
x=float(next_event["location"]["x"]),
y=float(next_event["location"]["y"]),
)
if team.team_id == str(next_event["team"]["id"]):
receiver_coordinates = next_event_location
else:
receiver_coordinates = _flip_point(next_event_location)

return {
"result": pass_result,
"qualifiers": _pass_qualifiers(raw_event),
"receive_timestamp": None,
"receiver_player": receiver_player,
"receiver_coordinates": Point(
x=float(raw_event["pass"]["endLocation"]["x"]),
y=float(raw_event["pass"]["endLocation"]["y"]),
)
if len(raw_event["pass"]["endLocation"]) > 1
else None,
"receiver_coordinates": receiver_coordinates,
}


Expand Down
7 changes: 4 additions & 3 deletions kloppy/tests/files/wyscout_events_v3.json
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,12 @@
"name": "Torino"
},
"pass": {
"accurate": true,
"accurate": false,
"height": "blocked",
"angle": -105,
"endLocation": {
"x": 18,
"y": 23
"x": 0,
"y": 0
},
"length": 20.41,
"recipient": {
Expand Down
12 changes: 12 additions & 0 deletions kloppy/tests/test_wyscout.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
CardQualifier,
CardType,
Orientation,
PassResult,
FormationType,
Time,
)
Expand Down Expand Up @@ -242,6 +243,17 @@ def test_normalized_deserialization(self, event_v3_data: Path):
0.36417591801878735, 0.7695098039215686
)

def test_pass_event(self, dataset: EventDataset):
pass_event = dataset.get_event_by_id(663292348)
assert pass_event.event_type == EventType.PASS
assert pass_event.coordinates == Point(x=52.0, y=47.0)
assert pass_event.receiver_coordinates == Point(x=60.0, y=32.0)

blocked_pass_event = dataset.get_event_by_id(663291838)
assert blocked_pass_event.result == PassResult.INCOMPLETE
assert blocked_pass_event.coordinates == Point(x=23.0, y=52.0)
assert blocked_pass_event.receiver_coordinates == Point(x=100.0, y=0.0)

def test_goalkeeper_event(self, dataset: EventDataset):
goalkeeper_event = dataset.get_event_by_id(1331979498)
assert goalkeeper_event.event_type == EventType.GOALKEEPER
Expand Down

0 comments on commit a2112f8

Please sign in to comment.