document.addEventListener('DOMContentLoaded', async function() { // Initialize cloud data const cloudData = [ { text: "Happiness", percentage: 0 }, { text: "Adventure", percentage: 0 }, { text: "Creativity", percentage: 0 }, { text: "Friendship", percentage: 0 }, { text: "Success", percentage: 0 }, { text: "Love", percentage: 0 }, { text: "Freedom", percentage: 0 }, { text: "Peace", percentage: 0 }, { text: "Growth", percentage: 0 }, { text: "Discovery", percentage: 0 } ]; const cloudContainer = document.getElementById('cloud-container'); const textInput = document.getElementById('text-input'); const analyzeBtn = document.getElementById('analyze-btn'); const resultsSection = document.getElementById('results'); const similarityResults = document.getElementById('similarity-results'); // Load the Universal Sentence Encoder let model; try { model = await use.load(); console.log('Model loaded successfully'); } catch (err) { console.error('Failed to load model:', err); return; } // Create initial clouds createClouds(); // Add event listeners analyzeBtn.addEventListener('click', () => { analyzeBtn.disabled = true; analyzeBtn.innerHTML = ''; feather.replace(); analyzeText().finally(() => { analyzeBtn.disabled = false; analyzeBtn.innerHTML = ''; feather.replace(); }); }); textInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { analyzeBtn.click(); } }); function createClouds() { cloudContainer.innerHTML = ''; const containerWidth = cloudContainer.offsetWidth; const containerHeight = cloudContainer.offsetHeight; // Create a circular layout for initial clouds const centerX = containerWidth / 2; const centerY = containerHeight / 2; const radius = Math.min(containerWidth, containerHeight) * 0.35; cloudData.forEach((cloud, i) => { const angle = (i / cloudData.length) * Math.PI * 2; const x = centerX + Math.cos(angle) * radius; const y = centerY + Math.sin(angle) * radius; // Create cloud with base size createCloud(cloud, x, y, 40); }); } function createCloud(data, x, y, baseSize) { const cloud = document.createElement('custom-cloud'); cloud.setAttribute('text', data.text); cloud.setAttribute('percentage', data.percentage); // Position the cloud cloud.style.left = `${x}px`; cloud.style.top = `${y}px`; cloudContainer.appendChild(cloud); return cloud; } async function analyzeText() { const inputText = textInput.value.trim(); if (!inputText) { alert('Please enter some text to analyze'); return; } try { // Generate embeddings for input text and cloud texts const inputEmbedding = await model.embed([inputText]); const cloudTexts = cloudData.map(c => c.text); const cloudEmbeddings = await model.embed(cloudTexts); // Calculate cosine similarity between input and each cloud text const inputArray = await inputEmbedding.array(); const cloudArrays = await cloudEmbeddings.array(); const similarities = []; for (let i = 0; i < cloudData.length; i++) { const similarity = cosineSimilarity(inputArray[0], cloudArrays[i]); const percentage = Math.round(similarity * 100); cloudData[i].percentage = percentage; similarities.push({ text: cloudData[i].text, percentage }); } // Sort by percentage descending similarities.sort((a, b) => b.percentage - a.percentage); // Update UI with results updateClouds(); showResults(inputText, similarities); } catch (err) { console.error('Error analyzing text:', err); resultsSection.classList.add('hidden'); alert('An error occurred while analyzing your text. Please try again.'); throw err; // Re-throw to ensure button state is reset } } function updateClouds() { cloudContainer.innerHTML = ''; const containerWidth = cloudContainer.offsetWidth; const containerHeight = cloudContainer.offsetHeight; // Sort clouds by percentage (highest first) const sortedClouds = [...cloudData].sort((a, b) => b.percentage - a.percentage); // Position clouds in a circular layout const centerX = containerWidth / 2; const centerY = containerHeight / 2; const radius = Math.min(containerWidth, containerHeight) * 0.35; sortedClouds.forEach((cloud, i) => { // Calculate angle for positioning const angle = (i / sortedClouds.length) * Math.PI * 2; // Calculate position with some randomness for a natural look const randomOffset = 30; const x = centerX + Math.cos(angle) * (radius + (Math.random() * randomOffset - randomOffset/2)); const y = centerY + Math.sin(angle) * (radius + (Math.random() * randomOffset - randomOffset/2)); // Create cloud with size based on percentage const baseSize = 40 + (cloud.percentage * 0.8); createCloud(cloud, x, y, baseSize); }); } function showResults(inputText, similarities) { resultsSection.classList.remove('hidden'); similarityResults.innerHTML = ''; const heading = document.createElement('h3'); heading.className = 'font-medium text-lg mb-2'; heading.textContent = `How "${inputText}" relates to our concepts:`; similarityResults.appendChild(heading); similarities.forEach(item => { const resultItem = document.createElement('div'); resultItem.className = 'flex items-center justify-between'; const textSpan = document.createElement('span'); textSpan.className = 'text-gray-700'; textSpan.textContent = item.text; const percentageBar = document.createElement('div'); percentageBar.className = 'flex items-center w-1/2'; const barContainer = document.createElement('div'); barContainer.className = 'flex-1 bg-gray-200 rounded-full h-4 mx-2'; const bar = document.createElement('div'); bar.className = 'bg-blue-500 h-4 rounded-full'; bar.style.width = `${item.percentage}%`; const percentageText = document.createElement('span'); percentageText.className = 'text-gray-600 w-12 text-right'; percentageText.textContent = `${item.percentage}%`; barContainer.appendChild(bar); percentageBar.appendChild(barContainer); percentageBar.appendChild(percentageText); resultItem.appendChild(textSpan); resultItem.appendChild(percentageBar); similarityResults.appendChild(resultItem); }); } // Helper function to calculate cosine similarity function cosineSimilarity(vecA, vecB) { let dotProduct = 0; let normA = 0; let normB = 0; for (let i = 0; i < vecA.length; i++) { dotProduct += vecA[i] * vecB[i]; normA += vecA[i] * vecA[i]; normB += vecB[i] * vecB[i]; } normA = Math.sqrt(normA); normB = Math.sqrt(normB); return dotProduct / (normA * normB); } // Handle window resize window.addEventListener('resize', () => { if (cloudData.some(c => c.percentage > 0)) { updateClouds(); } else { createClouds(); } }); });