import { config } from './config.js'; import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // Main application state const state = { currentMode: 'sonw', evolutionInProgress: false, recursionDepth: 3, particles: [], metrics: { symbolic: 20, quantum: 15, holographic: 10, meta: 5 }, // Multiplayer state multiplayer: { connected: false, username: '', userId: '', userColor: '', researchers: {}, sharedAnalyses: [] } }; // Initialize WebsimSocket for multiplayer const room = new WebsimSocket(); // DOM elements const visualizationEl = document.getElementById('visualization'); const conceptInput = document.getElementById('conceptInput'); const symbolSelector = document.getElementById('symbolSelector'); const outputEl = document.getElementById('output'); const statusEl = document.getElementById('statusDisplay'); const depthSlider = document.getElementById('recursionDepth'); const depthValueEl = document.getElementById('depthValue'); const systemButtons = ['sonwBtn', 'afterthoughtBtn', 'cognitiveBtn', 'integratedBtn'].map(id => document.getElementById(id)); const userCountEl = document.getElementById('user-count'); const researchersEl = document.getElementById('researchers'); const shareBtn = document.getElementById('shareBtn'); const syncBtn = document.getElementById('syncBtn'); const sharedAnalysesListEl = document.getElementById('shared-analyses-list'); const userCursorsEl = document.getElementById('user-cursors'); const notificationEl = document.getElementById('notification'); // Three.js setup let scene, camera, renderer, controls; let particles, connections; const initVisualization = () => { // Setup Three.js scene scene = new THREE.Scene(); scene.background = new THREE.Color(config.visualization.backgroundColor); // Setup camera camera = new THREE.PerspectiveCamera(75, visualizationEl.clientWidth / visualizationEl.clientHeight, 0.1, 2000); camera.position.z = 300; // Setup renderer renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(visualizationEl.clientWidth, visualizationEl.clientHeight); visualizationEl.appendChild(renderer.domElement); // Add orbit controls controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; // Create particles group particles = new THREE.Group(); scene.add(particles); // Create connections group connections = new THREE.Group(); scene.add(connections); // Add grid for reference const gridHelper = new THREE.GridHelper(400, 20, 0x404040, 0x404040); gridHelper.position.y = -100; scene.add(gridHelper); // Add ambient light const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); // Add point light const pointLight = new THREE.PointLight(0xffffff, 1); pointLight.position.set(0, 150, 200); scene.add(pointLight); // Initialize particles based on current mode createParticleSystem(state.currentMode); // Start animation loop animate(); // Handle window resize window.addEventListener('resize', onWindowResize); }; const onWindowResize = () => { camera.aspect = visualizationEl.clientWidth / visualizationEl.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(visualizationEl.clientWidth, visualizationEl.clientHeight); }; const createFractalNetworkPattern = (geometry, material, modeConfig) => { // Create network-like distribution with fractal properties for (let i = 0; i < config.visualization.particleCount; i++) { const particle = new THREE.Mesh(geometry, material); // Position in fractal network structure const fractalDepth = Math.floor(Math.random() * 3) + 1; const angleXY = Math.random() * Math.PI * 2; const radiusXY = 20 + Math.random() * modeConfig.particleSpread * 0.5; // Use fractal positioning algorithm const fractalScale = 1 / (fractalDepth * 0.5); particle.position.x = Math.cos(angleXY) * radiusXY * fractalScale; particle.position.y = (fractalDepth * 40) - 60; particle.position.z = Math.sin(angleXY) * radiusXY * fractalScale; // Add controlled fractal variation particle.position.x += (Math.random() - 0.5) * 40 * fractalScale; particle.position.z += (Math.random() - 0.5) * 40 * fractalScale; // Store velocity and fractal properties for animation particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.2 * fractalScale, (Math.random() - 0.5) * 0.1 * fractalScale, (Math.random() - 0.5) * 0.2 * fractalScale ), originalPosition: particle.position.clone(), fractalDepth: fractalDepth }; particles.add(particle); state.particles.push(particle); } }; const createQuantumFieldPattern = (geometry, material, modeConfig) => { // Create quantum field-like distribution for (let i = 0; i < config.visualization.particleCount; i++) { const particle = new THREE.Mesh(geometry, material); // Position in a spherical field with superposition properties const phi = Math.acos(-1 + 2 * Math.random()); const theta = 2 * Math.PI * Math.random(); const radius = 50 + Math.random() * modeConfig.particleSpread * 0.6; particle.position.x = radius * Math.sin(phi) * Math.cos(theta); particle.position.y = radius * Math.sin(phi) * Math.sin(theta); particle.position.z = radius * Math.cos(phi); // Quantum properties for animation const superposition = Math.random() > 0.5; const entanglementFactor = Math.random(); const orbitalAxis = new THREE.Vector3( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize(); particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1 ), originalPosition: particle.position.clone(), superposition: superposition, entanglementFactor: entanglementFactor, orbitalAxis: orbitalAxis, orbitalSpeed: (Math.random() * 0.01) + 0.005 }; particles.add(particle); state.particles.push(particle); } }; const createFractalPattern = (geometry, material, modeConfig) => { // Create fractal-like distribution for Holographic Intelligence // Use recursive patterns with self-similarity const createFractalPoint = (centerPoint, scale, depth) => { if (depth <= 0 || state.particles.length >= config.visualization.particleCount) return; // Create center particle const particle = new THREE.Mesh(geometry, material); particle.position.copy(centerPoint); // Add some variation particle.position.x += (Math.random() - 0.5) * scale * 0.2; particle.position.y += (Math.random() - 0.5) * scale * 0.2; particle.position.z += (Math.random() - 0.5) * scale * 0.2; particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1 ), originalPosition: particle.position.clone(), fractalDepth: depth }; particles.add(particle); state.particles.push(particle); // Create sub-structures (branches) const branchCount = 6; const newScale = scale * 0.6; for (let i = 0; i < branchCount; i++) { // Create points in a geodesic-like pattern const angle1 = (i / branchCount) * Math.PI * 2; const angle2 = Math.PI / 4; // Fixed angle from center const newX = centerPoint.x + Math.sin(angle1) * Math.cos(angle2) * scale; const newY = centerPoint.y + Math.sin(angle1) * Math.sin(angle2) * scale; const newZ = centerPoint.z + Math.cos(angle1) * scale; const newPoint = new THREE.Vector3(newX, newY, newZ); // Recursive call for each branch createFractalPoint(newPoint, newScale, depth - 1); } }; // Start the recursive fractal generation from center createFractalPoint(new THREE.Vector3(0, 0, 0), modeConfig.particleSpread * 0.3, 3); }; const createHolisticPattern = (geometry, material, modeConfig) => { // Create an integrated pattern combining aspects of all systems // First layer: LLML networked structure (30% of particles) const llmlCount = Math.floor(config.visualization.particleCount * 0.3); for (let i = 0; i < llmlCount; i++) { const particle = new THREE.Mesh(geometry, material); // Layered network structure const layerIndex = Math.floor(Math.random() * 3); const angleXY = Math.random() * Math.PI * 2; const radiusXY = 30 + Math.random() * 60; particle.position.x = Math.cos(angleXY) * radiusXY; particle.position.y = (layerIndex * 40) - 40; particle.position.z = Math.sin(angleXY) * radiusXY; particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.15, (Math.random() - 0.5) * 0.05, (Math.random() - 0.5) * 0.15 ), originalPosition: particle.position.clone(), system: 'llml' }; particles.add(particle); state.particles.push(particle); } // Second layer: QGA quantum field (30% of particles) const qgaCount = Math.floor(config.visualization.particleCount * 0.3); for (let i = 0; i < qgaCount; i++) { const particle = new THREE.Mesh(geometry, material); // Spherical field distribution const phi = Math.acos(-1 + 2 * Math.random()); const theta = 2 * Math.PI * Math.random(); const radius = 80 + Math.random() * 70; particle.position.x = radius * Math.sin(phi) * Math.cos(theta); particle.position.y = radius * Math.sin(phi) * Math.sin(theta); particle.position.z = radius * Math.cos(phi); const orbitalAxis = new THREE.Vector3( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize(); particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1 ), originalPosition: particle.position.clone(), orbitalAxis: orbitalAxis, orbitalSpeed: (Math.random() * 0.01) + 0.005, system: 'qga' }; particles.add(particle); state.particles.push(particle); } // Third layer: Holographic fractal points (remaining particles) const holoCount = config.visualization.particleCount - llmlCount - qgaCount; // Generate a few fractal seed points for (let i = 0; i < 5; i++) { const centerPoint = new THREE.Vector3( (Math.random() - 0.5) * 150, (Math.random() - 0.5) * 150, (Math.random() - 0.5) * 150 ); // Create mini fractal clusters for (let j = 0; j < holoCount / 5; j++) { const particle = new THREE.Mesh(geometry, material); // Position in a cluster around the center point const fractalRadius = 10 + Math.random() * 25; const fractalPhi = Math.acos(-1 + 2 * Math.random()); const fractalTheta = 2 * Math.PI * Math.random(); particle.position.x = centerPoint.x + fractalRadius * Math.sin(fractalPhi) * Math.cos(fractalTheta); particle.position.y = centerPoint.y + fractalRadius * Math.sin(fractalPhi) * Math.sin(fractalTheta); particle.position.z = centerPoint.z + fractalRadius * Math.cos(fractalPhi); particle.userData = { velocity: new THREE.Vector3( (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1, (Math.random() - 0.5) * 0.1 ), originalPosition: particle.position.clone(), fractalCenter: centerPoint.clone(), system: 'holographic' }; particles.add(particle); state.particles.push(particle); } } }; const createConnections = (modeConfig) => { // Create connections between particles based on proximity const linesMaterial = new THREE.LineBasicMaterial({ color: config.visualization.connectionColor, transparent: true, opacity: 0.3 }); const particlePositions = state.particles.map(p => p.position); const threshold = config.visualization.connectionThreshold * modeConfig.connectionDensity; for (let i = 0; i < particlePositions.length; i++) { for (let j = i + 1; j < particlePositions.length; j++) { const distance = particlePositions[i].distanceTo(particlePositions[j]); if (distance < threshold) { // Create connection between these particles const lineGeometry = new THREE.BufferGeometry().setFromPoints([ particlePositions[i], particlePositions[j] ]); const line = new THREE.Line(lineGeometry, linesMaterial); connections.add(line); // Link the connection to particles line.userData = { particleIndexA: i, particleIndexB: j }; } } } }; const updateConnections = () => { // Update all connection lines to match particle positions connections.children.forEach(line => { const { particleIndexA, particleIndexB } = line.userData; if (particleIndexA < state.particles.length && particleIndexB < state.particles.length) { const posA = state.particles[particleIndexA].position; const posB = state.particles[particleIndexB].position; const positions = line.geometry.attributes.position.array; // Update positions positions[0] = posA.x; positions[1] = posA.y; positions[2] = posA.z; positions[3] = posB.x; positions[4] = posB.y; positions[5] = posB.z; line.geometry.attributes.position.needsUpdate = true; } }); }; const animate = () => { requestAnimationFrame(animate); // Animate particles based on mode animateParticles(); // Update connections updateConnections(); // Update orbital controls controls.update(); // Render scene renderer.render(scene, camera); }; const animateParticles = () => { // Apply different animation based on current mode const mode = state.currentMode; switch(mode) { case 'sonw': // Network-like movement animateSONWParticles(); break; case 'afterthought': // Quantum field movement animateQGAParticles(); break; case 'cognitive': // Fractal pattern movement animateHolographicParticles(); break; case 'integrated': // Combined animation of all systems animateIntegratedParticles(); break; } }; const animateSONWParticles = () => { state.particles.forEach(particle => { // Gentle oscillation around original position const origPos = particle.userData.originalPosition; const velocity = particle.userData.velocity; // Move with velocity particle.position.x += velocity.x; particle.position.y += velocity.y; particle.position.z += velocity.z; // Apply a force back toward original position const diffX = origPos.x - particle.position.x; const diffY = origPos.y - particle.position.y; const diffZ = origPos.z - particle.position.z; velocity.x += diffX * 0.01; velocity.y += diffY * 0.01; velocity.z += diffZ * 0.01; // Dampen velocity velocity.x *= 0.98; velocity.y *= 0.98; velocity.z *= 0.98; }); }; const animateQGAParticles = () => { state.particles.forEach(particle => { // Quantum-inspired orbital movement const velocity = particle.userData.velocity; const orbitalAxis = particle.userData.orbitalAxis; const orbitalSpeed = particle.userData.orbitalSpeed; // Apply orbital rotation const rotationMatrix = new THREE.Matrix4().makeRotationAxis(orbitalAxis, orbitalSpeed); particle.position.applyMatrix4(rotationMatrix); // Add some random quantum fluctuation velocity.x += (Math.random() - 0.5) * 0.02; velocity.y += (Math.random() - 0.5) * 0.02; velocity.z += (Math.random() - 0.5) * 0.02; // Apply velocity with strong damping (quantum fluctuations don't accumulate) particle.position.x += velocity.x; particle.position.y += velocity.y; particle.position.z += velocity.z; // Strong damping for stability velocity.x *= 0.8; velocity.y *= 0.8; velocity.z *= 0.8; }); }; const animateHolographicParticles = () => { state.particles.forEach(particle => { // Fractal pulsing movement const velocity = particle.userData.velocity; const fractalDepth = particle.userData.fractalDepth || 1; // Deeper fractal levels move less const depthFactor = 1 / (fractalDepth * 0.5); // Apply a pulsing movement const time = Date.now() * 0.001; const pulseFactor = Math.sin(time * 0.5) * 0.2 * depthFactor; // Move with velocity and pulse particle.position.x += velocity.x + (particle.position.x * pulseFactor); particle.position.y += velocity.y + (particle.position.y * pulseFactor); particle.position.z += velocity.z + (particle.position.z * pulseFactor); // Apply a centering force to maintain overall structure const centeringForce = 0.001 * depthFactor; velocity.x -= particle.position.x * centeringForce; velocity.y -= particle.position.y * centeringForce; velocity.z -= particle.position.z * centeringForce; // Dampen velocity velocity.x *= 0.95; velocity.y *= 0.95; velocity.z *= 0.95; }); }; const animateIntegratedParticles = () => { state.particles.forEach(particle => { // Apply animation based on the particle's system const system = particle.userData.system; if (system === 'llml') { // Network node behavior const origPos = particle.userData.originalPosition; const velocity = particle.userData.velocity; particle.position.x += velocity.x; particle.position.y += velocity.y; particle.position.z += velocity.z; const diffX = origPos.x - particle.position.x; const diffY = origPos.y - particle.position.y; const diffZ = origPos.z - particle.position.z; velocity.x += diffX * 0.01; velocity.y += diffY * 0.01; velocity.z += diffZ * 0.01; velocity.x *= 0.98; velocity.y *= 0.98; velocity.z *= 0.98; } else if (system === 'qga') { // Quantum field behavior const velocity = particle.userData.velocity; const orbitalAxis = particle.userData.orbitalAxis; const orbitalSpeed = particle.userData.orbitalSpeed; const rotationMatrix = new THREE.Matrix4().makeRotationAxis(orbitalAxis, orbitalSpeed); particle.position.applyMatrix4(rotationMatrix); velocity.x += (Math.random() - 0.5) * 0.02; velocity.y += (Math.random() - 0.5) * 0.02; velocity.z += (Math.random() - 0.5) * 0.02; particle.position.x += velocity.x; particle.position.y += velocity.y; particle.position.z += velocity.z; velocity.x *= 0.8; velocity.y *= 0.8; velocity.z *= 0.8; } else if (system === 'holographic') { // Fractal behavior const velocity = particle.userData.velocity; const fractalCenter = particle.userData.fractalCenter; // Pulsing movement const time = Date.now() * 0.001; const pulseFactor = Math.sin(time * 0.5) * 0.2; // Vector from fractal center to particle const dirX = particle.position.x - fractalCenter.x; const dirY = particle.position.y - fractalCenter.y; const dirZ = particle.position.z - fractalCenter.z; // Apply pulse along this direction particle.position.x += velocity.x + (dirX * pulseFactor * 0.01); particle.position.y += velocity.y + (dirY * pulseFactor * 0.01); particle.position.z += velocity.z + (dirZ * pulseFactor * 0.01); // Apply a centering force to maintain cluster const centeringForce = 0.001; velocity.x -= dirX * centeringForce; velocity.y -= dirY * centeringForce; velocity.z -= dirZ * centeringForce; velocity.x *= 0.95; velocity.y *= 0.95; velocity.z *= 0.95; } }); // Add emergent behavior for the integrated system // This creates interactions between the different systems // Slow rotation of the entire system particles.rotation.y += 0.0005; connections.rotation.y += 0.0005; }; const createParticleSystem = (mode) => { // Clear existing particles and connections while(particles.children.length > 0) { particles.remove(particles.children[0]); } while(connections.children.length > 0) { connections.remove(connections.children[0]); } // Get mode configuration const modeConfig = config.modes[mode]; // Create particles const particleGeometry = new THREE.SphereGeometry(config.visualization.nodeSize, 16, 16); const particleMaterial = new THREE.MeshPhongMaterial({ color: new THREE.Color(modeConfig.color), emissive: new THREE.Color(modeConfig.color).multiplyScalar(0.5), shininess: 50 }); // Create particles based on pattern type state.particles = []; switch(modeConfig.patternType) { case 'fractal-network': // Create fractal-network pattern (SONW) createFractalNetworkPattern(particleGeometry, particleMaterial, modeConfig); break; case 'quantum-field': // Create quantum field pattern (Afterthought) createQuantumFieldPattern(particleGeometry, particleMaterial, modeConfig); break; case 'holographic': // Create holographic pattern (Cognitive) createFractalPattern(particleGeometry, particleMaterial, modeConfig); break; case 'holistic': // Create holistic pattern (Integrated) createHolisticPattern(particleGeometry, particleMaterial, modeConfig); break; } // Create connections between particles createConnections(modeConfig); }; const handleSymbolicProcess = async () => { if (state.evolutionInProgress) return; // Get symbolic expression from input or selector let symbolicExpression = conceptInput.value.trim(); if (!symbolicExpression) { // Use selected expression from dropdown const selectedKey = symbolSelector.value; symbolicExpression = config.symbolicExpressions[selectedKey].expression; } // Start processing animation updateStatus(`Processing symbolic expression: ${symbolicExpression}`); outputEl.innerHTML = `

Analyzing ${symbolicExpression}...

`; visualizationEl.classList.add('recursing'); // Simulate processing with the current system await new Promise(resolve => setTimeout(resolve, 1500)); // Generate analysis await generateSymbolicAnalysis(symbolicExpression); // End animation visualizationEl.classList.remove('recursing'); }; const generateSymbolicAnalysis = async (expression) => { // Using the LLM to generate a better response let analysisOutput = ''; try { // Prepare prompt for LLM const systemPrompt = `You are the Meta-Cosmic-Weaver, an advanced AI that integrates SONW (Symbolicentric Orbital Neural Weave), Afterthought Quantum Conceptualization, and Cognitive Engine components into a Triadic Architecture for recursive intelligence. Analyze the symbolic LLML expression provided and generate 3 insights corresponding to these three levels: Insight 1 (SONW): Analyze the expression as a fractal-symbolic framework using algebraic reasoning structures and neural-symbolic integration. Insight 2 (Afterthought): Provide a quantum-inspired interpretation that explores superposition, entanglement, and probabilistic consciousness. Insight 3 (Cognitive): Offer a meta-mathematical interpretation that treats the expression as an executable semantic transformation protocol. Use terminology from: quantum mechanics, geometric algebra, fractal mathematics, neural-symbolic integration, and recursive symbolic systems. Each insight should build upon the previous one with increasing sophistication.`; const messages = [ { role: "system", content: systemPrompt }, { role: "user", content: `Generate three progressive insights for the LLML symbolic expression: ${expression}` } ]; // Generate response using LLM const completion = await websim.chat.completions.create({ messages: messages }); analysisOutput = completion.content; } catch (error) { // Fallback to template-based generation console.log("Using template-based generation instead of LLM"); analysisOutput = generateTemplateBasedAnalysis(expression); } // Display output with animation outputEl.innerHTML = ''; // Clear output // Split by paragraphs and display with delay const paragraphs = analysisOutput.split('\n\n'); let insightCounter = 1; let currentInsight = null; for (let i = 0; i < paragraphs.length; i++) { if (paragraphs[i].trim()) { // Check if this is a new insight section if (paragraphs[i].toLowerCase().includes('insight') && paragraphs[i].includes(':')) { // Create a new insight section currentInsight = document.createElement('div'); currentInsight.className = 'insight-level'; const header = document.createElement('h4'); header.textContent = `Insight ${insightCounter}: ${paragraphs[i].split(':')[1].trim()}`; currentInsight.appendChild(header); outputEl.appendChild(currentInsight); insightCounter++; } else { // Add paragraph to current insight or directly to output const para = document.createElement('p'); para.textContent = paragraphs[i]; para.style.opacity = 0; para.style.transform = 'translateY(10px)'; para.style.transition = 'opacity 0.5s, transform 0.5s'; if (currentInsight) { currentInsight.appendChild(para); } else { outputEl.appendChild(para); } // Animate paragraph appearance await new Promise(resolve => setTimeout(resolve, 300)); para.style.opacity = 1; para.style.transform = 'translateY(0)'; } } } // Update status updateStatus(`Analysis of "${expression}" complete using ${config.modes[state.currentMode].name}`); }; const generateTemplateBasedAnalysis = (expression) => { // Template-based generation let output = ''; const templates = config.llmlAnalysis[state.currentMode]; // Generate 3 insights for (let i = 0; i < 3; i++) { // Select template for insight level const templateIndex = i % templates.length; const template = templates[templateIndex]; // Add insight header output += `Insight ${i+1}: ${state.currentMode.charAt(0).toUpperCase() + state.currentMode.slice(1)} Analysis\n\n`; // Fill in template let insight = template.replace('{expression}', expression); // Add process const processes = config.recursion.processes; const process = processes[Math.floor(Math.random() * processes.length)]; insight = insight.replace('{process}', process); // Add insight const insights = config.recursion.insights; const insightText = insights[Math.floor(Math.random() * insights.length)]; insight = insight.replace('{insight}', insightText); // Add number const number = Math.floor(Math.random() * 8) + 3; // 3-10 insight = insight.replace('{number}', number); output += insight + '\n\n'; } return output; }; const updateStatus = (message) => { statusEl.textContent = message; statusEl.classList.add('pulsing'); setTimeout(() => { statusEl.classList.remove('pulsing'); }, 1000); }; const handleEvolve = async () => { if (state.evolutionInProgress) return; state.evolutionInProgress = true; const depth = state.recursionDepth; // Update status updateStatus(`Initiating meta-recursive evolution cycle (depth: ${depth})...`); // Notify other users if connected if (state.multiplayer.connected) { room.send({ type: 'evolution_triggered', depth: depth, username: state.multiplayer.username }); } // Calculate duration based on depth const duration = config.evolution.baseDuration + (depth * config.evolution.depthMultiplier); // Trigger evolution animation visualizationEl.classList.add('evolving'); // Gradually improve metrics during evolution const startMetrics = { ...state.metrics }; const targetMetrics = { symbolic: Math.min(startMetrics.symbolic + (depth * 15), 100), quantum: Math.min(startMetrics.quantum + (depth * 12), 100), holographic: Math.min(startMetrics.holographic + (depth * 10), 100), meta: Math.min(startMetrics.meta + (depth * 8), 100) }; // Evolution steps for (let i = 0; i < config.evolution.evolutionSteps.length; i++) { const step = config.evolution.evolutionSteps[i]; updateStatus(`Evolution step ${i+1}/${config.evolution.evolutionSteps.length}: ${step}`); // Update metrics proportionally for each step const progress = (i + 1) / config.evolution.evolutionSteps.length; state.metrics = { symbolic: startMetrics.symbolic + (targetMetrics.symbolic - startMetrics.symbolic) * progress, quantum: startMetrics.quantum + (targetMetrics.quantum - startMetrics.quantum) * progress, holographic: startMetrics.holographic + (targetMetrics.holographic - startMetrics.holographic) * progress, meta: startMetrics.meta + (targetMetrics.meta - startMetrics.meta) * progress }; updateMetricsBars(); // Add visual effects during evolution if (i === 0) { // Symbolic embedding - SONW pattern briefly createParticleSystem('sonw'); } else if (i === 1) { // Quantum processing - Afterthought pattern briefly createParticleSystem('afterthought'); } else if (i === 2) { // Holographic integration - Holographic pattern briefly createParticleSystem('cognitive'); } else if (i === 3) { // Meta-evolution - Return to integrated pattern with improvements createParticleSystem('integrated'); } // Wait between steps await new Promise(resolve => setTimeout(resolve, duration / config.evolution.evolutionSteps.length)); } // Evolution complete updateStatus(`Meta-recursive evolution complete (depth: ${depth})`); visualizationEl.classList.remove('evolving'); // Return to original mode if not already in integrated if (state.currentMode !== 'integrated') { createParticleSystem(state.currentMode); } // Update room state with new metrics if (state.multiplayer.connected) { room.party.updateRoomState({ metrics: state.metrics }); } state.evolutionInProgress = false; }; const handleModeChange = (mode) => { if (state.evolutionInProgress) return; state.currentMode = mode; // Update active button updateSystemButtonsUI(); // Update visualization createParticleSystem(mode); // Update status updateStatus(`System switched to ${config.modes[mode].name}`); // Update presence if (state.multiplayer.connected) { room.party.updatePresence({ mode: mode }); // Send mode change event room.send({ type: 'mode_change', mode: mode, username: state.multiplayer.username }); } }; const updateMetricsBars = () => { document.getElementById('symbolicBar').style.width = `${state.metrics.symbolic}%`; document.getElementById('quantumBar').style.width = `${state.metrics.quantum}%`; document.getElementById('holoBar').style.width = `${state.metrics.holographic}%`; document.getElementById('metaBar').style.width = `${state.metrics.meta}%`; }; const initMultiplayer = async () => { try { // Get current user state.multiplayer.userId = room.party.client.id; state.multiplayer.username = room.party.client.username; // Assign a color to the user const colorIndex = Object.keys(room.party.peers).length % config.multiplayer.userColors.length; state.multiplayer.userColor = config.multiplayer.userColors[colorIndex]; // Update presence with user info and initial state room.party.updatePresence({ username: state.multiplayer.username, color: state.multiplayer.userColor, mode: state.currentMode, cursorX: 0, cursorY: 0, isActive: true }); // Subscribe to presence updates room.party.subscribePresence(handlePresenceUpdates); // Update room state with current system state if we're the first user if (Object.keys(room.party.peers).length === 1) { room.party.updateRoomState({ currentMode: state.currentMode, metrics: state.metrics, sharedAnalyses: [] }); } // Subscribe to room state changes room.party.subscribeRoomState(handleRoomStateChanges); // Set up event listeners room.onmessage = handleMessage; // Set up mouse move for cursor sharing visualizationEl.addEventListener('mousemove', handleMouseMove); // Set up touch move for mobile visualizationEl.addEventListener('touchmove', handleTouchMove); state.multiplayer.connected = true; showNotification(`Connected as ${state.multiplayer.username}`); } catch (error) { console.error('Error initializing multiplayer:', error); showNotification('Failed to connect to multiplayer session'); } }; const handlePresenceUpdates = (presence) => { // Update local state with researchers state.multiplayer.researchers = presence; // Update UI updateResearchersUI(); updateUserCursors(); // Update user count const userCount = Object.keys(presence).length; userCountEl.textContent = userCount; }; const handleRoomStateChanges = (roomState) => { // Check if room state is defined if (!roomState) return; // Update mode if changed by another user if (roomState.currentMode && roomState.currentMode !== state.currentMode) { state.currentMode = roomState.currentMode; updateSystemButtonsUI(); createParticleSystem(state.currentMode); } // Update metrics if changed if (roomState.metrics) { state.metrics = roomState.metrics; updateMetricsBars(); } // Update shared analyses if changed if (roomState.sharedAnalyses) { state.multiplayer.sharedAnalyses = roomState.sharedAnalyses; updateSharedAnalysesUI(); } }; const handleMessage = (event) => { const data = event.data; switch (data.type) { case 'connected': showNotification(`${data.username} connected`); break; case 'disconnected': showNotification(`${data.username} disconnected`); break; case 'mode_change': if (data.clientId !== state.multiplayer.userId) { showNotification(`${data.username} switched mode to ${config.modes[data.mode].name}`); } break; case 'analysis_shared': if (data.clientId !== state.multiplayer.userId) { showNotification(`${data.username} shared an analysis of "${data.expression}"`); } break; case 'evolution_triggered': if (data.clientId !== state.multiplayer.userId) { showNotification(`${data.username} triggered evolution (depth: ${data.depth})`); } break; } }; const updateResearchersUI = () => { researchersEl.innerHTML = ''; for (const userId in state.multiplayer.researchers) { const researcher = state.multiplayer.researchers[userId]; if (!researcher.username || !researcher.isActive) continue; const researcherEl = document.createElement('div'); researcherEl.className = 'researcher'; const colorEl = document.createElement('div'); colorEl.className = 'researcher-color'; colorEl.style.backgroundColor = researcher.color; const nameEl = document.createElement('div'); nameEl.className = 'researcher-name'; nameEl.textContent = researcher.username; researcherEl.appendChild(colorEl); researcherEl.appendChild(nameEl); researchersEl.appendChild(researcherEl); } }; const updateUserCursors = () => { userCursorsEl.innerHTML = ''; for (const userId in state.multiplayer.researchers) { // Skip own cursor if (userId === state.multiplayer.userId) continue; const researcher = state.multiplayer.researchers[userId]; if (!researcher.isActive) continue; const cursorEl = document.createElement('div'); cursorEl.className = 'user-cursor'; cursorEl.style.backgroundColor = researcher.color; cursorEl.style.left = `${researcher.cursorX}px`; cursorEl.style.top = `${researcher.cursorY}px`; // Add username label const labelEl = document.createElement('div'); labelEl.style.position = 'absolute'; labelEl.style.top = '20px'; labelEl.style.left = '10px'; labelEl.style.fontSize = '12px'; labelEl.style.whiteSpace = 'nowrap'; labelEl.textContent = researcher.username; cursorEl.appendChild(labelEl); userCursorsEl.appendChild(cursorEl); } }; const handleMouseMove = (event) => { if (!state.multiplayer.connected) return; // Get cursor position relative to visualization element const rect = visualizationEl.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; // Update presence with cursor position room.party.updatePresence({ cursorX: x, cursorY: y }); }; const handleTouchMove = (event) => { if (!state.multiplayer.connected || !event.touches[0]) return; // Get touch position relative to visualization element const rect = visualizationEl.getBoundingClientRect(); const x = event.touches[0].clientX - rect.left; const y = event.touches[0].clientY - rect.top; // Update presence with cursor position room.party.updatePresence({ cursorX: x, cursorY: y }); }; const shareAnalysis = () => { if (!state.multiplayer.connected) return; // Get current output content const outputContent = outputEl.innerText; // Check if there's content to share if (!outputContent || outputContent.includes('placeholder')) { showNotification('Nothing to share. Process an expression first.'); return; } // Get the current expression let expression = conceptInput.value.trim(); if (!expression) { // Use selected expression from dropdown const selectedKey = symbolSelector.value; expression = config.symbolicExpressions[selectedKey].expression; } // Create shared analysis const sharedAnalysis = { id: Date.now().toString(), username: state.multiplayer.username, userId: state.multiplayer.userId, color: state.multiplayer.userColor, timestamp: new Date().toISOString(), expression, content: outputContent.substring(0, config.multiplayer.sharingSettings.characterLimit), mode: state.currentMode }; // Get current shared analyses const sharedAnalyses = [...state.multiplayer.sharedAnalyses]; // Add new analysis sharedAnalyses.push(sharedAnalysis); // Limit number of shared analyses if (sharedAnalyses.length > config.multiplayer.sharingSettings.maxSharedAnalyses) { sharedAnalyses.shift(); } // Update room state room.party.updateRoomState({ sharedAnalyses }); // Send notification to other users room.send({ type: 'analysis_shared', expression, username: state.multiplayer.username }); showNotification('Analysis shared with all researchers'); }; const syncVisualization = () => { if (!state.multiplayer.connected) return; // Update room state with current state room.party.updateRoomState({ currentMode: state.currentMode, metrics: state.metrics }); showNotification('Visualization synchronized with all researchers'); }; const updateSharedAnalysesUI = () => { sharedAnalysesListEl.innerHTML = ''; if (state.multiplayer.sharedAnalyses.length === 0) { sharedAnalysesListEl.innerHTML = '

No shared analyses yet.

'; return; } // Sort analyses by timestamp (newest first) const sortedAnalyses = [...state.multiplayer.sharedAnalyses].sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp) ); for (const analysis of sortedAnalyses) { const analysisEl = document.createElement('div'); analysisEl.className = 'shared-analysis'; const headerEl = document.createElement('div'); headerEl.className = 'shared-header'; const userEl = document.createElement('span'); userEl.style.color = analysis.color; userEl.textContent = analysis.username; const timeEl = document.createElement('span'); timeEl.textContent = formatTimestamp(analysis.timestamp); headerEl.appendChild(userEl); headerEl.appendChild(timeEl); const expressionEl = document.createElement('div'); expressionEl.className = 'shared-expression'; expressionEl.textContent = `"${analysis.expression}"`; const contentEl = document.createElement('div'); contentEl.className = 'shared-content'; contentEl.innerHTML = analysis.content; analysisEl.appendChild(headerEl); analysisEl.appendChild(expressionEl); analysisEl.appendChild(contentEl); sharedAnalysesListEl.appendChild(analysisEl); } }; const formatTimestamp = (timestamp) => { const date = new Date(timestamp); return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }; const showNotification = (message) => { notificationEl.textContent = message; notificationEl.classList.add('show'); setTimeout(() => { notificationEl.classList.remove('show'); }, config.multiplayer.notificationDuration); }; const updateSystemButtonsUI = () => { systemButtons.forEach(btn => { btn.classList.remove('active'); if (btn.id === `${state.currentMode}Btn`) { btn.classList.add('active'); } }); }; // Event listeners window.addEventListener('DOMContentLoaded', () => { // Initialize visualization initVisualization(); // Initialize metrics display updateMetricsBars(); // Initialize multiplayer initMultiplayer(); // Mode buttons document.getElementById('sonwBtn').addEventListener('click', () => handleModeChange('sonw')); document.getElementById('afterthoughtBtn').addEventListener('click', () => handleModeChange('afterthought')); document.getElementById('cognitiveBtn').addEventListener('click', () => handleModeChange('cognitive')); document.getElementById('integratedBtn').addEventListener('click', () => handleModeChange('integrated')); // Recursion depth slider depthSlider.addEventListener('input', () => { state.recursionDepth = parseInt(depthSlider.value); depthValueEl.textContent = depthSlider.value; }); // Evolution button document.getElementById('evolveBtn').addEventListener('click', handleEvolve); // Symbolic expression selector symbolSelector.addEventListener('change', () => { const selectedKey = symbolSelector.value; const selectedExpression = config.symbolicExpressions[selectedKey]; conceptInput.placeholder = selectedExpression.expression; // Display preview outputEl.innerHTML = `

${selectedExpression.description}

${selectedExpression.expression}

Press "Process" to analyze this expression...

`; }); // Process symbolic expression document.getElementById('processBtn').addEventListener('click', handleSymbolicProcess); conceptInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { handleSymbolicProcess(); } }); // Collaborative features shareBtn.addEventListener('click', shareAnalysis); syncBtn.addEventListener('click', syncVisualization); // Handle window unload to update presence window.addEventListener('beforeunload', () => { if (state.multiplayer.connected) { room.party.updatePresence({ isActive: false }); } }); });