This commit is contained in:
Андрей Дувакин 2024-10-05 20:15:47 +05:00
parent c8338ba142
commit bd5aa7fcc6
3 changed files with 70 additions and 8 deletions

View File

@ -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')

View File

@ -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)) \

View File

@ -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()