mirror of
https://github.com/ZGCA-Forge/Elevator.git
synced 2025-12-17 13:01:03 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b60359894 | ||
|
|
0157496e6f | ||
|
|
1031e677e1 | ||
|
|
889d554f19 | ||
|
|
ee3c4bab7e | ||
|
|
99524eee3d |
@@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.0.5
|
current_version = 0.0.8
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
tag_name = v{new_version}
|
tag_name = v{new_version}
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ The controller provides these event handlers:
|
|||||||
- ``on_passenger_alight(elevator, passenger, floor)``: Passenger alights
|
- ``on_passenger_alight(elevator, passenger, floor)``: Passenger alights
|
||||||
- ``on_elevator_passing_floor(elevator, floor, direction)``: Elevator passes floor
|
- ``on_elevator_passing_floor(elevator, floor, direction)``: Elevator passes floor
|
||||||
- ``on_elevator_approaching(elevator, floor, direction)``: Elevator about to arrive
|
- ``on_elevator_approaching(elevator, floor, direction)``: Elevator about to arrive
|
||||||
|
- ``on_elevator_move(elevator, from_position, to_position, direction, status)``: Elevator moves
|
||||||
|
|
||||||
Complete Example
|
Complete Example
|
||||||
----------------
|
----------------
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ Event System
|
|||||||
Event Types
|
Event Types
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
The simulation generates 8 types of events defined in ``EventType`` enum:
|
The simulation generates 9 types of events defined in ``EventType`` enum:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -215,6 +215,7 @@ The simulation generates 8 types of events defined in ``EventType`` enum:
|
|||||||
IDLE = "idle"
|
IDLE = "idle"
|
||||||
PASSENGER_BOARD = "passenger_board"
|
PASSENGER_BOARD = "passenger_board"
|
||||||
PASSENGER_ALIGHT = "passenger_alight"
|
PASSENGER_ALIGHT = "passenger_alight"
|
||||||
|
ELEVATOR_MOVE = "elevator_move"
|
||||||
|
|
||||||
Event Generation
|
Event Generation
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
@@ -260,6 +261,19 @@ Events are generated during tick processing:
|
|||||||
for elevator in self.elevators:
|
for elevator in self.elevators:
|
||||||
# ... movement logic ...
|
# ... movement logic ...
|
||||||
|
|
||||||
|
# Elevator moves
|
||||||
|
if elevator.target_floor_direction != Direction.STOPPED:
|
||||||
|
self._emit_event(
|
||||||
|
EventType.ELEVATOR_MOVE,
|
||||||
|
{
|
||||||
|
"elevator": elevator.id,
|
||||||
|
"from_position": old_position,
|
||||||
|
"to_position": elevator.position.current_floor_float,
|
||||||
|
"direction": elevator.target_floor_direction.value,
|
||||||
|
"status": elevator.run_status.value,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Passing a floor
|
# Passing a floor
|
||||||
if old_floor != new_floor and new_floor != target_floor:
|
if old_floor != new_floor and new_floor != target_floor:
|
||||||
self._emit_event(
|
self._emit_event(
|
||||||
@@ -363,6 +377,14 @@ The ``ElevatorController`` base class automatically routes events to handler met
|
|||||||
elevator = self.elevators[event.data["elevator"]]
|
elevator = self.elevators[event.data["elevator"]]
|
||||||
self.on_elevator_idle(elevator)
|
self.on_elevator_idle(elevator)
|
||||||
|
|
||||||
|
elif event.type == EventType.ELEVATOR_MOVE:
|
||||||
|
elevator = self.elevators[event.data["elevator"]]
|
||||||
|
from_position = event.data["from_position"]
|
||||||
|
to_position = event.data["to_position"]
|
||||||
|
direction = event.data["direction"]
|
||||||
|
status = event.data["status"]
|
||||||
|
self.on_elevator_move(elevator, from_position, to_position, direction, status)
|
||||||
|
|
||||||
# ... other event types ...
|
# ... other event types ...
|
||||||
|
|
||||||
Control Flow: Bus Example
|
Control Flow: Bus Example
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ A Python implementation of the Elevator Saga game with event-driven architecture
|
|||||||
realistic elevator dispatch algorithm development and testing.
|
realistic elevator dispatch algorithm development and testing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.0.5"
|
__version__ = "0.0.8"
|
||||||
__author__ = "ZGCA Team"
|
__author__ = "ZGCA Team"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from elevator_saga.client.api_client import ElevatorAPIClient
|
from elevator_saga.client.api_client import ElevatorAPIClient
|
||||||
from elevator_saga.client.proxy_models import ProxyElevator, ProxyFloor, ProxyPassenger
|
from elevator_saga.client.proxy_models import ProxyElevator, ProxyFloor, ProxyPassenger
|
||||||
@@ -171,6 +171,22 @@ class ElevatorController(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# @abstractmethod 为了兼容性暂不强制要求elevator_move必须实现
|
||||||
|
def on_elevator_move(
|
||||||
|
self, elevator: ProxyElevator, from_position: float, to_position: float, direction: str, status: str
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
电梯移动时的回调 - 可选实现
|
||||||
|
|
||||||
|
Args:
|
||||||
|
elevator: 电梯代理对象
|
||||||
|
from_position: 起始位置(浮点数表示楼层)
|
||||||
|
to_position: 目标位置(浮点数表示楼层)
|
||||||
|
direction: 移动方向
|
||||||
|
status: 电梯运行状态
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def _internal_init(self, elevators: List[Any], floors: List[Any]) -> None:
|
def _internal_init(self, elevators: List[Any], floors: List[Any]) -> None:
|
||||||
"""内部初始化方法"""
|
"""内部初始化方法"""
|
||||||
self.elevators = elevators
|
self.elevators = elevators
|
||||||
@@ -218,7 +234,7 @@ class ElevatorController(ABC):
|
|||||||
# 获取初始状态并初始化,默认从0开始
|
# 获取初始状态并初始化,默认从0开始
|
||||||
try:
|
try:
|
||||||
state = self.api_client.get_state()
|
state = self.api_client.get_state()
|
||||||
except ConnectionResetError as ex:
|
except ConnectionResetError as _: # noqa: F841
|
||||||
print(f"模拟器可能并没有开启,请检查模拟器是否启动 {self.api_client.base_url}")
|
print(f"模拟器可能并没有开启,请检查模拟器是否启动 {self.api_client.base_url}")
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
if state.tick > 0:
|
if state.tick > 0:
|
||||||
@@ -381,6 +397,22 @@ class ElevatorController(ABC):
|
|||||||
floor_proxy = ProxyFloor(floor_id, self.api_client)
|
floor_proxy = ProxyFloor(floor_id, self.api_client)
|
||||||
self.on_passenger_alight(elevator_proxy, passenger_proxy, floor_proxy)
|
self.on_passenger_alight(elevator_proxy, passenger_proxy, floor_proxy)
|
||||||
|
|
||||||
|
elif event.type == EventType.ELEVATOR_MOVE:
|
||||||
|
elevator_id = event.data.get("elevator")
|
||||||
|
from_position = event.data.get("from_position")
|
||||||
|
to_position = event.data.get("to_position")
|
||||||
|
direction = event.data.get("direction")
|
||||||
|
status = event.data.get("status")
|
||||||
|
if (
|
||||||
|
elevator_id is not None
|
||||||
|
and from_position is not None
|
||||||
|
and to_position is not None
|
||||||
|
and direction is not None
|
||||||
|
and status is not None
|
||||||
|
):
|
||||||
|
elevator_proxy = ProxyElevator(elevator_id, self.api_client)
|
||||||
|
self.on_elevator_move(elevator_proxy, from_position, to_position, direction, status)
|
||||||
|
|
||||||
def _reset_and_reinit(self) -> None:
|
def _reset_and_reinit(self) -> None:
|
||||||
"""重置并重新初始化"""
|
"""重置并重新初始化"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ class ElevatorBusExampleController(ElevatorController):
|
|||||||
def on_elevator_approaching(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None:
|
def on_elevator_approaching(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def on_elevator_move(
|
||||||
|
self, elevator: ProxyElevator, from_position: float, to_position: float, direction: str, status: str
|
||||||
|
) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
algorithm = ElevatorBusExampleController()
|
algorithm = ElevatorBusExampleController()
|
||||||
|
|||||||
@@ -139,6 +139,17 @@ class ElevatorBusController(ElevatorController):
|
|||||||
elevator.go_to_floor(elevator.target_floor + 1, immediate=True)
|
elevator.go_to_floor(elevator.target_floor + 1, immediate=True)
|
||||||
print(f" 不让0号电梯上行停站,设定新目标楼层 {elevator.target_floor + 1}")
|
print(f" 不让0号电梯上行停站,设定新目标楼层 {elevator.target_floor + 1}")
|
||||||
|
|
||||||
|
def on_elevator_move(
|
||||||
|
self, elevator: ProxyElevator, from_position: float, to_position: float, direction: str, status: str
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
电梯移动时的回调
|
||||||
|
可以在这里记录电梯移动信息,用于调试或性能分析
|
||||||
|
"""
|
||||||
|
# 取消注释以显示电梯移动信息
|
||||||
|
# print(f"🚀 电梯 E{elevator.id} 移动: {from_position:.1f} -> {to_position:.1f} ({direction}, {status})")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
algorithm = ElevatorBusController(debug=True)
|
algorithm = ElevatorBusController(debug=True)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import uuid
|
|||||||
from dataclasses import asdict, dataclass, field
|
from dataclasses import asdict, dataclass, field
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union
|
from typing import Any, Dict, List, Optional, Tuple, Type, TypeVar, Union
|
||||||
|
|
||||||
# 类型变量
|
# 类型变量
|
||||||
T = TypeVar("T", bound="SerializableModel")
|
T = TypeVar("T", bound="SerializableModel")
|
||||||
@@ -55,6 +55,7 @@ class EventType(Enum):
|
|||||||
IDLE = "idle"
|
IDLE = "idle"
|
||||||
PASSENGER_BOARD = "passenger_board"
|
PASSENGER_BOARD = "passenger_board"
|
||||||
PASSENGER_ALIGHT = "passenger_alight"
|
PASSENGER_ALIGHT = "passenger_alight"
|
||||||
|
ELEVATOR_MOVE = "elevator_move" # 电梯移动事件
|
||||||
|
|
||||||
|
|
||||||
class SerializableModel:
|
class SerializableModel:
|
||||||
@@ -113,7 +114,7 @@ class Position(SerializableModel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def current_floor_float(self) -> float:
|
def current_floor_float(self) -> float:
|
||||||
return self.current_floor + self.floor_up_position / 10
|
return round(self.current_floor + self.floor_up_position / 10, 1)
|
||||||
|
|
||||||
def floor_up_position_add(self, num: int) -> int:
|
def floor_up_position_add(self, num: int) -> int:
|
||||||
self.floor_up_position += num
|
self.floor_up_position += num
|
||||||
@@ -161,12 +162,13 @@ class PassengerInfo(SerializableModel):
|
|||||||
arrive_tick: int
|
arrive_tick: int
|
||||||
pickup_tick: int = 0
|
pickup_tick: int = 0
|
||||||
dropoff_tick: int = 0
|
dropoff_tick: int = 0
|
||||||
|
arrived: bool = False
|
||||||
elevator_id: Optional[int] = None
|
elevator_id: Optional[int] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self) -> PassengerStatus:
|
def status(self) -> PassengerStatus:
|
||||||
"""乘客状态"""
|
"""乘客状态"""
|
||||||
if self.dropoff_tick > 0:
|
if self.arrived:
|
||||||
return PassengerStatus.COMPLETED
|
return PassengerStatus.COMPLETED
|
||||||
elif self.pickup_tick > 0:
|
elif self.pickup_tick > 0:
|
||||||
return PassengerStatus.IN_ELEVATOR
|
return PassengerStatus.IN_ELEVATOR
|
||||||
|
|||||||
@@ -138,6 +138,17 @@ class ElevatorBusController(ElevatorController):
|
|||||||
elevator.go_to_floor(elevator.target_floor + 1, immediate=True)
|
elevator.go_to_floor(elevator.target_floor + 1, immediate=True)
|
||||||
print(f" 不让0号电梯上行停站,设定新目标楼层 {elevator.target_floor + 1}")
|
print(f" 不让0号电梯上行停站,设定新目标楼层 {elevator.target_floor + 1}")
|
||||||
|
|
||||||
|
def on_elevator_move(
|
||||||
|
self, elevator: ProxyElevator, from_position: float, to_position: float, direction: str, status: str
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
电梯移动时的回调
|
||||||
|
可以在这里记录电梯移动信息,用于调试或性能分析
|
||||||
|
"""
|
||||||
|
# 取消注释以显示电梯移动信息
|
||||||
|
# print(f"🚀 电梯 E{elevator.id} 移动: {from_position:.1f} -> {to_position:.1f} ({direction}, {status})")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
algorithm = ElevatorBusController(debug=True)
|
algorithm = ElevatorBusController(debug=True)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import threading
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, cast
|
from typing import Any, Dict, List, cast
|
||||||
|
|
||||||
from flask import Flask, Response, request
|
from flask import Flask, Response, request
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ class ElevatorSimulation:
|
|||||||
# 2. Move elevators
|
# 2. Move elevators
|
||||||
self._move_elevators()
|
self._move_elevators()
|
||||||
|
|
||||||
# 3. Process elevator stops and passenger boarding/alighting
|
# 3. Process elevator stops and passenger alighting
|
||||||
self._process_elevator_stops()
|
self._process_elevator_stops()
|
||||||
|
|
||||||
# Return events generated this tick
|
# Return events generated this tick
|
||||||
@@ -310,7 +310,6 @@ class ElevatorSimulation:
|
|||||||
def _update_elevator_status(self) -> None:
|
def _update_elevator_status(self) -> None:
|
||||||
"""更新电梯运行状态"""
|
"""更新电梯运行状态"""
|
||||||
for elevator in self.elevators:
|
for elevator in self.elevators:
|
||||||
current_floor = elevator.position.current_floor
|
|
||||||
target_floor = elevator.target_floor
|
target_floor = elevator.target_floor
|
||||||
old_status = elevator.run_status.value
|
old_status = elevator.run_status.value
|
||||||
# 没有移动方向,说明电梯已经到达目标楼层
|
# 没有移动方向,说明电梯已经到达目标楼层
|
||||||
@@ -378,6 +377,7 @@ class ElevatorSimulation:
|
|||||||
|
|
||||||
# 根据状态和方向调整移动距离
|
# 根据状态和方向调整移动距离
|
||||||
elevator.last_tick_direction = elevator.target_floor_direction
|
elevator.last_tick_direction = elevator.target_floor_direction
|
||||||
|
old_position = elevator.position.current_floor_float
|
||||||
if elevator.target_floor_direction == Direction.UP:
|
if elevator.target_floor_direction == Direction.UP:
|
||||||
new_floor = elevator.position.floor_up_position_add(movement_speed)
|
new_floor = elevator.position.floor_up_position_add(movement_speed)
|
||||||
elif elevator.target_floor_direction == Direction.DOWN:
|
elif elevator.target_floor_direction == Direction.DOWN:
|
||||||
@@ -386,6 +386,19 @@ class ElevatorSimulation:
|
|||||||
# 之前的状态已经是到站了,清空上一次到站的方向
|
# 之前的状态已经是到站了,清空上一次到站的方向
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# 发送电梯移动事件
|
||||||
|
if elevator.target_floor_direction != Direction.STOPPED:
|
||||||
|
self._emit_event(
|
||||||
|
EventType.ELEVATOR_MOVE,
|
||||||
|
{
|
||||||
|
"elevator": elevator.id,
|
||||||
|
"from_position": old_position,
|
||||||
|
"to_position": elevator.position.current_floor_float,
|
||||||
|
"direction": elevator.target_floor_direction.value,
|
||||||
|
"status": elevator.run_status.value,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
# 移动后检测是否即将到站,从匀速状态切换到减速
|
# 移动后检测是否即将到站,从匀速状态切换到减速
|
||||||
if elevator.run_status == ElevatorStatus.CONSTANT_SPEED:
|
if elevator.run_status == ElevatorStatus.CONSTANT_SPEED:
|
||||||
# 检查是否需要开始减速,这里加速减速设置路程为1,匀速路程为2,这样能够保证不会匀速恰好到达,必须加减速
|
# 检查是否需要开始减速,这里加速减速设置路程为1,匀速路程为2,这样能够保证不会匀速恰好到达,必须加减速
|
||||||
@@ -444,6 +457,7 @@ class ElevatorSimulation:
|
|||||||
passenger = self.passengers[passenger_id]
|
passenger = self.passengers[passenger_id]
|
||||||
if passenger.destination == current_floor:
|
if passenger.destination == current_floor:
|
||||||
passenger.dropoff_tick = self.tick
|
passenger.dropoff_tick = self.tick
|
||||||
|
passenger.arrived = True
|
||||||
passengers_to_remove.append(passenger_id)
|
passengers_to_remove.append(passenger_id)
|
||||||
|
|
||||||
# Remove passengers who alighted
|
# Remove passengers who alighted
|
||||||
@@ -465,7 +479,6 @@ class ElevatorSimulation:
|
|||||||
[SERVER-DEBUG] 电梯 E0 被设定为前往 F1
|
[SERVER-DEBUG] 电梯 E0 被设定为前往 F1
|
||||||
说明电梯处于stop状态,这个tick直接采用下一个目的地运行了
|
说明电梯处于stop状态,这个tick直接采用下一个目的地运行了
|
||||||
"""
|
"""
|
||||||
original_target_floor = elevator.target_floor
|
|
||||||
elevator.position.target_floor = floor
|
elevator.position.target_floor = floor
|
||||||
server_debug_log(f"电梯 E{elevator.id} 被设定为前往 F{floor}")
|
server_debug_log(f"电梯 E{elevator.id} 被设定为前往 F{floor}")
|
||||||
new_target_floor_should_accel = self._should_start_deceleration(elevator)
|
new_target_floor_should_accel = self._should_start_deceleration(elevator)
|
||||||
|
|||||||
Reference in New Issue
Block a user