class VoiceTrack extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.recording = false; this.mediaRecorder = null; this.audioChunks = []; this.analysisResult = null; } connectedCallback() { this.shadowRoot.innerHTML = `

VoiceTrack Analysis

Record your voice to analyze pronunciation and confidence levels.

00:00

Analysis Results

Pronunciation Accuracy 0%
Confidence Level 0%
Fluency 0%
Clarity 0%
`; this.recordBtn = this.shadowRoot.getElementById('recordBtn'); this.analyzeBtn = this.shadowRoot.getElementById('analyzeBtn'); this.timer = this.shadowRoot.getElementById('timer'); this.results = this.shadowRoot.getElementById('results'); this.setupEventListeners(); } setupEventListeners() { this.recordBtn.addEventListener('click', () => { if (this.recording) { this.stopRecording(); } else { this.startRecording(); } }); this.analyzeBtn.addEventListener('click', () => { this.analyzeRecording(); }); } async startRecording() { try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); this.mediaRecorder = new MediaRecorder(stream); this.audioChunks = []; this.mediaRecorder.ondataavailable = event => { this.audioChunks.push(event.data); }; this.mediaRecorder.onstop = () => { this.recording = false; this.recordBtn.classList.remove('recording'); this.analyzeBtn.disabled = false; clearInterval(this.timerInterval); }; this.mediaRecorder.start(); this.recording = true; this.recordBtn.classList.add('recording'); this.analyzeBtn.disabled = true; this.results.style.display = 'none'; // Start timer let seconds = 0; this.timerInterval = setInterval(() => { seconds++; const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; this.timer.textContent = `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; }, 1000); } catch (error) { console.error('Error accessing microphone:', error); alert('Could not access microphone. Please check permissions.'); } } stopRecording() { if (this.mediaRecorder && this.recording) { this.mediaRecorder.stop(); this.recording = false; this.mediaRecorder.stream.getTracks().forEach(track => track.stop()); } } async analyzeRecording() { if (this.audioChunks.length === 0) return; this.analyzeBtn.disabled = true; this.analyzeBtn.innerHTML = ' Analyzing...'; const audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' }); try { // Simulate API response for demo await new Promise(resolve => setTimeout(resolve, 1500)); // Check if we're in a game context const isGamePage = window.location.pathname.includes('gamequest'); if (isGamePage) { // Game-specific analysis with higher scores this.analysisResult = { pronunciation: Math.floor(Math.random() * 20) + 80, confidence: Math.floor(Math.random() * 20) + 80, fluency: Math.floor(Math.random() * 20) + 80, clarity: Math.floor(Math.random() * 20) + 80 }; // Update game score if on game page if (typeof updateScore === 'function') { const points = Math.floor(this.analysisResult.confidence / 10); updateScore(points); } } else { // Regular analysis this.analysisResult = { pronunciation: Math.floor(Math.random() * 30) + 70, confidence: Math.floor(Math.random() * 30) + 70, fluency: Math.floor(Math.random() * 30) + 70, clarity: Math.floor(Math.random() * 30) + 70 }; } this.displayResults(); } catch (error) { console.error('Error analyzing recording:', error); alert('Error analyzing recording. Please try again.'); } finally { this.analyzeBtn.disabled = false; this.analyzeBtn.innerHTML = ' Analyze'; } } displayResults() { this.results.style.display = 'block'; this.shadowRoot.getElementById('pronunciationScore').textContent = `${this.analysisResult.pronunciation}%`; this.shadowRoot.getElementById('pronunciationBar').style.width = `${this.analysisResult.pronunciation}%`; this.shadowRoot.getElementById('confidenceScore').textContent = `${this.analysisResult.confidence}%`; this.shadowRoot.getElementById('confidenceBar').style.width = `${this.analysisResult.confidence}%`; this.shadowRoot.getElementById('fluencyScore').textContent = `${this.analysisResult.fluency}%`; this.shadowRoot.getElementById('fluencyBar').style.width = `${this.analysisResult.fluency}%`; this.shadowRoot.getElementById('clarityScore').textContent = `${this.analysisResult.clarity}%`; this.shadowRoot.getElementById('clarityBar').style.width = `${this.analysisResult.clarity}%`; } } customElements.define('voice-track', VoiceTrack);