woodml-parser 1.0.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.
Files changed (82) hide show
  1. package/README.md +181 -0
  2. package/dist/cli.d.ts +7 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +554 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/cost.d.ts +94 -0
  7. package/dist/cost.d.ts.map +1 -0
  8. package/dist/cost.js +340 -0
  9. package/dist/cost.js.map +1 -0
  10. package/dist/cost.test.d.ts +2 -0
  11. package/dist/cost.test.d.ts.map +1 -0
  12. package/dist/cost.test.js +241 -0
  13. package/dist/cost.test.js.map +1 -0
  14. package/dist/example.d.ts +6 -0
  15. package/dist/example.d.ts.map +1 -0
  16. package/dist/example.js +136 -0
  17. package/dist/example.js.map +1 -0
  18. package/dist/formulas.d.ts +23 -0
  19. package/dist/formulas.d.ts.map +1 -0
  20. package/dist/formulas.js +442 -0
  21. package/dist/formulas.js.map +1 -0
  22. package/dist/formulas.test.d.ts +5 -0
  23. package/dist/formulas.test.d.ts.map +1 -0
  24. package/dist/formulas.test.js +360 -0
  25. package/dist/formulas.test.js.map +1 -0
  26. package/dist/index.d.ts +23 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +93 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/integration.test.d.ts +6 -0
  31. package/dist/integration.test.d.ts.map +1 -0
  32. package/dist/integration.test.js +271 -0
  33. package/dist/integration.test.js.map +1 -0
  34. package/dist/optimizer.d.ts +119 -0
  35. package/dist/optimizer.d.ts.map +1 -0
  36. package/dist/optimizer.js +423 -0
  37. package/dist/optimizer.js.map +1 -0
  38. package/dist/optimizer.test.d.ts +2 -0
  39. package/dist/optimizer.test.d.ts.map +1 -0
  40. package/dist/optimizer.test.js +225 -0
  41. package/dist/optimizer.test.js.map +1 -0
  42. package/dist/parser.d.ts +59 -0
  43. package/dist/parser.d.ts.map +1 -0
  44. package/dist/parser.js +305 -0
  45. package/dist/parser.js.map +1 -0
  46. package/dist/parser.test.d.ts +5 -0
  47. package/dist/parser.test.d.ts.map +1 -0
  48. package/dist/parser.test.js +486 -0
  49. package/dist/parser.test.js.map +1 -0
  50. package/dist/pdf.d.ts +36 -0
  51. package/dist/pdf.d.ts.map +1 -0
  52. package/dist/pdf.js +316 -0
  53. package/dist/pdf.js.map +1 -0
  54. package/dist/svg.d.ts +73 -0
  55. package/dist/svg.d.ts.map +1 -0
  56. package/dist/svg.js +613 -0
  57. package/dist/svg.js.map +1 -0
  58. package/dist/svg.test.d.ts +5 -0
  59. package/dist/svg.test.d.ts.map +1 -0
  60. package/dist/svg.test.js +333 -0
  61. package/dist/svg.test.js.map +1 -0
  62. package/dist/templates.d.ts +126 -0
  63. package/dist/templates.d.ts.map +1 -0
  64. package/dist/templates.js +448 -0
  65. package/dist/templates.js.map +1 -0
  66. package/dist/templates.test.d.ts +5 -0
  67. package/dist/templates.test.d.ts.map +1 -0
  68. package/dist/templates.test.js +630 -0
  69. package/dist/templates.test.js.map +1 -0
  70. package/dist/types.d.ts +250 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +7 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/units.d.ts +53 -0
  75. package/dist/units.d.ts.map +1 -0
  76. package/dist/units.js +359 -0
  77. package/dist/units.js.map +1 -0
  78. package/dist/units.test.d.ts +5 -0
  79. package/dist/units.test.d.ts.map +1 -0
  80. package/dist/units.test.js +364 -0
  81. package/dist/units.test.js.map +1 -0
  82. package/package.json +46 -0
@@ -0,0 +1,423 @@
1
+ "use strict";
2
+ /**
3
+ * Cut list optimization for WoodML projects
4
+ * Uses First Fit Decreasing bin packing algorithm for sheet goods
5
+ * and 1D bin packing for dimensional lumber
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.STANDARD_BOARD_LENGTHS = exports.STANDARD_SHEET_SIZES = void 0;
9
+ exports.optimizeCutList = optimizeCutList;
10
+ exports.formatOptimizationResult = formatOptimizationResult;
11
+ const units_1 = require("./units");
12
+ /**
13
+ * Standard sheet sizes (in inches)
14
+ */
15
+ exports.STANDARD_SHEET_SIZES = {
16
+ '4x8': { width: 48, length: 96 },
17
+ '4x4': { width: 48, length: 48 },
18
+ '5x5': { width: 60, length: 60 },
19
+ '4x10': { width: 48, length: 120 },
20
+ '4x12': { width: 48, length: 144 },
21
+ };
22
+ /**
23
+ * Standard board lengths (in inches)
24
+ */
25
+ exports.STANDARD_BOARD_LENGTHS = [72, 96, 120, 144, 192]; // 6', 8', 10', 12', 16'
26
+ /**
27
+ * Check if a material is a sheet good
28
+ */
29
+ function isSheetGood(material) {
30
+ const sheetMaterials = [
31
+ 'plywood',
32
+ 'mdf',
33
+ 'particleboard',
34
+ 'hardboard',
35
+ 'melamine',
36
+ 'baltic birch',
37
+ 'osb',
38
+ ];
39
+ const lower = material.toLowerCase();
40
+ return sheetMaterials.some((m) => lower.includes(m));
41
+ }
42
+ /**
43
+ * Convert parts to optimization format
44
+ */
45
+ function prepareParts(doc, kerf) {
46
+ const parts = [];
47
+ for (const part of doc.resolvedParts) {
48
+ const length = (0, units_1.toInches)(part.dimensions.length) + kerf;
49
+ const width = (0, units_1.toInches)(part.dimensions.width) + kerf;
50
+ const thickness = (0, units_1.toInches)(part.dimensions.thickness);
51
+ const material = part.material || 'unknown';
52
+ const quantity = part.quantity || 1;
53
+ for (let i = 0; i < quantity; i++) {
54
+ parts.push({
55
+ id: quantity > 1 ? `${part.id}_${i + 1}` : part.id,
56
+ name: part.name || part.id,
57
+ length,
58
+ width,
59
+ thickness,
60
+ material,
61
+ quantity: 1,
62
+ isSheetGood: isSheetGood(material),
63
+ });
64
+ }
65
+ }
66
+ return parts;
67
+ }
68
+ /**
69
+ * Guillotine algorithm for 2D bin packing (sheet goods)
70
+ */
71
+ class GuillotinePacker {
72
+ sheetWidth;
73
+ sheetLength;
74
+ freeRects;
75
+ kerf;
76
+ constructor(width, length, kerf) {
77
+ this.sheetWidth = width;
78
+ this.sheetLength = length;
79
+ this.kerf = kerf;
80
+ this.freeRects = [
81
+ { x: 0, y: 0, width: width, height: length, valid: true },
82
+ ];
83
+ }
84
+ /**
85
+ * Try to place a part, returns placement or null
86
+ */
87
+ place(width, height, allowRotation) {
88
+ let bestRect = null;
89
+ let bestFit = Infinity;
90
+ let rotated = false;
91
+ for (const rect of this.freeRects) {
92
+ if (!rect.valid)
93
+ continue;
94
+ // Try normal orientation
95
+ if (width <= rect.width && height <= rect.height) {
96
+ const fit = rect.width * rect.height - width * height;
97
+ if (fit < bestFit) {
98
+ bestFit = fit;
99
+ bestRect = rect;
100
+ rotated = false;
101
+ }
102
+ }
103
+ // Try rotated orientation
104
+ if (allowRotation && height <= rect.width && width <= rect.height) {
105
+ const fit = rect.width * rect.height - height * width;
106
+ if (fit < bestFit) {
107
+ bestFit = fit;
108
+ bestRect = rect;
109
+ rotated = true;
110
+ }
111
+ }
112
+ }
113
+ if (!bestRect)
114
+ return null;
115
+ const placedWidth = rotated ? height : width;
116
+ const placedHeight = rotated ? width : height;
117
+ // Split the rectangle
118
+ this.splitRect(bestRect, placedWidth, placedHeight);
119
+ return { x: bestRect.x, y: bestRect.y, rotated };
120
+ }
121
+ /**
122
+ * Split a rectangle after placing a part
123
+ */
124
+ splitRect(rect, width, height) {
125
+ rect.valid = false;
126
+ // Create right remainder
127
+ if (rect.width - width > this.kerf) {
128
+ this.freeRects.push({
129
+ x: rect.x + width,
130
+ y: rect.y,
131
+ width: rect.width - width,
132
+ height: height,
133
+ valid: true,
134
+ });
135
+ }
136
+ // Create bottom remainder
137
+ if (rect.height - height > this.kerf) {
138
+ this.freeRects.push({
139
+ x: rect.x,
140
+ y: rect.y + height,
141
+ width: rect.width,
142
+ height: rect.height - height,
143
+ valid: true,
144
+ });
145
+ }
146
+ // Merge adjacent free rectangles
147
+ this.mergeFreeRects();
148
+ }
149
+ /**
150
+ * Merge adjacent free rectangles where possible
151
+ */
152
+ mergeFreeRects() {
153
+ // Simple cleanup - remove invalid rectangles
154
+ this.freeRects = this.freeRects.filter((r) => r.valid);
155
+ }
156
+ getWasteArea() {
157
+ return this.freeRects
158
+ .filter((r) => r.valid)
159
+ .reduce((sum, r) => sum + r.width * r.height, 0);
160
+ }
161
+ }
162
+ /**
163
+ * First Fit Decreasing for 1D bin packing (boards)
164
+ */
165
+ function packBoards(parts, boardLengths, kerf, minCutoff) {
166
+ // Sort parts by length descending
167
+ const sortedParts = [...parts].sort((a, b) => b.length - a.length);
168
+ // Find the most common width/thickness combination
169
+ const sizeGroups = new Map();
170
+ for (const part of sortedParts) {
171
+ const key = `${part.width.toFixed(2)}x${part.thickness.toFixed(2)}`;
172
+ if (!sizeGroups.has(key)) {
173
+ sizeGroups.set(key, []);
174
+ }
175
+ sizeGroups.get(key).push(part);
176
+ }
177
+ const boards = [];
178
+ let boardNumber = 1;
179
+ for (const [sizeKey, groupParts] of sizeGroups) {
180
+ const [widthStr, thicknessStr] = sizeKey.split('x');
181
+ const boardWidth = parseFloat(widthStr);
182
+ const boardThickness = parseFloat(thicknessStr);
183
+ // Find optimal board length for this group
184
+ const totalLength = groupParts.reduce((sum, p) => sum + p.length + kerf, 0);
185
+ const avgPartLength = groupParts.reduce((sum, p) => sum + p.length, 0) / groupParts.length;
186
+ // Select board length that minimizes waste
187
+ let optimalBoardLength = boardLengths[0];
188
+ for (const len of boardLengths) {
189
+ if (len >= avgPartLength * 1.5) {
190
+ optimalBoardLength = len;
191
+ break;
192
+ }
193
+ }
194
+ // Pack parts into boards
195
+ const remainingParts = [...groupParts];
196
+ while (remainingParts.length > 0) {
197
+ const board = {
198
+ boardNumber: boardNumber++,
199
+ boardLength: optimalBoardLength,
200
+ boardWidth,
201
+ boardThickness,
202
+ parts: [],
203
+ usedLength: 0,
204
+ wasteLength: 0,
205
+ efficiency: 0,
206
+ };
207
+ let position = 0;
208
+ const placedIndices = [];
209
+ // First fit decreasing
210
+ for (let i = 0; i < remainingParts.length; i++) {
211
+ const part = remainingParts[i];
212
+ const requiredLength = part.length + (board.parts.length > 0 ? kerf : 0);
213
+ if (position + requiredLength <= optimalBoardLength) {
214
+ board.parts.push({
215
+ partId: part.id,
216
+ partName: part.name,
217
+ position: position,
218
+ length: part.length,
219
+ });
220
+ position += requiredLength;
221
+ placedIndices.push(i);
222
+ }
223
+ }
224
+ // Remove placed parts
225
+ for (let i = placedIndices.length - 1; i >= 0; i--) {
226
+ remainingParts.splice(placedIndices[i], 1);
227
+ }
228
+ board.usedLength = position;
229
+ board.wasteLength = optimalBoardLength - position;
230
+ board.efficiency =
231
+ (board.usedLength / optimalBoardLength) * 100;
232
+ boards.push(board);
233
+ }
234
+ }
235
+ return boards;
236
+ }
237
+ /**
238
+ * Pack sheet goods using Guillotine algorithm
239
+ */
240
+ function packSheets(parts, sheetWidth, sheetLength, kerf, allowRotation) {
241
+ // Sort parts by area descending (First Fit Decreasing)
242
+ const sortedParts = [...parts].sort((a, b) => b.length * b.width - a.length * a.width);
243
+ const sheets = [];
244
+ const unplaced = [];
245
+ let sheetNumber = 1;
246
+ const remainingParts = [...sortedParts];
247
+ while (remainingParts.length > 0) {
248
+ const packer = new GuillotinePacker(sheetWidth, sheetLength, kerf);
249
+ const sheetParts = [];
250
+ let usedArea = 0;
251
+ const placedIndices = [];
252
+ for (let i = 0; i < remainingParts.length; i++) {
253
+ const part = remainingParts[i];
254
+ const placement = packer.place(part.width, part.length, allowRotation);
255
+ if (placement) {
256
+ sheetParts.push({
257
+ partId: part.id,
258
+ partName: part.name,
259
+ x: placement.x,
260
+ y: placement.y,
261
+ width: placement.rotated ? part.length : part.width,
262
+ length: placement.rotated ? part.width : part.length,
263
+ rotated: placement.rotated,
264
+ });
265
+ usedArea += part.width * part.length;
266
+ placedIndices.push(i);
267
+ }
268
+ }
269
+ // If we couldn't place any parts, they're too large
270
+ if (placedIndices.length === 0) {
271
+ for (const part of remainingParts) {
272
+ unplaced.push(part.id);
273
+ }
274
+ break;
275
+ }
276
+ // Remove placed parts
277
+ for (let i = placedIndices.length - 1; i >= 0; i--) {
278
+ remainingParts.splice(placedIndices[i], 1);
279
+ }
280
+ const totalArea = sheetWidth * sheetLength;
281
+ sheets.push({
282
+ sheetNumber: sheetNumber++,
283
+ sheetWidth,
284
+ sheetLength,
285
+ parts: sheetParts,
286
+ usedArea,
287
+ wasteArea: totalArea - usedArea,
288
+ efficiency: (usedArea / totalArea) * 100,
289
+ });
290
+ }
291
+ return { sheets, unplaced };
292
+ }
293
+ /**
294
+ * Optimize cut list for a project
295
+ */
296
+ function optimizeCutList(doc, options = {}) {
297
+ const kerf = options.kerf ?? 0.125; // 1/8" default
298
+ const allowRotation = options.allowRotation ?? true;
299
+ const minCutoff = options.minCutoff ?? 6;
300
+ const sheetSize = exports.STANDARD_SHEET_SIZES[options.sheetSize ?? '4x8'];
301
+ const boardLengths = options.boardLengths ?? exports.STANDARD_BOARD_LENGTHS;
302
+ // Prepare parts
303
+ const allParts = prepareParts(doc, kerf);
304
+ const sheetParts = allParts.filter((p) => p.isSheetGood);
305
+ const boardParts = allParts.filter((p) => !p.isSheetGood);
306
+ // Optimize sheet goods
307
+ const { sheets, unplaced: unplacedSheets } = packSheets(sheetParts, sheetSize.width, sheetSize.length, kerf, allowRotation);
308
+ // Optimize dimensional lumber
309
+ const boards = packBoards(boardParts, boardLengths, kerf, minCutoff);
310
+ // Calculate totals
311
+ const totalSheets = sheets.length;
312
+ const boardCounts = new Map();
313
+ for (const board of boards) {
314
+ const count = boardCounts.get(board.boardLength) || 0;
315
+ boardCounts.set(board.boardLength, count + 1);
316
+ }
317
+ const totalBoards = Array.from(boardCounts.entries())
318
+ .map(([length, count]) => ({ length, count }))
319
+ .sort((a, b) => a.length - b.length);
320
+ // Calculate overall efficiency
321
+ const totalSheetArea = totalSheets * sheetSize.width * sheetSize.length;
322
+ const usedSheetArea = sheets.reduce((sum, s) => sum + s.usedArea, 0);
323
+ const totalBoardLength = boards.reduce((sum, b) => sum + b.boardLength, 0);
324
+ const usedBoardLength = boards.reduce((sum, b) => sum + b.usedLength, 0);
325
+ let overallEfficiency = 0;
326
+ if (totalSheetArea + totalBoardLength > 0) {
327
+ overallEfficiency =
328
+ ((usedSheetArea + usedBoardLength) /
329
+ (totalSheetArea + totalBoardLength)) *
330
+ 100;
331
+ }
332
+ const wastePercentage = 100 - overallEfficiency;
333
+ // Generate notes
334
+ const notes = [];
335
+ if (kerf > 0) {
336
+ notes.push(`Kerf allowance: ${kerf}" per cut`);
337
+ }
338
+ if (unplacedSheets.length > 0) {
339
+ notes.push(`${unplacedSheets.length} part(s) could not be placed - may be larger than sheet size`);
340
+ }
341
+ if (overallEfficiency < 70) {
342
+ notes.push('Low material efficiency - consider consolidating parts or adjusting dimensions');
343
+ }
344
+ return {
345
+ sheets,
346
+ boards,
347
+ totalSheets,
348
+ totalBoards,
349
+ overallEfficiency: Math.round(overallEfficiency * 10) / 10,
350
+ wastePercentage: Math.round(wastePercentage * 10) / 10,
351
+ unplacedParts: unplacedSheets,
352
+ notes,
353
+ };
354
+ }
355
+ /**
356
+ * Format optimization result as text
357
+ */
358
+ function formatOptimizationResult(result) {
359
+ const lines = [];
360
+ lines.push('='.repeat(60));
361
+ lines.push('CUT LIST OPTIMIZATION RESULTS');
362
+ lines.push('='.repeat(60));
363
+ lines.push('');
364
+ // Sheet goods
365
+ if (result.sheets.length > 0) {
366
+ lines.push('SHEET GOODS');
367
+ lines.push('-'.repeat(60));
368
+ lines.push(`Total sheets needed: ${result.totalSheets}`);
369
+ lines.push('');
370
+ for (const sheet of result.sheets) {
371
+ lines.push(`Sheet #${sheet.sheetNumber} (${sheet.sheetWidth}" x ${sheet.sheetLength}")`);
372
+ lines.push(` Efficiency: ${sheet.efficiency.toFixed(1)}%`);
373
+ lines.push(' Parts:');
374
+ for (const part of sheet.parts) {
375
+ const rotated = part.rotated ? ' (rotated)' : '';
376
+ lines.push(` - ${part.partName}: ${part.length}" x ${part.width}" at (${part.x}", ${part.y}")${rotated}`);
377
+ }
378
+ lines.push('');
379
+ }
380
+ }
381
+ // Dimensional lumber
382
+ if (result.boards.length > 0) {
383
+ lines.push('DIMENSIONAL LUMBER');
384
+ lines.push('-'.repeat(60));
385
+ for (const { length, count } of result.totalBoards) {
386
+ const feet = length / 12;
387
+ lines.push(`${count} board(s) at ${feet}' length`);
388
+ }
389
+ lines.push('');
390
+ for (const board of result.boards) {
391
+ const feet = board.boardLength / 12;
392
+ lines.push(`Board #${board.boardNumber} (${feet}' x ${board.boardWidth}" x ${board.boardThickness}")`);
393
+ lines.push(` Efficiency: ${board.efficiency.toFixed(1)}%`);
394
+ lines.push(' Cuts:');
395
+ for (const part of board.parts) {
396
+ lines.push(` - ${part.partName}: ${part.length}" at position ${part.position}"`);
397
+ }
398
+ lines.push('');
399
+ }
400
+ }
401
+ // Summary
402
+ lines.push('='.repeat(60));
403
+ lines.push('SUMMARY');
404
+ lines.push('-'.repeat(60));
405
+ lines.push(`Overall efficiency: ${result.overallEfficiency}%`);
406
+ lines.push(`Waste: ${result.wastePercentage}%`);
407
+ if (result.unplacedParts.length > 0) {
408
+ lines.push('');
409
+ lines.push('UNPLACED PARTS:');
410
+ for (const id of result.unplacedParts) {
411
+ lines.push(` - ${id}`);
412
+ }
413
+ }
414
+ if (result.notes.length > 0) {
415
+ lines.push('');
416
+ lines.push('NOTES:');
417
+ for (const note of result.notes) {
418
+ lines.push(` * ${note}`);
419
+ }
420
+ }
421
+ return lines.join('\n');
422
+ }
423
+ //# sourceMappingURL=optimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.js","sourceRoot":"","sources":["../src/optimizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=optimizer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.test.d.ts","sourceRoot":"","sources":["../src/optimizer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const node_test_1 = require("node:test");
37
+ const assert = __importStar(require("node:assert"));
38
+ const index_1 = require("./index");
39
+ const optimizer_1 = require("./optimizer");
40
+ (0, node_test_1.describe)('cut list optimization', () => {
41
+ const SHEET_PROJECT = `
42
+ woodml: "1.0"
43
+ project:
44
+ name: "Sheet Good Project"
45
+ units: imperial
46
+
47
+ parts:
48
+ - id: panel_a
49
+ name: "Panel A"
50
+ material: plywood
51
+ dimensions:
52
+ length: 24"
53
+ width: 18"
54
+ thickness: 3/4"
55
+ quantity: 2
56
+
57
+ - id: panel_b
58
+ name: "Panel B"
59
+ material: plywood
60
+ dimensions:
61
+ length: 36"
62
+ width: 24"
63
+ thickness: 3/4"
64
+ quantity: 1
65
+ `;
66
+ const BOARD_PROJECT = `
67
+ woodml: "1.0"
68
+ project:
69
+ name: "Board Project"
70
+ units: imperial
71
+
72
+ parts:
73
+ - id: rail
74
+ name: "Rail"
75
+ material: oak
76
+ dimensions:
77
+ length: 36"
78
+ width: 3"
79
+ thickness: 3/4"
80
+ quantity: 2
81
+
82
+ - id: stile
83
+ name: "Stile"
84
+ material: oak
85
+ dimensions:
86
+ length: 24"
87
+ width: 3"
88
+ thickness: 3/4"
89
+ quantity: 4
90
+ `;
91
+ const MIXED_PROJECT = `
92
+ woodml: "1.0"
93
+ project:
94
+ name: "Mixed Project"
95
+ units: imperial
96
+
97
+ parts:
98
+ - id: back
99
+ name: "Back Panel"
100
+ material: plywood
101
+ dimensions:
102
+ length: 48"
103
+ width: 36"
104
+ thickness: 1/4"
105
+ quantity: 1
106
+
107
+ - id: leg
108
+ name: "Leg"
109
+ material: walnut
110
+ dimensions:
111
+ length: 30"
112
+ width: 2"
113
+ thickness: 2"
114
+ quantity: 4
115
+ `;
116
+ (0, node_test_1.describe)('optimizeCutList', () => {
117
+ (0, node_test_1.it)('should optimize sheet goods', () => {
118
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
119
+ const result = (0, optimizer_1.optimizeCutList)(doc);
120
+ assert.ok(result.sheets.length > 0);
121
+ assert.strictEqual(result.boards.length, 0);
122
+ assert.ok(result.overallEfficiency > 0);
123
+ });
124
+ (0, node_test_1.it)('should optimize dimensional lumber', () => {
125
+ const doc = (0, index_1.parseAndResolve)(BOARD_PROJECT);
126
+ const result = (0, optimizer_1.optimizeCutList)(doc);
127
+ assert.strictEqual(result.sheets.length, 0);
128
+ assert.ok(result.boards.length > 0);
129
+ assert.ok(result.overallEfficiency > 0);
130
+ });
131
+ (0, node_test_1.it)('should handle mixed materials', () => {
132
+ const doc = (0, index_1.parseAndResolve)(MIXED_PROJECT);
133
+ const result = (0, optimizer_1.optimizeCutList)(doc);
134
+ assert.ok(result.sheets.length > 0);
135
+ assert.ok(result.boards.length > 0);
136
+ });
137
+ (0, node_test_1.it)('should apply kerf allowance', () => {
138
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
139
+ const resultNoKerf = (0, optimizer_1.optimizeCutList)(doc, { kerf: 0 });
140
+ const resultWithKerf = (0, optimizer_1.optimizeCutList)(doc, { kerf: 0.125 });
141
+ // Both should produce valid results
142
+ assert.ok(resultNoKerf.overallEfficiency > 0);
143
+ assert.ok(resultWithKerf.overallEfficiency > 0);
144
+ // With kerf, used area will be slightly higher due to kerf added to dimensions
145
+ // Both should place all parts
146
+ assert.strictEqual(resultNoKerf.unplacedParts.length, 0);
147
+ assert.strictEqual(resultWithKerf.unplacedParts.length, 0);
148
+ });
149
+ (0, node_test_1.it)('should place parts on sheets', () => {
150
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
151
+ const result = (0, optimizer_1.optimizeCutList)(doc);
152
+ // All 3 parts should be placed
153
+ const totalPlacedParts = result.sheets.reduce((sum, s) => sum + s.parts.length, 0);
154
+ assert.strictEqual(totalPlacedParts, 3);
155
+ });
156
+ (0, node_test_1.it)('should calculate waste percentage', () => {
157
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
158
+ const result = (0, optimizer_1.optimizeCutList)(doc);
159
+ assert.ok(result.wastePercentage >= 0);
160
+ assert.ok(result.wastePercentage <= 100);
161
+ assert.strictEqual(result.overallEfficiency + result.wastePercentage, 100);
162
+ });
163
+ (0, node_test_1.it)('should use standard sheet size', () => {
164
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
165
+ const result = (0, optimizer_1.optimizeCutList)(doc, { sheetSize: '4x8' });
166
+ for (const sheet of result.sheets) {
167
+ assert.strictEqual(sheet.sheetWidth, optimizer_1.STANDARD_SHEET_SIZES['4x8'].width);
168
+ assert.strictEqual(sheet.sheetLength, optimizer_1.STANDARD_SHEET_SIZES['4x8'].length);
169
+ }
170
+ });
171
+ (0, node_test_1.it)('should report total sheets needed', () => {
172
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
173
+ const result = (0, optimizer_1.optimizeCutList)(doc);
174
+ assert.strictEqual(result.totalSheets, result.sheets.length);
175
+ });
176
+ (0, node_test_1.it)('should report total boards by length', () => {
177
+ const doc = (0, index_1.parseAndResolve)(BOARD_PROJECT);
178
+ const result = (0, optimizer_1.optimizeCutList)(doc);
179
+ const totalFromSummary = result.totalBoards.reduce((sum, b) => sum + b.count, 0);
180
+ assert.strictEqual(totalFromSummary, result.boards.length);
181
+ });
182
+ });
183
+ (0, node_test_1.describe)('formatOptimizationResult', () => {
184
+ (0, node_test_1.it)('should format sheet optimization', () => {
185
+ const doc = (0, index_1.parseAndResolve)(SHEET_PROJECT);
186
+ const result = (0, optimizer_1.optimizeCutList)(doc);
187
+ const formatted = (0, optimizer_1.formatOptimizationResult)(result);
188
+ assert.ok(formatted.includes('CUT LIST OPTIMIZATION'));
189
+ assert.ok(formatted.includes('SHEET GOODS'));
190
+ assert.ok(formatted.includes('Total sheets needed'));
191
+ assert.ok(formatted.includes('Efficiency'));
192
+ });
193
+ (0, node_test_1.it)('should format board optimization', () => {
194
+ const doc = (0, index_1.parseAndResolve)(BOARD_PROJECT);
195
+ const result = (0, optimizer_1.optimizeCutList)(doc);
196
+ const formatted = (0, optimizer_1.formatOptimizationResult)(result);
197
+ assert.ok(formatted.includes('DIMENSIONAL LUMBER'));
198
+ assert.ok(formatted.includes('Board #'));
199
+ });
200
+ (0, node_test_1.it)('should include summary', () => {
201
+ const doc = (0, index_1.parseAndResolve)(MIXED_PROJECT);
202
+ const result = (0, optimizer_1.optimizeCutList)(doc);
203
+ const formatted = (0, optimizer_1.formatOptimizationResult)(result);
204
+ assert.ok(formatted.includes('SUMMARY'));
205
+ assert.ok(formatted.includes('Overall efficiency'));
206
+ assert.ok(formatted.includes('Waste'));
207
+ });
208
+ });
209
+ (0, node_test_1.describe)('STANDARD_SHEET_SIZES', () => {
210
+ (0, node_test_1.it)('should have common sizes', () => {
211
+ assert.ok(optimizer_1.STANDARD_SHEET_SIZES['4x8']);
212
+ assert.ok(optimizer_1.STANDARD_SHEET_SIZES['4x4']);
213
+ assert.strictEqual(optimizer_1.STANDARD_SHEET_SIZES['4x8'].width, 48);
214
+ assert.strictEqual(optimizer_1.STANDARD_SHEET_SIZES['4x8'].length, 96);
215
+ });
216
+ });
217
+ (0, node_test_1.describe)('STANDARD_BOARD_LENGTHS', () => {
218
+ (0, node_test_1.it)('should have common lengths', () => {
219
+ assert.ok(optimizer_1.STANDARD_BOARD_LENGTHS.includes(96)); // 8'
220
+ assert.ok(optimizer_1.STANDARD_BOARD_LENGTHS.includes(120)); // 10'
221
+ assert.ok(optimizer_1.STANDARD_BOARD_LENGTHS.includes(144)); // 12'
222
+ });
223
+ });
224
+ });
225
+ //# sourceMappingURL=optimizer.test.js.map