/** * Cost Calculator Service * Estimates filament/resin costs based on file size */ // Default material costs (per kg) const DEFAULT_COSTS = { // FDM Filaments 'pla': 15, // PLA ~$15/kg 'abs': 18, // ABS ~$18/kg 'petg': 20, // PETG ~$20/kg 'nylon': 35, // Nylon ~$35/kg 'tpu': 40, // TPU ~$40/kg 'carbon': 50, // Carbon Fiber ~$50/kg 'bamboo': 25, // Bamboo ~$25/kg // Resin 'standard': 12, // Standard Resin ~$12/ml 'tough': 18, // Tough Resin ~$18/ml 'flexible': 20, // Flexible Resin ~$20/ml 'castable': 25, // Castable Resin ~$25/ml }; // Density of materials (g/cm³) const MATERIAL_DENSITY = { // FDM Filaments 'pla': 1.24, 'abs': 1.04, 'petg': 1.27, 'nylon': 1.14, 'tpu': 1.21, 'carbon': 1.30, 'bamboo': 1.25, // Resin 'standard': 1.15, 'tough': 1.18, 'flexible': 1.20, 'castable': 1.22, }; /** * Estimate material weight from file size * Using heuristic: file size in bytes → approximate volume → weight * * Formula: Weight (g) = (File Size in MB) * 50 * density / material_type_factor * This is a rough estimation since we don't have actual 3D geometry */ export function estimateWeight(fileSizeBytes, materialType = 'pla') { // Convert bytes to MB const fileSizeMB = fileSizeBytes / (1024 * 1024); // Heuristic factor: roughly 50-70g per MB of STL/OBJ, less for compressed 3MF // Average density is ~1.2, so we use that as baseline const baseFactor = 55; const density = MATERIAL_DENSITY[materialType] || 1.2; // Estimate weight in grams const weightGrams = fileSizeMB * baseFactor * (density / 1.2); return Math.max(weightGrams, 1); // Minimum 1 gram } /** * Calculate cost based on estimated weight and material type */ export function calculateCost(fileSizeBytes, materialType = 'pla', customCostPerUnit = null) { const costPerUnit = customCostPerUnit || DEFAULT_COSTS[materialType] || DEFAULT_COSTS['pla']; const weight = estimateWeight(fileSizeBytes, materialType); // Convert to kg for FDM or ml for resin const units = weight / 1000; return { material: materialType, weight: Math.round(weight * 100) / 100, // grams units: Math.round(units * 100) / 100, costPerUnit: costPerUnit, estimatedCost: Math.round(units * costPerUnit * 100) / 100, confidence: 'low' // Note: This is a rough estimate }; } /** * Get all available materials with their costs */ export function getMaterials() { return Object.keys(DEFAULT_COSTS).map(material => ({ type: material, costPerUnit: DEFAULT_COSTS[material], density: MATERIAL_DENSITY[material] })); } /** * Update cost for a material */ export function updateMaterialCost(materialType, costPerUnit) { if (DEFAULT_COSTS.hasOwnProperty(materialType)) { DEFAULT_COSTS[materialType] = costPerUnit; return true; } return false; } /** * Batch calculate costs for multiple models */ export function batchCalculateCosts(models, materialType = 'pla') { return models.map(model => ({ modelId: model.id, name: model.name, ...calculateCost(model.file_size, materialType) })); } export default { estimateWeight, calculateCost, getMaterials, updateMaterialCost, batchCalculateCosts };