Spaces:
Sleeping
Sleeping
File size: 5,865 Bytes
6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 6a808d5 72726e0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
import pandas as pd
from itertools import permutations
from fastapi import FastAPI, File, UploadFile, Form, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allows all origins
allow_credentials=True,
allow_methods=["*"], # Allows all methods
allow_headers=["*"], # Allows all headers
)
class Box:
def __init__(self, length, width, height, quantity, box_type):
self.length = length
self.width = width
self.height = height
self.quantity = quantity if quantity > 0 else 1 # Ensure at least 1 box if quantity is not specified
self.type = box_type
def rotated_dimensions(self):
# Return rotations that maximize base area and minimize height
possible_rotations = [
(self.length, self.width, self.height),
(self.length, self.height, self.width),
(self.width, self.length, self.height),
(self.width, self.height, self.length),
(self.height, self.length, self.width),
(self.height, self.width, self.length)
]
# Sort by volume and base area to prioritize the best fit
return sorted(possible_rotations, key=lambda x: (x[0] * x[1], x[2]), reverse=True)
def volume(self):
return self.length * self.width * self.height
class Truck:
def __init__(self, length, width, height):
self.length = length
self.width = width
self.height = height
self.volume = length * width * height
self.placed_boxes = []
self.available_space = [(0, 0, 0, length, width, height)] # (x, y, z, l, w, h)
def add_box(self, box):
best_fit = None
best_fit_space_index = -1
for rotation in box.rotated_dimensions():
for i, space in enumerate(self.available_space):
x, y, z, l, w, h = space
# Check if the box can fit in the current space
if rotation[0] <= l and rotation[1] <= w and rotation[2] <= h:
if not best_fit or (rotation[0] * rotation[1] > best_fit[0] * best_fit[1]):
best_fit = rotation
best_fit_space_index = i
if best_fit:
x, y, z, l, w, h = self.available_space[best_fit_space_index]
box_position = (x, y, z)
# Place the box in the truck
self.placed_boxes.append((best_fit, box_position))
# Update available space after placing the box
self.available_space.pop(best_fit_space_index)
self.update_space(best_fit, box_position, l, w, h)
return box_position
else:
return None
def update_space(self, box, position, l, w, h):
x, y, z = position
bl, bw, bh = box
# Create new spaces based on the placement of the new box
new_spaces = [
(x + bl, y, z, l - bl, w, h), # Space to the right
(x, y + bw, z, bl, w - bw, h), # Space in front
(x, y, z + bh, bl, bw, h - bh), # Space above
]
# Filter out invalid spaces
new_spaces = [space for space in new_spaces if space[3] > 0 and space[4] > 0 and space[5] > 0]
# Add new valid spaces to the available_space list
self.available_space.extend(new_spaces)
# Sort available spaces to prioritize lower and more central spaces for stacking
self.available_space.sort(key=lambda space: (space[2], space[1], space[0]))
def pack_boxes(truck, boxes):
packed_positions = []
# Sort all boxes by volume (largest first)
boxes.sort(key=lambda b: b.volume(), reverse=True)
# Pack all boxes, ensuring practical stacking
for box in boxes:
for _ in range(box.quantity):
position = truck.add_box(box)
if position is None:
break
packed_positions.append((box, position))
return packed_positions
@app.post("/upload/")
async def upload_file(
file: UploadFile = File(...),
length: float = Form(...),
width: float = Form(...),
height: float = Form(...),
):
if not file:
raise HTTPException(status_code=400, detail="No file uploaded")
ext = file.filename.split('.')[-1].lower()
if ext == 'csv':
data = pd.read_csv(file.file)
elif ext in ['xls', 'xlsx']:
data = pd.read_excel(file.file)
else:
raise HTTPException(status_code=400, detail="Unsupported file format")
# Convert dimensions from CM to inches
data['PieceLength'] = data['PieceLength'] / 2.54
data['PieceBreadth'] = data['PieceBreadth'] / 2.54
data['PieceHeight'] = data['PieceHeight'] / 2.54
# Create Box objects with quantity considered
boxes = [
Box(row['PieceLength'], row['PieceBreadth'], row['PieceHeight'], row.get('Quantity', 1), f"{row['PieceNo']}-{row['Priority']}")
for _, row in data.iterrows()
]
# Convert truck dimensions from feet to inches
truck_length = length * 12 # Convert to inches
truck_width = width * 12 # Convert to inches
truck_height = height * 12 # Convert to inches
truck = Truck(truck_length, truck_width, truck_height)
# Pack the boxes into the truck
packed_positions = pack_boxes(truck, boxes)
box_data = [
{
'length': box.length,
'width': box.width,
'height': box.height,
'type': box.type,
'quantity': box.quantity,
'position': {'x': pos[0], 'y': pos[1], 'z': pos[2]}
}
for box, pos in packed_positions
]
print(f"quantity {[box_data[i]['quantity'] for i in range(len(box_data))]}")
return {"boxes": box_data}
|