Skip to content

Commit

Permalink
Merge pull request #75 from bdagnino/improved-sequences
Browse files Browse the repository at this point in the history
Improve sequence definition based on latest added generic events
  • Loading branch information
koenvo authored Nov 17, 2020
2 parents e9478da + 23a7820 commit 14c3b8e
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 14 deletions.
9 changes: 8 additions & 1 deletion kloppy/domain/services/state_builder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ def add_state(dataset: EventDataset, *builder_keys: List[str]) -> EventDataset:

events = []
for event in dataset.events:

state = {
builder_key: builder.reduce_before(state[builder_key], event)
for builder_key, builder in builders.items()
}

events.append(replace(event, state=state))

state = {
builder_key: builder.reduce(state[builder_key], event)
builder_key: builder.reduce_after(state[builder_key], event)
for builder_key, builder in builders.items()
}

Expand Down
6 changes: 5 additions & 1 deletion kloppy/domain/services/state_builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ def initial_state(self, dataset: EventDataset) -> T:
pass

@abstractmethod
def reduce(self, state: T, event: Event) -> T:
def reduce_before(self, state: T, event: Event) -> T:
pass

@abstractmethod
def reduce_after(self, state: T, event: Event) -> T:
pass
5 changes: 4 additions & 1 deletion kloppy/domain/services/state_builder/builders/lineup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ def initial_state(self, dataset: EventDataset) -> Lineup:
)
)

def reduce(self, state: Lineup, event: Event) -> Lineup:
def reduce_before(self, state: Lineup, event: Event) -> Lineup:
return state

def reduce_after(self, state: Lineup, event: Event) -> Lineup:
if isinstance(event, SubstitutionEvent):
state = Lineup(
players=state.players - {event.player}
Expand Down
5 changes: 4 additions & 1 deletion kloppy/domain/services/state_builder/builders/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ class ScoreStateBuilder(StateBuilder):
def initial_state(self, dataset: EventDataset) -> Score:
return Score(home=0, away=0)

def reduce(self, state: Score, event: Event) -> Score:
def reduce_before(self, state: Score, event: Event) -> Score:
return state

def reduce_after(self, state: Score, event: Event) -> Score:
if isinstance(event, ShotEvent):
if event.result == ShotResult.GOAL:
if event.team.ground == Ground.HOME:
Expand Down
31 changes: 27 additions & 4 deletions kloppy/domain/services/state_builder/builders/sequence.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
from dataclasses import replace, dataclass

from kloppy.domain import Event, Team, EventDataset, PassEvent
from kloppy.domain import (
Event,
Team,
EventDataset,
PassEvent,
CarryEvent,
RecoveryEvent,
BallOutEvent,
FoulCommittedEvent,
ShotEvent,
)
from ..builder import StateBuilder

OPEN_SEQUENCE = (PassEvent, CarryEvent, RecoveryEvent)
CLOSE_SEQUENCE = (BallOutEvent, FoulCommittedEvent, ShotEvent)


@dataclass
class Sequence:
Expand All @@ -13,13 +26,23 @@ class Sequence:
class SequenceStateBuilder(StateBuilder):
def initial_state(self, dataset: EventDataset) -> Sequence:
for event in dataset.events:
if isinstance(event, PassEvent):
if isinstance(event, OPEN_SEQUENCE):
return Sequence(sequence_id=0, team=event.team)
return Sequence(sequence_id=0, team=None)

def reduce(self, state: Sequence, event: Event) -> Sequence:
if state.team != event.team:
def reduce_before(self, state: Sequence, event: Event) -> Sequence:
if isinstance(event, OPEN_SEQUENCE) and state.team != event.team:
state = replace(
state, sequence_id=state.sequence_id + 1, team=event.team
)

return state

def reduce_after(self, state: Sequence, event: Event) -> Sequence:

if isinstance(event, CLOSE_SEQUENCE):
state = replace(
state, sequence_id=state.sequence_id + 1, team=None
)

return state
32 changes: 26 additions & 6 deletions kloppy/tests/test_state_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_score_state_builder(self):
dataset = self._load_dataset()

with performance_logging("add_state"):
dataset_with_state = add_state(dataset, ["score", "sequence"])
dataset_with_state = add_state(dataset, ["score"])

events_per_score = {}
for score, events in groupby(
Expand All @@ -44,6 +44,23 @@ def test_score_state_builder(self):
"3-0": 3,
}

def test_sequence_state_builder(self):
dataset = self._load_dataset()

with performance_logging("add_state"):
dataset_with_state = add_state(dataset, ["sequence"])

events_per_sequence = {}
for sequence_id, events in groupby(
dataset_with_state.events,
lambda event: event.state["sequence"].sequence_id,
):
events = list(events)
events_per_sequence[sequence_id] = len(events)

assert events_per_sequence[0] == 9
assert events_per_sequence[50] == 2

def test_lineup_state_builder(self):
dataset = self._load_dataset("statsbomb_15986")

Expand Down Expand Up @@ -74,15 +91,18 @@ class CustomStateBuilder(StateBuilder):
def initial_state(self, dataset: EventDataset) -> int:
return 0

def reduce(self, state: int, event: Event) -> int:
def reduce_before(self, state: int, event: Event) -> int:
return state + 1

def reduce_after(self, state: int, event: Event) -> int:
return state + 1

dataset = self._load_dataset("statsbomb_15986")

with performance_logging("add_state"):
dataset_with_state = add_state(dataset, ["custom"])

assert dataset_with_state.events[0].state["custom"] == 0
assert dataset_with_state.events[1].state["custom"] == 1
assert dataset_with_state.events[2].state["custom"] == 2
assert dataset_with_state.events[3].state["custom"] == 3
assert dataset_with_state.events[0].state["custom"] == 1
assert dataset_with_state.events[1].state["custom"] == 3
assert dataset_with_state.events[2].state["custom"] == 5
assert dataset_with_state.events[3].state["custom"] == 7

0 comments on commit 14c3b8e

Please sign in to comment.