"""
ElevatorPanel.py - Elevator panels (interior and hall)
Implements SOLID: Single Responsibility (panel management only)
Interface Segregation (minimal panel interfaces)
"""
from typing import List, Callable, Optional
from Button import Button, ElevatorButton, HallButton, DoorOpenButton, DoorCloseButton, EmergencyButton, AlarmButton
from Direction import Direction
class BasePanel:
"""
Base class for all panels.
SOLID: Single Responsibility - manages buttons only
"""
def __init__(self, panel_id: int = 0):
"""Initialize base panel."""
self.panel_id = panel_id
self.buttons: List[Button] = []
def add_button(self, button: Button) -> None:
"""Add button to panel."""
if button not in self.buttons:
self.buttons.append(button)
def get_buttons(self) -> List[Button]:
"""Get all buttons."""
return self.buttons.copy()
def get_pressed_buttons(self) -> List[Button]:
"""Get all currently pressed buttons."""
return [btn for btn in self.buttons if btn.is_pressed()]
def press_button(self, button_index: int) -> bool:
"""
Press button at index.
Args:
button_index: Index of button to press
Returns:
True if button was pressed successfully
"""
if 0 <= button_index < len(self.buttons):
self.buttons[button_index].press()
return True
return False
def release_all(self) -> None:
"""Release all buttons."""
for button in self.buttons:
button.release()
def __str__(self) -> str:
return f"{self.__class__.__name__}(id={self.panel_id}, buttons={len(self.buttons)})"
class ElevatorPanel(BasePanel):
"""
Panel inside an elevator car with floor buttons and controls.
Buttons:
- Floor buttons (0 to N-1): Select destination floor
- Open door button: Manual door open
- Close door button: Manual door close
- Emergency button: Emergency stop
- Alarm button: Sound alarm
SOLID: Single Responsibility - manages interior car controls only
"""
def __init__(self, car_id: int, num_floors: int):
"""
Initialize elevator panel.
Args:
car_id: ID of elevator this panel belongs to
num_floors: Number of floors in building
"""
super().__init__(panel_id=car_id)
self.car_id = car_id
self.num_floors = num_floors
# Floor buttons
self.floor_buttons: List[ElevatorButton] = []
for floor in range(num_floors):
btn = ElevatorButton(floor)
self.floor_buttons.append(btn)
self.add_button(btn)
# Control buttons
self.open_button = DoorOpenButton()
self.close_button = DoorCloseButton()
self.emergency_button = EmergencyButton()
self.alarm_button = AlarmButton()
self.add_button(self.open_button)
self.add_button(self.close_button)
self.add_button(self.emergency_button)
self.add_button(self.alarm_button)
def press_floor_button(self, floor: int) -> bool:
"""
Press button for specific floor.
Args:
floor: Floor number (0 to num_floors-1)
Returns:
True if pressed successfully
"""
if 0 <= floor < len(self.floor_buttons):
self.floor_buttons[floor].press()
return True
return False
def get_selected_floors(self) -> List[int]:
"""Get list of currently selected floors."""
return [btn.get_destination_floor() for btn in self.floor_buttons if btn.is_pressed()]
def press_emergency(self) -> bool:
"""Press emergency button."""
self.emergency_button.press()
return self.emergency_button.is_pressed()
def press_open_door(self) -> bool:
"""Press open door button."""
self.open_button.press()
return self.open_button.is_pressed()
def press_close_door(self) -> bool:
"""Press close door button."""
self.close_button.press()
return self.close_button.is_pressed()
def press_alarm(self) -> bool:
"""Press alarm button."""
self.alarm_button.press()
return self.alarm_button.is_pressed()
def register_floor_request_callback(self, floor: int, callback: Callable) -> None:
"""
Register callback for floor button press.
Args:
floor: Floor number
callback: Function to call when button pressed
"""
if 0 <= floor < len(self.floor_buttons):
self.floor_buttons[floor]._action = callback
def __str__(self) -> str:
return f"ElevatorPanel(car_id={self.car_id}, floors={self.num_floors})"
class HallPanel(BasePanel):
"""
Panel on a floor in the hallway for calling elevator.
Buttons:
- Up button: Call elevator going UP (if not top floor)
- Down button: Call elevator going DOWN (if not ground floor)
SOLID: Single Responsibility - manages hall floor controls only
"""
def __init__(self, floor: int, num_floors: int):
"""
Initialize hall panel.
Args:
floor: Which floor this panel is on
num_floors: Total floors in building
"""
super().__init__(panel_id=floor)
self.floor = floor
self.num_floors = num_floors
self.up_button: Optional[HallButton] = None
self.down_button: Optional[HallButton] = None
# Create appropriate buttons based on floor location
if floor < num_floors - 1: # Not top floor
self.up_button = HallButton(floor, Direction.UP)
self.add_button(self.up_button)
if floor > 0: # Not ground floor
self.down_button = HallButton(floor, Direction.DOWN)
self.add_button(self.down_button)
def press_up(self) -> bool:
"""
Press up button.
Returns:
True if button exists and was pressed
"""
if self.up_button:
self.up_button.press()
return True
return False
def press_down(self) -> bool:
"""
Press down button.
Returns:
True if button exists and was pressed
"""
if self.down_button:
self.down_button.press()
return True
return False
def register_up_callback(self, callback: Callable) -> None:
"""Register callback for up button."""
if self.up_button:
self.up_button._action = callback
def register_down_callback(self, callback: Callable) -> None:
"""Register callback for down button."""
if self.down_button:
self.down_button._action = callback
def has_up_button(self) -> bool:
"""Check if this floor has up button."""
return self.up_button is not None
def has_down_button(self) -> bool:
"""Check if this floor has down button."""
return self.down_button is not None
def get_call_direction(self) -> Optional[Direction]:
"""Get direction if either button is pressed."""
if self.up_button and self.up_button.is_pressed():
return Direction.UP
if self.down_button and self.down_button.is_pressed():
return Direction.DOWN
return None
def __str__(self) -> str:
buttons = []
if self.up_button:
buttons.append("UP")
if self.down_button:
buttons.append("DOWN")
return f"HallPanel(floor={self.floor}, buttons={buttons})"
class Floor:
"""
Represents a floor with a hall panel.
SOLID: Single Responsibility - manages floor-level controls
"""
def __init__(self, floor_number: int, num_floors: int):
"""
Initialize floor.
Args:
floor_number: Floor number (0 to num_floors-1)
num_floors: Total floors in building
"""
self.floor_number = floor_number
self.hall_panel = HallPanel(floor_number, num_floors)
def call_up(self, callback: Callable) -> bool:
"""
Call elevator to go up.
Args:
callback: Function to call when button pressed
Returns:
True if successful
"""
if self.hall_panel.has_up_button():
self.hall_panel.register_up_callback(callback)
self.hall_panel.press_up()
return True
return False
def call_down(self, callback: Callable) -> bool:
"""
Call elevator to go down.
Args:
callback: Function to call when button pressed
Returns:
True if successful
"""
if self.hall_panel.has_down_button():
self.hall_panel.register_down_callback(callback)
self.hall_panel.press_down()
return True
return False
def get_panel(self) -> HallPanel:
"""Get hall panel."""
return self.hall_panel
def __str__(self) -> str:
return f"Floor({self.floor_number})"