diff --git a/src/app/deck-list.component.html b/src/app/deck-list.component.html index 8be74f6..add9730 100644 --- a/src/app/deck-list.component.html +++ b/src/app/deck-list.component.html @@ -18,9 +18,31 @@ -
-

{{ deck.images.length }} Bilder

-
+ + + +
- - -
-

{{ progress }}

- +

Training: {{ deck.name }}

+
+ + +
+ + + + + + + +
+ +

{{ progress }}

+

Gewusst: {{ knownCount }} | Nicht gewusst: {{ unknownCount }}

+ +
- \ No newline at end of file + diff --git a/src/app/training/training.component.ts b/src/app/training/training.component.ts index 08b3ba4..bde197e 100644 --- a/src/app/training/training.component.ts +++ b/src/app/training/training.component.ts @@ -1,7 +1,9 @@ // src/app/training.component.ts -import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { Deck, DeckImage } from '../deck.service'; +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', @@ -9,54 +11,148 @@ import { CommonModule } from '@angular/common'; standalone: true, imports: [CommonModule] }) -export class TrainingComponent { +export class TrainingComponent implements OnInit { @Input() deck!: Deck; @Output() close = new EventEmitter(); - currentIndex: number = 0; + @ViewChild('canvas') canvasRef!: ElementRef; + + currentImageIndex: number = 0; + currentImageData: DeckImage | null = null; + currentBoxIndex: number = 0; + boxes: Box[] = []; + boxRevealed: boolean[] = []; + knownCount: number = 0; unknownCount: number = 0; - showTextFlag: boolean = false; - get currentImage(): string | null { - if (this.currentIndex < this.deck.images.length) { - return `/api/debug_image/${this.deck.images[this.currentIndex].name}`; + 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(); } - return null; } - get progress(): string { - return `Fortschritt: ${this.currentIndex} / ${this.deck.images.length}`; + 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 { - this.showTextFlag = true; + if (this.currentBoxIndex >= this.boxes.length) return; + this.boxRevealed[this.currentBoxIndex] = true; + this.isShowingBox = true; + this.drawCanvas(); } markKnown(): void { this.knownCount++; - this.nextImage(); + this.nextBox(); } markUnknown(): void { this.unknownCount++; - this.nextImage(); + this.nextBox(); } - nextImage(): void { - this.currentIndex++; - this.showTextFlag = false; - if (this.currentIndex >= this.deck.images.length) { - this.endTraining(); + 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 { - this.close.emit(); + 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}`; } } + diff --git a/src/app/upload-image-modal/upload-image-modal.component.html b/src/app/upload-image-modal/upload-image-modal.component.html index dce60e7..6484778 100644 --- a/src/app/upload-image-modal/upload-image-modal.component.html +++ b/src/app/upload-image-modal/upload-image-modal.component.html @@ -1,6 +1,6 @@