13 KiB
Complete Code Index - Piano Training Platform
📋 Quick Navigation
Jump to: Frontend | Backend | Documentation | 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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
@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:
@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:
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:
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 overviewMVP_TESTING_GUIDE.md- Complete testing guide (2000+ lines)TESTING_READINESS.md- Feature status and librariesPROJECT_STRUCTURE.md- Detailed file structureAUDIT_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:
{
"tone": "^14.7.77",
"@tonejs/midi": "^2.0.28",
"opensheetmusicdisplay": "^1.8.6",
"react": "^18.2.0"
}
Backend
File: backend/pyproject.toml
Key Dependencies:
[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
backend/app/api/endpoints/analysis.py- API securitysrc/hooks/useGamification.ts- LocalStorage usagebackend/app/main.py- CORS configuration
For Performance Audit
src/components/Practice/PracticeMode.tsx- State updatesbackend/app/celery/tasks.py- Async processingsrc/components/Player/MidiPlayer.tsx- Audio performance
For Functionality Audit
backend/app/analysis/score_following.py- Core algorithmsrc/components/Practice/PracticeMode.tsx- User interactionbackend/app/analysis/metrics.py- Metric calculation
Total Files: 26 Total Lines: ~4,500 Documentation: ~7,500 lines Last Updated: 2025-10-25