❌ Error al mover el archivo.'; exit; } // Ejecutar el slicer (PrusaSlicer o script JS) $cmd = "node /var/www/html/runPrusa.js " . escapeshellarg($stlPath); exec($cmd, $output, $return_var); if ($return_var !== 0 || empty($output)) { echo '
⚠️ Error al generar G-code:
' . implode("
", $output) . '
'; exit; } $result = json_decode($output[0], true); if (!$result) { echo '
⚠️ No se pudo leer la información del G-code.
'; exit; } // Datos del archivo $margen = 0.10; $filamento_mm = $result['filamentUsedMm'] ?? 0; $filamento_cm3 = $result['filamentUsedCm3'] ?? 0; $tiempo_estimado = $result['estimatedTime'] ?? "0h 0m 0s"; $filamento_mm_seg = $filamento_mm * (1 + $margen); $filamento_cm3_seg = $filamento_cm3 * (1 + $margen); $tiempo_seg = ajustarTiempo($tiempo_estimado, $margen); $impresoraSeleccionada = $_POST['marca'] ?? 'markforged'; $materialSeleccionado = $_POST['material'] ?? 'pla'; include 'calculo_precio.php'; $cotizacion = calcularCotizacionImpresion( $filamento_cm3_seg, convertirTiempoAHoras($tiempo_seg), $materialSeleccionado, $impresoraSeleccionada ); // --- MOSTRAR RESULTADOS --- echo '

📊 Datos Base

Filamento usado: ' . number_format($filamento_mm, 2) . ' mm
Volumen usado: ' . number_format($filamento_cm3, 2) . ' cm³
Tiempo estimado: ' . htmlspecialchars($tiempo_estimado) . '

🛡️ Con Margen de Seguridad (10%)

Filamento usado (seguridad): ' . number_format($filamento_mm_seg, 2) . ' mm
Volumen usado (seguridad): ' . number_format($filamento_cm3_seg, 2) . ' cm³
Tiempo estimado (seguridad): ' . htmlspecialchars($tiempo_seg) . '

💰 Cotización Estimada

Impresora: ' . htmlspecialchars(ucfirst($impresoraSeleccionada)) . '
Material: ' . htmlspecialchars(ucfirst($materialSeleccionado)) . '

• Costo Material: ' . number_format($cotizacion['costo_material'], 2) . ' MXN
• Costo Tiempo: ' . number_format($cotizacion['costo_tiempo'], 2) . ' MXN
• Subtotal Producción: ' . number_format($cotizacion['subtotal_produccion'], 2) . ' MXN
• Consumible Impresión: ' . number_format($cotizacion['consumible_impresion'], 2) . ' MXN
• Costo Operación: ' . number_format($cotizacion['costo_operacion'], 2) . ' MXN
• Subtotal Operación: ' . number_format($cotizacion['subtotal_operacion'], 2) . ' MXN
• Costo Final: ' . number_format($cotizacion['costo_final_impresion'], 2) . ' MXN
• Indirectos: ' . number_format($cotizacion['indirectos'], 2) . ' MXN

💵 Precio Final Estimado: ' . number_format($cotizacion['precio_final'], 2) . ' MXN
'; // === VISUALIZADOR 3D === echo '

Controles del Visor 3D

'; $stlUrl = 'uploads/' . htmlspecialchars(basename($stlPath)); echo ''; } else { echo '
❌ No se recibió un archivo STL válido.
'; } } else { echo '
⚠️ Método no permitido.
'; } // --- FUNCIONES AUXILIARES --- function ajustarTiempo($tiempo_str, $porcentaje) { preg_match_all("/(\\d+)([hms])/", $tiempo_str, $matches, PREG_SET_ORDER); $segundos = 0; foreach ($matches as $match) { $valor = (int)$match[1]; switch ($match[2]) { case "h": $segundos += $valor * 3600; break; case "m": $segundos += $valor * 60; break; case "s": $segundos += $valor; break; } } $segundos_ajustados = round($segundos * (1 + $porcentaje)); $horas = intdiv($segundos_ajustados, 3600); $minutos = intdiv($segundos_ajustados % 3600, 60); $segundos_final = $segundos_ajustados % 60; return "{$horas}h {$minutos}m {$segundos_final}s"; } function convertirTiempoAHoras($tiempo_str) { preg_match_all("/(\\d+)([hms])/", $tiempo_str, $matches, PREG_SET_ORDER); $horas = 0; foreach ($matches as $match) { $valor = (int)$match[1]; switch ($match[2]) { case "h": $horas += $valor; break; case "m": $horas += $valor / 60; break; case "s": $horas += $valor / 3600; break; } } return $horas; } ?>