-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* merge_model_to_master * pr before develop * refactor: only keep eventframe related codes * feat: impl event controller * chore: rename event_frame to event_controller --------- Co-authored-by: zyr17 <[email protected]>
- Loading branch information
1 parent
3be319f
commit c4222b7
Showing
4 changed files
with
183 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import logging | ||
from typing import Any, List | ||
|
||
from .consts import ObjectPositionType | ||
from .event import EventArguments | ||
from .action import Actions | ||
from .struct import ObjectPosition | ||
from ..utils import BaseModel | ||
|
||
|
||
class EventFrame(BaseModel): | ||
""" | ||
Event frame is a frame of events, contains events with their arguments, the | ||
object lists that will be triggered by the event arguments, and the | ||
action lists that has triggered. | ||
When one action is done, it will generate a new event frame, with various | ||
number of events, and append it to the event frame list. When there are | ||
events and no processing objects and actions, the first event will | ||
trigger objects. When there are triggered objects, the first object | ||
position will be popped and trigger actions. When there are triggered | ||
actions, the first action will be popped and trigger events, then add | ||
a new event frame. If an event frame has no events, no triggered objects | ||
and no triggered actions, it will be removed from the list. | ||
""" | ||
|
||
events: List[EventArguments] | ||
processing_event: EventArguments | None = None | ||
triggered_objects: List[ObjectPosition] = [] | ||
triggered_actions: List[Actions] = [] | ||
|
||
|
||
class EventController(BaseModel): | ||
frame_list: List[EventFrame] = [] | ||
|
||
def has_event(self) -> bool: | ||
return len(self.frame_list) != 0 | ||
|
||
def append(self, event_frame: EventFrame) -> None: | ||
self.frame_list.append(event_frame) | ||
|
||
def pop(self) -> EventFrame: | ||
""" | ||
pop and return last event frame. | ||
""" | ||
return self.frame_list.pop() | ||
|
||
def run_event_frame(self, match: Any) -> None: | ||
""" | ||
run the event frame. if last event frame contains actions, do actions and | ||
return; otherwise, | ||
trigger next object; otherwise, trigger next event; otherwise, pop last frame; | ||
otherwise, clear trashbin and done triggering. | ||
When any actions has done, or no valid event frame exist, return. | ||
""" | ||
while len(self.frame_list): | ||
event_frame = self.frame_list[-1] | ||
if len(event_frame.triggered_actions): | ||
self.act_action(event_frame, match) | ||
return | ||
elif len(event_frame.triggered_objects): | ||
self.get_action(event_frame, match) | ||
elif len(event_frame.events): | ||
self.trigger_event(event_frame, match) | ||
else: | ||
self.pop() | ||
# event frame cleared, clear trashbin | ||
match.trashbin.clear() | ||
|
||
def act_action(self, frame: EventFrame, match: Any) -> None: | ||
""" | ||
Act the actions. If these actions are triggered by one object (i.e., | ||
event_frame.processing_event is not None), do all actions immediately; | ||
otherwise, actions are generated by system, and only do one action. | ||
""" | ||
if frame.processing_event is None: | ||
# do one action | ||
activated_action = frame.triggered_actions.pop(0) | ||
logging.info(f"Action activated: {activated_action}") | ||
event_args = match._act(activated_action) | ||
match.record_last_action_history() | ||
self.stack_events(event_args) | ||
else: | ||
# do all actions | ||
event_args = [] | ||
for activated_action in frame.triggered_actions: | ||
logging.info(f"Action activated: {activated_action}") | ||
event_args += match._act(activated_action) | ||
match.record_last_action_history() | ||
frame.triggered_actions = [] | ||
self.stack_events(event_args) | ||
|
||
def get_action(self, frame: EventFrame, match: Any) -> None: | ||
""" | ||
Get actions from triggered objects. | ||
""" | ||
event_arg = frame.processing_event | ||
assert event_arg is not None | ||
object_position = frame.triggered_objects.pop(0) | ||
obj = match.get_object(object_position, event_arg.type) | ||
handler_name = f"event_handler_{event_arg.type.name}" | ||
func = getattr(obj, handler_name, None) | ||
if func is not None: | ||
frame.triggered_actions = func(event_arg, match) | ||
self.frame_list[-1] = frame | ||
|
||
def trigger_event(self, event_frame: EventFrame, match: Any) -> None: | ||
""" | ||
trigger new event to update triggered object lists of a EventFrame. | ||
it will take first event from events, put it into processing_event, | ||
and update triggered object lists. | ||
""" | ||
event_arg = event_frame.events.pop(0) | ||
event_frame.processing_event = event_arg | ||
object_list = match.get_object_list() | ||
# add object in trashbin to list | ||
for obj in match.trashbin: | ||
if event_arg.type in obj.available_handler_in_trashbin: | ||
object_list.append(obj) | ||
handler_name = f"event_handler_{event_arg.type.name}" | ||
for obj in object_list: | ||
# for deck objects, check availability | ||
if obj.position.area == ObjectPositionType.DECK: | ||
if event_arg.type not in obj.available_handler_in_deck: | ||
continue | ||
func = getattr(obj, handler_name, None) | ||
if func is not None: | ||
event_frame.triggered_objects.append(obj.position) | ||
|
||
def stack_event(self, event_arg: EventArguments) -> EventFrame: | ||
""" | ||
stack a new event. It will wrap it into a list and call | ||
self.stack_events. | ||
""" | ||
return self.stack_events([event_arg]) | ||
|
||
def stack_actions(self, actions: List[Actions]) -> EventFrame: | ||
""" | ||
stack new actions, these actions are not triggered by any object, so when any | ||
action in it is triggered, its event will be triggered immediately. | ||
""" | ||
event_frame = EventFrame(events=[], triggered_actions=actions) | ||
self.frame_list.append(event_frame) | ||
return event_frame | ||
|
||
def stack_events(self, event_args: List[EventArguments]) -> EventFrame: | ||
""" | ||
stack events. It will create a new EventFrame with events and | ||
append it into self.event_frames. Then it will return the event frame. | ||
""" | ||
frame = EventFrame( | ||
events=event_args, | ||
) | ||
self.frame_list.append(frame) | ||
return frame |
Oops, something went wrong.