spaced repetition

This commit is contained in:
Andreas Knuth 2024-11-29 23:00:15 +01:00
parent c116b56934
commit b43044a0dd
2 changed files with 75 additions and 18 deletions

View File

@ -9,7 +9,7 @@
<button <button
(click)="showText()" (click)="showText()"
class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600" class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600"
[disabled]="isShowingBox || currentBoxIndex >= boxes.length" [disabled]="isShowingBox || currentBoxIndex >= boxesToReview.length"
> >
Anzeigen Anzeigen
</button> </button>
@ -18,7 +18,7 @@
<button <button
(click)="markKnown()" (click)="markKnown()"
class="bg-blue-500 disabled:bg-blue-200 text-white py-2 px-4 rounded hover:bg-blue-600" class="bg-blue-500 disabled:bg-blue-200 text-white py-2 px-4 rounded hover:bg-blue-600"
[disabled]="!isShowingBox || currentBoxIndex >= boxes.length" [disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length"
> >
Gewusst Gewusst
</button> </button>
@ -27,10 +27,19 @@
<button <button
(click)="markUnknown()" (click)="markUnknown()"
class="bg-red-500 disabled:bg-red-200 text-white py-2 px-4 rounded hover:bg-red-600" class="bg-red-500 disabled:bg-red-200 text-white py-2 px-4 rounded hover:bg-red-600"
[disabled]="!isShowingBox || currentBoxIndex >= boxes.length" [disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length"
> >
Nicht gewusst Nicht gewusst
</button> </button>
<!-- Nächstes Bild Button -->
<button
(click)="skipToNextImage()"
class="bg-yellow-500 disabled:bg-yellow-200 text-white py-2 px-4 rounded hover:bg-yellow-600"
[disabled]="currentImageIndex >= deck.images.length"
>
Nächstes Bild
</button>
</div> </div>
<p class="mt-2">{{ progress }}</p> <p class="mt-2">{{ progress }}</p>

View File

@ -19,8 +19,9 @@ export class TrainingComponent implements OnInit {
currentImageIndex: number = 0; currentImageIndex: number = 0;
currentImageData: DeckImage | null = null; currentImageData: DeckImage | null = null;
// Ändere currentBoxIndex zu boxesToReview als Array
currentBoxIndex: number = 0; currentBoxIndex: number = 0;
boxes: Box[] = []; boxesToReview: Box[] = [];
boxRevealed: boolean[] = []; boxRevealed: boolean[] = [];
knownCount: number = 0; knownCount: number = 0;
@ -33,6 +34,7 @@ export class TrainingComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
} }
ngAfterViewInit(){ ngAfterViewInit(){
if (this.deck && this.deck.images.length > 0) { if (this.deck && this.deck.images.length > 0) {
this.loadImage(this.currentImageIndex); this.loadImage(this.currentImageIndex);
@ -41,19 +43,19 @@ export class TrainingComponent implements OnInit {
this.close.emit(); this.close.emit();
} }
} }
loadImage(imageIndex: number): void { loadImage(imageIndex: number): void {
if (imageIndex >= this.deck.images.length) { if (imageIndex >= this.deck.images.length) {
this.endTraining(); this.endTraining();
return; return;
} }
const imageName = this.deck.images[imageIndex].name; this.currentImageData = this.deck.images[imageIndex];
this.currentImageData = this.deck.images[imageIndex]; // Initialisiere boxesToReview mit allen Boxen, gemischt
this.boxes = this.deck.images[imageIndex].boxes; this.boxesToReview = this.shuffleArray([...this.currentImageData.boxes]);
this.boxRevealed = new Array(this.boxes.length).fill(false); this.boxRevealed = new Array(this.boxesToReview.length).fill(false);
this.currentBoxIndex = 0; this.isShowingBox = false;
this.isShowingBox = false; this.drawCanvas();
this.drawCanvas();
} }
drawCanvas(): void { drawCanvas(): void {
@ -73,7 +75,7 @@ export class TrainingComponent implements OnInit {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Draw boxes // Draw boxes
this.boxes.forEach((box, index) => { this.boxesToReview.forEach((box, index) => {
if (this.boxRevealed[index]) { if (this.boxRevealed[index]) {
// Box ist bereits enthüllt, nichts zeichnen // Box ist bereits enthüllt, nichts zeichnen
return; return;
@ -87,6 +89,7 @@ export class TrainingComponent implements OnInit {
ctx.strokeStyle = 'black'; ctx.strokeStyle = 'black';
ctx.stroke(); ctx.stroke();
}); });
}; };
img.onerror = () => { img.onerror = () => {
@ -96,8 +99,34 @@ export class TrainingComponent implements OnInit {
}; };
} }
// Utility-Funktion zum Mischen eines Arrays
shuffleArray<T>(array: T[]): T[] {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex !== 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
get currentBox(): Box | null {
if (this.currentBoxIndex < this.boxesToReview.length) {
return this.boxesToReview[this.currentBoxIndex];
}
return null;
}
showText(): void { showText(): void {
if (this.currentBoxIndex >= this.boxes.length) return; if (this.currentBoxIndex >= this.boxesToReview.length) return;
this.boxRevealed[this.currentBoxIndex] = true; this.boxRevealed[this.currentBoxIndex] = true;
this.isShowingBox = true; this.isShowingBox = true;
this.drawCanvas(); this.drawCanvas();
@ -105,25 +134,35 @@ export class TrainingComponent implements OnInit {
markKnown(): void { markKnown(): void {
this.knownCount++; this.knownCount++;
// Entferne die aktuelle Box aus boxesToReview, da sie bekannt ist
this.boxesToReview.splice(this.currentBoxIndex, 1);
this.boxRevealed.splice(this.currentBoxIndex, 1);
this.nextBox(); this.nextBox();
} }
markUnknown(): void { markUnknown(): void {
this.unknownCount++; this.unknownCount++;
// Behalte die aktuelle Box in der Liste und verschiebe sie an eine zufällige Position am Ende
const box = this.boxesToReview.splice(this.currentBoxIndex, 1)[0];
this.boxesToReview.push(box);
this.boxRevealed.splice(this.currentBoxIndex, 1);
this.nextBox(); this.nextBox();
} }
nextBox(): void { nextBox(): void {
this.currentBoxIndex++;
this.isShowingBox = false; this.isShowingBox = false;
if (this.currentBoxIndex >= this.boxes.length) { if (this.boxesToReview.length === 0) {
// Alle Boxen für dieses Bild sind bearbeitet // Alle Boxen für dieses Bild sind bearbeitet
this.nextImage(); this.nextImage();
} else { return;
// Aktualisiere die Farben der Boxen
this.drawCanvas();
} }
if (this.currentBoxIndex >= this.boxesToReview.length) {
this.currentBoxIndex = 0;
}
this.drawCanvas();
} }
nextImage(): void { nextImage(): void {
@ -131,6 +170,15 @@ export class TrainingComponent implements OnInit {
this.loadImage(this.currentImageIndex); this.loadImage(this.currentImageIndex);
} }
skipToNextImage(): void {
if (this.currentImageIndex < this.deck.images.length - 1) {
this.currentImageIndex++;
this.loadImage(this.currentImageIndex);
} else {
alert('Dies ist das letzte Bild im Deck.');
}
}
endTraining(): void { endTraining(): void {
this.isTrainingFinished = true; this.isTrainingFinished = true;
alert(`Training beendet!\nGewusst: ${this.knownCount}\nNicht gewusst: ${this.unknownCount}`); alert(`Training beendet!\nGewusst: ${this.knownCount}\nNicht gewusst: ${this.unknownCount}`);