// ======================================== // CONTINUATION OF CALCULATION FUNCTIONS // ======================================== // Bolts Calculation function calcularParafusos() { const fy = parseFloat(document.getElementById('bolt-type').value) || 400; const d = parseFloat(document.getElementById('bolt-d').value) || 20; const qty = parseInt(document.getElementById('bolt-qty').value) || 1; const planes = parseInt(document.getElementById('bolt-planes').value) || 1; const force = parseFloat(document.getElementById('bolt-force').value) || 0; const area = Math.PI * Math.pow(d / 2, 2); const Fv = 0.6 * fy * area * planes / 1000; const capacity = Fv * qty; const utilization = (force / capacity) * 100; let alertClass = 'alert-success'; let status = '✅ OK - Capacidade adequada'; if (utilization > 100) { alertClass = 'alert-error'; status = '❌ FALHA - Capacidade insuficiente'; } else if (utilization > 80) { alertClass = 'alert-warning'; status = '⚠️ ATENÇÃO - Utilização elevada'; } document.getElementById('bolt-result').innerHTML = `
Verificação ao Cisalhamento
Área Parafuso
${area.toFixed(0)} mm²
Fv por Parafuso
${Fv.toFixed(1)} kN
Capacidade Total
${capacity.toFixed(1)} kN
Utilização
${utilization.toFixed(1)}%
${status}
`; addToHistory('Ligações Parafusadas', `${qty} parafusos Ø${d}mm, Utilização = ${utilization.toFixed(1)}%`); } // Layout Verification function verificarLayout() { const d = parseFloat(document.getElementById('layout-d').value) || 20; const edge = parseFloat(document.getElementById('layout-edge').value) || 0; const spacing = parseFloat(document.getElementById('layout-spacing').value) || 0; const minEdge = 1.5 * d; const maxEdge = 12 * 10; const minSpacing = 2.67 * d; const maxSpacing = 300; let edgeStatus = '✅ Conforme'; let edgeClass = 'alert-success'; if (edge < minEdge) { edgeStatus = `❌ Abaixo do mínimo (${minEdge.toFixed(1)}mm)`; edgeClass = 'alert-error'; } else if (edge > maxEdge) { edgeStatus = `⚠️ Acima do máximo (${maxEdge}mm)`; edgeClass = 'alert-warning'; } let spacingStatus = '✅ Conforme'; let spacingClass = 'alert-success'; if (spacing < minSpacing) { spacingStatus = `❌ Abaixo do mínimo (${minSpacing.toFixed(1)}mm)`; spacingClass = 'alert-error'; } else if (spacing > maxSpacing) { spacingStatus = `⚠️ Acima do máximo (${maxSpacing}mm)`; spacingClass = 'alert-warning'; } document.getElementById('layout-result').innerHTML = `
Verificação NBR 8800
Dist. Borda Mín
${minEdge.toFixed(1)} mm
Dist. Borda Máx
${maxEdge} mm
Espaç. Mínimo
${minSpacing.toFixed(1)} mm
Espaç. Máximo
${maxSpacing} mm
Distância de Borda: ${edgeStatus}
Espaçamento: ${spacingStatus}
`; addToHistory('Layout de Furação', `Ø${d}mm, Borda: ${edge}mm, Espaç: ${spacing}mm`); } // Bolt vs Weld Comparison function compararParafusoSolda() { const force = parseFloat(document.getElementById('comp-force').value) || 0; const length = parseFloat(document.getElementById('comp-length').value) || 0; const fy = parseFloat(document.getElementById('comp-fy').value) || 345; // Parafusos A325 Ø20mm const boltCapacity = 60; const boltQty = Math.ceil(force / boltCapacity); const boltCost = boltQty * 15; // Solda const weldLeg = (force * 1000) / (0.707 * length * 0.65 * fy); const weldLegRounded = Math.ceil(weldLeg); const weldCost = (weldLegRounded * length / 1000) * 25; document.getElementById('comparison-result').innerHTML = `
Comparação de Soluções

🔩 Solução Parafusada

Tipo: A325 Ø20mm

Quantidade: ${boltQty} parafusos

Capacidade: ${(boltQty * boltCapacity).toFixed(1)} kN

Custo estimado: R$ ${boltCost.toFixed(2)}

Vantagens: Desmontável, inspeção visual

Desvantagens: Maior tempo de instalação

🔥 Solução Soldada

Tipo: Solda de filete

Perna: ${weldLegRounded} mm

Comprimento: ${length} mm

Custo estimado: R$ ${weldCost.toFixed(2)}

Vantagens: Melhor rigidez, econômica

Desvantagens: Permanente, requer qualificação

Recomendação: ${weldCost < boltCost ? 'Solda de filete é mais econômica' : 'Parafusos mais econômicos'}
`; addToHistory('Parafuso vs Solda', `${boltQty} parafusos vs solda ${weldLegRounded}mm`); } // Preheat Calculation function calcularPreaquecimento() { const cev = parseFloat(document.getElementById('preheat-cev').value) || 0; const thickness = parseFloat(document.getElementById('preheat-thickness').value) || 0; const ambient = parseFloat(document.getElementById('preheat-ambient').value) || 20; const preheatTemp = 50 + (cev * 100) + (thickness / 10 * 20) + ((20 - ambient) / 2); const maxInterpass = preheatTemp + 100; let pwhtRecommendation = ''; if (thickness > 50 || cev > 0.60) { pwhtRecommendation = '⚠️ PWHT (Tratamento Térmico Pós-Soldagem) recomendado'; } else { pwhtRecommendation = '✅ PWHT não obrigatório'; } document.getElementById('preheat-result').innerHTML = `
Temperatura de Pré-Aquecimento (AWS D1.1)
Temp. Mínima
${Math.round(preheatTemp)}°C
Temp. Interpasse Máx
${Math.round(maxInterpass)}°C
${pwhtRecommendation}
Procedimento:
1. Aquecer uniformemente até ${Math.round(preheatTemp)}°C
2. Medir temperatura a 75mm da junta
3. Manter durante toda a soldagem
4. Temperatura interpasse máxima: ${Math.round(maxInterpass)}°C
`; addToHistory('Pré-Aquecimento', `CEV=${cev}, esp=${thickness}mm → ${Math.round(preheatTemp)}°C`); } // Weld Fillet Calculation function calcularSoldaFilete() { const force = parseFloat(document.getElementById('weld-force').value) || 0; const length = parseFloat(document.getElementById('weld-length').value) || 0; const fy = parseFloat(document.getElementById('weld-fy').value) || 345; const fyWeld = fy * 0.6; const leg = (force * 1000) / (0.707 * length * 0.65 * fyWeld); const throat = leg * 0.707; const legCommercial = Math.ceil(leg); const passes = legCommercial <= 5 ? 1 : legCommercial <= 8 ? 2 : 3; document.getElementById('weld-result').innerHTML = `
Dimensionamento da Solda de Filete
Perna Calculada
${leg.toFixed(2)} mm
Perna Adotada
${legCommercial} mm
Garganta Efetiva
${throat.toFixed(2)} mm
Número de Passes
${passes}
Eletrodo recomendado: E${Math.round(fy * 1.15)} (resistência compatível com o aço base)
`; addToHistory('Solda de Filete', `Perna ${legCommercial}mm, ${passes} passe(s)`); } // Heat Input Calculation function calcularEnergiaSoldagem() { const voltage = parseFloat(document.getElementById('hi-voltage').value) || 0; const current = parseFloat(document.getElementById('hi-current').value) || 0; const speed = parseFloat(document.getElementById('hi-speed').value) || 0; const heatInput = (voltage * current * 60) / (speed * 1000); let interpretation = ''; let alertClass = ''; if (heatInput < 1.0) { interpretation = 'Energia baixa - Risco de falta de fusão ou trincas a frio'; alertClass = 'alert-warning'; } else if (heatInput <= 2.0) { interpretation = 'Energia adequada - Dentro da faixa recomendada'; alertClass = 'alert-success'; } else { interpretation = 'Energia alta - Risco de fragilização da ZTA e distorção'; alertClass = 'alert-error'; } document.getElementById('hi-result').innerHTML = `
Energia de Soldagem (Heat Input)
Energia
${heatInput.toFixed(2)} kJ/mm
${interpretation}
Fórmula: HI = (V × I × 60) / (v × 1000)
Recomendações:
• Aços carbono: 0.8 - 2.0 kJ/mm
• Alta resistência: 0.8 - 1.5 kJ/mm
• Baixa liga: 1.0 - 2.5 kJ/mm
`; addToHistory('Energia de Soldagem', `HI = ${heatInput.toFixed(2)} kJ/mm`); } // Electrode Consumption function calcularConsumoEletrodos() { const leg = parseFloat(document.getElementById('elec-leg').value) || 0; const length = parseFloat(document.getElementById('elec-length').value) || 0; const factor = parseFloat(document.getElementById('elec-type').value) || 1.10; const loss = parseFloat(document.getElementById('elec-loss').value) || 15; const throat = leg * 0.707; const volume = throat * leg * length * 1000; const mass = (volume / 1000000) * 7850 / 1000; const consumption = mass * factor * (1 + loss / 100); document.getElementById('elec-result').innerHTML = `
Consumo de Eletrodos
Volume de Solda
${(volume / 1000).toFixed(1)} cm³
Massa de Solda
${mass.toFixed(2)} kg
Consumo Total
${consumption.toFixed(2)} kg
Estimativa de embalagens:
Eletrodos Ø3,25mm (1 kg cada): ${Math.ceil(consumption)} embalagens
`; addToHistory('Consumo de Eletrodos', `${consumption.toFixed(2)} kg para ${length}m de solda`); } // Hardness Converter function converterDureza(source) { let HB = 0; if (source === 'hb') { HB = parseFloat(document.getElementById('hard-hb').value) || 0; } else if (source === 'hrc') { const HRC = parseFloat(document.getElementById('hard-hrc').value) || 0; HB = (HRC + 9.8) / 0.0338; document.getElementById('hard-hb').value = Math.round(HB); } else if (source === 'hv') { const HV = parseFloat(document.getElementById('hard-hv').value) || 0; HB = HV / 0.95; document.getElementById('hard-hb').value = Math.round(HB); } if (HB === 0) return; const HRC = HB * 0.0338 - 9.8; const HV = HB * 0.95; const fu = HB * 10; const fy = fu * 0.7; if (source !== 'hrc') document.getElementById('hard-hrc').value = HRC.toFixed(1); if (source !== 'hv') document.getElementById('hard-hv').value = Math.round(HV); document.getElementById('hardness-result').innerHTML = `
Conversão de Dureza
HB (Brinell)
${Math.round(HB)}
HRC (Rockwell C)
${HRC.toFixed(1)}
HV (Vickers)
${Math.round(HV)}
Estimativa de Resistência:
fu ≈ ${fu.toFixed(0)} MPa
fy ≈ ${fy.toFixed(0)} MPa (aproximado)
`; } // Charpy Analysis function analisarCharpy() { const temps = [ parseFloat(document.getElementById('charpy-t1').value), parseFloat(document.getElementById('charpy-t2').value), parseFloat(document.getElementById('charpy-t3').value), parseFloat(document.getElementById('charpy-t4').value) ]; const energies = [ parseFloat(document.getElementById('charpy-e1').value), parseFloat(document.getElementById('charpy-e2').value), parseFloat(document.getElementById('charpy-e3').value), parseFloat(document.getElementById('charpy-e4').value) ]; const validPoints = temps.map((t, i) => ({ temp: t, energy: energies[i] })) .filter(p => !isNaN(p.temp) && !isNaN(p.energy)) .sort((a, b) => a.temp - b.temp); if (validPoints.length < 2) { alert('Insira pelo menos 2 pontos válidos'); return; } let ttdf = null; for (let i = 0; i < validPoints.length - 1; i++) { if ((validPoints[i].energy >= 27 && validPoints[i+1].energy < 27) || (validPoints[i].energy < 27 && validPoints[i+1].energy >= 27)) { const t1 = validPoints[i].temp; const e1 = validPoints[i].energy; const t2 = validPoints[i+1].temp; const e2 = validPoints[i+1].energy; ttdf = t1 + (27 - e1) * (t2 - t1) / (e2 - e1); break; } } document.getElementById('charpy-result').innerHTML = `
Curva de Transição Dúctil-Frágil
${ttdf !== null ? `
TTDF (Temperatura de Transição): ${ttdf.toFixed(1)}°C
Temperatura onde a energia de impacto = 27J
` : `
Não foi possível calcular TTDF
A curva não intercepta 27J no intervalo medido
`}
`; if (currentChart) { currentChart.destroy(); } const ctx = document.getElementById('charpy-chart').getContext('2d'); currentChart = new Chart(ctx, { type: 'line', data: { labels: validPoints.map(p => p.temp + '°C'), datasets: [{ label: 'Energia (J)', data: validPoints.map(p => p.energy), borderColor: '#1FB8CD', backgroundColor: '#1FB8CD40', tension: 0.4, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: 'Curva de Transição Charpy' } }, scales: { y: { title: { display: true, text: 'Energia (J)' } }, x: { title: { display: true, text: 'Temperatura (°C)' } } } } }); addToHistory('Análise Charpy', `${validPoints.length} pontos, TTDF = ${ttdf ? ttdf.toFixed(1) : 'N/A'}°C`); } // Certificate Checklist function gerarChecklistCertificado() { const norm = document.getElementById('cert-norm').value; const requirements = certRequirements[norm] || []; document.getElementById('cert-result').innerHTML = `
Checklist de Requisitos - ${norm.toUpperCase().replace('_', ' ')}
${requirements.map((req, index) => `
`).join('')}
`; } // Paint Area Calculation function updatePaintFields() { const type = document.getElementById('paint-type').value; const field3 = document.getElementById('paint-field3'); if (type === 'chapa') { document.getElementById('paint-label1').textContent = 'Comprimento (mm)'; document.getElementById('paint-label2').textContent = 'Largura (mm)'; field3.style.display = 'none'; } else if (type === 'perfilW') { document.getElementById('paint-label1').textContent = 'Comprimento (mm)'; document.getElementById('paint-label2').textContent = 'Altura (mm)'; field3.style.display = 'none'; } else if (type === 'tubo') { document.getElementById('paint-label1').textContent = 'Comprimento (mm)'; document.getElementById('paint-label2').textContent = 'Diâmetro (mm)'; field3.style.display = 'none'; } else if (type === 'rhs') { document.getElementById('paint-label1').textContent = 'Comprimento (mm)'; document.getElementById('paint-label2').textContent = 'Largura (mm)'; document.getElementById('paint-label3').textContent = 'Altura (mm)'; field3.style.display = 'block'; } } function calcularAreaPintura() { const type = document.getElementById('paint-type').value; const dim1 = parseFloat(document.getElementById('paint-dim1').value) || 0; const dim2 = parseFloat(document.getElementById('paint-dim2').value) || 0; const dim3 = parseFloat(document.getElementById('paint-dim3').value) || 0; const qty = parseInt(document.getElementById('paint-qty').value) || 1; let area = 0; if (type === 'chapa') { area = (dim1 * dim2 * 2) / 1000000; } else if (type === 'perfilW') { const perimeter = dim2 * 3.5; area = (perimeter * dim1) / 1000000; } else if (type === 'tubo') { area = (Math.PI * dim2 * dim1) / 1000000; } else if (type === 'rhs') { const perimeter = 2 * (dim2 + dim3); area = (perimeter * dim1) / 1000000; } const totalArea = area * qty; document.getElementById('paint-area-result').innerHTML = `
Área de Pintura
Área Unitária
${area.toFixed(2)} m²
Área Total
${totalArea.toFixed(2)} m²
`; document.getElementById('tinta-area').value = totalArea.toFixed(2); addToHistory('Área de Pintura', `${totalArea.toFixed(2)}m² (${qty} unidades)`); } // Paint Consumption function calcularConsumoTinta() { const area = parseFloat(document.getElementById('tinta-area').value) || 0; const dft = parseFloat(document.getElementById('tinta-dft').value) || 0; const solids = parseFloat(document.getElementById('tinta-solids').value) || 0; const loss = parseFloat(document.getElementById('tinta-loss').value) || 0; const coats = parseInt(document.getElementById('tinta-coats').value) || 1; const cost = parseFloat(document.getElementById('tinta-cost').value) || 0; const volumeTheoretical = (dft * area) / (1000 * (solids / 100)); const volumeWithLoss = volumeTheoretical / (1 - loss / 100); const volumePerCoat = volumeWithLoss; const volumeTotal = volumePerCoat * coats; const totalCost = volumeTotal * cost; document.getElementById('tinta-result').innerHTML = `
Consumo de Tinta
Volume Teórico
${volumeTheoretical.toFixed(2)} L
Volume por Demão
${volumePerCoat.toFixed(2)} L
Volume Total
${volumeTotal.toFixed(2)} L
Custo Total
R$ ${totalCost.toFixed(2)}
Recomendação de embalagens:
${volumeTotal > 20 ? `Galões 20L: ${Math.ceil(volumeTotal / 20)} unidades` : volumeTotal > 5 ? `Galões 5L: ${Math.ceil(volumeTotal / 5)} unidades` : `Latas 1L: ${Math.ceil(volumeTotal)} unidades`}
`; addToHistory('Consumo de Tinta', `${volumeTotal.toFixed(2)}L para ${area}m²`); } // Galvanization function calcularGalvanizacao() { const env = document.getElementById('galv-env').value; const area = parseFloat(document.getElementById('galv-area').value) || 0; const thickness = parseFloat(document.getElementById('galv-thickness').value) || 85; const corrosionRate = { 'interno': 0.5, 'urbano': 1.5, 'marinho': 3.0, 'industrial': 2.5 }; const rate = corrosionRate[env] || 1.5; const lifeYears = thickness / rate; const zincDensity = 7140; const zincMass = (area * thickness / 1000) * (zincDensity / 1000000); const zincCost = zincMass * 12; document.getElementById('galv-result').innerHTML = `
Galvanização a Quente
Taxa de Corrosão
${rate.toFixed(1)} μm/ano
Vida Útil Estimada
${lifeYears.toFixed(0)} anos
Consumo de Zinco
${zincMass.toFixed(2)} kg
Custo Estimado
R$ ${(zincCost + area * 180).toFixed(2)}
Normas aplicáveis: ASTM A123, ISO 1461, NBR 6323
`; addToHistory('Galvanização', `${area}m², ${thickness}μm → ${lifeYears.toFixed(0)} anos`); } // Budget function adicionarItemOrcamento() { const type = document.getElementById('budget-type').value; const spec = document.getElementById('budget-spec').value; const qty = parseFloat(document.getElementById('budget-qty').value) || 0; const unit = document.getElementById('budget-unit').value; const price = parseFloat(document.getElementById('budget-price').value) || 0; if (!spec || qty <= 0 || price <= 0) { alert('Preencha todos os campos corretamente'); return; } const item = { id: Date.now(), type: type, spec: spec, qty: qty, unit: unit, price: price, total: qty * price }; appState.budgetItems.push(item); atualizarTabelaOrcamento(); document.getElementById('budget-spec').value = ''; document.getElementById('budget-qty').value = '1'; document.getElementById('budget-price').value = '0'; } function removerItemOrcamento(id) { appState.budgetItems = appState.budgetItems.filter(item => item.id !== id); atualizarTabelaOrcamento(); } function atualizarTabelaOrcamento() { const tbody = document.getElementById('budget-tbody'); if (appState.budgetItems.length === 0) { tbody.innerHTML = 'Nenhum item adicionado'; } else { tbody.innerHTML = appState.budgetItems.map(item => ` ${item.type} ${item.spec} ${item.qty.toFixed(2)} ${item.unit} R$ ${item.price.toFixed(2)} R$ ${item.total.toFixed(2)} `).join(''); } atualizarTotalOrcamento(); } function atualizarTotalOrcamento() { const subtotal = appState.budgetItems.reduce((sum, item) => sum + item.total, 0); const bdi = parseFloat(document.getElementById('budget-bdi').value) || 0; const total = subtotal * (1 + bdi / 100); const resultDiv = document.getElementById('budget-total'); resultDiv.innerHTML = `
Subtotal
R$ ${subtotal.toFixed(2)}
BDI (${bdi}%)
R$ ${(total - subtotal).toFixed(2)}
TOTAL GERAL
R$ ${total.toFixed(2)}
`; } // Weight & Rigging function updateWeightFields() { const type = document.getElementById('weight-type').value; const field3 = document.getElementById('weight-field3'); const field4 = document.getElementById('weight-field4'); if (type === 'perfilW') { document.getElementById('weight-label1').textContent = 'Altura (mm)'; document.getElementById('weight-label2').textContent = 'Comprimento (m)'; field3.style.display = 'none'; field4.style.display = 'none'; } else if (type === 'chapa') { document.getElementById('weight-label1').textContent = 'Largura (mm)'; document.getElementById('weight-label2').textContent = 'Altura (mm)'; document.getElementById('weight-label3').textContent = 'Espessura (mm)'; field3.style.display = 'block'; field4.style.display = 'none'; } else if (type === 'tubo') { document.getElementById('weight-label1').textContent = 'Diâmetro Externo (mm)'; document.getElementById('weight-label2').textContent = 'Comprimento (m)'; document.getElementById('weight-label3').textContent = 'Espessura Parede (mm)'; field3.style.display = 'block'; field4.style.display = 'none'; } else if (type === 'barra') { document.getElementById('weight-label1').textContent = 'Diâmetro (mm)'; document.getElementById('weight-label2').textContent = 'Comprimento (m)'; field3.style.display = 'none'; field4.style.display = 'none'; } } function calcularPeso() { const type = document.getElementById('weight-type').value; const dim1 = parseFloat(document.getElementById('weight-dim1').value) || 0; const dim2 = parseFloat(document.getElementById('weight-dim2').value) || 0; const dim3 = parseFloat(document.getElementById('weight-dim3').value) || 0; let weight = 0; if (type === 'perfilW') { weight = (dim1 / 100) * 31.8 * dim2; } else if (type === 'chapa') { weight = (dim1 / 1000) * (dim2 / 1000) * (dim3 / 1000) * 7850; } else if (type === 'tubo') { const dExt = dim1; const dInt = dExt - 2 * dim3; const area = Math.PI * (Math.pow(dExt/2, 2) - Math.pow(dInt/2, 2)); weight = area / 1000000 * dim2 * 7850; } else if (type === 'barra') { const area = Math.PI * Math.pow(dim1/2, 2); weight = area / 1000000 * dim2 * 7850; } document.getElementById('weight-result').innerHTML = `
Cálculo de Peso
Peso Total
${weight.toFixed(2)} kg
`; document.getElementById('rigging-weight').value = weight.toFixed(0); addToHistory('Cálculo de Peso', `${weight.toFixed(2)}kg`); } function calcularRigging() { const weight = parseFloat(document.getElementById('rigging-weight').value) || 0; const points = parseInt(document.getElementById('rigging-points').value) || 2; const angle = parseInt(document.getElementById('rigging-angle').value) || 60; const fs = parseFloat(document.getElementById('rigging-fs').value) || 4; const angleRad = angle * Math.PI / 180; const forcePerCable = (weight * 9.81 / 1000) / (points * Math.cos(angleRad)) * fs; const cableSteelCapacity = 21; const chainCapacity = 15; const syntheticCapacity = 12; let recommendation = ''; let alertClass = 'alert-success'; if (forcePerCable <= syntheticCapacity) { recommendation = '✅ Cabo sintético (12 kN)'; } else if (forcePerCable <= chainCapacity) { recommendation = '✅ Corrente grau 80 (15 kN)'; } else if (forcePerCable <= cableSteelCapacity) { recommendation = '⚠️ Cabo de aço (21 kN)'; alertClass = 'alert-warning'; } else { recommendation = '❌ Requer cabo especial ou mais pontos de içamento'; alertClass = 'alert-error'; } document.getElementById('rigging-result').innerHTML = `
Plano de Rigging
Força por Cabo
${forcePerCable.toFixed(1)} kN
Ângulo
${angle}°
Fator Segurança
${fs}
Recomendação: ${recommendation}
Capacidades de Referência:
• Cabo sintético: 12 kN
• Corrente grau 80: 15 kN
• Cabo de aço: 21 kN
`; addToHistory('Rigging', `${weight}kg, ${points} pontos, ${angle}° → ${forcePerCable.toFixed(1)}kN/cabo`); } // ======================================== // INITIALIZATION // ======================================== document.addEventListener('DOMContentLoaded', function() { showSection('cev'); mostrarEquivalencias(); gerarChecklistCertificado(); updatePaintFields(); updateWeightFields(); });