vokabeltraining/src/app/training/training.component.ts

159 lines
4.2 KiB
TypeScript

// src/app/training.component.ts
import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Deck, DeckImage, DeckService, Box } from '../deck.service';
import { CommonModule } from '@angular/common';
import { switchMap } from 'rxjs/operators';
import { forkJoin } from 'rxjs';
@Component({
selector: 'app-training',
templateUrl: './training.component.html',
standalone: true,
imports: [CommonModule]
})
export class TrainingComponent implements OnInit {
@Input() deck!: Deck;
@Output() close = new EventEmitter<void>();
@ViewChild('canvas') canvasRef!: ElementRef<HTMLCanvasElement>;
currentImageIndex: number = 0;
currentImageData: DeckImage | null = null;
currentBoxIndex: number = 0;
boxes: Box[] = [];
boxRevealed: boolean[] = [];
knownCount: number = 0;
unknownCount: number = 0;
isShowingBox: boolean = false;
isTrainingFinished: boolean = false;
constructor(private deckService: DeckService) { }
ngOnInit(): void {
if (this.deck && this.deck.images.length > 0) {
this.loadImage(this.currentImageIndex);
} else {
alert('Kein Deck oder keine Bilder vorhanden.');
this.close.emit();
}
}
loadImage(imageIndex: number): void {
if (imageIndex >= this.deck.images.length) {
this.endTraining();
return;
}
const imageName = this.deck.images[imageIndex].name;
this.deckService.getImage(imageName).subscribe({
next: (imageData: DeckImage) => {
this.currentImageData = imageData;
this.boxes = imageData.boxes;
this.boxRevealed = new Array(this.boxes.length).fill(false);
this.currentBoxIndex = 0;
this.isShowingBox = false;
this.drawCanvas();
},
error: (err) => {
console.error('Fehler beim Laden des Bildes:', err);
alert('Fehler beim Laden des Bildes.');
this.close.emit();
}
});
}
drawCanvas(): void {
const canvas = this.canvasRef.nativeElement;
const ctx = canvas.getContext('2d');
if (!ctx || !this.currentImageData) return;
const img = new Image();
img.src = `/api/debug_image/${this.currentImageData.name}`;
img.onload = () => {
// Set canvas size to image size
canvas.width = img.width;
canvas.height = img.height;
// Draw image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Draw boxes
this.boxes.forEach((box, index) => {
if (this.boxRevealed[index]) {
// Box ist bereits enthüllt, nichts zeichnen
return;
}
ctx.beginPath();
ctx.rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
ctx.fillStyle = index === this.currentBoxIndex ? 'rgba(0, 255, 0, 0.99)' : 'rgba(255, 0, 0, 0.99)';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
});
};
img.onerror = () => {
console.error('Fehler beim Laden des Bildes für Canvas.');
alert('Fehler beim Laden des Bildes für Canvas.');
this.close.emit();
};
}
showText(): void {
if (this.currentBoxIndex >= this.boxes.length) return;
this.boxRevealed[this.currentBoxIndex] = true;
this.isShowingBox = true;
this.drawCanvas();
}
markKnown(): void {
this.knownCount++;
this.nextBox();
}
markUnknown(): void {
this.unknownCount++;
this.nextBox();
}
nextBox(): void {
this.currentBoxIndex++;
this.isShowingBox = false;
if (this.currentBoxIndex >= this.boxes.length) {
// Alle Boxen für dieses Bild sind bearbeitet
this.nextImage();
} else {
// Aktualisiere die Farben der Boxen
this.drawCanvas();
}
}
nextImage(): void {
this.currentImageIndex++;
this.loadImage(this.currentImageIndex);
}
endTraining(): void {
this.isTrainingFinished = true;
alert(`Training beendet!\nGewusst: ${this.knownCount}\nNicht gewusst: ${this.unknownCount}`);
this.close.emit();
}
closeTraining(): void {
if (confirm('Möchtest du das Training wirklich beenden?')) {
this.close.emit();
}
}
get progress(): string {
return `Bild ${this.currentImageIndex + 1} von ${this.deck.images.length}`;
}
}