Features: - Hybrid semantic + keyword quiz search (pgvector HNSW + PostgreSQL ILIKE) - AWS Bedrock Titan Embed V2 embeddings via LiteLLM proxy (0.71 cosine sim) - Multi-provider TTS: OpenAI, AWS Polly (neural), ElevenLabs, Google Cloud TTS - Unified Settings page (profile, theme, Nextcloud integration, admin shortcuts) - Good morning/afternoon greeting on dashboard - manage.py CLI: reset-password, list-users, reembed - Email verification enforced: register no longer returns JWT for unverified users - Quiz search with debounced input, semantic/keyword/title modes, highlighted snippets - TTS button: loading/playing states, voice selector locked during playback - TTS auto-stops when navigating between questions - Footer added; mobile quiz nav overflow fixed; markdown theme body selector fixed - OpenAI Alloy as default TTS voice; favicon added - SMTP configured via smtp2go; password reset rate limiting (3/hour) - PostgreSQL upgraded to pgvector/pgvector:pg16 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
from datetime import datetime, timedelta
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.reminder import ReminderSchedule
|
|
|
|
# SM-2 simplified intervals in days
|
|
INTERVALS = [1, 3, 7, 14, 30]
|
|
|
|
|
|
def update_reminder_schedule(
|
|
db: Session,
|
|
user_id: int,
|
|
quiz_id: int,
|
|
score_percentage: float,
|
|
):
|
|
"""Update or create a reminder schedule based on quiz performance."""
|
|
reminder = db.query(ReminderSchedule).filter(
|
|
ReminderSchedule.user_id == user_id,
|
|
ReminderSchedule.quiz_id == quiz_id,
|
|
).first()
|
|
|
|
if not reminder:
|
|
reminder = ReminderSchedule(
|
|
user_id=user_id,
|
|
quiz_id=quiz_id,
|
|
performance_score=score_percentage,
|
|
interval_days=INTERVALS[0],
|
|
next_reminder_at=datetime.utcnow() + timedelta(days=INTERVALS[0]),
|
|
is_active=True,
|
|
)
|
|
db.add(reminder)
|
|
else:
|
|
reminder.performance_score = score_percentage
|
|
reminder.is_active = True
|
|
|
|
# Find current interval index
|
|
current_idx = 0
|
|
for i, interval in enumerate(INTERVALS):
|
|
if reminder.interval_days <= interval:
|
|
current_idx = i
|
|
break
|
|
|
|
if score_percentage < 75:
|
|
# Below threshold: reset to shortest interval
|
|
new_idx = 0
|
|
elif score_percentage < 90:
|
|
# Decent performance: advance one step
|
|
new_idx = min(current_idx + 1, len(INTERVALS) - 1)
|
|
else:
|
|
# Excellent performance: advance or deactivate
|
|
if current_idx >= len(INTERVALS) - 1:
|
|
reminder.is_active = False
|
|
db.commit()
|
|
return
|
|
new_idx = min(current_idx + 2, len(INTERVALS) - 1)
|
|
|
|
reminder.interval_days = INTERVALS[new_idx]
|
|
reminder.next_reminder_at = datetime.utcnow() + timedelta(days=INTERVALS[new_idx])
|
|
|
|
db.commit()
|