Korrektur UserLogo, #12 Easy interal must be greater than good interval
This commit is contained in:
parent
9638feacb9
commit
47b393e134
|
|
@ -45,3 +45,5 @@ Thumbs.db
|
||||||
|
|
||||||
.nx/cache
|
.nx/cache
|
||||||
.nx/workspace-data
|
.nx/workspace-data
|
||||||
|
.aider*
|
||||||
|
.env
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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++;
|
||||||
|
|
||||||
|
// Faktor zuerst aktualisieren
|
||||||
|
const updatedFactor = Math.min(FACTOR_CHANGES.MAX, newFactor * FACTOR_CHANGES.EASY);
|
||||||
|
|
||||||
|
if (!newIsGraduated) {
|
||||||
|
// Direkte Graduierung mit Easy
|
||||||
newIsGraduated = true;
|
newIsGraduated = true;
|
||||||
newIvl = EASY_INTERVAL;
|
newIvl = LEARNING_STEPS.GRADUATION; // 1 Tag (1440 Minuten)
|
||||||
|
} else {
|
||||||
// Increase factor but not above maximum
|
// Anki-Formel für Easy in der Review-Phase
|
||||||
newFactor = Math.min(
|
newIvl = Math.round((newIvl + LEARNING_STEPS.GRADUATION / 2) * updatedFactor * EASY_BONUS);
|
||||||
FACTOR_CHANGES.MAX,
|
}
|
||||||
newFactor * FACTOR_CHANGES.EASY
|
|
||||||
);
|
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue