7268 lines
347 KiB
JavaScript
7268 lines
347 KiB
JavaScript
// ========================================
|
||
// 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 & 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)} m²\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}m²`);
|
||
}
|
||
|
||
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><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>>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 > 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><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>>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><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>>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();
|
||
}
|
||
});
|
||
}
|
||
}); |