pdf-quiz-generator/backend/app/services/reminder_service.py
ifedan-ed b876f13fac Initial commit: PDF Quiz Generator app
- FastAPI backend with JWT auth, roles (admin/moderator/user)
- PDF upload (up to 500MB) with streaming, PyMuPDF text extraction
- ChromaDB vectorization per page with metadata
- LiteLLM AI question extraction from PDF (not generation)
- Image extraction from PDF pages, graceful fallback
- Quiz modes: timed (countdown timer) + learning (answers shown inline)
- Page-by-page question navigation with dot navigator
- TTS endpoint using LiteLLM (Google Vertex / OpenAI voices)
- Admin dashboard: AI model management per task, user role management
- Moderator role: upload PDFs, create sections, generate quizzes
- Spaced repetition reminders via SMTP email (SM-2 intervals)
- APScheduler daily reminder jobs
- Celery + Redis for background PDF processing
- React frontend with all pages
- Docker Compose deployment (nginx + backend + celery + redis)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:04:53 +00:00

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 < 70:
# Poor performance: 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()