Files
SteelBase/ORIGINAL/app.js

7268 lines
347 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ========================================
// AÇO CALC PRO v6.5 - PROFESSIONAL EDITION
// Plataforma Técnica Completa com Base de Materiais
// ========================================
// In-memory data storage (no localStorage - using JavaScript objects)
const appState = {
history: [],
favorites: [],
budgetItems: [],
currentSection: 'cev',
currentTheme: 'dark', // 'dark' or 'light'
expertMode: false,
currentSidebarTab: 0
};
// Admin configuration (in-memory)
const adminConfig = {
appName: 'AÇO CALC PRO',
appSubtitle: 'Plataforma Técnica com Base de Dados de Materiais Brasileiros',
footerText: '© 2025 AÇO CALC PRO v6.5 PROFESSIONAL EDITION - Plataforma Técnica com Base de Dados de Materiais Brasileiros',
themeDefault: 'escuro',
modeDefault: 'simples',
toolsVisibility: {
'cev': true,
'seletor': true,
'equivalencias': false,
'comparativo': false,
'parafusos': true,
'layout': true,
'parafuso-vs-solda': false,
'preaquecimento': true,
'dureza': true,
'charpy': true,
'certificado': false,
'ultrassom': false,
'area-pintura': true,
'consumo-tinta': true,
'galvanizacao': false,
'custo-pintura': true,
'secagem': false,
'inspecao-pintura': false,
'orcamento': true,
'peso-rigging': false,
'referencia': false
}
};
// ========================================
// CSV MAPPING AND LOADING FUNCTIONS v6.6
// ========================================
const csvMapping = {
'perfil_w': 'csv_dados/perfis_w.csv',
'perfil_i': 'csv_dados/perfis_i.csv',
'perfil_hp': 'csv_dados/perfis_hp.csv',
'cantoneira': 'csv_dados/cantoneiras.csv',
'tubo_circ': 'csv_dados/tubos_circulares.csv',
'tubo_rhs': 'csv_dados/tubos_rhs.csv',
'chapa': 'csv_dados/chapas.csv',
'barra': 'csv_dados/barras.csv',
'eletrodo': 'csv_dados/eletrodos.csv',
'parafuso': 'csv_dados/parafusos.csv',
'tinta': 'csv_dados/tintas.csv'
};
// Function to load CSV
async function carregarCSV(tipoMaterial) {
const caminhoCSV = csvMapping[tipoMaterial];
if (!caminhoCSV) {
console.warn('Tipo de material não mapeado:', tipoMaterial);
return [];
}
try {
const response = await fetch(caminhoCSV);
if (!response.ok) {
throw new Error(`Erro ao carregar ${caminhoCSV}: ${response.status}`);
}
const csvText = await response.text();
return parseCSV(csvText);
} catch (error) {
console.error('Erro ao carregar CSV:', error);
// Return fallback data from materialsDatabase
return getFallbackData(tipoMaterial);
}
}
// Function to parse CSV
function parseCSV(csvText) {
const lines = csvText.trim().split('\n');
if (lines.length === 0) return [];
const headers = lines[0].split(',').map(h => h.trim());
const dados = [];
for (let i = 1; i < lines.length; i++) {
const obj = {};
const currentLine = lines[i].split(',');
for (let j = 0; j < headers.length; j++) {
obj[headers[j]] = currentLine[j] ? currentLine[j].trim() : '';
}
dados.push(obj);
}
return dados;
}
// Fallback to in-memory data if CSV fails
function getFallbackData(tipoMaterial) {
const typeMap = {
'perfil_w': 'perfis_w',
'perfil_i': 'perfis_i',
'perfil_hp': 'perfis_hp',
'cantoneira': 'cantoneiras',
'tubo_circ': 'tubos_circulares',
'tubo_rhs': 'tubos_retangulares',
'chapa': 'chapas',
'barra': 'barras',
'eletrodo': 'consumiveis',
'parafuso': 'parafusos',
'tinta': 'consumiveis'
};
const dbKey = typeMap[tipoMaterial];
return materialsDatabase[dbKey] || [];
}
// ========================================
// COMPREHENSIVE MATERIALS DATABASE
// ========================================
const materialsDatabase = {
perfis_w: [
{id: 'w150_13', nome: 'W150×13', altura: 150, aba: 100, peso: 13, tipo: 'Perfil W', unidade: 'm'},
{id: 'w150_18', nome: 'W150×18', altura: 150, aba: 100, peso: 18, tipo: 'Perfil W', unidade: 'm'},
{id: 'w200_15', nome: 'W200×15', altura: 200, aba: 100, peso: 15, tipo: 'Perfil W', unidade: 'm'},
{id: 'w200_22', nome: 'W200×22', altura: 200, aba: 100, peso: 22, tipo: 'Perfil W', unidade: 'm'},
{id: 'w200_31', nome: 'W200×31', altura: 200, aba: 100, peso: 31, tipo: 'Perfil W', unidade: 'm'},
{id: 'w250_25', nome: 'W250×25', altura: 254, aba: 203, peso: 25, tipo: 'Perfil W', unidade: 'm'},
{id: 'w250_32', nome: 'W250×32', altura: 254, aba: 203, peso: 32, tipo: 'Perfil W', unidade: 'm'},
{id: 'w250_38', nome: 'W250×38', altura: 254, aba: 203, peso: 38, tipo: 'Perfil W', unidade: 'm'},
{id: 'w310_24', nome: 'W310×24', altura: 307, aba: 200, peso: 24, tipo: 'Perfil W', unidade: 'm'},
{id: 'w310_33', nome: 'W310×33', altura: 307, aba: 203, peso: 33, tipo: 'Perfil W', unidade: 'm'},
{id: 'w310_39', nome: 'W310×39', altura: 307, aba: 203, peso: 39, tipo: 'Perfil W', unidade: 'm'},
{id: 'w310_52', nome: 'W310×52', altura: 307, aba: 205, peso: 52, tipo: 'Perfil W', unidade: 'm'},
{id: 'w310_67', nome: 'W310×67', altura: 310, aba: 306, peso: 67, tipo: 'Perfil W', unidade: 'm'},
{id: 'w360_44', nome: 'W360×44', altura: 355, aba: 203, peso: 44, tipo: 'Perfil W', unidade: 'm'},
{id: 'w360_51', nome: 'W360×51', altura: 357, aba: 204, peso: 51, tipo: 'Perfil W', unidade: 'm'},
{id: 'w360_72', nome: 'W360×72', altura: 361, aba: 206, peso: 72, tipo: 'Perfil W', unidade: 'm'},
{id: 'w410_60', nome: 'W410×60', altura: 410, aba: 205, peso: 60, tipo: 'Perfil W', unidade: 'm'},
{id: 'w410_85', nome: 'W410×85', altura: 414, aba: 209, peso: 85, tipo: 'Perfil W', unidade: 'm'},
{id: 'w500_84', nome: 'W500×84', altura: 510, aba: 210, peso: 84, tipo: 'Perfil W', unidade: 'm'},
{id: 'w610_101', nome: 'W610×101', altura: 615, aba: 210, peso: 101, tipo: 'Perfil W', unidade: 'm'}
],
perfis_i: [
{id: 'ipe_100', nome: 'IPE 100', altura: 100, aba: 55, peso: 8.1, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_120', nome: 'IPE 120', altura: 120, aba: 64, peso: 10.4, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_140', nome: 'IPE 140', altura: 140, aba: 73, peso: 12.9, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_160', nome: 'IPE 160', altura: 160, aba: 82, peso: 15.8, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_180', nome: 'IPE 180', altura: 180, aba: 91, peso: 18.8, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_200', nome: 'IPE 200', altura: 200, aba: 100, peso: 22.4, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_240', nome: 'IPE 240', altura: 240, aba: 120, peso: 30.7, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_300', nome: 'IPE 300', altura: 300, aba: 150, peso: 42.2, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_360', nome: 'IPE 360', altura: 360, aba: 170, peso: 57.1, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_400', nome: 'IPE 400', altura: 400, aba: 180, peso: 66.3, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_500', nome: 'IPE 500', altura: 500, aba: 200, peso: 90.7, tipo: 'Perfil I', unidade: 'm'},
{id: 'ipe_600', nome: 'IPE 600', altura: 600, aba: 220, peso: 122, tipo: 'Perfil I', unidade: 'm'}
],
perfis_hp: [
{id: 'hp200_53', nome: 'HP200×53', altura: 203, aba: 203, peso: 53, tipo: 'Perfil HP', unidade: 'm'},
{id: 'hp250_63', nome: 'HP250×63', altura: 254, aba: 254, peso: 63, tipo: 'Perfil HP', unidade: 'm'},
{id: 'hp310_79', nome: 'HP310×79', altura: 310, aba: 310, peso: 79, tipo: 'Perfil HP', unidade: 'm'},
{id: 'hp360_102', nome: 'HP360×102', altura: 362, aba: 362, peso: 102, tipo: 'Perfil HP', unidade: 'm'}
],
cantoneiras: [
{id: 'l50_50_5', nome: 'L50×50×5', lado: 50, esp: 5, peso: 3.75, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l50_50_6', nome: 'L50×50×6', lado: 50, esp: 6, peso: 4.50, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l63_63_6', nome: 'L63×63×6', lado: 63, esp: 6, peso: 5.80, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l75_75_8', nome: 'L75×75×8', lado: 75, esp: 8, peso: 9.1, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l100_100_10', nome: 'L100×100×10', lado: 100, esp: 10, peso: 15.0, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l100_100_12', nome: 'L100×100×12', lado: 100, esp: 12, peso: 17.8, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l125_125_12', nome: 'L125×125×12', lado: 125, esp: 12, peso: 22.4, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l150_150_12', nome: 'L150×150×12', lado: 150, esp: 12, peso: 26.8, tipo: 'Cantoneira', unidade: 'm'},
{id: 'l150_150_15', nome: 'L150×150×15', lado: 150, esp: 15, peso: 32.8, tipo: 'Cantoneira', unidade: 'm'}
],
tubos_circulares: [
{id: 'tubo_50_2', nome: 'Ø50×2.0', diametro: 50, esp: 2.0, peso: 2.45, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_60_2', nome: 'Ø60×2.0', diametro: 60, esp: 2.0, peso: 2.95, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_76_25', nome: 'Ø76×2.5', diametro: 76, esp: 2.5, peso: 4.65, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_80_3', nome: 'Ø80×3.0', diametro: 80, esp: 3.0, peso: 5.85, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_100_3', nome: 'Ø100×3.0', diametro: 100, esp: 3.0, peso: 7.35, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_100_4', nome: 'Ø100×4.0', diametro: 100, esp: 4.0, peso: 9.65, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_120_4', nome: 'Ø120×4.0', diametro: 120, esp: 4.0, peso: 11.70, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_150_5', nome: 'Ø150×5.0', diametro: 150, esp: 5.0, peso: 18.20, tipo: 'Tubo Circular', unidade: 'm'},
{id: 'tubo_200_4', nome: 'Ø200×4.0', diametro: 200, esp: 4.0, peso: 19.60, tipo: 'Tubo Circular', unidade: 'm'}
],
tubos_retangulares: [
{id: 'rhs_100_100_4', nome: '100×100×4', largura: 100, altura: 100, esp: 4, peso: 15.0, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_100_100_5', nome: '100×100×5', largura: 100, altura: 100, esp: 5, peso: 18.5, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_120_80_5', nome: '120×80×5', largura: 120, altura: 80, esp: 5, peso: 18.7, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_150_100_5', nome: '150×100×5', largura: 150, altura: 100, esp: 5, peso: 22.0, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_150_150_5', nome: '150×150×5', largura: 150, altura: 150, esp: 5, peso: 27.8, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_150_150_6', nome: '150×150×6', largura: 150, altura: 150, esp: 6, peso: 33.1, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_200_100_6', nome: '200×100×6', largura: 200, altura: 100, esp: 6, peso: 30.6, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_200_200_6', nome: '200×200×6', largura: 200, altura: 200, esp: 6, peso: 43.8, tipo: 'Tubo RHS', unidade: 'm'},
{id: 'rhs_200_200_8', nome: '200×200×8', largura: 200, altura: 200, esp: 8, peso: 57.8, tipo: 'Tubo RHS', unidade: 'm'}
],
chapas: [
{id: 'chapa_475', nome: 'CHAPA 4.75mm', esp: 4.75, formato: '2500×1250', peso_m2: 37.3, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_635', nome: 'CHAPA 6.35mm', esp: 6.35, formato: '2500×1250', peso_m2: 49.8, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_95', nome: 'CHAPA 9.5mm', esp: 9.5, formato: '2500×1250', peso_m2: 74.6, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_127', nome: 'CHAPA 12.7mm', esp: 12.7, formato: '2500×1250', peso_m2: 99.7, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_159', nome: 'CHAPA 15.9mm', esp: 15.9, formato: '2500×1250', peso_m2: 124.8, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_191', nome: 'CHAPA 19.1mm', esp: 19.1, formato: '2500×1250', peso_m2: 150.0, tipo: 'Chapa', unidade: 'm²'},
{id: 'chapa_254', nome: 'CHAPA 25.4mm', esp: 25.4, formato: '2000×1000', peso_m2: 199.4, tipo: 'Chapa', unidade: 'm²'}
],
barras: [
{id: 'barra_8', nome: 'Ø8mm', diametro: 8, peso: 0.395, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_10', nome: 'Ø10mm', diametro: 10, peso: 0.616, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_12', nome: 'Ø12mm', diametro: 12, peso: 0.888, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_16', nome: 'Ø16mm', diametro: 16, peso: 1.580, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_20', nome: 'Ø20mm', diametro: 20, peso: 2.466, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_25', nome: 'Ø25mm', diametro: 25, peso: 3.852, tipo: 'Barra Redonda', unidade: 'm'},
{id: 'barra_32', nome: 'Ø32mm', diametro: 32, peso: 6.313, tipo: 'Barra Redonda', unidade: 'm'}
],
consumiveis: [
{id: 'e7018', nome: 'E7018 (Eletrodo)', peso_kg: 1, custo_kg: 45, tipo: 'Consumível', unidade: 'kg'},
{id: 'e6013', nome: 'E6013 (Eletrodo)', peso_kg: 1, custo_kg: 28, tipo: 'Consumível', unidade: 'kg'},
{id: 'e8018', nome: 'E8018 (Eletrodo)', peso_kg: 1, custo_kg: 65, tipo: 'Consumível', unidade: 'kg'},
{id: 'er70s6', nome: 'ER70S-6 (MIG)', peso_kg: 1, custo_kg: 32, tipo: 'Consumível', unidade: 'kg'},
{id: 'tinta_c3', nome: 'TINTA C3 Epóxi', custo_l: 80, tipo: 'Consumível', unidade: 'L'},
{id: 'tinta_c4', nome: 'TINTA C4 Epóxi+PU', custo_l: 120, tipo: 'Consumível', unidade: 'L'},
{id: 'tinta_c5', nome: 'TINTA C5 Zinc-Rich', custo_l: 150, tipo: 'Consumível', unidade: 'L'},
{id: 'fundo_zinc', nome: 'FUNDO Zinc-Rich', custo_l: 60, tipo: 'Consumível', unidade: 'L'}
],
parafusos: [
{id: 'para_a325_m12', nome: 'Parafuso A325 M12', custo_un: 0.85, tipo: 'Parafuso', unidade: 'un'},
{id: 'para_a325_m16', nome: 'Parafuso A325 M16', custo_un: 1.20, tipo: 'Parafuso', unidade: 'un'},
{id: 'para_a325_m20', nome: 'Parafuso A325 M20', custo_un: 1.80, tipo: 'Parafuso', unidade: 'un'},
{id: 'para_a490_m16', nome: 'Parafuso A490 M16', custo_un: 2.50, tipo: 'Parafuso', unidade: 'un'},
{id: 'porca_m12', nome: 'Porca M12', custo_un: 0.15, tipo: 'Parafuso', unidade: 'un'},
{id: 'porca_m16', nome: 'Porca M16', custo_un: 0.25, tipo: 'Parafuso', unidade: 'un'},
{id: 'arruela', nome: 'Arruela DIN 125', custo_un: 0.08, tipo: 'Parafuso', unidade: 'un'}
]
};
const regionalPricing = {
sudeste: {
perfil_w: 7.50,
perfil_i: 7.50,
perfil_hp: 7.50,
cantoneira: 7.50,
tubo_circ: 8.00,
tubo_rhs: 8.50,
chapa: 7.80,
barra: 7.50
},
sul: {
perfil_w: 7.20,
perfil_i: 7.20,
perfil_hp: 7.20,
cantoneira: 7.20,
tubo_circ: 7.80,
tubo_rhs: 8.20,
chapa: 7.50,
barra: 7.20
},
nordeste: {
perfil_w: 8.00,
perfil_i: 8.00,
perfil_hp: 8.00,
cantoneira: 8.00,
tubo_circ: 8.50,
tubo_rhs: 9.00,
chapa: 8.20,
barra: 8.00
},
centrooeste: {
perfil_w: 7.70,
perfil_i: 7.70,
perfil_hp: 7.70,
cantoneira: 7.70,
tubo_circ: 8.30,
tubo_rhs: 8.70,
chapa: 8.00,
barra: 7.70
}
};
// Steel database
const steelDatabase = {
a36: { nome: 'ASTM A36', fy: 250, fu: 400, elong: 20, cev: 0.41, charpy: 27, temp: -20, custo: 100, soldabilidade: '⭐⭐⭐⭐⭐', equiv: ['EN S235JR', 'JIS SS400'] },
a572: { nome: 'ASTM A572 Gr.50', fy: 345, fu: 450, elong: 18, cev: 0.45, charpy: 27, temp: -20, custo: 115, soldabilidade: '⭐⭐⭐⭐', equiv: ['EN S355J2', 'JIS SM490'] },
a588: { nome: 'ASTM A588', fy: 345, fu: 485, elong: 19, cev: 0.50, charpy: 27, temp: -20, custo: 125, soldabilidade: '⭐⭐⭐', equiv: ['EN S355K2G3', 'API 2H'] },
a992: { nome: 'ASTM A992', fy: 345, fu: 450, elong: 21, cev: 0.45, charpy: 27, temp: -20, custo: 118, soldabilidade: '⭐⭐⭐⭐', equiv: ['EN S355J2'] },
s235: { nome: 'EN S235JR', fy: 235, fu: 360, elong: 26, cev: 0.38, charpy: 27, temp: -20, custo: 100, soldabilidade: '⭐⭐⭐⭐⭐', equiv: ['ASTM A36', 'JIS SS400'] },
s355: { nome: 'EN S355J2', fy: 355, fu: 490, elong: 22, cev: 0.50, charpy: 27, temp: -20, custo: 115, soldabilidade: '⭐⭐⭐⭐', equiv: ['ASTM A572', 'API 2H'] },
s460: { nome: 'EN S460', fy: 460, fu: 540, elong: 17, cev: 0.55, charpy: 27, temp: -20, custo: 140, soldabilidade: '⭐⭐⭐', equiv: ['ASTM A514'] },
ar350: { nome: 'NBR AR350', fy: 345, fu: 450, elong: 18, cev: 0.45, charpy: 27, temp: -20, custo: 115, soldabilidade: '⭐⭐⭐⭐', equiv: ['ASTM A572', 'EN S355J2'] }
};
// Regional pricing
const regionalPrices = {
sudeste: { a36: 2800, a572: 3100, solda: 65, pintura: 40, galv: 180 },
sul: { a36: 2700, a572: 3000, solda: 60, pintura: 38, galv: 175 },
nordeste: { a36: 3000, a572: 3300, solda: 70, pintura: 42, galv: 190 },
centrooeste: { a36: 2900, a572: 3200, solda: 68, pintura: 41, galv: 185 }
};
// Normative requirements
const certRequirements = {
astm_a36: ['fy ≥ 250 MPa', 'fu 400-550 MPa', 'Alongamento ≥ 20%', 'C ≤ 0.25%', 'Mn ≤ 1.20%'],
astm_a572: ['fy ≥ 345 MPa', 'fu 450-620 MPa', 'Alongamento ≥ 18%', 'CEV ≤ 0.55%'],
en_s235: ['fy ≥ 235 MPa', 'fu 360-510 MPa', 'Alongamento ≥ 26%'],
en_s355: ['fy ≥ 355 MPa', 'fu 470-630 MPa', 'Alongamento ≥ 22%', 'Charpy 27J @ -20°C'],
nbr_ar350: ['fy ≥ 345 MPa', 'fu ≥ 450 MPa', 'Alongamento ≥ 18%', 'C ≤ 0.15%']
};
let currentChart = null;
// ========================================
// NAVIGATION & UI FUNCTIONS
// ========================================
function switchSidebarTab(index) {
document.querySelectorAll('.sidebar-tab').forEach((tab, i) => {
tab.classList.toggle('active', i === index);
});
document.querySelectorAll('.sidebar-content').forEach((content, i) => {
content.classList.toggle('active', i === index);
});
appState.currentSidebarTab = index;
}
function showSection(sectionId) {
appState.currentSection = sectionId;
// Update sidebar active state
document.querySelectorAll('.sidebar-item').forEach(item => {
item.classList.toggle('active', item.dataset.section === sectionId);
});
// Load section content
loadSectionContent(sectionId);
// Add help button after content loads
setTimeout(() => addHelpButton(sectionId), 100);
}
function loadSectionContent(sectionId) {
const content = document.getElementById('main-content');
const sections = {
'cev': getCEVContent(),
'seletor': getSeletorContent(),
'equivalencias': getEquivalenciasContent(),
'comparativo': getComparativoContent(),
'parafusos': getParafusosContent(),
'layout': getLayoutContent(),
'parafuso-vs-solda': getParafusoVsSoldaContent(),
'preaquecimento': getPreaquecimentoContent(),
'solda-filete': getSoldaFileteContent(),
'energia-soldagem': getEnergiaSoldagemContent(),
'consumo-eletrodos': getConsumoEletrodosContent(),
'dureza': getDurezaContent(),
'charpy': getCharpyContent(),
'certificado': getCertificadoContent(),
'ultrassom': getUltrassomContent(),
'area-pintura': getAreaPinturaContent(),
'consumo-tinta': getConsumoTintaContent(),
'galvanizacao': getGalvanizacaoContent(),
'custo-pintura': getCustoPinturaContent(),
'secagem': getSecagemContent(),
'inspecao-pintura': getInspecaoPinturaContent(),
'orcamento': getOrcamentoContent(),
'peso-rigging': getPesoRiggingContent(),
'referencia': getReferenciaContent()
};
content.innerHTML = sections[sectionId] || '<p>Seção não encontrada</p>';
}
function toggleTheme() {
appState.currentTheme = appState.currentTheme === 'dark' ? 'light' : 'dark';
applyTheme();
}
function applyTheme() {
document.documentElement.setAttribute('data-theme', appState.currentTheme);
const btn = document.getElementById('theme-toggle');
if (btn) {
btn.textContent = appState.currentTheme === 'dark' ? '☀️ Claro' : '🌙 Escuro';
btn.classList.toggle('light', appState.currentTheme === 'light');
}
}
function toggleExpertMode() {
appState.expertMode = !appState.expertMode;
document.documentElement.classList.toggle('expert-mode', appState.expertMode);
const btn = document.getElementById('expert-toggle');
btn.textContent = appState.expertMode ? '🔬 Expert' : '🎯 Simples';
btn.classList.toggle('active', appState.expertMode);
filterToolsByMode();
}
function filterToolsByMode() {
const allItems = document.querySelectorAll('.sidebar-item');
allItems.forEach(item => {
const sectionId = item.dataset.section;
if (appState.expertMode) {
// Expert mode: show all tools
item.classList.remove('hidden');
} else {
// Simple mode: show only selected tools
const isVisible = adminConfig.toolsVisibility[sectionId];
if (isVisible) {
item.classList.remove('hidden');
} else {
item.classList.add('hidden');
}
}
});
}
function toggleFavorite(event, sectionId) {
event.stopPropagation();
const starBtn = event.target;
const favIndex = appState.favorites.indexOf(sectionId);
if (favIndex > -1) {
appState.favorites.splice(favIndex, 1);
starBtn.textContent = '☆';
starBtn.classList.remove('active');
} else {
appState.favorites.push(sectionId);
starBtn.textContent = '★';
starBtn.classList.add('active');
}
}
function addToHistory(title, details) {
const historyItem = {
id: Date.now(),
title: title,
details: details,
date: new Date().toLocaleString('pt-BR')
};
appState.history.unshift(historyItem);
if (appState.history.length > 100) {
appState.history = appState.history.slice(0, 100);
}
}
function openHistoryModal() {
const modal = document.getElementById('history-modal');
const list = document.getElementById('history-list');
if (appState.history.length === 0) {
list.innerHTML = '<p style="text-align: center; color: var(--color-text-secondary);">Nenhum cálculo no histórico</p>';
} else {
list.innerHTML = appState.history.map(item => `
<div class="history-item">
<div style="font-weight: 600; margin-bottom: 4px;">${item.title}</div>
<div style="font-size: 12px; color: var(--color-text-secondary);">${item.date}</div>
<p style="margin-top: 8px; font-size: 14px;">${item.details}</p>
</div>
`).join('');
}
modal.classList.add('active');
}
function closeHistoryModal() {
document.getElementById('history-modal').classList.remove('active');
}
function openFavoritesModal() {
const modal = document.getElementById('favorites-modal');
const list = document.getElementById('favorites-list');
if (appState.favorites.length === 0) {
list.innerHTML = '<p style="text-align: center; color: var(--color-text-secondary);">Nenhuma seção favoritada</p>';
} else {
list.innerHTML = appState.favorites.map(sectionId => `
<div class="favorite-item" style="cursor: pointer;" onclick="showSection('${sectionId}'); closeFavoritesModal();">
<strong>${getSectionName(sectionId)}</strong>
</div>
`).join('');
}
modal.classList.add('active');
}
function closeFavoritesModal() {
document.getElementById('favorites-modal').classList.remove('active');
}
function updateUtFields() {
const type = document.getElementById('ut-type').value;
const diameterGroup = document.getElementById('ut-diameter-group');
const qtyGroup = document.getElementById('ut-qty-group');
const lengthGroup = document.getElementById('ut-length-group');
if (type === 'porosidade') {
diameterGroup.style.display = 'block';
qtyGroup.style.display = 'block';
lengthGroup.style.display = 'block';
} else if (type === 'trinca' || type === 'falta-fusao' || type === 'falta-penetracao') {
diameterGroup.style.display = 'none';
qtyGroup.style.display = 'none';
lengthGroup.style.display = 'block';
} else {
diameterGroup.style.display = 'block';
qtyGroup.style.display = 'block';
lengthGroup.style.display = 'block';
}
}
function analisarUltrassom() {
const norm = document.getElementById('ut-norm').value;
const type = document.getElementById('ut-type').value;
const location = document.getElementById('ut-location').value;
const diameter = parseFloat(document.getElementById('ut-diameter').value) || 0;
const qty = parseInt(document.getElementById('ut-qty').value) || 0;
const length = parseFloat(document.getElementById('ut-length').value) || 0;
const depth = parseFloat(document.getElementById('ut-depth').value) || 0;
const thickness = parseFloat(document.getElementById('ut-thickness').value) || 0;
let maxDiameter = 3;
let maxQtyIn25mm = 5;
let maxDepth = thickness / 4;
let status = '✅ ACEITA';
let alertClass = 'alert-success';
let reasoning = [];
if (norm === 'aws') {
maxDiameter = 3;
maxQtyIn25mm = 5;
} else if (norm === 'asme') {
maxDiameter = 4;
maxQtyIn25mm = 6;
} else {
maxDiameter = 3.5;
maxQtyIn25mm = 5;
}
if (type === 'porosidade') {
const totalLength = qty * diameter;
const allowedInSpan = 25 * 0.36;
if (diameter > maxDiameter) {
status = '❌ REJEITA';
alertClass = 'alert-error';
reasoning.push(`Diâmetro ${diameter}mm > máximo ${maxDiameter}mm`);
}
if (qty > maxQtyIn25mm) {
status = '❌ REJEITA';
alertClass = 'alert-error';
reasoning.push(`Quantidade ${qty} > máximo ${maxQtyIn25mm} poros em 25mm`);
}
if (totalLength > allowedInSpan) {
status = '⚠️ ANÁLISE';
if (alertClass !== 'alert-error') alertClass = 'alert-warning';
reasoning.push(`Comprimento total ${totalLength.toFixed(1)}mm > permitido ${allowedInSpan.toFixed(1)}mm`);
}
if (depth > maxDepth) {
status = '❌ REJEITA';
alertClass = 'alert-error';
reasoning.push(`Profundidade ${depth}mm > máximo ${maxDepth.toFixed(1)}mm (esp/4)`);
}
if (status === '✅ ACEITA') {
reasoning.push(`Diâmetro ${diameter}mm ≤ ${maxDiameter}mm ✓`);
reasoning.push(`Quantidade ${qty}${maxQtyIn25mm} em 25mm ✓`);
reasoning.push(`Comprimento total ${totalLength.toFixed(1)}mm ≤ ${allowedInSpan.toFixed(1)}mm ✓`);
reasoning.push(`Profundidade ${depth}mm ≤ ${maxDepth.toFixed(1)}mm ✓`);
}
} else if (type === 'trinca') {
status = '❌ REJEITA';
alertClass = 'alert-error';
reasoning.push('Trincas não são permitidas em nenhuma norma');
reasoning.push('Ação requerida: Remover completamente a solda e refazer');
} else if (type === 'falta-fusao' || type === 'falta-penetracao') {
if (length > 25) {
status = '❌ REJEITA';
alertClass = 'alert-error';
reasoning.push(`Comprimento ${length}mm > máximo 25mm`);
} else if (length > 10) {
status = '⚠️ ANÁLISE';
alertClass = 'alert-warning';
reasoning.push(`Comprimento ${length}mm requer análise de engenharia`);
} else {
status = '✅ ACEITA';
reasoning.push(`Comprimento ${length}mm ≤ 10mm (aceitável) ✓`);
}
}
const normName = norm === 'aws' ? 'AWS D1.1' : norm === 'asme' ? 'ASME Sec VIII' : 'DNV-GL';
const typeName = {
'porosidade': 'Porosidade',
'inclusao': 'Inclusão de Escória',
'falta-fusao': 'Falta de Fusão',
'falta-penetracao': 'Falta de Penetração',
'trinca': 'Trinca',
'mordedura': 'Mordedura'
}[type];
document.getElementById('ut-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-1); border-left: 4px solid var(--color-primary);">
<div class="result-title">🏥 INTERPRETAÇÃO ULTRASSOM - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>NORMA APLICADA:</strong> ${normName}<br>
<strong>Descontinuidade:</strong> ${typeName}<br>
<strong>Localização:</strong> ${location.charAt(0).toUpperCase() + location.slice(1)}
</div>
${type === 'porosidade' ? `
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px;">
<strong>DADOS DA DESCONTINUIDADE:</strong><br>
• Diâmetro: ${diameter} mm<br>
• Quantidade: ${qty} poros<br>
• Tamanho Total: ${(qty * diameter).toFixed(1)} mm<br>
• Profundidade: ${depth} mm<br>
• Espessura Chapa: ${thickness} mm
</div>
<div style="padding: 16px; background: var(--color-bg-2); border-radius: 8px; margin-bottom: 16px;">
<strong>CRITÉRIO ${normName}:</strong><br>
<strong>Porosidade Isolada:</strong><br>
• Diâmetro máximo: ${maxDiameter} mm<br>
• Quantidade máxima: ${maxQtyIn25mm} poros em 25mm<br>
• Comprimento total permitido: ${(25 * 0.36).toFixed(1)} mm em 25mm<br>
• Profundidade máxima: ${maxDepth.toFixed(1)} mm (espessura/4)
</div>
` : type === 'trinca' ? `
<div style="padding: 16px; background: var(--color-bg-4); border-radius: 8px; margin-bottom: 16px; border: 2px solid var(--color-error);">
<strong>⚠️ DESCONTINUIDADE CRÍTICA:</strong><br>
Trincas são defeitos graves que comprometem a integridade estrutural.<br>
Nenhuma norma permite trincas de qualquer tamanho.
</div>
` : `
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px;">
<strong>DADOS:</strong><br>
• Comprimento: ${length} mm<br>
• Profundidade: ${depth} mm<br>
• Espessura: ${thickness} mm
</div>
`}
<div style="padding: 16px; background: var(--color-bg-3); border-radius: 8px; margin-bottom: 16px;">
<strong>📊 ANÁLISE:</strong><br>
${reasoning.map(r => `${r}`).join('<br>')}
</div>
<div class="alert ${alertClass}">
<strong>RESULTADO: ${status}</strong><br>
${status === '✅ ACEITA' ? 'Descontinuidade dentro dos limites permitidos. A solda está APROVADA para serviço.' :
status === '❌ REJEITA' ? 'Descontinuidade excede limites. REPROVAR a solda e realizar retrabalho.' :
'Descontinuidade requer análise de engenharia detalhada antes da aprovação.'}
</div>
${status === '❌ REJEITA' ? `
<div style="margin-top: 16px; padding: 16px; background: var(--color-bg-6); border-radius: 8px;">
<strong>🔧 OPÇÕES DE REPARO:</strong><br>
1. <strong>Retrabalho Total:</strong> Remover completamente a solda defeituosa e refazer<br>
2. <strong>Retoque Local:</strong> Escarear o defeito e preencher com nova solda<br>
3. <strong>Análise de Risco:</strong> Para casos não-críticos, avaliar se pode ser aceito com ressalvas
</div>
` : ''}
</div>
`;
addToHistory('Ultrassom', `${typeName}, ${status}`);
}
function calcularCustoTotal() {
const area = parseFloat(document.getElementById('custo-area').value) || 0;
const regiao = document.getElementById('custo-regiao').value;
const tipoTinta = document.getElementById('custo-tipo-tinta').value;
const custoMO = parseFloat(document.getElementById('custo-mo').value) || 85;
const prod = parseFloat(document.getElementById('custo-prod').value) || 5;
const volume = parseFloat(document.getElementById('custo-volume').value) || 0;
const incluirEPI = document.getElementById('custo-incluir-epi').checked;
const incluirEquip = document.getElementById('custo-incluir-equip').checked;
const precosTinta = {
sudeste: { padrao: 80, premium: 120, economica: 50 },
sul: { padrao: 75, premium: 115, economica: 48 },
nordeste: { padrao: 85, premium: 125, economica: 52 },
centrooeste: { padrao: 82, premium: 122, economica: 51 }
};
const precoLitro = precosTinta[regiao][tipoTinta];
const custoMaterial = volume * precoLitro;
const horasTotais = area / prod;
const custoMaoObra = horasTotais * custoMO;
const custoEPI = incluirEPI ? 500 : 0;
const custoEquip = incluirEquip ? 800 : 0;
const subtotal = custoMaterial + custoMaoObra + custoEPI + custoEquip;
const margem = subtotal * 0.10;
const total = subtotal + margem;
const custoPorM2 = total / area;
const regiaoNome = {
sudeste: 'Sudeste',
sul: 'Sul',
nordeste: 'Nordeste',
centrooeste: 'Centro-Oeste'
}[regiao];
const tintaNome = {
padrao: 'Padrão Industrial',
premium: 'Premium',
economica: 'Econômica'
}[tipoTinta];
document.getElementById('custo-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-2); border-left: 4px solid var(--color-warning);">
<div class="result-title">💰 CUSTO TOTAL - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>PARÂMETROS:</strong><br>
Área: ${area} m²<br>
Região: ${regiaoNome}<br>
Tinta: ${tintaNome} (R$ ${precoLitro}/L)<br>
Volume: ${volume} L
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Custo Material (Tinta)</div>
<div class="result-value">R$ ${custoMaterial.toFixed(2)}</div>
</div>
<div class="result-item">
<div class="result-label">Custo Mão de Obra</div>
<div class="result-value">R$ ${custoMaoObra.toFixed(2)}</div>
</div>
${incluirEPI ? `
<div class="result-item">
<div class="result-label">EPI e Consumíveis</div>
<div class="result-value">R$ ${custoEPI.toFixed(2)}</div>
</div>
` : ''}
${incluirEquip ? `
<div class="result-item">
<div class="result-label">Aluguel Equipamentos</div>
<div class="result-value">R$ ${custoEquip.toFixed(2)}</div>
</div>
` : ''}
</div>
<div style="margin-top: 20px; padding: 20px; background: var(--color-bg-3); border-radius: 12px; border: 2px solid var(--color-success);">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div>
<strong>Subtotal:</strong><br>
<span style="font-size: 20px;">R$ ${subtotal.toFixed(2)}</span>
</div>
<div>
<strong>Margem (10%):</strong><br>
<span style="font-size: 20px;">R$ ${margem.toFixed(2)}</span>
</div>
</div>
<hr style="margin: 16px 0; border: 1px solid var(--color-border);">
<div style="text-align: center;">
<strong style="font-size: 18px;">TOTAL GERAL:</strong><br>
<span style="font-size: 32px; color: var(--color-success); font-weight: bold;">R$ ${total.toFixed(2)}</span><br>
<span style="color: var(--color-text-secondary);">(Custo por m²: R$ ${custoPorM2.toFixed(2)}/m²)</span>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>📊 BREAKDOWN DETALHADO:</strong><br>
• Horas totais: ${horasTotais.toFixed(1)} h (${area}m² ÷ ${prod}m²/h)<br>
• Custo/hora MO: R$ ${custoMO}/h<br>
• Produtividade: ${prod} m²/h<br>
• Tempo estimado: ${Math.ceil(horasTotais / 8)} dias (8h/dia)
</div>
</div>
`;
addToHistory('Custo Pintura', `${area}m², R$ ${total.toFixed(2)}`);
}
function calcularSecagem() {
const tipo = document.getElementById('sec-tipo').value;
const temp = parseFloat(document.getElementById('sec-temp').value) || 25;
const umidade = parseFloat(document.getElementById('sec-umidade').value) || 60;
const espessura = parseFloat(document.getElementById('sec-espessura').value) || 80;
const dadosTinta = {
epoxi: { tempIdeal: 25, umidadeMax: 85, tempoBase: 24, fatorEsp: 0.2 },
poliuretano: { tempIdeal: 20, umidadeMax: 80, tempoBase: 16, fatorEsp: 0.15 },
alquidica: { tempIdeal: 25, umidadeMax: 75, tempoBase: 48, fatorEsp: 0.3 },
acrilica: { tempIdeal: 23, umidadeMax: 70, tempoBase: 12, fatorEsp: 0.1 }
};
const dados = dadosTinta[tipo];
const fatorTemp = 1 + ((dados.tempIdeal - temp) * 0.05);
const fatorUmid = umidade > dados.umidadeMax ? 1.3 : 1.0;
const fatorEsp = 1 + ((espessura - 80) / 80 * dados.fatorEsp);
const tempoToque = dados.tempoBase * 0.25 * fatorTemp * fatorUmid * fatorEsp;
const tempoManipulacao = dados.tempoBase * 0.5 * fatorTemp * fatorUmid * fatorEsp;
const tempoProximaDemao = dados.tempoBase * fatorTemp * fatorUmid * fatorEsp;
const tempoCuraTotal = dados.tempoBase * 3 * fatorTemp * fatorUmid * fatorEsp;
let alertas = [];
let alertClass = 'alert-success';
if (temp < 5) {
alertas.push('⚠️ Temperatura muito baixa (< 5°C) - NÃO APLICAR');
alertClass = 'alert-error';
} else if (temp < 10) {
alertas.push('⚠️ Temperatura baixa - Tempo de secagem significativamente aumentado');
alertClass = 'alert-warning';
}
if (umidade > dados.umidadeMax) {
alertas.push(`⚠️ Umidade acima do máximo (${dados.umidadeMax}%) - Risco de defeitos`);
alertClass = 'alert-error';
} else if (umidade > dados.umidadeMax - 10) {
alertas.push(`⚠️ Umidade próxima do limite - Monitorar condições`);
if (alertClass !== 'alert-error') alertClass = 'alert-warning';
}
if (temp > 40) {
alertas.push('⚠️ Temperatura muito alta - Risco de secagem rápida e defeitos');
if (alertClass !== 'alert-error') alertClass = 'alert-warning';
}
if (alertas.length === 0) {
alertas.push('✅ Condições ideais para aplicação');
}
const tipoNome = {
epoxi: 'Epóxi (2 componentes)',
poliuretano: 'Poliuretano (PU)',
alquidica: 'Alquídica',
acrilica: 'Acrílica'
}[tipo];
document.getElementById('sec-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-5); border-left: 4px solid #a855f7;">
<div class="result-title">⏱️ TEMPO DE SECAGEM - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>TIPO DE TINTA:</strong> ${tipoNome}<br>
<strong>Temperatura:</strong> ${temp}°C<br>
<strong>Umidade Relativa:</strong> ${umidade}%<br>
<strong>Espessura:</strong> ${espessura} μm
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Secagem ao Toque</div>
<div class="result-value">${Math.round(tempoToque)} h</div>
</div>
<div class="result-item">
<div class="result-label">Manipulação</div>
<div class="result-value">${Math.round(tempoManipulacao)} h</div>
</div>
<div class="result-item">
<div class="result-label">Próxima Demão</div>
<div class="result-value">${Math.round(tempoProximaDemao)} h</div>
</div>
<div class="result-item">
<div class="result-label">Cura Total</div>
<div class="result-value">${Math.round(tempoCuraTotal / 24)} dias</div>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-2); border-radius: 8px;">
<strong>📊 FATORES DE CORREÇÃO APLICADOS:</strong><br>
• Fator Temperatura: ${fatorTemp.toFixed(2)}×<br>
• Fator Umidade: ${fatorUmid.toFixed(2)}×<br>
• Fator Espessura: ${fatorEsp.toFixed(2)}×<br>
• Tempo Base (${tipoNome}): ${dados.tempoBase}h
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>ALERTAS E RECOMENDAÇÕES:</strong><br>
${alertas.map(a => `${a}`).join('<br>')}
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>💡 DICAS PARA MELHORAR CONDIÇÕES:</strong><br>
${temp < 15 ? '• Aumentar temperatura do ambiente com aquecedores<br>' : ''}
${umidade > 75 ? '• Usar desumidificadores ou melhorar ventilação<br>' : ''}
• Aplicar em horários de menor umidade (meio-dia)<br>
• Evitar aplicação com orvalho ou chuva prevista<br>
• Proteger superfície de contaminação durante secagem
</div>
</div>
`;
addToHistory('Tempo Secagem', `${tipoNome}, ${Math.round(tempoProximaDemao)}h`);
}
function gerarRelatorioInspecao() {
const checks = [];
for (let i = 1; i <= 8; i++) {
const checkbox = document.getElementById(`insp-${i}`);
checks.push({
id: i,
checked: checkbox.checked,
label: checkbox.nextElementSibling.textContent
});
}
const totalChecked = checks.filter(c => c.checked).length;
const percentApproved = (totalChecked / checks.length) * 100;
let status = '';
let alertClass = '';
let recommendation = '';
if (percentApproved === 100) {
status = '✅ APROVADO';
alertClass = 'alert-success';
recommendation = 'Todos os critérios foram atendidos. Pintura aprovada para aceitação final.';
} else if (percentApproved >= 75) {
status = '⚠️ APROVADO COM RESSALVAS';
alertClass = 'alert-warning';
recommendation = 'Maioria dos critérios atendidos. Verificar itens pendentes antes da liberação final.';
} else {
status = '❌ REPROVADO';
alertClass = 'alert-error';
recommendation = 'Vários critérios não atendidos. Realizar correções antes de aprovar.';
}
const uncheckedItems = checks.filter(c => !c.checked);
document.getElementById('insp-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-1); border-left: 4px solid var(--color-primary);">
<div class="result-title">📋 RELATÓRIO DE INSPEÇÃO</div>
<div style="margin-bottom: 20px; padding: 20px; background: var(--color-surface); border-radius: 12px; text-align: center;">
<div style="font-size: 48px; margin-bottom: 10px;">${Math.round(percentApproved)}%</div>
<div style="font-size: 18px; font-weight: bold;">${totalChecked} de ${checks.length} critérios aprovados</div>
</div>
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px;">
<strong>ITENS VERIFICADOS:</strong><br><br>
${checks.map(c => `
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 8px;">
<span style="font-size: 20px;">${c.checked ? '✅' : '❌'}</span>
<span style="${c.checked ? '' : 'color: var(--color-error); font-weight: bold;'}">${c.label}</span>
</div>
`).join('')}
</div>
${uncheckedItems.length > 0 ? `
<div style="padding: 16px; background: var(--color-bg-4); border-radius: 8px; margin-bottom: 16px; border: 2px solid var(--color-error);">
<strong>⚠️ ITENS NÃO CONFORMES (${uncheckedItems.length}):</strong><br><br>
${uncheckedItems.map((item, idx) => `${idx + 1}. ${item.label}`).join('<br>')}
</div>
` : ''}
<div class="alert ${alertClass}">
<strong>STATUS: ${status}</strong><br>
${recommendation}
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-3); border-radius: 8px;">
<strong>📝 AÇÕES CORRETIVAS SUGERIDAS:</strong><br>
${uncheckedItems.length > 0 ? `
${uncheckedItems.map((item, idx) => {
let action = '';
if (item.id === 1) action = 'Realizar nova preparação com grau Sa 2½';
else if (item.id === 2) action = 'Limpar superfície com solvente adequado';
else if (item.id === 3) action = 'Aplicar demão adicional para atingir DFT especificado';
else if (item.id === 4) action = 'Melhorar técnica de aplicação ou preparação';
else if (item.id === 5) action = 'Aplicar retoque ou nova demão';
else if (item.id === 6) action = 'Aplicar nova demão nas áreas descobertas';
else if (item.id === 7) action = 'Remover defeitos e reaplicar';
else if (item.id === 8) action = 'Aguardar tempo de cura adequado';
return `${idx + 1}. ${action}`;
}).join('<br>')}
` : 'Nenhuma ação corretiva necessária ✓'}
</div>
<div style="margin-top: 20px; text-align: center;">
<strong>Data da Inspeção:</strong> ${new Date().toLocaleDateString('pt-BR')}<br>
<strong>Norma de Referência:</strong> ISO 12944
</div>
</div>
`;
addToHistory('Inspeção Pintura', `${percentApproved.toFixed(0)}% aprovado, ${status}`);
}
function getSectionName(sectionId) {
const names = {
'cev': 'CEV Avançado',
'seletor': 'Seletor de Aço',
'equivalencias': 'Equivalências',
'comparativo': 'Comparativo',
'parafusos': 'Ligações Parafusadas',
'layout': 'Layout de Furação',
'parafuso-vs-solda': 'Parafuso vs Solda',
'preaquecimento': 'Pré-Aquecimento',
'solda-filete': 'Solda Filete',
'energia-soldagem': 'Energia de Soldagem',
'consumo-eletrodos': 'Consumo de Eletrodos',
'dureza': 'Dureza',
'charpy': 'Charpy',
'certificado': 'Certificado',
'ultrassom': 'Ultrassom',
'area-pintura': 'Área de Pintura',
'consumo-tinta': 'Consumo de Tinta',
'galvanizacao': 'Galvanização',
'custo-pintura': 'Custo Pintura',
'secagem': 'Secagem',
'inspecao-pintura': 'Inspeção',
'orcamento': 'Orçamento',
'peso-rigging': 'Peso & Rigging',
'referencia': 'Referência'
};
return names[sectionId] || sectionId;
}
// ========================================
// SECTION CONTENT GENERATORS
// ========================================
function getCEVContent() {
return `
<div class="section-header">
<div class="section-title">🔬 CEV Avançado (IIW + Pcm)</div>
<div class="section-description">Cálculo do Carbono Equivalente para avaliação de soldabilidade segundo IIW e Pcm</div>
</div>
<div class="card">
<div class="card-title">Composição Química (%)</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Carbono (C)</label>
<input type="number" class="form-control" id="cev-c" step="0.01" value="0.20">
</div>
<div class="form-group">
<label class="form-label">Manganês (Mn)</label>
<input type="number" class="form-control" id="cev-mn" step="0.01" value="1.00">
</div>
<div class="form-group">
<label class="form-label">Cromo (Cr)</label>
<input type="number" class="form-control" id="cev-cr" step="0.01" value="0.10">
</div>
<div class="form-group">
<label class="form-label">Molibdênio (Mo)</label>
<input type="number" class="form-control" id="cev-mo" step="0.01" value="0.05">
</div>
<div class="form-group">
<label class="form-label">Vanádio (V)</label>
<input type="number" class="form-control" id="cev-v" step="0.01" value="0.03">
</div>
<div class="form-group">
<label class="form-label">Níquel (Ni)</label>
<input type="number" class="form-control" id="cev-ni" step="0.01" value="0.10">
</div>
<div class="form-group">
<label class="form-label">Cobre (Cu)</label>
<input type="number" class="form-control" id="cev-cu" step="0.01" value="0.10">
</div>
<div class="form-group expert-only">
<label class="form-label">Silício (Si)</label>
<input type="number" class="form-control" id="cev-si" step="0.01" value="0.25">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Espessura (mm)</label>
<input type="number" class="form-control" id="cev-thickness" step="1" value="25">
</div>
<div class="form-group expert-only">
<label class="form-label">Temperatura Ambiente (°C)</label>
<input type="number" class="form-control" id="cev-temp" step="1" value="20">
</div>
<div class="form-group expert-only">
<label class="form-label">Fórmula</label>
<select class="form-control" id="cev-formula">
<option value="iw">IIW (Padrão)</option>
<option value="pcm">Pcm (Alta resistência)</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="calcularCEV()">🔬 Calcular CEV</button>
</div>
<div id="cev-result"></div>
`;
}
function getSeletorContent() {
return `
<div class="section-header">
<div class="section-title">🎯 Seletor de Aço Inteligente</div>
<div class="section-description">Selecione o aço ideal baseado em critérios técnicos</div>
</div>
<div class="card">
<div class="card-title">Critérios de Seleção</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Aplicação</label>
<select class="form-control" id="sel-app">
<option value="edificio">Edifício</option>
<option value="ponte">Ponte</option>
<option value="offshore">Offshore</option>
<option value="industrial">Industrial</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Temperatura de Serviço (°C)</label>
<input type="number" class="form-control" id="sel-temp" value="20">
</div>
<div class="form-group">
<label class="form-label">Resistência Mínima (MPa)</label>
<input type="number" class="form-control" id="sel-fy" value="250">
</div>
<div class="form-group">
<label class="form-label">Soldabilidade</label>
<select class="form-control" id="sel-weld">
<option value="any">Qualquer</option>
<option value="excellent">Excelente</option>
<option value="good">Boa</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="selecionarAco()">🎯 Buscar Aços</button>
</div>
<div id="seletor-result"></div>
`;
}
function getEquivalenciasContent() {
return `
<div class="section-header">
<div class="section-title">📊 Equivalências Internacionais</div>
<div class="section-description">Tabela de equivalências entre normas ASTM, EN, JIS, NBR</div>
</div>
<div class="card">
<div class="card-title">Selecionar Aço</div>
<div class="form-group">
<label class="form-label">Aço de Referência</label>
<select class="form-control" id="equiv-steel" onchange="mostrarEquivalencias()">
<option value="a36">ASTM A36</option>
<option value="a572">ASTM A572 Gr.50</option>
<option value="a588">ASTM A588</option>
<option value="s235">EN S235JR</option>
<option value="s355">EN S355J2</option>
<option value="ar350">NBR AR350</option>
</select>
</div>
</div>
<div id="equiv-result"></div>
`;
}
function getComparativoContent() {
return `
<div class="section-header">
<div class="section-title">📈 Comparativo de Aços</div>
<div class="section-description">Comparação visual de propriedades mecânicas</div>
</div>
<div class="card">
<div class="card-title">Selecionar Aços para Comparação</div>
<div class="checkbox-group">
<label class="checkbox-item">
<input type="checkbox" value="a36" checked> A36
</label>
<label class="checkbox-item">
<input type="checkbox" value="a572" checked> A572
</label>
<label class="checkbox-item">
<input type="checkbox" value="a588"> A588
</label>
<label class="checkbox-item">
<input type="checkbox" value="s235"> S235
</label>
<label class="checkbox-item">
<input type="checkbox" value="s355"> S355
</label>
<label class="checkbox-item">
<input type="checkbox" value="s460"> S460
</label>
</div>
<div class="form-group">
<label class="form-label">Tipo de Visualização</label>
<select class="form-control" id="chart-type" style="max-width: 300px;">
<option value="resistance">Resistência (fy vs fu)</option>
<option value="ductility">Ductilidade</option>
<option value="table">Tabela Comparativa</option>
</select>
</div>
<button class="btn btn-primary" onclick="gerarGraficoComparativo()">📊 Gerar Comparação</button>
</div>
<div id="chart-result"></div>
`;
}
function getParafusosContent() {
return `
<div class="section-header">
<div class="section-title">🔩 Ligações Parafusadas - 5 Abas Completas</div>
<div class="section-description">Dimensionamento completo de conexões parafusadas</div>
</div>
<div class="tabs-container">
<div class="tabs-nav">
<button class="tab-btn active" onclick="switchTab(0)" data-tab="0">1⃣ Cisalhamento</button>
<button class="tab-btn" onclick="switchTab(1)" data-tab="1">2⃣ Esmagamento</button>
<button class="tab-btn" onclick="switchTab(2)" data-tab="2">3⃣ Bloco</button>
<button class="tab-btn" onclick="switchTab(3)" data-tab="3">4⃣ Layout</button>
<button class="tab-btn" onclick="switchTab(4)" data-tab="4">5⃣ vs Solda</button>
</div>
<!-- Tab 1: Cisalhamento -->
<div class="tab-content active" id="tab-0">
<div class="card" style="background: var(--color-bg-1);">
<div class="card-title">📐 Dimensionamento de Parafusos ao Cisalhamento</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Calcula a resistência ao cisalhamento de parafusos individuais e totais</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Tipo de Parafuso</label>
<select class="form-control" id="bolt-type">
<option value="a325">A325 (fy = 400 MPa)</option>
<option value="a490">A490 (fy = 565 MPa)</option>
<option value="iso88">ISO 8.8 (fy = 640 MPa)</option>
<option value="iso109">ISO 10.9 (fy = 900 MPa)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Diâmetro (mm)</label>
<select class="form-control" id="bolt-d">
<option value="12">12</option>
<option value="16">16</option>
<option value="20" selected>20</option>
<option value="24">24</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Quantidade</label>
<input type="number" class="form-control" id="bolt-qty" step="1" value="4" min="1" max="100">
</div>
<div class="form-group">
<label class="form-label">Planos de Corte</label>
<select class="form-control" id="bolt-planes">
<option value="1">1</option>
<option value="2" selected>2</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Força Aplicada (kN)</label>
<input type="number" class="form-control" id="bolt-force" step="1" value="200">
</div>
</div>
<button class="btn btn-primary" onclick="calcularCisalhamento()">🔧 Calcular Cisalhamento</button>
</div>
<div id="bolt-shear-result"></div>
</div>
<!-- Tab 2: Esmagamento -->
<div class="tab-content" id="tab-1">
<div class="card" style="background: var(--color-bg-3);">
<div class="card-title">🔨 Verificação de Esmagamento (Bearing)</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Calcula a resistência ao esmagamento da chapa</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Diâmetro Parafuso (mm)</label>
<select class="form-control" id="bear-d">
<option value="12">12</option>
<option value="16" selected>16</option>
<option value="20">20</option>
<option value="24">24</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Espessura da Chapa (mm)</label>
<input type="number" class="form-control" id="bear-thickness" step="1" value="10">
</div>
<div class="form-group">
<label class="form-label">Quantidade de Parafusos</label>
<input type="number" class="form-control" id="bear-qty" step="1" value="4">
</div>
<div class="form-group">
<label class="form-label">Tipo de Aço da Chapa</label>
<select class="form-control" id="bear-steel">
<option value="a36">A36 (fy=250, fu=400 MPa)</option>
<option value="a572" selected>A572 (fy=345, fu=450 MPa)</option>
<option value="s235">S235 (fy=235, fu=360 MPa)</option>
<option value="s355">S355 (fy=355, fu=490 MPa)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Distância de Borda (mm)</label>
<input type="number" class="form-control" id="bear-edge" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Espaçamento entre Furos (mm)</label>
<input type="number" class="form-control" id="bear-spacing" step="1" value="75">
</div>
</div>
<button class="btn btn-primary" onclick="calcularEsmagamento()">🔧 Calcular Esmagamento</button>
</div>
<div id="bolt-bearing-result"></div>
</div>
<!-- Tab 3: Ruptura Bloco -->
<div class="tab-content" id="tab-2">
<div class="card" style="background: var(--color-bg-6);">
<div class="card-title">⚠️ Ruptura em Bloco de Cisalhamento</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Verifica ruptura por bloco segundo AISC 360-16</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Diâmetro Parafuso (mm)</label>
<select class="form-control" id="block-d">
<option value="12">12</option>
<option value="16" selected>16</option>
<option value="20">20</option>
<option value="24">24</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Quantidade Horizontal</label>
<input type="number" class="form-control" id="block-h-qty" step="1" value="2">
</div>
<div class="form-group">
<label class="form-label">Quantidade Vertical</label>
<input type="number" class="form-control" id="block-v-qty" step="1" value="2">
</div>
<div class="form-group">
<label class="form-label">Espaçamento Horizontal (mm)</label>
<input type="number" class="form-control" id="block-h-space" step="1" value="75">
</div>
<div class="form-group">
<label class="form-label">Distância Borda Esquerda (mm)</label>
<input type="number" class="form-control" id="block-edge-left" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Distância Borda Topo (mm)</label>
<input type="number" class="form-control" id="block-edge-top" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Distância Borda Direita (mm)</label>
<input type="number" class="form-control" id="block-edge-right" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Espessura (mm)</label>
<input type="number" class="form-control" id="block-thickness" step="1" value="10">
</div>
<div class="form-group">
<label class="form-label">Aço</label>
<select class="form-control" id="block-steel">
<option value="a36">A36 (fu=400 MPa)</option>
<option value="a572" selected>A572 (fu=450 MPa)</option>
<option value="s235">S235 (fu=360 MPa)</option>
<option value="s355">S355 (fu=490 MPa)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Força (kN)</label>
<input type="number" class="form-control" id="block-force" step="1" value="200">
</div>
</div>
<button class="btn btn-primary" onclick="calcularBlocoRuptura()">🔧 Calcular Bloco</button>
</div>
<div id="bolt-block-result"></div>
</div>
<!-- Tab 4: Layout de Furação -->
<div class="tab-content" id="tab-3">
<div class="card" style="background: var(--color-bg-5);">
<div class="card-title">📐 Verificação de Layout de Furação</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Verifica conformidade com NBR 8800 e AISC 360</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Diâmetro Parafuso (mm)</label>
<select class="form-control" id="layout2-d">
<option value="12">12</option>
<option value="16" selected>16</option>
<option value="20">20</option>
<option value="24">24</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Borda Esquerda (mm)</label>
<input type="number" class="form-control" id="layout2-edge-left" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Borda Direita (mm)</label>
<input type="number" class="form-control" id="layout2-edge-right" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Borda Topo (mm)</label>
<input type="number" class="form-control" id="layout2-edge-top" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Borda Base (mm)</label>
<input type="number" class="form-control" id="layout2-edge-bottom" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Espaçamento Horizontal (mm)</label>
<input type="number" class="form-control" id="layout2-h-space" step="1" value="75">
</div>
<div class="form-group">
<label class="form-label">Espaçamento Vertical (mm)</label>
<input type="number" class="form-control" id="layout2-v-space" step="1" value="75">
</div>
<div class="form-group">
<label class="form-label">Espessura Chapa (mm)</label>
<input type="number" class="form-control" id="layout2-thickness" step="1" value="10">
</div>
</div>
<button class="btn btn-primary" onclick="verificarLayoutCompleto()">✓ Verificar Conformidade</button>
</div>
<div id="layout-full-result"></div>
</div>
<!-- Tab 5: Parafuso vs Solda -->
<div class="tab-content" id="tab-4">
<div class="card" style="background: var(--color-bg-4);">
<div class="card-title">⚖️ Comparação: Parafuso vs Solda</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Compara alternativas de conexão com análise de custos</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Força a Transmitir (kN)</label>
<input type="number" class="form-control" id="comp2-force" step="1" value="200">
</div>
<div class="form-group">
<label class="form-label">Comprimento Disponível (mm)</label>
<input type="number" class="form-control" id="comp2-length" step="1" value="300">
</div>
<div class="form-group">
<label class="form-label">Tipo Aço Base</label>
<select class="form-control" id="comp2-steel">
<option value="a36">A36 (fy=250 MPa)</option>
<option value="a572" selected>A572 (fy=345 MPa)</option>
<option value="s355">S355 (fy=355 MPa)</option>
</select>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 20px 0;">
<div style="padding: 16px; background: var(--color-bg-1); border-radius: 12px;">
<h4 style="margin-bottom: 12px; color: var(--color-primary);">🔩 Opção Parafuso</h4>
<div class="form-group">
<label class="form-label">Tipo</label>
<select class="form-control" id="comp2-bolt-type">
<option value="a325" selected>A325</option>
<option value="a490">A490</option>
<option value="iso88">ISO 8.8</option>
<option value="iso109">ISO 10.9</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Diâmetro (mm)</label>
<select class="form-control" id="comp2-bolt-d">
<option value="12">12</option>
<option value="16" selected>16</option>
<option value="20">20</option>
<option value="24">24</option>
</select>
</div>
</div>
<div style="padding: 16px; background: var(--color-bg-6); border-radius: 12px;">
<h4 style="margin-bottom: 12px; color: var(--color-warning);">🔥 Opção Solda</h4>
<div class="form-group">
<label class="form-label">Tipo Eletrodo</label>
<select class="form-control" id="comp2-electrode">
<option value="e6010">E6010</option>
<option value="e7018" selected>E7018</option>
<option value="e8018">E8018</option>
</select>
</div>
</div>
</div>
<button class="btn btn-primary" onclick="compararParafusoSoldaCompleto()">🔄 Gerar Comparação Completa</button>
</div>
<div id="comparison-full-result"></div>
</div>
</div>
`;
}
function getLayoutContent() {
return `
<div class="section-header">
<div class="section-title">🎯 Layout de Furação (NBR 8800)</div>
<div class="section-description">Verificação de distâncias e espaçamentos</div>
</div>
<div class="card">
<div class="card-title">Parâmetros de Layout</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Diâmetro Parafuso (mm)</label>
<input type="number" class="form-control" id="layout-d" step="1" value="20">
</div>
<div class="form-group">
<label class="form-label">Distância de Borda (mm)</label>
<input type="number" class="form-control" id="layout-edge" step="1" value="40">
</div>
<div class="form-group">
<label class="form-label">Espaçamento entre Furos (mm)</label>
<input type="number" class="form-control" id="layout-spacing" step="1" value="60">
</div>
<div class="form-group expert-only">
<label class="form-label">Espessura Chapa (mm)</label>
<input type="number" class="form-control" id="layout-thickness" step="1" value="10">
</div>
</div>
<button class="btn btn-primary" onclick="verificarLayout()">✓ Verificar Conformidade</button>
</div>
<div id="layout-result"></div>
`;
}
function getParafusoVsSoldaContent() {
return `
<div class="section-header">
<div class="section-title">⚙️ Comparação: Parafuso vs Solda</div>
<div class="section-description">Análise comparativa de soluções de ligação</div>
</div>
<div class="card">
<div class="card-title">Parâmetros da Ligação</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Força a Transmitir (kN)</label>
<input type="number" class="form-control" id="comp-force" step="1" value="150">
</div>
<div class="form-group">
<label class="form-label">Comprimento Disponível (mm)</label>
<input type="number" class="form-control" id="comp-length" step="1" value="400">
</div>
<div class="form-group">
<label class="form-label">Aço Base (fy MPa)</label>
<input type="number" class="form-control" id="comp-fy" step="1" value="345">
</div>
</div>
<button class="btn btn-primary" onclick="compararParafusoSolda()">⚙️ Comparar Soluções</button>
</div>
<div id="comparison-result"></div>
`;
}
function getPreaquecimentoContent() {
return `
<div class="section-header">
<div class="section-title">🔥 SOLDAGEM - Sistema Completo</div>
<div class="section-description">Dimensionamento completo de soldagem com 6 ferramentas integradas</div>
</div>
<!-- Seletor Global de Processo e Consumível -->
<div class="card" style="background: var(--color-bg-2); border: 2px solid var(--color-primary);">
<div class="card-title">⚙️ SELEÇÃO DE PROCESSO E CONSUMÍVEL</div>
<p style="color: var(--color-text-secondary); margin-bottom: 16px;">Selecione o processo e consumível que será usado em todas as ferramentas abaixo</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Processo de Soldagem</label>
<select class="form-control" id="weld-process" onchange="updateWeldingProcess()">
<option value="smaw" selected>SMAW (Eletrodo Revestido)</option>
<option value="gmaw">GMAW (MIG/MAG)</option>
<option value="fcaw">FCAW (Arame Tubular)</option>
<option value="gtaw">GTAW (TIG)</option>
<option value="saw">SAW (Soldagem Submersa)</option>
<option value="esw">ESW (Soldagem por Escória)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Consumível / Eletrodo</label>
<select class="form-control" id="weld-electrode" onchange="updateWeldingElectrode()">
<option value="e7018" selected>E7018 (AWS) - Básico</option>
<option value="e6013">E6013 (AWS) - Rutílico</option>
<option value="e8018">E8018 (AWS) - Básico Alta Resistência</option>
<option value="e7016">E7016 (AWS) - Básico</option>
<option value="e8016">E8016 (AWS) - Básico</option>
<option value="er70s2">ER70S-2 (MIG)</option>
<option value="er70s6">ER70S-6 (MIG)</option>
<option value="er4043">ER4043 (TIG - Al)</option>
<option value="er5356">ER5356 (TIG - Al)</option>
</select>
</div>
</div>
<button class="btn btn-success" onclick="applyToAllTabs()" style="margin-top: 16px;">✅ Atualizar Todas as Abas</button>
<button class="btn btn-secondary" onclick="showElectrodeProperties()" style="margin-top: 16px;">📋 Mostrar Propriedades do Consumível</button>
</div>
<div id="electrode-properties"></div>
<!-- 6 Abas de Soldagem -->
<div class="tabs-container">
<div class="tabs-nav">
<button class="tab-btn active" onclick="switchWeldTab(0)">🌡️ Pré-Aquecimento</button>
<button class="tab-btn" onclick="switchWeldTab(1)">⚡ Filete</button>
<button class="tab-btn" onclick="switchWeldTab(2)">🔥 Energia</button>
<button class="tab-btn" onclick="switchWeldTab(3)">📊 Consumo</button>
<button class="tab-btn" onclick="switchWeldTab(4)">🔄 Sequência</button>
<button class="tab-btn" onclick="switchWeldTab(5)">📋 Padrões</button>
</div>
<!-- ABA 1: Pré-Aquecimento -->
<div class="tab-content active" id="weld-tab-0">
<div class="card" style="background: var(--color-bg-1);">
<div class="card-title">🌡️ Pré-Aquecimento AWS D1.1</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Calcula temperatura mínima de pré-aquecimento</p>
<div style="padding: 12px; background: var(--color-surface); border-radius: 8px; margin-bottom: 20px;">
<strong>Processo Selecionado:</strong> <span id="preheat-process-display">SMAW (E7018)</span>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Carbono Equivalente (CEV)</label>
<input type="number" class="form-control" id="preheat-cev" step="0.01" value="0.45">
<small style="color: var(--color-text-secondary);">Ou calcule na seção Materiais</small>
</div>
<div class="form-group">
<label class="form-label">Espessura da Junta (mm)</label>
<input type="number" class="form-control" id="preheat-thickness" step="1" value="25">
</div>
<div class="form-group">
<label class="form-label">Temperatura Ambiente (°C)</label>
<input type="number" class="form-control" id="preheat-ambient" step="1" value="15">
</div>
<div class="form-group">
<label class="form-label">Tipo de Junta</label>
<select class="form-control" id="preheat-joint">
<option value="filete">Filete</option>
<option value="topo">Topo</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Restrição da Junta</label>
<select class="form-control" id="preheat-restraint">
<option value="1.0">Não Restrita</option>
<option value="1.1">Parcialmente Restrita</option>
<option value="1.2" selected>Totalmente Restrita</option>
</select>
</div>
</div>
<div style="margin: 20px 0;">
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
<input type="checkbox" id="preheat-interpass" style="width: 18px; height: 18px;">
<span>Calcular Temperatura Interpass (entre passes)</span>
</label>
</div>
<button class="btn btn-primary" onclick="calcularPreaquecimentoCompleto()">🔥 Calcular Pré-Aquecimento</button>
</div>
<div id="preheat-result"></div>
</div>
<!-- ABA 2: Dimensionamento de Filete -->
<div class="tab-content" id="weld-tab-1">
<div class="card" style="background: var(--color-bg-3);">
<div class="card-title">⚡ Dimensionamento de Soldas de Filete</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Calcula perna necessária e número de passes</p>
<div style="padding: 12px; background: var(--color-surface); border-radius: 8px; margin-bottom: 20px;">
<strong>Processo:</strong> <span id="filete-process-display">SMAW (E7018)</span>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Força a Transmitir (kN)</label>
<input type="number" class="form-control" id="filete-force" step="1" value="250">
</div>
<div class="form-group">
<label class="form-label">Comprimento Disponível (mm)</label>
<input type="number" class="form-control" id="filete-length" step="1" value="400">
</div>
<div class="form-group">
<label class="form-label">Tipo de Junta</label>
<select class="form-control" id="filete-joint">
<option value="1">Filete Simples</option>
<option value="2" selected>Filete Duplo</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Tipo de Aço Base</label>
<select class="form-control" id="filete-steel">
<option value="250">A36 (250 MPa)</option>
<option value="345" selected>A572 (345 MPa)</option>
<option value="235">S235 (235 MPa)</option>
<option value="355">S355 (355 MPa)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Posição Soldagem</label>
<select class="form-control" id="filete-position">
<option value="1.0" selected>Plana (1F)</option>
<option value="0.9">Horizontal (2F)</option>
<option value="0.8">Vertical (3F)</option>
<option value="0.7">Sobrecabeça (4F)</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="calcularFileteCompleto()">⚡ Calcular Filete</button>
</div>
<div id="filete-result"></div>
</div>
<!-- ABA 3: Energia de Soldagem -->
<div class="tab-content" id="weld-tab-2">
<div class="card" style="background: var(--color-bg-6);">
<div class="card-title">🔥 Energia de Soldagem (Heat Input)</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Controla aporte de calor para evitar fragilização</p>
<div style="padding: 12px; background: var(--color-surface); border-radius: 8px; margin-bottom: 20px;">
<strong>Processo:</strong> <span id="hi-process-display">SMAW (E7018)</span>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Voltagem (V)</label>
<input type="number" class="form-control" id="hi-voltage" step="1" value="26">
</div>
<div class="form-group">
<label class="form-label">Corrente (A)</label>
<input type="number" class="form-control" id="hi-current" step="1" value="140">
</div>
<div class="form-group">
<label class="form-label">Velocidade Soldagem (cm/min)</label>
<input type="number" class="form-control" id="hi-speed" step="1" value="25">
</div>
<div class="form-group">
<label class="form-label">Eficiência de Arco</label>
<input type="number" class="form-control" id="hi-efficiency" step="0.01" value="0.75">
</div>
<div class="form-group">
<label class="form-label">Tipo de Aço (para análise)</label>
<select class="form-control" id="hi-steel">
<option value="a36">A36 (1.5-3.0 kJ/mm)</option>
<option value="a572" selected>A572 (1.0-2.5 kJ/mm)</option>
<option value="s355">S355 (0.8-2.0 kJ/mm)</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="calcularEnergiaCompleta()">🔥 Calcular Energia</button>
<button class="btn btn-secondary" onclick="verificarLimitesAco()" style="margin-left: 10px;">📊 Verificar Limites por Aço</button>
</div>
<div id="hi-result"></div>
</div>
<!-- ABA 4: Consumo de Eletrodos -->
<div class="tab-content" id="weld-tab-3">
<div class="card" style="background: var(--color-bg-5);">
<div class="card-title">📊 Consumo de Eletrodos e Consumíveis</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Calcula quantidade e custo de eletrodos necessários</p>
<div style="padding: 12px; background: var(--color-surface); border-radius: 8px; margin-bottom: 20px;">
<strong>Eletrodo:</strong> <span id="consumo-electrode-display">E7018</span>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Perna da Solda (mm)</label>
<input type="number" class="form-control" id="consumo-leg" step="1" value="6">
</div>
<div class="form-group">
<label class="form-label">Comprimento Total (m)</label>
<input type="number" class="form-control" id="consumo-length" step="0.1" value="10">
</div>
<div class="form-group">
<label class="form-label">Perdas/Respingos (%)</label>
<input type="number" class="form-control" id="consumo-loss" step="1" value="15">
</div>
<div class="form-group">
<label class="form-label">Porcentagem de Sucata (%)</label>
<input type="number" class="form-control" id="consumo-scrap" step="1" value="5">
</div>
</div>
<button class="btn btn-primary" onclick="calcularConsumoCompleto()">📊 Calcular Consumo</button>
<button class="btn btn-secondary" onclick="gerarOrcamentoConsumiveis()" style="margin-left: 10px;">💰 Gerar Orçamento</button>
</div>
<div id="consumo-result"></div>
</div>
<!-- ABA 5: Sequência de Soldagem -->
<div class="tab-content" id="weld-tab-4">
<div class="card" style="background: var(--color-bg-7);">
<div class="card-title">🔄 Sequência de Soldagem para Minimizar Distorções</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Padrões de deposição e passes</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Tipo de Junta</label>
<select class="form-control" id="seq-joint">
<option value="filete" selected>Filete Duplo</option>
<option value="topo">Topo</option>
<option value="angular">Angular</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Comprimento Total (mm)</label>
<input type="number" class="form-control" id="seq-length" step="1" value="400">
</div>
<div class="form-group">
<label class="form-label">Perna (mm)</label>
<input type="number" class="form-control" id="seq-leg" step="1" value="3">
</div>
<div class="form-group">
<label class="form-label">Número de Passes</label>
<input type="number" class="form-control" id="seq-passes" step="1" value="2">
</div>
<div class="form-group">
<label class="form-label">Padrão de Deposição</label>
<select class="form-control" id="seq-pattern">
<option value="skip" selected>Skip Welding (Recomendado)</option>
<option value="backstep">Backstep Welding</option>
<option value="pulsed">Pulsado</option>
<option value="continuous">Contínuo</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="gerarDiagramaSequencia()">📐 Gerar Diagrama de Sequência</button>
<button class="btn btn-secondary" onclick="visualizarDistorcoes()" style="margin-left: 10px;">📊 Visualizar Distorções Esperadas</button>
</div>
<div id="sequencia-result"></div>
</div>
<!-- ABA 6: Padrões de Solda -->
<div class="tab-content" id="weld-tab-5">
<div class="card" style="background: var(--color-bg-8);">
<div class="card-title">📋 Padrões de Solda Recomendados por Aplicação</div>
<p style="color: var(--color-text-secondary); margin-bottom: 20px;">Seleção de padrão otimizado para sua aplicação</p>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Aplicação / Estrutura</label>
<select class="form-control" id="padrao-app">
<option value="edificio" selected>Edifício de Múltiplos Andares</option>
<option value="ponte">Ponte Rodoviária</option>
<option value="industrial">Estrutura Industrial</option>
<option value="tubulacao">Tubulação de Pressão</option>
<option value="equipamento">Equipamento Mecânico</option>
<option value="offshore">Marinha/Offshore</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Criticidade</label>
<select class="form-control" id="padrao-criticality">
<option value="baixa">Baixa (Cargas Estáticas)</option>
<option value="media" selected>Média (Fadiga Baixa)</option>
<option value="alta">Alta (Fadiga/Impacto)</option>
<option value="critica">Crítica (Pressão/Temperatura)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Ambiente Serviço</label>
<select class="form-control" id="padrao-env">
<option value="interno">Interno Seco</option>
<option value="externo" selected>Externo Temperado</option>
<option value="agressivo">Externo Agressivo / Marinho</option>
<option value="baixatemp">Baixas Temperaturas (-20°C)</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="buscarPadraoIdeal()">🔍 Buscar Padrão Ideal</button>
</div>
<div id="padrao-result"></div>
</div>
</div>
`;
}
function getSoldaFileteContent() {
return `
<div class="section-header">
<div class="section-title">⚡ Dimensionamento de Solda de Filete</div>
<div class="section-description">Cálculo da perna necessária segundo NBR 8800</div>
</div>
<div class="card">
<div class="card-title">Dados da Solda</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Força (kN)</label>
<input type="number" class="form-control" id="weld-force" step="1" value="100">
</div>
<div class="form-group">
<label class="form-label">Comprimento Total (mm)</label>
<input type="number" class="form-control" id="weld-length" step="1" value="500">
</div>
<div class="form-group">
<label class="form-label">Aço Base (fy MPa)</label>
<input type="number" class="form-control" id="weld-fy" step="1" value="345">
</div>
<div class="form-group expert-only">
<label class="form-label">Posição de Soldagem</label>
<select class="form-control" id="weld-position">
<option value="1.0">Plana</option>
<option value="0.9">Horizontal</option>
<option value="0.85">Vertical</option>
<option value="0.8">Sobrecabeça</option>
</select>
</div>
</div>
<button class="btn btn-primary" onclick="calcularSoldaFilete()">⚡ Dimensionar Solda</button>
</div>
<div id="weld-result"></div>
`;
}
function getEnergiaSoldagemContent() {
return `
<div class="section-header">
<div class="section-title">🔥 Energia de Soldagem (Heat Input)</div>
<div class="section-description">Controle de energia para evitar fragilização da ZTA</div>
</div>
<div class="card">
<div class="card-title">Parâmetros de Soldagem</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Voltagem (V)</label>
<input type="number" class="form-control" id="hi-voltage" step="1" value="25">
</div>
<div class="form-group">
<label class="form-label">Corrente (A)</label>
<input type="number" class="form-control" id="hi-current" step="1" value="150">
</div>
<div class="form-group">
<label class="form-label">Velocidade (cm/min)</label>
<input type="number" class="form-control" id="hi-speed" step="1" value="20">
</div>
<div class="form-group expert-only">
<label class="form-label">Eficiência (%)</label>
<input type="number" class="form-control" id="hi-efficiency" step="1" value="85">
</div>
</div>
<button class="btn btn-primary" onclick="calcularEnergiaS oldagem()">🔥 Calcular Energia</button>
</div>
<div id="hi-result"></div>
`;
}
function getConsumoEletrodosContent() {
return `
<div class="section-header">
<div class="section-title">📊 Consumo de Eletrodos</div>
<div class="section-description">Estimativa de consumo com perdas</div>
</div>
<div class="card">
<div class="card-title">Dados da Solda</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Perna da Solda (mm)</label>
<input type="number" class="form-control" id="elec-leg" step="1" value="6">
</div>
<div class="form-group">
<label class="form-label">Comprimento Total (m)</label>
<input type="number" class="form-control" id="elec-length" step="0.1" value="10">
</div>
<div class="form-group">
<label class="form-label">Tipo de Eletrodo</label>
<select class="form-control" id="elec-type">
<option value="1.15">E6010</option>
<option value="1.10" selected>E7018</option>
<option value="1.12">E8018</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Perdas (%)</label>
<input type="number" class="form-control" id="elec-loss" step="1" value="15">
</div>
</div>
<button class="btn btn-primary" onclick="calcularConsumoEletrodos()">📊 Calcular Consumo</button>
</div>
<div id="elec-result"></div>
`;
}
function getDurezaContent() {
return `
<div class="section-header">
<div class="section-title">🔨 Conversor de Dureza</div>
<div class="section-description">Conversão entre escalas HB, HRC, HV</div>
</div>
<div class="card">
<div class="card-title">Digite em Qualquer Campo</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Brinell (HB)</label>
<input type="number" class="form-control" id="hard-hb" step="1" value="200" oninput="converterDureza('hb')">
</div>
<div class="form-group">
<label class="form-label">Rockwell C (HRC)</label>
<input type="number" class="form-control" id="hard-hrc" step="0.1" oninput="converterDureza('hrc')">
</div>
<div class="form-group">
<label class="form-label">Vickers (HV)</label>
<input type="number" class="form-control" id="hard-hv" step="1" oninput="converterDureza('hv')">
</div>
</div>
</div>
<div id="hardness-result"></div>
`;
}
function getCharpyContent() {
return `
<div class="section-header">
<div class="section-title">📉 Análise de Charpy</div>
<div class="section-description">Curva de transição dúctil-frágil</div>
</div>
<div class="card">
<div class="card-title">Insira até 4 Pares Temperatura/Energia</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Temp 1 (°C)</label>
<input type="number" class="form-control" id="charpy-t1" step="1" value="20">
</div>
<div class="form-group">
<label class="form-label">Energia 1 (J)</label>
<input type="number" class="form-control" id="charpy-e1" step="1" value="80">
</div>
<div class="form-group">
<label class="form-label">Temp 2 (°C)</label>
<input type="number" class="form-control" id="charpy-t2" step="1" value="0">
</div>
<div class="form-group">
<label class="form-label">Energia 2 (J)</label>
<input type="number" class="form-control" id="charpy-e2" step="1" value="50">
</div>
<div class="form-group">
<label class="form-label">Temp 3 (°C)</label>
<input type="number" class="form-control" id="charpy-t3" step="1" value="-20">
</div>
<div class="form-group">
<label class="form-label">Energia 3 (J)</label>
<input type="number" class="form-control" id="charpy-e3" step="1" value="30">
</div>
<div class="form-group">
<label class="form-label">Temp 4 (°C)</label>
<input type="number" class="form-control" id="charpy-t4" step="1" value="-40">
</div>
<div class="form-group">
<label class="form-label">Energia 4 (J)</label>
<input type="number" class="form-control" id="charpy-e4" step="1" value="15">
</div>
</div>
<button class="btn btn-primary" onclick="analisarCharpy()">📉 Gerar Curva</button>
</div>
<div id="charpy-result"></div>
`;
}
function getUltrassomContent() {
return `
<div class="section-header">
<div class="section-title">🏥 Interpretação de Ultrassom</div>
<div class="section-description">Classificação de descontinuidades segundo AWS/ASME</div>
</div>
<div class="card">
<div class="card-title">Parâmetros da Descontinuidade</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Norma de Avaliação</label>
<select class="form-control" id="ut-norm">
<option value="aws">AWS D1.1</option>
<option value="asme">ASME Section VIII Div 1</option>
<option value="dnv">DNV-GL</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Tipo de Descontinuidade</label>
<select class="form-control" id="ut-type" onchange="updateUtFields()">
<option value="porosidade">Porosidade</option>
<option value="inclusao">Inclusão de Escória</option>
<option value="falta-fusao">Falta de Fusão</option>
<option value="falta-penetracao">Falta de Penetração</option>
<option value="trinca">Trinca</option>
<option value="mordedura">Mordedura</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Localização</label>
<select class="form-control" id="ut-location">
<option value="raiz">Raiz</option>
<option value="passes">Passes Intermediários</option>
<option value="enchimento">Enchimento</option>
<option value="acabamento">Acabamento</option>
</select>
</div>
<div class="form-group" id="ut-diameter-group">
<label class="form-label">Diâmetro (mm)</label>
<input type="number" class="form-control" id="ut-diameter" step="0.1" value="2.5">
</div>
<div class="form-group" id="ut-qty-group">
<label class="form-label">Quantidade</label>
<input type="number" class="form-control" id="ut-qty" step="1" value="3">
</div>
<div class="form-group" id="ut-length-group">
<label class="form-label">Comprimento Total (mm)</label>
<input type="number" class="form-control" id="ut-length" step="0.1" value="25">
</div>
<div class="form-group">
<label class="form-label">Profundidade (mm)</label>
<input type="number" class="form-control" id="ut-depth" step="0.1" value="1.2">
</div>
<div class="form-group">
<label class="form-label">Espessura da Chapa (mm)</label>
<input type="number" class="form-control" id="ut-thickness" step="1" value="10">
</div>
</div>
<button class="btn btn-primary" onclick="analisarUltrassom()">🔍 Analisar Conforme Norma</button>
</div>
<div id="ut-result"></div>
`;
}
function getCertificadoContent() {
return `
<div class="section-header">
<div class="section-title">📋 Checklist de Certificado</div>
<div class="section-description">Verificação de conformidade com normas</div>
</div>
<div class="card">
<div class="card-title">Selecionar Norma</div>
<div class="form-group">
<label class="form-label">Norma de Referência</label>
<select class="form-control" id="cert-norm" onchange="gerarChecklistCertificado()">
<option value="astm_a36">ASTM A36</option>
<option value="astm_a572">ASTM A572 Gr.50</option>
<option value="en_s235">EN S235JR</option>
<option value="en_s355">EN S355J2</option>
<option value="nbr_ar350">NBR AR350</option>
</select>
</div>
</div>
<div id="cert-result"></div>
`;
}
function getAreaPinturaContent() {
return `
<div class="section-header">
<div class="section-title">📐 Cálculo de Área de Pintura</div>
<div class="section-description">Área total de superfície a pintar</div>
</div>
<div class="card">
<div class="card-title">Tipo de Produto</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Tipo</label>
<select class="form-control" id="paint-type" onchange="updatePaintFields()">
<option value="chapa">Chapa</option>
<option value="perfilW">Perfil W</option>
<option value="tubo">Tubo Circular</option>
<option value="rhs">Tubo Retangular (RHS)</option>
</select>
</div>
<div class="form-group" id="paint-field1">
<label class="form-label" id="paint-label1">Comprimento (mm)</label>
<input type="number" class="form-control" id="paint-dim1" step="1" value="6000">
</div>
<div class="form-group" id="paint-field2">
<label class="form-label" id="paint-label2">Largura (mm)</label>
<input type="number" class="form-control" id="paint-dim2" step="1" value="1000">
</div>
<div class="form-group" id="paint-field3" style="display:none;">
<label class="form-label" id="paint-label3">Altura (mm)</label>
<input type="number" class="form-control" id="paint-dim3" step="1" value="300">
</div>
<div class="form-group">
<label class="form-label">Quantidade</label>
<input type="number" class="form-control" id="paint-qty" step="1" value="1">
</div>
</div>
<button class="btn btn-primary" onclick="calcularAreaPintura()">📐 Calcular Área</button>
</div>
<div id="paint-area-result"></div>
`;
}
function getConsumoTintaContent() {
return `
<div class="section-header">
<div class="section-title">🎯 Consumo de Tinta</div>
<div class="section-description">Cálculo de volume e custo</div>
</div>
<div class="card">
<div class="card-title">Parâmetros de Pintura</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Área Total (m²)</label>
<input type="number" class="form-control" id="tinta-area" step="0.1" value="50">
</div>
<div class="form-group">
<label class="form-label">DFT Desejado (μm)</label>
<input type="number" class="form-control" id="tinta-dft" step="1" value="160">
</div>
<div class="form-group">
<label class="form-label">% Sólidos</label>
<input type="number" class="form-control" id="tinta-solids" step="1" value="65">
</div>
<div class="form-group">
<label class="form-label">% Perdas</label>
<input type="number" class="form-control" id="tinta-loss" step="1" value="25">
</div>
<div class="form-group">
<label class="form-label">Número de Demãos</label>
<input type="number" class="form-control" id="tinta-coats" step="1" value="2">
</div>
<div class="form-group">
<label class="form-label">Custo/Litro (R$)</label>
<input type="number" class="form-control" id="tinta-cost" step="0.01" value="80.00">
</div>
</div>
<button class="btn btn-primary" onclick="calcularConsumoTinta()">🎯 Calcular Consumo</button>
</div>
<div id="tinta-result"></div>
`;
}
function getCustoPinturaContent() {
return `
<div class="section-header">
<div class="section-title">💰 Custo Total de Pintura</div>
<div class="section-description">Análise completa de custos com mão de obra e materiais</div>
</div>
<div class="card">
<div class="card-title">Parâmetros de Custos</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Área Total (m²)</label>
<input type="number" class="form-control" id="custo-area" step="0.1" value="50">
</div>
<div class="form-group">
<label class="form-label">Região do Brasil</label>
<select class="form-control" id="custo-regiao">
<option value="sudeste">Sudeste (SP/RJ/MG)</option>
<option value="sul">Sul (RS/SC/PR)</option>
<option value="nordeste">Nordeste (CE/PE/BA)</option>
<option value="centrooeste">Centro-Oeste (DF/GO/MS)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Tipo de Tinta</label>
<select class="form-control" id="custo-tipo-tinta">
<option value="padrao">Padrão Industrial</option>
<option value="premium">Premium (Maior Durabilidade)</option>
<option value="economica">Econômica (Budget)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Custo Mão de Obra (R$/hora)</label>
<input type="number" class="form-control" id="custo-mo" step="1" value="85">
</div>
<div class="form-group">
<label class="form-label">Produtividade (m²/hora)</label>
<input type="number" class="form-control" id="custo-prod" step="0.1" value="5">
</div>
<div class="form-group">
<label class="form-label">Volume de Tinta (L)</label>
<input type="number" class="form-control" id="custo-volume" step="0.1" value="100">
</div>
</div>
<div style="margin: 20px 0;">
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer;">
<input type="checkbox" id="custo-incluir-epi" checked style="width: 18px; height: 18px;">
<span>Incluir EPI e Materiais Consumíveis</span>
</label>
<label style="display: flex; align-items: center; gap: 8px; cursor: pointer; margin-top: 8px;">
<input type="checkbox" id="custo-incluir-equip" style="width: 18px; height: 18px;">
<span>Incluir Aluguel de Equipamentos</span>
</label>
</div>
<button class="btn btn-primary" onclick="calcularCustoTotal()">💵 Calcular Custo Final</button>
</div>
<div id="custo-result"></div>
`;
}
function getSecagemContent() {
return `
<div class="section-header">
<div class="section-title">⏱️ Tempo de Secagem</div>
<div class="section-description">Estimativa de tempo com análise de condições ambientais</div>
</div>
<div class="card">
<div class="card-title">Condições de Aplicação</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Tipo de Tinta</label>
<select class="form-control" id="sec-tipo">
<option value="epoxi">Epóxi</option>
<option value="poliuretano">Poliuretano (PU)</option>
<option value="alquidica">Alquídica</option>
<option value="acrilica">Acrílica</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Temperatura (°C)</label>
<input type="number" class="form-control" id="sec-temp" step="1" value="25">
</div>
<div class="form-group">
<label class="form-label">Umidade Relativa (%)</label>
<input type="number" class="form-control" id="sec-umidade" step="1" value="60">
</div>
<div class="form-group">
<label class="form-label">Espessura Aplicada (μm)</label>
<input type="number" class="form-control" id="sec-espessura" step="10" value="80">
</div>
</div>
<button class="btn btn-primary" onclick="calcularSecagem()">⏱️ Calcular Tempo</button>
</div>
<div id="sec-result"></div>
`;
}
function getInspecaoPinturaContent() {
return `
<div class="section-header">
<div class="section-title">✔️ Inspeção de Qualidade de Pintura</div>
<div class="section-description">Checklist profissional conforme ISO 12944</div>
</div>
<div class="card">
<div class="card-title">Checklist de Inspeção</div>
<div style="display: flex; flex-direction: column; gap: 12px; margin: 20px 0;">
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-1" style="width: 20px; height: 20px;">
<span><strong>Preparação de Superfície (ISO 8501):</strong> Grau de limpeza adequado (Sa 2½ mínimo)</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-2" style="width: 20px; height: 20px;">
<span><strong>Limpeza:</strong> Superfície livre de pó, óleo, ferrugem e contaminantes</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-3" style="width: 20px; height: 20px;">
<span><strong>Medição DFT:</strong> Espessura de película seca conforme especificação</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-4" style="width: 20px; height: 20px;">
<span><strong>Teste de Aderência (ISO 2409):</strong> Cross-cut test aprovado</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-5" style="width: 20px; height: 20px;">
<span><strong>Aspecto Visual:</strong> Cor, brilho e textura uniformes</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-6" style="width: 20px; height: 20px;">
<span><strong>Uniformidade de Cobertura:</strong> Sem áreas descobertas ou falhas</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-7" style="width: 20px; height: 20px;">
<span><strong>Ausência de Defeitos:</strong> Sem bolhas, rachaduras, escorrimentos ou crateras</span>
</label>
<label style="display: flex; align-items: center; gap: 12px; padding: 12px; background: var(--color-background); border-radius: 8px; cursor: pointer;">
<input type="checkbox" id="insp-8" style="width: 20px; height: 20px;">
<span><strong>Tempo de Cura:</strong> Intervalo entre demãos e cura final adequados</span>
</label>
</div>
<button class="btn btn-primary" onclick="gerarRelatorioInspecao()">📋 Gerar Relatório</button>
</div>
<div id="insp-result"></div>
`;
}
function getGalvanizacaoContent() {
return `
<div class="section-header">
<div class="section-title">🛡️ Galvanização a Quente</div>
<div class="section-description">Espessura mínima e vida útil</div>
</div>
<div class="card">
<div class="card-title">Parâmetros de Galvanização</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Ambiente</label>
<select class="form-control" id="galv-env">
<option value="interno">Interno (C1)</option>
<option value="urbano">Urbano (C2/C3)</option>
<option value="marinho" selected>Marinho (C4/C5)</option>
<option value="industrial">Industrial (C4)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Área a Galvanizar (m²)</label>
<input type="number" class="form-control" id="galv-area" step="0.1" value="100">
</div>
<div class="form-group">
<label class="form-label">Espessura Desejada (μm)</label>
<input type="number" class="form-control" id="galv-thickness" step="1" value="85">
</div>
<div class="form-group expert-only">
<label class="form-label">Vida Útil Desejada (anos)</label>
<input type="number" class="form-control" id="galv-life" step="1" value="20">
</div>
</div>
<button class="btn btn-primary" onclick="calcularGalvanizacao()">🛡️ Calcular</button>
</div>
<div id="galv-result"></div>
`;
}
function getOrcamentoContent() {
return `
<div class="section-header">
<div class="section-title">💵 Orçamento Detalhado v6.5</div>
<div class="section-description">Gerenciador completo com base de dados integrada de materiais</div>
</div>
<div style="padding: 20px; background: var(--color-bg-8); border-radius: 12px; border: 2px solid var(--color-primary); margin-bottom: 20px;">
<h3 style="margin-bottom: 12px; color: var(--color-primary);">🎉 NOVIDADE v6.5: Base de Dados Completa de Materiais!</h3>
<p style="margin-bottom: 12px;">Agora você pode selecionar materiais de um banco de dados com <strong>100+ produtos do mercado brasileiro</strong> (Gerdau, Usiminas):</p>
<ul style="margin-left: 20px; margin-bottom: 12px;">
<li>✅ Perfis W, I (IPE), HP - Pesos automáticos</li>
<li>✅ Cantoneiras, Tubos Circulares e RHS</li>
<li>✅ Chapas, Barras, Eletrodos, Tintas, Parafusos</li>
<li>✅ Preços regionais (Sudeste, Sul, Nordeste, Centro-Oeste)</li>
<li>✅ Cálculo automático de preço unitário baseado em peso e região</li>
</ul>
<button class="btn btn-primary" onclick="carregarOrcamentoExemplo()" style="margin-right: 10px;">📦 Carregar Orçamento Exemplo</button>
<button class="btn btn-secondary" onclick="alert('📖 TUTORIAL:\n\n1. Selecione a Região (preços ajustam automaticamente)\n2. Escolha Categoria: Material, Serviço, Consumível ou Indireto\n3. Selecione Tipo de Produto (ex: Perfil W)\n4. Escolha Especificação da lista (ex: W250×38)\n5. Preço e peso preenchem automaticamente!\n6. Digite quantidade e adicione\n\nSimples assim! 🚀')">📖 Como Usar</button>
</div>
<div class="card" style="background: var(--color-bg-1); border: 2px solid var(--color-primary);">
<div class="card-title">🌍 Configuração Regional</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Região do Brasil</label>
<select class="form-control" id="budget-region" onchange="updateRegionalPricing()">
<option value="sudeste" selected>Sudeste (SP/RJ/MG)</option>
<option value="sul">Sul (RS/SC/PR)</option>
<option value="nordeste">Nordeste (CE/PE/BA)</option>
<option value="centrooeste">Centro-Oeste (DF/GO/MS)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Data do Orçamento</label>
<input type="date" class="form-control" id="budget-date" value="2025-11-07">
</div>
<div class="form-group">
<label class="form-label">Nome do Projeto</label>
<input type="text" class="form-control" id="budget-project" placeholder="Ex: Estrutura Galpão Industrial">
</div>
</div>
</div>
<div class="card">
<div class="card-title">✎ Adicionar Item ao Orçamento</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Categoria</label>
<select class="form-control" id="budget-category" onchange="updateBudgetTypeOptions()">
<option value="material">Material</option>
<option value="servico">Serviço</option>
<option value="consumivel">Consumível</option>
<option value="indireto">Indireto</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Tipo de Produto</label>
<select class="form-control" id="budget-type" onchange="updateBudgetSpecOptions()">
<option value="perfil_w">Perfil W</option>
<option value="perfil_i">Perfil I (IPE)</option>
<option value="perfil_hp">Perfil HP</option>
<option value="cantoneira">Cantoneira</option>
<option value="tubo_circ">Tubo Circular</option>
<option value="tubo_rhs">Tubo Retangular (RHS)</option>
<option value="chapa">Chapa</option>
<option value="barra">Barra Redonda</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Especificação (Produto)</label>
<select class="form-control" id="budget-spec" onchange="autoFillBudgetData()">
<option value="">Selecione...</option>
</select>
</div>
</div>
<div style="padding: 16px; background: var(--color-surface); border-radius: 8px; margin: 16px 0; display: none;" id="product-info-display">
<strong>📋 Informações do Produto:</strong><br>
<span id="product-details"></span>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Quantidade</label>
<input type="number" class="form-control" id="budget-qty" step="0.01" value="1" oninput="updateBudgetTotal()">
</div>
<div class="form-group">
<label class="form-label">Unidade</label>
<input type="text" class="form-control" id="budget-unit" value="m" readonly style="background: var(--color-secondary);">
</div>
<div class="form-group">
<label class="form-label">Preço Unitário (R$)</label>
<input type="number" class="form-control" id="budget-price" step="0.01" value="0" readonly style="background: var(--color-bg-3); font-weight: bold;">
</div>
<div class="form-group">
<label class="form-label">Total (R$)</label>
<input type="text" class="form-control" id="budget-item-total" value="R$ 0.00" readonly style="background: var(--color-bg-1); font-weight: bold; font-size: 16px;">
</div>
</div>
<button class="btn btn-success" onclick="adicionarItemOrcamentoV2()" style="width: 100%; padding: 16px; font-size: 16px;"> Adicionar ao Orçamento</button>
</div>
<div class="card">
<div class="card-title">📋 Itens do Orçamento</div>
<div class="table-container">
<table id="budget-table" style="font-size: 13px;">
<thead>
<tr style="background: var(--color-primary); color: var(--color-btn-primary-text);">
<th style="padding: 12px;">#</th>
<th>Categoria</th>
<th>Especificação</th>
<th>Qtd</th>
<th>Un</th>
<th>Preço Unit.</th>
<th>Valor Total</th>
<th>Ações</th>
</tr>
</thead>
<tbody id="budget-tbody">
<tr>
<td colspan="8" style="text-align: center; color: var(--color-text-secondary); padding: 24px;">Nenhum item adicionado</td>
</tr>
</tbody>
</table>
</div>
<div class="form-group" style="margin-top: 20px; max-width: 300px;">
<label class="form-label">BDI / Margem (%)</label>
<input type="number" class="form-control" id="budget-bdi" step="0.1" value="25" onchange="atualizarTotalOrcamentoV2()" style="font-size: 16px; font-weight: bold;">
</div>
<div id="budget-total"></div>
</div>
`;
}
function getPesoRiggingContent() {
return `
<div class="section-header">
<div class="section-title">⚖️ Peso &amp; Plano de Rigging</div>
<div class="section-description">Cálculo de peso e dimensionamento de içamento</div>
</div>
<div class="card">
<div class="card-title">Cálculo de Peso</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Tipo</label>
<select class="form-control" id="weight-type" onchange="updateWeightFields()">
<option value="perfilW">Perfil W</option>
<option value="chapa">Chapa</option>
<option value="tubo">Tubo Circular</option>
<option value="barra">Barra Redonda</option>
</select>
</div>
<div class="form-group" id="weight-field1">
<label class="form-label" id="weight-label1">Altura (mm)</label>
<input type="number" class="form-control" id="weight-dim1" step="1" value="300">
</div>
<div class="form-group" id="weight-field2">
<label class="form-label" id="weight-label2">Comprimento (m)</label>
<input type="number" class="form-control" id="weight-dim2" step="0.1" value="6">
</div>
<div class="form-group" id="weight-field3" style="display:none;">
<label class="form-label" id="weight-label3">Largura (mm)</label>
<input type="number" class="form-control" id="weight-dim3" step="1" value="1000">
</div>
<div class="form-group" id="weight-field4" style="display:none;">
<label class="form-label" id="weight-label4">Espessura (mm)</label>
<input type="number" class="form-control" id="weight-dim4" step="0.1" value="10">
</div>
</div>
<button class="btn btn-primary" onclick="calcularPeso()">⚖️ Calcular Peso</button>
</div>
<div id="weight-result"></div>
<div class="card">
<div class="card-title">Dimensionamento de Rigging</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Peso Total (kg)</label>
<input type="number" class="form-control" id="rigging-weight" step="1" value="1000">
</div>
<div class="form-group">
<label class="form-label">Pontos de Içamento</label>
<select class="form-control" id="rigging-points">
<option value="2" selected>2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Ângulo</label>
<select class="form-control" id="rigging-angle">
<option value="90">90°</option>
<option value="75">75°</option>
<option value="60" selected>60°</option>
<option value="45">45°</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Fator de Segurança</label>
<input type="number" class="form-control" id="rigging-fs" step="0.1" value="4">
</div>
</div>
<button class="btn btn-primary" onclick="calcularRigging()">🏗️ Calcular Rigging</button>
</div>
<div id="rigging-result"></div>
`;
}
function getReferenciaContent() {
return `
<div class="section-header">
<div class="section-title">📖 Referência Técnica</div>
<div class="section-description">Banco de dados completo de aços e sistemas</div>
</div>
<div class="card">
<div class="card-title">Aços Estruturais</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Designação</th>
<th>fy (MPa)</th>
<th>fu (MPa)</th>
<th>Along. (%)</th>
<th>CEV</th>
<th>Soldabilidade</th>
<th>Aplicação</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>ASTM A36</strong></td>
<td>250</td>
<td>400</td>
<td>20</td>
<td>0.41</td>
<td>⭐⭐⭐⭐⭐</td>
<td>Estruturas gerais</td>
</tr>
<tr>
<td><strong>ASTM A572 Gr.50</strong></td>
<td>345</td>
<td>450</td>
<td>18</td>
<td>0.45</td>
<td>⭐⭐⭐⭐</td>
<td>Edifícios, pontes</td>
</tr>
<tr>
<td><strong>ASTM A588</strong></td>
<td>345</td>
<td>485</td>
<td>19</td>
<td>0.50</td>
<td>⭐⭐⭐</td>
<td>Weathering</td>
</tr>
<tr>
<td><strong>EN S235JR</strong></td>
<td>235</td>
<td>360</td>
<td>26</td>
<td>0.38</td>
<td>⭐⭐⭐⭐⭐</td>
<td>Estruturas gerais</td>
</tr>
<tr>
<td><strong>EN S355J2</strong></td>
<td>355</td>
<td>490</td>
<td>22</td>
<td>0.50</td>
<td>⭐⭐⭐⭐</td>
<td>Pontes, pesadas</td>
</tr>
<tr>
<td><strong>NBR AR350</strong></td>
<td>345</td>
<td>450</td>
<td>18</td>
<td>0.45</td>
<td>⭐⭐⭐⭐</td>
<td>Construção civil</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-title">Sistemas de Pintura ISO 12944</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Classe</th>
<th>Ambiente</th>
<th>DFT (μm)</th>
<th>Sistema</th>
<th>Vida Útil</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>C1</strong></td>
<td>Interior seco</td>
<td>80</td>
<td>Monocomponente</td>
<td>5-10 anos</td>
</tr>
<tr>
<td><strong>C2</strong></td>
<td>Interior úmido</td>
<td>120</td>
<td>Epóxi 2c</td>
<td>5-10 anos</td>
</tr>
<tr>
<td><strong>C3</strong></td>
<td>Exterior médio</td>
<td>160</td>
<td>Epóxi + PU</td>
<td>10-15 anos</td>
</tr>
<tr>
<td><strong>C4</strong></td>
<td>Exterior agressivo</td>
<td>200</td>
<td>Epóxi alicíclico + PU</td>
<td>15-20 anos</td>
</tr>
<tr>
<td><strong>C5</strong></td>
<td>Marinho</td>
<td>250</td>
<td>Epóxi zinc-rich + PU</td>
<td>20+ anos</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-title">Normas de Referência</div>
<ul style="list-style-type: none; padding: 0;">
<li style="padding: 12px; background: var(--color-bg-1); margin-bottom: 8px; border-radius: 8px;">
<strong>AWS D1.1/D1.1M</strong> - Soldagem de estruturas de aço
</li>
<li style="padding: 12px; background: var(--color-bg-2); margin-bottom: 8px; border-radius: 8px;">
<strong>NBR 8800:2008</strong> - Projeto de estruturas de aço de edifícios
</li>
<li style="padding: 12px; background: var(--color-bg-3); margin-bottom: 8px; border-radius: 8px;">
<strong>EN 1993-1-8</strong> - Design of connections
</li>
<li style="padding: 12px; background: var(--color-bg-4); margin-bottom: 8px; border-radius: 8px;">
<strong>ISO 12944</strong> - Proteção de estruturas de aço com tinta
</li>
<li style="padding: 12px; background: var(--color-bg-5); margin-bottom: 8px; border-radius: 8px;">
<strong>ASTM A123</strong> - Galvanização a quente
</li>
</ul>
</div>
`;
}
// ========================================
// CALCULATION FUNCTIONS
// ========================================
// CEV Calculation
function calcularCEV() {
const C = parseFloat(document.getElementById('cev-c').value) || 0;
const Mn = parseFloat(document.getElementById('cev-mn').value) || 0;
const Cr = parseFloat(document.getElementById('cev-cr').value) || 0;
const Mo = parseFloat(document.getElementById('cev-mo').value) || 0;
const V = parseFloat(document.getElementById('cev-v').value) || 0;
const Ni = parseFloat(document.getElementById('cev-ni').value) || 0;
const Cu = parseFloat(document.getElementById('cev-cu').value) || 0;
const thickness = parseFloat(document.getElementById('cev-thickness').value) || 0;
// IIW Formula
const CEV = C + Mn/6 + (Cr+Mo+V)/5 + (Ni+Cu)/15;
// Interpretation
let stars = '';
let interpretation = '';
let alertClass = '';
if (CEV < 0.40) {
stars = '⭐⭐⭐⭐⭐';
interpretation = 'Excelente soldabilidade - Sem pré-aquecimento até 50mm';
alertClass = 'alert-success';
} else if (CEV < 0.50) {
stars = '⭐⭐⭐⭐';
interpretation = 'Boa soldabilidade - Pré-aquecimento recomendado acima de 25mm';
alertClass = 'alert-success';
} else if (CEV < 0.60) {
stars = '⭐⭐⭐';
interpretation = 'Soldabilidade média - Pré-aquecimento essencial acima de 15mm';
alertClass = 'alert-warning';
} else if (CEV < 0.70) {
stars = '⭐⭐';
interpretation = 'Soldabilidade difícil - Pré-aquecimento obrigatório, considerar PWHT';
alertClass = 'alert-warning';
} else {
stars = '⭐';
interpretation = 'Soldabilidade muito difícil - Procedimento especial necessário';
alertClass = 'alert-error';
}
// Preheat temperature (AWS D1.1)
const tempAmb = parseFloat(document.getElementById('cev-temp')?.value) || 20;
const preheatTemp = 50 + (CEV * 50) + (thickness / 10 * 20) + ((20 - tempAmb) / 2);
const result = document.getElementById('cev-result');
result.innerHTML = `
<div class="result-box">
<div class="result-title">Resultado do Cálculo CEV (IIW)</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">CEV</div>
<div class="result-value">${CEV.toFixed(3)}</div>
</div>
<div class="result-item">
<div class="result-label">Avaliação</div>
<div class="result-value" style="font-size: 28px;">${stars}</div>
</div>
<div class="result-item">
<div class="result-label">Pré-aquecimento Mínimo</div>
<div class="result-value">${Math.round(preheatTemp)}°C</div>
</div>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>${interpretation}</strong>
</div>
<div class="expert-only" style="margin-top: 16px; padding: 16px; background: var(--color-bg-2); border-radius: 8px;">
<strong>Fórmula IIW:</strong> CEV = C + Mn/6 + (Cr+Mo+V)/5 + (Ni+Cu)/15<br>
<strong>Normas aplicáveis:</strong> AWS D1.1, NBR 16239, EN 1011-2
</div>
</div>
`;
addToHistory('CEV Avançado', `CEV = ${CEV.toFixed(3)}, Pré-aquecimento = ${Math.round(preheatTemp)}°C`);
}
// Steel Selector
function selecionarAco() {
const fyMin = parseFloat(document.getElementById('sel-fy').value) || 0;
const weldReq = document.getElementById('sel-weld').value;
const steels = Object.values(steelDatabase).filter(steel => {
if (steel.fy < fyMin) return false;
if (weldReq === 'excellent' && steel.cev > 0.45) return false;
if (weldReq === 'good' && steel.cev > 0.55) return false;
return true;
});
if (steels.length === 0) {
document.getElementById('seletor-result').innerHTML = `
<div class="alert alert-warning">
Nenhum aço encontrado com os critérios especificados
</div>
`;
return;
}
const result = steels.map(steel => `
<div class="steel-card">
<h3 style="color: var(--color-primary); margin-bottom: 12px;">${steel.nome}</h3>
<div class="result-grid">
<div class="result-item">
<div class="result-label">fy</div>
<div class="result-value" style="font-size: 20px;">${steel.fy} MPa</div>
</div>
<div class="result-item">
<div class="result-label">fu</div>
<div class="result-value" style="font-size: 20px;">${steel.fu} MPa</div>
</div>
<div class="result-item">
<div class="result-label">Alongamento</div>
<div class="result-value" style="font-size: 20px;">${steel.elong}%</div>
</div>
<div class="result-item">
<div class="result-label">CEV</div>
<div class="result-value" style="font-size: 20px;">${steel.cev}</div>
</div>
</div>
<p style="margin-top: 12px;"><strong>Soldabilidade:</strong> ${steel.soldabilidade}</p>
<p><strong>Equivalentes:</strong> ${steel.equiv.join(', ')}</p>
<p><strong>Custo relativo:</strong> ${steel.custo}%</p>
</div>
`).join('');
document.getElementById('seletor-result').innerHTML = `
<div class="card">
<div class="card-title">Aços Recomendados (${steels.length})</div>
${result}
</div>
`;
addToHistory('Seletor de Aço', `${steels.length} aços encontrados com fy ≥ ${fyMin} MPa`);
}
// Equivalencias
function mostrarEquivalencias() {
const steelId = document.getElementById('equiv-steel').value;
const steel = steelDatabase[steelId];
if (!steel) return;
document.getElementById('equiv-result').innerHTML = `
<div class="card">
<div class="card-title">Equivalências para ${steel.nome}</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Norma</th>
<th>Designação</th>
<th>fy (MPa)</th>
<th>fu (MPa)</th>
<th>Along. (%)</th>
<th>CEV</th>
</tr>
</thead>
<tbody>
<tr style="background: var(--color-bg-1);">
<td><strong>Base</strong></td>
<td><strong>${steel.nome}</strong></td>
<td><strong>${steel.fy}</strong></td>
<td><strong>${steel.fu}</strong></td>
<td><strong>${steel.elong}</strong></td>
<td><strong>${steel.cev}</strong></td>
</tr>
${steel.equiv.map(eq => {
const eqSteel = Object.values(steelDatabase).find(s => s.nome === eq);
if (!eqSteel) return '';
return `
<tr>
<td>${eq.includes('ASTM') ? 'ASTM' : eq.includes('EN') ? 'EN' : eq.includes('NBR') ? 'NBR' : 'JIS'}</td>
<td>${eqSteel.nome}</td>
<td>${eqSteel.fy}</td>
<td>${eqSteel.fu}</td>
<td>${eqSteel.elong}</td>
<td>${eqSteel.cev}</td>
</tr>
`;
}).join('')}
</tbody>
</table>
</div>
</div>
`;
}
// Comparative Chart
function gerarGraficoComparativo() {
const checkboxes = document.querySelectorAll('.checkbox-group input:checked');
const selectedSteels = Array.from(checkboxes).map(cb => cb.value);
const chartType = document.getElementById('chart-type').value;
if (selectedSteels.length === 0) {
alert('Selecione pelo menos um aço');
return;
}
if (chartType === 'table') {
let tableHtml = `
<div class="card">
<div class="card-title">Tabela Comparativa</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Aço</th>
<th>fy (MPa)</th>
<th>fu (MPa)</th>
<th>Along. (%)</th>
<th>CEV</th>
<th>Soldabilidade</th>
<th>Custo</th>
</tr>
</thead>
<tbody>
`;
selectedSteels.forEach(steelId => {
const steel = steelDatabase[steelId];
if (steel) {
tableHtml += `
<tr>
<td><strong>${steel.nome}</strong></td>
<td>${steel.fy}</td>
<td>${steel.fu}</td>
<td>${steel.elong}</td>
<td>${steel.cev}</td>
<td>${steel.soldabilidade}</td>
<td>${steel.custo}%</td>
</tr>
`;
}
});
tableHtml += `
</tbody>
</table>
</div>
</div>
`;
document.getElementById('chart-result').innerHTML = tableHtml;
} else {
document.getElementById('chart-result').innerHTML = `
<div class="card">
<div class="card-title">Gráfico Comparativo</div>
<div class="chart-container">
<canvas id="comparison-chart"></canvas>
</div>
</div>
`;
if (currentChart) {
currentChart.destroy();
}
const ctx = document.getElementById('comparison-chart').getContext('2d');
const colors = ['#1FB8CD', '#FFC185', '#B4413C', '#ECEBD5', '#5D878F', '#DB4545'];
if (chartType === 'resistance') {
currentChart = new Chart(ctx, {
type: 'bar',
data: {
labels: selectedSteels.map(s => steelDatabase[s]?.nome || s),
datasets: [
{
label: 'fy (MPa)',
data: selectedSteels.map(s => steelDatabase[s]?.fy || 0),
backgroundColor: colors[0]
},
{
label: 'fu (MPa)',
data: selectedSteels.map(s => steelDatabase[s]?.fu || 0),
backgroundColor: colors[1]
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Comparação de Resistência'
}
}
}
});
} else if (chartType === 'ductility') {
currentChart = new Chart(ctx, {
type: 'line',
data: {
labels: selectedSteels.map(s => steelDatabase[s]?.nome || s),
datasets: [{
label: 'Alongamento (%)',
data: selectedSteels.map(s => steelDatabase[s]?.elong || 0),
borderColor: colors[2],
backgroundColor: colors[2] + '40',
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Comparação de Ductilidade'
}
}
}
});
}
}
addToHistory('Gráficos Comparativos', `Comparação de ${selectedSteels.length} aços`);
}
// Tab switching function
function switchTab(tabIndex) {
document.querySelectorAll('.tab-btn').forEach((btn, i) => {
btn.classList.toggle('active', i === tabIndex);
});
document.querySelectorAll('.tab-content').forEach((content, i) => {
content.classList.toggle('active', i === tabIndex);
});
}
// Bolt database with capacities
const boltDatabase = {
a325: {fy: 400, fu: 635, capacidade: {12: 5.2, 16: 9.2, 20: 14.4, 24: 20.7}, custo: 8},
a490: {fy: 565, fu: 895, capacidade: {12: 7.3, 16: 13.0, 20: 20.3, 24: 29.2}, custo: 15},
iso88: {fy: 640, fu: 800, capacidade: {12: 6.1, 16: 10.8, 20: 16.8, 24: 24.2}, custo: 5},
iso109: {fy: 900, fu: 1000, capacidade: {12: 8.7, 16: 15.5, 20: 24.2, 24: 34.8}, custo: 20}
};
const steelBearing = {
a36: {fy: 250, fu: 400},
a572: {fy: 345, fu: 450},
s235: {fy: 235, fu: 360},
s355: {fy: 355, fu: 490}
};
// Tab 1: Cisalhamento (Shear)
function calcularCisalhamento() {
const boltType = document.getElementById('bolt-type').value;
const d = parseFloat(document.getElementById('bolt-d').value);
const qty = parseInt(document.getElementById('bolt-qty').value);
const planes = parseInt(document.getElementById('bolt-planes').value);
const force = parseFloat(document.getElementById('bolt-force').value);
const bolt = boltDatabase[boltType];
const area = Math.PI * Math.pow(d / 2, 2);
const Fv = bolt.capacidade[d] * planes;
const capacity = Fv * qty;
const utilization = (force / capacity) * 100;
let alertClass = 'alert-success';
let status = '✅ ATENDE';
let recommendation = 'Capacidade adequada para a força aplicada';
if (utilization > 100) {
alertClass = 'alert-error';
status = '⚠️ NÃO ATENDE (Insuficiente)';
const qtyNeeded = Math.ceil(force / Fv);
recommendation = `Aumentar para ${qtyNeeded} parafusos ou usar tipo mais resistente`;
} else if (utilization > 85) {
alertClass = 'alert-warning';
status = '⚠️ ATENÇÃO (Utilização elevada)';
recommendation = 'Considere aumentar a quantidade de parafusos';
}
// Alternativas
let alternatives = '';
Object.keys(boltDatabase).forEach(type => {
if (type !== boltType) {
const altCap = boltDatabase[type].capacidade[d] * planes * qty;
const altUtil = (force / altCap) * 100;
if (altUtil < 100) {
alternatives += `<li>• ${qty} parafusos ${type.toUpperCase()}${altCap.toFixed(1)} kN ✅</li>`;
}
}
});
// Reference table
const refTable = `
<table style="width: 100%; margin-top: 20px; font-size: 12px;">
<thead>
<tr style="background: var(--color-primary); color: white;">
<th style="padding: 8px;">Tipo</th>
<th>Ø12</th>
<th>Ø16</th>
<th>Ø20</th>
<th>Ø24</th>
</tr>
</thead>
<tbody>
<tr><td><strong>A325</strong></td><td>5.2</td><td>9.2</td><td>14.4</td><td>20.7</td></tr>
<tr><td><strong>A490</strong></td><td>7.3</td><td>13.0</td><td>20.3</td><td>29.2</td></tr>
<tr><td><strong>ISO88</strong></td><td>6.1</td><td>10.8</td><td>16.8</td><td>24.2</td></tr>
<tr><td><strong>ISO109</strong></td><td>8.7</td><td>15.5</td><td>24.2</td><td>34.8</td></tr>
</tbody>
</table>
`;
document.getElementById('bolt-shear-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-1); border-left: 4px solid var(--color-primary);">
<div class="result-title">✅ CISALHAMENTO - RESULTADO</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Capacidade por Parafuso</div>
<div class="result-value">${Fv.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Capacidade Total (${qty}×${boltType.toUpperCase()})</div>
<div class="result-value">${capacity.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Força Aplicada</div>
<div class="result-value">${force.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Utilização</div>
<div class="result-value" style="color: ${utilization > 100 ? 'var(--color-error)' : utilization > 85 ? 'var(--color-warning)' : 'var(--color-success)'}">${utilization.toFixed(0)}%</div>
</div>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>STATUS: ${status}</strong><br>
Recomendação: ${recommendation}
</div>
${alternatives ? `
<div style="margin-top: 16px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>Alternativas Sugeridas:</strong>
<ul style="margin: 8px 0 0 20px;">${alternatives}</ul>
</div>
` : ''}
<div style="margin-top: 20px;">
<strong>Tabela de Referência (kN por parafuso, plano simples):</strong>
${refTable}
</div>
</div>
`;
addToHistory('Cisalhamento', `${qty} parafusos Ø${d}mm ${boltType.toUpperCase()}, Util: ${utilization.toFixed(0)}%`);
}
// Tab 2: Esmagamento (Bearing)
function calcularEsmagamento() {
const d = parseFloat(document.getElementById('bear-d').value);
const thickness = parseFloat(document.getElementById('bear-thickness').value);
const qty = parseInt(document.getElementById('bear-qty').value);
const steelType = document.getElementById('bear-steel').value;
const edge = parseFloat(document.getElementById('bear-edge').value);
const spacing = parseFloat(document.getElementById('bear-spacing').value);
const steel = steelBearing[steelType];
const fu = steel.fu;
// Location factor
let factor = 1.0;
if (edge < 1.5 * d) {
factor = 0.7;
}
// Bearing capacity
const Abc = d * thickness;
const Fb = 1.2 * fu * d * thickness * factor / 1000;
const FbTotal = Fb * qty;
// Compare with shear (assuming A325 Ø16)
const shearCap = 9.2 * 2 * qty;
const critical = FbTotal < shearCap ? 'ESMAGAMENTO' : 'CISALHAMENTO';
let status = '✅ OK';
let alertClass = 'alert-success';
let recommendation = 'Capacidade de esmagamento adequada';
if (factor < 1.0) {
alertClass = 'alert-warning';
status = '⚠️ ATENÇÃO';
recommendation = 'Distância de borda reduzida (fator 0.7 aplicado)';
}
document.getElementById('bolt-bearing-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-3); border-left: 4px solid #16a34a;">
<div class="result-title">✅ ESMAGAMENTO - RESULTADO</div>
<div style="margin-bottom: 20px;">
<p><strong>Espessura da Chapa:</strong> ${thickness} mm</p>
<p><strong>Diâmetro Parafuso:</strong> ${d} mm</p>
<p><strong>Aço da Chapa:</strong> ${steelType.toUpperCase()} (fu=${fu} MPa)</p>
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Área de Contato</div>
<div class="result-value">${Abc.toFixed(0)} mm²</div>
</div>
<div class="result-item">
<div class="result-label">Fator Localização</div>
<div class="result-value">${factor.toFixed(1)} ${factor === 1.0 ? '✓' : '⚠️'}</div>
</div>
<div class="result-item">
<div class="result-label">Capacidade por Parafuso</div>
<div class="result-value">${Fb.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Capacidade Total (${qty} un)</div>
<div class="result-value">${FbTotal.toFixed(1)} kN</div>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>Verificação contra Cisalhamento:</strong><br>
Cisalhamento: ${shearCap.toFixed(1)} kN<br>
Esmagamento: ${FbTotal.toFixed(1)} kN<br>
<strong style="color: var(--color-warning);">CONTROLA O ${critical}</strong>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>STATUS: ${status}</strong><br>
${recommendation}
</div>
</div>
`;
addToHistory('Esmagamento', `Ø${d}mm, esp=${thickness}mm, Cap=${FbTotal.toFixed(1)}kN`);
}
// Tab 3: Ruptura em Bloco
function calcularBlocoRuptura() {
const d = parseFloat(document.getElementById('block-d').value);
const hQty = parseInt(document.getElementById('block-h-qty').value);
const vQty = parseInt(document.getElementById('block-v-qty').value);
const hSpace = parseFloat(document.getElementById('block-h-space').value);
const edgeLeft = parseFloat(document.getElementById('block-edge-left').value);
const edgeTop = parseFloat(document.getElementById('block-edge-top').value);
const edgeRight = parseFloat(document.getElementById('block-edge-right').value);
const thickness = parseFloat(document.getElementById('block-thickness').value);
const steelType = document.getElementById('block-steel').value;
const force = parseFloat(document.getElementById('block-force').value);
const steel = steelBearing[steelType];
const fu = steel.fu;
const dHole = d + 2;
// Net tension area
const Ant = (edgeLeft + edgeRight) * thickness - (1 * dHole * thickness);
// Net shear area (vertical length)
const vertLength = (vQty - 1) * hSpace;
const Agv = vertLength * thickness - ((vQty - 1) * dHole * thickness);
// Block shear capacity (AISC 360-16)
const Rbs = (0.6 * fu * Agv + 0.3 * fu * Ant) / 1000;
const utilization = (force / Rbs) * 100;
let status = '✅ ATENDE';
let alertClass = 'alert-success';
let recommendation = 'Resistência ao bloco adequada';
if (utilization > 100) {
alertClass = 'alert-error';
status = '⚠️ NÃO ATENDE';
recommendation = 'Aumentar distância de borda ou espessura da chapa';
} else if (utilization > 85) {
alertClass = 'alert-warning';
status = '⚠️ ATENÇÃO';
recommendation = 'Utilização elevada, considere reforço';
}
document.getElementById('bolt-block-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-6); border-left: 4px solid var(--color-warning);">
<div class="result-title">✅ RUPTURA EM BLOCO - RESULTADO</div>
<div style="margin-bottom: 20px;">
<p><strong>Área Líquida Tração (Ant):</strong> ${Ant.toFixed(0)} mm²</p>
<p><strong>Área Líquida Cisalhamento (Agv):</strong> ${Agv.toFixed(0)} mm²</p>
</div>
<div style="padding: 16px; background: var(--color-surface); border-radius: 8px; margin-bottom: 16px;">
<strong>Resistência Ruptura (AISC 360-16):</strong><br>
Rbs = 0.6×fu×Agv + 0.3×fu×Ant<br>
Rbs = 0.6×${fu}×${Agv.toFixed(0)} + 0.3×${fu}×${Ant.toFixed(0)}<br>
Rbs = ${(0.6 * fu * Agv / 1000).toFixed(1)} + ${(0.3 * fu * Ant / 1000).toFixed(1)} = <strong>${Rbs.toFixed(1)} kN</strong>
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Resistência Bloco</div>
<div class="result-value">${Rbs.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Força Aplicada</div>
<div class="result-value">${force.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Utilização</div>
<div class="result-value" style="color: ${utilization > 100 ? 'var(--color-error)' : utilization > 85 ? 'var(--color-warning)' : 'var(--color-success)'}">${utilization.toFixed(0)}%</div>
</div>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>STATUS: ${status}</strong><br>
${recommendation}
</div>
</div>
`;
addToHistory('Bloco Ruptura', `Rbs=${Rbs.toFixed(1)}kN, Util=${utilization.toFixed(0)}%`);
}
// Tab 4: Layout de Furação Completo
function verificarLayoutCompleto() {
const d = parseFloat(document.getElementById('layout2-d').value);
const edgeLeft = parseFloat(document.getElementById('layout2-edge-left').value);
const edgeRight = parseFloat(document.getElementById('layout2-edge-right').value);
const edgeTop = parseFloat(document.getElementById('layout2-edge-top').value);
const edgeBottom = parseFloat(document.getElementById('layout2-edge-bottom').value);
const hSpace = parseFloat(document.getElementById('layout2-h-space').value);
const vSpace = parseFloat(document.getElementById('layout2-v-space').value);
const thickness = parseFloat(document.getElementById('layout2-thickness').value);
// NBR 8800 limits
const minEdge = 1.5 * d;
const maxEdge = Math.min(12 * thickness, 150);
const minSpacing = 2.67 * d;
const maxSpacing = 300;
// Check each parameter
const checks = [
{name: 'Esquerda', value: edgeLeft, min: minEdge, max: maxEdge},
{name: 'Direita', value: edgeRight, min: minEdge, max: maxEdge},
{name: 'Topo', value: edgeTop, min: minEdge, max: maxEdge},
{name: 'Base', value: edgeBottom, min: minEdge, max: maxEdge},
{name: 'Horizontal', value: hSpace, min: minSpacing, max: maxSpacing, isSpacing: true},
{name: 'Vertical', value: vSpace, min: minSpacing, max: maxSpacing, isSpacing: true}
];
let allConform = true;
let checksList = '';
checks.forEach(check => {
let status = '✅ CONFORME';
let statusClass = 'color: var(--color-success);';
let detail = `(mín ${check.min.toFixed(1)}mm)`;
if (check.value < check.min) {
status = '❌ ABAIXO DO MÍNIMO';
statusClass = 'color: var(--color-error);';
detail = `(mín ${check.min.toFixed(1)}mm)`;
allConform = false;
} else if (check.value > check.max) {
status = '⚠️ ACIMA DO MÁXIMO';
statusClass = 'color: var(--color-warning);';
detail = `(máx ${check.max.toFixed(0)}mm)`;
allConform = false;
} else if (!check.isSpacing) {
detail = `(${check.min.toFixed(1)}-${check.max.toFixed(0)}mm)`;
} else {
detail = `(${check.min.toFixed(1)}-${check.max}mm)`;
}
checksList += `
<tr style="border-bottom: 1px solid var(--color-border);">
<td style="padding: 10px;"><strong>${check.name}</strong></td>
<td style="padding: 10px;">${check.value} mm</td>
<td style="padding: 10px; ${statusClass}">${status}</td>
<td style="padding: 10px; color: var(--color-text-secondary);">${detail}</td>
</tr>
`;
});
// Simple layout drawing
const drawing = `
<div style="margin-top: 20px; padding: 20px; background: var(--color-surface); border-radius: 12px; font-family: monospace;">
<div style="text-align: center; margin-bottom: 16px;"><strong>DESENHO DE LAYOUT</strong></div>
<pre style="background: var(--color-background); padding: 16px; border-radius: 8px; overflow-x: auto;">
┌───────────────────────┐
${edgeTop} ${edgeTop} ${edgeTop}
│ ●─────●─────● │ ${edgeRight}
│ │ ${hSpace}${hSpace} │ │
│ ●─────●─────● │ ${vSpace}
│ │ │ │ │
│ ●─────●─────● │ ${vSpace}
${edgeLeft} ${edgeLeft} ${edgeLeft}
└───────────────────────┘
${edgeBottom} ${edgeBottom} ${edgeBottom}
</pre>
</div>
`;
document.getElementById('layout-full-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-5); border-left: 4px solid #a855f7;">
<div class="result-title">✅ LAYOUT DE FURAÇÃO - VERIFICAÇÃO</div>
<div style="margin-bottom: 20px;">
<p><strong>Diâmetro do Parafuso:</strong> ${d} mm</p>
<p><strong>Espessura da Chapa:</strong> ${thickness} mm</p>
</div>
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background: var(--color-primary); color: white;">
<th style="padding: 10px; text-align: left;">Parâmetro</th>
<th style="padding: 10px; text-align: left;">Valor</th>
<th style="padding: 10px; text-align: left;">Status</th>
<th style="padding: 10px; text-align: left;">Limites NBR 8800</th>
</tr>
</thead>
<tbody>
${checksList}
</tbody>
</table>
<div class="alert ${allConform ? 'alert-success' : 'alert-error'}" style="margin-top: 20px;">
<strong>${allConform ? '✅ 100% CONFORME COM NBR 8800' : '⚠️ AJUSTES NECESSÁRIOS'}</strong><br>
${allConform ? 'Todos os parâmetros estão dentro dos limites normativos' : 'Alguns parâmetros precisam ser ajustados'}
</div>
${drawing}
</div>
`;
addToHistory('Layout Furação', `Ø${d}mm, ${allConform ? 'CONFORME' : 'NÃO CONFORME'}`);
}
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 = `
<div class="card">
<div class="card-title">Verificação NBR 8800</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Dist. Borda Mín</div>
<div class="result-value" style="font-size: 18px;">${minEdge.toFixed(1)} mm</div>
</div>
<div class="result-item">
<div class="result-label">Dist. Borda Máx</div>
<div class="result-value" style="font-size: 18px;">${maxEdge} mm</div>
</div>
<div class="result-item">
<div class="result-label">Espaç. Mínimo</div>
<div class="result-value" style="font-size: 18px;">${minSpacing.toFixed(1)} mm</div>
</div>
<div class="result-item">
<div class="result-label">Espaç. Máximo</div>
<div class="result-value" style="font-size: 18px;">${maxSpacing} mm</div>
</div>
</div>
<div class="alert ${edgeClass}" style="margin-top: 16px;">
<strong>Distância de Borda: ${edgeStatus}</strong>
</div>
<div class="alert ${spacingClass}">
<strong>Espaçamento: ${spacingStatus}</strong>
</div>
</div>
`;
addToHistory('Layout de Furação', `Ø${d}mm, Borda: ${edge}mm, Espaç: ${spacing}mm`);
}
// Tab 5: Parafuso vs Solda Completo
function compararParafusoSoldaCompleto() {
const force = parseFloat(document.getElementById('comp2-force').value);
const length = parseFloat(document.getElementById('comp2-length').value);
const steelType = document.getElementById('comp2-steel').value;
const boltType = document.getElementById('comp2-bolt-type').value;
const boltD = parseFloat(document.getElementById('comp2-bolt-d').value);
const steel = steelBearing[steelType];
const bolt = boltDatabase[boltType];
// BOLT SOLUTION
const boltCapacity = bolt.capacidade[boltD] * 2; // 2 planes
const boltQty = Math.ceil(force / boltCapacity);
const boltTotalCap = boltCapacity * boltQty;
const boltMaterialCost = boltQty * bolt.custo;
const boltTimeMin = boltQty * 5;
const boltLaborCost = (boltTimeMin / 60) * 30;
const boltTotalCost = boltMaterialCost + boltLaborCost;
// WELD SOLUTION
const fyWeld = steel.fy * 0.6;
const weldLeg = (force * 1000) / (0.707 * length * 0.65 * fyWeld);
const weldLegRounded = Math.max(Math.ceil(weldLeg), 5);
const weldVolume = (weldLegRounded * weldLegRounded * 0.5 * length) / 1000; // cm³
const weldMass = (weldVolume / 1000) * 7.85; // kg
const electrodeKg = weldMass * 1.15 * 1.15; // losses
const electrodeCost = electrodeKg * 45;
const weldTimeMin = (length / 1000) * 30; // ~30 min per meter
const weldLaborCost = (weldTimeMin / 60) * 60;
const weldTotalCost = electrodeCost + weldLaborCost;
const weldCapacity = (0.707 * weldLegRounded * length * 0.65 * fyWeld) / 1000;
// Comparison
const cheaper = boltTotalCost < weldTotalCost ? 'PARAFUSO' : 'SOLDA';
const savings = Math.abs(boltTotalCost - weldTotalCost);
const timeSaved = Math.abs(boltTimeMin - weldTimeMin);
// Chart data
setTimeout(() => {
if (currentChart) currentChart.destroy();
const ctx = document.getElementById('comparison-chart').getContext('2d');
currentChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [
{
label: 'Parafuso',
data: [{x: boltTimeMin, y: boltTotalCost}],
backgroundColor: '#16a34a',
pointRadius: 10,
pointHoverRadius: 12
},
{
label: 'Solda',
data: [{x: weldTimeMin, y: weldTotalCost}],
backgroundColor: '#ea580c',
pointRadius: 10,
pointHoverRadius: 12
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Custo vs Tempo de Instalação'
},
legend: {
display: true,
position: 'top'
}
},
scales: {
x: {
title: {
display: true,
text: 'Tempo (minutos)'
}
},
y: {
title: {
display: true,
text: 'Custo (R$)'
}
}
}
}
});
}, 100);
document.getElementById('comparison-full-result').innerHTML = `
<div class="result-box" style="background: var(--color-bg-4); border-left: 4px solid var(--color-error);">
<div class="result-title">⚖️ COMPARAÇÃO: PARAFUSO vs SOLDA</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin: 20px 0;">
<div style="padding: 20px; background: var(--color-bg-1); border-radius: 12px; border: 2px solid var(--color-success);">
<h3 style="color: var(--color-success); margin-bottom: 16px;">🔩 PARAFUSO</h3>
<table style="width: 100%; font-size: 14px;">
<tr><td><strong>Tipo:</strong></td><td>${boltType.toUpperCase()} Ø${boltD}mm</td></tr>
<tr><td><strong>Quantidade:</strong></td><td>${boltQty} un</td></tr>
<tr><td><strong>Capacidade:</strong></td><td>${boltTotalCap.toFixed(1)} kN</td></tr>
<tr style="height: 10px;"></tr>
<tr style="background: var(--color-surface);"><td><strong>Custo Material:</strong></td><td>R$ ${boltMaterialCost.toFixed(2)}</td></tr>
<tr style="background: var(--color-surface);"><td><strong>Custo Mão de Obra:</strong></td><td>R$ ${boltLaborCost.toFixed(2)}</td></tr>
<tr><td><strong>Tempo Instalação:</strong></td><td>${boltTimeMin} min</td></tr>
<tr style="height: 10px;"></tr>
<tr style="background: var(--color-success); color: white;"><td><strong>CUSTO TOTAL:</strong></td><td><strong>R$ ${boltTotalCost.toFixed(2)}</strong></td></tr>
</table>
<div style="margin-top: 16px; padding: 12px; background: var(--color-surface); border-radius: 8px;">
<strong>Vantagens:</strong><br>
✅ Mais rápido<br>
✅ Reversível<br>
✅ Inspeção visual simples
</div>
</div>
<div style="padding: 20px; background: var(--color-bg-6); border-radius: 12px; border: 2px solid var(--color-warning);">
<h3 style="color: var(--color-warning); margin-bottom: 16px;">🔥 SOLDA</h3>
<table style="width: 100%; font-size: 14px;">
<tr><td><strong>Tipo:</strong></td><td>Filete</td></tr>
<tr><td><strong>Perna:</strong></td><td>${weldLegRounded} mm</td></tr>
<tr><td><strong>Comprimento:</strong></td><td>${length} mm</td></tr>
<tr style="height: 10px;"></tr>
<tr style="background: var(--color-surface);"><td><strong>Custo Material:</strong></td><td>R$ ${electrodeCost.toFixed(2)}</td></tr>
<tr style="background: var(--color-surface);"><td><strong>Custo Mão de Obra:</strong></td><td>R$ ${weldLaborCost.toFixed(2)}</td></tr>
<tr><td><strong>Tempo Soldagem:</strong></td><td>${Math.round(weldTimeMin)} min</td></tr>
<tr style="height: 10px;"></tr>
<tr style="background: var(--color-warning); color: white;"><td><strong>CUSTO TOTAL:</strong></td><td><strong>R$ ${weldTotalCost.toFixed(2)}</strong></td></tr>
</table>
<div style="margin-top: 16px; padding: 12px; background: var(--color-surface); border-radius: 8px;">
<strong>Vantagens:</strong><br>
✅ Maior rigidez<br>
✅ Melhor aparência<br>
✅ Distribuição de tensões
</div>
</div>
</div>
<div class="alert alert-success" style="margin-top: 20px;">
<strong>⭐ RECOMENDAÇÃO: ${cheaper}</strong><br>
Economia de R$ ${savings.toFixed(2)} | ${Math.abs(timeSaved).toFixed(0)} min ${boltTimeMin < weldTimeMin ? 'mais rápido' : 'mais lento'}
</div>
<div style="margin-top: 20px;">
<strong>📊 Gráfico Comparativo:</strong>
<div class="chart-container" style="height: 300px; margin-top: 10px;">
<canvas id="comparison-chart"></canvas>
</div>
</div>
</div>
`;
addToHistory('Parafuso vs Solda', `${cheaper} mais econômico (R$${savings.toFixed(2)})`);
// Add button to send recommended option to budget
const resultDiv = document.getElementById('comparison-full-result');
const existingButton = resultDiv.querySelector('.add-to-budget-btn');
if (!existingButton && cheaper === 'PARAFUSO') {
const button = document.createElement('button');
button.className = 'btn btn-success add-to-budget-btn';
button.style.marginTop = '16px';
button.textContent = '💰 Adicionar Parafusos ao Orçamento';
button.onclick = () => addBoltsToOrcamento(boltQty, boltType, boltD);
resultDiv.querySelector('.result-box').appendChild(button);
}
}
function addBoltsToOrcamento(qty, type, diameter) {
showSection('orcamento');
setTimeout(() => {
document.getElementById('budget-category').value = 'consumivel';
updateBudgetTypeOptions();
setTimeout(() => {
document.getElementById('budget-type').value = 'parafusos';
updateBudgetSpecOptions();
setTimeout(() => {
document.getElementById('budget-qty').value = qty;
updateBudgetTotal();
alert(`✅ Parafusos transferidos!\n\n${qty} parafusos ${type.toUpperCase()} M${diameter}\n\nSelecione na lista e adicione.`);
}, 200);
}, 200);
}, 300);
}
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;
const boltCapacity = 60;
const boltQty = Math.ceil(force / boltCapacity);
const boltCost = boltQty * 15;
const fyWeld = fy * 0.6;
const weldLeg = (force * 1000) / (0.707 * length * 0.65 * fyWeld);
const weldLegRounded = Math.ceil(weldLeg);
const weldCost = (weldLegRounded * length / 1000) * 25;
document.getElementById('comparison-result').innerHTML = `
<div class="card">
<div class="card-title">Comparação de Soluções</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div style="background: var(--color-bg-1); padding: 20px; border-radius: 12px;">
<h3 style="color: var(--color-primary); margin-bottom: 16px;">🔩 Solução Parafusada</h3>
<p><strong>Tipo:</strong> A325 Ø20mm</p>
<p><strong>Quantidade:</strong> ${boltQty} parafusos</p>
<p><strong>Capacidade:</strong> ${(boltQty * boltCapacity).toFixed(1)} kN</p>
<p><strong>Custo estimado:</strong> R$ ${boltCost.toFixed(2)}</p>
<p><strong>Vantagens:</strong> Desmontável, inspeção visual</p>
<p><strong>Desvantagens:</strong> Maior tempo de instalação</p>
</div>
<div style="background: var(--color-bg-2); padding: 20px; border-radius: 12px;">
<h3 style="color: var(--color-warning); margin-bottom: 16px;">🔥 Solução Soldada</h3>
<p><strong>Tipo:</strong> Solda de filete</p>
<p><strong>Perna:</strong> ${weldLegRounded} mm</p>
<p><strong>Comprimento:</strong> ${length} mm</p>
<p><strong>Custo estimado:</strong> R$ ${weldCost.toFixed(2)}</p>
<p><strong>Vantagens:</strong> Melhor rigidez, econômica</p>
<p><strong>Desvantagens:</strong> Permanente, requer qualificação</p>
</div>
</div>
<div class="alert alert-success" style="margin-top: 20px;">
<strong>Recomendação:</strong> ${weldCost < boltCost ? 'Solda de filete é mais econômica' : 'Parafusos mais econômicos'}
</div>
</div>
`;
addToHistory('Parafuso vs Solda', `${boltQty} parafusos vs solda ${weldLegRounded}mm`);
}
// ========================================
// WELDING PROCESS TO CONSUMABLES MAPPING
// ========================================
const processoConsumiveisMap = {
smaw: {
nome: 'SMAW (Eletrodo Revestido)',
consumiveis: ['e7018', 'e6013', 'e8018', 'e7016', 'e8016'],
defaultConsumivel: 'e7018'
},
gmaw: {
nome: 'GMAW (MIG/MAG)',
consumiveis: ['er70s2', 'er70s6'],
defaultConsumivel: 'er70s6'
},
fcaw: {
nome: 'FCAW (Arame Tubular)',
consumiveis: ['er70s2', 'er70s6'],
defaultConsumivel: 'er70s6'
},
gtaw: {
nome: 'GTAW (TIG)',
consumiveis: ['er70s2', 'er70s6', 'er4043', 'er5356'],
defaultConsumivel: 'er70s2'
},
saw: {
nome: 'SAW (Soldagem Submersa)',
consumiveis: ['er70s2', 'er70s6'],
defaultConsumivel: 'er70s6'
},
esw: {
nome: 'ESW (Soldagem por Escória)',
consumiveis: ['er70s2', 'er70s6'],
defaultConsumivel: 'er70s6'
}
};
// ========================================
// WELDING DATABASE
// ========================================
const weldingElectrodes = {
e7018: {
nome: 'E7018',
tipo: 'Básico',
processo: 'SMAW',
resistencia_tracao_min: 485,
resistencia_tracao_max: 620,
limite_escoamento: 345,
alongamento: 17,
charpy: 47,
posicoes: 'Todas (1F, 2F, 3F, 4F)',
corrente_min: 100,
corrente_max: 180,
voltagem_min: 24,
voltagem_max: 28,
rendimento: 0.68,
taxa_deposicao: 3.5,
custo_kg: 45,
diametros: [2.0, 2.4, 3.2, 4.0]
},
e6013: {
nome: 'E6013',
tipo: 'Rutílico',
processo: 'SMAW',
resistencia_tracao_min: 420,
resistencia_tracao_max: 550,
limite_escoamento: 300,
alongamento: 22,
charpy: 27,
posicoes: 'Todas',
corrente_min: 70,
corrente_max: 140,
voltagem_min: 22,
voltagem_max: 26,
rendimento: 0.62,
taxa_deposicao: 2.8,
custo_kg: 28,
diametros: [2.0, 2.4, 3.2, 4.0]
},
e8018: {
nome: 'E8018',
tipo: 'Básico Alta Resistência',
processo: 'SMAW',
resistencia_tracao_min: 550,
resistencia_tracao_max: 680,
limite_escoamento: 450,
alongamento: 15,
charpy: 68,
posicoes: 'Todas',
corrente_min: 120,
corrente_max: 200,
voltagem_min: 26,
voltagem_max: 30,
rendimento: 0.72,
taxa_deposicao: 4.2,
custo_kg: 65,
diametros: [2.4, 3.2, 4.0, 5.0]
},
e7016: {
nome: 'E7016',
tipo: 'Básico',
processo: 'SMAW',
resistencia_tracao_min: 485,
resistencia_tracao_max: 620,
limite_escoamento: 345,
alongamento: 17,
charpy: 47,
posicoes: 'Todas',
corrente_min: 90,
corrente_max: 170,
voltagem_min: 24,
voltagem_max: 28,
rendimento: 0.65,
taxa_deposicao: 3.2,
custo_kg: 38,
diametros: [2.0, 2.4, 3.2, 4.0]
},
e8016: {
nome: 'E8016',
tipo: 'Básico',
processo: 'SMAW',
resistencia_tracao_min: 550,
resistencia_tracao_max: 680,
limite_escoamento: 450,
alongamento: 15,
charpy: 54,
posicoes: 'Todas',
corrente_min: 110,
corrente_max: 190,
voltagem_min: 26,
voltagem_max: 30,
rendimento: 0.68,
taxa_deposicao: 3.8,
custo_kg: 58,
diametros: [2.4, 3.2, 4.0, 5.0]
},
er70s2: {
nome: 'ER70S-2',
tipo: 'MIG',
processo: 'GMAW',
resistencia_tracao_min: 490,
resistencia_tracao_max: 550,
limite_escoamento: 400,
alongamento: 22,
charpy: 27,
posicoes: 'Todas',
corrente_min: 150,
corrente_max: 250,
voltagem_min: 22,
voltagem_max: 28,
rendimento: 0.88,
taxa_deposicao: 5.5,
custo_kg: 35,
diametros: [0.8, 1.0, 1.2, 1.6]
},
er70s6: {
nome: 'ER70S-6',
tipo: 'MIG',
processo: 'GMAW',
resistencia_tracao_min: 490,
resistencia_tracao_max: 550,
limite_escoamento: 400,
alongamento: 22,
charpy: 27,
posicoes: 'Todas',
corrente_min: 150,
corrente_max: 250,
voltagem_min: 22,
voltagem_max: 28,
rendimento: 0.90,
taxa_deposicao: 6.0,
custo_kg: 32,
diametros: [0.8, 1.0, 1.2, 1.6]
},
er4043: {
nome: 'ER4043',
tipo: 'TIG - Alumínio',
processo: 'GTAW',
resistencia_tracao_min: 145,
resistencia_tracao_max: 185,
limite_escoamento: 70,
alongamento: 10,
charpy: 0,
posicoes: 'Todas',
corrente_min: 80,
corrente_max: 180,
voltagem_min: 10,
voltagem_max: 15,
rendimento: 0.95,
taxa_deposicao: 1.8,
custo_kg: 120,
diametros: [1.6, 2.0, 2.4, 3.2]
},
er5356: {
nome: 'ER5356',
tipo: 'TIG - Alumínio',
processo: 'GTAW',
resistencia_tracao_min: 290,
resistencia_tracao_max: 345,
limite_escoamento: 150,
alongamento: 12,
charpy: 0,
posicoes: 'Todas',
corrente_min: 90,
corrente_max: 200,
voltagem_min: 10,
voltagem_max: 15,
rendimento: 0.92,
taxa_deposicao: 2.2,
custo_kg: 135,
diametros: [1.6, 2.0, 2.4, 3.2]
}
};
const weldingProcesses = {
smaw: { nome: 'SMAW (Eletrodo Revestido)', ajuste_temp: 20 },
gmaw: { nome: 'GMAW (MIG/MAG)', ajuste_temp: 10 },
fcaw: { nome: 'FCAW (Arame Tubular)', ajuste_temp: 15 },
gtaw: { nome: 'GTAW (TIG)', ajuste_temp: 0 },
saw: { nome: 'SAW (Soldagem Submersa)', ajuste_temp: 25 },
esw: { nome: 'ESW (Soldagem por Escória)', ajuste_temp: 30 }
};
let currentWeldProcess = 'smaw';
let currentWeldElectrode = 'e7018';
// ========================================
// WELDING FUNCTIONS
// ========================================
function updateWeldingProcess() {
currentWeldProcess = document.getElementById('weld-process').value;
updateElectrodeOptions();
// Auto-update all tabs display after process change
const processName = weldingProcesses[currentWeldProcess]?.nome || 'SMAW';
const electrodeName = weldingElectrodes[currentWeldElectrode]?.nome || 'E7018';
const display = `${processName} (${electrodeName})`;
document.getElementById('preheat-process-display').textContent = display;
document.getElementById('filete-process-display').textContent = display;
document.getElementById('hi-process-display').textContent = display;
document.getElementById('consumo-electrode-display').textContent = electrodeName;
}
function updateWeldingElectrode() {
currentWeldElectrode = document.getElementById('weld-electrode').value;
}
function updateElectrodeOptions() {
const select = document.getElementById('weld-electrode');
const process = currentWeldProcess;
// Get valid consumables for this process
const processData = processoConsumiveisMap[process];
if (!processData) {
select.innerHTML = '<option value="e7018">E7018 (Padrão)</option>';
currentWeldElectrode = 'e7018';
return;
}
// Build options only with valid consumables
let options = '';
processData.consumiveis.forEach(consumivelId => {
const elec = weldingElectrodes[consumivelId];
if (elec) {
options += `<option value="${consumivelId}">${elec.nome} - ${elec.tipo}</option>`;
}
});
select.innerHTML = options || '<option value="e7018">E7018 (Padrão)</option>';
// Set default consumable for this process
select.value = processData.defaultConsumivel;
currentWeldElectrode = select.value;
// Update electrode display in consumption tab
const electrodeName = weldingElectrodes[currentWeldElectrode]?.nome || 'E7018';
document.getElementById('consumo-electrode-display').textContent = electrodeName;
}
function applyToAllTabs() {
const processName = weldingProcesses[currentWeldProcess]?.nome || 'SMAW';
const electrodeName = weldingElectrodes[currentWeldElectrode]?.nome || 'E7018';
const display = `${processName} (${electrodeName})`;
document.getElementById('preheat-process-display').textContent = display;
document.getElementById('filete-process-display').textContent = display;
document.getElementById('hi-process-display').textContent = display;
document.getElementById('consumo-electrode-display').textContent = electrodeName;
alert(`✅ Processo e consumível atualizados em todas as abas!\n\n${display}`);
}
function showElectrodeProperties() {
const elec = weldingElectrodes[currentWeldElectrode];
if (!elec) return;
const html = `
<div class="card" style="background: var(--color-bg-3); margin-top: 20px;">
<div class="card-title">📋 Propriedades do ${elec.nome}</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Resistência Tração</div>
<div class="result-value" style="font-size: 18px;">${elec.resistencia_tracao_min}-${elec.resistencia_tracao_max} MPa</div>
</div>
<div class="result-item">
<div class="result-label">Limite Escoamento</div>
<div class="result-value" style="font-size: 18px;">≥ ${elec.limite_escoamento} MPa</div>
</div>
<div class="result-item">
<div class="result-label">Alongamento</div>
<div class="result-value" style="font-size: 18px;">≥ ${elec.alongamento}%</div>
</div>
<div class="result-item">
<div class="result-label">Charpy (-20°C)</div>
<div class="result-value" style="font-size: 18px;">${elec.charpy > 0 ? '≥ ' + elec.charpy + ' J' : 'N/A'}</div>
</div>
<div class="result-item">
<div class="result-label">Corrente Recomendada</div>
<div class="result-value" style="font-size: 18px;">${elec.corrente_min}-${elec.corrente_max} A</div>
</div>
<div class="result-item">
<div class="result-label">Voltagem</div>
<div class="result-value" style="font-size: 18px;">${elec.voltagem_min}-${elec.voltagem_max} V</div>
</div>
<div class="result-item">
<div class="result-label">Rendimento de Deposição</div>
<div class="result-value" style="font-size: 18px;">${(elec.rendimento * 100).toFixed(0)}%</div>
</div>
<div class="result-item">
<div class="result-label">Custo</div>
<div class="result-value" style="font-size: 18px;">R$ ${elec.custo_kg}/kg</div>
</div>
</div>
<div style="margin-top: 16px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<p><strong>Tipo de Revestimento:</strong> ${elec.tipo}</p>
<p><strong>Posição Soldagem:</strong> ${elec.posicoes}</p>
<p><strong>Taxa de Deposição:</strong> ${elec.taxa_deposicao} kg/h</p>
<p><strong>Diâmetros Comerciais:</strong> ${elec.diametros.join(', ')} mm</p>
</div>
</div>
`;
document.getElementById('electrode-properties').innerHTML = html;
}
function switchWeldTab(index) {
document.querySelectorAll('.tabs-nav .tab-btn').forEach((btn, i) => {
if (btn.textContent.includes('Pré-Aquecimento') || btn.textContent.includes('Filete') ||
btn.textContent.includes('Energia') || btn.textContent.includes('Consumo') ||
btn.textContent.includes('Sequência') || btn.textContent.includes('Padrões')) {
btn.classList.toggle('active', i === index);
}
});
for (let i = 0; i < 6; i++) {
const tab = document.getElementById(`weld-tab-${i}`);
if (tab) {
tab.classList.toggle('active', i === index);
}
}
}
function calcularPreaquecimentoCompleto() {
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 restraint = parseFloat(document.getElementById('preheat-restraint').value) || 1.0;
const calcInterpass = document.getElementById('preheat-interpass').checked;
const processAdjust = weldingProcesses[currentWeldProcess]?.ajuste_temp || 0;
// AWS D1.1 Formula
const cevFactor = cev * 50;
const thicknessFactor = (thickness / 10) * 20;
const ambientFactor = (20 - ambient) / 2;
let preheatTemp = 50 + cevFactor + thicknessFactor + ambientFactor + processAdjust;
preheatTemp = preheatTemp * restraint;
const interpassTemp = preheatTemp + 25;
const maxInterpass = 200;
let cevClass = '';
let cevInterpretation = '';
if (cev < 0.40) {
cevClass = 'Baixo';
cevInterpretation = 'Excelente soldabilidade';
} else if (cev < 0.50) {
cevClass = 'Médio';
cevInterpretation = 'Boa soldabilidade com cuidados';
} else if (cev < 0.60) {
cevClass = 'Alto';
cevInterpretation = 'Soldabilidade moderada';
} else {
cevClass = 'Crítico';
cevInterpretation = 'Requer procedimento especial';
}
let thicknessClass = thickness > 50 ? 'Crítica' : thickness > 25 ? 'Alta' : 'Normal';
const html = `
<div class="result-box" style="background: var(--color-bg-1); border-left: 4px solid var(--color-warning);">
<div class="result-title">🔥 PRÉ-AQUECIMENTO AWS D1.1 - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>DADOS RESUMIDOS:</strong><br>
Processo: ${weldingProcesses[currentWeldProcess].nome}<br>
Consumível: ${weldingElectrodes[currentWeldElectrode].nome}<br>
CEV: ${cev.toFixed(2)} (${cevClass} - ${cevInterpretation})<br>
Espessura: ${thickness} mm (${thicknessClass})<br>
Ambiente: ${ambient}°C<br>
Restrição: ${restraint === 1.0 ? 'Não restrita' : restraint === 1.1 ? 'Parcial' : 'Total'}
</div>
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px;">
<strong>CÁLCULOS:</strong><br>
CEV Factor: ${cev.toFixed(2)} × 50 = ${cevFactor.toFixed(1)}°C<br>
Esp Factor: (${thickness}/10) × 20 = ${thicknessFactor.toFixed(1)}°C<br>
Amb Factor: (20 - ${ambient}) / 2 = ${ambientFactor.toFixed(1)}°C<br>
Processo Adj: +${processAdjust}°C (${currentWeldProcess.toUpperCase()})<br>
Restrição: ×${restraint} = Multiplica por ${restraint}
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">PRÉ-AQUECIMENTO MÍNIMO</div>
<div class="result-value">${Math.round(preheatTemp)}°C</div>
</div>
${calcInterpass ? `
<div class="result-item">
<div class="result-label">INTERPASS (entre passes)</div>
<div class="result-value">${Math.round(interpassTemp)}°C</div>
</div>
<div class="result-item">
<div class="result-label">Temperatura Máxima</div>
<div class="result-value">${maxInterpass}°C</div>
</div>
` : ''}
</div>
<div class="alert alert-warning" style="margin-top: 20px;">
<strong>⚠️ RECOMENDAÇÕES CRÍTICAS:</strong><br>
1. Pré-aqueça todo o acesso de soldagem (min 75mm da junta)<br>
${calcInterpass ? `2. Manter interpass entre ${Math.round(preheatTemp)}-${Math.round(interpassTemp)}°C<br>` : ''}
${calcInterpass ? `3. Não exceder ${maxInterpass}°C (risco de fragilização ZTA)<br>` : ''}
${calcInterpass ? '4' : '2'}. Usar termômetro de contato ou pirômetro<br>
${calcInterpass ? '5' : '3'}. ${thickness > 50 || cev > 0.60 ? 'PWHT (Tratamento Térmico Pós) RECOMENDADO' : 'Considerar PWHT para maior confiabilidade'}
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-2); border-radius: 8px;">
<strong>📊 TABELA AWS D1.1 REFERÊNCIA:</strong>
<table style="width: 100%; margin-top: 12px; font-size: 12px;">
<thead>
<tr style="background: var(--color-primary); color: white;">
<th style="padding: 8px;">Espessura</th>
<th>CEV < 0.40</th>
<th>CEV 0.40-0.60</th>
<th>CEV > 0.60</th>
</tr>
</thead>
<tbody>
<tr><td style="padding: 8px;">< 12mm</td><td>Não req.</td><td>50°C</td><td>100°C</td></tr>
<tr style="background: ${thickness >= 12 && thickness < 25 ? 'var(--color-bg-3)' : ''};"><td style="padding: 8px;">12-25mm</td><td>50°C</td><td>100°C</td><td>150°C</td></tr>
<tr style="background: ${thickness >= 25 && thickness < 50 ? 'var(--color-bg-3)' : ''};"><td style="padding: 8px;">25-50mm</td><td>50°C</td><td>100°C</td><td>165°C</td></tr>
<tr style="background: ${thickness >= 50 ? 'var(--color-bg-3)' : ''};"><td style="padding: 8px;">> 50mm</td><td>100°C</td><td>150°C</td><td>225°C</td></tr>
</tbody>
</table>
</div>
</div>
`;
document.getElementById('preheat-result').innerHTML = html;
addToHistory('Pré-Aquecimento', `${Math.round(preheatTemp)}°C (CEV=${cev.toFixed(2)}, esp=${thickness}mm)`);
}
function calcularFileteCompleto() {
const force = parseFloat(document.getElementById('filete-force').value) || 0;
const length = parseFloat(document.getElementById('filete-length').value) || 0;
const jointType = parseInt(document.getElementById('filete-joint').value) || 1;
const fy = parseFloat(document.getElementById('filete-steel').value) || 345;
const positionFactor = parseFloat(document.getElementById('filete-position').value) || 1.0;
const elec = weldingElectrodes[currentWeldElectrode];
// Weld capacity calculation
const fyWeld = fy * 0.6;
const legTheoretical = (force * 1000) / (0.707 * length * jointType * 0.65 * fyWeld * positionFactor);
const legCommercial = Math.max(Math.ceil(legTheoretical), 3);
const throat = legCommercial * 0.707;
// Number of passes
let passes = 1;
let maxDiameter = 3.25;
if (legCommercial <= 5) {
passes = 1;
maxDiameter = 3.25;
} else if (legCommercial <= 8) {
passes = 2;
maxDiameter = 4.0;
} else {
passes = Math.ceil(legCommercial / 4);
maxDiameter = 4.0;
}
// Real capacity
const realCapacity = (0.707 * legCommercial * length * jointType * 0.65 * fyWeld * positionFactor) / 1000;
const safetyMargin = realCapacity - force;
const utilization = (force / realCapacity) * 100;
// Time and consumption estimate
const timePerPass = (length / 1000) * 30; // 30 min/m
const totalTime = timePerPass * passes;
const volume = (legCommercial * legCommercial * 0.5 * length * jointType) / 1000; // cm³
const mass = (volume / 1000) * 7.85; // kg
const consumption = mass / elec.rendimento * 1.15; // with losses
const positionName = positionFactor === 1.0 ? 'Plana (1F)' : positionFactor === 0.9 ? 'Horizontal (2F)' : positionFactor === 0.8 ? 'Vertical (3F)' : 'Sobrecabeça (4F)';
let status = '✅ VIÁVEL';
let alertClass = 'alert-success';
if (utilization > 100) {
status = '❌ INSUFICIENTE';
alertClass = 'alert-error';
} else if (utilization > 85) {
status = '⚠️ ATENÇÃO';
alertClass = 'alert-warning';
}
const html = `
<div class="result-box" style="background: var(--color-bg-3); border-left: 4px solid var(--color-success);">
<div class="result-title">⚡ DIMENSIONAMENTO DE FILETE - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>DADOS:</strong><br>
Processo: ${weldingProcesses[currentWeldProcess].nome}<br>
Eletrodo: ${elec.nome}<br>
Força: ${force} kN | Comprimento: ${length} mm<br>
Aço Base: fy = ${fy} MPa<br>
Junta: ${jointType === 1 ? 'Filete Simples' : 'Filete Duplo'} | Posição: ${positionName}
</div>
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px; font-family: var(--font-family-mono); font-size: 13px;">
<strong>CÁLCULO:</strong><br>
Fv unitário = 0.707 × perna × comp × 0.65 × fy / 1000<br>
Fv = 0.707 × perna × ${length} × 0.65 × ${fy}/1000<br>
Fv = ${(0.707 * length * 0.65 * fy / 1000).toFixed(2)} × perna (kN)<br><br>
Para ${jointType} filete(s): ${jointType} × Fv = ${(jointType * 0.707 * length * 0.65 * fy / 1000).toFixed(2)} × perna<br><br>
Perna necessária: ${force} / ${(jointType * 0.707 * length * 0.65 * fy / 1000).toFixed(2)} = ${legTheoretical.toFixed(2)} mm
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Perna Teórica</div>
<div class="result-value">${legTheoretical.toFixed(2)} mm</div>
</div>
<div class="result-item">
<div class="result-label">Perna Comercial</div>
<div class="result-value" style="color: var(--color-success);">${legCommercial} mm</div>
</div>
<div class="result-item">
<div class="result-label">Capacidade Real</div>
<div class="result-value">${realCapacity.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Margem de Segurança</div>
<div class="result-value">${safetyMargin.toFixed(1)} kN (${((realCapacity/force - 1) * 100).toFixed(0)}%)</div>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-1); border-radius: 8px;">
<strong>⚙️ DIMENSIONAMENTO DE PASSES:</strong><br>
Eletrodo Máximo: ${maxDiameter}mm (para ${passes} passa${passes > 1 ? 's' : ''})
</div>
<div style="margin-top: 16px; padding: 16px; background: var(--color-surface); border-radius: 8px; border: 2px solid var(--color-primary);">
<strong>OPÇÃO ${passes === 1 ? 'RECOMENDADA' : '1'}: ${passes} PASSA${passes > 1 ? 'S' : ''}:</strong><br>
Perna: ${passes === 1 ? legCommercial : passes + '×' + Math.ceil(legCommercial/passes)} mm (diâmetro ${maxDiameter}mm)<br>
Corrente: ${elec.corrente_min}-${elec.corrente_max} A<br>
Tempo: ${Math.round(totalTime)} min<br>
Consumo: ${consumption.toFixed(2)} kg<br>
${status === '✅ VIÁVEL' ? '✅ VIÁVEL (Margem de ' + ((realCapacity/force - 1) * 100).toFixed(0) + '%)' : status}
</div>
${passes === 1 && legCommercial >= 5 ? `
<div style="margin-top: 16px; padding: 16px; background: var(--color-bg-6); border-radius: 8px;">
<strong>OPÇÃO 2: 2 PASSES (Maior Confiabilidade):</strong><br>
Perna: 2×${Math.ceil(legCommercial/2)} = ${legCommercial} mm<br>
Corrente: ${elec.corrente_min} A × 2<br>
Tempo: ${Math.round(totalTime * 2)} min<br>
Consumo: ${(consumption * 2).toFixed(2)} kg<br>
✅ RECOMENDADO (Maior qualidade e resistência)
</div>
` : ''}
<div class="alert ${alertClass}" style="margin-top: 20px;">
<strong>RECOMENDAÇÕES:</strong><br>
- ${elec.nome} é ${elec.tipo === 'Básico' ? 'excelente' : 'adequado'} para essa aplicação<br>
- ${passes > 1 ? 'Usar ' + passes + ' passes garante melhor qualidade' : 'Soldagem em 1 passa é viável'}<br>
- Manter interpass 150°C (vindo da Aba Pré-Aquecimento)<br>
- Utilização: ${utilization.toFixed(1)}% ${status}
</div>
</div>
`;
document.getElementById('filete-result').innerHTML = html;
addToHistory('Filete', `Perna ${legCommercial}mm, ${passes} passe(s), ${force}kN`);
}
function calcularEnergiaCompleta() {
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 efficiency = parseFloat(document.getElementById('hi-efficiency').value) || 0.75;
const steelType = document.getElementById('hi-steel').value;
// Heat Input calculation
const heatInput = (voltage * current * 60 * efficiency) / (speed * 1000);
const steelLimits = {
'a36': { min: 1.5, max: 3.0, name: 'A36' },
'a572': { min: 1.0, max: 2.5, name: 'A572' },
's355': { min: 0.8, max: 2.0, name: 'S355' }
};
const limits = steelLimits[steelType];
let hiStatus = '';
let alertClass = '';
let recommendations = [];
if (heatInput < limits.min) {
hiStatus = 'BAIXO';
alertClass = 'alert-warning';
recommendations.push('Aumentar corrente ou reduzir velocidade');
recommendations.push('Risco de falta de fusão ou trincas a frio');
} else if (heatInput <= limits.max) {
hiStatus = 'ADEQUADO ✅';
alertClass = 'alert-success';
recommendations.push('Energia dentro da faixa recomendada');
recommendations.push('Manter os parâmetros atuais');
} else {
hiStatus = 'MUITO ALTO ⚠️';
alertClass = 'alert-error';
const newSpeed = Math.ceil((voltage * current * 60 * efficiency) / (limits.max * 1000));
const newCurrent = Math.ceil((limits.max * 1000 * speed) / (voltage * 60 * efficiency));
recommendations.push('AUMENTAR VELOCIDADE para ' + newSpeed + ' cm/min → HI = ' + limits.max.toFixed(2) + ' kJ/mm ✅');
recommendations.push('OU REDUZIR CORRENTE para ' + newCurrent + ' A → HI = ' + limits.max.toFixed(2) + ' kJ/mm ✅');
recommendations.push('OPÇÃO 3: Usar processo GMAW (mais eficiente) → HI ≈ ' + (heatInput * 0.6).toFixed(2) + ' kJ/mm ✅');
}
const html = `
<div class="result-box" style="background: var(--color-bg-6); border-left: 4px solid var(--color-warning);">
<div class="result-title">🔥 ENERGIA DE SOLDAGEM - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>PARÂMETROS:</strong><br>
Voltagem: ${voltage} V<br>
Corrente: ${current} A<br>
Velocidade: ${speed} cm/min<br>
Eficiência: ${(efficiency * 100).toFixed(0)}%
</div>
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px; font-family: var(--font-family-mono); font-size: 13px;">
<strong>CÁLCULO:</strong><br>
HI = (V × I × 60 × η) / (v × 1000)<br>
HI = (${voltage} × ${current} × 60 × ${efficiency}) / (${speed} × 1000)<br>
HI = ${(voltage * current * 60 * efficiency).toFixed(1)} / ${speed * 1000} = ${heatInput.toFixed(2)} kJ/mm
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Energia de Soldagem</div>
<div class="result-value" style="color: ${heatInput <= limits.max && heatInput >= limits.min ? 'var(--color-success)' : 'var(--color-error)'}">${heatInput.toFixed(2)} kJ/mm</div>
</div>
<div class="result-item">
<div class="result-label">Classificação</div>
<div class="result-value" style="font-size: 20px;">${hiStatus}</div>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-2); border-radius: 8px;">
<strong>⚠️ ANÁLISE POR TIPO DE AÇO:</strong>
<table style="width: 100%; margin-top: 12px; font-size: 13px;">
<thead>
<tr style="background: var(--color-primary); color: white;">
<th style="padding: 8px;">Aço</th>
<th>Ideal (kJ/mm)</th>
<th>Valor</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr style="background: ${steelType === 'a36' ? 'var(--color-bg-3)' : ''};">
<td style="padding: 8px;">A36</td>
<td>1.5-3.0</td>
<td>${heatInput.toFixed(2)}</td>
<td>${heatInput >= 1.5 && heatInput <= 3.0 ? '✅ OK' : heatInput > 3.0 ? '❌ ALTO' : '⚠️ BAIXO'}</td>
</tr>
<tr style="background: ${steelType === 'a572' ? 'var(--color-bg-3)' : ''};">
<td style="padding: 8px;">A572</td>
<td>1.0-2.5</td>
<td>${heatInput.toFixed(2)}</td>
<td>${heatInput >= 1.0 && heatInput <= 2.5 ? '✅ OK' : heatInput > 2.5 ? '❌ ALTO' : '⚠️ BAIXO'}</td>
</tr>
<tr style="background: ${steelType === 's355' ? 'var(--color-bg-3)' : ''};">
<td style="padding: 8px;">S355</td>
<td>0.8-2.0</td>
<td>${heatInput.toFixed(2)}</td>
<td>${heatInput >= 0.8 && heatInput <= 2.0 ? '✅ OK' : heatInput > 2.0 ? '❌ CRÍTICO' : '⚠️ BAIXO'}</td>
</tr>
</tbody>
</table>
</div>
${heatInput > limits.max ? `
<div style="margin-top: 16px; padding: 16px; background: var(--color-bg-4); border-radius: 8px; border: 2px solid var(--color-error);">
<strong>⚠️ RISCOS:</strong><br>
1. Aquecimento excessivo da ZTA<br>
2. Possível fragilização por alívio<br>
3. Risco de trincas pelo resfriamento rápido<br>
4. Redução de tenacidade
</div>
` : ''}
<div class="alert ${alertClass}" style="margin-top: 20px;">
<strong>✅ RECOMENDAÇÕES:</strong><br>
${recommendations.map((rec, i) => `${i + 1}. ${rec}`).join('<br>')}
</div>
<div style="margin-top: 16px; padding: 12px; background: var(--color-surface); border-radius: 8px; text-align: center;">
<strong>🔧 CALCULADORA INTERATIVA:</strong><br>
<small>Teste diferentes velocidades/correntes acima para encontrar HI ideal!</small>
</div>
</div>
`;
document.getElementById('hi-result').innerHTML = html;
addToHistory('Energia Soldagem', `HI=${heatInput.toFixed(2)} kJ/mm (${hiStatus})`);
}
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 = `
<div class="result-box">
<div class="result-title">Temperatura de Pré-Aquecimento (AWS D1.1)</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Temp. Mínima</div>
<div class="result-value">${Math.round(preheatTemp)}°C</div>
</div>
<div class="result-item">
<div class="result-label">Temp. Interpasse Máx</div>
<div class="result-value">${Math.round(maxInterpass)}°C</div>
</div>
</div>
<div class="alert alert-warning" style="margin-top: 16px;">
<strong>${pwhtRecommendation}</strong>
</div>
</div>
`;
addToHistory('Pré-Aquecimento', `CEV=${cev}, esp=${thickness}mm → ${Math.round(preheatTemp)}°C`);
}
function calcularConsumoCompleto() {
const leg = parseFloat(document.getElementById('consumo-leg').value) || 0;
const length = parseFloat(document.getElementById('consumo-length').value) || 0;
const loss = parseFloat(document.getElementById('consumo-loss').value) || 15;
const scrap = parseFloat(document.getElementById('consumo-scrap').value) || 5;
const elec = weldingElectrodes[currentWeldElectrode];
// Volume calculation
const throat = leg * 0.707;
const volumeCm3 = (throat * leg * length * 1000 * 0.5) / 1000;
const massKg = (volumeCm3 / 1000000) * 7850;
// Consumption with efficiency
const massConsumable = massKg / elec.rendimento;
const lossKg = massConsumable * (loss / 100);
const scrapKg = massConsumable * (scrap / 100);
const totalKg = massConsumable + lossKg + scrapKg;
// Time estimation
const timeHours = totalKg / elec.taxa_deposicao;
const timeMin = timeHours * 60;
// Cost
const costMaterial = totalKg * elec.custo_kg;
const costLabor = timeHours * 60; // R$ 60/h average
const costTotal = costMaterial + costLabor;
// Compare with other electrodes
let comparisons = [];
Object.keys(weldingElectrodes).forEach(key => {
const e = weldingElectrodes[key];
if (e.processo === 'SMAW' && key !== currentWeldElectrode) {
const altMass = massKg / e.rendimento * (1 + loss/100) * (1 + scrap/100);
const altTime = (altMass / e.taxa_deposicao) * 60;
const altCost = altMass * e.custo_kg + (altTime / 60) * 60;
comparisons.push({
name: e.nome,
mass: altMass,
time: altTime,
cost: altCost
});
}
});
const html = `
<div class="result-box" style="background: var(--color-bg-5); border-left: 4px solid #a855f7;">
<div class="result-title">📊 CONSUMO DE ELETRODOS - RESULTADO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>CONSUMÍVEL SELECIONADO:</strong><br>
Eletrodo ${elec.nome} (AWS A5.1)<br>
Rendimento: ${(elec.rendimento * 100).toFixed(0)}%<br>
Taxa Deposição: ${elec.taxa_deposicao} kg/h<br>
Custo: R$ ${elec.custo_kg}/kg
</div>
<div style="padding: 16px; background: var(--color-background); border-radius: 8px; margin-bottom: 16px; font-family: var(--font-family-mono); font-size: 13px;">
<strong>CÁLCULOS:</strong><br>
Volume de Solda: ${volumeCm3.toFixed(0)} mm³<br>
Massa Teórica: ${massKg.toFixed(3)} kg<br>
Fator Rendimento: ${(elec.rendimento * 100).toFixed(0)}% = ÷${elec.rendimento.toFixed(2)}<br>
Massa Consumível: ${massKg.toFixed(3)} ÷ ${elec.rendimento.toFixed(2)} = ${massConsumable.toFixed(3)} kg<br><br>
Perdas (Respingos): ${loss}% × ${massConsumable.toFixed(3)} = ${lossKg.toFixed(4)}kg<br>
Sucata (Pontas): ${scrap}% × ${massConsumable.toFixed(3)} = ${scrapKg.toFixed(4)}kg<br><br>
TOTAL NECESSÁRIO: ${totalKg.toFixed(4)} kg
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Consumo de Eletrodo</div>
<div class="result-value">${(totalKg * 1000).toFixed(0)} g (${totalKg.toFixed(3)} kg)</div>
</div>
<div class="result-item">
<div class="result-label">Caixas de 5kg</div>
<div class="result-value">${Math.ceil(totalKg / 5)} caixa${Math.ceil(totalKg / 5) > 1 ? 's' : ''}</div>
</div>
<div class="result-item">
<div class="result-label">Custo Total Material</div>
<div class="result-value">R$ ${costMaterial.toFixed(2)}</div>
</div>
<div class="result-item">
<div class="result-label">Tempo de Soldagem</div>
<div class="result-value">${Math.round(timeMin)} min</div>
</div>
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-2); border-radius: 8px;">
<strong>📊 COMPARAÇÃO DE ELETRODOS PARA MESMO TRABALHO:</strong>
<table style="width: 100%; margin-top: 12px; font-size: 13px;">
<thead>
<tr style="background: var(--color-primary); color: white;">
<th style="padding: 8px;">Eletrodo</th>
<th>Consumo</th>
<th>Custo</th>
<th>Tempo</th>
</tr>
</thead>
<tbody>
<tr style="background: var(--color-bg-3);">
<td style="padding: 8px;"><strong>${elec.nome}</strong></td>
<td>${totalKg.toFixed(3)}kg</td>
<td>R$ ${costTotal.toFixed(2)}</td>
<td>${Math.round(timeMin)} min</td>
</tr>
${comparisons.map(c => `
<tr>
<td style="padding: 8px;">${c.name}</td>
<td>${c.mass.toFixed(3)}kg</td>
<td>R$ ${c.cost.toFixed(2)} ${c.cost < costTotal ? '✅' : ''}</td>
<td>${Math.round(c.time)} min ${c.time < timeMin ? '✅' : ''}</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
<div class="alert alert-success" style="margin-top: 20px;">
<strong>✅ RECOMENDAÇÃO:</strong><br>
${comparisons.length > 0 && comparisons[0].cost < costTotal ?
`${comparisons[0].name} é mais barato (${((1 - comparisons[0].cost/costTotal) * 100).toFixed(0)}% economia!)` :
`${elec.nome} é a melhor opção considerando custo e qualidade`}
</div>
</div>
`;
document.getElementById('consumo-result').innerHTML = html;
addToHistory('Consumo Eletrodos', `${totalKg.toFixed(3)}kg ${elec.nome} para ${length}m`);
// Add button to send to budget
const resultDiv = document.getElementById('consumo-result');
const existingButton = resultDiv.querySelector('.add-to-budget-btn');
if (!existingButton) {
const button = document.createElement('button');
button.className = 'btn btn-success add-to-budget-btn';
button.style.marginTop = '16px';
button.textContent = '💰 Adicionar ao Orçamento';
button.onclick = () => addConsumoToOrcamento(totalKg, elec.nome, elec.custo_kg);
resultDiv.querySelector('.result-box').appendChild(button);
}
}
function addConsumoToOrcamento(kg, electrodeNome, custoKg) {
// Switch to orcamento section
showSection('orcamento');
setTimeout(() => {
document.getElementById('budget-category').value = 'consumivel';
updateBudgetTypeOptions();
setTimeout(() => {
document.getElementById('budget-type').value = 'consumiveis';
updateBudgetSpecOptions();
setTimeout(() => {
// Find matching electrode
const electrodeId = electrodeNome.toLowerCase().replace(/[^a-z0-9]/g, '').substring(0, 6);
const specSelect = document.getElementById('budget-spec');
const option = Array.from(specSelect.options).find(opt => opt.value.includes(electrodeId));
if (option) {
specSelect.value = option.value;
autoFillBudgetData();
}
document.getElementById('budget-qty').value = kg.toFixed(2);
updateBudgetTotal();
alert(`✅ Eletrodo transferido para Orçamento!\n\n${electrodeNome}: ${kg.toFixed(2)} kg\n\nClique em Adicionar.`);
}, 200);
}, 200);
}, 300);
}
function gerarDiagramaSequencia() {
const jointType = document.getElementById('seq-joint').value;
const length = parseFloat(document.getElementById('seq-length').value) || 0;
const leg = parseFloat(document.getElementById('seq-leg').value) || 0;
const passes = parseInt(document.getElementById('seq-passes').value) || 1;
const pattern = document.getElementById('seq-pattern').value;
let patternName = '';
let distortionReduction = 0;
let description = '';
switch(pattern) {
case 'skip':
patternName = 'Skip Welding';
distortionReduction = 80;
description = 'Soldagem alternada em segmentos';
break;
case 'backstep':
patternName = 'Backstep Welding';
distortionReduction = 60;
description = 'Soldagem em segmentos na direção oposta';
break;
case 'pulsed':
patternName = 'Pulsado';
distortionReduction = 50;
description = 'Corrente pulsada para controle térmico';
break;
case 'continuous':
patternName = 'Contínuo';
distortionReduction = 0;
description = 'Soldagem contínua sem paradas';
break;
}
const timePerPass = (length / 1000) * 30;
const totalTime = timePerPass * passes;
const skipDiagram = `
<pre style="background: var(--color-surface); padding: 16px; border-radius: 8px; overflow-x: auto; font-size: 11px;">
VISTA SUPERIOR (Plano Vertical):
LADO ESQUERDO (1º Lado):
┌──────────────────────────────┐
│ PASSA 1 (1ª Metade): │
│ ━━━ ━━━ ━━━ ━━━ (Skip) │
│ 1 2 3 4 5 6 7 8 │ ${length}mm
│ [${Math.round(length/8)}mm segmentos, ${Math.round(length/8)}mm espaços] │
│ │
│ PASSA 2 (2ª Metade): │
│ ━━━ ━━━ ━━━ ━━━ (Reverso) │
│ 16 15 14 13 12 11 10 9 │
│ [Preenchimento dos espaços] │
│ │
│ RESULTADO: Distorção mínima ✅ │
└──────────────────────────────┘
LADO DIREITO: [Sequência idêntica]
</pre>
`;
const html = `
<div class="result-box" style="background: var(--color-bg-7); border-left: 4px solid #ec4899;">
<div class="result-title">📐 SEQUÊNCIA DE SOLDAGEM - PLANO VISUAL</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>JUNTA:</strong> ${jointType === 'filete' ? 'Filete Duplo' : jointType === 'topo' ? 'Topo' : 'Angular'} (${length}mm × ${leg}mm × ${passes} passa${passes > 1 ? 's' : ''})<br>
<strong>PADRÃO:</strong> ${patternName} (${description})<br>
<strong>PROCESSO:</strong> ${weldingProcesses[currentWeldProcess].nome}
</div>
${pattern === 'skip' ? skipDiagram : `
<div style="padding: 16px; background: var(--color-surface); border-radius: 8px; text-align: center;">
<strong>Padrão ${patternName}</strong><br>
<p style="margin-top: 12px; color: var(--color-text-secondary);">${description}</p>
</div>
`}
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-1); border-radius: 8px;">
<strong>⏱️ CRONOGRAMA:</strong><br>
Sequência 1º Lado: ${Math.round(totalTime)} min<br>
Sequência 2º Lado: ${Math.round(totalTime)} min<br>
Tempo Total: ${Math.round(totalTime * 2)} min (com pausas)
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-6); border-radius: 8px;">
<strong>📊 ANÁLISE DE DISTORÇÃO:</strong><br><br>
<strong>Método ${patternName}:</strong><br>
- Distorção Angular Esperada: ±${pattern === 'continuous' ? '2.5' : '0.5'}°<br>
- Distorção Longitudinal: ±${pattern === 'continuous' ? '8' : '2'}mm<br>
- Avaliação: ${distortionReduction > 60 ? 'EXCELENTE ✅' : distortionReduction > 40 ? 'BOA ✅' : 'NÃO RECOMENDADO ⚠️'}<br><br>
${pattern !== 'continuous' ? `
<strong>vs Método Contínuo (sem otimização):</strong><br>
- Distorção Angular: ±2.5° ⚠️<br>
- Distorção Longitudinal: ±8mm ⚠️<br>
- Avaliação: NÃO RECOMENDADO<br><br>
` : ''}
<strong>✅ VANTAGENS ${patternName.toUpperCase()}:</strong><br>
1. Reduz distorções em ${distortionReduction}%<br>
2. Controla melhor a temperatura<br>
3. Facilita inspeção entre passes<br>
4. Reduz stress residual
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px; border: 2px solid var(--color-primary);">
<strong>🔧 INSTRUÇÕES PARA SOLDADOR:</strong><br>
1. Marcar posições com giz (0, ${Math.round(length/8)}, ${Math.round(length/4)}...)<br>
2. Soldar segmentos 1-8 (1ª passa)<br>
3. Aguardar resfriamento (espaços resfriem)<br>
4. Soldar segmentos 9-16 (preencher vazios)<br>
5. Controlar temperatura: 150-200°C (interpass)<br>
6. Inspeção visual entre passes
</div>
</div>
`;
document.getElementById('sequencia-result').innerHTML = html;
addToHistory('Sequência Soldagem', `${patternName}, ${length}mm, ${passes} passes`);
}
function buscarPadraoIdeal() {
const app = document.getElementById('padrao-app').value;
const criticality = document.getElementById('padrao-criticality').value;
const env = document.getElementById('padrao-env').value;
let standardClass = 'B';
let electrode = 'E7018';
let passes = 2;
let leg = 4;
let preheat = 100;
let inspection = 'Visual 100% + Ultrassom 10%';
let costIndex = 140;
if (criticality === 'baixa') {
standardClass = 'A';
electrode = 'E6013';
passes = 1;
leg = 3;
preheat = 60;
inspection = 'Visual 100%';
costIndex = 100;
} else if (criticality === 'critica' || app === 'ponte' || app === 'offshore') {
standardClass = 'C';
electrode = 'E8018';
passes = 3;
leg = 6;
preheat = 125;
inspection = 'Visual 100% + UT 100% + RT 20%';
costIndex = 200;
}
const elec = weldingElectrodes[electrode.toLowerCase()];
const consumptionPerMeter = (leg * leg * 0.5 * 1000) / 1000000 * 7.85 / elec.rendimento * 1.2;
const timePerMeter = (consumptionPerMeter / elec.taxa_deposicao) * 60;
const costPerMeter = consumptionPerMeter * elec.custo_kg + (timePerMeter / 60) * 60;
const html = `
<div class="result-box" style="background: var(--color-bg-8); border-left: 4px solid #06b6d4;">
<div class="result-title">📋 PADRÕES DE SOLDA POR APLICAÇÃO</div>
<div style="margin-bottom: 20px; padding: 16px; background: var(--color-surface); border-radius: 8px;">
<strong>APLICAÇÃO:</strong> ${app === 'edificio' ? 'Edifício Múltiplos Andares' : app === 'ponte' ? 'Ponte Rodoviária' : app === 'industrial' ? 'Estrutura Industrial' : app === 'tubulacao' ? 'Tubulação de Pressão' : app === 'equipamento' ? 'Equipamento Mecânico' : 'Marinha/Offshore'}<br>
<strong>Criticidade:</strong> ${criticality === 'baixa' ? 'Baixa' : criticality === 'media' ? 'Média' : criticality === 'alta' ? 'Alta' : 'Crítica'} | <strong>Ambiente:</strong> ${env === 'interno' ? 'Interno Seco' : env === 'externo' ? 'Externo Temperado' : env === 'agressivo' ? 'Agressivo/Marinho' : 'Baixas Temperaturas'}<br>
<strong>Norma:</strong> AISC 360-16, AWS D1.1
</div>
<div style="padding: 20px; background: ${standardClass === 'A' ? 'var(--color-bg-2)' : standardClass === 'B' ? 'var(--color-bg-1)' : 'var(--color-bg-6)'}; border-radius: 12px; border: 2px solid var(--color-primary);">
<h3 style="color: var(--color-primary); margin-bottom: 16px;">✅ PADRÃO RECOMENDADO: Classe ${standardClass}</h3>
<strong>Processo:</strong> ${weldingProcesses[currentWeldProcess].nome}<br>
<strong>Eletrodo:</strong> ${electrode} (${elec.tipo})<br>
<strong>Processo Secundário:</strong> ${standardClass === 'C' ? 'SAW (se volume alto)' : 'SMAW padrão'}<br><br>
<strong>ESPECIFICAÇÃO:</strong><br>
• Número de Passes: ${passes}<br>
• Perna Filete: ${leg} mm<br>
• Pré-aquecimento: ${preheat}°C<br>
• Interpass: 150-200°C<br>
• Velocidade: 20-30 cm/min<br>
• Posição: Plana e Horizontal preferida<br>
• Inspeção: ${inspection}<br><br>
<strong>CONSUMO POR METRO LINEAR:</strong><br>
• Eletrodos: ${consumptionPerMeter.toFixed(2)} kg<br>
• Tempo: ${Math.round(timePerMeter)} min/m<br>
• Custo: R$ ${costPerMeter.toFixed(2)}/m (material + mão de obra)<br><br>
<strong>QUALIDADE ESPERADA:</strong><br>
✓ Resistência à tração: >${elec.resistencia_tracao_min} MPa<br>
✓ Alongamento: >${elec.alongamento}%<br>
✓ Charpy (-20°C): >${elec.charpy} J<br>
✓ Dureza ZTA: <260 HV<br><br>
<strong>⚠️ RESTRIÇÕES:</strong><br>
• Não usar em posição overhead sem suporte<br>
• Temperatura mínima: ${env === 'baixatemp' ? '-20' : '-10'}°C<br>
• Não esticar além de 2x o comprimento
</div>
<div style="margin-top: 20px; padding: 16px; background: var(--color-bg-5); border-radius: 8px;">
<strong>📊 ALTERNATIVAS:</strong><br><br>
${standardClass !== 'A' ? `
<strong>⭐ OPÇÃO INFERIOR (Economia):</strong><br>
PADRÃO: Classe A (Soldagem Econômica)<br>
Eletrodo: E6013 (mais barato)<br>
Passes: 1 | Perna: 3mm<br>
Custo: R$ ${(costPerMeter * 0.56).toFixed(2)}/m (${((1 - 0.56) * 100).toFixed(0)}% menos)<br>
⚠️ Tenacidade reduzida - Use em estruturas baixas<br><br>
` : ''}
${standardClass !== 'C' ? `
<strong>🏆 OPÇÃO PREMIUM (Máxima Qualidade):</strong><br>
PADRÃO: Classe C (Soldagem Crítica)<br>
Eletrodo: E8018 (maior tenacidade)<br>
Passes: 3-4 | Perna: 6mm<br>
Processo: SAW (qualidade automática)<br>
Inspeção: Visual 100% + UT 100% + RT 20%<br>
Custo: R$ ${(costPerMeter * 1.89).toFixed(2)}/m (${((1.89 - 1) * 100).toFixed(0)}% mais)<br>
✅ Máxima confiabilidade - Use em pontes/crítico
` : ''}
</div>
</div>
`;
document.getElementById('padrao-result').innerHTML = html;
addToHistory('Padrões Solda', `Classe ${standardClass}, ${electrode}, ${app}`);
}
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 = `
<div class="result-box">
<div class="result-title">Dimensionamento da Solda de Filete</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Perna Calculada</div>
<div class="result-value">${leg.toFixed(2)} mm</div>
</div>
<div class="result-item">
<div class="result-label">Perna Adotada</div>
<div class="result-value">${legCommercial} mm</div>
</div>
<div class="result-item">
<div class="result-label">Garganta Efetiva</div>
<div class="result-value">${throat.toFixed(2)} mm</div>
</div>
<div class="result-item">
<div class="result-label">Número de Passes</div>
<div class="result-value">${passes}</div>
</div>
</div>
<div class="alert alert-success" style="margin-top: 16px;">
<strong>Eletrodo recomendado:</strong> E${Math.round(fy * 1.15)} (resistência compatível com o aço base)
</div>
</div>
`;
addToHistory('Solda de Filete', `Perna ${legCommercial}mm, ${passes} passe(s)`);
}
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 = `
<div class="result-box">
<div class="result-title">Energia de Soldagem (Heat Input)</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Energia</div>
<div class="result-value">${heatInput.toFixed(2)} kJ/mm</div>
</div>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>${interpretation}</strong>
</div>
</div>
`;
addToHistory('Energia de Soldagem', `HI = ${heatInput.toFixed(2)} kJ/mm`);
}
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 = `
<div class="result-box">
<div class="result-title">Consumo de Eletrodos</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Volume de Solda</div>
<div class="result-value">${(volume / 1000).toFixed(1)} cm³</div>
</div>
<div class="result-item">
<div class="result-label">Massa de Solda</div>
<div class="result-value">${mass.toFixed(2)} kg</div>
</div>
<div class="result-item">
<div class="result-label">Consumo Total</div>
<div class="result-value">${consumption.toFixed(2)} kg</div>
</div>
</div>
</div>
`;
addToHistory('Consumo de Eletrodos', `${consumption.toFixed(2)} kg para ${length}m de solda`);
}
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 = `
<div class="result-box">
<div class="result-title">Conversão de Dureza</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">HB (Brinell)</div>
<div class="result-value">${Math.round(HB)}</div>
</div>
<div class="result-item">
<div class="result-label">HRC (Rockwell C)</div>
<div class="result-value">${HRC.toFixed(1)}</div>
</div>
<div class="result-item">
<div class="result-label">HV (Vickers)</div>
<div class="result-value">${Math.round(HV)}</div>
</div>
</div>
<div style="margin-top: 16px; padding: 16px; background: var(--color-bg-6); border-radius: 8px;">
<strong>Estimativa de Resistência:</strong><br>
fu ≈ ${fu.toFixed(0)} MPa<br>
fy ≈ ${fy.toFixed(0)} MPa (aproximado)
</div>
</div>
`;
}
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 = `
<div class="card">
<div class="card-title">Curva de Transição Dúctil-Frágil</div>
<div class="chart-container">
<canvas id="charpy-chart"></canvas>
</div>
${ttdf !== null ? `
<div class="alert alert-success" style="margin-top: 16px;">
<strong>TTDF (Temperatura de Transição):</strong> ${ttdf.toFixed(1)}°C<br>
Temperatura onde a energia de impacto = 27J
</div>
` : `
<div class="alert alert-warning" style="margin-top: 16px;">
<strong>Não foi possível calcular TTDF</strong><br>
A curva não intercepta 27J no intervalo medido
</div>
`}
</div>
`;
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`);
}
function gerarChecklistCertificado() {
const norm = document.getElementById('cert-norm').value;
const requirements = certRequirements[norm] || [];
document.getElementById('cert-result').innerHTML = `
<div class="card">
<div class="card-title">Checklist de Requisitos - ${norm.toUpperCase().replace('_', ' ')}</div>
${requirements.map((req, index) => `
<div style="padding: 12px; background: var(--color-background); border-radius: 8px; margin-bottom: 8px; display: flex; align-items: center; gap: 12px;">
<input type="checkbox" id="req-${index}" style="width: 20px; height: 20px; cursor: pointer;">
<label for="req-${index}" style="cursor: pointer; flex: 1;">${req}</label>
</div>
`).join('')}
</div>
`;
}
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 = `
<div class="result-box">
<div class="result-title">Área de Pintura</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Área Unitária</div>
<div class="result-value">${area.toFixed(2)} m²</div>
</div>
<div class="result-item">
<div class="result-label">Área Total</div>
<div class="result-value">${totalArea.toFixed(2)} m²</div>
</div>
</div>
</div>
`;
document.getElementById('tinta-area').value = totalArea.toFixed(2);
addToHistory('Área de Pintura', `${totalArea.toFixed(2)}m² (${qty} unidades)`);
// Add button to send to budget
const resultDiv = document.getElementById('paint-area-result');
const existingButton = resultDiv.querySelector('.add-to-budget-btn');
if (!existingButton) {
const button = document.createElement('button');
button.className = 'btn btn-success add-to-budget-btn';
button.style.marginTop = '16px';
button.textContent = '💰 Adicionar ao Orçamento';
button.onclick = () => addAreaPinturaToOrcamento(totalArea, type, dim1, dim2);
resultDiv.querySelector('.result-box').appendChild(button);
}
}
function addAreaPinturaToOrcamento(area, type, dim1, dim2) {
// Switch to orcamento section
showSection('orcamento');
// Set values
setTimeout(() => {
document.getElementById('budget-category').value = 'servico';
updateBudgetTypeOptions();
setTimeout(() => {
const qtyInput = document.getElementById('budget-qty');
const priceInput = document.getElementById('budget-price');
const unitInput = document.getElementById('budget-unit');
qtyInput.value = area.toFixed(2);
unitInput.value = 'm²';
priceInput.value = '40.00';
priceInput.removeAttribute('readonly');
priceInput.style.background = 'var(--color-surface)';
updateBudgetTotal();
alert(`✅ Dados transferidos para Orçamento!\n\nÁrea: ${area.toFixed(2)}\n\nAjuste o preço e clique em Adicionar.`);
}, 200);
}, 300);
}
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 = `
<div class="result-box">
<div class="result-title">Consumo de Tinta</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Volume Teórico</div>
<div class="result-value">${volumeTheoretical.toFixed(2)} L</div>
</div>
<div class="result-item">
<div class="result-label">Volume por Demão</div>
<div class="result-value">${volumePerCoat.toFixed(2)} L</div>
</div>
<div class="result-item">
<div class="result-label">Volume Total</div>
<div class="result-value">${volumeTotal.toFixed(2)} L</div>
</div>
<div class="result-item">
<div class="result-label">Custo Total</div>
<div class="result-value">R$ ${totalCost.toFixed(2)}</div>
</div>
</div>
</div>
`;
addToHistory('Consumo de Tinta', `${volumeTotal.toFixed(2)}L para ${area}`);
}
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 = `
<div class="result-box">
<div class="result-title">Galvanização a Quente</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Taxa de Corrosão</div>
<div class="result-value">${rate.toFixed(1)} μm/ano</div>
</div>
<div class="result-item">
<div class="result-label">Vida Útil Estimada</div>
<div class="result-value">${lifeYears.toFixed(0)} anos</div>
</div>
<div class="result-item">
<div class="result-label">Consumo de Zinco</div>
<div class="result-value">${zincMass.toFixed(2)} kg</div>
</div>
<div class="result-item">
<div class="result-label">Custo Estimado</div>
<div class="result-value">R$ ${(zincCost + area * 180).toFixed(2)}</div>
</div>
</div>
<div class="alert alert-success" style="margin-top: 16px;">
<strong>Normas aplicáveis:</strong> ASTM A123, ISO 1461, NBR 6323
</div>
</div>
`;
addToHistory('Galvanização', `${area}m², ${thickness}μm → ${lifeYears.toFixed(0)} anos`);
}
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 atualizarTabelaOrcamentoV2() {
const tbody = document.getElementById('budget-tbody');
if (appState.budgetItems.length === 0) {
tbody.innerHTML = '<tr><td colspan="8" style="text-align: center; color: var(--color-text-secondary);">Nenhum item adicionado</td></tr>';
} else {
// Group by category
const grouped = {
material: [],
servico: [],
consumivel: [],
indireto: []
};
appState.budgetItems.forEach(item => {
grouped[item.category].push(item);
});
let html = '';
let itemNumber = 1;
Object.keys(grouped).forEach(cat => {
if (grouped[cat].length > 0) {
const catName = {
material: 'MATERIAIS',
servico: 'SERVIÇOS',
consumivel: 'CONSUMÍVEIS',
indireto: 'INDIRETOS'
}[cat];
html += `<tr style="background: var(--color-primary); color: var(--color-btn-primary-text); font-weight: bold;">
<td colspan="8" style="padding: 12px;">📁 ${catName}</td>
</tr>`;
grouped[cat].forEach(item => {
html += `
<tr style="border-bottom: 1px solid var(--color-border);">
<td style="padding: 10px;">${itemNumber++}</td>
<td>${item.category.toUpperCase()}</td>
<td><strong>${item.spec}</strong></td>
<td>${item.qty.toFixed(2)}</td>
<td>${item.unit}</td>
<td>R$ ${item.price.toFixed(2)}</td>
<td style="font-weight: bold; color: var(--color-success);">R$ ${item.total.toFixed(2)}</td>
<td><button class="btn btn-secondary" style="padding: 6px 12px; font-size: 12px;" onclick="removerItemOrcamento(${item.id})">🗑️</button></td>
</tr>
`;
});
}
});
tbody.innerHTML = html;
}
atualizarTotalOrcamentoV2();
}
function atualizarTabelaOrcamento() {
// Legacy function - redirect to new version
atualizarTabelaOrcamentoV2();
}
function atualizarTotalOrcamentoV2() {
// Calculate subtotals by category
const grouped = {
material: 0,
servico: 0,
consumivel: 0,
indireto: 0
};
appState.budgetItems.forEach(item => {
grouped[item.category] += item.total;
});
const subtotal = Object.values(grouped).reduce((sum, val) => sum + val, 0);
const bdi = parseFloat(document.getElementById('budget-bdi').value) || 25;
const bdiValue = subtotal * (bdi / 100);
const total = subtotal + bdiValue;
const resultDiv = document.getElementById('budget-total');
resultDiv.innerHTML = `
<div class="result-box" style="background: var(--color-bg-3); border-left: 4px solid var(--color-success);">
<div class="result-title">📊 RESUMO FINANCEIRO</div>
<div style="padding: 16px; background: var(--color-surface); border-radius: 8px; margin-bottom: 16px;">
<strong>Subtotais por Categoria:</strong><br><br>
${grouped.material > 0 ? `<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span>📦 Materiais:</span>
<strong>R$ ${grouped.material.toFixed(2)}</strong>
</div>` : ''}
${grouped.servico > 0 ? `<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span>🔧 Serviços:</span>
<strong>R$ ${grouped.servico.toFixed(2)}</strong>
</div>` : ''}
${grouped.consumivel > 0 ? `<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span>🧰 Consumíveis:</span>
<strong>R$ ${grouped.consumivel.toFixed(2)}</strong>
</div>` : ''}
${grouped.indireto > 0 ? `<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span>💼 Indiretos:</span>
<strong>R$ ${grouped.indireto.toFixed(2)}</strong>
</div>` : ''}
<hr style="margin: 12px 0; border: 1px solid var(--color-border);">
<div style="display: flex; justify-content: space-between; font-size: 16px;">
<span><strong>Subtotal Geral:</strong></span>
<strong style="color: var(--color-primary);">R$ ${subtotal.toFixed(2)}</strong>
</div>
</div>
<div style="padding: 16px; background: var(--color-bg-2); border-radius: 8px; margin-bottom: 16px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
<span>BDI (${bdi}%):</span>
<strong>R$ ${bdiValue.toFixed(2)}</strong>
</div>
</div>
<div style="padding: 24px; background: var(--color-bg-3); border-radius: 12px; border: 3px solid var(--color-success); text-align: center;">
<div style="font-size: 14px; color: var(--color-text-secondary); margin-bottom: 8px;">TOTAL DO ORÇAMENTO</div>
<div style="font-size: 42px; font-weight: bold; color: var(--color-success);">R$ ${total.toFixed(2)}</div>
</div>
<div style="margin-top: 20px; display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;">
<button class="btn btn-primary" onclick="gerarAnaliseDetalhada()" style="padding: 12px 24px;">📊 Análise Detalhada</button>
<button class="btn btn-primary" onclick="gerarPDFOrcamento()" style="padding: 12px 24px;">📄 Gerar PDF</button>
<button class="btn btn-success" onclick="salvarOrcamento()" style="padding: 12px 24px;">💾 Salvar Orçamento</button>
<button class="btn btn-secondary" onclick="limparOrcamento()" style="padding: 12px 24px;">🗑️ Limpar Tudo</button>
</div>
</div>
`;
}
function atualizarTotalOrcamento() {
// Legacy function - redirect to new version
atualizarTotalOrcamentoV2();
}
function gerarPDFOrcamento() {
const project = document.getElementById('budget-project').value || 'Projeto Sem Nome';
const date = document.getElementById('budget-date').value || '2025-11-07';
const region = document.getElementById('budget-region').value;
alert(`📄 Gerando PDF do Orçamento:\n\nProjeto: ${project}\nData: ${date}\nRegião: ${region}\n\nTotal de Itens: ${appState.budgetItems.length}\n\nEm ambiente real, isto geraria um PDF profissional.`);
addToHistory('PDF Orçamento', `${project} - ${appState.budgetItems.length} itens`);
}
function salvarOrcamento() {
const project = document.getElementById('budget-project').value || 'Projeto Sem Nome';
alert(`💾 Orçamento "${project}" salvo com sucesso!\n\nTotal: R$ ${appState.budgetItems.reduce((sum, item) => sum + item.total, 0).toFixed(2)}`);
addToHistory('Orçamento Salvo', project);
}
function limparOrcamento() {
if (confirm('⚠️ Deseja realmente limpar todo o orçamento?')) {
appState.budgetItems = [];
atualizarTabelaOrcamentoV2();
alert('✅ Orçamento limpo!');
}
}
function gerarAnaliseDetalhada() {
if (appState.budgetItems.length === 0) {
alert('⚠️ Adicione itens ao orçamento primeiro!');
return;
}
// Calculate by category
const grouped = {
material: 0,
servico: 0,
consumivel: 0,
indireto: 0
};
appState.budgetItems.forEach(item => {
grouped[item.category] += item.total;
});
const subtotal = Object.values(grouped).reduce((sum, val) => sum + val, 0);
const bdi = parseFloat(document.getElementById('budget-bdi').value) || 25;
const total = subtotal * (1 + bdi / 100);
// Percentages
const percMaterial = (grouped.material / subtotal) * 100;
const percServico = (grouped.servico / subtotal) * 100;
const percConsumivel = (grouped.consumivel / subtotal) * 100;
const percIndireto = (grouped.indireto / subtotal) * 100;
// Estimate project area (rough estimate)
const estimatedArea = 1500; // m²
const costPerM2 = total / estimatedArea;
// Timeline estimate
const weeks = Math.ceil(appState.budgetItems.length / 2) + 2;
const html = `
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 2000; display: flex; align-items: center; justify-content: center; padding: 20px;" onclick="this.remove()">
<div style="background: var(--color-surface); border-radius: 16px; padding: 32px; max-width: 900px; max-height: 90vh; overflow-y: auto; box-shadow: var(--shadow-lg);" onclick="event.stopPropagation()">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px;">
<h2 style="color: var(--color-primary); font-size: 28px;">📊 ANÁLISE DETALHADA DO ORÇAMENTO</h2>
<button onclick="this.closest('div[style*=fixed]').remove()" style="background: none; border: none; font-size: 32px; cursor: pointer; color: var(--color-text-secondary);">×</button>
</div>
<div style="padding: 20px; background: var(--color-bg-1); border-radius: 12px; margin-bottom: 20px;">
<h3 style="margin-bottom: 16px; color: var(--color-primary);">Composição por Categoria</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
${grouped.material > 0 ? `<div style="padding: 12px; background: var(--color-surface); border-radius: 8px;">
<div style="font-size: 12px; color: var(--color-text-secondary);">Materiais</div>
<div style="font-size: 24px; font-weight: bold; color: var(--color-success);">${percMaterial.toFixed(0)}%</div>
<div style="font-size: 14px;">R$ ${grouped.material.toFixed(2)}</div>
</div>` : ''}
${grouped.servico > 0 ? `<div style="padding: 12px; background: var(--color-surface); border-radius: 8px;">
<div style="font-size: 12px; color: var(--color-text-secondary);">Serviços</div>
<div style="font-size: 24px; font-weight: bold; color: var(--color-warning);">${percServico.toFixed(0)}%</div>
<div style="font-size: 14px;">R$ ${grouped.servico.toFixed(2)}</div>
</div>` : ''}
${grouped.consumivel > 0 ? `<div style="padding: 12px; background: var(--color-surface); border-radius: 8px;">
<div style="font-size: 12px; color: var(--color-text-secondary);">Consumíveis</div>
<div style="font-size: 24px; font-weight: bold; color: var(--color-info);">${percConsumivel.toFixed(0)}%</div>
<div style="font-size: 14px;">R$ ${grouped.consumivel.toFixed(2)}</div>
</div>` : ''}
${grouped.indireto > 0 ? `<div style="padding: 12px; background: var(--color-surface); border-radius: 8px;">
<div style="font-size: 12px; color: var(--color-text-secondary);">Indiretos</div>
<div style="font-size: 24px; font-weight: bold; color: var(--color-text);">${percIndireto.toFixed(0)}%</div>
<div style="font-size: 14px;">R$ ${grouped.indireto.toFixed(2)}</div>
</div>` : ''}
</div>
</div>
<div style="padding: 20px; background: var(--color-bg-3); border-radius: 12px; margin-bottom: 20px;">
<h3 style="margin-bottom: 16px; color: var(--color-success);">Custo por Área</h3>
<p>Considerando área estimada de <strong>${estimatedArea} m²</strong>:</p>
<div style="font-size: 32px; font-weight: bold; color: var(--color-success); margin: 12px 0;">R$ ${costPerM2.toFixed(2)}/m²</div>
<p style="font-size: 12px; color: var(--color-text-secondary);">Este valor é uma média estimada baseada no orçamento total</p>
</div>
<div style="padding: 20px; background: var(--color-bg-6); border-radius: 12px; margin-bottom: 20px;">
<h3 style="margin-bottom: 16px; color: var(--color-warning);">Cronograma Estimado</h3>
<ul style="list-style: none; padding: 0;">
<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">✅ Semana 1: Fornecimento de Materiais</li>
<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">✅ Semana 2-${Math.min(weeks-2, 3)}: Fabricação</li>
<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">✅ Semana ${Math.min(weeks-1, 4)}-${weeks}: Montagem e Soldagem</li>
<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">✅ Semana ${weeks+1}: Pintura e Acabamento</li>
<li style="padding: 8px 0;">✅ Semana ${weeks+2}: Inspeção Final</li>
</ul>
<p style="margin-top: 12px; font-weight: bold;">Prazo Total Estimado: ${weeks+2} semanas</p>
</div>
<div style="padding: 20px; background: var(--color-bg-5); border-radius: 12px;">
<h3 style="margin-bottom: 16px; color: #a855f7;">Fornecedores Envolvidos</h3>
<ul style="list-style: none; padding: 0;">
${grouped.material > 0 ? '<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">🏭 <strong>Gerdau/Usiminas</strong> - Perfis e Chapas</li>' : ''}
${grouped.consumivel > 0 && appState.budgetItems.some(i => i.spec.includes('E70') || i.spec.includes('E60')) ? '<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">🔥 <strong>Esab/Lincoln</strong> - Eletrodos</li>' : ''}
${grouped.consumivel > 0 && appState.budgetItems.some(i => i.spec.includes('TINTA')) ? '<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">🎨 <strong>Sherwin-Williams/Coral</strong> - Tintas</li>' : ''}
${grouped.consumivel > 0 && appState.budgetItems.some(i => i.spec.includes('Parafuso')) ? '<li style="padding: 8px 0; border-bottom: 1px solid var(--color-border);">🔩 <strong>Distribuidores Locais</strong> - Parafusos</li>' : ''}
${grouped.servico > 0 ? '<li style="padding: 8px 0;">👷 <strong>Mão de Obra Especializada</strong> - Soldadores e Montadores</li>' : ''}
</ul>
</div>
<div style="text-align: center; margin-top: 24px;">
<button class="btn btn-primary" onclick="this.closest('div[style*=fixed]').remove()" style="padding: 12px 32px;">Fechar Análise</button>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', html);
addToHistory('Análise Orçamento', `${appState.budgetItems.length} itens, R$ ${total.toFixed(2)}`);
}
function carregarOrcamentoExemplo() {
if (appState.budgetItems.length > 0) {
if (!confirm('Já existem itens no orçamento. Deseja substituí-los com o exemplo?')) {
return;
}
}
// Clear existing items
appState.budgetItems = [];
// Example budget items
const exampleItems = [
{id: Date.now() + 1, category: 'material', type: 'perfil_w', spec: 'W250×38', qty: 50, unit: 'm', price: 285, total: 14250},
{id: Date.now() + 2, category: 'material', type: 'chapa', spec: 'CHAPA 9.5mm', qty: 200, unit: 'm²', price: 74.6, total: 14920},
{id: Date.now() + 3, category: 'material', type: 'cantoneira', spec: 'L100×100×10', qty: 80, unit: 'm', price: 112.5, total: 9000},
{id: Date.now() + 4, category: 'consumivel', type: 'consumiveis', spec: 'E7018 (Eletrodo)', qty: 50, unit: 'kg', price: 45, total: 2250},
{id: Date.now() + 5, category: 'consumivel', type: 'consumiveis', spec: 'TINTA C3 Epóxi', qty: 100, unit: 'L', price: 80, total: 8000},
{id: Date.now() + 6, category: 'consumivel', type: 'parafusos', spec: 'Parafuso A325 M16', qty: 200, unit: 'un', price: 1.20, total: 240},
{id: Date.now() + 7, category: 'servico', type: 'servico_custom', spec: 'Soldagem', qty: 1000, unit: 'h', price: 65, total: 65000},
{id: Date.now() + 8, category: 'servico', type: 'servico_custom', spec: 'Pintura', qty: 500, unit: 'm²', price: 40, total: 20000},
{id: Date.now() + 9, category: 'indireto', type: 'indireto_custom', spec: 'Transporte', qty: 1, unit: 'un', price: 5000, total: 5000},
{id: Date.now() + 10, category: 'indireto', type: 'indireto_custom', spec: 'EPI e Segurança', qty: 1, unit: 'un', price: 2000, total: 2000}
];
appState.budgetItems = exampleItems;
atualizarTabelaOrcamentoV2();
alert('✅ Orçamento exemplo carregado com sucesso!\n\n10 itens adicionados\nTotal: R$ 140.660,00');
}
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 = `
<div class="result-box">
<div class="result-title">Cálculo de Peso</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Peso Total</div>
<div class="result-value">${weight.toFixed(2)} kg</div>
</div>
</div>
</div>
`;
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 = `
<div class="result-box">
<div class="result-title">Plano de Rigging</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label">Força por Cabo</div>
<div class="result-value">${forcePerCable.toFixed(1)} kN</div>
</div>
<div class="result-item">
<div class="result-label">Ângulo</div>
<div class="result-value">${angle}°</div>
</div>
<div class="result-item">
<div class="result-label">Fator Segurança</div>
<div class="result-value">${fs}</div>
</div>
</div>
<div class="alert ${alertClass}" style="margin-top: 16px;">
<strong>Recomendação: ${recommendation}</strong>
</div>
</div>
`;
addToHistory('Rigging', `${weight}kg, ${points} pontos, ${angle}° → ${forcePerCable.toFixed(1)}kN/cabo`);
}
// ========================================
// BUDGET v6.6 FUNCTIONS WITH CSV INTEGRATION
// ========================================
function updateBudgetTypeOptions() {
const category = document.getElementById('budget-category').value;
const typeSelect = document.getElementById('budget-type');
let options = '<option value="">Selecione...</option>';
if (category === 'material') {
options += '<option value="perfil_w">Perfil W</option>';
options += '<option value="perfil_i">Perfil I (IPE)</option>';
options += '<option value="perfil_hp">Perfil HP</option>';
options += '<option value="cantoneira">Cantoneira</option>';
options += '<option value="tubo_circ">Tubo Circular</option>';
options += '<option value="tubo_rhs">Tubo Retangular (RHS)</option>';
options += '<option value="chapa">Chapa</option>';
options += '<option value="barra">Barra Redonda</option>';
} else if (category === 'consumivel') {
options += '<option value="eletrodo">Eletrodos</option>';
options += '<option value="parafuso">Parafusos</option>';
options += '<option value="tinta">Tintas</option>';
} else if (category === 'servico') {
options += '<option value="servico_custom">Serviço Customizado</option>';
} else if (category === 'indireto') {
options += '<option value="indireto_custom">Custo Indireto</option>';
}
typeSelect.innerHTML = options;
updateBudgetSpecOptions();
}
async function updateBudgetSpecOptions() {
const type = document.getElementById('budget-type').value;
const specSelect = document.getElementById('budget-spec');
const productInfo = document.getElementById('product-info-display');
specSelect.innerHTML = '<option value="">Selecione...</option>';
productInfo.style.display = 'none';
if (!type || type.includes('custom')) {
return;
}
// Show loading state
specSelect.innerHTML = '<option value="">Carregando...</option>';
// Load data from CSV
const dados = await carregarCSV(type);
specSelect.innerHTML = '<option value="">Selecione...</option>';
dados.forEach(item => {
const option = document.createElement('option');
option.value = item.id;
option.textContent = item.nome;
option.dataset.itemData = JSON.stringify(item);
specSelect.appendChild(option);
});
if (dados.length === 0) {
specSelect.innerHTML = '<option value="">Nenhum item encontrado</option>';
}
}
function autoFillBudgetData() {
const specSelect = document.getElementById('budget-spec');
const selectedOption = specSelect.options[specSelect.selectedIndex];
if (!selectedOption || !selectedOption.value) {
document.getElementById('product-info-display').style.display = 'none';
return;
}
const itemData = JSON.parse(selectedOption.dataset.itemData || '{}');
const type = document.getElementById('budget-type').value;
const region = document.getElementById('budget-region').value;
// Display product info
const productDetails = document.getElementById('product-details');
const productInfo = document.getElementById('product-info-display');
let detailsHtml = `<strong>${itemData.nome}</strong><br>`;
if (itemData.peso_kg_m) {
detailsHtml += `Peso: ${itemData.peso_kg_m} kg/m<br>`;
}
if (itemData.altura_mm) {
detailsHtml += `Altura: ${itemData.altura_mm} mm<br>`;
}
if (itemData.diametro_mm) {
detailsHtml += `Diâmetro: ${itemData.diametro_mm} mm<br>`;
}
if (itemData.espessura_mm) {
detailsHtml += `Espessura: ${itemData.espessura_mm} mm<br>`;
}
productDetails.innerHTML = detailsHtml;
productInfo.style.display = 'block';
// Auto-fill unit
const unitInput = document.getElementById('budget-unit');
unitInput.value = itemData.unidade || 'm';
// Calculate and fill price
const priceInput = document.getElementById('budget-price');
let price = 0;
if (itemData.custo_kg) {
price = parseFloat(itemData.custo_kg);
} else if (itemData.custo_unitario_r) {
price = parseFloat(itemData.custo_unitario_r);
} else if (itemData.custo_litro_r) {
price = parseFloat(itemData.custo_litro_r);
} else if (itemData.peso_kg_m && regionalPricing[region]) {
const categoryKey = type.replace('perfil_', '').replace('tubo_', '');
const pricePerKg = regionalPricing[region][type] || regionalPricing[region][categoryKey] || 7.5;
price = parseFloat(itemData.peso_kg_m) * pricePerKg;
}
priceInput.value = price.toFixed(2);
priceInput.removeAttribute('readonly');
priceInput.style.background = 'var(--color-surface)';
updateBudgetTotal();
}
function updateBudgetTotal() {
const qty = parseFloat(document.getElementById('budget-qty').value) || 0;
const price = parseFloat(document.getElementById('budget-price').value) || 0;
const total = qty * price;
document.getElementById('budget-item-total').value = `R$ ${total.toFixed(2)}`;
}
function adicionarItemOrcamentoV2() {
const category = document.getElementById('budget-category').value;
const type = document.getElementById('budget-type').value;
const specSelect = document.getElementById('budget-spec');
const spec = specSelect.options[specSelect.selectedIndex]?.text || 'Item Customizado';
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 (!type || qty <= 0 || price <= 0) {
alert('⚠️ Preencha todos os campos corretamente:\n\n- Tipo de Produto\n- Quantidade > 0\n- Preço > 0');
return;
}
const item = {
id: Date.now(),
category: category,
type: type,
spec: spec,
qty: qty,
unit: unit,
price: price,
total: qty * price
};
appState.budgetItems.push(item);
atualizarTabelaOrcamentoV2();
// Clear form
document.getElementById('budget-spec').value = '';
document.getElementById('budget-qty').value = '1';
document.getElementById('budget-price').value = '0';
document.getElementById('product-info-display').style.display = 'none';
alert('✅ Item adicionado ao orçamento com sucesso!');
}
function updateRegionalPricing() {
// Trigger price recalculation when region changes
const specSelect = document.getElementById('budget-spec');
if (specSelect && specSelect.value) {
autoFillBudgetData();
}
}
// Initialize budget on load
function initializeBudget() {
if (document.getElementById('budget-region')) {
updateBudgetTypeOptions();
updateBudgetSpecOptions();
}
}
// Admin Modal Functions
function openAdminModal() {
const modal = document.getElementById('adminModal');
modal.classList.add('active');
// Load current config
document.getElementById('adminAppName').value = adminConfig.appName;
document.getElementById('adminAppSubtitle').value = adminConfig.appSubtitle;
document.getElementById('adminFooterText').value = adminConfig.footerText;
document.getElementById('adminThemeDefault').value = adminConfig.themeDefault;
document.getElementById('adminModeDefault').value = adminConfig.modeDefault;
// Set tool checkboxes
document.querySelectorAll('.admin-tools-grid input[type="checkbox"]').forEach(input => {
const sectionId = input.value;
input.checked = adminConfig.toolsVisibility[sectionId] || false;
});
}
function closeAdminModal() {
document.getElementById('adminModal').classList.remove('active');
}
function saveAdminConfig() {
// Save branding
adminConfig.appName = document.getElementById('adminAppName').value;
adminConfig.appSubtitle = document.getElementById('adminAppSubtitle').value;
adminConfig.footerText = document.getElementById('adminFooterText').value;
adminConfig.themeDefault = document.getElementById('adminThemeDefault').value;
adminConfig.modeDefault = document.getElementById('adminModeDefault').value;
// Save tools visibility
document.querySelectorAll('.admin-tools-grid input[type="checkbox"]').forEach(input => {
const sectionId = input.value;
adminConfig.toolsVisibility[sectionId] = input.checked;
});
// Apply changes
applyAdminConfig();
closeAdminModal();
alert('✅ Configurações salvas com sucesso!');
}
function resetAdminDefaults() {
if (confirm('⚠️ Deseja restaurar todas as configurações padrão?')) {
adminConfig.appName = 'AÇO CALC PRO';
adminConfig.appSubtitle = 'Plataforma Técnica com Base de Dados de Materiais Brasileiros';
adminConfig.footerText = '© 2025 AÇO CALC PRO v6.5 PROFESSIONAL EDITION - Plataforma Técnica com Base de Dados de Materiais Brasileiros';
adminConfig.themeDefault = 'escuro';
adminConfig.modeDefault = 'simples';
// Reset visibility to defaults
Object.keys(adminConfig.toolsVisibility).forEach(key => {
adminConfig.toolsVisibility[key] = ['cev', 'seletor', 'parafusos', 'layout', 'preaquecimento', 'dureza', 'charpy', 'area-pintura', 'consumo-tinta', 'custo-pintura', 'orcamento'].includes(key);
});
applyAdminConfig();
openAdminModal(); // Refresh modal
alert('✅ Configurações restauradas!');
}
}
function applyAdminConfig() {
// Update branding elements
const logoEl = document.getElementById('appLogo');
const subtitleEl = document.getElementById('appSubtitle');
const footerEl = document.getElementById('appFooter');
if (logoEl) logoEl.textContent = '🏗️ ' + adminConfig.appName;
if (subtitleEl) subtitleEl.textContent = adminConfig.appSubtitle;
if (footerEl) footerEl.querySelector('p').textContent = adminConfig.footerText;
// Update page title
document.title = '🏗️ ' + adminConfig.appName + ' - Plataforma Técnica';
// Apply theme
if (adminConfig.themeDefault === 'escuro') {
appState.currentTheme = 'dark';
} else {
appState.currentTheme = 'light';
}
applyTheme();
// Apply mode
if (adminConfig.modeDefault === 'expert' && !appState.expertMode) {
toggleExpertMode();
} else if (adminConfig.modeDefault === 'simples' && appState.expertMode) {
toggleExpertMode();
}
// Filter tools
filterToolsByMode();
}
// ========================================
// HELP SYSTEM & USER MANUAL
// ========================================
let currentHelpSection = null;
const ajudaDatabase = {
cev: {
titulo: '⛗️ CEV Avançado (IIW + Pcm)',
oQueE: 'CEV (Carbono Equivalente) é um valor calculado que representa a capacidade de endurecimento de um aço durante a soldagem. Valores mais altos indicam maior dificuldade de soldagem e maior risco de trincas.',
paraQueServe: 'Determinar a dificuldade de soldagem de um aço e recomendar: temperatura de pré-aquecimento necessária, velocidade de soldagem, tipo de eletrodo apropriado e necessidade de PWHT (tratamento térmico pós-soldagem).',
quandoUsar: 'Sempre que for soldar um aço estrutural ou de alta resistência para verificar a soldabilidade e determinar os cuidados necessários antes de iniciar o processo.',
avisos: [
'CEV é apenas um indicador - sempre consulte o fabricante do aço',
'Valores altos (>0.55) requerem rigoroso controle de processo',
'Não substitui ensaios de qualidade na prática',
'Considere ambiente, espessura e restrição da junta'
],
campos: [
{ nome: 'Carbono (C)', unidade: '%', significado: 'Elemento principal que aumenta dureza e reduz ductilidade', intervalo: '0.15-0.35', dica: 'Valores mais altos = mais difícil soldar' },
{ nome: 'Manganês (Mn)', unidade: '%', significado: 'Aumenta resistência e temperabilidade', intervalo: '0.80-1.50', dica: 'Fator multiplicador do carbono' },
{ nome: 'Cromo (Cr)', unidade: '%', significado: 'Aumenta resistência à corrosão e dureza', intervalo: '0.05-0.20', dica: 'Elemento de liga menor' },
{ nome: 'Molibdênio (Mo)', unidade: '%', significado: 'Aumenta temperabilidade', intervalo: '0.02-0.10', dica: 'Forte efeito na temperabilidade' },
{ nome: 'Vanádio (V)', unidade: '%', significado: 'Aumenta resistência e dureza', intervalo: '0.02-0.05', dica: 'Elemento de liga menor' },
{ nome: 'Níquel (Ni)', unidade: '%', significado: 'Aumenta tenacidade e resistência ao impacto', intervalo: '0.05-0.15', dica: 'Melhora ductilidade' },
{ nome: 'Cobre (Cu)', unidade: '%', significado: 'Aumenta resistência à corrosão atmosférica', intervalo: '0.05-0.15', dica: 'Residual do processo' },
{ nome: 'Espessura', unidade: 'mm', significado: 'Quanto mais espesso, maior resfriamento = maior dureza', intervalo: '10-50', dica: 'Chapa mais espessa = maior pré-aquecimento' }
],
resultados: '<h4>CEV IIW (Instituto Internacional de Soldagem)</h4><p><strong>Fórmula:</strong> CEV = C + (Mn/6) + (Cr+Mo+V)/5 + (Ni+Cu)/15</p><p><strong>Interpretação:</strong></p><ul><li>&lt;0.35: Excelente soldabilidade, sem pré-aquecimento</li><li>0.35-0.45: Boa soldabilidade, considerar pré-aquecimento</li><li>0.45-0.55: Soldabilidade moderada, pré-aquecimento necessário</li><li>&gt;0.55: Soldabilidade difícil, controle rigoroso necessário</li></ul>',
referencias: [
{ titulo: 'IIW - Classification of high strength weld metals', ano: 1988, url: 'https://www.iiw.net' },
{ titulo: 'AWS D1.1 - Structural Welding Code', ano: 2020, url: 'https://www.aws.org' },
{ titulo: 'NBR 16239 - Soldagem de Aços', ano: 2013 }
],
manualRelacionado: ['aco_introducao', 'cev_entendimento', 'preaquecimento_guia']
},
preaquecimento: {
titulo: '🔥 Pré-Aquecimento AWS D1.1',
oQueE: 'Pré-aquecimento é o processo de elevar a temperatura do material base antes da soldagem para reduzir a taxa de resfriamento e aumentar a ductilidade, prevenindo trincas.',
paraQueServe: 'Prevenir trincas por resfriamento rápido em aços com alto CEV ou em seções espessas, controlando a formação de estruturas metastabiláveis como martensita.',
quandoUsar: 'Quando o CEV > 0.35, temperatura ambiente < 5°C, espessura > 20mm, ou conforme especificação do projeto.',
avisos: [
'Aplicar pré-aquecimento de forma uniforme em toda a zona afetada pelo calor',
'Medir com termômetro de contato para garantir temperatura correta',
'Manter interpass durante toda a soldagem',
'Não exceder 200°C de temperatura máxima'
],
campos: [
{ nome: 'CEV', unidade: '-', significado: 'Carbono Equivalente do aço', intervalo: '0.2-0.8', dica: 'Calcule com a ferramenta CEV Avançado' },
{ nome: 'Espessura', unidade: 'mm', significado: 'Espessura da chapa ou seção', intervalo: '5-100', dica: 'Seções maiores exigem mais pré-aq' },
{ nome: 'Temperatura Ambiente', unidade: '°C', significado: 'Temperatura do local de soldagem', intervalo: '-10 a 40', dica: 'Frio aumenta necessidade de pré-aq' },
{ nome: 'Tipo de Junta', unidade: '-', significado: 'Configuração da junta', intervalo: 'Simples/Dupla', dica: 'Junta dupla restringe mais' },
{ nome: 'Restrição', unidade: '-', significado: 'Liberdade de movimento do material', intervalo: 'Baixa/Média/Alta', dica: 'Maior restrição = mais pré-aq' }
],
resultados: '<h4>Temperatura de Pré-aquecimento</h4><p><strong>Fórmula AWS D1.1:</strong> T_preaq = 50 + (CEV × 50) + (Espessura/10 × 20)</p><p><strong>Interpass:</strong> Temperatura entre passes: Pré-aq + 25°C (máximo 200°C)</p>',
referencias: [
{ titulo: 'AWS D1.1 - Structural Welding Code - Steel', ano: 2020, url: 'https://www.aws.org' },
{ titulo: 'NBR 8800 - Projeto de estruturas de aço', ano: 2008 }
],
manualRelacionado: ['cev_entendimento', 'soldagem_introducao', 'preaquecimento_guia']
},
parafusos: {
titulo: '🔩 Ligações Parafusadas',
oQueE: 'Ligações parafusadas são conexões mecânicas que utilizam parafusos de alta resistência para transmitir forças entre elementos estruturais.',
paraQueServe: 'Dimensionar conexões seguras e verificar capacidade ao cisalhamento, esmagamento e ruptura em bloco conforme NBR 8800 e AISC 360.',
quandoUsar: 'Quando necessitar de conexões desmontáveis, rápida montagem em campo, ou quando soldagem não é viável.',
avisos: [
'Verificar todos os modos de falha: cisalhamento, esmagamento e bloco',
'Respeitar distâncias mínimas de borda (1.5d)',
'Espaçamento mínimo entre furos (2.67d)',
'Usar torque adequado na instalação'
],
campos: [
{ nome: 'Tipo de Parafuso', unidade: '-', significado: 'Classe de resistência (A325, A490, ISO 8.8, ISO 10.9)', intervalo: 'A325/A490', dica: 'A325 é padrão para estruturas' },
{ nome: 'Diâmetro', unidade: 'mm', significado: 'Diâmetro nominal do parafuso', intervalo: '12-24', dica: 'Diâmetros maiores = maior capacidade' },
{ nome: 'Quantidade', unidade: 'un', significado: 'Número de parafusos na ligação', intervalo: '1-20', dica: 'Distribua uniformemente' },
{ nome: 'Planos de Corte', unidade: '-', significado: 'Quantidade de interfaces cisalhadas', intervalo: '1-2', dica: '2 planos dobra a capacidade' },
{ nome: 'Força Aplicada', unidade: 'kN', significado: 'Força total a ser transmitida', intervalo: '10-500', dica: 'Força de cálculo (fatorada)' }
],
resultados: '<h4>Capacidade ao Cisalhamento</h4><p><strong>Fórmula:</strong> Fv = 0.6 × fy × A × n_planos</p><p>Verifica se capacidade total &gt; força aplicada</p><h4>Verificações Adicionais</h4><ul><li>Esmagamento da chapa</li><li>Ruptura em bloco de cisalhamento</li><li>Distâncias mínimas NBR 8800</li></ul>',
referencias: [
{ titulo: 'NBR 8800 - Projeto de estruturas de aço', ano: 2008 },
{ titulo: 'AISC 360-16 - Specification for Structural Steel Buildings', ano: 2016, url: 'https://www.aisc.org' }
],
manualRelacionado: ['parafusos_basico', 'cisalhamento_analise']
},
'consumo-tinta': {
titulo: '🎯 Consumo de Tinta',
oQueE: 'Consumo de tinta é o volume total (em litros) de tinta necessária para pintar uma área com determinada espessura seca (DFT).',
paraQueServe: 'Calcular a quantidade de tinta para orçamentos e planejar compras de material, considerando perdas e número de demãos.',
quandoUsar: 'Sempre na fase inicial de planejamento de um projeto de pintura, após calcular a área total a pintar.',
avisos: [
'Não esqueça de adicionar perda de 15-25% por respingos e cantos',
'DFT mínimo garante durabilidade adequada',
'Cada demão requer intervalo mínimo antes da próxima',
'Verifique % de sólidos na ficha técnica da tinta'
],
campos: [
{ nome: 'Área Total', unidade: 'm²', significado: 'Área a pintar', intervalo: '10-10000', dica: 'Use ferramenta de cálculo de área antes' },
{ nome: 'DFT', unidade: 'μm', significado: 'Dry Film Thickness - Espessura da película seca', intervalo: '80-250', dica: 'Confira norma ISO 12944 para sua aplicação' },
{ nome: '% Sólidos', unidade: '%', significado: 'Percentual de sólidos na tinta', intervalo: '30-95', dica: 'Tipicamente 60% para epóxis' },
{ nome: 'Número de Demãos', unidade: '-', significado: 'Quantas camadas serão aplicadas', intervalo: '1-4', dica: 'Mais camadas = melhor proteção' },
{ nome: 'Perdas', unidade: '%', significado: 'Percentual de perda por respingos e cantos', intervalo: '5-25', dica: 'Tipicamente 15%' }
],
resultados: '<h4>Cálculo do Volume</h4><p><strong>V_teórico = (DFT × Área) / (1000 × % Sólidos)</strong></p><p><strong>V_com_perdas = V_teórico / (1 - % Perdas)</strong></p><p><strong>V_total = V_com_perdas × Número de Demãos</strong></p>',
referencias: [
{ titulo: 'ISO 12944 - Paints and Coatings - Corrosion Protection', ano: 2018, url: 'https://www.iso.org' },
{ titulo: 'ASTM D3276 - Standard Practice for Paint Application', ano: 2021 }
],
manualRelacionado: ['pintura_introducao', 'iso12944']
},
dureza: {
titulo: '🔨 Conversor de Dureza',
oQueE: 'Conversor que transforma valores entre diferentes escalas de dureza (Brinell, Rockwell C e Vickers) usando correlações normativas.',
paraQueServe: 'Permitir comparação de valores de dureza medidos em diferentes escalas e estimar propriedades mecânicas do material.',
quandoUsar: 'Quando tiver medida em uma escala e precisar converter para outra, ou quando quiser estimar resistência a partir da dureza.',
avisos: [
'Conversões são aproximadas, use como referência',
'Para aços carbonos, conversões são mais precisas',
'HRC só é válido para HB > 200',
'Estimativas de resistência são aproximadas'
],
campos: [
{ nome: 'Brinell (HB)', unidade: 'HB', significado: 'Dureza Brinell - teste com esfera', intervalo: '100-650', dica: 'Mais comum em certificados' },
{ nome: 'Rockwell C (HRC)', unidade: 'HRC', significado: 'Dureza Rockwell C - teste com cone de diamante', intervalo: '20-70', dica: 'Comum em ferramentas' },
{ nome: 'Vickers (HV)', unidade: 'HV', significado: 'Dureza Vickers - teste com pirâmide', intervalo: '100-1000', dica: 'Versátil para todos os materiais' }
],
resultados: '<h4>Conversões</h4><p><strong>HRC = HB × 0.0338 - 9.8</strong></p><p><strong>HV = HB × 0.95</strong></p><h4>Estimativa de Resistência</h4><p><strong>fu ≈ HB × 10 MPa</strong></p>',
referencias: [
{ titulo: 'ASTM E140 - Hardness Conversion Tables', ano: 2019 },
{ titulo: 'ISO 18265 - Conversion of hardness values', ano: 2013 }
],
manualRelacionado: ['ensaios_introducao', 'dureza_escalas']
},
charpy: {
titulo: '📉 Análise de Charpy',
oQueE: 'Análise que gera a curva de transição dúctil-frágil a partir de ensaios de impacto Charpy em diferentes temperaturas.',
paraQueServe: 'Determinar a temperatura de transição dúctil-frágil (TTDF) e avaliar se o material é adequado para serviço em baixas temperaturas.',
quandoUsar: 'Para estruturas que operam em baixas temperaturas, estruturas offshore, pontes em regiões frias, ou quando especificado em projeto.',
avisos: [
'Insira pelo menos 2 pontos temperatura/energia',
'Ideal: 4 pontos cobrindo ampla faixa de temperatura',
'TTDF ideal deve ser menor que temperatura de serviço',
'Energia mínima 27J @ temperatura de projeto'
],
campos: [
{ nome: 'Temperatura', unidade: '°C', significado: 'Temperatura do ensaio Charpy', intervalo: '-60 a +40', dica: 'Cubra ampla faixa de temperatura' },
{ nome: 'Energia', unidade: 'J', significado: 'Energia absorvida no impacto', intervalo: '5-150', dica: 'Valores altos = mais tenáz' }
],
resultados: '<h4>Curva de Transição</h4><p>Gráfico mostra como energia absorvida varia com temperatura</p><p><strong>TTDF (27J):</strong> Temperatura onde energia = 27J</p><p>Material é dúctil acima da TTDF e frágil abaixo</p>',
referencias: [
{ titulo: 'ASTM E23 - Standard Test Methods for Notched Bar Impact Testing', ano: 2018, url: 'https://www.astm.org' },
{ titulo: 'ISO 148-1 - Charpy pendulum impact test', ano: 2016 }
],
manualRelacionado: ['ensaios_introducao', 'impacto_charpy']
},
orcamento: {
titulo: '💵 Orçamento Detalhado',
oQueE: 'Sistema completo de orçamento com base de dados integrada de materiais brasileiros (100+ produtos) e preços regionais.',
paraQueServe: 'Criar orçamentos detalhados de projetos de estruturas metálicas com materiais, serviços, consumíveis e custos indiretos.',
quandoUsar: 'Na fase de proposta comercial ou planejamento de compras de um projeto estrutural.',
avisos: [
'Selecione a região correta (preços variam)',
'BDI/Margem deve cobrir custos indiretos e lucro',
'Verifique preços atualizados com fornecedores',
'Adicione itens indiretos (transporte, EPI, etc)'
],
campos: [
{ nome: 'Categoria', unidade: '-', significado: 'Tipo do item (Material, Serviço, Consumível, Indireto)', intervalo: '4 opções', dica: 'Organize por categoria' },
{ nome: 'Tipo de Produto', unidade: '-', significado: 'Categoria específica (Perfil W, Chapa, Eletrodo, etc)', intervalo: '15+ tipos', dica: 'Define lista de produtos' },
{ nome: 'Especificação', unidade: '-', significado: 'Produto específico do banco de dados', intervalo: '100+ produtos', dica: 'Preço preenche automaticamente' },
{ nome: 'Quantidade', unidade: 'variável', significado: 'Quantidade do item', intervalo: '> 0', dica: 'Use unidade correta (m, kg, un, m²)' },
{ nome: 'BDI / Margem', unidade: '%', significado: 'Margem de lucro e custos indiretos', intervalo: '15-35', dica: 'Tipicamente 25%' }
],
resultados: '<h4>Cálculo de Total</h4><p><strong>Subtotal = ∑(Quantidade × Preço Unitário)</strong></p><p><strong>BDI = Subtotal × (% BDI)</strong></p><p><strong>TOTAL = Subtotal + BDI</strong></p>',
referencias: [
{ titulo: 'SINAPI - Sistema Nacional de Pesquisa de Custos', url: 'https://www.caixa.gov.br' },
{ titulo: 'Tabela Gerdau - Preços de Aços', ano: 2025 }
],
manualRelacionado: ['orcamento_basico', 'bdi_margem']
}
};
const manualConteudo = {
aco_introducao: {
titulo: '📦 Introdução aos Aços',
secao: 'MATERIAIS',
conteudo: `
<h2>O que é um Aço?</h2>
<p>Aço é uma liga de ferro e carbono, com teor de carbono entre 0.04% e 2%, que oferece propriedades superiores ao ferro puro em termos de resistência, dureza e ductilidade.</p>
<h3>Classificação dos Aços</h3>
<ul>
<li><strong>Aços Simples (Carbono):</strong> Apenas Fe + C, sem elementos de liga adicionados</li>
<li><strong>Aços Ligados:</strong> Contêm Mn, Cr, Mo, V, Ni, etc para melhorar propriedades</li>
<li><strong>Aços Inoxidáveis:</strong> Alto teor de Cr (>10%), excelente resistência à corrosão</li>
<li><strong>Aços Estruturais:</strong> Otimizados para uso em estruturas (edifícios, pontes, etc)</li>
</ul>
<h3>Propriedades Principais</h3>
<table class="propriedades-tabela">
<tr><th>Propriedade</th><th>Definição</th><th>Unidade</th></tr>
<tr><td>Resistência à Tração (fu)</td><td>Máxima tensão que o aço aguenta</td><td>MPa</td></tr>
<tr><td>Limite de Escoamento (fy)</td><td>Tensão a partir da qual começa deformação permanente</td><td>MPa</td></tr>
<tr><td>Alongamento</td><td>Quanto o aço se alonga antes de quebrar</td><td>%</td></tr>
<tr><td>Dureza</td><td>Resistência ao risco/deformação superficial</td><td>HB, HRC</td></tr>
<tr><td>Tenacidade</td><td>Capacidade de absorver impactos sem quebrar</td><td>J (Joules)</td></tr>
</table>
<h3>Aços Estruturais Mais Comuns</h3>
<table>
<tr><th>Norma</th><th>Designação</th><th>fy (MPa)</th><th>fu (MPa)</th><th>Aplicação</th></tr>
<tr><td>ASTM</td><td>A36</td><td>250</td><td>400-550</td><td>Uso geral, estruturas comuns</td></tr>
<tr><td>ASTM</td><td>A572 Gr.50</td><td>345</td><td>450-620</td><td>Estruturas de alta resistência</td></tr>
<tr><td>EN</td><td>S235</td><td>235</td><td>360-510</td><td>Estruturas gerais (Europa)</td></tr>
<tr><td>EN</td><td>S355</td><td>355</td><td>510-680</td><td>Estruturas exigentes (Europa)</td></tr>
</table>
`
},
cev_entendimento: {
titulo: '⛗️ Entendendo Carbono Equivalente',
secao: 'MATERIAIS',
conteudo: `
<h2>O que é CEV?</h2>
<p>Carbono Equivalente (CEV) é um valor calculado que representa a "capacidade de endurecimento" de um aço durante a soldagem. Quanto maior o CEV, mais difícil é soldar.</p>
<h3>Por que CEV importa?</h3>
<p>Durante a soldagem, o material próximo à solda esfria muito rapidamente (taxa de resfriamento). Aços com alto CEV endurecem muito durante este resfriamento rápido, podendo desenvolver trincas.</p>
<h3>Fórmulas de CEV</h3>
<div class="formulas-container">
<h4>CEV IIW (Internacional)</h4>
<p><strong>CEV = C + (Mn/6) + (Cr+Mo+V)/5 + (Ni+Cu)/15</strong></p>
</div>
<h3>Interpretação de Valores</h3>
<table class="tabela-interpretacao">
<tr><th>CEV</th><th>Soldabilidade</th><th>Recomendação</th></tr>
<tr><td>&lt;0.35</td><td style="background: #4caf50; color: white">Excelente</td><td>Nenhuma restrição, soldagem direta</td></tr>
<tr><td>0.35-0.45</td><td style="background: #ffc107; color: black">Boa</td><td>Considerar pré-aquecimento</td></tr>
<tr><td>0.45-0.55</td><td style="background: #ff9800; color: white">Moderada</td><td>Pré-aquecimento necessário</td></tr>
<tr><td>&gt;0.55</td><td style="background: #f44336; color: white">Difícil</td><td>Controle rigoroso + especialista</td></tr>
</table>
<h3>Exemplos Práticos</h3>
<div class="exemplos-box">
<p><strong>Exemplo 1: A36</strong></p>
<p>C=0.20, Mn=0.95, Cr=0.10, Mo=0, V=0, Ni=0, Cu=0</p>
<p>CEV = 0.20 + (0.95/6) + 0 = <strong>0.36</strong> (Soldável)</p>
</div>
`
},
preaquecimento_guia: {
titulo: '🌡️ Guia Completo de Pré-Aquecimento',
secao: 'SOLDAGEM',
conteudo: `
<h2>O que é Pré-Aquecimento?</h2>
<p>Pré-aquecimento é o processo de elevar a temperatura do material base (e zona ao redor) ANTES de iniciar a soldagem.</p>
<h3>Por que Pré-aquecer?</h3>
<p>Durante a soldagem, o material próximo à solda esfria muito rapidamente. Este resfriamento rápido pode causar:</p>
<ul>
<li>📉 Aumento de dureza excessiva</li>
<li>🔨 Formação de estrutura frágil (martensita)</li>
<li>⚠️ Risco de trincas (especialmente em aços com alto CEV)</li>
</ul>
<p>Pré-aquecimento <strong>reduz a taxa de resfriamento</strong>, permitindo transformação metalúrgica adequada.</p>
<h3>Quando Usar?</h3>
<table>
<tr><th>Situação</th><th>CEV</th><th>Recomendação</th></tr>
<tr><td>Aço simples + espessura fina</td><td>&lt;0.35</td><td>❌ Não necessário</td></tr>
<tr><td>Aço estrutural comum</td><td>0.35-0.45</td><td>⚠️ Considerar</td></tr>
<tr><td>Aço de alta resistência</td><td>0.45-0.55</td><td>✅ Necessário</td></tr>
<tr><td>Aço muito ligado</td><td>&gt;0.55</td><td>🔴 Crítico</td></tr>
</table>
<h3>Instruções Práticas</h3>
<ol>
<li><strong>Medir:</strong> Use termômetro de contato em vários pontos</li>
<li><strong>Aquecer:</strong> Maçarico, resistência, forno - qualquer método vale</li>
<li><strong>Verificar:</strong> Confirme temperatura antes de soldar</li>
<li><strong>Manter:</strong> Mantenha interpass durante toda soldagem</li>
<li><strong>Esfriar:</strong> Deixe esfriar lentamente (não molhe bruscamente!)</li>
</ol>
`
},
soldagem_introducao: {
titulo: '🔥 Introdução à Soldagem',
secao: 'SOLDAGEM',
conteudo: `
<h2>O que é Soldagem?</h2>
<p>Soldagem é um processo de união de materiais metálicos por fusão, onde as peças são aquecidas até o ponto de fusão, permitindo que se fundam e formem uma junta única e contínua.</p>
<h3>Processos de Soldagem Principais</h3>
<ul>
<li><strong>SMAW (Eletrodo Revestido):</strong> Processo manual mais comum</li>
<li><strong>GMAW (MIG/MAG):</strong> Soldagem com arame contínuo e gás de proteção</li>
<li><strong>GTAW (TIG):</strong> Alta qualidade, ideal para aços inoxidáveis</li>
<li><strong>FCAW:</strong> Arame tubular, produtivo</li>
</ul>
<h3>Fatores Críticos</h3>
<p>Para uma boa solda, considere:</p>
<ol>
<li>Limpeza da superfície</li>
<li>Pré-aquecimento adequado</li>
<li>Velocidade de soldagem controlada</li>
<li>Energia de soldagem (Heat Input) apropriada</li>
<li>Proteção gasosa eficaz</li>
</ol>
`
}
};
const manualNavStructure = {
'MATERIAIS': ['aco_introducao', 'cev_entendimento', 'equivalencias_normas', 'acos_estruturais'],
'CONEXÕES': ['parafusos_basico', 'cisalhamento_analise', 'layout_furacao'],
'SOLDAGEM': ['soldagem_introducao', 'preaquecimento_guia', 'eletrodos_tipos', 'sequencia_soldagem'],
'ENSAIOS': ['ensaios_introducao', 'dureza_escalas', 'impacto_charpy'],
'PINTURA': ['pintura_introducao', 'iso12944', 'preparo_superficie'],
'ORÇAMENTO': ['orcamento_basico', 'bdi_margem', 'precos_mercado']
};
// Add more manual content
manualConteudo.parafusos_basico = {
titulo: '🔩 Introdução a Parafusos',
secao: 'CONEXÕES',
conteudo: `
<h2>O que são Parafusos Estruturais?</h2>
<p>Parafusos estruturais são elementos de fixação de alta resistência projetados para transmitir forças entre componentes de estruturas metálicas.</p>
<h3>Tipos Principais</h3>
<table>
<tr><th>Tipo</th><th>fy (MPa)</th><th>fu (MPa)</th><th>Aplicação</th></tr>
<tr><td><strong>ASTM A325</strong></td><td>400</td><td>635</td><td>Estruturas gerais (padrão)</td></tr>
<tr><td><strong>ASTM A490</strong></td><td>565</td><td>895</td><td>Alta resistência</td></tr>
<tr><td><strong>ISO 8.8</strong></td><td>640</td><td>800</td><td>Padrão métrico</td></tr>
<tr><td><strong>ISO 10.9</strong></td><td>900</td><td>1000</td><td>Máxima resistência</td></tr>
</table>
<h3>Componentes da Ligação</h3>
<ul>
<li><strong>Parafuso:</strong> Elemento principal com rosca</li>
<li><strong>Porca:</strong> Elemento de fixação roscado</li>
<li><strong>Arruela:</strong> Distribui tensão e protege superfície</li>
</ul>
<h3>Modos de Falha</h3>
<ol>
<li><strong>Cisalhamento do Parafuso:</strong> Ruptura do corpo do parafuso</li>
<li><strong>Esmagamento da Chapa:</strong> Deformação da chapa no furo</li>
<li><strong>Ruptura em Bloco:</strong> Ruptura de seção da chapa</li>
<li><strong>Tração:</strong> Ruptura do parafuso por tração</li>
</ol>
`
};
manualConteudo.cisalhamento_analise = {
titulo: '🔧 Análise de Cisalhamento',
secao: 'CONEXÕES',
conteudo: `
<h2>Cisalhamento em Parafusos</h2>
<p>O cisalhamento é o modo de falha mais comum em ligações parafusadas, onde o parafuso é cortado transversalmente pela força aplicada.</p>
<h3>Fórmula de Verificação</h3>
<div class="formulas-container">
<p><strong>Fv = 0.6 × fy × A × n</strong></p>
<p>Onde:</p>
<ul>
<li>Fv = Resistência ao cisalhamento (kN)</li>
<li>fy = Limite de escoamento do parafuso (MPa)</li>
<li>A = Área do parafuso (mm²)</li>
<li>n = Número de planos de corte (1 ou 2)</li>
</ul>
</div>
<h3>Planos de Corte</h3>
<p><strong>Plano Simples (n=1):</strong> Parafuso cortado em um ponto</p>
<p><strong>Plano Duplo (n=2):</strong> Parafuso cortado em dois pontos - DOBRA a capacidade!</p>
<h3>Exemplo Prático</h3>
<div class="exemplos-box">
<p><strong>Parafuso A325 Ø16mm</strong></p>
<p>fy = 400 MPa, A = π(16/2)² = 201 mm²</p>
<p><strong>Plano Simples:</strong> Fv = 0.6 × 400 × 201 / 1000 = 48.2 kN</p>
<p><strong>Plano Duplo:</strong> Fv = 48.2 × 2 = 96.4 kN ✅</p>
</div>
`
};
manualConteudo.pintura_introducao = {
titulo: '🎨 Introdução à Pintura Industrial',
secao: 'PINTURA',
conteudo: `
<h2>Sistemas de Pintura</h2>
<p>Pintura industrial é um sistema de proteção anticorrosiva composto por múltiplas camadas (demãos) que protegem o aço contra degradação.</p>
<h3>Componentes do Sistema</h3>
<ol>
<li><strong>Fundo (Primer):</strong> Primeira camada, aderência e proteção</li>
<li><strong>Intermediário:</strong> Aumenta espessura e proteção</li>
<li><strong>Acabamento:</strong> Proteção UV e estética</li>
</ol>
<h3>Tipos de Tinta</h3>
<table>
<tr><th>Tipo</th><th>Características</th><th>Aplicação</th></tr>
<tr><td><strong>Epóxi</strong></td><td>Excelente adesão, química</td><td>Fundo e intermediário</td></tr>
<tr><td><strong>Poliuretano</strong></td><td>Resistência UV, brilho</td><td>Acabamento</td></tr>
<tr><td><strong>Alquídica</strong></td><td>Econômica, secagem lenta</td><td>Ambientes leves</td></tr>
<tr><td><strong>Zinc-Rich</strong></td><td>Proteção galvânica</td><td>Ambientes agressivos</td></tr>
</table>
`
};
manualConteudo.iso12944 = {
titulo: '🎯 ISO 12944 - Classificação de Ambientes',
secao: 'PINTURA',
conteudo: `
<h2>ISO 12944 - Padrão Internacional</h2>
<p>ISO 12944 classifica ambientes de corrosividade e especifica sistemas de pintura adequados para cada categoria.</p>
<h3>Categorias de Corrosividade</h3>
<table>
<tr><th>Classe</th><th>Ambiente</th><th>DFT Mín (μm)</th><th>Vida Útil</th></tr>
<tr><td><strong>C1</strong></td><td>Interior seco (escritório)</td><td>80</td><td>5-10 anos</td></tr>
<tr><td><strong>C2</strong></td><td>Interior úmido (ginásio)</td><td>120</td><td>5-10 anos</td></tr>
<tr><td><strong>C3</strong></td><td>Exterior urbano/costeiro</td><td>160</td><td>10-15 anos</td></tr>
<tr><td><strong>C4</strong></td><td>Industrial/marinho moderado</td><td>200</td><td>15-20 anos</td></tr>
<tr><td><strong>C5</strong></td><td>Marinho agressivo/offshore</td><td>250</td><td>20+ anos</td></tr>
</table>
<h3>Sistemas Recomendados por Categoria</h3>
<div class="exemplos-box">
<p><strong>C3 (Padrão Indústria):</strong></p>
<ul>
<li>Fundo: Epóxi 60μm</li>
<li>Intermediário: Epóxi 60μm</li>
<li>Acabamento: Poliuretano 40μm</li>
<li><strong>Total: 160μm</strong></li>
</ul>
</div>
`
};
manualConteudo.orcamento_basico = {
titulo: '💰 Conceitos Básicos de Orçamento',
secao: 'ORÇAMENTO',
conteudo: `
<h2>Estrutura de um Orçamento</h2>
<p>Orçamento é a estimativa detalhada de todos os custos envolvidos em um projeto.</p>
<h3>Categorias de Custos</h3>
<ol>
<li><strong>Materiais:</strong> Perfis, chapas, parafusos</li>
<li><strong>Serviços:</strong> Mão de obra especializada</li>
<li><strong>Consumíveis:</strong> Eletrodos, tintas, gases</li>
<li><strong>Indiretos:</strong> Transporte, EPI, aluguel de equipamentos</li>
</ol>
<h3>Como Calcular Preço de Materiais</h3>
<p>Para perfis e chapas: <strong>Preço = Peso × Preço/kg</strong></p>
<p>Preços variam por região do Brasil:</p>
<ul>
<li>Sudeste: R$ 7.50/kg (referência)</li>
<li>Sul: R$ 7.20/kg (mais barato)</li>
<li>Nordeste: R$ 8.00/kg</li>
<li>Centro-Oeste: R$ 7.70/kg</li>
</ul>
`
};
manualConteudo.bdi_margem = {
titulo: '📊 BDI e Margem de Lucro',
secao: 'ORÇAMENTO',
conteudo: `
<h2>O que é BDI?</h2>
<p>BDI (Benefícios e Despesas Indiretas) é um percentual aplicado sobre os custos diretos para cobrir:</p>
<h3>Componentes do BDI</h3>
<ul>
<li><strong>Administração Central:</strong> Escritório, contabilidade (5-8%)</li>
<li><strong>Lucro:</strong> Margem de lucro da empresa (8-15%)</li>
<li><strong>Impostos:</strong> ISS, PIS, COFINS (5-10%)</li>
<li><strong>Riscos:</strong> Contingência para imprevistos (2-5%)</li>
</ul>
<h3>BDI Típico por Tipo de Obra</h3>
<table>
<tr><th>Tipo de Obra</th><th>BDI Típico</th></tr>
<tr><td>Pequenas estruturas</td><td>20-25%</td></tr>
<tr><td>Edifícios comerciais</td><td>25-30%</td></tr>
<tr><td>Pontes e obras públicas</td><td>25-28%</td></tr>
<tr><td>Offshore e projetos complexos</td><td>30-35%</td></tr>
</table>
<h3>Exemplo de Cálculo</h3>
<div class="exemplos-box">
<p><strong>Custos Diretos:</strong> R$ 100.000,00</p>
<p><strong>BDI:</strong> 25%</p>
<p><strong>Valor BDI:</strong> R$ 100.000 × 0.25 = R$ 25.000,00</p>
<p><strong>TOTAL:</strong> R$ 125.000,00</p>
</div>
`
};
manualConteudo.ensaios_introducao = {
titulo: '✅ Introdução a Ensaios',
secao: 'ENSAIOS',
conteudo: `
<h2>Por que Ensaiar?</h2>
<p>Ensaios são testes realizados em materiais e soldas para verificar conformidade com especificações e normas.</p>
<h3>Tipos de Ensaios</h3>
<h4>Ensaios Destrutivos</h4>
<ul>
<li><strong>Tração:</strong> Mede fy, fu e alongamento</li>
<li><strong>Dureza:</strong> Mede resistência à penetração</li>
<li><strong>Charpy:</strong> Mede tenacidade ao impacto</li>
<li><strong>Dobramento:</strong> Verifica ductilidade da solda</li>
</ul>
<h4>Ensaios Não Destrutivos (END)</h4>
<ul>
<li><strong>Ultrassom (UT):</strong> Detecta defeitos internos</li>
<li><strong>Radiografia (RT):</strong> Imagem de defeitos</li>
<li><strong>Partículas Magnéticas (MT):</strong> Defeitos superficiais</li>
<li><strong>Líquido Penetrante (PT):</strong> Trincas superficiais</li>
</ul>
`
};
manualConteudo.dureza_escalas = {
titulo: '🔨 Escalas de Dureza',
secao: 'ENSAIOS',
conteudo: `
<h2>Escalas de Dureza</h2>
<p>Dureza mede a resistência de um material à deformação permanente por indentação.</p>
<h3>Brinell (HB)</h3>
<p><strong>Método:</strong> Esfera de aço ou tungstênio pressionada na superfície</p>
<p><strong>Faixa:</strong> 100-650 HB</p>
<p><strong>Aplicação:</strong> Aços estruturais, ferro fundido</p>
<h3>Rockwell C (HRC)</h3>
<p><strong>Método:</strong> Cone de diamante</p>
<p><strong>Faixa:</strong> 20-70 HRC</p>
<p><strong>Aplicação:</strong> Aços temperados, ferramentas</p>
<h3>Vickers (HV)</h3>
<p><strong>Método:</strong> Pirâmide de diamante</p>
<p><strong>Faixa:</strong> 100-1000+ HV</p>
<p><strong>Aplicação:</strong> Universal, todos os materiais</p>
<h3>Correlação com Resistência</h3>
<p>Para aços carbono:</p>
<p><strong>fu (MPa) ≈ HB × 10</strong></p>
<div class="exemplos-box">
<p>HB 250 → fu ≈ 2500 MPa</p>
</div>
`
};
manualConteudo.impacto_charpy = {
titulo: '📉 Ensaio de Impacto Charpy',
secao: 'ENSAIOS',
conteudo: `
<h2>O que é o Ensaio Charpy?</h2>
<p>Ensaio que mede a energia absorvida por um corpo de prova entalhado ao ser rompido por um pêndulo.</p>
<h3>Por que é Importante?</h3>
<p>Materiais podem se comportar de forma <strong>dúctil</strong> (absorvem energia) ou <strong>frágil</strong> (quebram subitamente) dependendo da temperatura.</p>
<h3>Temperatura de Transição (TTDF)</h3>
<p>Temperatura onde o material muda de comportamento dúctil para frágil.</p>
<p><strong>Critério comum:</strong> TTDF = temperatura onde energia = 27J</p>
<h3>Requisitos por Aplicação</h3>
<table>
<tr><th>Aplicação</th><th>Energia Mín</th><th>Temperatura</th></tr>
<tr><td>Estruturas internas</td><td>27J</td><td>0°C</td></tr>
<tr><td>Estruturas externas</td><td>27J</td><td>-20°C</td></tr>
<tr><td>Offshore/Ártico</td><td>40J</td><td>-40°C</td></tr>
</table>
`
};
manualConteudo.layout_furacao = {
titulo: '📍 Layout de Furação',
secao: 'CONEXÕES',
conteudo: `
<h2>Distâncias e Espaçamentos</h2>
<p>NBR 8800 e AISC 360 estabelecem limites para garantir resistência adequada.</p>
<h3>Distância de Borda</h3>
<p><strong>Mínimo:</strong> 1.5d (evita ruptura da borda)</p>
<p><strong>Máximo:</strong> 12t ou 150mm (evita empenamento)</p>
<h3>Espaçamento entre Furos</h3>
<p><strong>Mínimo:</strong> 2.67d (evita interferência de tensões)</p>
<p><strong>Máximo:</strong> 300mm (evita correlação local)</p>
<h3>Exemplo</h3>
<div class="exemplos-box">
<p><strong>Parafuso Ø20mm, Chapa 10mm</strong></p>
<p>Mínimo borda: 1.5 × 20 = 30mm</p>
<p>Máximo borda: 12 × 10 = 120mm</p>
<p>Mínimo espaçamento: 2.67 × 20 = 53.4mm</p>
</div>
`
};
manualConteudo.eletrodos_tipos = {
titulo: '🔥 Tipos de Eletrodos',
secao: 'SOLDAGEM',
conteudo: `
<h2>Eletrodos Revestidos (SMAW)</h2>
<p>Eletrodo revestido é composto por alma metálica + revestimento que gera escória protetora e gás.</p>
<h3>Classificação AWS</h3>
<table>
<tr><th>Eletrodo</th><th>Revestimento</th><th>Resistência</th><th>Aplicação</th></tr>
<tr><td><strong>E6013</strong></td><td>Rutílico</td><td>420 MPa</td><td>Geral, fácil</td></tr>
<tr><td><strong>E7018</strong></td><td>Básico</td><td>485 MPa</td><td>Estrutural (padrão)</td></tr>
<tr><td><strong>E8018</strong></td><td>Básico</td><td>550 MPa</td><td>Alta resistência</td></tr>
</table>
<h3>Vantagens do Básico (E7018)</h3>
<ul>
<li>✅ Baixo hidrogênio (previne trincas)</li>
<li>✅ Alta tenacidade (Charpy 47J)</li>
<li>✅ Excelente para estruturas críticas</li>
</ul>
`
};
manualConteudo.sequencia_soldagem = {
titulo: '🔄 Sequência de Soldagem',
secao: 'SOLDAGEM',
conteudo: `
<h2>Por que Sequência Importa?</h2>
<p>A ordem de deposição da solda afeta diretamente as distorções e tensões residuais na estrutura.</p>
<h3>Padrões de Soldagem</h3>
<h4>1. Skip Welding (Recomendado)</h4>
<p>Solda em segmentos alternados, deixando espaços que são preenchidos depois.</p>
<p><strong>Vantagem:</strong> Reduz distorções em 80%</p>
<h4>2. Backstep Welding</h4>
<p>Soldagem em segmentos curtos na direção oposta ao avanço geral.</p>
<p><strong>Vantagem:</strong> Reduz distorções em 60%</p>
<h4>3. Contínuo (Não Recomendado)</h4>
<p>Soldagem contínua sem paradas.</p>
<p><strong>Desvantagem:</strong> Máxima distorção</p>
`
};
manualConteudo.equivalencias_normas = {
titulo: '🌍 Equivalências Internacionais',
secao: 'MATERIAIS',
conteudo: `
<h2>Por que Equivalências?</h2>
<p>Projetos internacionais podem especificar aços de diferentes normas. Conhecer equivalências permite substituição adequada.</p>
<h3>Principais Equivalências</h3>
<table>
<tr><th>ASTM</th><th>EN</th><th>JIS</th><th>NBR</th></tr>
<tr><td>A36</td><td>S235JR</td><td>SS400</td><td>-</td></tr>
<tr><td>A572 Gr.50</td><td>S355J2</td><td>SM490</td><td>AR350</td></tr>
<tr><td>A588</td><td>S355K2G3</td><td>-</td><td>-</td></tr>
</table>
<h3>⚠️ Cuidados na Substituição</h3>
<ul>
<li>Verificar composição química</li>
<li>Confirmar propriedades mecânicas</li>
<li>Checar soldabilidade (CEV)</li>
<li>Validar com engenheiro responsável</li>
</ul>
`
};
manualConteudo.acos_estruturais = {
titulo: '🏭 Aços Estruturais Comuns',
secao: 'MATERIAIS',
conteudo: `
<h2>Aços Mais Usados no Brasil</h2>
<h3>ASTM A36 - O "Trabalhador"</h3>
<p><strong>Propriedades:</strong> fy=250 MPa, fu=400 MPa</p>
<p><strong>Aplicação:</strong> Estruturas gerais, baixa responsabilidade</p>
<p><strong>Vantagens:</strong> Barato, muito soldável, disponível</p>
<h3>ASTM A572 Gr.50 - O "Profissional"</h3>
<p><strong>Propriedades:</strong> fy=345 MPa, fu=450 MPa</p>
<p><strong>Aplicação:</strong> Edifícios altos, pontes, estruturas pesadas</p>
<p><strong>Vantagens:</strong> Ótima relação custo/benefício</p>
<h3>EN S355J2 - O "Europeu"</h3>
<p><strong>Propriedades:</strong> fy=355 MPa, fu=490 MPa</p>
<p><strong>Aplicação:</strong> Projetos internacionais</p>
<p><strong>Vantagens:</strong> Boa tenacidade, amplamente especificado</p>
`
};
manualConteudo.preparo_superficie = {
titulo: '🧹 Preparação de Superfície',
secao: 'PINTURA',
conteudo: `
<h2>A Preparação É Fundamental!</h2>
<p>90% dos problemas de pintura vem de preparação inadequada da superfície.</p>
<h3>Graus de Limpeza ISO 8501-1</h3>
<table>
<tr><th>Grau</th><th>Descrição</th><th>Uso</th></tr>
<tr><td><strong>Sa 1</strong></td><td>Jateamento ligeiro</td><td>Não recomendado</td></tr>
<tr><td><strong>Sa 2</strong></td><td>Jateamento comercial</td><td>Ambientes leves</td></tr>
<tr><td><strong>Sa 2½</strong></td><td>Jateamento ao metal quase branco</td><td><strong>Padrão indústria</strong></td></tr>
<tr><td><strong>Sa 3</strong></td><td>Jateamento ao metal branco</td><td>Ambientes severos</td></tr>
</table>
<h3>Métodos de Preparação</h3>
<ul>
<li><strong>Jateamento Abrasivo:</strong> Método mais eficaz</li>
<li><strong>Lixamento Mecânico:</strong> Para pequenas áreas</li>
<li><strong>Escovamento:</strong> Manutenção apenas</li>
<li><strong>Desengraxe:</strong> Sempre necessário</li>
</ul>
`
};
manualConteudo.precos_mercado = {
titulo: '💲 Preços do Mercado Brasileiro',
secao: 'ORÇAMENTO',
conteudo: `
<h2>Preços Médios 2025</h2>
<p>Valores de referência para orçamentos (sujeitos a variação).</p>
<h3>Aços Estruturais</h3>
<table>
<tr><th>Região</th><th>A36 (R$/kg)</th><th>A572 (R$/kg)</th></tr>
<tr><td>Sudeste (SP/RJ)</td><td>7.50</td><td>8.50</td></tr>
<tr><td>Sul (RS/SC/PR)</td><td>7.20</td><td>8.20</td></tr>
<tr><td>Nordeste</td><td>8.00</td><td>9.00</td></tr>
<tr><td>Centro-Oeste</td><td>7.70</td><td>8.70</td></tr>
</table>
<h3>Serviços</h3>
<ul>
<li><strong>Soldagem:</strong> R$ 60-70/h (soldador qualificado)</li>
<li><strong>Pintura:</strong> R$ 35-45/m²</li>
<li><strong>Montagem:</strong> R$ 50-65/h</li>
</ul>
<h3>Consumíveis</h3>
<ul>
<li><strong>E7018:</strong> R$ 45/kg</li>
<li><strong>Tinta Epóxi C3:</strong> R$ 80/L</li>
<li><strong>Parafuso A325 M16:</strong> R$ 1.20/un</li>
</ul>
`
};
function addHelpButton(sectionId) {
const mainContent = document.getElementById('main-content');
if (!mainContent) return;
const existingBtn = mainContent.querySelector('.btn-help');
if (existingBtn) existingBtn.remove();
if (ajudaDatabase[sectionId]) {
const btnHelp = document.createElement('button');
btnHelp.className = 'btn-help';
btnHelp.textContent = '❓';
btnHelp.onclick = () => openAjudaModal(sectionId);
btnHelp.title = 'Clique para ajuda';
mainContent.style.position = 'relative';
mainContent.appendChild(btnHelp);
}
}
function openAjudaModal(sectionId) {
currentHelpSection = sectionId;
const ajuda = ajudaDatabase[sectionId];
if (!ajuda) return;
document.getElementById('ajudaTitulo').textContent = ajuda.titulo;
// Tab 0: Explicação
document.getElementById('help-tab-0').innerHTML = `
<div class="ajuda-secao">
<h3>O que é?</h3>
<p>${ajuda.oQueE}</p>
</div>
<div class="ajuda-secao">
<h3>Para que serve?</h3>
<p>${ajuda.paraQueServe}</p>
</div>
<div class="ajuda-secao">
<h3>Quando usar?</h3>
<p>${ajuda.quandoUsar}</p>
</div>
<div class="ajuda-secao">
<h3>⚠️ Avisos Importantes</h3>
<ul>${ajuda.avisos.map(a => `<li>${a}</li>`).join('')}</ul>
</div>
`;
// Tab 1: Campos
document.getElementById('help-tab-1').innerHTML = `
<table class="tabela-campos">
<thead>
<tr>
<th>Campo</th>
<th>Unidade</th>
<th>Significado</th>
<th>Intervalo Típico</th>
<th>Dica</th>
</tr>
</thead>
<tbody>
${ajuda.campos.map(c => `
<tr>
<td><strong>${c.nome}</strong></td>
<td>${c.unidade}</td>
<td>${c.significado}</td>
<td>${c.intervalo}</td>
<td>${c.dica}</td>
</tr>
`).join('')}
</tbody>
</table>
`;
// Tab 2: Resultados
document.getElementById('help-tab-2').innerHTML = `
<div class="ajuda-secao">
<h3>O que significam os resultados?</h3>
${ajuda.resultados}
</div>
`;
// Tab 3: Referências
document.getElementById('help-tab-3').innerHTML = `
<div class="ajuda-secao">
<h3>📚 Referências Bibliográficas</h3>
<div class="referencias-list">
${ajuda.referencias.map(r => `
<div class="referencia-item">
<strong>${r.titulo}</strong><br>
${r.ano ? `Ano: ${r.ano}<br>` : ''}
${r.url ? `<a href="${r.url}" target="_blank">${r.url}</a>` : ''}
</div>
`).join('')}
</div>
<h3>📖 Leia também no Manual</h3>
<ul class="manual-links">
${ajuda.manualRelacionado.map(tema => {
const conteudo = manualConteudo[tema];
return conteudo ? `<li><a href="#" onclick="abrirManualNoTema('${tema}'); return false;">${conteudo.titulo}</a></li>` : '';
}).join('')}
</ul>
</div>
`;
document.getElementById('modalAjuda').classList.add('active');
}
function closeAjudaModal() {
document.getElementById('modalAjuda').classList.remove('active');
}
function switchHelpTab(index) {
document.querySelectorAll('.help-tab-btn').forEach((btn, i) => {
btn.classList.toggle('active', i === index);
});
document.querySelectorAll('.help-tab-content').forEach((content, i) => {
content.classList.toggle('active', i === index);
});
}
function abrirManualRelacionado() {
if (currentHelpSection && ajudaDatabase[currentHelpSection]) {
const temas = ajudaDatabase[currentHelpSection].manualRelacionado;
if (temas && temas.length > 0) {
closeAjudaModal();
abrirManualNoTema(temas[0]);
}
}
}
function openManualUsuario() {
carregarManualNav();
abrirManualNoTema('aco_introducao');
document.getElementById('modalManual').classList.add('active');
}
function closeManualModal() {
document.getElementById('modalManual').classList.remove('active');
}
function carregarManualNav() {
const nav = document.getElementById('manualNav');
let html = '';
Object.keys(manualNavStructure).forEach(secao => {
html += `
<div class="manual-secao">
<button class="manual-secao-btn" onclick="toggleManualSecao(this)">
${secao}
</button>
<div class="manual-items">
${manualNavStructure[secao].map(tema => {
const conteudo = manualConteudo[tema];
return conteudo ? `
<button class="manual-item" onclick="abrirManualNoTema('${tema}')">
${conteudo.titulo}
</button>
` : '';
}).join('')}
</div>
</div>
`;
});
nav.innerHTML = html;
}
function toggleManualSecao(btn) {
const items = btn.nextElementSibling;
items.classList.toggle('active');
}
function abrirManualNoTema(temaId) {
const conteudo = manualConteudo[temaId];
if (!conteudo) return;
document.getElementById('manualConteudo').innerHTML = `
<h2>${conteudo.titulo}</h2>
<div class="manual-secao-badge" style="display: inline-block; background: var(--color-primary); color: var(--color-btn-primary-text); padding: 4px 12px; border-radius: 4px; font-size: 12px; margin-bottom: 20px;">
${conteudo.secao}
</div>
${conteudo.conteudo}
`;
// Mark active item
document.querySelectorAll('.manual-item').forEach(item => {
item.classList.remove('active');
});
const activeBtn = Array.from(document.querySelectorAll('.manual-item')).find(btn =>
btn.textContent.includes(conteudo.titulo)
);
if (activeBtn) {
activeBtn.classList.add('active');
// Open parent section
const items = activeBtn.parentElement;
if (items) items.classList.add('active');
}
document.getElementById('modalManual').classList.add('active');
// Scroll to top
document.querySelector('.manual-content').scrollTop = 0;
}
function buscarNoManual() {
const searchTerm = document.getElementById('manualSearch').value.toLowerCase();
const items = document.querySelectorAll('.manual-item');
items.forEach(item => {
const text = item.textContent.toLowerCase();
if (text.includes(searchTerm)) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
}
document.addEventListener('DOMContentLoaded', function() {
showSection('cev');
mostrarEquivalencias();
gerarChecklistCertificado();
updatePaintFields();
updateWeightFields();
applyAdminConfig();
filterToolsByMode();
addHelpButton('cev');
// Initialize budget when switching to orcamento section
const observer = new MutationObserver(() => {
if (appState.currentSection === 'orcamento') {
setTimeout(initializeBudget, 100);
}
});
// Close admin modal on outside click
const adminModal = document.getElementById('adminModal');
if (adminModal) {
adminModal.addEventListener('click', function(e) {
if (e.target === adminModal) {
closeAdminModal();
}
});
}
});