This commit is contained in:
Андрей Дувакин 2024-10-05 19:44:49 +05:00
parent a5d5460203
commit c8338ba142
3 changed files with 115 additions and 3 deletions

View File

@ -4,12 +4,12 @@ from sqlalchemy.orm import Session
from app.core.entities.city import CityEntity
from app.infrastructure.database.models.cities import City
from app.infrastructure.database.repository.city_repository import CitiesRepository
from app.infrastructure.database.repository.city_repository import CityRepository
class CitiesService:
def __init__(self, db: Session):
self.repository = CitiesRepository(db)
self.repository = CityRepository(db)
def get_all_cities(self) -> List[CityEntity]:
cities = self.repository.get_all_with_federal_district()

View File

@ -0,0 +1,112 @@
from itertools import permutations
from math import ceil
from sqlalchemy.orm import Session
from app.infrastructure.database.repository.accessory_repository import AccessoriesRepository
from app.infrastructure.database.repository.city_repository import CityRepository
from app.infrastructure.database.repository.delivery_accessory_repository import DeliveryAccessoriesRepository
from app.infrastructure.database.repository.delivery_order_repository import DeliveryOrdersRepository
from app.infrastructure.database.repository.total_order_repository import TotalOrdersRepository
class NewTotalOrderService:
def __init__(self, db: Session):
self.total_order_repository = TotalOrdersRepository(db)
self.delivery_order_repository = DeliveryOrdersRepository(db)
self.delivery_accessory_repository = DeliveryAccessoriesRepository(db)
self.city_repository = CityRepository(db)
self.accessory_repository = AccessoriesRepository(db)
def total_calculate(self):
grouped_by_period = self.group_accessories_by_period(accessories)
routes_by_period = self.find_routes_by_period(grouped_by_period, distances, cities)
for period, routes in routes_by_period.items():
for route in routes:
vehicle_count, selected_track = self.calculate_vehicle_requirements(
[a for a in accessories if a.period == period], tracks)
cost = self.calculate_route_cost(route, accessories, distances)
print(f"Период: {period}")
print(f"Маршрут: {' -> '.join([city.name for city in route])}")
selected_vehicle_name = next((track.name for track in tracks if track.id == selected_track),
"Нет доступного автомобиля")
print(f"Тип автомобиля: {selected_vehicle_name}")
print(f"Количество автомобилей: {vehicle_count}")
print(f"Стоимость перевозки: {cost}\n")
def find_routes_by_period(self, grouped_by_period, distances, cities):
routes_by_period = {}
for period, accessories in grouped_by_period.items():
cities_in_period = [next(city for city in cities if city.id == accessory.cityId) for accessory in
accessories]
all_routes = self.generate_routes(cities_in_period, next(city for city in cities if city.id == 9))
routes_with_details = []
for route in all_routes:
distance = self.calculate_route_distance(route, distances)
total_weight = sum(
sum(accessory.weight for accessory in accessories if accessory.cityId == city.id) for city in route)
cost = self.calculate_route_cost(route, accessories, distances)
routes_with_details.append((route, (distance, total_weight, cost)))
sorted_routes = sorted(routes_with_details, key=lambda x: (x[1][2], x[1][0]))
routes_by_period[period] = [sorted_routes[0][0]]
return routes_by_period
@staticmethod
def group_accessories_by_period(accessories):
grouped = {}
for accessory in accessories:
if accessory.period not in grouped:
grouped[accessory.period] = []
grouped[accessory.period].append(accessory)
return grouped
@staticmethod
def generate_routes(cities, start_city):
routes = []
cities_without_start = [city for city in cities if city.id != start_city.id]
all_routes = list(permutations(cities_without_start))
for route in all_routes:
routes.append([start_city] + list(route) + [start_city])
return routes
@staticmethod
def calculate_route_distance(route, distances):
total_distance = 0
for i in range(len(route) - 1):
total_distance += distances[route[i].id - 1][route[i + 1].id - 1]
return total_distance
@staticmethod
def calculate_route_cost(route, accessories, distances):
total_weight = 0.0
total_cost = 0.0
for i in range(len(route) - 1):
if route[i].id != 9:
city_accessories = [accessory for accessory in accessories if accessory.cityId == route[i].id]
total_weight += sum(accessory.weight for accessory in city_accessories) * 20.0
total_cost += distances[route[i].id - 1][route[i + 1].id - 1] * (total_weight / 1000.0) * 8
return total_cost
@staticmethod
def calculate_vehicle_requirements(accessories, tracks):
total_weight = sum(accessory.weight for accessory in accessories) * 20
total_vehicles = float('inf')
selected_track = 0
for track in tracks:
weight_vehicles = ceil(total_weight / track.weight)
if weight_vehicles < total_vehicles:
total_vehicles = weight_vehicles
selected_track = track.id
return total_vehicles, selected_track

View File

@ -2,7 +2,7 @@ from sqlalchemy.orm import Session, joinedload
from app.infrastructure.database.models.cities import City
class CitiesRepository:
class CityRepository:
def __init__(self, db: Session):
self.db = db