From c8338ba142562dbd566c94c4aa301da3610cace5 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 5 Oct 2024 19:44:49 +0500 Subject: [PATCH] ._. --- app/core/usecases/city_service.py | 4 +- app/core/usecases/new_total_order_service.py | 112 ++++++++++++++++++ .../database/repository/city_repository.py | 2 +- 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 app/core/usecases/new_total_order_service.py diff --git a/app/core/usecases/city_service.py b/app/core/usecases/city_service.py index 82d0b1d..32794d5 100644 --- a/app/core/usecases/city_service.py +++ b/app/core/usecases/city_service.py @@ -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() diff --git a/app/core/usecases/new_total_order_service.py b/app/core/usecases/new_total_order_service.py new file mode 100644 index 0000000..b836e2e --- /dev/null +++ b/app/core/usecases/new_total_order_service.py @@ -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 diff --git a/app/infrastructure/database/repository/city_repository.py b/app/infrastructure/database/repository/city_repository.py index 6587724..ff1311f 100644 --- a/app/infrastructure/database/repository/city_repository.py +++ b/app/infrastructure/database/repository/city_repository.py @@ -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