From bd5aa7fcc643261aa1620735a9629659980640a6 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 5 Oct 2024 20:15:47 +0500 Subject: [PATCH] ._. --- app/core/usecases/new_total_order_service.py | 68 ++++++++++++++++--- .../database/repository/city_repository.py | 3 + .../fastapi/total_order_routes.py | 7 ++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/app/core/usecases/new_total_order_service.py b/app/core/usecases/new_total_order_service.py index b836e2e..16b11a3 100644 --- a/app/core/usecases/new_total_order_service.py +++ b/app/core/usecases/new_total_order_service.py @@ -1,6 +1,8 @@ from itertools import permutations from math import ceil +from pprint import pprint +import requests from sqlalchemy.orm import Session from app.infrastructure.database.repository.accessory_repository import AccessoriesRepository @@ -8,6 +10,7 @@ from app.infrastructure.database.repository.city_repository import CityRepositor 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 +from app.infrastructure.database.repository.truck_repository import TrucksRepository class NewTotalOrderService: @@ -17,38 +20,57 @@ class NewTotalOrderService: self.delivery_accessory_repository = DeliveryAccessoriesRepository(db) self.city_repository = CityRepository(db) self.accessory_repository = AccessoriesRepository(db) + self.truck_repository = TrucksRepository(db) def total_calculate(self): + print(111111111111111111111111111111111111111) + + accessories = self.accessory_repository.get_with_cities_all() + cities = self.city_repository.get_all_with_federal_district() + tracks = self.truck_repository.get_all() + distances = self.create_distance_matrix(cities) + + for i in distances: + for j in i: + print(j) + print() + grouped_by_period = self.group_accessories_by_period(accessories) routes_by_period = self.find_routes_by_period(grouped_by_period, distances, cities) + response = '' + 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])}") + response += f"Период: {period}\n" + response += f"Маршрут: {' -> '.join([city.name for city in route])}\n" 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") + response += f"Тип автомобиля: {selected_vehicle_name}" + response += f"Количество автомобилей: {vehicle_count}" + response += f"Стоимость перевозки: {cost}\n" def find_routes_by_period(self, grouped_by_period, distances, cities): + purpose_city_id = self.city_repository.get_by_name('Челябинск').id + 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 + cities_in_period = [next(city for city in cities if city.id == accessory.city_id) for accessory in accessories] - all_routes = self.generate_routes(cities_in_period, next(city for city in cities if city.id == 9)) + all_routes = self.generate_routes(cities_in_period, + next(city for city in cities if city.id == purpose_city_id)) 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) + sum(accessory.weight for accessory in accessories if accessory.city_id == city.id) for city in + route) cost = self.calculate_route_cost(route, accessories, distances) routes_with_details.append((route, (distance, total_weight, cost))) @@ -57,6 +79,21 @@ class NewTotalOrderService: return routes_by_period + def create_distance_matrix(self, cities): + num_cities = len(cities) + distances = [[0] * num_cities for _ in range(num_cities)] + + for i in range(num_cities): + for j in range(num_cities): + if i != j: + start_coords = (cities[i].x_coordinate, cities[i].y_coordinate) + end_coords = (cities[j].x_coordinate, cities[j].y_coordinate) + distances[i][j] = self.get_distance(start_coords, end_coords) + else: + distances[i][j] = 0 + + return distances + @staticmethod def group_accessories_by_period(accessories): grouped = {} @@ -80,6 +117,7 @@ class NewTotalOrderService: @staticmethod def calculate_route_distance(route, distances): total_distance = 0 + pprint(distances) for i in range(len(route) - 1): total_distance += distances[route[i].id - 1][route[i + 1].id - 1] return total_distance @@ -110,3 +148,17 @@ class NewTotalOrderService: selected_track = track.id return total_vehicles, selected_track + + @staticmethod + def get_distance(start_coords, end_coords): + base_url = "http://router.project-osrm.org/route/v1/driving" + url = f"{base_url}/{start_coords[1]},{start_coords[0]};{end_coords[1]},{end_coords[0]}?overview=full" + + response = requests.get(url) + data = response.json() + + if data['routes']: + distance = data['routes'][0]['distance'] / 1000 + return distance + else: + return float('inf') diff --git a/app/infrastructure/database/repository/city_repository.py b/app/infrastructure/database/repository/city_repository.py index ff1311f..6eab5d3 100644 --- a/app/infrastructure/database/repository/city_repository.py +++ b/app/infrastructure/database/repository/city_repository.py @@ -9,6 +9,9 @@ class CityRepository: def get_all(self): return self.db.query(City).all() + def get_by_name(self, city_name): + return self.db.query(City).filter(City.name == city_name).first() + def get_all_with_federal_district(self): return self.db.query(City) \ .options(joinedload(City.federal_district)) \ diff --git a/app/infrastructure/fastapi/total_order_routes.py b/app/infrastructure/fastapi/total_order_routes.py index d0ec5cf..4c573ca 100644 --- a/app/infrastructure/fastapi/total_order_routes.py +++ b/app/infrastructure/fastapi/total_order_routes.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, HTTPException, Depends from sqlalchemy.orm import Session from app.core.usecases.auth_service import verify_token +from app.core.usecases.new_total_order_service import NewTotalOrderService from app.infrastructure.database.dependencies import get_db from app.core.entities.total_order import TotalOrderEntity from app.core.usecases.total_order_service import TotalOrdersService @@ -54,3 +55,9 @@ def delete_total_order(total_order_id: int, db: Session = Depends(get_db), if not success: raise HTTPException(status_code=404, detail="Total order not found") return success + + +@router.post("/total-orders/calculate", response_model=TotalOrderEntity) +def calculate_total_order(db: Session = Depends(get_db)): + service = NewTotalOrderService(db) + return service.total_calculate()