// Global variables let currentImage = null; let analysisInProgress = false; // DOM Elements const dropZone = document.getElementById('dropZone'); const imageUpload = document.getElementById('imageUpload'); const previewImage = document.getElementById('previewImage'); const resultsSection = document.getElementById('resultsSection'); const loadingSection = document.getElementById('loadingSection'); // Measurement elements const measurementElements = { bust: { value: document.getElementById('bustValue'), note: document.getElementById('bustNote') }, underbust: { value: document.getElementById('underbustValue'), note: document.getElementById('underbustNote') }, waist: { value: document.getElementById('waistValue'), note: document.getElementById('waistNote') }, hips: { value: document.getElementById('hipsValue'), note: document.getElementById('hipsNote') }, height: { value: document.getElementById('heightValue'), note: document.getElementById('heightNote') }, weight: { value: document.getElementById('weightValue'), note: document.getElementById('weightNote') } }; // Confidence elements const confidenceValue = document.getElementById('confidenceValue'); const analysisNotes = document.getElementById('analysisNotes'); // Initialize the application document.addEventListener('DOMContentLoaded', function() { initializeEventListeners(); }); function initializeEventListeners() { // File input change imageUpload.addEventListener('change', handleFileSelect); // Drag and drop events ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, preventDefaults, false); }); ['dragenter', 'dragover'].forEach(eventName => { dropZone.addEventListener(eventName, highlight, false); }); ['dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, unhighlight, false); }); dropZone.addEventListener('drop', handleDrop, false); } function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } function highlight() { dropZone.classList.add('drag-over'); } function unhighlight() { dropZone.classList.remove('drag-over'); } function handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; handleFiles(files); } function handleFileSelect(e) { const files = e.target.files; handleFiles(files); } function handleFiles(files) { if (analysisInProgress) return; const file = files[0]; if (!file) return; // Check if file is an image if (!file.type.match('image.*')) { alert('Please upload an image file (JPG, PNG, WEBP)'); return; } // Check file size (10MB max) if (file.size > 10 * 1024 * 1024) { alert('File size must be less than 10MB'); return; } // Create preview const reader = new FileReader(); reader.onload = function(e) { previewImage.src = e.target.result; currentImage = e.target.result; startAnalysis(); }; reader.readAsDataURL(file); } function startAnalysis() { if (!currentImage) return; analysisInProgress = true; // Show loading state resultsSection.classList.add('hidden'); loadingSection.classList.remove('hidden'); // Get reference values const referenceType = document.getElementById('referenceType').value; const referenceValue = parseFloat(document.getElementById('referenceValue').value) || null; const unitSystem = document.getElementById('unitSystem').value; const actualHeight = parseFloat(document.getElementById('actualHeight').value) || null; const heightUnit = document.getElementById('heightUnit').value; // Simulate AI analysis (in a real app, this would call an API) setTimeout(() => { performAnalysis(referenceType, referenceValue, unitSystem, actualHeight, heightUnit); }, 3000); } function performAnalysis(referenceType, referenceValue, unitSystem, actualHeight, heightUnit) { // This is a mock analysis - in a real application, this would use computer vision APIs const measurements = generateMockMeasurements(referenceType, referenceValue, unitSystem, actualHeight, heightUnit); // Update UI with results updateResultsUI(measurements, unitSystem); // Hide loading, show results loadingSection.classList.add('hidden'); resultsSection.classList.remove('hidden'); analysisInProgress = false; } function generateMockMeasurements(referenceType, referenceValue, unitSystem, actualHeight, heightUnit) { // Convert actual height to cm for internal calculations let baseHeightCm; if (actualHeight) { baseHeightCm = heightUnit === 'in' ? actualHeight * 2.54 : actualHeight; } else { baseHeightCm = 160 + Math.random() * 30; // 160-190cm if not provided } // Base measurements in cm for metric system let baseMeasurements = { bust: (85 + Math.random() * 20) * (baseHeightCm / 170), underbust: (70 + Math.random() * 15) * (baseHeightCm / 170), waist: (65 + Math.random() * 15) * (baseHeightCm / 170), hips: (90 + Math.random() * 20) * (baseHeightCm / 170), height: baseHeightCm, weight: (55 + Math.random() * 25) * (baseHeightCm / 170) / 1.7 }; // Adjust measurements if reference is provided if (referenceValue && referenceType) { // Convert reference value to cm if needed let referenceValueCm = referenceValue; if (unitSystem === 'imperial' && referenceType !== 'weight') { referenceValueCm = referenceValue * 2.54; } else if (unitSystem === 'imperial' && referenceType === 'weight') { referenceValueCm = referenceValue * 0.453592; } // Calculate scaling factor based on reference const scalingFactor = referenceValueCm / baseMeasurements[referenceType]; // Apply scaling to all measurements Object.keys(baseMeasurements).forEach(key => { if (key !== 'weight') { baseMeasurements[key] *= scalingFactor; } else { baseMeasurements[key] *= scalingFactor; } }); } // Convert to desired unit system for display const measurements = {}; Object.keys(baseMeasurements).forEach(key => { let displayValue; let estimated = true; let confidence = 'medium'; // Determine if this measurement is accurate based on reference if (referenceType === key) { estimated = false; confidence = 'high'; } else if (referenceValue && referenceType) { confidence = 'high'; } if (unitSystem === 'metric') { if (key === 'weight') { displayValue = Math.round(baseMeasurements[key]); } else { displayValue = Math.round(baseMeasurements[key]); } } else { if (key === 'weight') { displayValue = Math.round(baseMeasurements[key] * 2.20462); } else { displayValue = Math.round(baseMeasurements[key] / 2.54 * 10) / 10; // Round to 1 decimal for inches } else { displayValue = Math.round(baseMeasurements[key]); } } measurements[key] = { value: displayValue, estimated: estimated, confidence: confidence }; }); return measurements; } function updateResultsUI(measurements, unitSystem) { // Update each measurement Object.keys(measurements).forEach(key => { const measurement = measurements[key]; const element = measurementElements[key]; if (element) { // Update value with appropriate units let unit = ''; if (key === 'weight') { unit = unitSystem === 'metric' ? 'kg' : 'lbs'; } else { unit = unitSystem === 'metric' ? 'cm' : 'in'; } element.value.textContent = `${measurement.value} ${unit}`; // Update note if (measurement.estimated) { element.note.textContent = 'Estimated value'; element.note.className = 'text-sm text-amber-600'; } else { element.note.textContent = 'Measured from reference'; element.note.className = 'text-sm text-green-600'; } } }); // Update confidence level const confidenceLevels = Object.values(measurements).map(m => m.confidence); const avgConfidence = confidenceLevels.reduce((a, b) => { const values = { low: 1, medium: 2, high: 3 }; return a + values[b]; }, 0) / confidenceLevels.length; let confidenceText = ''; let confidenceColor = ''; if (avgConfidence >= 2.5) { confidenceText = 'High'; confidenceColor = 'text-green-600'; } else if (avgConfidence >= 1.5) { confidenceText = 'Medium'; confidenceColor = 'text-amber-600'; } else { confidenceText = 'Low'; confidenceColor = 'text-red-600'; } confidenceValue.textContent = confidenceText; confidenceValue.className = `font-semibold ${confidenceColor}`; // Update analysis notes let notes = []; const referenceType = document.getElementById('referenceType').value; const referenceValue = parseFloat(document.getElementById('referenceValue').value) || null; const actualHeight = parseFloat(document.getElementById('actualHeight').value) || null; if (!referenceValue && !actualHeight) { notes.push('No reference measurement provided. Measurements are estimated based on average proportions.'); } else if (referenceValue && !actualHeight) { notes.push(`Using ${referenceType} measurement as reference. Height is estimated.`); } else if (actualHeight) { notes.push('Using provided height for proportion calculations.'); } if (measurements.weight.estimated) { notes.push('Weight is estimated based on body proportions and typical BMI ranges.'); } analysisNotes.querySelector('span').textContent = notes.join(' '); } function resetAnalysis() { // Reset file input imageUpload.value = ''; // Reset preview previewImage.src = ''; currentImage = null; // Reset measurement values Object.values(measurementElements).forEach(element => { element.value.textContent = '-- cm'; element.note.textContent = ''; element.note.className = 'text-sm text-gray-600'; }); // Reset reference inputs document.getElementById('referenceType').value = 'bust'; document.getElementById('unitSystem').value = 'metric'; document.getElementById('referenceValue').value = ''; document.getElementById('actualHeight').value = ''; document.getElementById('heightUnit').value = 'cm'; // Hide results resultsSection.classList.add('hidden'); } // Utility function to convert pixels to real measurements function pixelsToCm(pixels, referencePixels, referenceCm) { if (!referencePixels || !referenceCm) return null; return (pixels / referencePixels) * referenceCm; }