Spaces:
Runtime error
Runtime error
| """ | |
| Practice session and analysis models | |
| """ | |
| from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Float, JSON, Text, Boolean | |
| from sqlalchemy.orm import relationship | |
| from sqlalchemy.sql import func | |
| from config.database import Base | |
| class PracticeSession(Base): | |
| __tablename__ = "practice_sessions" | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey("students.id"), nullable=False) | |
| assignment_id = Column(Integer, ForeignKey("assignments.id"), nullable=True) | |
| # Session info | |
| practice_type = Column(String, nullable=False) # conversation, reading, articulation | |
| technique = Column(String, nullable=False) # normal, prolonged_speech, easy_onset | |
| duration_seconds = Column(Float) | |
| # Content | |
| prompt_text = Column(Text) # What they were supposed to say/read | |
| transcribed_text = Column(Text) # What they actually said | |
| audio_file_path = Column(JSON) # Array of audio file paths (for multi-turn sessions) or single path | |
| # Format: ["sessionID_date_studentID_therapistID_turn1.wav", "sessionID_date_studentID_therapistID_turn2.wav", ...] | |
| # For reading practice: single string or array with one element | |
| # Quick metrics | |
| total_words = Column(Integer) | |
| words_per_minute = Column(Float) | |
| # Status | |
| is_completed = Column(Boolean, default=False) | |
| completed_at = Column(DateTime(timezone=True)) | |
| created_at = Column(DateTime(timezone=True), server_default=func.now()) | |
| # Relationships | |
| student = relationship("Student", back_populates="sessions") | |
| assignment = relationship("Assignment", back_populates="sessions") | |
| analysis = relationship("SessionAnalysis", back_populates="session", uselist=False) | |
| def __repr__(self): | |
| return f"<PracticeSession {self.id} - {self.practice_type}>" | |
| class SessionAnalysis(Base): | |
| __tablename__ = "session_analyses" | |
| id = Column(Integer, primary_key=True) | |
| session_id = Column(Integer, ForeignKey("practice_sessions.id"), unique=True, nullable=False) | |
| # Analysis results (stored as JSON for flexibility) | |
| stutter_analysis = Column(JSON) # Detailed stutter types, counts, locations | |
| fluency_analysis = Column(JSON) # Prolongation %, consistency scores | |
| rushed_speech_analysis = Column(JSON) # Burst patterns, pause analysis | |
| articulation_analysis = Column(JSON) # Accuracy scores per sound | |
| # Summary metrics | |
| total_stutters = Column(Integer, default=0) | |
| stutter_frequency_percent = Column(Float, default=0.0) | |
| fluency_score = Column(Float) # 0-100 | |
| rushed_speech_severity = Column(String) # minimal, mild, moderate, severe | |
| articulation_accuracy = Column(Float) # 0-100 | |
| # Affected phonemes/patterns | |
| struggled_phonemes = Column(JSON) # List of problem sounds | |
| stutter_patterns = Column(JSON) # Common patterns identified | |
| # Feedback | |
| patient_feedback = Column(Text) # Generated patient-friendly feedback | |
| therapist_notes = Column(Text) # Detailed clinical notes | |
| # Timestamps | |
| analyzed_at = Column(DateTime(timezone=True), server_default=func.now()) | |
| # Relationships | |
| session = relationship("PracticeSession", back_populates="analysis") | |
| def __repr__(self): | |
| return f"<SessionAnalysis for session {self.session_id}>" |