Spaces:
Sleeping
Sleeping
""" | |
Student profile data models for TutorX-MCP. | |
This module defines data structures for storing and managing | |
student learning profiles, preferences, and characteristics. | |
""" | |
from datetime import datetime, timedelta | |
from typing import Dict, List, Optional, Any | |
from dataclasses import dataclass, field | |
from enum import Enum | |
import json | |
class LearningStyle(Enum): | |
"""Learning style preferences.""" | |
VISUAL = "visual" | |
AUDITORY = "auditory" | |
KINESTHETIC = "kinesthetic" | |
READING_WRITING = "reading_writing" | |
MULTIMODAL = "multimodal" | |
class LearningPace(Enum): | |
"""Learning pace preferences.""" | |
SLOW = "slow" | |
MODERATE = "moderate" | |
FAST = "fast" | |
ADAPTIVE = "adaptive" | |
class DifficultyPreference(Enum): | |
"""Difficulty progression preferences.""" | |
GRADUAL = "gradual" | |
MODERATE = "moderate" | |
AGGRESSIVE = "aggressive" | |
ADAPTIVE = "adaptive" | |
class FeedbackPreference(Enum): | |
"""Feedback delivery preferences.""" | |
IMMEDIATE = "immediate" | |
DELAYED = "delayed" | |
SUMMARY = "summary" | |
MINIMAL = "minimal" | |
class LearningPreferences: | |
"""Student learning preferences and settings.""" | |
learning_style: LearningStyle = LearningStyle.MULTIMODAL | |
learning_pace: LearningPace = LearningPace.ADAPTIVE | |
difficulty_preference: DifficultyPreference = DifficultyPreference.ADAPTIVE | |
feedback_preference: FeedbackPreference = FeedbackPreference.IMMEDIATE | |
# Session preferences | |
preferred_session_length: int = 30 # minutes | |
max_session_length: int = 60 # minutes | |
break_frequency: int = 20 # minutes between breaks | |
# Content preferences | |
gamification_enabled: bool = True | |
hints_enabled: bool = True | |
explanations_enabled: bool = True | |
examples_enabled: bool = True | |
# Notification preferences | |
reminders_enabled: bool = True | |
progress_notifications: bool = True | |
achievement_notifications: bool = True | |
def to_dict(self) -> Dict[str, Any]: | |
"""Convert to dictionary for serialization.""" | |
return { | |
'learning_style': self.learning_style.value, | |
'learning_pace': self.learning_pace.value, | |
'difficulty_preference': self.difficulty_preference.value, | |
'feedback_preference': self.feedback_preference.value, | |
'preferred_session_length': self.preferred_session_length, | |
'max_session_length': self.max_session_length, | |
'break_frequency': self.break_frequency, | |
'gamification_enabled': self.gamification_enabled, | |
'hints_enabled': self.hints_enabled, | |
'explanations_enabled': self.explanations_enabled, | |
'examples_enabled': self.examples_enabled, | |
'reminders_enabled': self.reminders_enabled, | |
'progress_notifications': self.progress_notifications, | |
'achievement_notifications': self.achievement_notifications | |
} | |
def from_dict(cls, data: Dict[str, Any]) -> 'LearningPreferences': | |
"""Create from dictionary.""" | |
return cls( | |
learning_style=LearningStyle(data.get('learning_style', 'multimodal')), | |
learning_pace=LearningPace(data.get('learning_pace', 'adaptive')), | |
difficulty_preference=DifficultyPreference(data.get('difficulty_preference', 'adaptive')), | |
feedback_preference=FeedbackPreference(data.get('feedback_preference', 'immediate')), | |
preferred_session_length=data.get('preferred_session_length', 30), | |
max_session_length=data.get('max_session_length', 60), | |
break_frequency=data.get('break_frequency', 20), | |
gamification_enabled=data.get('gamification_enabled', True), | |
hints_enabled=data.get('hints_enabled', True), | |
explanations_enabled=data.get('explanations_enabled', True), | |
examples_enabled=data.get('examples_enabled', True), | |
reminders_enabled=data.get('reminders_enabled', True), | |
progress_notifications=data.get('progress_notifications', True), | |
achievement_notifications=data.get('achievement_notifications', True) | |
) | |
class StudentGoals: | |
"""Student learning goals and objectives.""" | |
target_concepts: List[str] = field(default_factory=list) | |
target_mastery_level: float = 0.8 | |
target_completion_date: Optional[datetime] = None | |
daily_time_goal: int = 30 # minutes per day | |
weekly_concept_goal: int = 2 # concepts per week | |
# Long-term goals | |
grade_level_target: Optional[str] = None | |
subject_focus_areas: List[str] = field(default_factory=list) | |
career_interests: List[str] = field(default_factory=list) | |
def to_dict(self) -> Dict[str, Any]: | |
"""Convert to dictionary for serialization.""" | |
return { | |
'target_concepts': self.target_concepts, | |
'target_mastery_level': self.target_mastery_level, | |
'target_completion_date': self.target_completion_date.isoformat() if self.target_completion_date else None, | |
'daily_time_goal': self.daily_time_goal, | |
'weekly_concept_goal': self.weekly_concept_goal, | |
'grade_level_target': self.grade_level_target, | |
'subject_focus_areas': self.subject_focus_areas, | |
'career_interests': self.career_interests | |
} | |
def from_dict(cls, data: Dict[str, Any]) -> 'StudentGoals': | |
"""Create from dictionary.""" | |
target_date = None | |
if data.get('target_completion_date'): | |
target_date = datetime.fromisoformat(data['target_completion_date']) | |
return cls( | |
target_concepts=data.get('target_concepts', []), | |
target_mastery_level=data.get('target_mastery_level', 0.8), | |
target_completion_date=target_date, | |
daily_time_goal=data.get('daily_time_goal', 30), | |
weekly_concept_goal=data.get('weekly_concept_goal', 2), | |
grade_level_target=data.get('grade_level_target'), | |
subject_focus_areas=data.get('subject_focus_areas', []), | |
career_interests=data.get('career_interests', []) | |
) | |
class StudentProfile: | |
"""Comprehensive student learning profile.""" | |
student_id: str | |
name: Optional[str] = None | |
grade_level: Optional[str] = None | |
age: Optional[int] = None | |
# Learning characteristics | |
preferences: LearningPreferences = field(default_factory=LearningPreferences) | |
goals: StudentGoals = field(default_factory=StudentGoals) | |
# Profile metadata | |
created_at: datetime = field(default_factory=datetime.utcnow) | |
last_updated: datetime = field(default_factory=datetime.utcnow) | |
last_active: Optional[datetime] = None | |
# Adaptive learning state | |
current_difficulty_level: float = 0.5 | |
learning_velocity: float = 0.0 # concepts per day | |
engagement_level: float = 0.5 | |
# Performance summary | |
total_concepts_attempted: int = 0 | |
total_concepts_mastered: int = 0 | |
total_learning_time: int = 0 # minutes | |
average_accuracy: float = 0.0 | |
# Strengths and challenges | |
strength_areas: List[str] = field(default_factory=list) | |
challenge_areas: List[str] = field(default_factory=list) | |
# Adaptive learning insights | |
learning_patterns: List[str] = field(default_factory=list) | |
recommended_strategies: List[str] = field(default_factory=list) | |
def update_last_active(self): | |
"""Update last active timestamp.""" | |
self.last_active = datetime.utcnow() | |
self.last_updated = datetime.utcnow() | |
def update_performance_summary(self, concepts_attempted: int, concepts_mastered: int, | |
learning_time: int, accuracy: float): | |
"""Update performance summary statistics.""" | |
self.total_concepts_attempted = concepts_attempted | |
self.total_concepts_mastered = concepts_mastered | |
self.total_learning_time = learning_time | |
self.average_accuracy = accuracy | |
self.last_updated = datetime.utcnow() | |
def calculate_mastery_rate(self) -> float: | |
"""Calculate overall mastery rate.""" | |
if self.total_concepts_attempted == 0: | |
return 0.0 | |
return self.total_concepts_mastered / self.total_concepts_attempted | |
def calculate_daily_average_time(self, days: int = 30) -> float: | |
"""Calculate average daily learning time over specified period.""" | |
if days <= 0: | |
return 0.0 | |
# This would need to be calculated from actual session data | |
# For now, return a simple estimate | |
return self.total_learning_time / max(1, days) | |
def is_active_learner(self, days: int = 7) -> bool: | |
"""Check if student has been active in recent days.""" | |
if not self.last_active: | |
return False | |
cutoff_date = datetime.utcnow() - timedelta(days=days) | |
return self.last_active >= cutoff_date | |
def get_learning_efficiency(self) -> float: | |
"""Calculate learning efficiency (mastery per hour).""" | |
if self.total_learning_time == 0: | |
return 0.0 | |
hours = self.total_learning_time / 60.0 | |
return self.total_concepts_mastered / hours | |
def add_strength_area(self, area: str): | |
"""Add a strength area if not already present.""" | |
if area not in self.strength_areas: | |
self.strength_areas.append(area) | |
self.last_updated = datetime.utcnow() | |
def add_challenge_area(self, area: str): | |
"""Add a challenge area if not already present.""" | |
if area not in self.challenge_areas: | |
self.challenge_areas.append(area) | |
self.last_updated = datetime.utcnow() | |
def add_learning_pattern(self, pattern: str): | |
"""Add a detected learning pattern.""" | |
if pattern not in self.learning_patterns: | |
self.learning_patterns.append(pattern) | |
self.last_updated = datetime.utcnow() | |
def add_recommended_strategy(self, strategy: str): | |
"""Add a recommended learning strategy.""" | |
if strategy not in self.recommended_strategies: | |
self.recommended_strategies.append(strategy) | |
self.last_updated = datetime.utcnow() | |
def to_dict(self) -> Dict[str, Any]: | |
"""Convert to dictionary for serialization.""" | |
return { | |
'student_id': self.student_id, | |
'name': self.name, | |
'grade_level': self.grade_level, | |
'age': self.age, | |
'preferences': self.preferences.to_dict(), | |
'goals': self.goals.to_dict(), | |
'created_at': self.created_at.isoformat(), | |
'last_updated': self.last_updated.isoformat(), | |
'last_active': self.last_active.isoformat() if self.last_active else None, | |
'current_difficulty_level': self.current_difficulty_level, | |
'learning_velocity': self.learning_velocity, | |
'engagement_level': self.engagement_level, | |
'total_concepts_attempted': self.total_concepts_attempted, | |
'total_concepts_mastered': self.total_concepts_mastered, | |
'total_learning_time': self.total_learning_time, | |
'average_accuracy': self.average_accuracy, | |
'strength_areas': self.strength_areas, | |
'challenge_areas': self.challenge_areas, | |
'learning_patterns': self.learning_patterns, | |
'recommended_strategies': self.recommended_strategies | |
} | |
def from_dict(cls, data: Dict[str, Any]) -> 'StudentProfile': | |
"""Create from dictionary.""" | |
created_at = datetime.fromisoformat(data['created_at']) if data.get('created_at') else datetime.utcnow() | |
last_updated = datetime.fromisoformat(data['last_updated']) if data.get('last_updated') else datetime.utcnow() | |
last_active = datetime.fromisoformat(data['last_active']) if data.get('last_active') else None | |
preferences = LearningPreferences.from_dict(data.get('preferences', {})) | |
goals = StudentGoals.from_dict(data.get('goals', {})) | |
return cls( | |
student_id=data['student_id'], | |
name=data.get('name'), | |
grade_level=data.get('grade_level'), | |
age=data.get('age'), | |
preferences=preferences, | |
goals=goals, | |
created_at=created_at, | |
last_updated=last_updated, | |
last_active=last_active, | |
current_difficulty_level=data.get('current_difficulty_level', 0.5), | |
learning_velocity=data.get('learning_velocity', 0.0), | |
engagement_level=data.get('engagement_level', 0.5), | |
total_concepts_attempted=data.get('total_concepts_attempted', 0), | |
total_concepts_mastered=data.get('total_concepts_mastered', 0), | |
total_learning_time=data.get('total_learning_time', 0), | |
average_accuracy=data.get('average_accuracy', 0.0), | |
strength_areas=data.get('strength_areas', []), | |
challenge_areas=data.get('challenge_areas', []), | |
learning_patterns=data.get('learning_patterns', []), | |
recommended_strategies=data.get('recommended_strategies', []) | |
) | |
def to_json(self) -> str: | |
"""Convert to JSON string.""" | |
return json.dumps(self.to_dict(), indent=2) | |
def from_json(cls, json_str: str) -> 'StudentProfile': | |
"""Create from JSON string.""" | |
data = json.loads(json_str) | |
return cls.from_dict(data) | |