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 itertools import permutations
from math import ceil from math import ceil
from pprint import pprint
import requests import requests
from sqlalchemy.orm import Session 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.accessory_repository import AccessoriesRepository
from app.infrastructure.database.repository.city_repository import CityRepository 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_accessory_repository import DeliveryAccessoriesRepository
@ -23,36 +27,60 @@ class NewTotalOrderService:
self.truck_repository = TrucksRepository(db) self.truck_repository = TrucksRepository(db)
def total_calculate(self): def total_calculate(self):
print(111111111111111111111111111111111111111)
accessories = self.accessory_repository.get_with_cities_all() accessories = self.accessory_repository.get_with_cities_all()
cities = self.city_repository.get_all_with_federal_district() 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) 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) grouped_by_period = self.group_accessories_by_period(accessories)
routes_by_period = self.find_routes_by_period(grouped_by_period, distances, cities) 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(): response = ''
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 += f"Период: {period}\n" for period, routes in routes_by_period.items():
response += f"Маршрут: {' -> '.join([city.name for city in route])}\n" for route in routes:
selected_vehicle_name = next((track.name for track in tracks if track.id == selected_track), vehicle_count, selected_truck = self.calculate_vehicle_requirements(
"Нет доступного автомобиля") [a for a in accessories if a.period == period], trucks)
response += f"Тип автомобиля: {selected_vehicle_name}" cost = self.calculate_route_cost(route, accessories, distances)
response += f"Количество автомобилей: {vehicle_count}"
response += f"Стоимость перевозки: {cost}\n" 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): def find_routes_by_period(self, grouped_by_period, distances, cities):
purpose_city_id = self.city_repository.get_by_name('Челябинск').id purpose_city_id = self.city_repository.get_by_name('Челябинск').id
@ -60,8 +88,10 @@ class NewTotalOrderService:
routes_by_period = {} routes_by_period = {}
for period, accessories in grouped_by_period.items(): 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 cities_in_period = [
accessories] next(city for city in cities if city.id == accessory.city_id)
for accessory in accessories
]
all_routes = self.generate_routes(cities_in_period, all_routes = self.generate_routes(cities_in_period,
next(city for city in cities if city.id == purpose_city_id)) next(city for city in cities if city.id == purpose_city_id))
@ -117,37 +147,37 @@ class NewTotalOrderService:
@staticmethod @staticmethod
def calculate_route_distance(route, distances): def calculate_route_distance(route, distances):
total_distance = 0 total_distance = 0
pprint(distances)
for i in range(len(route) - 1): for i in range(len(route) - 1):
total_distance += distances[route[i].id - 1][route[i + 1].id - 1] total_distance += distances[route[i].id - 1][route[i + 1].id - 1]
return total_distance return total_distance
@staticmethod def calculate_route_cost(self, route, accessories, distances):
def calculate_route_cost(route, accessories, distances): purpose_city_id = self.city_repository.get_by_name('Челябинск').id
total_weight = 0.0 total_weight = 0.0
total_cost = 0.0 total_cost = 0.0
for i in range(len(route) - 1): for i in range(len(route) - 1):
if route[i].id != 9: if route[i].id != purpose_city_id:
city_accessories = [accessory for accessory in accessories if accessory.cityId == route[i].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_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 total_cost += distances[route[i].id - 1][route[i + 1].id - 1] * (total_weight / 1000.0) * 8
return total_cost return total_cost
@staticmethod @staticmethod
def calculate_vehicle_requirements(accessories, tracks): def calculate_vehicle_requirements(accessories, trucks):
total_weight = sum(accessory.weight for accessory in accessories) * 20 total_weight = sum(accessory.weight for accessory in accessories) * 20
total_vehicles = float('inf') total_vehicles = float('inf')
selected_track = 0 selected_truck = 0
for track in tracks: for truck in trucks:
weight_vehicles = ceil(total_weight / track.weight) weight_vehicles = ceil(total_weight / truck.capacity)
if weight_vehicles < total_vehicles: if weight_vehicles < total_vehicles:
total_vehicles = weight_vehicles total_vehicles = weight_vehicles
selected_track = track.id selected_truck = truck.id
return total_vehicles, selected_track return total_vehicles, selected_truck
@staticmethod @staticmethod
def get_distance(start_coords, end_coords): def get_distance(start_coords, end_coords):

View File

@ -1,3 +1,4 @@
from sqlalchemy import asc
from sqlalchemy.orm import Session, joinedload from sqlalchemy.orm import Session, joinedload
from app.infrastructure.database.models.cities import City from app.infrastructure.database.models.cities import City
@ -15,6 +16,7 @@ class CityRepository:
def get_all_with_federal_district(self): def get_all_with_federal_district(self):
return self.db.query(City) \ return self.db.query(City) \
.options(joinedload(City.federal_district)) \ .options(joinedload(City.federal_district)) \
.order_by(asc(City.id)) \
.all() .all()
def get_by_id(self, city_id: int): 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) @router.post("/total-orders/calculate", response_model=TotalOrderEntity)
def calculate_total_order(db: Session = Depends(get_db)): def calculate_total_order(db: Session = Depends(get_db)):
service = NewTotalOrderService(db) service = NewTotalOrderService(db)
return service.total_calculate() result = service.total_calculate()
print(result)
return result