/** * Superior Parallel Screenshot Service * Uses the proven scalp preset parallel API technique for maximum efficiency */ // Scalping-focused timeframes (most commonly used) const SCALP_TIMEFRAMES = [ { name: '1m', tv: '1', description: 'Ultra-short scalping' }, { name: '3m', tv: '3', description: 'Short scalping' }, { name: '5m', tv: '5', description: 'Standard scalping' }, { name: '15m', tv: '15', description: 'Swing scalping' }, { name: '30m', tv: '30', description: 'Longer scalping' }, { name: '1h', tv: '60', description: 'Context timeframe' }, { name: '4h', tv: '240', description: 'Trend context' } ] // Additional timeframes for comprehensive analysis const EXTENDED_TIMEFRAMES = [ { name: '2m', tv: '2', description: 'Very short scalping' }, { name: '10m', tv: '10', description: 'Medium scalping' }, { name: '45m', tv: '45', description: 'Extended scalping' }, { name: '2h', tv: '120', description: 'Medium trend' }, { name: '6h', tv: '360', description: 'Long trend' }, { name: '12h', tv: '720', description: 'Daily trend' }, { name: '1D', tv: '1D', description: 'Daily analysis' }, { name: '3D', tv: '3D', description: 'Multi-day trend' }, { name: '1W', tv: '1W', description: 'Weekly analysis' } ] export interface SuperiorScreenshotConfig { symbol: string timeframes?: string[] // If not provided, uses SCALP_TIMEFRAMES layouts?: string[] // Default: ['ai', 'diy'] preset?: 'scalp' | 'extended' | 'all' | 'custom' analyze?: boolean // Whether to run AI analysis apiUrl?: string // API endpoint (default: http://localhost:9001) } export interface ScreenshotResult { timeframe: string timeframeName: string success: boolean screenshots?: string[] sessionId?: string error?: string } export class SuperiorScreenshotService { private apiUrl: string constructor(apiUrl: string = 'http://localhost:9001') { this.apiUrl = apiUrl } /** * Capture screenshots using the superior parallel API technique * This replaces all legacy screenshot methods with proven efficiency */ async captureParallel(config: SuperiorScreenshotConfig): Promise { console.log('šŸš€ SUPERIOR SCREENSHOT SERVICE: Parallel API Capture') const { symbol, layouts = ['ai', 'diy'], preset = 'scalp', analyze = false } = config // Determine timeframes based on preset let timeframesToCapture: typeof SCALP_TIMEFRAMES switch (preset) { case 'scalp': timeframesToCapture = SCALP_TIMEFRAMES break case 'extended': timeframesToCapture = [...SCALP_TIMEFRAMES, ...EXTENDED_TIMEFRAMES] break case 'all': timeframesToCapture = [...SCALP_TIMEFRAMES, ...EXTENDED_TIMEFRAMES] break case 'custom': if (config.timeframes) { // Convert custom timeframes to our format timeframesToCapture = config.timeframes.map(tf => ({ name: tf, tv: tf, description: 'Custom timeframe' })) } else { timeframesToCapture = SCALP_TIMEFRAMES } break default: timeframesToCapture = SCALP_TIMEFRAMES } console.log('šŸ“‹ Configuration:') console.log(` šŸ“Š Symbol: ${symbol}`) console.log(` šŸ“ˆ Preset: ${preset}`) console.log(` ā±ļø Timeframes: ${timeframesToCapture.length} (${timeframesToCapture.map(tf => tf.name).join(', ')})`) console.log(` šŸŽØ Layouts: ${layouts.length} (${layouts.join(', ')})`) console.log(` šŸ“ø Total Screenshots: ${timeframesToCapture.length * layouts.length}`) console.log(` šŸ¤– AI Analysis: ${analyze ? 'Yes' : 'No'}`) const startTime = Date.now() try { console.log('\nšŸ”„ Starting superior parallel capture...') // Create parallel promises for each timeframe using proven API technique const capturePromises = timeframesToCapture.map(async (tf, index) => { try { console.log(`šŸ“ø [${index + 1}/${timeframesToCapture.length}] Capturing ${tf.name} (${tf.tv})...`) const response = await fetch(`${this.apiUrl}/api/enhanced-screenshot`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol: symbol, timeframe: tf.tv, layouts: layouts, analyze: analyze }) }) if (!response.ok) { throw new Error(`API request failed: ${response.status} ${response.statusText}`) } const result = await response.json() if (result.success && result.screenshots) { console.log(`āœ… ${tf.name}: Captured ${result.screenshots.length}/${layouts.length} screenshots`) return { timeframe: tf.tv, timeframeName: tf.name, success: true, screenshots: result.screenshots, sessionId: result.sessionId } } else { throw new Error(result.error || 'Unknown API error') } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) console.error(`āŒ ${tf.name}: Failed - ${errorMessage}`) return { timeframe: tf.tv, timeframeName: tf.name, success: false, error: errorMessage } } }) // Wait for all parallel captures to complete console.log('\nā³ Waiting for all parallel captures to complete...') const results = await Promise.all(capturePromises) const endTime = Date.now() const duration = (endTime - startTime) / 1000 // Analyze results const successful = results.filter(r => r.success) const failed = results.filter(r => !r.success) const totalScreenshots = successful.reduce((sum, r) => sum + (r.screenshots?.length || 0), 0) console.log('\nāœ… SUPERIOR PARALLEL CAPTURE COMPLETED!') console.log(`ā±ļø Total Duration: ${duration.toFixed(2)} seconds`) console.log(`šŸ“ø Screenshots Captured: ${totalScreenshots}/${timeframesToCapture.length * layouts.length}`) console.log(`šŸŽÆ Timeframes Successful: ${successful.length}/${timeframesToCapture.length}`) console.log(`šŸš€ Average Speed: ${(totalScreenshots / duration).toFixed(1)} screenshots/second`) const successRate = (successful.length / timeframesToCapture.length * 100).toFixed(1) console.log(`šŸ“ˆ SUCCESS RATE: ${successRate}%`) if (successful.length === timeframesToCapture.length) { console.log('šŸŽ‰ PERFECT SUCCESS: All timeframes captured!') } else if (successful.length > 0) { console.log(`āš ļø PARTIAL SUCCESS: ${successful.length}/${timeframesToCapture.length} timeframes`) } return results } catch (error) { console.error('āŒ Superior screenshot service failed:', error) throw error } } /** * Quick capture for single timeframe (backwards compatibility) * Uses the superior parallel technique even for single captures */ async captureQuick(symbol: string, timeframe: string, layouts: string[] = ['ai']): Promise { console.log(`šŸš€ Quick capture using superior technique: ${symbol} ${timeframe}`) const config: SuperiorScreenshotConfig = { symbol, preset: 'custom', timeframes: [timeframe], layouts, analyze: false } const results = await this.captureParallel(config) const successfulResult = results.find(r => r.success) return successfulResult?.screenshots || [] } /** * Scalp preset - optimized for scalping strategies */ async captureScalpPreset(symbol: string, analyze: boolean = false): Promise { return this.captureParallel({ symbol, preset: 'scalp', layouts: ['ai', 'diy'], analyze }) } /** * Extended preset - comprehensive timeframe analysis */ async captureExtendedPreset(symbol: string, analyze: boolean = false): Promise { return this.captureParallel({ symbol, preset: 'extended', layouts: ['ai', 'diy'], analyze }) } /** * Legacy compatibility method - replaces old captureWithLogin */ async captureWithLogin(config: any): Promise { console.log('šŸ”„ Legacy captureWithLogin called - upgrading to superior technique') const superiorConfig: SuperiorScreenshotConfig = { symbol: config.symbol || 'SOLUSD', preset: 'custom', timeframes: [config.timeframe || '240'], layouts: config.layouts || ['ai', 'diy'], analyze: false } const results = await this.captureParallel(superiorConfig) // Return flat array of screenshot paths for compatibility return results.reduce((paths: string[], result) => { if (result.success && result.screenshots) { paths.push(...result.screenshots) } return paths }, []) } /** * No cleanup needed - API handles all browser management */ async cleanup(): Promise { console.log('āœ… Superior screenshot service cleanup (API-managed)') // No action needed - API handles all cleanup } } // Export singleton instance for drop-in replacement export const superiorScreenshotService = new SuperiorScreenshotService() // Export for legacy compatibility export const enhancedScreenshotService = superiorScreenshotService