package main import ( "encoding/json" "fmt" "math" "net/http" ) type Container struct { Length float64 `json:"length"` Width float64 `json:"width"` Height float64 `json:"height"` WeightLimit float64 `json:"weightLimit"` } type Box struct { Length float64 `json:"length"` Width float64 `json:"width"` Height float64 `json:"height"` Weight float64 `json:"weight"` } type Placement struct { X float64 `json:"x"` Y float64 `json:"y"` Z float64 `json:"z"` RotationX float64 `json:"rotationX"` RotationY float64 `json:"rotationY"` RotationZ float64 `json:"rotationZ"` BoxNumber int `json:"boxNumber"` } type Layer struct { Count int `json:"count"` Layout []Placement `json:"layout"` } func main() { fmt.Println("集装箱装箱系统已启动,监听端口 :8080") 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"` } err := json.NewDecoder(r.Body).Decode(&data) if err != nil { http.Error(w, "参数解析失败", http.StatusBadRequest) fmt.Printf("⚠️ 错误:参数解析失败 - %v\n", err) return } fmt.Printf("🚀 收到请求:\n集装箱参数:长%fmm × 宽%fmm × 高%fmm(承重%fkg)\n纸箱参数:长%fmm × 宽%fmm × 高%fmm(重量%fkg)\n", data.Container.Length, data.Container.Width, data.Container.Height, data.Container.WeightLimit, data.Box.Length, data.Box.Width, data.Box.Height, data.Box.Weight) layout, strategy, count := optimizePacking(data.Container, data.Box) layerMap := make(map[float64][]Placement) for _, pos := range layout { layerMap[pos.Z] = append(layerMap[pos.Z], pos) } var layers []Layer for _, layer := range layerMap { layers = append(layers, Layer{ Count: len(layer), Layout: layer, }) } response := struct { Count int `json:"count"` Layers []Layer `json:"layers"` Strategy string `json:"strategy"` SpaceUtilization float64 `json:"spaceUtilization"` TotalWeight float64 `json:"totalWeight"` BoxLength float64 `json:"boxLength"` BoxWidth float64 `json:"boxWidth"` BoxHeight float64 `json:"boxHeight"` }{ Count: count, Layers: layers, Strategy: strategy, SpaceUtilization: calculateDensity(data.Container, data.Box, count), TotalWeight: float64(count) * data.Box.Weight, BoxLength: data.Box.Length, BoxWidth: data.Box.Width, BoxHeight: data.Box.Height, } json.NewEncoder(w).Encode(response) fmt.Printf("✅ 返回结果:\n最优装箱数:%d\n策略:%s\n空间利用率:%.2f%%\n", count, strategy, response.SpaceUtilization) }) http.ListenAndServe(":8080", nil) } func optimizePacking(con Container, box Box) ([]Placement, string, int) { fmt.Printf("📦 开始装箱优化\n容器尺寸:长%fmm × 宽%fmm × 高%fmm\n纸箱尺寸:长%fmm × 宽%fmm × 高%fmm\n", con.Length, con.Width, con.Height, box.Length, box.Width, box.Height) rotations := generateRotations(con, box) fmt.Printf("🔧 生成有效旋转方式:共%d种\n", len(rotations)) type candidate struct { layout []Placement count int strategy string } var candidates []candidate for _, r := range rotations { fmt.Printf("正在尝试旋转方式:%f×%f×%f\n", r.Length, r.Width, r.Height) 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) } totalByVolume := int(xCount * yCount * zCount) maxCountByWeight := int(math.Floor(con.WeightLimit / box.Weight)) actualCount := totalByVolume if actualCount > maxCountByWeight { actualCount = maxCountByWeight } if actualCount > 0 { layout := generateLayout(r, xCount, yCount, zCount, strategy) candidates = append(candidates, candidate{ layout: layout[:actualCount], count: actualCount, strategy: strategy, }) fmt.Printf("💡 新增方案:策略[%s] 可装载%d箱(尺寸:%dx%dx%d)\n", strategy, actualCount, xCount, yCount, zCount) } } } if len(candidates) == 0 { fmt.Printf("❗️ 未找到有效装箱方案\n") return nil, "", 0 } maxCount := 0 var finalLayout []Placement var finalStrategy string for _, c := range candidates { if c.count > maxCount { maxCount = c.count finalLayout = c.layout finalStrategy = c.strategy } } fmt.Printf("🏆 最优方案:策略[%s] 可装载%d箱\n", finalStrategy, maxCount) return finalLayout, finalStrategy, maxCount } func generateRotations(con Container, box Box) []Box { validRotations := make([]Box, 0) rotations := []Box{ {Length: box.Length, Width: box.Width, Height: box.Height, Weight: box.Weight}, {Length: box.Length, Width: box.Height, Height: box.Width, Weight: box.Weight}, {Length: box.Width, Width: box.Length, Height: box.Height, Weight: box.Weight}, {Length: box.Width, Width: box.Height, Height: box.Length, Weight: box.Weight}, {Length: box.Height, Width: box.Length, Height: box.Width, Weight: box.Weight}, {Length: box.Height, Width: box.Width, Height: box.Length, Weight: box.Weight}, } for _, r := range rotations { if r.Length <= con.Length && r.Width <= con.Width && r.Height <= con.Height { validRotations = append(validRotations, r) } } return validRotations } func generateLayout(r Box, xCount, yCount, zCount float64, strategy string) []Placement { fmt.Printf("正在生成布局:策略[%s](尺寸:%dx%dx%d)\n", strategy, xCount, yCount, zCount) 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: y * r.Width, Z: z * r.Height, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } 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: y * r.Width, Z: z * r.Height, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } 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: y * r.Length, Z: z * r.Height, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } 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: y * r.Length, Z: z * r.Height, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } 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: y * r.Height, Z: z * r.Length, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } 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: y * r.Height, Z: z * r.Length, RotationX: 0.0, RotationY: 0.0, RotationZ: 0.0, BoxNumber: len(layout), }) } } } default: fmt.Printf("❗️ 无效策略:%s\n", strategy) } return layout } func calculateDensity(con Container, box Box, count int) float64 { containerVolume := con.Length * con.Width * con.Height boxVolume := float64(count) * box.Length * box.Width * box.Height density := (boxVolume / containerVolume) * 100 fmt.Printf("📊 体积利用率计算:%.2f%%(箱子总容积%fmm³ / 集装箱容积%fmm³)\n", density, boxVolume, containerVolume) return density }