@cratefit/pack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +51 -0
- package/README.md +131 -0
- package/dist/index.cjs +360 -0
- package/dist/index.d.cts +1280 -0
- package/dist/index.d.ts +1280 -0
- package/dist/index.js +360 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
CrateFit SDK License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 supra126 (https://github.com/supra126). All rights reserved.
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS
|
|
6
|
+
|
|
7
|
+
1. GRANT OF LICENSE
|
|
8
|
+
Permission is hereby granted, free of charge, to any person or organization
|
|
9
|
+
obtaining a copy of this software and associated documentation files (the
|
|
10
|
+
"Software"), to use the Software in applications, subject to the following
|
|
11
|
+
conditions.
|
|
12
|
+
|
|
13
|
+
2. PERMITTED USES
|
|
14
|
+
You MAY:
|
|
15
|
+
- Use the Software in your own applications (commercial or non-commercial)
|
|
16
|
+
- Distribute applications that incorporate the Software
|
|
17
|
+
- Use the Software for development, testing, and production purposes
|
|
18
|
+
|
|
19
|
+
3. RESTRICTIONS
|
|
20
|
+
You MAY NOT:
|
|
21
|
+
- Modify, adapt, alter, or create derivative works of the Software
|
|
22
|
+
- Reverse engineer, decompile, disassemble, or otherwise attempt to derive
|
|
23
|
+
the source code of the Software
|
|
24
|
+
- Redistribute, sublicense, sell, or transfer the Software itself
|
|
25
|
+
(in source or compiled form) as a standalone product
|
|
26
|
+
- Remove or alter any proprietary notices, labels, or marks on the Software
|
|
27
|
+
- Use the Software to create a competing product or service
|
|
28
|
+
|
|
29
|
+
4. ATTRIBUTION
|
|
30
|
+
Applications using the Software should include the following attribution
|
|
31
|
+
in their documentation or about section:
|
|
32
|
+
"Powered by CrateFit (https://github.com/supra126/cratefit)"
|
|
33
|
+
|
|
34
|
+
5. DISCLAIMER OF WARRANTY
|
|
35
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
36
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
37
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
38
|
+
|
|
39
|
+
6. LIMITATION OF LIABILITY
|
|
40
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
41
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
42
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
43
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
44
|
+
|
|
45
|
+
7. TERMINATION
|
|
46
|
+
This license is effective until terminated. It will terminate automatically
|
|
47
|
+
if you fail to comply with any of its terms and conditions. Upon termination,
|
|
48
|
+
you must destroy all copies of the Software in your possession.
|
|
49
|
+
|
|
50
|
+
For commercial licensing options or inquiries, please contact:
|
|
51
|
+
https://github.com/supra126
|
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @cratefit/pack
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@cratefit/pack)
|
|
4
|
+
|
|
5
|
+
A powerful 3D bin packing library for optimizing container, pallet, and truck loading.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Multiple Algorithms**: Extreme Point, Layer Building, Wall Building, EB-AFIT
|
|
10
|
+
- **Metaheuristic Optimization**: Simulated Annealing, Tabu Search, Genetic Algorithm
|
|
11
|
+
- **Industry Standards**: Built-in pallet and container specifications (EUR, ISO, etc.)
|
|
12
|
+
- **Advanced Constraints**: Weight limits, stacking rules, rotation restrictions, support checking
|
|
13
|
+
- **Real-time Packing**: Online packing mode for dynamic item placement
|
|
14
|
+
- **Exclude Zones**: Support for irregular container shapes
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @cratefit/pack
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For visualization support:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @cratefit/pack @cratefit/viz three
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { pack, createBin, createItem } from '@cratefit/pack';
|
|
32
|
+
|
|
33
|
+
// Define a bin (container)
|
|
34
|
+
const bin = createBin({
|
|
35
|
+
id: 'bin-1',
|
|
36
|
+
width: 1200,
|
|
37
|
+
height: 1000,
|
|
38
|
+
depth: 800,
|
|
39
|
+
maxWeight: 1000,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Define items to pack
|
|
43
|
+
const items = [
|
|
44
|
+
createItem({ id: 'item-1', width: 400, height: 300, depth: 200, weight: 10, quantity: 5 }),
|
|
45
|
+
createItem({ id: 'item-2', width: 300, height: 200, depth: 150, weight: 5, quantity: 8 }),
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// Pack items
|
|
49
|
+
const result = pack({
|
|
50
|
+
bins: [bin],
|
|
51
|
+
items,
|
|
52
|
+
options: {
|
|
53
|
+
algorithm: 'auto',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
console.log(`Utilization: ${(result.stats.avgUtilization * 100).toFixed(1)}%`);
|
|
58
|
+
console.log(`Packed: ${result.stats.packedItems}/${result.stats.totalItems} items`);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Pallet Packing
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { packPallet, PALLET_STANDARDS } from '@cratefit/pack';
|
|
65
|
+
|
|
66
|
+
const result = packPallet({
|
|
67
|
+
pallet: PALLET_STANDARDS.EUR1,
|
|
68
|
+
items: [...],
|
|
69
|
+
options: {
|
|
70
|
+
maxStackHeight: 1800,
|
|
71
|
+
stackingRules: true,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Container Loading
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { packContainer, CONTAINER_STANDARDS } from '@cratefit/pack';
|
|
80
|
+
|
|
81
|
+
const result = packContainer({
|
|
82
|
+
container: CONTAINER_STANDARDS['20ft'],
|
|
83
|
+
items: [...],
|
|
84
|
+
options: {
|
|
85
|
+
optimizeForWeight: true,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Visualization
|
|
91
|
+
|
|
92
|
+
Use `@cratefit/viz` for 2D/3D rendering:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { pack } from '@cratefit/pack';
|
|
96
|
+
import { renderTopView, create3DScene, renderPackedBin3D } from '@cratefit/viz';
|
|
97
|
+
|
|
98
|
+
// 2D Canvas
|
|
99
|
+
renderTopView(canvas, result.packed[0], { showLabels: true });
|
|
100
|
+
|
|
101
|
+
// 3D Three.js
|
|
102
|
+
const { scene, camera, renderer } = await create3DScene(container);
|
|
103
|
+
await renderPackedBin3D(scene, result.packed[0]);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
See [@cratefit/viz](https://www.npmjs.com/package/@cratefit/viz) for more details.
|
|
107
|
+
|
|
108
|
+
## API Reference
|
|
109
|
+
|
|
110
|
+
### Core Functions
|
|
111
|
+
|
|
112
|
+
- `pack(options)` - Main packing function
|
|
113
|
+
- `createBin(spec)` - Create a bin specification
|
|
114
|
+
- `createItem(spec)` - Create an item specification
|
|
115
|
+
|
|
116
|
+
### Scenario Functions
|
|
117
|
+
|
|
118
|
+
- `packPallet(options)` - Pallet-specific packing
|
|
119
|
+
- `packContainer(options)` - Container-specific packing
|
|
120
|
+
- `packTruck(options)` - Truck-specific packing with axle weight calculation
|
|
121
|
+
|
|
122
|
+
### Algorithm Options
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
type Algorithm =
|
|
126
|
+
| 'extreme-point' // Fast, good for uniform items
|
|
127
|
+
| 'layer-building' // Best for stable stacking
|
|
128
|
+
| 'wall-building' // Good for varied sizes
|
|
129
|
+
| 'eb-afit' // Human-like heuristic
|
|
130
|
+
| 'auto'; // Automatic selection
|
|
131
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
'use strict';/**
|
|
2
|
+
* CrateFit SDK v0.1.0
|
|
3
|
+
* Copyright (c) 2026 supra126 (https://github.com/supra126)
|
|
4
|
+
* Licensed under CrateFit SDK License
|
|
5
|
+
* https://github.com/supra126/cratefit
|
|
6
|
+
*/
|
|
7
|
+
var y={RT_WHD:0,RT_HWD:1,RT_HDW:2,RT_DHW:3,RT_DWH:4,RT_WDH:5};function D(t,e){return {minX:t.x,maxX:t.x+e.width,minY:t.y,maxY:t.y+e.height,minZ:t.z,maxZ:t.z+e.depth}}function B(t,e){return !(t.maxX<=e.minX||e.maxX<=t.minX||t.maxY<=e.minY||e.maxY<=t.minY||t.maxZ<=e.minZ||e.maxZ<=t.minZ)}function oi(t,e){return t.minX<=e.minX&&t.maxX>=e.maxX&&t.minY<=e.minY&&t.maxY>=e.maxY&&t.minZ<=e.minZ&&t.maxZ>=e.maxZ}function ri(t){return (t.maxX-t.minX)*(t.maxY-t.minY)*(t.maxZ-t.minZ)}function P(t){return t.width*t.height*t.depth}function v(t){return D(t.position,t.dimensions)}function _(t,e){let i=Math.max(0,Math.min(t.maxX,e.maxX)-Math.max(t.minX,e.minX)),n=Math.max(0,Math.min(t.maxZ,e.maxZ)-Math.max(t.minZ,e.minZ));return i*n}function ai(t,e){let i=v(t),n=v(e);return i.minY!==n.maxY?false:_(i,n)>0}var yt=class{items=[];insert(t){this.items.push(t);}remove(t){let e=this.items.findIndex(i=>i.item.id===t.item.id);e!==-1&&this.items.splice(e,1);}query(t){return this.items.filter(e=>{let i=v(e);return B(i,t)})}clear(){this.items=[];}getAll(){return [...this.items]}get size(){return this.items.length}};function O(){return new yt}function L(t,e,i){let n=D(t,e),s=i.query(n);for(let o of s){let r=v(o);if(B(n,r))return true}return false}function X(t,e,i){return t.x>=0&&t.y>=0&&t.z>=0&&t.x+e.width<=i.width&&t.y+e.height<=i.height&&t.z+e.depth<=i.depth}function N(t,e,i){if(!i.excludeZones||i.excludeZones.length===0)return false;let n=D(t,e);for(let s of i.excludeZones)if(B(n,s))return true;return false}function Y(t,e,i){if(!i.maxWeight)return true;let n=t.reduce((o,r)=>o+(r.item.weight||0),0),s=e.weight||0;return n+s<=i.maxWeight}function zt(t){return t.reduce((e,i)=>e+(i.item.weight||0),0)}function ot(t,e){let i=0,n=0,s=0,o=0;for(let r of t){let a=r.item.weight||0;if(a<=0)continue;let u=r.position.x+r.dimensions.width/2,h=r.position.y+r.dimensions.height/2,d=r.position.z+r.dimensions.depth/2;n+=a*u,s+=a*h,o+=a*d,i+=a;}return i<=0?{x:e.width/2,y:0,z:e.depth/2}:{x:n/i,y:s/i,z:o/i}}function hi(t,e,i=.15){let n=ot(t,e),s=e.width/2,o=e.depth/2;return Math.abs(n.x-s)<e.width*i&&Math.abs(n.z-o)<e.depth*i}function rt(t,e,i){if(t.y===0)return e.width*e.depth;let n=D(t,e),s=0;for(let o of i){let r=v(o);r.maxY===n.minY&&(s+=_(n,r));}return s}function V(t,e,i,n=.7){if(t.y===0)return true;let s=e.width*e.depth;return s<=0?false:rt(t,e,i)/s>=n}function ui(t,e,i){if(!t.item.maxStackWeight)return true;let n=v(t),s=e;for(let o of i){let r=v(o);r.minY>=n.maxY&&_(r,n)>0&&(s+=o.item.weight||0);}return s<=t.item.maxStackWeight}function I(t,e,i,n){switch(n){case y.RT_WHD:return {width:t,height:e,depth:i};case y.RT_HWD:return {width:e,height:t,depth:i};case y.RT_HDW:return {width:e,height:i,depth:t};case y.RT_DHW:return {width:i,height:e,depth:t};case y.RT_DWH:return {width:i,height:t,depth:e};case y.RT_WDH:return {width:t,height:i,depth:e};default:return {width:t,height:e,depth:i}}}function T(t){switch(t){case "all":return [y.RT_WHD,y.RT_HWD,y.RT_HDW,y.RT_DHW,y.RT_DWH,y.RT_WDH];case "horizontal":return [y.RT_WHD,y.RT_DWH];case "fixed":return [y.RT_WHD];default:return [y.RT_WHD]}}function ci(t,e,i,n){return n.map(s=>({rotation:s,dimensions:I(t,e,i,s)}))}function G(t,e,i={}){let n=O(),s=[],o=[],r={projectToSupport:i.features?.supportCheck??true,maxPoints:3e3};if(t.existingItems)for(let u of t.existingItems)n.insert(u),s.push(u);let a=Mt(t);if(t.existingItems)for(let u of t.existingItems)a=K(a,u,t,s,r);for(let u of e){let h=bt(u,a,t,s,n,i);if(h){let d={item:u,position:{x:h.point.x,y:h.point.y,z:h.point.z},rotation:h.rotation,dimensions:h.dimensions};s.push(d),n.insert(d),a=K(a,d,t,s,r);}else o.push(u);}return {packed:s,unpacked:o}}function bt(t,e,i,n,s,o,r){let a=t.allowedRotations||T(t.rotationType||"all"),u=[],h=[...e].sort((d,c)=>d.score-c.score);for(let d of h)for(let c of a){let l=I(t.width,t.height,t.depth,c);if(!X(d,l,i)||N(d,l,i)||L(d,l,s)||!Y(n,t,i))continue;if(o.features?.supportCheck){let m=t.requiresSupport??.5;if(!V(d,l,n,m))continue}let p=vt(d,l,i,n),f={point:d,rotation:c,dimensions:l,score:p};return f;}return u.length>0?(u.sort((d,c)=>d.score-c.score),u[0]):null}function vt(t,e,i,n){let s=t.x/i.width,o=t.y/i.height,r=t.z/i.depth,a=o*100+r*10+s;t.y===0&&(a-=50);let u=t.x===0||t.x+e.width===i.width,h=t.z===0||t.z+e.depth===i.depth;u&&(a-=5),h&&(a-=5);let d=Bt(t,e,n);a-=d*3;let c=rt(t,e,n),l=e.width*e.depth;return t.y>0&&c<l*.9&&(a+=10),a}function Bt(t,e,i){let n=0,s=.001;for(let o of i){let r=o.position.x,a=o.position.y,u=o.position.z,h=o.dimensions,d=(Math.abs(t.x-(r+h.width))<s||Math.abs(t.x+e.width-r)<s)&&kt(t,e,o),c=(Math.abs(t.y-(a+h.height))<s||Math.abs(t.y+e.height-a)<s)&&St(t,e,o),l=(Math.abs(t.z-(u+h.depth))<s||Math.abs(t.z+e.depth-u)<s)&&It(t,e,o);(d||c||l)&&n++;}return n}function kt(t,e,i){let n=i.position,s=i.dimensions;return t.y<n.y+s.height&&t.y+e.height>n.y&&t.z<n.z+s.depth&&t.z+e.depth>n.z}function St(t,e,i){let n=i.position,s=i.dimensions;return t.x<n.x+s.width&&t.x+e.width>n.x&&t.z<n.z+s.depth&&t.z+e.depth>n.z}function It(t,e,i){let n=i.position,s=i.dimensions;return t.x<n.x+s.width&&t.x+e.width>n.x&&t.y<n.y+s.height&&t.y+e.height>n.y}function K(t,e,i,n,s){let{position:o,dimensions:r}=e,a=[],u=$(o.x+r.width,o.y,o.z,i,n,s);u&&a.push(u);let h=$(o.x,o.y+r.height,o.z,i,n,s);h&&a.push(h);let d=$(o.x,o.y,o.z+r.depth,i,n,s);d&&a.push(d);let c=$(o.x+r.width,o.y,o.z+r.depth,i,n,s);c&&a.push(c);let l=$(o.x+r.width,o.y+r.height,o.z,i,n,s);l&&a.push(l);let p=$(o.x,o.y+r.height,o.z+r.depth,i,n,s);p&&a.push(p);let f=D(o,r);for(let g of t){let x=D(g,{width:.001,height:.001,depth:.001});B(x,f)||a.push(g);}let m=at(a);return s.maxPoints&&m.length>s.maxPoints?(m.sort((g,x)=>g.score-x.score),m.slice(0,s.maxPoints)):m}function $(t,e,i,n,s,o){if(t<0||t>=n.width||e<0||e>=n.height||i<0||i>=n.depth)return null;let r=e,a=e===0;if(o.projectToSupport&&e>0){let h=At(t,i,s,e);h!==null?(r=h,a=true):e>0&&(a=false);}let u=E(t,r,i,n,a);return {x:t,y:r,z:i,score:u,onSupport:a}}function At(t,e,i,n){let s=null;for(let o of i){let r=o.position.x,a=o.position.y,u=o.position.z,h=o.dimensions;if(t>=r&&t<r+h.width&&e>=u&&e<u+h.depth){let d=a+h.height;d<=n&&(s===null||d>s)&&(s=d);}}return s}function E(t,e,i,n,s){let o=t/n.width,r=e/n.height,a=i/n.depth,u=r*100+a*10+o;return e===0&&(u-=20),s&&(u-=10),t===0&&(u-=5),i===0&&(u-=5),u}function at(t){let e=[];for(let n of t)e.some(o=>Math.abs(o.x-n.x)<.001&&Math.abs(o.y-n.y)<.001&&Math.abs(o.z-n.z)<.001)||e.push(n);return e}function Mt(t,e){let i=[],n={x:0,y:0,z:0,score:0,onSupport:true};if(i.push(n),!t.excludeZones||t.excludeZones.length===0)return i;for(let s of t.excludeZones)if(!(s.minY>0)){if(s.minX===0&&s.maxX<t.width){let o={x:s.maxX,y:0,z:0,score:E(s.maxX,0,0,t,true),onSupport:true};i.push(o),s.minZ===0&&s.maxZ<t.depth&&(i.push({x:0,y:0,z:s.maxZ,score:E(0,0,s.maxZ,t,true),onSupport:true}),i.push({x:s.maxX,y:0,z:s.maxZ,score:E(s.maxX,0,s.maxZ,t,true),onSupport:true}));}if(s.minZ===0&&s.maxZ<t.depth&&s.minX!==0){let o={x:0,y:0,z:s.maxZ,score:E(0,0,s.maxZ,t,true),onSupport:true};i.push(o);}s.minX>0&&i.push({x:0,y:0,z:0,score:0,onSupport:true}),s.minZ>0&&i.push({x:0,y:0,z:0,score:0,onSupport:true});}return at(i)}function $t(t,e,i={}){let n=O(),s=[],o=[];({heightTolerance:Math.min(t.height*.1,50)});let a=0;if(t.existingItems)for(let d of t.existingItems)n.insert(d),s.push(d),a=Math.max(a,d.position.y+d.dimensions.height);let h=[...[...e].sort((d,c)=>{let l=Math.max(d.height,d.width,d.depth);return Math.max(c.height,c.width,c.depth)-l})];for(;h.length>0&&a<t.height;){let d=Ct(h,t,a,s,n,i);if(d.items.length===0)break;for(let c of d.items){s.push(c),n.insert(c);let l=h.findIndex(p=>p.id===c.item.id);l!==-1&&h.splice(l,1);}a=d.yLevel+d.height;}return o.push(...h),{packed:s,unpacked:o}}function Ct(t,e,i,n,s,o,r){let a={yLevel:i,height:0,items:[],spaces:[{x:0,z:0,width:e.width,depth:e.depth}]},u=0,h=[...t];for(let d of h){if(a.items.some(l=>l.item.id===d.id))continue;let c=Dt(d,a,e,i,n,s,o);if(c){u===0&&(u=c.dimensions.height);let l={item:d,position:c.position,rotation:c.rotation,dimensions:c.dimensions};a.items.push(l),a.height=Math.max(a.height,c.dimensions.height),a.spaces=Tt(a.spaces,{x:c.position.x,z:c.position.z,width:c.dimensions.width,depth:c.dimensions.depth});}}return a}function Dt(t,e,i,n,s,o,r,a,u){let h=t.allowedRotations||T(t.rotationType||"all"),d=[...e.spaces].sort((c,l)=>c.z!==l.z?c.z-l.z:c.x-l.x);for(let c of d)for(let l of h){let p=I(t.width,t.height,t.depth,l);if(p.width>c.width||p.depth>c.depth)continue;let f={x:c.x,y:n,z:c.z};if(X(f,p,i)&&!N(f,p,i)&&!L(f,p,o)&&Y([...s,...e.items],t,i)){if(r.features?.supportCheck){let m=[...s,...e.items],g=t.requiresSupport??.5;if(!V(f,p,m,g))continue}return {position:f,rotation:l,dimensions:p}}}return null}function Tt(t,e){let i=[];for(let n of t){if(!Wt(n,e)){i.push(n);continue}let s=Et(n,e);i.push(...s);}return Pt(i)}function Wt(t,e){return !(t.x+t.width<=e.x||e.x+e.width<=t.x||t.z+t.depth<=e.z||e.z+e.depth<=t.z)}function Et(t,e){let i=[];return e.x+e.width<t.x+t.width&&i.push({x:e.x+e.width,z:t.z,width:t.x+t.width-(e.x+e.width),depth:t.depth}),e.z+e.depth<t.z+t.depth&&i.push({x:t.x,z:e.z+e.depth,width:t.width,depth:t.z+t.depth-(e.z+e.depth)}),t.x<e.x&&i.push({x:t.x,z:t.z,width:e.x-t.x,depth:t.depth}),t.z<e.z&&i.push({x:t.x,z:t.z,width:t.width,depth:e.z-t.z}),i}function Pt(t){return t.filter(i=>i.width>=1&&i.depth>=1)}function di(t,e,i){let n=new Map;for(let r of t){let a=r.position.y;n.has(a)||n.set(a,[]),n.get(a).push(r);}let s=[],o=[...n.keys()].sort((r,a)=>r-a);for(let r of o){let a=n.get(r),u=Math.max(...a.map(d=>d.dimensions.height)),h=0;if(e&&i){let d=e*i;d>0&&(h=a.reduce((l,p)=>l+p.dimensions.width*p.dimensions.depth,0)/d);}s.push({yLevel:r,height:u,items:a,coverage:h});}return s}function Ft(t,e,i={}){let n=O(),s=[],o=[];({depthTolerance:Math.min(t.depth*.1,50)});let a=0;if(t.existingItems)for(let d of t.existingItems)n.insert(d),s.push(d),a=Math.max(a,d.position.z+d.dimensions.depth);let h=[...[...e].sort((d,c)=>{let l=Math.max(d.depth,d.width,d.height);return Math.max(c.depth,c.width,c.height)-l})];for(;h.length>0&&a<t.depth;){let d=Rt(h,t,a,s,n,i);if(d.items.length===0)break;for(let c of d.items){s.push(c),n.insert(c);let l=h.findIndex(p=>p.id===c.item.id);l!==-1&&h.splice(l,1);}a=d.zStart+d.depth;}return o.push(...h),{packed:s,unpacked:o}}function Rt(t,e,i,n,s,o,r){let a={zStart:i,depth:0,items:[],spaces:[{x:0,y:0,width:e.width,height:e.height}]},u=0,h=[...t];for(let d of h){if(a.items.some(l=>l.item.id===d.id))continue;let c=Zt(d,a,e,i,n,s,o);if(c){u===0&&(u=c.dimensions.depth);let l={item:d,position:c.position,rotation:c.rotation,dimensions:c.dimensions};a.items.push(l),a.depth=Math.max(a.depth,c.dimensions.depth),a.spaces=Ot(a.spaces,{x:c.position.x,y:c.position.y,width:c.dimensions.width,height:c.dimensions.height});}}return a}function Zt(t,e,i,n,s,o,r,a,u){let h=t.allowedRotations||T(t.rotationType||"all"),d=[...e.spaces].sort((c,l)=>c.y!==l.y?c.y-l.y:c.x-l.x);for(let c of d)for(let l of h){let p=I(t.width,t.height,t.depth,l);if(p.width>c.width||p.height>c.height||n+p.depth>i.depth)continue;let f={x:c.x,y:c.y,z:n};if(X(f,p,i)&&!N(f,p,i)&&!L(f,p,o)&&Y([...s,...e.items],t,i)){if(r.features?.supportCheck){let m=[...s,...e.items],g=t.requiresSupport??.5;if(!V(f,p,m,g))continue}return {position:f,rotation:l,dimensions:p}}}return null}function Ot(t,e){let i=[];for(let n of t){if(!Lt(n,e)){i.push(n);continue}let s=Xt(n,e);i.push(...s);}return Nt(i)}function Lt(t,e){return !(t.x+t.width<=e.x||e.x+e.width<=t.x||t.y+t.height<=e.y||e.y+e.height<=t.y)}function Xt(t,e){let i=[];return e.x+e.width<t.x+t.width&&i.push({x:e.x+e.width,y:t.y,width:t.x+t.width-(e.x+e.width),height:t.height}),e.y+e.height<t.y+t.height&&i.push({x:t.x,y:e.y+e.height,width:t.width,height:t.y+t.height-(e.y+e.height)}),t.x<e.x&&i.push({x:t.x,y:t.y,width:e.x-t.x,height:t.height}),t.y<e.y&&i.push({x:t.x,y:t.y,width:t.width,height:e.y-t.y}),i}function Nt(t){return t.filter(i=>i.width>=1&&i.height>=1)}function li(t,e){let i=e.depth*.05,n=new Map;for(let r of t){let a=r.position.z,u=false;for(let[h]of n)if(Math.abs(a-h)<=i){n.get(h).push(r),u=true;break}u||n.set(a,[r]);}let s=[],o=[...n.keys()].sort((r,a)=>r-a);for(let r of o){let a=n.get(r),u=Math.max(...a.map(c=>c.position.z+c.dimensions.depth)),h=e.width*e.height,d=a.reduce((c,l)=>c+l.dimensions.width*l.dimensions.height,0);s.push({zStart:r,zEnd:u,items:a,utilization:d/h});}return s}function Yt(t,e,i={}){let n=O(),s=[],o=0;if(t.existingItems)for(let a of t.existingItems)n.insert(a),s.push(a),o=Math.max(o,a.position.y+a.dimensions.height);let r=[...e];for(;r.length>0&&o<t.height;){let a=Vt(r,t,o);if(!a||a.potentialItems.length===0)break;let u=Ut(r,t,o,a.height,s,n,i);if(u.placedItems.length===0)break;for(let h of u.placedItems){s.push(h),n.insert(h);let d=r.findIndex(c=>c.id===h.item.id);d!==-1&&r.splice(d,1);}o+=a.height;}return {packed:s,unpacked:r}}function Vt(t,e,i){let n=e.height-i,s=new Set;for(let r of t)r.width<=n&&s.add(r.width),r.height<=n&&s.add(r.height),r.depth<=n&&s.add(r.depth);if(s.size===0)return null;let o=[];for(let r of s){let a=Ht(t,e,r,n);o.push(a);}return o.sort((r,a)=>a.score-r.score),o[0]}function Ht(t,e,i,n){let s=[],o=0,r=0;for(let l of t){let p=l.allowedRotations||T(l.rotationType||"all");for(let f of p){let m=I(l.width,l.height,l.depth,f);if(m.height<=i){s.push(l),o+=m.width*m.depth,Math.abs(m.height-i)<1&&r++;break}}}let a=e.width*e.depth,u=Math.min(o/a,1),h=i/n,d=r/Math.max(s.length,1),c=u*100+(1-h)*20+d*30;return {height:i,score:c,potentialItems:s}}function Ut(t,e,i,n,s,o,r){let a=[],u=[{x:0,y:i,z:0,width:e.width,height:n,depth:e.depth}],h=[...t].sort((d,c)=>{let l=d.width*d.height*d.depth;return c.width*c.height*c.depth-l});for(let d of h){if(a.some(l=>l.item.id===d.id))continue;let c=jt(d,u,e,i,n,s,a,o,r);if(c){let l={item:d,position:c.position,rotation:c.rotation,dimensions:c.dimensions};a.push(l),Gt(u,c.position,c.dimensions);}}return {placedItems:a,gaps:u}}function jt(t,e,i,n,s,o,r,a,u){let h=t.allowedRotations||T(t.rotationType||"all"),d=null,c=[...e].sort((l,p)=>l.z!==p.z?l.z-p.z:l.x!==p.x?l.x-p.x:l.y-p.y);for(let l of c)for(let p of h){let f=I(t.width,t.height,t.depth,p);if(f.width>l.width||f.height>l.height||f.depth>l.depth||f.height>s)continue;let m={x:l.x,y:l.y,z:l.z};if(!X(m,f,i)||N(m,f,i)||L(m,f,a))continue;let g=[...o,...r];if(!Y(g,t,i))continue;if(u.features?.supportCheck){let w=t.requiresSupport??.5;if(!V(m,f,g,w))continue}let x=_t(l,f);(!d||x<d.score)&&(d={position:m,rotation:p,dimensions:f,score:x});}return d}function _t(t,e){let i=t.width-e.width,n=t.height-e.height,s=t.depth-e.depth,o=i*n*s,r=0;i===0&&(r-=100),n===0&&(r-=100),s===0&&(r-=100);let a=t.z+t.x*.1+t.y*.01;return o+r+a}function Gt(t,e,i){let n=e.x+i.width,s=e.y+i.height,o=e.z+i.depth,r=[];for(let u=0;u<t.length;u++){let h=t[u];if(e.x>=h.x+h.width||n<=h.x||e.y>=h.y+h.height||s<=h.y||e.z>=h.z+h.depth||o<=h.z){r.push(h);continue}n<h.x+h.width&&r.push({x:n,y:h.y,z:h.z,width:h.x+h.width-n,height:h.height,depth:h.depth}),s<h.y+h.height&&r.push({x:h.x,y:s,z:h.z,width:h.width,height:h.y+h.height-s,depth:h.depth}),o<h.z+h.depth&&r.push({x:h.x,y:h.y,z:o,width:h.width,height:h.height,depth:h.z+h.depth-o}),e.x>h.x&&r.push({x:h.x,y:h.y,z:h.z,width:e.x-h.x,height:h.height,depth:h.depth}),e.y>h.y&&r.push({x:h.x,y:h.y,z:h.z,width:h.width,height:e.y-h.y,depth:h.depth}),e.z>h.z&&r.push({x:h.x,y:h.y,z:h.z,width:h.width,height:h.height,depth:e.z-h.z});}t.length=0;let a=1;for(let u of r)u.width>=a&&u.height>=a&&u.depth>=a&&t.push(u);qt(t);}function qt(t){let e=true,i=0,n=Math.max(t.length*t.length,1e3);for(;e&&i<n;){e=false,i++;for(let s=0;s<t.length;s++){for(let o=s+1;o<t.length;o++){let r=t[s],a=t[o],u=Kt(r,a);if(u){t[s]=u,t.splice(o,1),e=true;break}}if(e)break}}}function Kt(t,e){return Math.abs(t.x+t.width-e.x)<.001&&Math.abs(t.y-e.y)<.001&&Math.abs(t.height-e.height)<.001&&Math.abs(t.z-e.z)<.001&&Math.abs(t.depth-e.depth)<.001?{x:t.x,y:t.y,z:t.z,width:t.width+e.width,height:t.height,depth:t.depth}:Math.abs(t.y+t.height-e.y)<.001&&Math.abs(t.x-e.x)<.001&&Math.abs(t.width-e.width)<.001&&Math.abs(t.z-e.z)<.001&&Math.abs(t.depth-e.depth)<.001?{x:t.x,y:t.y,z:t.z,width:t.width,height:t.height+e.height,depth:t.depth}:Math.abs(t.z+t.depth-e.z)<.001&&Math.abs(t.x-e.x)<.001&&Math.abs(t.width-e.width)<.001&&Math.abs(t.y-e.y)<.001&&Math.abs(t.height-e.height)<.001?{x:t.x,y:t.y,z:t.z,width:t.width,height:t.height,depth:t.depth+e.depth}:null}function Jt(t,e={}){let i=e.populationSize??30,n=e.generations??50,s=e.crossoverRate??.8,o=e.mutationRate??.2,r=e.elitismCount??2,a=e.timeBudgetMs??5e3,u=Date.now(),h=[],d=[];for(let g of t.packed){d.push(g.bin);for(let x of g.items)h.push(x.item);}if(h.push(...t.unpacked),h.length===0||d.length===0)return t;let c=d[0],l=te(h,i);J(l,h,c,e.packOptions);for(let g=0;g<n&&!(Date.now()-u>a);g++){let x=[];l.sort((w,z)=>z.fitness-w.fitness);for(let w=0;w<r&&w<l.length;w++)x.push({...l[w]});for(;x.length<i;){let w=Q(l),z=Q(l),b;Math.random()<s?b=ee(w,z):b={ordering:[...w.ordering],fitness:0},Math.random()<o&&ie(b),x.push(b);}J(x,h,c,e.packOptions),l=x;}l.sort((g,x)=>x.fitness-g.fitness);let p=l[0],f=t.packed[0]?.utilization??0,m=p.fitness;if(m>f&&p.result){let g=c.width*c.height*c.depth,x=p.result.packed.reduce((M,k)=>M+k.dimensions.width*k.dimensions.height*k.dimensions.depth,0),w=p.result.packed.reduce((M,k)=>M+(k.item.weight||0),0),z=Qt(p.result.packed);return {packed:[{bin:c,items:p.result.packed,utilization:m,weight:w,centerOfGravity:z}],unpacked:p.result.unpacked,stats:{totalBins:1,totalItems:h.length,packedItems:p.result.packed.length,unpackedItems:p.result.unpacked.length,avgUtilization:m,totalVolume:g,usedVolume:x,totalWeight:w,actualWeight:w}}}return t}function Qt(t){if(t.length===0)return {x:0,y:0,z:0};let e=0,i=0,n=0,s=0;for(let o of t){let r=o.item.weight||1,a=o.position.x+o.dimensions.width/2,u=o.position.y+o.dimensions.height/2,h=o.position.z+o.dimensions.depth/2;i+=a*r,n+=u*r,s+=h*r,e+=r;}return {x:i/e,y:n/e,z:s/e}}function te(t,e){let i=[];i.push({ordering:t.map(o=>o.id),fitness:0});let n=[...t].sort((o,r)=>{let a=o.width*o.height*o.depth;return r.width*r.height*r.depth-a});i.push({ordering:n.map(o=>o.id),fitness:0});let s=[...t].sort((o,r)=>{let a=o.width*o.depth;return r.width*r.depth-a});for(i.push({ordering:s.map(o=>o.id),fitness:0});i.length<e;){let o=ne(t.map(r=>r.id));i.push({ordering:o,fitness:0});}return i}function J(t,e,i,n){let s=new Map(e.map(o=>[o.id,o]));for(let o of t)if(o.fitness===0){let r=o.ordering.map(p=>s.get(p)).filter(p=>p!==void 0),a=G(i,r,n),u=i.width*i.height*i.depth,h=a.packed.reduce((p,f)=>p+f.dimensions.width*f.dimensions.height*f.dimensions.depth,0),d=u>0?h/u:0,c=a.unpacked.length*.05,l=(isNaN(d)?0:d)-c;o.fitness=Math.max(0,l),o.result=a;}}function Q(t,e=3){let i=null;for(let n=0;n<e;n++){let s=Math.floor(Math.random()*t.length),o=t[s];(!i||o.fitness>i.fitness)&&(i=o);}return i}function ee(t,e){let i=t.ordering.length;if(i<3)return {ordering:[...t.ordering],fitness:0};let n=Math.floor(Math.random()*i),s=n+Math.floor(Math.random()*(i-n)),o=new Array(i).fill(null),r=new Set;for(let u=n;u<=s;u++)o[u]=t.ordering[u],r.add(t.ordering[u]);let a=(s+1)%i;for(let u of e.ordering)if(!r.has(u)){for(;o[a]!==null;)a=(a+1)%i;o[a]=u,a=(a+1)%i;}return {ordering:o,fitness:0}}function ie(t){let e=t.ordering.length;if(!(e<2)){if(Math.random()<.5){let i=Math.floor(Math.random()*e),n=Math.floor(Math.random()*e);for(;n===i;)n=Math.floor(Math.random()*e);let s=t.ordering[i];t.ordering[i]=t.ordering[n],t.ordering[n]=s;}else {let i=Math.floor(Math.random()*e),n=Math.floor(Math.random()*e),[s]=t.ordering.splice(i,1);t.ordering.splice(n,0,s);}t.fitness=0,t.result=void 0;}}function ne(t){let e=[...t];for(let i=e.length-1;i>0;i--){let n=Math.floor(Math.random()*(i+1));[e[i],e[n]]=[e[n],e[i]];}return e}function Z(t){return {ordering:[...t],fitness:0,result:void 0}}function C(t){return {ordering:[...t.ordering],fitness:t.fitness,result:t.result?{...t.result}:void 0}}function F(t,e,i,n){let s=new Map(e.map(c=>[c.id,c])),o=t.ordering.map(c=>s.get(c)).filter(c=>c!==void 0),r=G(i,o,n),a=i.width*i.height*i.depth,u=r.packed.reduce((c,l)=>c+l.dimensions.width*l.dimensions.height*l.dimensions.depth,0),h=a>0?u/a:0,d=r.unpacked.length*.05;t.fitness=Math.max(0,h-d),t.result=r;}function se(t,e){let i=[...t],{type:n,i:s,j:o}=e;switch(n){case "swap":[i[s],i[o]]=[i[o],i[s]];break;case "insert":let[r]=i.splice(s,1);i.splice(o,0,r);break;case "reverse":let a=Math.min(s,o),u=Math.max(s,o),h=i.slice(a,u+1).reverse();i.splice(a,u-a+1,...h);break;case "2-opt":let d=Math.min(s,o),c=Math.max(s,o);for(;d<c;)[i[d],i[c]]=[i[c],i[d]],d++,c--;break}return i}function ht(t,e=["swap","insert"]){let i=t.length;if(i<2)return {ordering:[...t],move:{type:"swap",i:0,j:0}};let n=e[Math.floor(Math.random()*e.length)],s=Math.floor(Math.random()*i),o=Math.floor(Math.random()*i);for(;o===s;)o=Math.floor(Math.random()*i);let r={type:n,i:s,j:o};return {ordering:se(t,r),move:r}}function oe(t,e,i=["swap","insert"]){let n=[],s=new Set;for(;n.length<e;){let o=ht(t,i),r=o.ordering.join(",");if(s.has(r)||(s.add(r),n.push(o)),s.size>e*3)break}return n}function re(t){if(t.length===0)return {x:0,y:0,z:0};let e=0,i=0,n=0,s=0;for(let o of t){let r=o.item.weight||1,a=o.position.x+o.dimensions.width/2,u=o.position.y+o.dimensions.height/2,h=o.position.z+o.dimensions.depth/2;i+=a*r,n+=u*r,s+=h*r,e+=r;}return {x:i/e,y:n/e,z:s/e}}function ut(t,e,i){if(!t.result)return {packed:[],unpacked:i,stats:{totalBins:1,totalItems:i.length,packedItems:0,unpackedItems:i.length,avgUtilization:0,totalVolume:e.width*e.height*e.depth,usedVolume:0,totalWeight:0,actualWeight:0}};let n=e.width*e.height*e.depth,s=t.result.packed.reduce((u,h)=>u+h.dimensions.width*h.dimensions.height*h.dimensions.depth,0),o=t.result.packed.reduce((u,h)=>u+(h.item.weight||0),0),r=re(t.result.packed);return {packed:[{bin:e,items:t.result.packed,utilization:t.fitness,weight:o,centerOfGravity:r}],unpacked:t.result.unpacked,stats:{totalBins:1,totalItems:i.length,packedItems:t.result.packed.length,unpackedItems:t.result.unpacked.length,avgUtilization:t.fitness,totalVolume:n,usedVolume:s,totalWeight:o,actualWeight:o}}}function ct(t){let e=[];e.push(t.map(r=>r.id));let i=[...t].sort((r,a)=>{let u=r.width*r.height*r.depth;return a.width*a.height*a.depth-u});e.push(i.map(r=>r.id));let n=[...t].sort((r,a)=>{let u=r.width*r.depth;return a.width*a.depth-u});e.push(n.map(r=>r.id));let s=[...t].sort((r,a)=>a.height-r.height);e.push(s.map(r=>r.id));let o=[...t].sort((r,a)=>(a.weight||0)-(r.weight||0));return e.push(o.map(r=>r.id)),e}function ae(t,e,i){if(e>t)return 1;let n=e-t;return Math.exp(n/i)}function he(t,e,i,n,s){let{initialTemperature:o,finalTemperature:r,coolingRate:a,iterationsPerTemp:u,timeBudgetMs:h,maxIterations:d,packOptions:c,onProgress:l}=n,p=o,f=C(t),m=C(f),g=0;for(F(f,e,i,c),m.fitness=f.fitness,m.result=f.result;p>r&&!(g>=d||Date.now()-s>h);){for(let x=0;x<u;x++){g++;let{ordering:w}=ht(f.ordering,["swap","insert"]),z=Z(w);F(z,e,i,c);let b=ae(f.fitness,z.fitness,p);Math.random()<b&&(f=z,f.fitness>m.fitness&&(m=C(f))),l&&g%50===0&&l({iteration:g,bestFitness:m.fitness,currentFitness:f.fitness,elapsedMs:Date.now()-s,info:{temperature:p}});}p*=a;}return {best:m,iterations:g}}function ue(t,e={}){let i={initialTemperature:Math.max(.001,e.initialTemperature??1),finalTemperature:Math.max(1e-4,e.finalTemperature??.001),coolingRate:Math.max(.5,Math.min(.9999,e.coolingRate??.995)),iterationsPerTemp:Math.max(1,e.iterationsPerTemp??10),restarts:Math.max(1,e.restarts??1),maxIterations:Math.max(1,e.maxIterations??5e3),timeBudgetMs:Math.max(100,e.timeBudgetMs??5e3),packOptions:e.packOptions,onProgress:e.onProgress},n=Date.now(),s=[],o=[];for(let c of t.packed){o.push(c.bin);for(let l of c.items)s.push(l.item);}if(s.push(...t.unpacked),s.length===0||o.length===0)return t;let r=o[0],a=t.packed[0]?.utilization??0,u=ct(s),h=null;for(let c=0;c<i.restarts&&!(Date.now()-n>i.timeBudgetMs);c++){let l=u[c%u.length],p=Z(l),{best:f}=he(p,s,r,i,n);(!h||f.fitness>h.fitness)&&(h=f);}return h&&h.fitness>a?ut(h,r,s):t}function dt(t){let[e,i]=[Math.min(t.i,t.j),Math.max(t.i,t.j)];return `${t.type}:${e}:${i}`}function ce(t,e,i){let n=dt(e),s=t.get(n);return s!==void 0&&s>i}function de(t,e,i,n){let s=dt(e);t.set(s,i+n);}function le(t,e){for(let[i,n]of t)n<=e&&t.delete(i);}function pe(t,e,i,n,s){let{tabuListSize:o,neighborhoodSize:r,useAspiration:a,diversificationFreq:u,maxIterations:h,timeBudgetMs:d,packOptions:c,onProgress:l}=n,p=C(t),f=C(p),m=new Map;F(p,e,i,c),f.fitness=p.fitness,f.result=p.result;let g=0,x=0;for(;g<h&&!(Date.now()-s>d);){g++,x++;let w=oe(p.ordering,r,["swap","insert"]),z=null,b=null,M=-1/0;for(let{ordering:k,move:q}of w){let W=Z(k);F(W,e,i,c);let xt=ce(m,q,g),wt=a&&W.fitness>f.fitness;(!xt||wt)&&W.fitness>M&&(z=W,b=q,M=W.fitness);}if(z&&b&&(p=z,de(m,b,g,o),p.fitness>f.fitness&&(f=C(p),x=0)),u>0&&x>=u){let k=[...p.ordering].sort(()=>Math.random()-.5);p=Z(k),F(p,e,i,c),x=0,m.clear();}g%20===0&&le(m,g),l&&g%20===0&&l({iteration:g,bestFitness:f.fitness,currentFitness:p.fitness,elapsedMs:Date.now()-s,info:{tabuListSize:m.size}});}return {best:f,iterations:g}}function fe(t,e={}){let i={tabuListSize:e.tabuListSize??20,neighborhoodSize:e.neighborhoodSize??30,useAspiration:e.useAspiration??true,diversificationFreq:e.diversificationFreq??50,restarts:e.restarts??1,maxIterations:e.maxIterations??1e3,timeBudgetMs:e.timeBudgetMs??5e3,packOptions:e.packOptions,onProgress:e.onProgress},n=Date.now(),s=[],o=[];for(let c of t.packed){o.push(c.bin);for(let l of c.items)s.push(l.item);}if(s.push(...t.unpacked),s.length===0||o.length===0)return t;let r=o[0],a=t.packed[0]?.utilization??0,u=ct(s),h=null;for(let c=0;c<i.restarts&&!(Date.now()-n>i.timeBudgetMs);c++){let l=u[c%u.length],p=Z(l),{best:f}=pe(p,s,r,i,n);(!h||f.fitness>h.fitness)&&(h=f);}return h&&h.fitness>a?ut(h,r,s):t}function pi(t,e){if(!e.incompatibleWith||e.incompatibleWith.length===0)return true;for(let i of t){let n=i.item.groupId;if(n&&e.incompatibleWith.includes(n))return false}return true}function fi(t){let e=new Map;for(let i of t){let n=i.groupId||"__ungrouped__";e.has(n)||e.set(n,[]),e.get(n).push(i);}return e}function me(t){return [...t].sort((e,i)=>{let n=e.deliveryOrder??0;return (i.deliveryOrder??0)-n})}function ge(t,e=false){return [...t].sort((i,n)=>{let s=i.width*i.height*i.depth,o=n.width*n.height*n.depth;return e?s-o:o-s})}function xe(t,e=false){return [...t].sort((i,n)=>{let s=i.weight??0,o=n.weight??0;return e?s-o:o-s})}var we={algorithm:"extreme-point",preprocessor:"none",enhancer:"none",features:{supportCheck:true,weightBalance:false,stackingLimit:true},constraints:{respectDeliveryOrder:false,keepGroupsTogether:false,enforceIncompatibility:true},optimize:{target:"space"},binSelection:"first-fit",spatialIndex:"naive"};function A(t){let e={...we,...t.options},{bins:i,items:n}=t;if(i.length===0)return ve(n);let s=[...n];e.constraints?.respectDeliveryOrder?s=me(s):s=ge(s),e.features?.weightBalance&&(s=xe(s));let o=[],r=[...s];for(let u of i){if(r.length===0)break;let{packed:h,unpacked:d}=ze(u,r,e);h.length>0&&o.push(be(u,h)),r=d;}let a=Be(o,r,n.length);return e.enhancer&&e.enhancer!=="none"?ye(a,e):a}function ye(t,e){let i={timeBudgetMs:e.timeBudgetMs??5e3,packOptions:e};switch(e.enhancer){case "genetic":return Jt(t,i);case "simulated-annealing":return ue(t,i);case "tabu-search":return fe(t,i);default:return t}}function ze(t,e,i){switch(i.algorithm){case "layer-building":return $t(t,e,i);case "wall-building":return Ft(t,e,i);case "eb-afit":return Yt(t,e,i);default:return G(t,e,i)}}function be(t,e){let i=t.width*t.height*t.depth,n=e.reduce((r,a)=>r+P(a.dimensions),0),s=zt(e),o=ot(e,t);return {bin:t,items:e,utilization:i>0?n/i:0,weight:s,centerOfGravity:o}}function ve(t){return {packed:[],unpacked:t,stats:lt([],t.length)}}function Be(t,e,i){return {packed:t,unpacked:e,stats:lt(t,i)}}function lt(t,e){let i=t.reduce((u,h)=>u+h.items.length,0),n=t.reduce((u,h)=>u+h.bin.width*h.bin.height*h.bin.depth,0),s=t.reduce((u,h)=>u+h.items.reduce((d,c)=>d+P(c.dimensions),0),0),o=t.reduce((u,h)=>u+h.weight,0),r=t.reduce((u,h)=>u+(h.bin.cost||0),0),a=t.length>0?t.reduce((u,h)=>u+h.utilization,0)/t.length:0;return {totalBins:t.length,totalItems:e,packedItems:i,unpackedItems:e-i,avgUtilization:a,totalVolume:n,usedVolume:s,totalWeight:o,totalCost:r>0?r:void 0,actualWeight:o}}var ke=class{bins=[];items=[];options={};addBin(t){return this.bins.push(t),this}addBins(t){return this.bins.push(...t),this}addItem(t){return this.items.push(t),this}addItems(t){return this.items.push(...t),this}setOptions(t){return this.options={...this.options,...t},this}pack(t){let e={...this.options,...t};return A({bins:this.bins,items:this.items,options:e})}reset(){return this.bins=[],this.items=[],this.options={},this}getBins(){return [...this.bins]}getItems(){return [...this.items]}getOptions(){return {...this.options}}};function mi(){return new ke}function gi(t,e={}){let i=e.minBlockSize??2,n=e.maxBlockSize??27,s=e.tolerancePct??0,o=[],r=[],a=Se(t,s);for(let[,u]of a)if(u.length>=i){let h=Ie(u,n,e);o.push(...h.blocks),r.push(...h.remaining);}else r.push(...u);return {blocks:o,remaining:r}}function Se(t,e){let i=new Map;for(let n of t){let o=[n.width,n.height,n.depth].sort((r,a)=>r-a).map(r=>Math.round(r/(1+e))).join("x");i.has(o)||i.set(o,[]),i.get(o).push(n);}return i}function Ie(t,e,i){let n=[],s=[...t],o=t[0],r={width:o.width,height:o.height,depth:o.depth},a=Ae(e);if(a.sort((u,h)=>{let d=u.countX*u.countY*u.countZ;return h.countX*h.countY*h.countZ-d}),i.optimizeForContainer){let u=i.optimizeForContainer;a.sort((h,d)=>{let c={width:h.countX*r.width,height:h.countY*r.height,depth:h.countZ*r.depth},l={width:d.countX*r.width,height:d.countY*r.height,depth:d.countZ*r.depth},p=tt(c,u);return tt(l,u)-p});}for(let u of a){let h=u.countX*u.countY*u.countZ;for(;s.length>=h;){let d=s.splice(0,h),c=Me(d,u,r);n.push(c);}if(s.length===0)break}return {blocks:n,remaining:s}}function Ae(t){let e=[];for(let i=1;i<=t;i++)for(let n=1;n<=t/i;n++)for(let s=1;s<=t/(i*n);s++){let o=i*n*s;o>=2&&o<=t&&e.push({countX:i,countY:n,countZ:s,itemWidth:0,itemHeight:0,itemDepth:0});}return e}function tt(t,e){if(t.width<=0||t.depth<=0||t.width>e.width||t.height>e.height||t.depth>e.depth)return 0;let i=e.width/t.width,n=e.depth/t.depth,s=e.width%t.width,o=e.depth%t.depth,r=(s+o)/(e.width+e.depth);return Math.floor(i)*Math.floor(n)*(1-r)}function Me(t,e,i){let n=t.reduce((s,o)=>s+(o.weight||0),0);return {id:`block_${t[0].id}_${t.length}`,originalItems:t,width:e.countX*i.width,height:e.countY*i.height,depth:e.countZ*i.depth,weight:n,count:t.length,arrangement:{...e,itemWidth:i.width,itemHeight:i.height,itemDepth:i.depth}}}function xi(t){let e=[];for(let i of t)e.push(...i.originalItems);return e}var $e={maxItemsPerNode:8,maxDepth:8,minNodeSize:1},et=class S{bounds;items=[];children=null;depth;constructor(e,i){this.bounds=e,this.depth=i;}isLeaf(){return this.children===null}getCenter(){return {x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2,z:(this.bounds.minZ+this.bounds.maxZ)/2}}subdivide(){let e=this.getCenter(),{minX:i,minY:n,minZ:s,maxX:o,maxY:r,maxZ:a}=this.bounds;this.children=[new S({minX:i,minY:n,minZ:s,maxX:e.x,maxY:e.y,maxZ:e.z},this.depth+1),new S({minX:e.x,minY:n,minZ:s,maxX:o,maxY:e.y,maxZ:e.z},this.depth+1),new S({minX:i,minY:e.y,minZ:s,maxX:e.x,maxY:r,maxZ:e.z},this.depth+1),new S({minX:e.x,minY:e.y,minZ:s,maxX:o,maxY:r,maxZ:e.z},this.depth+1),new S({minX:i,minY:n,minZ:e.z,maxX:e.x,maxY:e.y,maxZ:a},this.depth+1),new S({minX:e.x,minY:n,minZ:e.z,maxX:o,maxY:e.y,maxZ:a},this.depth+1),new S({minX:i,minY:e.y,minZ:e.z,maxX:e.x,maxY:r,maxZ:a},this.depth+1),new S({minX:e.x,minY:e.y,minZ:e.z,maxX:o,maxY:r,maxZ:a},this.depth+1)];}},Ce=class{root;config;itemCount=0;itemMap=new Map;constructor(t,e={}){this.config={...$e,...e},this.root=new et(t,0);}insert(t){let e=v(t);if(!B(e,this.root.bounds)){this.root.items.push(t),this.itemMap.set(t.item.id,t),this.itemCount++;return}this.insertIntoNode(this.root,t,e),this.itemMap.set(t.item.id,t),this.itemCount++;}insertIntoNode(t,e,i){if(t.isLeaf()){t.items.push(e),this.shouldSubdivide(t)&&this.subdivideNode(t);return}let n=false;for(let s of t.children)B(i,s.bounds)&&(this.insertIntoNode(s,e,i),n=true);n||t.items.push(e);}shouldSubdivide(t){if(t.items.length<=this.config.maxItemsPerNode||t.depth>=this.config.maxDepth)return false;let e=t.bounds.maxX-t.bounds.minX,i=t.bounds.maxY-t.bounds.minY,n=t.bounds.maxZ-t.bounds.minZ;return !(e/2<this.config.minNodeSize||i/2<this.config.minNodeSize||n/2<this.config.minNodeSize)}subdivideNode(t){t.subdivide();let e=t.items;t.items=[];for(let i of e){let n=v(i),s=false;for(let o of t.children)B(n,o.bounds)&&(o.items.push(i),s=true);s||t.items.push(i);}}remove(t){this.itemMap.has(t.item.id)&&(this.removeFromNode(this.root,t),this.itemMap.delete(t.item.id),this.itemCount--);}removeFromNode(t,e){let i=t.items.findIndex(n=>n.item.id===e.item.id);if(i!==-1)return t.items.splice(i,1),true;if(!t.isLeaf()){let n=v(e);for(let s of t.children)if(B(n,s.bounds)&&this.removeFromNode(s,e))return true}return false}query(t){let e=[],i=new Set;return this.queryNode(this.root,t,e,i),e}queryNode(t,e,i,n){for(let s of t.items)if(!n.has(s.item.id)){let o=v(s);B(o,e)&&(i.push(s),n.add(s.item.id));}if(!t.isLeaf())for(let s of t.children)B(s.bounds,e)&&this.queryNode(s,e,i,n);}clear(){this.root=new et(this.root.bounds,0),this.itemMap.clear(),this.itemCount=0;}getAll(){return Array.from(this.itemMap.values())}get size(){return this.itemCount}getStats(){let t={totalNodes:0,leafNodes:0,maxDepth:0,itemCount:this.itemCount,avgItemsPerLeaf:0},e=0;return this.collectStats(this.root,t,i=>{e+=i;}),t.avgItemsPerLeaf=t.leafNodes>0?e/t.leafNodes:0,t}collectStats(t,e,i){if(e.totalNodes++,e.maxDepth=Math.max(e.maxDepth,t.depth),t.isLeaf())e.leafNodes++,i(t.items.length);else for(let n of t.children)this.collectStats(n,e,i);}};function wi(t,e){return new Ce(t,e)}var De=1e3,U=De;function yi(t){U=t;}function zi(){return U}function bi(t){return Math.round(t*U)}function vi(t){return t/U}function Te(t,e,i,n,s={}){let o=[],r=[],a=We(e,i,n);a&&o.push(a);let u=Ee(t,e);o.push(...u);let h=Pe(e);o.push(...h);let d=Re(e);if(d&&o.push(d),s.checkSupport){let f=it(e);o.push(...f);}else {let f=it(e);for(let m of f)r.push({type:"gap",message:m.message});}let c=t.width*t.height*t.depth,l=e.reduce((f,m)=>f+m.dimensions.width*m.dimensions.height*m.dimensions.depth,0),p=c>0?l/c:0;return p<.5&&e.length>0&&r.push({type:"utilization",message:`Low utilization: ${(p*100).toFixed(1)}%`}),{valid:o.length===0,errors:o,warnings:r}}function We(t,e,i){let n=new Set(t.map(a=>a.item.id)),s=new Set(e.map(a=>a.id)),o=new Set(i.map(a=>a.id));if(n.size!==t.length)return {type:"count",message:"Duplicate items found in packed result"};let r=n.size+s.size;if(r!==o.size)return {type:"count",message:`Item count mismatch: ${r} in result vs ${o.size} original`};for(let a of o)if(!n.has(a)&&!s.has(a))return {type:"count",message:`Missing item: ${a}`,items:[a]};return null}function Ee(t,e){let i=[];for(let n of e){let{position:s,dimensions:o}=n;(s.x<0||s.y<0||s.z<0)&&i.push({type:"boundary",message:`Item ${n.item.id} has negative position: (${s.x}, ${s.y}, ${s.z})`,items:[n.item.id]}),s.x+o.width>t.width+.001&&i.push({type:"boundary",message:`Item ${n.item.id} exceeds bin width: ${s.x+o.width} > ${t.width}`,items:[n.item.id]}),s.y+o.height>t.height+.001&&i.push({type:"boundary",message:`Item ${n.item.id} exceeds bin height: ${s.y+o.height} > ${t.height}`,items:[n.item.id]}),s.z+o.depth>t.depth+.001&&i.push({type:"boundary",message:`Item ${n.item.id} exceeds bin depth: ${s.z+o.depth} > ${t.depth}`,items:[n.item.id]});}return i}function Pe(t){let e=[];for(let n=0;n<t.length;n++)for(let s=n+1;s<t.length;s++){let o=t[n],r=t[s];Fe(o.position,o.dimensions,r.position,r.dimensions,.001)&&e.push({type:"collision",message:`Collision detected between ${o.item.id} and ${r.item.id}`,items:[o.item.id,r.item.id]});}return e}function Fe(t,e,i,n,s){let o=t.x+e.width<=i.x+s||i.x+n.width<=t.x+s,r=t.y+e.height<=i.y+s||i.y+n.height<=t.y+s,a=t.z+e.depth<=i.z+s||i.z+n.depth<=t.z+s;return !(o||r||a)}function Re(t){for(let e of t){let{item:i,dimensions:n}=e,s=i.width*i.height*i.depth,o=n.width*n.height*n.depth;if(Math.abs(s-o)>.01)return {type:"volume",message:`Volume mismatch for ${i.id}: original ${s} vs placed ${o}`,items:[i.id]}}return null}function it(t){let e=[];for(let n of t){if(n.position.y<.001)continue;let s=false;for(let o of t){if(o.item.id===n.item.id)continue;let r=o.position.y+o.dimensions.height;if(Math.abs(r-n.position.y)<.001){let a=n.position.x<o.position.x+o.dimensions.width&&n.position.x+n.dimensions.width>o.position.x,u=n.position.z<o.position.z+o.dimensions.depth&&n.position.z+n.dimensions.depth>o.position.z;if(a&&u){s=true;break}}}s||e.push({type:"support",message:`Item ${n.item.id} is floating at y=${n.position.y}`,items:[n.item.id]});}return e}function Bi(t,e,i,n,s={}){return Te(t,e,i,n,s).valid}function Ze(t,e){let i={...t,bins:t.bins.map(n=>({...n,steps:n.steps.map(s=>{let{placedItem:o,...r}=s;return e.includeCoordinates?r:{...r,position:{description:r.position.description,referenceItemId:r.position.referenceItemId,relationship:r.position.relationship}}})}))};return JSON.stringify(i,null,2)}var Oe={en:{title:"Packing Instructions",generatedAt:"Generated at",summary:"Summary",binInfo:"Bin Information",binId:"Bin ID",binType:"Type",dimensions:"Dimensions",itemCount:"Item Count",totalWeight:"Total Weight",layerCount:"Layer Count",utilization:"Utilization",packingSteps:"Packing Steps",layer:"Layer",step:"Step",item:"Item",position:"Position",orientation:"Orientation",size:"Size",notes:"Notes",warnings:"Warnings",unpackedWarning:"items could not be packed",noItems:"No items to pack",actions:{place:"Place",stack:"Stack",rotate:"Place (rotated)"}},"zh-TW":{title:"\u88DD\u7BB1\u6307\u793A",generatedAt:"\u7522\u751F\u6642\u9593",summary:"\u6458\u8981",binInfo:"\u5BB9\u5668\u8CC7\u8A0A",binId:"\u5BB9\u5668 ID",binType:"\u985E\u578B",dimensions:"\u5C3A\u5BF8",itemCount:"\u7269\u54C1\u6578\u91CF",totalWeight:"\u7E3D\u91CD\u91CF",layerCount:"\u5C64\u6578",utilization:"\u7A7A\u9593\u4F7F\u7528\u7387",packingSteps:"\u88DD\u7BB1\u6B65\u9A5F",layer:"\u7B2C",step:"\u6B65\u9A5F",item:"\u7269\u54C1",position:"\u4F4D\u7F6E",orientation:"\u65B9\u5411",size:"\u5C3A\u5BF8",notes:"\u6CE8\u610F\u4E8B\u9805",warnings:"\u8B66\u544A",unpackedWarning:"\u500B\u7269\u54C1\u7121\u6CD5\u88DD\u5165",noItems:"\u6C92\u6709\u7269\u54C1\u9700\u8981\u88DD\u7BB1",actions:{place:"\u653E\u7F6E",stack:"\u5806\u758A",rotate:"\u65CB\u8F49\u653E\u7F6E"}}};function Le(t,e,i){let n=[],s=e.actions[t.action],o=`${t.step}. **${s}**\u3010${t.itemName}\u3011\u2192 ${t.position.description}`;if(n.push(o),i.detailLevel==="detailed"){let r=[],{width:a,height:u,depth:h}=t.dimensions;if(r.push(`${e.size}: ${a} \xD7 ${u} \xD7 ${h}`),i.includeCoordinates){let{x:d,y:c,z:l}=t.position.coordinates;r.push(`(${d}, ${c}, ${l})`);}i.includeWeight&&t.placedItem.item.weight&&r.push(`${t.placedItem.item.weight} kg`),r.length>0&&n.push(` - ${r.join(" | ")}`),t.notes.length>0&&t.notes.forEach(d=>{n.push(` - \u26A0\uFE0F ${d}`);});}return n.join(`
|
|
8
|
+
`)}function Xe(t,e,i,n){let s=[],{summary:o,steps:r}=t;if(s.push(`## ${i.binInfo} #${e+1}: ${o.binId}`),s.push(""),s.push(`| ${i.binType} | ${i.dimensions} | ${i.itemCount} | ${i.totalWeight} | ${i.layerCount} | ${i.utilization} |`),s.push("|------|------|------|------|------|------|"),s.push(`| ${o.binType} | ${o.binDimensions} | ${o.itemCount} | ${o.totalWeight} kg | ${o.layerCount} | ${o.utilization}% |`),s.push(""),s.push(`### ${i.packingSteps}`),s.push(""),r.length===0)return s.push(`*${i.noItems}*`),s.push(""),s.join(`
|
|
9
|
+
`);let a=new Map;r.forEach(h=>{let d=a.get(h.layer)||[];d.push(h),a.set(h.layer,d);});let u=[...a.keys()].sort((h,d)=>h-d);for(let h of u){let d=a.get(h),c=n.language==="zh-TW"?`${i.layer} ${h} \u5C64`:`${i.layer} ${h}`;s.push(`#### ${c}`),s.push(""),d.forEach(l=>{s.push(Le(l,i,n));}),s.push("");}return t.notes.length>0&&(s.push(`### ${i.notes}`),s.push(""),t.notes.forEach(h=>{s.push(`- ${h}`);}),s.push("")),s.join(`
|
|
10
|
+
`)}function nt(t,e){let i=Oe[e.language],n=[];n.push(`# ${i.title}`),n.push("");let o=new Date(t.generatedAt).toLocaleString(e.language==="zh-TW"?"zh-TW":"en-US");return n.push(`> ${i.generatedAt}: ${o}`),n.push(""),t.globalNotes.length>0&&(n.push(`## \u26A0\uFE0F ${i.warnings}`),n.push(""),t.globalNotes.forEach(r=>{n.push(`- ${r}`);}),n.push("")),n.push(`## ${i.summary}`),n.push(""),n.push(e.language==="zh-TW"?`- \u7E3D\u5BB9\u5668\u6578: ${t.totalBins}`:`- Total Bins: ${t.totalBins}`),n.push(e.language==="zh-TW"?`- \u7E3D\u7269\u54C1\u6578: ${t.totalItems}`:`- Total Items: ${t.totalItems}`),n.push(""),n.push("---"),n.push(""),t.bins.forEach((r,a)=>{n.push(Xe(r,a,i,e)),a<t.bins.length-1&&(n.push("---"),n.push(""));}),n.join(`
|
|
11
|
+
`)}var Ne={en:{title:"Packing Instructions",generatedAt:"Generated at",summary:"Summary",binInfo:"Bin",binId:"ID",binType:"Type",dimensions:"Dimensions",itemCount:"Items",totalWeight:"Weight",layerCount:"Layers",utilization:"Utilization",packingSteps:"Packing Steps",layer:"Layer",step:"Step",item:"Item",position:"Position",size:"Size",notes:"Notes",warnings:"Warnings",printButton:"Print",actions:{place:"Place",stack:"Stack on",rotate:"Place (rotated)"}},"zh-TW":{title:"\u88DD\u7BB1\u6307\u793A",generatedAt:"\u7522\u751F\u6642\u9593",summary:"\u6458\u8981",binInfo:"\u5BB9\u5668",binId:"ID",binType:"\u985E\u578B",dimensions:"\u5C3A\u5BF8",itemCount:"\u7269\u54C1\u6578",totalWeight:"\u91CD\u91CF",layerCount:"\u5C64\u6578",utilization:"\u4F7F\u7528\u7387",packingSteps:"\u88DD\u7BB1\u6B65\u9A5F",layer:"\u7B2C",step:"\u6B65\u9A5F",item:"\u7269\u54C1",position:"\u4F4D\u7F6E",size:"\u5C3A\u5BF8",notes:"\u6CE8\u610F\u4E8B\u9805",warnings:"\u8B66\u544A",printButton:"\u5217\u5370",actions:{place:"\u653E\u7F6E",stack:"\u5806\u758A\u65BC",rotate:"\u65CB\u8F49\u653E\u7F6E"}}},Ye=`
|
|
12
|
+
* {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
body {
|
|
19
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
20
|
+
line-height: 1.6;
|
|
21
|
+
color: #1a1a1a;
|
|
22
|
+
background: #f5f5f5;
|
|
23
|
+
padding: 20px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.container {
|
|
27
|
+
max-width: 800px;
|
|
28
|
+
margin: 0 auto;
|
|
29
|
+
background: white;
|
|
30
|
+
padding: 40px;
|
|
31
|
+
border-radius: 8px;
|
|
32
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1 {
|
|
36
|
+
font-size: 28px;
|
|
37
|
+
color: #111;
|
|
38
|
+
margin-bottom: 8px;
|
|
39
|
+
padding-bottom: 16px;
|
|
40
|
+
border-bottom: 3px solid #3b82f6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h2 {
|
|
44
|
+
font-size: 20px;
|
|
45
|
+
color: #333;
|
|
46
|
+
margin: 24px 0 12px;
|
|
47
|
+
padding-bottom: 8px;
|
|
48
|
+
border-bottom: 1px solid #e5e7eb;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
h3 {
|
|
52
|
+
font-size: 16px;
|
|
53
|
+
color: #4b5563;
|
|
54
|
+
margin: 16px 0 8px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.meta {
|
|
58
|
+
color: #6b7280;
|
|
59
|
+
font-size: 14px;
|
|
60
|
+
margin-bottom: 24px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.warning-box {
|
|
64
|
+
background: #fef3c7;
|
|
65
|
+
border: 1px solid #f59e0b;
|
|
66
|
+
border-left: 4px solid #f59e0b;
|
|
67
|
+
padding: 12px 16px;
|
|
68
|
+
margin: 16px 0;
|
|
69
|
+
border-radius: 4px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.warning-box ul {
|
|
73
|
+
margin: 8px 0 0 20px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.summary-grid {
|
|
77
|
+
display: grid;
|
|
78
|
+
grid-template-columns: repeat(2, 1fr);
|
|
79
|
+
gap: 12px;
|
|
80
|
+
margin: 16px 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.summary-item {
|
|
84
|
+
background: #f9fafb;
|
|
85
|
+
padding: 12px;
|
|
86
|
+
border-radius: 6px;
|
|
87
|
+
border: 1px solid #e5e7eb;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.summary-item .label {
|
|
91
|
+
font-size: 12px;
|
|
92
|
+
color: #6b7280;
|
|
93
|
+
text-transform: uppercase;
|
|
94
|
+
letter-spacing: 0.5px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.summary-item .value {
|
|
98
|
+
font-size: 24px;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
color: #111;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.bin-card {
|
|
104
|
+
border: 1px solid #e5e7eb;
|
|
105
|
+
border-radius: 8px;
|
|
106
|
+
margin: 24px 0;
|
|
107
|
+
overflow: hidden;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.bin-header {
|
|
111
|
+
background: #3b82f6;
|
|
112
|
+
color: white;
|
|
113
|
+
padding: 12px 16px;
|
|
114
|
+
font-weight: 600;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.bin-info {
|
|
118
|
+
display: grid;
|
|
119
|
+
grid-template-columns: repeat(3, 1fr);
|
|
120
|
+
gap: 1px;
|
|
121
|
+
background: #e5e7eb;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.bin-info-item {
|
|
125
|
+
background: #f9fafb;
|
|
126
|
+
padding: 12px;
|
|
127
|
+
text-align: center;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.bin-info-item .label {
|
|
131
|
+
font-size: 11px;
|
|
132
|
+
color: #6b7280;
|
|
133
|
+
text-transform: uppercase;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.bin-info-item .value {
|
|
137
|
+
font-size: 16px;
|
|
138
|
+
font-weight: 600;
|
|
139
|
+
color: #111;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.layer-section {
|
|
143
|
+
padding: 16px;
|
|
144
|
+
border-top: 1px solid #e5e7eb;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.layer-title {
|
|
148
|
+
font-size: 14px;
|
|
149
|
+
font-weight: 600;
|
|
150
|
+
color: #3b82f6;
|
|
151
|
+
margin-bottom: 12px;
|
|
152
|
+
padding: 4px 8px;
|
|
153
|
+
background: #eff6ff;
|
|
154
|
+
border-radius: 4px;
|
|
155
|
+
display: inline-block;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.step {
|
|
159
|
+
display: flex;
|
|
160
|
+
gap: 12px;
|
|
161
|
+
padding: 12px;
|
|
162
|
+
margin: 8px 0;
|
|
163
|
+
background: #fafafa;
|
|
164
|
+
border-radius: 6px;
|
|
165
|
+
border-left: 3px solid #e5e7eb;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.step.action-place { border-left-color: #10b981; }
|
|
169
|
+
.step.action-stack { border-left-color: #f59e0b; }
|
|
170
|
+
.step.action-rotate { border-left-color: #8b5cf6; }
|
|
171
|
+
|
|
172
|
+
.step-number {
|
|
173
|
+
width: 28px;
|
|
174
|
+
height: 28px;
|
|
175
|
+
background: #3b82f6;
|
|
176
|
+
color: white;
|
|
177
|
+
border-radius: 50%;
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
font-size: 12px;
|
|
182
|
+
font-weight: 600;
|
|
183
|
+
flex-shrink: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.step-content {
|
|
187
|
+
flex: 1;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.step-main {
|
|
191
|
+
font-weight: 500;
|
|
192
|
+
color: #111;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.step-action {
|
|
196
|
+
display: inline-block;
|
|
197
|
+
padding: 2px 6px;
|
|
198
|
+
border-radius: 3px;
|
|
199
|
+
font-size: 12px;
|
|
200
|
+
font-weight: 600;
|
|
201
|
+
margin-right: 4px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.step-action.place { background: #d1fae5; color: #065f46; }
|
|
205
|
+
.step-action.stack { background: #fef3c7; color: #92400e; }
|
|
206
|
+
.step-action.rotate { background: #ede9fe; color: #5b21b6; }
|
|
207
|
+
|
|
208
|
+
.step-item-name {
|
|
209
|
+
font-weight: 600;
|
|
210
|
+
color: #1f2937;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.step-details {
|
|
214
|
+
font-size: 13px;
|
|
215
|
+
color: #6b7280;
|
|
216
|
+
margin-top: 4px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.step-note {
|
|
220
|
+
font-size: 12px;
|
|
221
|
+
color: #b45309;
|
|
222
|
+
background: #fffbeb;
|
|
223
|
+
padding: 4px 8px;
|
|
224
|
+
border-radius: 4px;
|
|
225
|
+
margin-top: 6px;
|
|
226
|
+
display: inline-block;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.print-button {
|
|
230
|
+
position: fixed;
|
|
231
|
+
bottom: 20px;
|
|
232
|
+
right: 20px;
|
|
233
|
+
background: #3b82f6;
|
|
234
|
+
color: white;
|
|
235
|
+
border: none;
|
|
236
|
+
padding: 12px 24px;
|
|
237
|
+
border-radius: 8px;
|
|
238
|
+
font-size: 14px;
|
|
239
|
+
font-weight: 600;
|
|
240
|
+
cursor: pointer;
|
|
241
|
+
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
|
242
|
+
transition: all 0.2s;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.print-button:hover {
|
|
246
|
+
background: #2563eb;
|
|
247
|
+
transform: translateY(-1px);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@media print {
|
|
251
|
+
body {
|
|
252
|
+
background: white;
|
|
253
|
+
padding: 0;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.container {
|
|
257
|
+
box-shadow: none;
|
|
258
|
+
padding: 20px;
|
|
259
|
+
max-width: none;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.print-button {
|
|
263
|
+
display: none;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.bin-card {
|
|
267
|
+
break-inside: avoid;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.layer-section {
|
|
271
|
+
break-inside: avoid;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
`;function R(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Ve(t,e,i){let n=t.action,s=e.actions[t.action],{width:o,height:r,depth:a}=t.dimensions,u="";if(i.detailLevel==="detailed"){let d=[`${e.size}: ${o} \xD7 ${r} \xD7 ${a}`];if(i.includeWeight&&t.placedItem.item.weight&&d.push(`${t.placedItem.item.weight} kg`),i.includeCoordinates){let{x:c,y:l,z:p}=t.position.coordinates;d.push(`(${c}, ${l}, ${p})`);}u=`<div class="step-details">${d.join(" \xB7 ")}</div>`;}let h=t.notes.length>0?t.notes.map(d=>`<div class="step-note">\u26A0\uFE0F ${R(d)}</div>`).join(""):"";return `
|
|
275
|
+
<div class="step action-${n}">
|
|
276
|
+
<div class="step-number">${t.step}</div>
|
|
277
|
+
<div class="step-content">
|
|
278
|
+
<div class="step-main">
|
|
279
|
+
<span class="step-action ${n}">${s}</span>
|
|
280
|
+
<span class="step-item-name">\u3010${R(t.itemName)}\u3011</span>
|
|
281
|
+
\u2192 ${R(t.position.description)}
|
|
282
|
+
</div>
|
|
283
|
+
${u}
|
|
284
|
+
${h}
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
`}function He(t,e,i,n){let{summary:s,steps:o}=t,r=new Map;o.forEach(h=>{let d=r.get(h.layer)||[];d.push(h),r.set(h.layer,d);});let u=[...r.keys()].sort((h,d)=>h-d).map(h=>{let d=r.get(h),c=n.language==="zh-TW"?`${i.layer} ${h} \u5C64`:`${i.layer} ${h}`,l=d.map(p=>Ve(p,i,n)).join("");return `
|
|
288
|
+
<div class="layer-section">
|
|
289
|
+
<div class="layer-title">${c}</div>
|
|
290
|
+
${l}
|
|
291
|
+
</div>
|
|
292
|
+
`}).join("");return `
|
|
293
|
+
<div class="bin-card">
|
|
294
|
+
<div class="bin-header">${i.binInfo} #${e+1}: ${R(s.binId)}</div>
|
|
295
|
+
<div class="bin-info">
|
|
296
|
+
<div class="bin-info-item">
|
|
297
|
+
<div class="label">${i.dimensions}</div>
|
|
298
|
+
<div class="value">${s.binDimensions}</div>
|
|
299
|
+
</div>
|
|
300
|
+
<div class="bin-info-item">
|
|
301
|
+
<div class="label">${i.itemCount}</div>
|
|
302
|
+
<div class="value">${s.itemCount}</div>
|
|
303
|
+
</div>
|
|
304
|
+
<div class="bin-info-item">
|
|
305
|
+
<div class="label">${i.totalWeight}</div>
|
|
306
|
+
<div class="value">${s.totalWeight} kg</div>
|
|
307
|
+
</div>
|
|
308
|
+
<div class="bin-info-item">
|
|
309
|
+
<div class="label">${i.layerCount}</div>
|
|
310
|
+
<div class="value">${s.layerCount}</div>
|
|
311
|
+
</div>
|
|
312
|
+
<div class="bin-info-item">
|
|
313
|
+
<div class="label">${i.utilization}</div>
|
|
314
|
+
<div class="value">${s.utilization}%</div>
|
|
315
|
+
</div>
|
|
316
|
+
<div class="bin-info-item">
|
|
317
|
+
<div class="label">${i.binType}</div>
|
|
318
|
+
<div class="value">${s.binType}</div>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
${u}
|
|
322
|
+
</div>
|
|
323
|
+
`}function Ue(t,e){let i=Ne[e.language],s=new Date(t.generatedAt).toLocaleString(e.language==="zh-TW"?"zh-TW":"en-US"),o=t.globalNotes.length>0?`
|
|
324
|
+
<div class="warning-box">
|
|
325
|
+
<strong>\u26A0\uFE0F ${i.warnings}</strong>
|
|
326
|
+
<ul>
|
|
327
|
+
${t.globalNotes.map(u=>`<li>${R(u)}</li>`).join("")}
|
|
328
|
+
</ul>
|
|
329
|
+
</div>
|
|
330
|
+
`:"",r=`
|
|
331
|
+
<h2>${i.summary}</h2>
|
|
332
|
+
<div class="summary-grid">
|
|
333
|
+
<div class="summary-item">
|
|
334
|
+
<div class="label">${e.language==="zh-TW"?"\u7E3D\u5BB9\u5668\u6578":"Total Bins"}</div>
|
|
335
|
+
<div class="value">${t.totalBins}</div>
|
|
336
|
+
</div>
|
|
337
|
+
<div class="summary-item">
|
|
338
|
+
<div class="label">${e.language==="zh-TW"?"\u7E3D\u7269\u54C1\u6578":"Total Items"}</div>
|
|
339
|
+
<div class="value">${t.totalItems}</div>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
`,a=t.bins.map((u,h)=>He(u,h,i,e)).join("");return `<!DOCTYPE html>
|
|
343
|
+
<html lang="${e.language}">
|
|
344
|
+
<head>
|
|
345
|
+
<meta charset="UTF-8">
|
|
346
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
347
|
+
<title>${i.title}</title>
|
|
348
|
+
<style>${Ye}</style>
|
|
349
|
+
</head>
|
|
350
|
+
<body>
|
|
351
|
+
<div class="container">
|
|
352
|
+
<h1>${i.title}</h1>
|
|
353
|
+
<div class="meta">${i.generatedAt}: ${s}</div>
|
|
354
|
+
${o}
|
|
355
|
+
${r}
|
|
356
|
+
${a}
|
|
357
|
+
</div>
|
|
358
|
+
<button class="print-button" onclick="window.print()">\u{1F5A8}\uFE0F ${i.printButton}</button>
|
|
359
|
+
</body>
|
|
360
|
+
</html>`}var pt={en:{positions:{bottomLeft:"bottom-left corner",bottomRight:"bottom-right corner",topLeft:"top-left corner",topRight:"top-right corner",center:"center",above:"above",beside:"beside",behind:"behind",inFront:"in front of"},orientations:{upright:"upright",flat:"flat",sideways:"sideways",rotated90:"rotated 90\xB0",rotated180:"rotated 180\xB0",custom:"custom orientation"},notes:{heavyItem:"Heavy item - handle with care",fragile:"Fragile - this side up",stackable:"Stackable",floorOnly:"Must be placed on floor",groupWith:"Keep together with group",deliveryOrder:"Delivery priority"},layers:{bottom:"Bottom layer",middle:"Middle layer",top:"Top layer"}},"zh-TW":{positions:{bottomLeft:"\u5DE6\u4E0B\u89D2",bottomRight:"\u53F3\u4E0B\u89D2",topLeft:"\u5DE6\u4E0A\u89D2",topRight:"\u53F3\u4E0A\u89D2",center:"\u4E2D\u592E",above:"\u4E0A\u65B9",beside:"\u65C1\u908A",behind:"\u5F8C\u65B9",inFront:"\u524D\u65B9"},orientations:{upright:"\u76F4\u7ACB",flat:"\u5E73\u653E",sideways:"\u5074\u653E",rotated90:"\u65CB\u8F49 90\xB0",rotated180:"\u65CB\u8F49 180\xB0",custom:"\u81EA\u5B9A\u7FA9\u65B9\u5411"},notes:{heavyItem:"\u91CD\u7269 - \u5C0F\u5FC3\u642C\u904B",fragile:"\u6613\u788E - \u6B64\u9762\u671D\u4E0A",stackable:"\u53EF\u5806\u758A",floorOnly:"\u5FC5\u9808\u653E\u7F6E\u65BC\u5730\u9762",groupWith:"\u8207\u540C\u7D44\u7269\u54C1\u653E\u5728\u4E00\u8D77",deliveryOrder:"\u51FA\u8CA8\u512A\u5148\u9806\u5E8F"},layers:{bottom:"\u5E95\u5C64",middle:"\u4E2D\u5C64",top:"\u9802\u5C64"}}};function st(t,e){return Math.floor(t/e)+1}function je(t){let{rotation:e,item:i,dimensions:n}=t;return n.height===i.height?e===0?"upright":"rotated-90":n.height===i.width||n.height===i.depth?"flat":"custom"}function _e(t,e,i,n,s){let o=pt[s].positions,{position:r,dimensions:a}=t,u=r.x+a.width/2,h=r.z+a.depth/2,d=ft(t,n);if(d&&r.y>0)return {description:`${o.above} [${mt(d)}]`,coordinates:r,referenceItemId:d.item.id,relationship:"above"};let c=u<e/2,l=h<i/2,p;return c&&l?p=o.bottomLeft:!c&&l?p=o.bottomRight:c&&!l?p=o.topLeft:p=o.topRight,{description:p,coordinates:r}}function ft(t,e){for(let n of e){if(n===t)continue;let s=n.position.y+n.dimensions.height;if(Math.abs(s-t.position.y)>1)continue;let o=t.position.x<n.position.x+n.dimensions.width&&t.position.x+t.dimensions.width>n.position.x,r=t.position.z<n.position.z+n.dimensions.depth&&t.position.z+t.dimensions.depth>n.position.z;if(o&&r)return n}return null}function mt(t){let{item:e}=t;return e.metadata?.name&&typeof e.metadata.name=="string"?e.metadata.name:e.id}function Ge(t,e,i){let n=pt[e].notes,s=[],{item:o}=t;return i==="simple"||(o.weight&&o.weight>20&&s.push(n.heavyItem),o.requiresFloor&&s.push(n.floorOnly),o.groupId&&s.push(`${n.groupWith}: ${o.groupId}`),o.deliveryOrder&&s.push(`${n.deliveryOrder}: #${o.deliveryOrder}`)),s}function qe(t,e){return ft(t,e)?"stack":t.rotation!==0?"rotate":"place"}function Ke(t,e){let{bin:i,items:n,utilization:s,weight:o}=t,{language:r,detailLevel:a,layerHeightThreshold:u}=e,h=[...n].sort((f,m)=>f.position.y!==m.position.y?f.position.y-m.position.y:f.position.z!==m.position.z?f.position.z-m.position.z:f.position.x-m.position.x),d=h.reduce((f,m)=>{let g=st(m.position.y,u);return Math.max(f,g)},0),c={binId:i.id,binType:i.type,binDimensions:`${i.width} \xD7 ${i.height} \xD7 ${i.depth}`,itemCount:n.length,totalWeight:o,layerCount:d,utilization:Math.round(s*100)},l=h.map((f,m)=>{let g=st(f.position.y,u),x=je(f),w=_e(f,i.width,i.depth,n,r),z=Ge(f,r,a),b=qe(f,n);return {step:m+1,action:b,itemId:f.item.id,itemName:mt(f),position:w,dimensions:f.dimensions,orientation:x,layer:g,notes:z,placedItem:f}}),p=[];if(o>0&&i.maxWeight){let f=Math.round(o/i.maxWeight*100);p.push(r==="zh-TW"?`\u91CD\u91CF\u4F7F\u7528\u7387: ${f}%`:`Weight usage: ${f}%`);}return {summary:c,steps:l,notes:p}}function ki(t,e={}){let i={format:e.format??"markdown",language:e.language??"zh-TW",detailLevel:e.detailLevel??"detailed",includeCoordinates:e.includeCoordinates??false,includeWeight:e.includeWeight??true,layerHeightThreshold:e.layerHeightThreshold??100},n=t.packed.map(a=>Ke(a,i)),s=[];t.unpacked.length>0&&s.push(i.language==="zh-TW"?`\u8B66\u544A: ${t.unpacked.length} \u500B\u7269\u54C1\u7121\u6CD5\u88DD\u5165`:`Warning: ${t.unpacked.length} items could not be packed`);let o={generatedAt:new Date().toISOString(),totalBins:t.packed.length,totalItems:t.stats.packedItems,bins:n,globalNotes:s},r;switch(i.format){case "json":r=Ze(o,i);break;case "markdown":r=nt(o,i);break;case "html":r=Ue(o,i);break;default:r=nt(o,i);}return {instructions:o,formatted:r,format:i.format,language:i.language}}var Si=class{options;binStates=new Map;binOrder=[];stats;eventListeners=new Map;autoAddCounter=0;constructor(t={}){if(this.options={algorithm:t.algorithm??"online-extreme-point",binSelection:t.binSelection??"first-fit",autoAddBins:t.autoAddBins??false,binTemplate:t.binTemplate??{id:"auto-bin",type:"box",width:100,height:100,depth:100},maxBins:t.maxBins??100,features:t.features??{supportCheck:true},constraints:t.constraints??{}},this.stats={totalItems:0,placedItems:0,rejectedItems:0,binsInUse:0,avgUtilization:0,totalWeight:0},t.bins)for(let e of t.bins)this.addBin(e);}addBin(t){if(this.binStates.has(t.id))throw new Error(`Bin with id "${t.id}" already exists`);let e={bin:t,items:[],spatialIndex:O(),extremePoints:this.generateInitialExtremePoints(t),totalVolume:t.width*t.height*t.depth,usedVolume:0,weight:0};if(t.existingItems)for(let i of t.existingItems)e.items.push(i),e.spatialIndex.insert(i),e.usedVolume+=P(i.dimensions),e.weight+=i.item.weight??0,this.updateExtremePoints(e,i);this.binStates.set(t.id,e),this.binOrder.push(t.id),this.stats.binsInUse++,this.emit("bin-added",{bin:t});}removeBin(t){let e=this.binStates.get(t);if(!e)return null;let i={bin:e.bin,items:[...e.items],utilization:e.totalVolume>0?e.usedVolume/e.totalVolume:0,weight:e.weight,remainingVolume:e.totalVolume-e.usedVolume};return this.binStates.delete(t),this.binOrder=this.binOrder.filter(n=>n!==t),this.stats.binsInUse--,i}placeItem(t){if(this.stats.totalItems++,this.options.autoAddBins&&!this.canFitInTemplate(t)){this.stats.rejectedItems++;let n={success:false,reason:"no-fit"};return this.emit("item-rejected",{item:t,placement:n}),n}let e=this.options.maxBins+1;for(let n=0;n<e;n++){if(this.binStates.size===0)if(this.options.autoAddBins&&this.stats.binsInUse<this.options.maxBins)this.autoAddBin();else {this.stats.rejectedItems++;let o={success:false,reason:"no-bins"};return this.emit("item-rejected",{item:t,placement:o}),o}let s=this.findPlacement(t);if(s){let o=this.binStates.get(s.binId),r={item:t,position:s.position,rotation:s.rotation,dimensions:s.dimensions};o.items.push(r),o.spatialIndex.insert(r),o.usedVolume+=P(s.dimensions),o.weight+=t.weight??0,this.updateExtremePoints(o,r),this.stats.placedItems++,this.stats.totalWeight+=t.weight??0,this.updateAvgUtilization();let a={success:true,binId:s.binId,position:s.position,placedItem:r};return this.emit("item-placed",{item:t,bin:o.bin,placement:a}),a}if(this.options.autoAddBins&&this.stats.binsInUse<this.options.maxBins){this.autoAddBin();continue}break}this.stats.rejectedItems++;let i={success:false,reason:"no-fit"};return this.emit("item-rejected",{item:t,placement:i}),i}canFitInTemplate(t){let e=this.options.binTemplate,i=[t.width,t.height,t.depth].sort((s,o)=>s-o),n=[e.width,e.height,e.depth].sort((s,o)=>s-o);return i[0]<=n[0]&&i[1]<=n[1]&&i[2]<=n[2]}findPlacement(t){let e=[],i=this.getBinOrder();for(let s of i){let o=this.binStates.get(s),r=this.findPlacementInBin(t,o);if(r){if(this.options.binSelection==="first-fit")return {binId:s,...r};let a=P(r.dimensions),u=o.totalVolume-o.usedVolume-a;e.push({binId:s,...r,score:u});}}if(e.length===0)return null;this.options.binSelection==="best-fit"?e.sort((s,o)=>s.score-o.score):e.sort((s,o)=>o.score-s.score);let n=e[0];return {binId:n.binId,position:n.position,rotation:n.rotation,dimensions:n.dimensions}}findPlacementInBin(t,e){let i=t.allowedRotations||T(t.rotationType||"all"),n=[...e.extremePoints].sort((s,o)=>s.y!==o.y?s.y-o.y:s.z!==o.z?s.z-o.z:s.x-o.x);for(let s of n)for(let o of i){let r=I(t.width,t.height,t.depth,o);if(X(s,r,e.bin)&&!N(s,r,e.bin)&&!L(s,r,e.spatialIndex)&&Y(e.items,t,e.bin)){if(this.options.features?.supportCheck){let a=t.requiresSupport??.5;if(!V(s,r,e.items,a))continue}return {position:{...s},rotation:o,dimensions:r}}}return null}updateExtremePoints(t,e){let{position:i,dimensions:n}=e,s=[];s.push({x:i.x+n.width,y:i.y,z:i.z}),s.push({x:i.x,y:i.y+n.height,z:i.z}),s.push({x:i.x,y:i.y,z:i.z+n.depth}),t.extremePoints=t.extremePoints.filter(o=>!(o.x>=i.x&&o.x<i.x+n.width&&o.y>=i.y&&o.y<i.y+n.height&&o.z>=i.z&&o.z<i.z+n.depth));for(let o of s)o.x>=0&&o.x<t.bin.width&&o.y>=0&&o.y<t.bin.height&&o.z>=0&&o.z<t.bin.depth&&(t.extremePoints.some(a=>Math.abs(a.x-o.x)<.001&&Math.abs(a.y-o.y)<.001&&Math.abs(a.z-o.z)<.001)||t.extremePoints.push(o));}getBinOrder(){return this.options.binSelection==="first-fit"?this.binOrder:[...this.binOrder].sort((t,e)=>{let i=this.binStates.get(t),n=this.binStates.get(e),s=i.totalVolume>0?i.usedVolume/i.totalVolume:0,o=n.totalVolume>0?n.usedVolume/n.totalVolume:0;return this.options.binSelection==="best-fit"?o-s:s-o})}autoAddBin(){this.autoAddCounter++;let t={...this.options.binTemplate,id:`${this.options.binTemplate.id}-${this.autoAddCounter}`};this.addBin(t);}updateAvgUtilization(){if(this.binStates.size===0){this.stats.avgUtilization=0;return}let t=0;for(let e of this.binStates.values())t+=e.totalVolume>0?e.usedVolume/e.totalVolume:0;this.stats.avgUtilization=this.binStates.size>0?t/this.binStates.size:0;}getStats(){return {...this.stats}}getBinState(t){let e=this.binStates.get(t);return e?{bin:e.bin,items:[...e.items],utilization:e.totalVolume>0?e.usedVolume/e.totalVolume:0,weight:e.weight,remainingVolume:e.totalVolume-e.usedVolume}:null}getAllBinStates(){return this.binOrder.map(t=>this.getBinState(t))}getBinIds(){return [...this.binOrder]}reset(){this.binStates.clear(),this.binOrder=[],this.autoAddCounter=0,this.stats={totalItems:0,placedItems:0,rejectedItems:0,binsInUse:0,avgUtilization:0,totalWeight:0};}on(t,e){return this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e),()=>{this.eventListeners.get(t)?.delete(e);}}emit(t,e){let i={type:t,timestamp:Date.now(),...e},n=this.eventListeners.get(t);if(n)for(let s of n)s(i);}generateInitialExtremePoints(t){let e=[];if(e.push({x:0,y:0,z:0}),!t.excludeZones||t.excludeZones.length===0)return e;for(let n of t.excludeZones)n.minY>0||(n.minX===0&&n.maxX<t.width&&(e.push({x:n.maxX,y:0,z:0}),n.minZ===0&&n.maxZ<t.depth&&(e.push({x:0,y:0,z:n.maxZ}),e.push({x:n.maxX,y:0,z:n.maxZ}))),n.minZ===0&&n.maxZ<t.depth&&n.minX!==0&&e.push({x:0,y:0,z:n.maxZ}));let i=[];for(let n of e)i.some(o=>Math.abs(o.x-n.x)<.001&&Math.abs(o.y-n.y)<.001&&Math.abs(o.z-n.z)<.001)||i.push(n);return i}};var H={EUR1:{width:800,depth:1200,height:144,name:"EUR1 (Euro Pallet)"},EUR2:{width:1200,depth:1e3,height:144,name:"EUR2"},EUR3:{width:1e3,depth:1200,height:144,name:"EUR3"},EUR6:{width:600,depth:800,height:144,name:"EUR6 (Half Pallet)"},US:{width:1016,depth:1219,height:150,name:'US (40"\xD748")'},US_GROCERY:{width:1016,depth:1219,height:150,name:"US Grocery"},ASIA:{width:1100,depth:1100,height:150,name:"Asia Standard"},AUSTRALIA:{width:1165,depth:1165,height:150,name:"Australia Standard"}};function Je(t){return H[t]}var Qe=1800,ti=1e3;function ei(t,e={}){let i,n;if(typeof e.palletSize=="string"){let h=H[e.palletSize];i=h.width,n=h.depth;}else e.palletSize?(i=e.palletSize.width,n=e.palletSize.depth):(i=H.EUR1.width,n=H.EUR1.depth);let s=e.maxHeight??Qe,o=e.maxWeight??ti,r={id:"pallet-1",type:"pallet",width:i,height:s,depth:n,maxWeight:o},a={algorithm:e.algorithm??"layer-building",features:{supportCheck:true,weightBalance:true,stackingLimit:true},...e.packOptions};return {...A({bins:[r],items:t,options:a}),palletSpec:r}}var j={"20ft":{width:2352,height:2393,depth:5898,maxWeight:21770,name:"20ft Standard"},"40ft":{width:2352,height:2393,depth:12032,maxWeight:26680,name:"40ft Standard"},"40ftHC":{width:2352,height:2698,depth:12032,maxWeight:26460,name:"40ft High Cube"},"45ftHC":{width:2352,height:2698,depth:13556,maxWeight:25600,name:"45ft High Cube"}};function ii(t){return j[t]}function ni(t,e={}){let i,n,s,o;if(typeof e.containerSize=="string"){let h=j[e.containerSize];i=h.width,n=h.height,s=h.depth,o=e.maxWeight??h.maxWeight;}else if(e.containerSize)i=e.containerSize.width,n=e.containerSize.height,s=e.containerSize.depth,o=e.maxWeight??26e3;else {let h=j["40ft"];i=h.width,n=h.height,s=h.depth,o=e.maxWeight??h.maxWeight;}let r={id:"container-1",type:"container",width:i,height:n,depth:s,maxWeight:o,constraints:{loadingDirection:e.loadingDirection??"rear"}},a={algorithm:e.algorithm??"wall-building",features:{supportCheck:true,weightBalance:true,stackingLimit:true},constraints:{respectDeliveryOrder:e.respectDeliveryOrder??false},...e.packOptions};return {...A({bins:[r],items:t,options:a}),containerSpec:r}}function gt(t,e,i,n){let s=i??e*.6,o=n??e*.2,r=0,a=0;for(let u of t){let h=u.item.weight??0;if(h===0)continue;let c=u.position.z+u.dimensions.depth/2-o,l=Math.max(0,Math.min(1,c/s));a+=h*l,r+=h*(1-l);}return {front:r,rear:a,isValid:true}}function si(t,e){let{truckSize:i,maxWeight:n,axleWeights:s}=e,o={id:"truck-1",type:"truck",width:i.width,height:i.height,depth:i.depth,maxWeight:n,constraints:{axleWeights:s,loadingDirection:"rear"}},r={algorithm:e.algorithm??"wall-building",features:{supportCheck:true,weightBalance:true,stackingLimit:true},constraints:{respectDeliveryOrder:true},...e.packOptions},a=A({bins:[o],items:t,options:r}),u=a.packed.length>0?a.packed[0].items:[],h=gt(u,i.depth,e.wheelbase,e.frontAxleOffset);return s&&(h.isValid=h.front<=s.front&&h.rear<=s.rear),{...a,truckSpec:o,axleWeights:h}}exports.CONTAINER_STANDARDS=j;exports.NaiveSpatialIndex=yt;exports.OctreeIndex=Ce;exports.OnlinePacker=Si;exports.PALLET_STANDARDS=H;exports.Packer=ke;exports.RotationType=y;exports.buildBlocks=gi;exports.calcAxleWeights=gt;exports.calcCenterOfGravity=ot;exports.calcOverlapAreaXZ=_;exports.calcSupportedArea=rt;exports.calcTotalWeight=zt;exports.canAddWeight=Y;exports.canMixInBin=pi;exports.canStackOn=ui;exports.containsAABB=oi;exports.createAABB=D;exports.createNaiveIndex=O;exports.createOctreeIndex=wi;exports.createPacker=mi;exports.enhanceWithGenetic=Jt;exports.expandBlocks=xi;exports.extractLayers=di;exports.extractWalls=li;exports.fitsInBin=X;exports.formatAsHtml=Ue;exports.formatAsJson=Ze;exports.formatAsMarkdown=nt;exports.generateInstructions=ki;exports.getAllowedRotations=T;exports.getContainerStandard=ii;exports.getItemAABB=v;exports.getPalletStandard=Je;exports.getRotatedDimensions=I;exports.getRotationVariants=ci;exports.getScale=zi;exports.groupItems=fi;exports.hasCollision=L;exports.hasSufficientSupport=V;exports.intersectsAABB=B;exports.isDirectlyAbove=ai;exports.isInExcludeZone=N;exports.isValidPacking=Bi;exports.isWeightBalanced=hi;exports.pack=A;exports.packContainer=ni;exports.packPallet=ei;exports.packTruck=si;exports.packWithEBAFIT=Yt;exports.packWithExtremePoint=G;exports.packWithLayerBuilding=$t;exports.packWithWallBuilding=Ft;exports.setScale=yi;exports.sortByDeliveryOrder=me;exports.sortByVolume=ge;exports.sortByWeight=xe;exports.toExternal=vi;exports.toInternal=bi;exports.validatePackingResult=Te;exports.volume=P;exports.volumeAABB=ri;
|