From d99b162d3a3e67772f0816c354e689296a6605c4 Mon Sep 17 00:00:00 2001 From: Xuwznln <18435084+Xuwznln@users.noreply.github.com> Date: Sun, 28 Sep 2025 22:11:08 +0800 Subject: [PATCH] fix setup.py --- .../scripts/client_examples/simple_example.py | 1 - elevator_saga/traffic/inter_floor.json | 318 ------------------ setup.py | 4 +- simple_example.py | 142 ++++++++ test_example.py | 49 +++ 5 files changed, 193 insertions(+), 321 deletions(-) create mode 100644 simple_example.py create mode 100644 test_example.py diff --git a/elevator_saga/scripts/client_examples/simple_example.py b/elevator_saga/scripts/client_examples/simple_example.py index 89d8cc0..02b51f7 100644 --- a/elevator_saga/scripts/client_examples/simple_example.py +++ b/elevator_saga/scripts/client_examples/simple_example.py @@ -52,7 +52,6 @@ class ElevatorBusController(ElevatorController): self, tick: int, events: List[SimulationEvent], elevators: List[ProxyElevator], floors: List[ProxyFloor] ) -> None: """事件执行后的回调""" - # print(f"✅ Tick {tick}: 已处理 {len(events)} 个事件") pass def on_passenger_call(self, passenger:ProxyPassenger, floor: ProxyFloor, direction: str) -> None: diff --git a/elevator_saga/traffic/inter_floor.json b/elevator_saga/traffic/inter_floor.json index 9ea8fe9..a58f640 100644 --- a/elevator_saga/traffic/inter_floor.json +++ b/elevator_saga/traffic/inter_floor.json @@ -147,324 +147,6 @@ "origin": 5, "destination": 8, "tick": 97 - }, - { - "id": 24, - "origin": 1, - "destination": 3, - "tick": 101 - }, - { - "id": 25, - "origin": 2, - "destination": 4, - "tick": 106 - }, - { - "id": 26, - "origin": 2, - "destination": 10, - "tick": 107 - }, - { - "id": 27, - "origin": 4, - "destination": 7, - "tick": 111 - }, - { - "id": 28, - "origin": 2, - "destination": 7, - "tick": 112 - }, - { - "id": 29, - "origin": 8, - "destination": 6, - "tick": 115 - }, - { - "id": 30, - "origin": 8, - "destination": 9, - "tick": 116 - }, - { - "id": 31, - "origin": 7, - "destination": 3, - "tick": 118 - }, - { - "id": 32, - "origin": 6, - "destination": 7, - "tick": 121 - }, - { - "id": 33, - "origin": 2, - "destination": 11, - "tick": 123 - }, - { - "id": 34, - "origin": 6, - "destination": 1, - "tick": 128 - }, - { - "id": 35, - "origin": 8, - "destination": 7, - "tick": 129 - }, - { - "id": 36, - "origin": 6, - "destination": 10, - "tick": 131 - }, - { - "id": 37, - "origin": 8, - "destination": 4, - "tick": 135 - }, - { - "id": 38, - "origin": 10, - "destination": 6, - "tick": 137 - }, - { - "id": 39, - "origin": 10, - "destination": 5, - "tick": 157 - }, - { - "id": 40, - "origin": 1, - "destination": 8, - "tick": 158 - }, - { - "id": 41, - "origin": 6, - "destination": 11, - "tick": 159 - }, - { - "id": 42, - "origin": 7, - "destination": 5, - "tick": 161 - }, - { - "id": 43, - "origin": 6, - "destination": 4, - "tick": 162 - }, - { - "id": 44, - "origin": 3, - "destination": 8, - "tick": 163 - }, - { - "id": 45, - "origin": 6, - "destination": 9, - "tick": 165 - }, - { - "id": 46, - "origin": 6, - "destination": 5, - "tick": 172 - }, - { - "id": 47, - "origin": 2, - "destination": 8, - "tick": 173 - }, - { - "id": 48, - "origin": 9, - "destination": 10, - "tick": 174 - }, - { - "id": 49, - "origin": 1, - "destination": 10, - "tick": 175 - }, - { - "id": 50, - "origin": 3, - "destination": 5, - "tick": 176 - }, - { - "id": 51, - "origin": 1, - "destination": 8, - "tick": 179 - }, - { - "id": 52, - "origin": 5, - "destination": 4, - "tick": 184 - }, - { - "id": 53, - "origin": 7, - "destination": 10, - "tick": 186 - }, - { - "id": 54, - "origin": 8, - "destination": 2, - "tick": 194 - }, - { - "id": 55, - "origin": 5, - "destination": 1, - "tick": 200 - }, - { - "id": 56, - "origin": 10, - "destination": 2, - "tick": 204 - }, - { - "id": 57, - "origin": 5, - "destination": 2, - "tick": 205 - }, - { - "id": 58, - "origin": 7, - "destination": 11, - "tick": 210 - }, - { - "id": 59, - "origin": 11, - "destination": 4, - "tick": 212 - }, - { - "id": 60, - "origin": 4, - "destination": 7, - "tick": 230 - }, - { - "id": 61, - "origin": 8, - "destination": 6, - "tick": 239 - }, - { - "id": 62, - "origin": 7, - "destination": 3, - "tick": 249 - }, - { - "id": 63, - "origin": 6, - "destination": 1, - "tick": 250 - }, - { - "id": 64, - "origin": 5, - "destination": 4, - "tick": 254 - }, - { - "id": 65, - "origin": 9, - "destination": 10, - "tick": 256 - }, - { - "id": 66, - "origin": 4, - "destination": 7, - "tick": 267 - }, - { - "id": 67, - "origin": 11, - "destination": 4, - "tick": 269 - }, - { - "id": 68, - "origin": 3, - "destination": 8, - "tick": 272 - }, - { - "id": 69, - "origin": 8, - "destination": 10, - "tick": 278 - }, - { - "id": 70, - "origin": 10, - "destination": 3, - "tick": 279 - }, - { - "id": 71, - "origin": 11, - "destination": 2, - "tick": 284 - }, - { - "id": 72, - "origin": 10, - "destination": 11, - "tick": 288 - }, - { - "id": 73, - "origin": 7, - "destination": 2, - "tick": 291 - }, - { - "id": 74, - "origin": 2, - "destination": 9, - "tick": 294 - }, - { - "id": 75, - "origin": 7, - "destination": 9, - "tick": 295 - }, - { - "id": 76, - "origin": 7, - "destination": 8, - "tick": 297 } ] } \ No newline at end of file diff --git a/setup.py b/setup.py index 43ee6f4..afb503c 100644 --- a/setup.py +++ b/setup.py @@ -36,8 +36,8 @@ setup( "numpy>=1.20.0", "matplotlib>=3.5.0", "seaborn>=0.11.0", - "pandas>=1.3.0",, - "flask + "pandas>=1.3.0", + "flask" ], extras_require={ "dev": [ diff --git a/simple_example.py b/simple_example.py new file mode 100644 index 0000000..ef9071a --- /dev/null +++ b/simple_example.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +""" +公交车式电梯调度算法示例 +电梯像公交车一样运营,按固定路线循环停靠每一层 +""" +from typing import Dict, List + +from elevator_saga.client.base_controller import ElevatorController +from elevator_saga.client.proxy_models import ProxyElevator, ProxyFloor, ProxyPassenger +from elevator_saga.core.models import SimulationEvent, Direction + + +class ElevatorBusController(ElevatorController): + """ + 公交车式电梯调度算法 + 电梯像公交车一样按固定路线循环运行,在每层都停 + """ + + def __init__(self, server_url: str = "http://127.0.0.1:8000", debug: bool = False): + """初始化控制器""" + super().__init__(server_url, debug) + self.elevator_directions: Dict[int, str] = {} # 记录每个电梯的当前方向 + self.max_floor = 0 # 最大楼层数 + + def on_init(self, elevators: List[ProxyElevator], floors: List[ProxyFloor]) -> None: + """初始化公交车式电梯算法""" + print("🚌 公交车式电梯算法初始化") + print(f" 管理 {len(elevators)} 部电梯") + print(f" 服务 {len(floors)} 层楼") + # 获取最大楼层数 + self.max_floor = len(floors) - 1 + # 初始化每个电梯的方向 - 开始都向上 + for elevator in elevators: + self.elevator_directions[elevator.id] = "up" + # 简单的初始分布 - 均匀分散到不同楼层 + for i, elevator in enumerate(elevators): + # 计算目标楼层 - 均匀分布在不同楼层 + target_floor = (i * (len(floors) - 1)) // len(elevators) + # 立刻移动到目标位置并开始循环 + elevator.go_to_floor(target_floor, immediate=True) + + def on_event_execute_start( + self, tick: int, events: List[SimulationEvent], elevators: List[ProxyElevator], floors: List[ProxyFloor] + ) -> None: + """事件执行前的回调""" + print(f"Tick {tick}: 即将处理 {len(events)} 个事件 {[e.type.value for e in events]}") + for i in elevators: + print(f"\t{i.id}[{i.target_floor_direction.value},{i.current_floor_float}/{i.target_floor}]" + "👦" * len(i.passengers), end="") + print() + + def on_event_execute_end( + self, tick: int, events: List[SimulationEvent], elevators: List[ProxyElevator], floors: List[ProxyFloor] + ) -> None: + """事件执行后的回调""" + # print(f"✅ Tick {tick}: 已处理 {len(events)} 个事件") + pass + + def on_passenger_call(self, passenger:ProxyPassenger, floor: ProxyFloor, direction: str) -> None: + """ + 乘客呼叫时的回调 + 公交车模式下,电梯已经在循环运行,无需特别响应呼叫 + """ + print(f"乘客 {passenger.id} F{floor.floor} 请求 {passenger.origin} -> {passenger.destination} ({direction})") + + def on_elevator_idle(self, elevator: ProxyElevator) -> None: + """ + 电梯空闲时的回调 + 让空闲的电梯继续执行公交车循环路线,每次移动一层楼 + """ + print(f"🛑 电梯 E{elevator.id} 在 F{elevator.current_floor} 层空闲") + # 设置指示器让乘客知道电梯的行进方向 + if self.elevator_directions[elevator.id] == "down" and elevator.current_floor != 0: + elevator.go_to_floor(elevator.current_floor - 1, immediate=True) + # elevator.set_up_indicator(True) + elevator.go_to_floor(1) + # current_direction = self.elevator_directions[elevator.id] + # if current_direction == "up": + # elevator.set_up_indicator(True) + # elevator.set_down_indicator(False) + # else: + # elevator.set_up_indicator(False) + # elevator.set_down_indicator(True) + + def on_elevator_stopped(self, elevator: ProxyElevator, floor: ProxyFloor) -> None: + """ + 电梯停靠时的回调 + 公交车模式下,在每一层都停下,然后继续下一站 + 需要注意的是,stopped会比idle先触发 + """ + print(f"🛑 电梯 E{elevator.id} 停靠在 F{floor.floor}") + if self.elevator_directions[elevator.id] == "up" and elevator.current_floor == self.max_floor: + elevator.go_to_floor(elevator.current_floor - 1, immediate=True) + self.elevator_directions[elevator.id] = "down" + elif self.elevator_directions[elevator.id] == "down" and elevator.current_floor == 0: + elevator.go_to_floor(elevator.current_floor + 1, immediate=True) + self.elevator_directions[elevator.id] = "up" + elif self.elevator_directions[elevator.id] == "up": + # if elevator.id == 0: + # raise ValueError("这里故意要求0号电梯不可能触发非两端停止,通过on_elevator_approaching实现") + elevator.go_to_floor(elevator.current_floor + 1, immediate=True) + # 这里故意少写下降的情况,用于了解stopped会先于idle触发 + # elif self.elevator_directions[elevator.id] == "down": + # elevator.go_to_floor(elevator.current_floor - 1, immediate=True) + # self.elevator_directions[elevator.id] = "down" + + def on_passenger_board(self, elevator: ProxyElevator, passenger: ProxyPassenger) -> None: + """ + 乘客上梯时的回调 + 打印乘客上梯信息 + """ + print( + f" 乘客{passenger.id} E{elevator.id}⬆️ F{elevator.current_floor} -> F{passenger.destination}" + ) + + def on_passenger_alight(self, elevator: ProxyElevator, passenger: ProxyPassenger, floor: ProxyFloor) -> None: + """ + 乘客下车时的回调 + 打印乘客下车信息 + """ + print(f" 乘客{passenger.id} E{elevator.id}⬇️ F{floor.floor}") + + def on_elevator_passing_floor(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None: + """ + 电梯经过楼层时的回调 + 打印经过楼层的信息 + """ + print(f"🔄 电梯 E{elevator.id} 经过 F{floor.floor} (方向: {direction})") + + def on_elevator_approaching(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None: + """ + 电梯即将到达时的回调 (START_DOWN事件) + 电梯开始减速,即将到达目标楼层 + """ + print(f"🎯 电梯 E{elevator.id} 即将到达 F{floor.floor} (方向: {direction})") + if elevator.target_floor == floor.floor and elevator.target_floor_direction == Direction.UP: # 电梯的目标楼层就是即将停靠的楼层 + if elevator.id == 0: # 这里为了测试,让0号电梯往上一层就新加一层,上行永远不会开门 + elevator.go_to_floor(elevator.target_floor + 1, immediate=True) + print(f" 不让0号电梯上行停站,设定新目标楼层 {elevator.target_floor + 1}") + +if __name__ == "__main__": + algorithm = ElevatorBusController(debug=True) + algorithm.start() diff --git a/test_example.py b/test_example.py new file mode 100644 index 0000000..f384776 --- /dev/null +++ b/test_example.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +from typing import List + +from elevator_saga.client.base_controller import ElevatorController +from elevator_saga.client.proxy_models import ProxyElevator, ProxyFloor, ProxyPassenger +from elevator_saga.core.models import SimulationEvent, Direction + + +class TestElevatorBusController(ElevatorController): + def __init__(self): + super().__init__("http://127.0.0.1:8000", True) + + def on_init(self, elevators: List[ProxyElevator], floors: List[ProxyFloor]) -> None: + pass + + def on_event_execute_start( + self, tick: int, events: List[SimulationEvent], elevators: List[ProxyElevator], floors: List[ProxyFloor] + ) -> None: + pass + + def on_event_execute_end( + self, tick: int, events: List[SimulationEvent], elevators: List[ProxyElevator], floors: List[ProxyFloor] + ) -> None: + pass + + def on_passenger_call(self, passenger:ProxyPassenger, floor: ProxyFloor, direction: str) -> None: + pass + + def on_elevator_idle(self, elevator: ProxyElevator) -> None: + pass + + def on_elevator_stopped(self, elevator: ProxyElevator, floor: ProxyFloor) -> None: + pass + + def on_passenger_board(self, elevator: ProxyElevator, passenger: ProxyPassenger) -> None: + pass + + def on_passenger_alight(self, elevator: ProxyElevator, passenger: ProxyPassenger, floor: ProxyFloor) -> None: + pass + + def on_elevator_passing_floor(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None: + pass + + def on_elevator_approaching(self, elevator: ProxyElevator, floor: ProxyFloor, direction: str) -> None: + pass + +if __name__ == "__main__": + algorithm = TestElevatorBusController() + algorithm.start()