megadicing / core /step.py
gloygum
Initial megadicing space
35465a0
Raw
History Blame Contribute Delete
5.21 kB
# -*- coding: utf-8 -*-
from core.kick_off_event import KickOffEvent
class Step:
"""Represents a single replay step, potentially containing major events."""
def __init__(self, step_number=None, game_turn=None, team0_score=0, team1_score=0, active_team_id=None):
self.step_number = step_number # Sequential replay step counter
self.game_turn = game_turn # GameTurn value from replay
self.team0_score = team0_score
self.team1_score = team1_score
self.active_team_id = active_team_id # 0 or 1, from PlayerStep
self.turn_owner_team_id = None
self.kick_off = None # KickOffEvent if one occurred in this step
self.touchdown = None # Touchdown details if one occurred in this step
self.weather = None # Weather snapshot after this step, if known
self.roll_events = [] # All non-kickoff dice roll events found in this step
self.explicit_turn_end = False # True when replay emitted EventEndTurn in this step
self.end_turn_reason = None # Replay EventEndTurn.Reason
self.end_turn_type = None # Replay EventEndTurn.FinishingTurnType
self.next_active_team_id = None # Replay next active gamer, when explicit
self.acting_player_id = None # Replay-resolved acting player for this step
self.acting_player_name = None
self.acting_player_team_id = None
def has_kick_off(self):
"""Check if this step has a kickoff event."""
return self.kick_off is not None
def set_kick_off(self, kick_off_event):
"""Set the kickoff event for this step."""
if isinstance(kick_off_event, KickOffEvent):
self.kick_off = kick_off_event
else:
raise ValueError("kick_off_event must be a KickOffEvent instance")
def has_touchdown(self):
"""Check if this step records a touchdown."""
return self.touchdown is not None
def set_touchdown(self, player_id, player_name, team_id):
"""Store touchdown details for this step."""
self.touchdown = {
'player_id': player_id,
'player_name': player_name,
'team_id': team_id,
}
def set_weather(self, weather):
"""Store weather snapshot for this step."""
if isinstance(weather, dict) or weather is None:
self.weather = weather
else:
raise ValueError("weather must be a dict or None")
def add_roll_event(self, roll_event):
"""Add a parsed dice roll event for this step."""
if isinstance(roll_event, dict):
self.roll_events.append(roll_event)
else:
raise ValueError("roll_event must be a dict")
def set_turn_boundary(self, explicit_turn_end=False, end_turn_reason=None, end_turn_type=None, next_active_team_id=None):
"""Store explicit turn-boundary metadata extracted from replay events."""
self.explicit_turn_end = bool(explicit_turn_end)
self.end_turn_reason = end_turn_reason
self.end_turn_type = end_turn_type
self.next_active_team_id = next_active_team_id
def set_turn_owner(self, team_id):
"""Store canonical team-turn ownership for this step."""
self.turn_owner_team_id = team_id
def set_acting_player(self, player_id=None, player_name=None, team_id=None):
"""Store replay-resolved acting player metadata for this step."""
self.acting_player_id = player_id
self.acting_player_name = player_name
self.acting_player_team_id = team_id
def __repr__(self) -> str:
kick_off_str = f", KickOff: {self.kick_off}" if self.kick_off else ""
touchdown_str = f", Touchdown: {self.touchdown}" if self.touchdown else ""
weather_str = f", Weather: {self.weather}" if self.weather else ""
turn_end_str = ""
if self.explicit_turn_end:
turn_end_str = (
f", TurnEnd(reason={self.end_turn_reason}, type={self.end_turn_type}, "
f"next={self.next_active_team_id})"
)
return f"Step(#{self.step_number}, GameTurn={self.game_turn}, Team{self.active_team_id} active, Score {self.team0_score}-{self.team1_score}{kick_off_str}{touchdown_str}{weather_str}{turn_end_str})"
def to_dict(self):
return {
'step_number': self.step_number,
'game_turn': self.game_turn,
'team0_score': self.team0_score,
'team1_score': self.team1_score,
'active_team_id': self.active_team_id,
'turn_owner_team_id': self.turn_owner_team_id,
'kick_off': self.kick_off.to_dict() if self.kick_off else None,
'touchdown': self.touchdown,
'weather': self.weather,
'roll_events': self.roll_events,
'explicit_turn_end': self.explicit_turn_end,
'end_turn_reason': self.end_turn_reason,
'end_turn_type': self.end_turn_type,
'next_active_team_id': self.next_active_team_id,
'acting_player_id': self.acting_player_id,
'acting_player_name': self.acting_player_name,
'acting_player_team_id': self.acting_player_team_id,
}