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
(click)="showText()"
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
</button>
@ -18,7 +18,7 @@
<button
(click)="markKnown()"
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
</button>
@ -27,10 +27,19 @@
<button
(click)="markUnknown()"
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
</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>
<p class="mt-2">{{ progress }}</p>

View File

@ -19,8 +19,9 @@ export class TrainingComponent implements OnInit {
currentImageIndex: number = 0;
currentImageData: DeckImage | null = null;
// Ändere currentBoxIndex zu boxesToReview als Array
currentBoxIndex: number = 0;
boxes: Box[] = [];
boxesToReview: Box[] = [];
boxRevealed: boolean[] = [];
knownCount: number = 0;
@ -33,6 +34,7 @@ export class TrainingComponent implements OnInit {
ngOnInit(): void {
}
ngAfterViewInit(){
if (this.deck && this.deck.images.length > 0) {
this.loadImage(this.currentImageIndex);
@ -41,17 +43,17 @@ export class TrainingComponent implements OnInit {
this.close.emit();
}
}
loadImage(imageIndex: number): void {
if (imageIndex >= this.deck.images.length) {
this.endTraining();
return;
}
const imageName = this.deck.images[imageIndex].name;
this.currentImageData = this.deck.images[imageIndex];
this.boxes = this.deck.images[imageIndex].boxes;
this.boxRevealed = new Array(this.boxes.length).fill(false);
this.currentBoxIndex = 0;
// Initialisiere boxesToReview mit allen Boxen, gemischt
this.boxesToReview = this.shuffleArray([...this.currentImageData.boxes]);
this.boxRevealed = new Array(this.boxesToReview.length).fill(false);
this.isShowingBox = false;
this.drawCanvas();
}
@ -73,7 +75,7 @@ export class TrainingComponent implements OnInit {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Draw boxes
this.boxes.forEach((box, index) => {
this.boxesToReview.forEach((box, index) => {
if (this.boxRevealed[index]) {
// Box ist bereits enthüllt, nichts zeichnen
return;
@ -87,6 +89,7 @@ export class TrainingComponent implements OnInit {
ctx.strokeStyle = 'black';
ctx.stroke();
});
};
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 {
if (this.currentBoxIndex >= this.boxes.length) return;
if (this.currentBoxIndex >= this.boxesToReview.length) return;
this.boxRevealed[this.currentBoxIndex] = true;
this.isShowingBox = true;
this.drawCanvas();
@ -105,25 +134,35 @@ export class TrainingComponent implements OnInit {
markKnown(): void {
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();
}
markUnknown(): void {
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();
}
nextBox(): void {
this.currentBoxIndex++;
this.isShowingBox = false;
if (this.currentBoxIndex >= this.boxes.length) {
if (this.boxesToReview.length === 0) {
// Alle Boxen für dieses Bild sind bearbeitet
this.nextImage();
} else {
// Aktualisiere die Farben der Boxen
this.drawCanvas();
return;
}
if (this.currentBoxIndex >= this.boxesToReview.length) {
this.currentBoxIndex = 0;
}
this.drawCanvas();
}
nextImage(): void {
@ -131,6 +170,15 @@ export class TrainingComponent implements OnInit {
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 {
this.isTrainingFinished = true;
alert(`Training beendet!\nGewusst: ${this.knownCount}\nNicht gewusst: ${this.unknownCount}`);