This commit is contained in:
Андрей Дувакин 2024-10-05 20:56:46 +05:00
parent bd5aa7fcc6
commit 3e6e6c60f7
3 changed files with 69 additions and 35 deletions

View File

@ -1,10 +1,14 @@
from datetime import datetime, timedelta
from itertools import permutations
from math import ceil
from pprint import pprint
import requests
from sqlalchemy.orm import Session
from app.infrastructure.database.dependencies import get_db
from app.infrastructure.database.models.delivery_accessories import DeliveryAccessory
from app.infrastructure.database.models.delivery_orders import DeliveryOrder
from app.infrastructure.database.models.total_orders import TotalOrder
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
@ -23,36 +27,60 @@ class NewTotalOrderService:
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()
trucks = 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 = ''
with get_db() as session:
new_total_order = TotalOrder(
order_datetime=datetime.now(),
count_robots=2000,
deadline=datetime.now(),
)
session.add(new_total_order)
session.flush()
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)
response = ''
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),
"Нет доступного автомобиля")
response += f"Тип автомобиля: {selected_vehicle_name}"
response += f"Количество автомобилей: {vehicle_count}"
response += f"Стоимость перевозки: {cost}\n"
for period, routes in routes_by_period.items():
for route in routes:
vehicle_count, selected_truck = self.calculate_vehicle_requirements(
[a for a in accessories if a.period == period], trucks)
cost = self.calculate_route_cost(route, accessories, distances)
delivery_order_deadline = new_total_order.deadline - timedelta(days=period)
new_delivery_order = DeliveryOrder(
order_datetime=datetime.now(),
count_trucks=vehicle_count,
deadline=delivery_order_deadline,
price=cost,
truck_id=selected_truck,
total_order_id=new_delivery_order.id,
)
session.add(new_total_order)
for point_index in range(len(route)):
new_delivery_accessory = DeliveryAccessory(
queue=point_index + 1,
)
response += f"Период: {period}\n"
response += f"Маршрут: {' -> '.join([city.name for city in route])}\n"
selected_vehicle_name = next((truck.name for truck in trucks if truck.id == selected_truck),
"Нет доступного автомобиля")
response += f"Тип автомобиля: {selected_vehicle_name}"
response += f"Количество автомобилей: {vehicle_count}"
response += f"Стоимость перевозки: {cost}\n"
return response
def find_routes_by_period(self, grouped_by_period, distances, cities):
purpose_city_id = self.city_repository.get_by_name('Челябинск').id
@ -60,8 +88,10 @@ class NewTotalOrderService:
routes_by_period = {}
for period, accessories in grouped_by_period.items():
cities_in_period = [next(city for city in cities if city.id == accessory.city_id) for accessory in
accessories]
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 == purpose_city_id))
@ -117,37 +147,37 @@ 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
@staticmethod
def calculate_route_cost(route, accessories, distances):
def calculate_route_cost(self, route, accessories, distances):
purpose_city_id = self.city_repository.get_by_name('Челябинск').id
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]
if route[i].id != purpose_city_id:
city_accessories = [accessory for accessory in accessories if accessory.city_id == 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):
def calculate_vehicle_requirements(accessories, trucks):
total_weight = sum(accessory.weight for accessory in accessories) * 20
total_vehicles = float('inf')
selected_track = 0
selected_truck = 0
for track in tracks:
weight_vehicles = ceil(total_weight / track.weight)
for truck in trucks:
weight_vehicles = ceil(total_weight / truck.capacity)
if weight_vehicles < total_vehicles:
total_vehicles = weight_vehicles
selected_track = track.id
selected_truck = truck.id
return total_vehicles, selected_track
return total_vehicles, selected_truck
@staticmethod
def get_distance(start_coords, end_coords):

View File

@ -1,3 +1,4 @@
from sqlalchemy import asc
from sqlalchemy.orm import Session, joinedload
from app.infrastructure.database.models.cities import City
@ -15,6 +16,7 @@ class CityRepository:
def get_all_with_federal_district(self):
return self.db.query(City) \
.options(joinedload(City.federal_district)) \
.order_by(asc(City.id)) \
.all()
def get_by_id(self, city_id: int):

View File

@ -60,4 +60,6 @@ def delete_total_order(total_order_id: int, db: Session = Depends(get_db),
@router.post("/total-orders/calculate", response_model=TotalOrderEntity)
def calculate_total_order(db: Session = Depends(get_db)):
service = NewTotalOrderService(db)
return service.total_calculate()
result = service.total_calculate()
print(result)
return result