|
|
import { Component, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core'; |
|
|
import { FindwordService } from '../findword/findword.service'; |
|
|
import { Router } from '@angular/router'; |
|
|
import { HeaderComponent } from '../shared/header/header.component'; |
|
|
import { ButtonComponent } from '../shared/button/button.component'; |
|
|
import { CommonModule } from '@angular/common'; |
|
|
import { FormsModule } from '@angular/forms'; |
|
|
|
|
|
@Component({ |
|
|
selector: 'app-findword', |
|
|
templateUrl: './findword.component.html', |
|
|
styleUrl: './findword.component.css', |
|
|
standalone: true, |
|
|
imports: [ButtonComponent, CommonModule, FormsModule, HeaderComponent] |
|
|
}) |
|
|
export class FindwordComponent { |
|
|
@ViewChild('audioPlayer', { static: false }) audioPlayer?: ElementRef<HTMLAudioElement>; |
|
|
@ViewChild('audioPlayer') audioRef!: ElementRef<HTMLAudioElement>; |
|
|
|
|
|
step: number = 1; |
|
|
progress: number = 0; |
|
|
audioUrl: string | null = null; |
|
|
userInput: string = ''; |
|
|
validationMessage: string = ''; |
|
|
isCorrect: boolean = false; |
|
|
isLoading: boolean = false; |
|
|
attemptsLeft: number = 3; |
|
|
correctWord: string | null = null; |
|
|
isGenerateDisabled: boolean = false; |
|
|
wordMeaning: string | null = null; |
|
|
wordSentence: string | null = null; |
|
|
showMeaning: boolean = false; |
|
|
showSentence: boolean = false; |
|
|
isPopupVisible: boolean = false; |
|
|
popupMessage: string = ''; |
|
|
audioFinished: boolean = false; |
|
|
canSubmit: boolean = false; |
|
|
isPlaying: boolean = false; |
|
|
currentTimeDisplay = '0:00'; |
|
|
durationDisplay = '0:00'; |
|
|
constructor( |
|
|
private findwordService: FindwordService, |
|
|
private cd: ChangeDetectorRef, |
|
|
private router: Router |
|
|
) { } |
|
|
|
|
|
fetchAudio() { |
|
|
this.isLoading = true; |
|
|
this.correctWord = null; |
|
|
this.attemptsLeft = 3; |
|
|
this.validationMessage = ''; |
|
|
this.userInput = ''; |
|
|
this.isGenerateDisabled = true; |
|
|
this.wordMeaning = null; |
|
|
this.wordSentence = null; |
|
|
this.showMeaning = true; |
|
|
this.showSentence = true; |
|
|
this.audioFinished = false; |
|
|
this.canSubmit = false; |
|
|
|
|
|
console.log("π€ Fetching new vocabulary..."); |
|
|
|
|
|
this.findwordService.fetchAudio().subscribe((response: any) => { |
|
|
if (!response || !response.audio_file_path || !response.word) { |
|
|
console.error("β Invalid response from backend:", response); |
|
|
return; |
|
|
} |
|
|
|
|
|
this.correctWord = response.word.trim(); |
|
|
this.wordMeaning = response.meaning; |
|
|
this.wordSentence = response.sentence; |
|
|
console.log("β
Correct Word Set:", this.correctWord); |
|
|
|
|
|
this.audioUrl = this.findwordService.buildAssetUrl(response.audio_file_path); |
|
|
this.cd.detectChanges(); |
|
|
|
|
|
setTimeout(() => { |
|
|
if (this.audioPlayer && this.audioPlayer.nativeElement) { |
|
|
console.log("π Loading new audio..."); |
|
|
this.audioPlayer.nativeElement.load(); |
|
|
|
|
|
this.audioPlayer.nativeElement.onended = () => { |
|
|
console.log("π Audio finished playing"); |
|
|
this.audioFinished = true; |
|
|
}; |
|
|
} else { |
|
|
console.error("β Audio player not found!"); |
|
|
} |
|
|
}, 500); |
|
|
}, error => { |
|
|
console.error('β Error fetching audio:', error); |
|
|
this.isLoading = false; |
|
|
}); |
|
|
} |
|
|
|
|
|
onInputChange(): void { |
|
|
this.canSubmit = this.userInput.trim().length > 0; |
|
|
} |
|
|
|
|
|
startGame(): void { |
|
|
this.resetStep2State(); |
|
|
this.step = 2; |
|
|
this.progress = 0; |
|
|
} |
|
|
|
|
|
getMeaning() { |
|
|
if (this.wordMeaning) { |
|
|
this.popupMessage = `Meaning: ${this.wordMeaning}`; |
|
|
} else { |
|
|
this.popupMessage = 'Meaning not available for this word.'; |
|
|
} |
|
|
this.isPopupVisible = true; |
|
|
} |
|
|
|
|
|
getSentence() { |
|
|
if (this.wordSentence) { |
|
|
this.popupMessage = `Example Sentence: ${this.wordSentence}`; |
|
|
} else { |
|
|
this.popupMessage = 'Example sentence not available for this word.'; |
|
|
} |
|
|
this.isPopupVisible = true; |
|
|
} |
|
|
|
|
|
validateWord() { |
|
|
if (this.attemptsLeft <= 0) { |
|
|
this.showMeaning = true; |
|
|
this.showSentence = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
console.log(`π Validating answer: ${this.userInput} (Attempts left: ${this.attemptsLeft})`); |
|
|
|
|
|
if (!this.correctWord) { |
|
|
console.error("β Error: No correct word set for validation!"); |
|
|
this.validationMessage = 'Error validating word: Missing correct word.'; |
|
|
this.showMeaning = true; |
|
|
this.showSentence = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
const requestData = { |
|
|
user_input: this.userInput.trim(), |
|
|
correct_word: this.correctWord.trim().replace('.', '') |
|
|
}; |
|
|
console.log("π€ Sending validation request:", requestData); |
|
|
|
|
|
this.findwordService.validateWord(this.userInput, this.correctWord).subscribe(response => { |
|
|
console.log("π₯ Validation Response:", response); |
|
|
|
|
|
if (response.status === 'success') { |
|
|
this.validationMessage = "β
Correct!"; |
|
|
this.isCorrect = true; |
|
|
this.ui.pulseOk = true; |
|
|
setTimeout(() => (this.ui.pulseOk = false), 1200); |
|
|
this.attemptsLeft = 0; |
|
|
this.popupMessage = this.validationMessage; |
|
|
this.isGenerateDisabled = true; |
|
|
} else { |
|
|
this.attemptsLeft--; |
|
|
if (this.attemptsLeft === 0) { |
|
|
this.validationMessage = `β Incorrect! The correct word was '${this.correctWord}'.`; |
|
|
this.correctWord = response.correct_word; |
|
|
this.isGenerateDisabled = true; |
|
|
this.showMeaning = true; |
|
|
this.showSentence = true; |
|
|
} else { |
|
|
this.validationMessage = `β Incorrect! You have ${this.attemptsLeft} attempt(s) left.`; |
|
|
} |
|
|
this.isCorrect = false; |
|
|
this.ui.shake = true; |
|
|
setTimeout(() => (this.ui.shake = false), 400); |
|
|
} |
|
|
}, error => { |
|
|
console.error("β Validation API Error:", error); |
|
|
this.validationMessage = 'Error validating word: API failed.'; |
|
|
}); |
|
|
} |
|
|
|
|
|
onAudioReady() { |
|
|
console.log("π§ Audio is ready, trying to play..."); |
|
|
if (this.audioPlayer) { |
|
|
this.audioPlayer.nativeElement.play().then(() => { |
|
|
console.log("β
Audio played successfully."); |
|
|
}).catch((error: any) => { |
|
|
console.error("β Play failed:", error); |
|
|
}); |
|
|
} |
|
|
} |
|
|
pauseAudio() { |
|
|
if (this.audioPlayer?.nativeElement) { |
|
|
this.audioPlayer.nativeElement.pause(); |
|
|
} |
|
|
} |
|
|
playAudio() { |
|
|
if (this.audioPlayer?.nativeElement) { |
|
|
this.audioPlayer.nativeElement.play(); |
|
|
} |
|
|
|
|
|
console.log("π΅ Play button clicked. Trying to play audio:", this.audioUrl); |
|
|
|
|
|
if (this.audioPlayer && this.audioPlayer.nativeElement) { |
|
|
this.audioPlayer.nativeElement.play().then(() => { |
|
|
console.log("β
Audio played successfully."); |
|
|
}).catch((error: any) => { |
|
|
console.error("β Manual play failed:", error); |
|
|
}); |
|
|
} else { |
|
|
console.error("β Audio player not found!"); |
|
|
} |
|
|
} |
|
|
|
|
|
nextQuestion() { |
|
|
this.isGenerateDisabled = false; |
|
|
this.audioUrl = null; |
|
|
this.userInput = ''; |
|
|
this.validationMessage = ''; |
|
|
this.attemptsLeft = 3; |
|
|
this.correctWord = null; |
|
|
this.showMeaning = false; |
|
|
this.showSentence = false; |
|
|
this.isCorrect = false; |
|
|
this.isLoading = false; |
|
|
this.fetchAudio(); |
|
|
} |
|
|
|
|
|
goToHome() { |
|
|
this.router.navigate(['/home']); |
|
|
} |
|
|
|
|
|
goBack(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (audio) { try { audio.pause(); } catch { } } |
|
|
this.step = 1; |
|
|
} |
|
|
|
|
|
showMeaningPanel() { |
|
|
if (this.wordMeaning) { |
|
|
this.popupMessage = `π Meaning: ${this.wordMeaning}`; |
|
|
} else { |
|
|
this.popupMessage = 'Meaning not available for this word.'; |
|
|
} |
|
|
this.isPopupVisible = true; |
|
|
this.ui.showMeaning = true; |
|
|
this.ui.showExample = false; |
|
|
this.ui.meaningText = (this as any).meaningText || (this as any).meaning || ''; |
|
|
} |
|
|
|
|
|
showSentencePanel() { |
|
|
if (this.wordSentence) { |
|
|
this.popupMessage = `β Example Sentence: ${this.wordSentence}`; |
|
|
} else { |
|
|
this.popupMessage = 'Example sentence not available for this word.'; |
|
|
} |
|
|
this.isPopupVisible = true; |
|
|
this.ui.showExample = true; |
|
|
this.ui.showMeaning = false; |
|
|
this.ui.exampleText = (this as any).exampleText || (this as any).sentence || (this as any).exampleSentence || ''; |
|
|
} |
|
|
|
|
|
closePopup() { |
|
|
console.log("β Closing popup..."); |
|
|
this.isPopupVisible = false; |
|
|
} |
|
|
|
|
|
get isMeaningButtonDisabled(): boolean { |
|
|
return !(this.isCorrect || this.attemptsLeft <= 2); |
|
|
} |
|
|
|
|
|
get isExampleButtonDisabled(): boolean { |
|
|
return !(this.isCorrect || this.attemptsLeft === 0); |
|
|
} |
|
|
|
|
|
bars = Array.from({ length: 12 }); |
|
|
|
|
|
togglePlayback(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (!audio || !this.audioUrl) { return; } |
|
|
|
|
|
if (audio.paused) { |
|
|
audio.play().then(() => { |
|
|
this.isPlaying = true; |
|
|
}).catch(() => { |
|
|
this.isPlaying = false; |
|
|
}); |
|
|
} else { |
|
|
audio.pause(); |
|
|
this.isPlaying = false; |
|
|
} |
|
|
} |
|
|
|
|
|
onLoadedMeta(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (!audio) { return; } |
|
|
this.durationDisplay = this.formatTime(audio.duration); |
|
|
this.currentTimeDisplay = '0:00'; |
|
|
this.progress = 0; |
|
|
this.isPlaying = false; |
|
|
if (typeof this.audioFinished !== 'undefined') { |
|
|
this.audioFinished = false; |
|
|
} |
|
|
} |
|
|
|
|
|
onTimeUpdate(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (!audio) { return; } |
|
|
const current = isFinite(audio.currentTime) ? audio.currentTime : 0; |
|
|
const dur = isFinite(audio.duration) ? audio.duration : 0.00001; |
|
|
this.currentTimeDisplay = this.formatTime(current); |
|
|
this.progress = Math.min(100, (current / dur) * 100); |
|
|
} |
|
|
|
|
|
onAudioEnded(): void { |
|
|
this.isPlaying = false; |
|
|
this.progress = 100; |
|
|
if (typeof this.audioFinished !== 'undefined') { |
|
|
this.audioFinished = true; |
|
|
} |
|
|
} |
|
|
|
|
|
private formatTime(sec: number): string { |
|
|
if (!isFinite(sec)) { return '0:00'; } |
|
|
const m = Math.floor(sec / 60); |
|
|
const s = Math.floor(sec % 60); |
|
|
return `${m}:${s.toString().padStart(2, '0')}`; |
|
|
} |
|
|
|
|
|
private resetPlayerUI(): void { |
|
|
this.isPlaying = false; |
|
|
this.progress = 0; |
|
|
this.currentTimeDisplay = '0:00'; |
|
|
this.durationDisplay = '0:00'; |
|
|
} |
|
|
|
|
|
ui = { |
|
|
pulseOk: false, |
|
|
shake: false, |
|
|
showMeaning: false, |
|
|
showExample: false, |
|
|
meaningText: '', |
|
|
exampleText: '' |
|
|
}; |
|
|
|
|
|
private resetStep2State(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (audio) { |
|
|
try { audio.pause(); } catch { } |
|
|
audio.currentTime = 0; |
|
|
} |
|
|
this.audioUrl = null; |
|
|
this.isPlaying = false; |
|
|
this.progress = 0; |
|
|
this.currentTimeDisplay = '0:00'; |
|
|
this.durationDisplay = '0:00'; |
|
|
this.userInput = ''; |
|
|
this.validationMessage = ''; |
|
|
this.isCorrect = false; |
|
|
this.attemptsLeft = 3; |
|
|
this.canSubmit = false; |
|
|
this.audioFinished = false; |
|
|
this.correctWord = null; |
|
|
this.wordMeaning = null; |
|
|
this.wordSentence = null; |
|
|
this.isGenerateDisabled = false; |
|
|
this.isLoading = false; |
|
|
this.showMeaning = false; |
|
|
this.showSentence = false; |
|
|
if (this.ui) { |
|
|
this.ui.pulseOk = false; |
|
|
this.ui.shake = false; |
|
|
this.ui.showMeaning = false; |
|
|
this.ui.showExample = false; |
|
|
this.ui.meaningText = ''; |
|
|
this.ui.exampleText = ''; |
|
|
} |
|
|
this.isPopupVisible = false; |
|
|
this.popupMessage = ''; |
|
|
} |
|
|
|
|
|
closeToStart(): void { |
|
|
const audio = this.audioRef?.nativeElement; |
|
|
if (audio) { |
|
|
try { audio.pause(); } catch { } |
|
|
audio.currentTime = 0; |
|
|
} |
|
|
this.isPlaying = false; |
|
|
this.audioUrl = null; |
|
|
this.userInput = ''; |
|
|
this.validationMessage = ''; |
|
|
this.isCorrect = false; |
|
|
this.attemptsLeft = 3; |
|
|
this.canSubmit = false; |
|
|
this.audioFinished = false; |
|
|
this.isGenerateDisabled = false; |
|
|
this.isLoading = false; |
|
|
this.showMeaning = false; |
|
|
this.showSentence = false; |
|
|
this.isPopupVisible = false; |
|
|
this.popupMessage = ''; |
|
|
this.step = 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|