Korrektur UserLogo, #12 Easy interal must be greater than good interval

This commit is contained in:
Your Name 2025-01-27 20:17:45 +01:00
parent 9638feacb9
commit 47b393e134
3 changed files with 63 additions and 35 deletions

2
.gitignore vendored
View File

@ -45,3 +45,5 @@ Thumbs.db
.nx/cache .nx/cache
.nx/workspace-data .nx/workspace-data
.aider*
.env

View File

@ -30,10 +30,16 @@ import { ClickOutsideDirective } from './service/click-outside.directive';
<div class="flex justify-center items-center mb-8"> <div class="flex justify-center items-center mb-8">
<h1 class="text-3xl font-bold mx-auto">Vocabulary Training</h1> <h1 class="text-3xl font-bold mx-auto">Vocabulary Training</h1>
<div class="relative" appClickOutside (clickOutside)="showDropdown = false"> <div class="relative" appClickOutside (clickOutside)="showDropdown = false">
<img [src]="photoURL" alt="User Photo" class="w-10 h-10 rounded-full cursor-pointer" (click)="toggleDropdown()" /> @if(photoURL){
<div *ngIf="showDropdown" class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg"> <img [src]="photoURL" alt="User Photo" class="w-10 h-10 rounded-full cursor-pointer" (click)="toggleDropdown()" referrerpolicy="no-referrer" crossorigin="anonymous"/>
} @else {
<div class="image-placeholder w-10 h-10 rounded-full cursor-pointer">Image</div>
}
@if(showDropdown){
<div class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg">
<button (click)="logout()" class="block w-full text-left px-4 py-2 text-gray-700 hover:bg-gray-100">Abmelden</button> <button (click)="logout()" class="block w-full text-left px-4 py-2 text-gray-700 hover:bg-gray-100">Abmelden</button>
</div> </div>
}
</div> </div>
</div> </div>
<app-deck-list></app-deck-list> <app-deck-list></app-deck-list>
@ -72,6 +78,7 @@ img:hover {
.dropdown button:hover { .dropdown button:hover {
background-color: #f7fafc; background-color: #f7fafc;
} }
`, `,
imports: [CommonModule, DeckListComponent, ClickOutsideDirective], imports: [CommonModule, DeckListComponent, ClickOutsideDirective],
}) })
@ -79,7 +86,7 @@ export class AppComponent {
isLoggedIn = false; isLoggedIn = false;
private auth: Auth = inject(Auth); private auth: Auth = inject(Auth);
showDropdown = false; showDropdown = false;
photoURL: string = 'https://via.placeholder.com/40'; photoURL: string = 'https://placehold.co/40';
// user: User | null = null; // user: User | null = null;
ngOnInit() { ngOnInit() {
@ -88,7 +95,7 @@ export class AppComponent {
const accessToken = localStorage.getItem('accessToken'); const accessToken = localStorage.getItem('accessToken');
const refreshToken = localStorage.getItem('refreshToken'); const refreshToken = localStorage.getItem('refreshToken');
this.photoURL = localStorage.getItem('photoURL'); this.photoURL = localStorage.getItem('photoURL');
this.showDropdown = false;
if (isLoggedIn && accessToken && refreshToken) { if (isLoggedIn && accessToken && refreshToken) {
this.isLoggedIn = true; this.isLoggedIn = true;
} }
@ -107,6 +114,8 @@ export class AppComponent {
localStorage.setItem('refreshToken', result.user.refreshToken); localStorage.setItem('refreshToken', result.user.refreshToken);
localStorage.setItem('photoURL', result.user.photoURL); localStorage.setItem('photoURL', result.user.photoURL);
this.showDropdown = false;
console.log('Logged in with Google', result.user); console.log('Logged in with Google', result.user);
} catch (error) { } catch (error) {
console.error('Google Login failed', error); console.error('Google Login failed', error);

View File

@ -1,7 +1,7 @@
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 { CommonModule } from '@angular/common';
import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { Box, Deck, DeckImage, DeckService } from '../deck.service';
const LEARNING_STEPS = { const LEARNING_STEPS = {
AGAIN: 1, // 1 minute AGAIN: 1, // 1 minute
@ -267,7 +267,27 @@ export class TrainingComponent implements OnInit {
* @param action The action ('again', 'good', 'easy') * @param action The action ('again', 'good', 'easy')
* @returns An object with the new values for ivl, factor, reps, and lapses * @returns An object with the new values for ivl, factor, reps, and lapses
*/ */
calculateNewInterval(box: Box, action: 'again' | 'good' | 'easy'): { newIvl: number, newFactor: number, newReps: number, newLapses: number, newIsGraduated: boolean } { calculateNewInterval(box: Box, action: 'again' | 'good' | 'easy'): {
newIvl: number,
newFactor: number,
newReps: number,
newLapses: number,
newIsGraduated: boolean
} {
const LEARNING_STEPS = {
AGAIN: 1, // 1 minute
GOOD: 10, // 10 minutes
GRADUATION: 1440 // 1 day (1440 minutes)
};
const EASY_BONUS = 1.3; // Zusätzlicher Easy-Multiplikator
/* const FACTOR_CHANGES = {
MIN: 1.3,
MAX: 2.5,
AGAIN: 0.85,
EASY: 1.15
}; */
let newIvl = box.ivl || 0; let newIvl = box.ivl || 0;
let newFactor = box.factor || 2.5; let newFactor = box.factor || 2.5;
let newReps = box.reps || 0; let newReps = box.reps || 0;
@ -279,27 +299,26 @@ export class TrainingComponent implements OnInit {
newReps = 0; newReps = 0;
newIvl = LEARNING_STEPS.AGAIN; newIvl = LEARNING_STEPS.AGAIN;
newIsGraduated = false; newIsGraduated = false;
newFactor = Math.max(FACTOR_CHANGES.MIN, newFactor * FACTOR_CHANGES.AGAIN);
// Reduce factor but not below minimum
newFactor = Math.max(
FACTOR_CHANGES.MIN,
newFactor * FACTOR_CHANGES.AGAIN
);
return { newIvl, newFactor, newReps, newLapses, newIsGraduated }; return { newIvl, newFactor, newReps, newLapses, newIsGraduated };
} }
if (action === 'easy') { if (action === 'easy') {
newReps++; newReps++;
newIsGraduated = true;
newIvl = EASY_INTERVAL;
// Increase factor but not above maximum // Faktor zuerst aktualisieren
newFactor = Math.min( const updatedFactor = Math.min(FACTOR_CHANGES.MAX, newFactor * FACTOR_CHANGES.EASY);
FACTOR_CHANGES.MAX,
newFactor * FACTOR_CHANGES.EASY
);
if (!newIsGraduated) {
// Direkte Graduierung mit Easy
newIsGraduated = true;
newIvl = LEARNING_STEPS.GRADUATION; // 1 Tag (1440 Minuten)
} else {
// Anki-Formel für Easy in der Review-Phase
newIvl = Math.round((newIvl + LEARNING_STEPS.GRADUATION / 2) * updatedFactor * EASY_BONUS);
}
newFactor = updatedFactor;
return { newIvl, newFactor, newReps, newLapses, newIsGraduated }; return { newIvl, newFactor, newReps, newLapses, newIsGraduated };
} }
@ -307,16 +326,14 @@ export class TrainingComponent implements OnInit {
newReps++; newReps++;
if (!newIsGraduated) { if (!newIsGraduated) {
// Card is in learning phase
if (newReps === 1) { if (newReps === 1) {
newIvl = LEARNING_STEPS.GOOD; newIvl = LEARNING_STEPS.GOOD; // 10 Minuten
} else { } else {
// Graduate the card
newIsGraduated = true; newIsGraduated = true;
newIvl = LEARNING_STEPS.GRADUATION; newIvl = LEARNING_STEPS.GRADUATION; // 1 Tag nach zweiter Good-Antwort
} }
} else { } else {
// Card is in review phase, apply space repetition // Standard-SR-Formel
newIvl = Math.round(newIvl * newFactor); newIvl = Math.round(newIvl * newFactor);
} }