Files
JDClone/jd-clone/src/services/song-service.ts

116 lines
3.6 KiB
TypeScript

import { Song, Choreography, DifficultyLevel, Move } from '../types';
class SongService {
/**
* Get all available songs
*/
async getSongs(): Promise<Song[]> {
try {
const response = await fetch('/index.json');
if (!response.ok) {
throw new Error(`Failed to fetch songs: ${response.statusText}`);
}
const data = await response.json();
// Transform the data to match our Song interface
return Object.entries(data.songs).map(([id, songData]: [string, any]) => ({
id,
...songData,
// Add default difficulty levels since they're not in the JSON
difficulty: ['medium', 'hard']
}));
} catch (error) {
console.error('Error fetching songs:', error);
return [];
}
}
/**
* Get a specific song by ID
*/
async getSongById(id: string): Promise<Song | null> {
try {
const songs = await this.getSongs();
return songs.find(song => song.id === id) || null;
} catch (error) {
console.error(`Error fetching song ${id}:`, error);
return null;
}
}
/**
* Get choreography for a song at a specific difficulty
*/
async getChoreography(songId: string, difficulty: DifficultyLevel): Promise<Choreography | null> {
try {
const song = await this.getSongById(songId);
if (!song) {
return null;
}
// Fetch the moves data from the URL in song.GameData.moves
const response = await fetch(song.GameData.moves);
if (!response.ok) {
throw new Error(`Failed to fetch choreography: ${response.statusText}`);
}
const choreographyData = await response.json();
// Process the choreography data based on difficulty
// This would need to be adjusted based on the actual format of the moves data
return {
songId,
difficulty,
moves: this.processChoreographyData(choreographyData, difficulty)
};
} catch (error) {
console.error(`Error fetching choreography for song ${songId}:`, error);
return null;
}
}
/**
* Process choreography data from the JSON file
* Note: This would need to be adjusted based on the actual data structure
*/
private processChoreographyData(data: any, difficulty: DifficultyLevel): Move[] {
// This is a placeholder implementation
// You'll need to adapt this based on the actual format of your poses.json files
const moves: Move[] = [];
// Example implementation assuming data has a moves array
if (Array.isArray(data.moves)) {
data.moves.forEach((moveData: any, index: number) => {
moves.push({
id: `${difficulty}-move-${index}`,
startTime: moveData.startTime || index * 3000,
duration: moveData.duration || 2000,
keyPosePoints: moveData.keyPoints || [],
difficulty,
score: difficulty === 'easy' ? 100 :
difficulty === 'medium' ? 150 :
difficulty === 'hard' ? 200 : 300
});
});
}
return moves;
}
/**
* Generate a choreography from a video (placeholder for future implementation)
*/
async generateChoreography(videoUrl: string, songId: string, difficulty: DifficultyLevel): Promise<Choreography | null> {
// This would use the pose detection API to analyze a video and generate choreography data
console.log(`Generating choreography for ${videoUrl}, song ${songId}, difficulty ${difficulty}`);
// This is a placeholder - in a real implementation,
// this would call an API to process the video and generate choreography
return null;
}
}
// Create singleton instance
const songService = new SongService();
export default songService;