stream_app/main.go
2025-04-18 14:03:36 +08:00

219 lines
5.5 KiB
Go

package main
import (
"encoding/json"
"math"
"net/http"
)
type Container struct {
Length float64 `json:"length"`
Width float64 `json:"width"`
Height float64 `json:"height"`
}
type Box struct {
Length float64 `json:"length"`
Width float64 `json:"width"`
Height float64 `json:"height"`
}
type Placement struct {
X, Y, Z float64 `json:"x"`
}
type Response struct {
Count int `json:"count"`
Layout []Placement `json:"layout"`
BoxLength float64 `json:"boxLength"`
BoxWidth float64 `json:"boxWidth"`
BoxHeight float64 `json:"boxHeight"`
Strategy string `json:"strategy"`
Density float64 `json:"density"`
SpaceUtilization float64 `json:"spaceUtilization"`
UsedVolume float64 `json:"usedVolume"`
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
http.HandleFunc("/calculate", func(w http.ResponseWriter, r *http.Request) {
var data struct {
Container Container `json:"container"`
Box Box `json:"box"`
}
json.NewDecoder(r.Body).Decode(&data)
layout, bestRotation, strategy, density, spaceUtilization, usedVolume := optimizePacking(data.Container, data.Box)
count := len(layout)
response := Response{
Count: count,
Layout: layout,
BoxLength: bestRotation.Length,
BoxWidth: bestRotation.Width,
BoxHeight: bestRotation.Height,
Strategy: strategy,
Density: density,
SpaceUtilization: spaceUtilization,
UsedVolume: usedVolume,
}
json.NewEncoder(w).Encode(response)
})
http.ListenAndServe(":8080", nil)
}
func optimizePacking(con Container, box Box) ([]Placement, Box, string, float64, float64, float64) {
var bestLayout []Placement
var bestRotation Box
var bestStrategy string
maxCount := 0
var bestDensity float64
var bestSpaceUtilization float64
var bestUsedVolume float64
rotations := generateRotations(box)
conVolume := con.Length * con.Width * con.Height
for _, r := range rotations {
for _, strategy := range []string{"XY", "XZ", "YX", "YZ", "ZX", "ZY"} {
var xCount, yCount, zCount float64
switch strategy {
case "XY":
xCount = math.Floor(con.Length / r.Length)
yCount = math.Floor(con.Width / r.Width)
zCount = math.Floor(con.Height / r.Height)
case "XZ":
xCount = math.Floor(con.Length / r.Length)
zCount = math.Floor(con.Height / r.Height)
yCount = math.Floor(con.Width / r.Width)
case "YX":
yCount = math.Floor(con.Width / r.Length)
xCount = math.Floor(con.Length / r.Width)
zCount = math.Floor(con.Height / r.Height)
case "YZ":
yCount = math.Floor(con.Width / r.Length)
zCount = math.Floor(con.Height / r.Height)
xCount = math.Floor(con.Length / r.Width)
case "ZX":
zCount = math.Floor(con.Height / r.Length)
xCount = math.Floor(con.Length / r.Width)
yCount = math.Floor(con.Width / r.Height)
case "ZY":
zCount = math.Floor(con.Height / r.Length)
yCount = math.Floor(con.Width / r.Height)
xCount = math.Floor(con.Length / r.Width)
}
total := int(xCount * yCount * zCount)
if total > maxCount && total > 0 {
maxCount = total
bestRotation = r
bestStrategy = strategy
bestLayout = generateLayout(r, xCount, yCount, zCount, strategy)
boxVolume := r.Length * r.Width * r.Height
bestUsedVolume = float64(total) * boxVolume
bestDensity = (bestUsedVolume / conVolume) * 100
bestSpaceUtilization = bestDensity
}
}
}
return bestLayout, bestRotation, bestStrategy, bestDensity, bestSpaceUtilization, bestUsedVolume
}
func generateRotations(box Box) []Box {
return []Box{
{box.Length, box.Width, box.Height},
{box.Length, box.Height, box.Width},
{box.Width, box.Length, box.Height},
{box.Width, box.Height, box.Length},
{box.Height, box.Length, box.Width},
{box.Height, box.Width, box.Length},
}
}
func generateLayout(r Box, xCount, yCount, zCount float64, strategy string) []Placement {
var layout []Placement
switch strategy {
case "XY":
for x := 0.0; x < xCount; x++ {
for y := 0.0; y < yCount; y++ {
for z := 0.0; z < zCount; z++ {
layout = append(layout, Placement{
X: x * r.Length,
Y: z * r.Height,
Z: y * r.Width,
})
}
}
}
case "XZ":
for x := 0.0; x < xCount; x++ {
for z := 0.0; z < zCount; z++ {
for y := 0.0; y < yCount; y++ {
layout = append(layout, Placement{
X: x * r.Length,
Y: z * r.Height,
Z: y * r.Width,
})
}
}
}
case "YX":
for y := 0.0; y < yCount; y++ {
for x := 0.0; x < xCount; x++ {
for z := 0.0; z < zCount; z++ {
layout = append(layout, Placement{
X: x * r.Width,
Y: z * r.Height,
Z: y * r.Length,
})
}
}
}
case "YZ":
for y := 0.0; y < yCount; y++ {
for z := 0.0; z < zCount; z++ {
for x := 0.0; x < xCount; x++ {
layout = append(layout, Placement{
X: x * r.Width,
Y: z * r.Height,
Z: y * r.Length,
})
}
}
}
case "ZX":
for z := 0.0; z < zCount; z++ {
for x := 0.0; x < xCount; x++ {
for y := 0.0; y < yCount; y++ {
layout = append(layout, Placement{
X: x * r.Width,
Y: z * r.Length,
Z: y * r.Height,
})
}
}
}
case "ZY":
for z := 0.0; z < zCount; z++ {
for y := 0.0; y < yCount; y++ {
for x := 0.0; x < xCount; x++ {
layout = append(layout, Placement{
X: x * r.Width,
Y: z * r.Length,
Z: y * r.Height,
})
}
}
}
}
return layout
}