@jjlmoya/utils-diy 1.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/package.json +60 -0
- package/src/category/i18n/en.ts +110 -0
- package/src/category/i18n/es.ts +110 -0
- package/src/category/i18n/fr.ts +101 -0
- package/src/category/index.ts +25 -0
- package/src/category/seo.astro +15 -0
- package/src/components/PreviewNavSidebar.astro +116 -0
- package/src/components/PreviewToolbar.astro +143 -0
- package/src/data.ts +11 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +57 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +146 -0
- package/src/pages/[locale].astro +251 -0
- package/src/pages/index.astro +4 -0
- package/src/tests/faq_count.test.ts +19 -0
- package/src/tests/locale_completeness.test.ts +42 -0
- package/src/tests/mocks/astro_mock.js +2 -0
- package/src/tests/no_h1_in_components.test.ts +48 -0
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/seo_length.test.ts +22 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tool/balusterCalculator/bibliography.astro +14 -0
- package/src/tool/balusterCalculator/component.astro +605 -0
- package/src/tool/balusterCalculator/i18n/en.ts +264 -0
- package/src/tool/balusterCalculator/i18n/es.ts +264 -0
- package/src/tool/balusterCalculator/i18n/fr.ts +264 -0
- package/src/tool/balusterCalculator/index.ts +33 -0
- package/src/tool/balusterCalculator/seo.astro +15 -0
- package/src/tool/balusterCalculator/ui.ts +15 -0
- package/src/tool/clayCalculator/bibliography.astro +14 -0
- package/src/tool/clayCalculator/component.astro +731 -0
- package/src/tool/clayCalculator/i18n/en.ts +183 -0
- package/src/tool/clayCalculator/i18n/es.ts +183 -0
- package/src/tool/clayCalculator/i18n/fr.ts +183 -0
- package/src/tool/clayCalculator/index.ts +33 -0
- package/src/tool/clayCalculator/seo.astro +15 -0
- package/src/tool/clayCalculator/ui.ts +19 -0
- package/src/tool/concreteCalculator/bibliography.astro +13 -0
- package/src/tool/concreteCalculator/component.astro +1089 -0
- package/src/tool/concreteCalculator/i18n/en.ts +201 -0
- package/src/tool/concreteCalculator/i18n/es.ts +201 -0
- package/src/tool/concreteCalculator/i18n/fr.ts +201 -0
- package/src/tool/concreteCalculator/index.ts +28 -0
- package/src/tool/concreteCalculator/seo.astro +14 -0
- package/src/tool/concreteCalculator/ui.ts +35 -0
- package/src/tool/cutOptimizer/bibliography.astro +13 -0
- package/src/tool/cutOptimizer/component.astro +825 -0
- package/src/tool/cutOptimizer/i18n/en.ts +178 -0
- package/src/tool/cutOptimizer/i18n/es.ts +178 -0
- package/src/tool/cutOptimizer/i18n/fr.ts +178 -0
- package/src/tool/cutOptimizer/index.ts +28 -0
- package/src/tool/cutOptimizer/optimizer.ts +199 -0
- package/src/tool/cutOptimizer/seo.astro +14 -0
- package/src/tool/cutOptimizer/ui.ts +25 -0
- package/src/tool/drillCalculator/bibliography.astro +13 -0
- package/src/tool/drillCalculator/component.astro +1210 -0
- package/src/tool/drillCalculator/engine.ts +63 -0
- package/src/tool/drillCalculator/i18n/en.ts +137 -0
- package/src/tool/drillCalculator/i18n/es.ts +137 -0
- package/src/tool/drillCalculator/i18n/fr.ts +137 -0
- package/src/tool/drillCalculator/index.ts +28 -0
- package/src/tool/drillCalculator/seo.astro +14 -0
- package/src/tool/drillCalculator/ui.ts +41 -0
- package/src/tool/drillSharpener/bibliography.astro +13 -0
- package/src/tool/drillSharpener/component.astro +712 -0
- package/src/tool/drillSharpener/engine.ts +42 -0
- package/src/tool/drillSharpener/i18n/en.ts +121 -0
- package/src/tool/drillSharpener/i18n/es.ts +121 -0
- package/src/tool/drillSharpener/i18n/fr.ts +121 -0
- package/src/tool/drillSharpener/index.ts +31 -0
- package/src/tool/drillSharpener/seo.astro +14 -0
- package/src/tool/drillSharpener/ui.ts +53 -0
- package/src/tool/epoxyCalculator/bibliography.astro +14 -0
- package/src/tool/epoxyCalculator/component.astro +888 -0
- package/src/tool/epoxyCalculator/i18n/en.ts +195 -0
- package/src/tool/epoxyCalculator/i18n/es.ts +195 -0
- package/src/tool/epoxyCalculator/i18n/fr.ts +195 -0
- package/src/tool/epoxyCalculator/index.ts +33 -0
- package/src/tool/epoxyCalculator/seo.astro +15 -0
- package/src/tool/epoxyCalculator/ui.ts +22 -0
- package/src/tool/furnitureFit/bibliography.astro +13 -0
- package/src/tool/furnitureFit/component.astro +552 -0
- package/src/tool/furnitureFit/engine.ts +51 -0
- package/src/tool/furnitureFit/i18n/en.ts +152 -0
- package/src/tool/furnitureFit/i18n/es.ts +152 -0
- package/src/tool/furnitureFit/i18n/fr.ts +152 -0
- package/src/tool/furnitureFit/index.ts +28 -0
- package/src/tool/furnitureFit/seo.astro +14 -0
- package/src/tool/furnitureFit/ui.ts +21 -0
- package/src/tool/mortarCalculator/bibliography.astro +13 -0
- package/src/tool/mortarCalculator/component.astro +1139 -0
- package/src/tool/mortarCalculator/i18n/en.ts +219 -0
- package/src/tool/mortarCalculator/i18n/es.ts +205 -0
- package/src/tool/mortarCalculator/i18n/fr.ts +220 -0
- package/src/tool/mortarCalculator/index.ts +24 -0
- package/src/tool/mortarCalculator/seo.astro +14 -0
- package/src/tool/mortarCalculator/ui.ts +37 -0
- package/src/tool/passepartoutCalculator/bibliography.astro +13 -0
- package/src/tool/passepartoutCalculator/component.astro +741 -0
- package/src/tool/passepartoutCalculator/i18n/en.ts +178 -0
- package/src/tool/passepartoutCalculator/i18n/es.ts +178 -0
- package/src/tool/passepartoutCalculator/i18n/fr.ts +178 -0
- package/src/tool/passepartoutCalculator/index.ts +28 -0
- package/src/tool/passepartoutCalculator/seo.astro +14 -0
- package/src/tool/passepartoutCalculator/ui.ts +17 -0
- package/src/tool/stairCalculator/bibliography.astro +52 -0
- package/src/tool/stairCalculator/component.astro +766 -0
- package/src/tool/stairCalculator/engine.ts +128 -0
- package/src/tool/stairCalculator/i18n/en.ts +149 -0
- package/src/tool/stairCalculator/i18n/es.ts +149 -0
- package/src/tool/stairCalculator/i18n/fr.ts +149 -0
- package/src/tool/stairCalculator/index.ts +31 -0
- package/src/tool/stairCalculator/seo.astro +211 -0
- package/src/tool/stairCalculator/ui.ts +109 -0
- package/src/tool/thermalExpansionCalculator/bibliography.astro +13 -0
- package/src/tool/thermalExpansionCalculator/component.astro +771 -0
- package/src/tool/thermalExpansionCalculator/engine.ts +23 -0
- package/src/tool/thermalExpansionCalculator/i18n/en.ts +174 -0
- package/src/tool/thermalExpansionCalculator/i18n/es.ts +174 -0
- package/src/tool/thermalExpansionCalculator/i18n/fr.ts +174 -0
- package/src/tool/thermalExpansionCalculator/index.ts +28 -0
- package/src/tool/thermalExpansionCalculator/seo.astro +14 -0
- package/src/tool/thermalExpansionCalculator/ui.ts +41 -0
- package/src/tool/voltageDropCalculator/bibliography.astro +13 -0
- package/src/tool/voltageDropCalculator/component.astro +1022 -0
- package/src/tool/voltageDropCalculator/i18n/en.ts +155 -0
- package/src/tool/voltageDropCalculator/i18n/es.ts +155 -0
- package/src/tool/voltageDropCalculator/i18n/fr.ts +148 -0
- package/src/tool/voltageDropCalculator/index.ts +28 -0
- package/src/tool/voltageDropCalculator/seo.astro +14 -0
- package/src/tool/voltageDropCalculator/ui.ts +22 -0
- package/src/tools.ts +16 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { CutOptimizerUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'cut-optimizer';
|
|
6
|
+
const title = '1D and 2D Cut Optimizer: Minimize Material Waste for Wood and Metal';
|
|
7
|
+
const description =
|
|
8
|
+
'Free cut optimizer for wood, metal, and pipes. Calculate the most efficient cutting plan using the Best Fit Decreasing algorithm. Supports 1D linear and 2D panel optimization with kerf compensation.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'What is a 1D cut optimizer?',
|
|
13
|
+
answer:
|
|
14
|
+
'A 1D cut optimizer uses the Bin Packing algorithm to determine how to cut smaller pieces from standard-length stock material (timber, metal profiles, pipes) with minimum waste. It solves the Cutting Stock Problem computationally in milliseconds.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Why does kerf width matter in cut planning?',
|
|
18
|
+
answer:
|
|
19
|
+
'Every saw cut consumes material equal to the blade thickness (kerf). A standard table saw removes 3mm per cut. On a project with 10 cuts, that is 30mm of lost material. Ignoring kerf means your last pieces will be shorter than planned.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'What is the difference between 1D and 2D cut optimization?',
|
|
23
|
+
answer:
|
|
24
|
+
'1D optimization handles linear material (boards, bars, pipes) by optimizing length only. 2D optimization handles sheet material (plywood, MDF, glass) by fitting rectangular pieces onto a larger sheet, optimizing both dimensions simultaneously.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'How do I save my cut plan?',
|
|
28
|
+
answer:
|
|
29
|
+
'Print the page or take a screenshot of the visual cut diagram to use as a physical guide in your workshop. Annotate each bar with its number to follow the sequence without mistakes.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Define the stock material',
|
|
36
|
+
text: 'Enter the total length (and width for panels) of the stock material you have available.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Set the kerf width',
|
|
40
|
+
text: 'Adjust the blade thickness in millimetres so the calculation accounts for material lost per cut.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'List the required pieces',
|
|
44
|
+
text: 'Enter the length and quantity of each piece needed for your project.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Run the optimization',
|
|
48
|
+
text: 'Get the most efficient cut layout and the exact waste percentage generated.',
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
53
|
+
'@context': 'https://schema.org',
|
|
54
|
+
'@type': 'FAQPage',
|
|
55
|
+
mainEntity: faqData.map((item) => ({
|
|
56
|
+
'@type': 'Question',
|
|
57
|
+
name: item.question,
|
|
58
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
59
|
+
})),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
63
|
+
'@context': 'https://schema.org',
|
|
64
|
+
'@type': 'HowTo',
|
|
65
|
+
name: title,
|
|
66
|
+
description,
|
|
67
|
+
step: howToData.map((step, i) => ({
|
|
68
|
+
'@type': 'HowToStep',
|
|
69
|
+
position: i + 1,
|
|
70
|
+
name: step.name,
|
|
71
|
+
text: step.text,
|
|
72
|
+
})),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
76
|
+
'@context': 'https://schema.org',
|
|
77
|
+
'@type': 'SoftwareApplication',
|
|
78
|
+
name: title,
|
|
79
|
+
description,
|
|
80
|
+
applicationCategory: 'UtilityApplication',
|
|
81
|
+
operatingSystem: 'All',
|
|
82
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
83
|
+
inLanguage: 'en',
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const content: ToolLocaleContent<CutOptimizerUI> = {
|
|
87
|
+
slug,
|
|
88
|
+
title,
|
|
89
|
+
description,
|
|
90
|
+
faqTitle: 'Frequently Asked Questions',
|
|
91
|
+
faq: faqData,
|
|
92
|
+
bibliographyTitle: 'Technical References',
|
|
93
|
+
bibliography: [
|
|
94
|
+
{
|
|
95
|
+
name: 'Cutting Stock Problem: Wikipedia',
|
|
96
|
+
url: 'https://en.wikipedia.org/wiki/Cutting_stock_problem',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Bin Packing Problem: Wolfram MathWorld',
|
|
100
|
+
url: 'https://mathworld.wolfram.com/BinPackingProblem.html',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
howTo: howToData,
|
|
104
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
105
|
+
seo: [
|
|
106
|
+
{
|
|
107
|
+
type: 'title',
|
|
108
|
+
text: 'The Complete Guide to Cut Optimization',
|
|
109
|
+
level: 2,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'paragraph',
|
|
113
|
+
html: 'Cut optimization — technically known as the <strong>Cutting Stock Problem</strong> — is one of the most practically useful problems in combinatorial mathematics. For a project with 20 pieces and 5 bars of stock, there are millions of possible arrangements. A computational algorithm finds the near-optimal solution in milliseconds, reducing typical 15% material waste to under 5%.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
type: 'title',
|
|
117
|
+
text: 'Linear 1D vs Panel 2D Optimization',
|
|
118
|
+
level: 3,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'card',
|
|
122
|
+
icon: 'mdi:arrow-expand-horizontal',
|
|
123
|
+
title: 'Linear Optimization for Bars and Profiles',
|
|
124
|
+
html: '<p><strong>Linear (1D) optimization</strong> handles material that is optimized by length alone: timber, aluminium profiles, steel sections, copper pipe, and threaded rod. The algorithm packs all required pieces onto the minimum number of stock lengths, accounting for saw kerf at every cut.</p>',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'card',
|
|
128
|
+
icon: 'mdi:view-grid',
|
|
129
|
+
title: 'Panel Optimization for Sheet Materials',
|
|
130
|
+
html: '<p><strong>Panel (2D) optimization</strong> handles sheet materials such as plywood, MDF, chipboard, glass, acrylic, and sheet metal. It uses a guillotine-cut algorithm, meaning every cut runs edge to edge — matching how table saws and panel saws actually operate.</p>',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'Understanding Kerf: The Hidden Material Loss',
|
|
135
|
+
level: 3,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: 'The <strong>kerf</strong> is the width of material removed by the blade per cut. A standard table saw blade removes 3.0 to 3.2mm per pass. A circular hand saw removes 1.5 to 2.5mm. A laser cutter removes just 0.1 to 0.3mm. On a project with 10 cuts from a 2400mm board, a 3mm kerf costs you 30mm of usable material — enough to lose a whole small piece.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: 'The Best Fit Decreasing Algorithm',
|
|
144
|
+
level: 3,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'card',
|
|
148
|
+
icon: 'mdi:chip',
|
|
149
|
+
title: 'How the Optimizer Works Under the Hood',
|
|
150
|
+
html: '<p>The core algorithm uses the <strong>Best Fit Decreasing (BFD)</strong> strategy: pieces are sorted from largest to smallest, since large pieces are hardest to fit. For each piece, the algorithm scans all existing offcuts and places it in the one that leaves the least remaining space. Only when no existing offcut can accommodate the piece is a new stock bar opened. This approach typically achieves 95% or better material efficiency.</p>',
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
ui: {
|
|
154
|
+
modeLinearLabel: 'Linear (Bars)',
|
|
155
|
+
modePanelLabel: 'Panel (Sheets)',
|
|
156
|
+
configTitle: 'Material Configuration',
|
|
157
|
+
labelStockLength: 'Stock Length (mm)',
|
|
158
|
+
labelStockWidth: 'Stock Width (mm)',
|
|
159
|
+
labelKerf: 'Blade Kerf (mm)',
|
|
160
|
+
cutsTitle: 'Cut List',
|
|
161
|
+
placeholderLength: 'Length',
|
|
162
|
+
placeholderWidth: 'Width',
|
|
163
|
+
placeholderQty: 'Qty',
|
|
164
|
+
btnRemoveTitle: 'Remove',
|
|
165
|
+
statStockUsed: 'Stock Used',
|
|
166
|
+
statTotalCuts: 'Total Cuts',
|
|
167
|
+
statWaste: 'Total Waste',
|
|
168
|
+
statEfficiency: 'Efficiency',
|
|
169
|
+
vizTitle: 'Cut Visualization',
|
|
170
|
+
emptyState: 'Add cuts and run the optimizer to see the cut plan.',
|
|
171
|
+
noValidCuts: 'Could not generate valid cuts. Check your measurements.',
|
|
172
|
+
noValidPanels: 'Could not generate valid panels. Check that pieces fit within the sheet.',
|
|
173
|
+
stockLabel: 'Stock',
|
|
174
|
+
panelLabel: 'Panel',
|
|
175
|
+
wasteLabel: 'Waste:',
|
|
176
|
+
effLabel: 'Eff:',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { CutOptimizerUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'optimizador-corte';
|
|
6
|
+
const title = 'Optimizador de Cortes de Listones y Tableros';
|
|
7
|
+
const description =
|
|
8
|
+
'Calculadora gratuita para optimizar cortes en madera, metal o tuberías. Minimiza el desperdicio con algoritmo de Bin Packing 1D y 2D. Ideal para carpintería, metalurgia y reformas.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: '¿Qué es un optimizador de corte 1D?',
|
|
13
|
+
answer:
|
|
14
|
+
'Es una herramienta que usa algoritmos matemáticos (como el Bin Packing Problem) para determinar cómo cortar piezas más pequeñas de una pieza larga estándar (listón, perfil, tubería) con el mínimo desperdicio posible.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: '¿Por qué incluir el grosor del corte (Kerf)?',
|
|
18
|
+
answer:
|
|
19
|
+
'Cada vez que la sierra corta el material, se consume unos milímetros (normalmente entre 2mm y 4mm según el disco). Si no calculas este espacio, las últimas piezas de tu lista quedarán más cortas de lo planeado.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: '¿Puedo mezclar piezas de diferentes longitudes?',
|
|
23
|
+
answer:
|
|
24
|
+
'Sí, nuestra calculadora acepta cualquier combinación de longitudes y cantidades. El algoritmo evaluará todas las combinaciones posibles y priorizará el aprovechamiento máximo del material de stock.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: '¿Cómo guardo mi plan de corte?',
|
|
28
|
+
answer:
|
|
29
|
+
'Una vez optimizado, puedes imprimir la página o hacer una captura de pantalla del esquema visual. Esto te servirá de guía física en el taller para no confundir el orden de los cortes.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Definir el material base (Stock)',
|
|
36
|
+
text: 'Introduce la longitud total del listón o perfil disponible (ej. 2400mm o 6000mm).',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Configurar el grosor del disco (Kerf)',
|
|
40
|
+
text: 'Ajusta los milímetros que la sierra elimina en cada paso para que el cálculo sea milimétrico.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Listar las piezas deseadas',
|
|
44
|
+
text: 'Escribe la longitud y cantidad de cada pieza que necesitas para tu proyecto.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Ejecutar la optimización',
|
|
48
|
+
text: 'Obtén el esquema de corte más eficiente y el porcentaje exacto de desperdicio generado.',
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
53
|
+
'@context': 'https://schema.org',
|
|
54
|
+
'@type': 'FAQPage',
|
|
55
|
+
mainEntity: faqData.map((item) => ({
|
|
56
|
+
'@type': 'Question',
|
|
57
|
+
name: item.question,
|
|
58
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
59
|
+
})),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
63
|
+
'@context': 'https://schema.org',
|
|
64
|
+
'@type': 'HowTo',
|
|
65
|
+
name: title,
|
|
66
|
+
description,
|
|
67
|
+
step: howToData.map((step, i) => ({
|
|
68
|
+
'@type': 'HowToStep',
|
|
69
|
+
position: i + 1,
|
|
70
|
+
name: step.name,
|
|
71
|
+
text: step.text,
|
|
72
|
+
})),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
76
|
+
'@context': 'https://schema.org',
|
|
77
|
+
'@type': 'SoftwareApplication',
|
|
78
|
+
name: title,
|
|
79
|
+
description,
|
|
80
|
+
applicationCategory: 'UtilityApplication',
|
|
81
|
+
operatingSystem: 'All',
|
|
82
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
83
|
+
inLanguage: 'es',
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const content: ToolLocaleContent<CutOptimizerUI> = {
|
|
87
|
+
slug,
|
|
88
|
+
title,
|
|
89
|
+
description,
|
|
90
|
+
faqTitle: 'Preguntas Frecuentes',
|
|
91
|
+
faq: faqData,
|
|
92
|
+
bibliographyTitle: 'Referencias Técnicas',
|
|
93
|
+
bibliography: [
|
|
94
|
+
{
|
|
95
|
+
name: 'Cutting Stock Problem: Wikipedia',
|
|
96
|
+
url: 'https://en.wikipedia.org/wiki/Cutting_stock_problem',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Bin Packing Problem: Wolfram MathWorld',
|
|
100
|
+
url: 'https://mathworld.wolfram.com/BinPackingProblem.html',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
howTo: howToData,
|
|
104
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
105
|
+
seo: [
|
|
106
|
+
{
|
|
107
|
+
type: 'title',
|
|
108
|
+
text: 'Guía Definitiva de Optimización de Corte',
|
|
109
|
+
level: 2,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'paragraph',
|
|
113
|
+
html: 'La optimización de corte, conocida técnicamente como el <strong>Problema de Corte de Stock</strong>, es uno de los desafíos logísticos más fascinantes en la ingeniería industrial. Para un proyecto con 20 piezas y 5 barras de stock, existen millones de combinaciones posibles. Un algoritmo computacional puede encontrar la solución óptima en milisegundos, reduciendo el desperdicio habitual del 15% a menos del 5%.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
type: 'title',
|
|
117
|
+
text: 'Corte Lineal 1D y Corte de Panel 2D',
|
|
118
|
+
level: 3,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'card',
|
|
122
|
+
icon: 'mdi:arrow-expand-horizontal',
|
|
123
|
+
title: 'Corte Lineal para Listones y Perfiles',
|
|
124
|
+
html: '<p>En el <strong>corte lineal (1D)</strong>, la optimización ocurre en una sola dimensión: la longitud. El ancho del material se asume constante. Es ideal para madera dimensional (listones, vigas), perfilería metálica y de aluminio, tuberías de PVC o cobre, y varillas roscadas.</p>',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'card',
|
|
128
|
+
icon: 'mdi:view-grid',
|
|
129
|
+
title: 'Corte de Panel para Tableros y Chapas',
|
|
130
|
+
html: '<p>En el <strong>corte de panel (2D)</strong>, se gestionan dos dimensiones: ancho y largo. La herramienta utiliza algoritmos tipo guillotina, donde cada corte va de borde a borde. Ideal para tableros derivados (MDF, aglomerado), contrachapado, vidrio, metacrilato y chapas metálicas.</p>',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'El Factor Crítico: El Grosor del Corte (Kerf)',
|
|
135
|
+
level: 3,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: 'El <strong>Kerf</strong> es el material que se elimina en cada corte. Un disco de sierra estándar de mesa consume entre 3,0mm y 3,2mm por corte. Una sierra circular de mano consume 1,5 a 2,5mm. Un corte láser en metacrilato apenas 0,1 a 0,3mm. Ignorar el kerf en un proyecto con 10 cortes en listones de 2400mm puede hacerte perder entre 30mm y 32mm de material útil.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: 'El Algoritmo Best Fit Decreasing',
|
|
144
|
+
level: 3,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'card',
|
|
148
|
+
icon: 'mdi:chip',
|
|
149
|
+
title: 'Cómo Funciona el Optimizador por Dentro',
|
|
150
|
+
html: '<p>El núcleo del optimizador usa la estrategia <strong>Best Fit Decreasing (BFD)</strong>: primero ordena todas las piezas de mayor a menor longitud (las grandes son más difíciles de encajar). Luego, para cada pieza, busca el retal existente donde quepa dejando el menor sobrante posible. Solo si no cabe en ninguno, abre una nueva barra virgen. Este proceso reduce el desperdicio en un orden de magnitud respecto a la selección aleatoria.</p>',
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
ui: {
|
|
154
|
+
modeLinearLabel: 'Lineal (Barras)',
|
|
155
|
+
modePanelLabel: 'Panel (Tableros)',
|
|
156
|
+
configTitle: 'Configuración Material',
|
|
157
|
+
labelStockLength: 'Largo del Material (mm)',
|
|
158
|
+
labelStockWidth: 'Ancho del Material (mm)',
|
|
159
|
+
labelKerf: 'Grosor de Hoja / Kerf (mm)',
|
|
160
|
+
cutsTitle: 'Lista de Cortes',
|
|
161
|
+
placeholderLength: 'Largo',
|
|
162
|
+
placeholderWidth: 'Ancho',
|
|
163
|
+
placeholderQty: 'Cant.',
|
|
164
|
+
btnRemoveTitle: 'Eliminar',
|
|
165
|
+
statStockUsed: 'Material Usado',
|
|
166
|
+
statTotalCuts: 'Cortes Totales',
|
|
167
|
+
statWaste: 'Desperdicio Total',
|
|
168
|
+
statEfficiency: 'Eficiencia',
|
|
169
|
+
vizTitle: 'Visualización de Corte',
|
|
170
|
+
emptyState: 'Añade cortes y pulsa calcular para ver el plan de corte.',
|
|
171
|
+
noValidCuts: 'No se pudieron generar cortes válidos. Verifica las medidas.',
|
|
172
|
+
noValidPanels: 'No se pudieron generar paneles válidos. Verifica que las piezas quepan en el tablero.',
|
|
173
|
+
stockLabel: 'Material',
|
|
174
|
+
panelLabel: 'Panel',
|
|
175
|
+
wasteLabel: 'Desperdicio:',
|
|
176
|
+
effLabel: 'Efic:',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { CutOptimizerUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'optimiseur-decoupe';
|
|
6
|
+
const title = 'Optimiseur de Découpe 1D et 2D: Réduire les Chutes de Matériaux';
|
|
7
|
+
const description =
|
|
8
|
+
"Optimiseur de découpe gratuit pour bois, métal et tubes. Calculez le plan de coupe le plus efficace avec l'algorithme Best Fit Decreasing. Supporte la découpe linéaire 1D et panneaux 2D avec compensation du trait de scie.";
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: "Qu'est-ce qu'un optimiseur de découpe 1D?",
|
|
13
|
+
answer:
|
|
14
|
+
"Un optimiseur de découpe 1D utilise l'algorithme de Bin Packing pour déterminer comment couper des pièces plus petites dans des longueurs standard (bois, profilés, tubes) avec un minimum de chutes. Il résout le problème de découpe de stock de manière informatique en quelques millisecondes.",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: "Pourquoi le trait de scie (Kerf) est-il important?",
|
|
18
|
+
answer:
|
|
19
|
+
"Chaque passage de scie consomme du matériau égal à l'épaisseur de la lame. Une scie circulaire sur table standard enlève 3mm par coupe. Sur un projet avec 10 coupes, cela représente 30mm de matériau perdu. Ignorer le trait de scie signifie que vos dernières pièces seront plus courtes que prévu.",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: "Quelle est la différence entre la découpe 1D et 2D?",
|
|
23
|
+
answer:
|
|
24
|
+
"La découpe 1D traite les matériaux linéaires (barres, profilés, tubes) en optimisant uniquement la longueur. La découpe 2D traite les panneaux (contreplaqué, MDF, verre) en ajustant des pièces rectangulaires sur un panneau plus grand, en optimisant les deux dimensions simultanément.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: "Comment sauvegarder mon plan de découpe?",
|
|
28
|
+
answer:
|
|
29
|
+
"Imprimez la page ou faites une capture d'écran du schéma visuel pour l'utiliser comme guide physique dans votre atelier. Annotez chaque barre avec son numéro pour suivre la séquence sans erreur.",
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Définir le matériau de base',
|
|
36
|
+
text: 'Saisissez la longueur totale (et la largeur pour les panneaux) du matériau de stock disponible.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Configurer le trait de scie',
|
|
40
|
+
text: "Ajustez l'épaisseur de lame en millimètres pour que le calcul tienne compte du matériau perdu par coupe.",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Lister les pièces requises',
|
|
44
|
+
text: 'Saisissez la longueur et la quantité de chaque pièce nécessaire pour votre projet.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "Lancer l'optimisation",
|
|
48
|
+
text: "Obtenez le plan de coupe le plus efficace et le pourcentage exact de chutes générées.",
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
53
|
+
'@context': 'https://schema.org',
|
|
54
|
+
'@type': 'FAQPage',
|
|
55
|
+
mainEntity: faqData.map((item) => ({
|
|
56
|
+
'@type': 'Question',
|
|
57
|
+
name: item.question,
|
|
58
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
59
|
+
})),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
63
|
+
'@context': 'https://schema.org',
|
|
64
|
+
'@type': 'HowTo',
|
|
65
|
+
name: title,
|
|
66
|
+
description,
|
|
67
|
+
step: howToData.map((step, i) => ({
|
|
68
|
+
'@type': 'HowToStep',
|
|
69
|
+
position: i + 1,
|
|
70
|
+
name: step.name,
|
|
71
|
+
text: step.text,
|
|
72
|
+
})),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
76
|
+
'@context': 'https://schema.org',
|
|
77
|
+
'@type': 'SoftwareApplication',
|
|
78
|
+
name: title,
|
|
79
|
+
description,
|
|
80
|
+
applicationCategory: 'UtilityApplication',
|
|
81
|
+
operatingSystem: 'All',
|
|
82
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
83
|
+
inLanguage: 'fr',
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const content: ToolLocaleContent<CutOptimizerUI> = {
|
|
87
|
+
slug,
|
|
88
|
+
title,
|
|
89
|
+
description,
|
|
90
|
+
faqTitle: 'Questions Fréquentes',
|
|
91
|
+
faq: faqData,
|
|
92
|
+
bibliographyTitle: 'Références Techniques',
|
|
93
|
+
bibliography: [
|
|
94
|
+
{
|
|
95
|
+
name: 'Problème de découpe de stock: Wikipedia',
|
|
96
|
+
url: 'https://en.wikipedia.org/wiki/Cutting_stock_problem',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Problème de bin packing: Wolfram MathWorld',
|
|
100
|
+
url: 'https://mathworld.wolfram.com/BinPackingProblem.html',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
howTo: howToData,
|
|
104
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
105
|
+
seo: [
|
|
106
|
+
{
|
|
107
|
+
type: 'title',
|
|
108
|
+
text: "Guide Complet de l'Optimisation de Découpe",
|
|
109
|
+
level: 2,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'paragraph',
|
|
113
|
+
html: "L'optimisation de découpe, connue techniquement sous le nom de <strong>Problème de Découpe de Stock</strong>, est l'un des défis logistiques les plus utiles en mathématiques combinatoires. Pour un projet avec 20 pièces et 5 barres de stock, il existe des millions de combinaisons possibles. Un algorithme informatique trouve la solution quasi optimale en quelques millisecondes, réduisant les chutes habituelles de 15% à moins de 5%.",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
type: 'title',
|
|
117
|
+
text: 'Découpe Linéaire 1D et Découpe Panneau 2D',
|
|
118
|
+
level: 3,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'card',
|
|
122
|
+
icon: 'mdi:arrow-expand-horizontal',
|
|
123
|
+
title: 'Optimisation Linéaire pour Barres et Profilés',
|
|
124
|
+
html: "<p>La <strong>découpe linéaire (1D)</strong> traite les matériaux optimisés uniquement par leur longueur: bois dimensionnel, profilés aluminium, tubes PVC ou cuivre, et tiges filetées. L'algorithme dispose toutes les pièces requises sur le nombre minimum de longueurs de stock, en intégrant le trait de scie à chaque coupe.</p>",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'card',
|
|
128
|
+
icon: 'mdi:view-grid',
|
|
129
|
+
title: 'Optimisation Panneau pour Matériaux en Feuille',
|
|
130
|
+
html: "<p>La <strong>découpe panneau (2D)</strong> traite les matériaux en feuille tels que contreplaqué, MDF, verre, méthacrylate et tôle. Elle utilise un algorithme à coupe guillotine, où chaque coupe va d'un bord à l'autre, conformément au fonctionnement réel des scies circulaires et des scies de format.</p>",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'Le Trait de Scie: La Perte de Matériau Cachée',
|
|
135
|
+
level: 3,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: "Le <strong>trait de scie (Kerf)</strong> est la largeur de matériau enlevée par la lame à chaque coupe. Une scie circulaire sur table standard enlève 3,0 à 3,2mm par passage. Une scie circulaire portative enlève 1,5 à 2,5mm. Un laser enlève seulement 0,1 à 0,3mm. Sur un projet avec 10 coupes dans une planche de 2400mm, un kerf de 3mm représente 30mm de matériau utilisable perdu — de quoi rater une petite pièce entière.",
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: "L'Algorithme Best Fit Decreasing",
|
|
144
|
+
level: 3,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'card',
|
|
148
|
+
icon: 'mdi:chip',
|
|
149
|
+
title: "Fonctionnement Interne de l'Optimiseur",
|
|
150
|
+
html: "<p>Le cœur de l'algorithme utilise la stratégie <strong>Best Fit Decreasing (BFD)</strong>: les pièces sont triées de la plus grande à la plus petite, car les grandes pièces sont plus difficiles à placer. Pour chaque pièce, l'algorithme parcourt tous les chutes existantes et la place dans celle qui laisse le moins d'espace résiduel. Seulement si aucune chute existante ne peut accueillir la pièce, une nouvelle barre vierge est ouverte. Cette approche atteint généralement 95% d'efficacité matérielle ou plus.</p>",
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
ui: {
|
|
154
|
+
modeLinearLabel: 'Linéaire (Barres)',
|
|
155
|
+
modePanelLabel: 'Panneau (Tableros)',
|
|
156
|
+
configTitle: 'Configuration Matériau',
|
|
157
|
+
labelStockLength: 'Longueur du matériau (mm)',
|
|
158
|
+
labelStockWidth: 'Largeur du matériau (mm)',
|
|
159
|
+
labelKerf: 'Trait de scie / Kerf (mm)',
|
|
160
|
+
cutsTitle: 'Liste de Découpes',
|
|
161
|
+
placeholderLength: 'Longueur',
|
|
162
|
+
placeholderWidth: 'Largeur',
|
|
163
|
+
placeholderQty: 'Qté',
|
|
164
|
+
btnRemoveTitle: 'Supprimer',
|
|
165
|
+
statStockUsed: 'Matériaux utilisés',
|
|
166
|
+
statTotalCuts: 'Coupes totales',
|
|
167
|
+
statWaste: 'Chutes totales',
|
|
168
|
+
statEfficiency: 'Efficacité',
|
|
169
|
+
vizTitle: 'Visualisation de Découpe',
|
|
170
|
+
emptyState: 'Ajoutez des coupes et lancez le calcul pour voir le plan de découpe.',
|
|
171
|
+
noValidCuts: 'Impossible de générer des coupes valides. Vérifiez les dimensions.',
|
|
172
|
+
noValidPanels: 'Impossible de générer des panneaux valides. Vérifiez que les pièces rentrent dans le panneau.',
|
|
173
|
+
stockLabel: 'Matériau',
|
|
174
|
+
panelLabel: 'Panneau',
|
|
175
|
+
wasteLabel: 'Chute:',
|
|
176
|
+
effLabel: 'Eff:',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import CutOptimizerComponent from './component.astro';
|
|
2
|
+
import CutOptimizerSEO from './seo.astro';
|
|
3
|
+
import CutOptimizerBibliography from './bibliography.astro';
|
|
4
|
+
import type { DiyToolEntry, ToolDefinition } from '../../types';
|
|
5
|
+
import type { CutOptimizerUI } from './ui';
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
CutOptimizerComponent,
|
|
9
|
+
CutOptimizerSEO,
|
|
10
|
+
CutOptimizerBibliography,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const es = async () => (await import('./i18n/es')).content;
|
|
14
|
+
const en = async () => (await import('./i18n/en')).content;
|
|
15
|
+
const fr = async () => (await import('./i18n/fr')).content;
|
|
16
|
+
|
|
17
|
+
export const cutOptimizer: DiyToolEntry<CutOptimizerUI> = {
|
|
18
|
+
id: 'cut-optimizer',
|
|
19
|
+
icons: { bg: 'mdi:saw-blade', fg: 'mdi:ruler' },
|
|
20
|
+
i18n: { es, en, fr },
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const CUT_OPTIMIZER_TOOL: ToolDefinition = {
|
|
24
|
+
entry: cutOptimizer,
|
|
25
|
+
Component: CutOptimizerComponent,
|
|
26
|
+
SEOComponent: CutOptimizerSEO,
|
|
27
|
+
BibliographyComponent: CutOptimizerBibliography,
|
|
28
|
+
};
|