Загрузка данных
from datetime import datetime
from typing import List, Optional
class Dimensions:
def __init__(self, length: float, width: float, height: float):
self.length = length
self.width = width
self.height = height
class IStorageUnit:
def store(self, parcel) -> bool: pass
def remove(self, tracking_number: str): pass
def can_store(self, parcel) -> bool: pass
class Parcel:
def __init__(self, tracking_number: str, weight: float, dimensions: Dimensions):
self.tracking_number = tracking_number
self.weight = weight
self.dimensions = dimensions
class Human:
def __init__(self, name: str, passport: str):
self.name = name
self.passport = passport
class Employee(Human):
def __init__(self, name: str, passport: str, stress_level: int = 50):
super().__init__(name, passport)
self.stress_level = stress_level
class FrozenParcel(Parcel):
def __init__(self, tracking_number: str, weight: float, dimensions: Dimensions, temperature: float = -18):
super().__init__(tracking_number, weight, dimensions)
self.temperature = temperature
class FragileParcel(Parcel):
pass
class Shelf(IStorageUnit):
def __init__(self, capacity: float, shelf_id: int):
self.capacity = capacity
self.shelf_id = shelf_id
self.current_load = 0.0
self.parcels = []
def can_store(self, parcel: Parcel) -> bool:
if isinstance(parcel, FrozenParcel):
return False
return self.current_load + parcel.weight <= self.capacity
def store(self, parcel: Parcel) -> bool:
if self.can_store(parcel):
self.parcels.append(parcel)
self.current_load += parcel.weight
return True
return False
def remove(self, tracking_number: str):
for i, p in enumerate(self.parcels):
if p.tracking_number == tracking_number:
self.current_load -= p.weight
return self.parcels.pop(i)
return None
class Fridge(IStorageUnit):
def __init__(self, capacity: float, fridge_id: int, temperature: float = -18):
self.capacity = capacity
self.fridge_id = fridge_id
self.current_load = 0.0
self.parcels = []
def can_store(self, parcel: Parcel) -> bool:
if not isinstance(parcel, FrozenParcel):
return False
return self.current_load + parcel.weight <= self.capacity
def store(self, parcel: Parcel) -> bool:
if self.can_store(parcel):
self.parcels.append(parcel)
self.current_load += parcel.weight
return True
return False
def remove(self, tracking_number: str):
for i, p in enumerate(self.parcels):
if p.tracking_number == tracking_number:
self.current_load -= p.weight
return self.parcels.pop(i)
return None
class FloorCorner(IStorageUnit):
def __init__(self, max_weight: float, corner_id: int):
self.max_weight = max_weight
self.current_weight = 0.0
self.parcels = []
self.corner_id = corner_id
def can_store(self, parcel: Parcel) -> bool:
return self.current_weight + parcel.weight <= self.max_weight
def store(self, parcel: Parcel) -> bool:
if self.can_store(parcel):
self.parcels.append(parcel)
self.current_weight += parcel.weight
return True
return False
def remove(self, tracking_number: str):
for i, p in enumerate(self.parcels):
if p.tracking_number == tracking_number:
self.current_weight -= p.weight
return self.parcels.pop(i)
return None
class ActionLogger:
def __init__(self):
self.logs = []
def log(self, actor: str, action: str, details: str = ""):
timestamp = datetime.now().strftime("[%H:%M:%S]")
entry = f"{timestamp} {actor}: {action}"
if details:
entry += f" ({details})"
self.logs.append(entry)
def get_logs(self):
return self.logs
class PickupPoint:
def __init__(self, address: str, employee: Employee):
self.address = address
self.employee = employee
self.shelves = []
self.fridges = []
self.floor_corners = []
self.logger = ActionLogger()
self.logger.log(employee.name, "открыл ПВЗ", f"по адресу {address}")
def add_shelf(self, capacity: float) -> int:
shelf_id = len(self.shelves) + 1
self.shelves.append(Shelf(capacity, shelf_id))
self.logger.log(self.employee.name, "добавил полку", f"вместимость {capacity} кг")
return shelf_id
def add_fridge(self, capacity: float, temperature: float = -18) -> int:
fridge_id = len(self.fridges) + 1
self.fridges.append(Fridge(capacity, fridge_id, temperature))
return fridge_id
def add_floor_corner(self, max_weight: float) -> int:
corner_id = len(self.floor_corners) + 1
self.floor_corners.append(FloorCorner(max_weight, corner_id))
return corner_id
def receive_parcel(self, courier: Human, parcel: Parcel) -> bool:
self.logger.log(courier.name, "принял посылку", parcel.tracking_number)
storage = None
storage_type = ""
storage_id = None
if isinstance(parcel, FrozenParcel):
for f in self.fridges:
if f.can_store(parcel):
storage, storage_type, storage_id = f, "холодильник", f.fridge_id
break
elif isinstance(parcel, FragileParcel):
for s in self.shelves:
if s.can_store(parcel) and len(s.parcels) == 0:
storage, storage_type, storage_id = s, "полку", s.shelf_id
break
if not storage:
for c in self.floor_corners:
if c.can_store(parcel):
storage, storage_type, storage_id = c, "угол", c.corner_id
break
else:
for s in self.shelves:
if s.can_store(parcel):
storage, storage_type, storage_id = s, "полку", s.shelf_id
break
if not storage:
for c in self.floor_corners:
if c.can_store(parcel):
storage, storage_type, storage_id = c, "угол", c.corner_id
break
if not storage:
self.logger.log(self.employee.name, "НЕ удалось разместить посылку", f"{parcel.tracking_number} — нет подходящего места")
return False
try:
if storage.store(parcel):
self.logger.log(self.employee.name, "разместил посылку", f"{parcel.tracking_number} на {storage_type} {storage_id}")
return True
else:
self.logger.log(self.employee.name, "не подошла полка", f"{parcel.tracking_number} — полка отказала")
return False
except Exception as e:
self.logger.log(self.employee.name, "ошибка при размещении", f"{parcel.tracking_number} — {str(e)}")
return False
def serve_client(self, client: Human, tracking_number: str):
self.logger.log(self.employee.name, "запрос на выдачу", tracking_number)
for s in self.shelves:
p = s.remove(tracking_number)
if p:
self.logger.log(self.employee.name, "снял посылку", f"{tracking_number} с полки {s.shelf_id}")
self.logger.log(self.employee.name, "выдал посылку", f"{tracking_number} клиенту {client.name}")
return p
for f in self.fridges:
p = f.remove(tracking_number)
if p:
self.logger.log(self.employee.name, "снял посылку", f"{tracking_number} с холодильника {f.fridge_id}")
self.logger.log(self.employee.name, "выдал посылку", f"{tracking_number} клиенту {client.name}")
return p
for c in self.floor_corners:
p = c.remove(tracking_number)
if p:
self.logger.log(self.employee.name, "снял посылку", f"{tracking_number} с угла {c.corner_id}")
self.logger.log(self.employee.name, "выдал посылку", f"{tracking_number} клиенту {client.name}")
return p
self.logger.log(self.employee.name, "посылка не найдена", tracking_number)
return None
def get_logs(self):
return self.logger.get_logs()