# Complete Code Index - Piano Training Platform ## 📋 Quick Navigation **Jump to**: [Frontend](#frontend-code) | [Backend](#backend-code) | [Documentation](#documentation) | [Configuration](#configuration) --- ## Frontend Code ### 🎮 Gamification System #### StreakCounter.tsx **Path**: `src/components/Gamification/StreakCounter.tsx` **Lines**: 100 **Purpose**: Track daily practice streaks with visual feedback **Key Features**: - Flame intensity based on streak (cool/warm/hot/inferno) - Best streak tracking - Today's practice status - Motivational messages **Code Preview**: ```typescript const getFlameIntensity = (streak: number) => { if (streak >= 30) return 'inferno'; if (streak >= 14) return 'hot'; if (streak >= 7) return 'warm'; return 'cool'; }; ``` #### AchievementSystem.tsx **Path**: `src/components/Gamification/AchievementSystem.tsx` **Lines**: 120 **Purpose**: Manage achievements and level progression **Key Features**: - Achievement unlocking logic - Progress tracking - Level calculation (100 points = 1 level) - Visual badges **Code Preview**: ```typescript const getLevelProgress = () => { const pointsForNextLevel = level * 100; return Math.min((totalPoints % 100) / 100, 1); }; ``` #### Leaderboard.tsx **Path**: `src/components/Gamification/Leaderboard.tsx` **Lines**: 150 **Purpose**: Competitive ranking system **Key Features**: - Multiple timeframes (daily/weekly/monthly/all-time) - Expandable user details - Current user highlighting - Rank medals (🥇🥈🥉) **Code Preview**: ```typescript const getRankIcon = (rank: number) => { switch (rank) { case 1: return '🥇'; case 2: return '🥈'; case 3: return '🥉'; default: return `#${rank}`; } }; ``` #### useGamification.ts **Path**: `src/hooks/useGamification.ts` **Lines**: 250 **Purpose**: Gamification state management with persistence **Key Features**: - LocalStorage persistence - Streak calculation - Achievement unlocking - Session recording **Code Preview**: ```typescript const recordSession = useCallback((sessionData: { duration: number; accuracy: number; hasErrors: boolean; }) => { updateStreak(); updateAchievementProgress('first_session', 1); if (sessionData.accuracy >= 95) { updateAchievementProgress('accuracy_master', sessionData.accuracy); } }, [updateStreak, updateAchievementProgress]); ``` ### 🛠️ Practice Tools #### Metronome.tsx **Path**: `src/components/Tools/Metronome.tsx` **Lines**: 200 **Purpose**: Interactive metronome with audio **Key Features**: - BPM control (40-240) - Multiple time signatures - Tap tempo detection - Web Audio API sound generation **Code Preview**: ```typescript const createOscillator = (frequency: number, duration: number) => { const osc = audioContext.createOscillator(); const gainNode = audioContext.createGain(); osc.frequency.value = frequency; osc.type = 'sine'; gainNode.gain.setValueAtTime(0.3, audioContext.currentTime); osc.start(audioContext.currentTime); osc.stop(audioContext.currentTime + duration); }; ``` #### StudyLoop.tsx **Path**: `src/components/Tools/StudyLoop.tsx` **Lines**: 180 **Purpose**: Practice loop for specific measures **Key Features**: - Measure range selection - Repetition counting - Progress tracking - Auto-pause on completion **Code Preview**: ```typescript const handleStartLoop = () => { const loopMeasures = Array.from( { length: loopEnd - loopStart + 1 }, (_, i) => loopStart + i ); setIsLooping(true); onLoopChange(loopMeasures, true); }; ``` ### 🎹 MIDI Player & Practice #### MidiPlayer.tsx **Path**: `src/components/Player/MidiPlayer.tsx` **Lines**: 300 **Purpose**: Full-featured MIDI playback **Key Features**: - Speed control (0.25x - 2x) - Volume control - Seek/progress bar - Tone.js integration **Code Preview**: ```typescript const scheduleMidi = (midi: Midi) => { midi.tracks.forEach(track => { track.notes.forEach(note => { Tone.Transport.schedule((time) => { synth.triggerAttackRelease( note.name, note.duration, time, note.velocity ); }, note.time); }); }); }; ``` #### PracticeMode.tsx **Path**: `src/components/Practice/PracticeMode.tsx` **Lines**: 400 **Purpose**: Real-time practice with feedback **Key Features**: - Note detection from MIDI - Instant correct/incorrect feedback - Combo tracking - Grade calculation (S/A/B/C/D) - Score statistics **Code Preview**: ```typescript const handleNotePlay = (note: string, velocity: number) => { const expectedNote = expectedNotes[currentNoteIndex.current]; const isCorrect = expectedNote && note === expectedNote.name; if (isCorrect) { setScore(prev => ({ ...prev, correct: prev.correct + 1 })); setCombo(prev => prev + 1); setFeedback('✓ Correto!'); } else { setScore(prev => ({ ...prev, incorrect: prev.incorrect + 1 })); setCombo(0); setFeedback('✗ Incorreto'); } }; ``` ### 📊 Dashboard #### StudentDashboard.tsx **Path**: `src/pages/StudentDashboard.tsx` **Lines**: 250 **Purpose**: Main student interface **Key Features**: - Tab navigation (Progress/Tools/Community) - Stats overview - Session history - Practice goals **Code Preview**: ```typescript const handleSessionComplete = () => { gamification.recordSession({ duration: 25, accuracy: 0.87, hasErrors: true }); }; ``` --- ## Backend Code ### 🎯 Score Following & Analysis #### score_following.py **Path**: `backend/app/analysis/score_following.py` **Lines**: 250 **Purpose**: Real-time score following with DTW **Key Features**: - MIDI score loading - Feature extraction (pitch class vectors) - DTW alignment - Real-time position tracking **Code Preview**: ```python def align_performance(self, performance_notes: List[Dict]) -> Dict[str, Any]: # Extract performance features perf_features = self._extract_features(performance_notes) # Compute DTW alignment distance = dtw.distance(perf_features, self.score_features) path = dtw.warping_path(perf_features, self.score_features) # Convert to alignment mapping alignment = self._create_alignment_mapping(path, perf_onsets, score_onsets) return { 'success': True, 'alignment': alignment, 'dtw_distance': distance } ``` #### metrics.py **Path**: `backend/app/analysis/metrics.py` **Lines**: 300 **Purpose**: Calculate performance metrics **Key Features**: - Onset detection (F1, precision, recall) - Pitch accuracy - Rhythm analysis - Expressivity metrics **Code Preview**: ```python def compute_overall_assessment(self, alignment: List[Dict]) -> Dict[str, Any]: onset_metrics = self.compute_onset_metrics(alignment) pitch_metrics = self.compute_pitch_metrics(alignment) rhythm_metrics = self.compute_rhythm_metrics(alignment) expressivity_metrics = self.compute_expressivity_metrics() # Weighted overall score overall_score = ( onset_metrics['onset_f1'] * 0.3 + pitch_metrics['pitch_accuracy'] * 0.3 + rhythm_metrics['tempo_accuracy'] * 0.25 + expressivity_metrics['dynamic_range'] * 0.15 ) return { 'overall_score': float(overall_score), 'performance_level': self._determine_level(overall_score), ... } ``` #### measure_analysis.py **Path**: `backend/app/analysis/measure_analysis.py` **Lines**: 200 **Purpose**: Measure-by-measure analysis **Key Features**: - Group notes by measure - Calculate measure metrics - Identify problem areas - Generate practice suggestions **Code Preview**: ```python def get_problem_measures(self, measure_results: Dict[int, Dict], threshold: float = 0.7) -> List[Dict]: problem_measures = [] for measure, results in measure_results.items(): if results['accuracy'] < threshold: problem_measures.append({ 'measure': measure, 'accuracy': results['accuracy'], 'issues': self._identify_issues(results), 'suggestions': self._generate_suggestions(results) }) return sorted(problem_measures, key=lambda x: x['accuracy']) ``` ### 🌐 API Layer #### analysis.py (endpoints) **Path**: `backend/app/api/endpoints/analysis.py` **Lines**: 250 **Purpose**: REST API + WebSocket for analysis **Key Features**: - POST /analyze - Create analysis job - GET /analyze/{job_id} - Get results - WebSocket /ws/realtime - Real-time following - POST /analyze/batch - Batch processing **Code Preview**: ```python @router.post("/analyze", response_model=AnalysisResponse) async def create_analysis(request: AnalysisRequest, background_tasks: BackgroundTasks): job_id = str(uuid.uuid4()) analysis_jobs[job_id] = { "status": AnalysisStatus.PENDING, "created_at": datetime.utcnow(), "request": request.dict() } # Start async task analyze_performance_task.delay( job_id=job_id, score_midi_url=request.score_midi_url, performance_midi_url=request.performance_midi_url ) return AnalysisResponse(job_id=job_id, status=AnalysisStatus.PENDING) ``` ### ⚙️ Async Processing #### tasks.py **Path**: `backend/app/celery/tasks.py` **Lines**: 200 **Purpose**: Celery tasks for heavy processing **Key Features**: - analyze_performance_task - Full analysis - Progress tracking - Error handling - Result storage **Code Preview**: ```python @celery_app.task(bind=True, name="analyze_performance_task") def analyze_performance_task(self, job_id: str, score_midi_url: str, performance_midi_url: str): try: # Update progress self.update_state(state='PROCESSING', meta={'current': 20, 'total': 100}) # Load and analyze score_follower = ScoreFollower(score_midi_path=score_path) alignment = score_follower.align_performance(performance_notes) # Compute metrics self.update_state(state='PROCESSING', meta={'current': 80, 'total': 100}) metrics = PerformanceMetrics(score_notes, performance_notes) assessment = metrics.compute_overall_assessment(alignment['alignment']) return {'success': True, 'assessment': assessment} except Exception as e: return {'success': False, 'error': str(e)} ``` ### 📦 Schemas #### analysis.py (schemas) **Path**: `backend/app/schemas/analysis.py` **Lines**: 150 **Purpose**: Pydantic models for validation **Key Features**: - AnalysisRequest/Response - PerformanceMetrics - MeasureMetrics - RealTimeUpdate **Code Preview**: ```python class PerformanceMetrics(BaseModel): overall_score: float = Field(..., description="Overall score (0-1)") performance_level: str = Field(..., description="Level (Expert/Advanced/...)") onset_metrics: Dict[str, float] pitch_metrics: Dict[str, float] rhythm_metrics: Dict[str, float] expressivity_metrics: Dict[str, float] ``` ### 🚀 Application Entry #### main.py **Path**: `backend/app/main.py` **Lines**: 70 **Purpose**: FastAPI application setup **Key Features**: - CORS configuration - Router inclusion - Health check endpoint - Lifespan management **Code Preview**: ```python app = FastAPI( title="Music Training Platform API", description="Backend for Score Following & Analysis", version="0.1.0", lifespan=lifespan ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["analysis"]) ``` --- ## Documentation ### Main Guides - `README.md` - Project overview - `MVP_TESTING_GUIDE.md` - Complete testing guide (2000+ lines) - `TESTING_READINESS.md` - Feature status and libraries - `PROJECT_STRUCTURE.md` - Detailed file structure - `AUDIT_SUMMARY.md` - Audit priorities and checklist ### Feature Documentation - `FEATURE_7_README.md` - Gamification & UX (3000+ lines) - `backend/FEATURE_4_README.md` - Score Following (2500+ lines) --- ## Configuration ### Frontend **File**: `package.json` **Key Dependencies**: ```json { "tone": "^14.7.77", "@tonejs/midi": "^2.0.28", "opensheetmusicdisplay": "^1.8.6", "react": "^18.2.0" } ``` ### Backend **File**: `backend/pyproject.toml` **Key Dependencies**: ```toml [tool.poetry.dependencies] fastapi = "^0.104.0" celery = "^5.3.4" partitura = "^1.5.0" mir-eval = "^0.7" librosa = "^0.10.1" dtaidistance = "^2.3.12" ``` --- ## Quick File Access ### For Security Audit 1. `backend/app/api/endpoints/analysis.py` - API security 2. `src/hooks/useGamification.ts` - LocalStorage usage 3. `backend/app/main.py` - CORS configuration ### For Performance Audit 1. `src/components/Practice/PracticeMode.tsx` - State updates 2. `backend/app/celery/tasks.py` - Async processing 3. `src/components/Player/MidiPlayer.tsx` - Audio performance ### For Functionality Audit 1. `backend/app/analysis/score_following.py` - Core algorithm 2. `src/components/Practice/PracticeMode.tsx` - User interaction 3. `backend/app/analysis/metrics.py` - Metric calculation --- **Total Files**: 26 **Total Lines**: ~4,500 **Documentation**: ~7,500 lines **Last Updated**: 2025-10-25