"use strict"; // Prevent duplicate initialization if (typeof window !== 'undefined' && window.ConnectionManager) { console.warn('ConnectionManager already exists! Preventing duplicate initialization.'); throw new Error('ConnectionManager already initialized'); } // Global configuration const CONNECTION_CONFIG = { MAX_RETRIES: 3, RETRY_DELAY: 2000, TIMEOUT: 10000, STATUS_CHECK_INTERVAL: 5000, API_ENDPOINT: 'https://volunteerscience.com/openai/chat/', MODEL: 'gpt-3.5-turbo-0125', TEMPERATURE: 0.3 }; if (typeof window !== 'undefined') { window.CONNECTION_CONFIG = CONNECTION_CONFIG; } class ConnectionManager { constructor() { this.isConnected = false; this.connectionAttempts = 0; this.maxAttempts = 5; this.retryDelay = 2000; this.connectionStartTime = Date.now(); this.initializeUI(); this.startConnection(); } initializeUI() { // Get UI elements this.statusText = document.querySelector('.status-text'); this.statusIcon = document.querySelector('.fa-sync'); this.connectionLog = document.getElementById('log-entries'); this.startButton = document.getElementById('start-game'); // Create elements if they don't exist if (!this.statusText) { this.statusText = document.createElement('span'); this.statusText.className = 'status-text'; document.querySelector('.connection-status')?.appendChild(this.statusText); } if (!this.statusIcon) { this.statusIcon = document.createElement('i'); this.statusIcon.className = 'fa fa-sync fa-spin'; document.querySelector('.connection-status')?.appendChild(this.statusIcon); } if (!this.connectionLog) { this.connectionLog = document.createElement('div'); this.connectionLog.id = 'log-entries'; document.querySelector('.connection-log')?.appendChild(this.connectionLog); } // Initialize with connecting state this.updateStatus(false, 'Connecting...'); } startConnection() { // Use the previously working connection endpoint const API_ENDPOINT = 'https://volunteerscience.com/openai/chat/'; this.updateStatus(false, 'Connecting...'); this.logConnection('Attempting to connect to API...'); // Test connection with minimal payload fetch(API_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: "gpt-3.5-turbo-0125", temperature: 0.3, message: { role: "user", content: "Connection test" } }) }) .then(response => { if (response.ok) { this.handleSuccessfulConnection(); } else { throw new Error('API returned error status'); } }) .catch(error => { this.handleConnectionError(error); }); } handleSuccessfulConnection() { this.isConnected = true; this.updateStatus(true, 'Connected'); this.logConnection('Connection established successfully'); // Enable start button if (this.startButton) { this.startButton.disabled = false; } } handleConnectionError(error) { this.connectionAttempts++; this.updateStatus(false, `Connection failed (Attempt ${this.connectionAttempts}/${this.maxAttempts})`); this.logConnection(`Connection attempt failed: ${error.message}`); if (this.connectionAttempts < this.maxAttempts) { setTimeout(() => this.testConnection(), this.retryDelay); } else { this.updateStatus(false, 'Connection failed. Please try again.'); this.logConnection('Maximum connection attempts reached'); } } updateStatus(connected, message) { if (this.statusText) { this.statusText.textContent = message; this.statusText.className = `status-text ${connected ? 'connected' : 'connecting'}`; } if (this.statusIcon) { if (connected) { this.statusIcon.classList.remove('fa-spin'); this.statusIcon.style.color = '#4CAF50'; } else { this.statusIcon.classList.add('fa-spin'); this.statusIcon.style.color = ''; } } } logConnection(message, type = 'info') { if (!this.connectionLog) return; const entry = document.createElement('div'); entry.className = `log-entry ${type}`; const timestamp = new Date().toLocaleTimeString(); entry.innerHTML = `[${timestamp}] ${message}`; this.connectionLog.appendChild(entry); this.connectionLog.scrollTop = this.connectionLog.scrollHeight; } retry() { this.connectionAttempts = 0; this.connectionStartTime = Date.now(); this.isConnected = false; this.updateStatus(false, 'Retrying connection...'); this.logConnection('Manual retry initiated'); this.testConnection(); } } // Export for use in other files if (typeof window !== 'undefined') { window.ConnectionManager = ConnectionManager; } // Initialize connection manager when the page loads if (typeof window !== 'undefined') { let initializationAttempts = 0; const MAX_INIT_ATTEMPTS = 10; const INIT_RETRY_DELAY = 100; const initializeConnection = () => { // Check if all required dependencies are loaded if (!window.screenManager) { initializationAttempts++; if (initializationAttempts < MAX_INIT_ATTEMPTS) { console.log(`Waiting for ScreenManager to initialize (attempt ${initializationAttempts}/${MAX_INIT_ATTEMPTS})...`); setTimeout(initializeConnection, INIT_RETRY_DELAY); return; } else { console.error('Failed to initialize ConnectionManager: ScreenManager not found after maximum attempts'); // Create ScreenManager if it doesn't exist if (typeof ScreenManager !== 'undefined') { console.log('Creating new ScreenManager instance...'); window.screenManager = new ScreenManager(); } } } // Initialize ConnectionManager if not already initialized if (!window.connectionManager) { console.log('Creating new ConnectionManager instance...'); window.connectionManager = new ConnectionManager(); window.connectionManager.establishConnection(); } }; // Start initialization when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializeConnection); } else { initializeConnection(); } }