- Update pagination from 50 to 100 songs per page for better UX - Frontend: Update usePaginatedSongs hook default pageSize to 100 - Frontend: Update API service default limits to 100 - Frontend: Update App.tsx pageSize configuration to 100 - Backend: Update songs routes default limit to 100 for both main and playlist endpoints - Maintain existing infinite scroll functionality with larger batch sizes - Improve performance by reducing number of API calls needed - Verified API endpoints return correct pagination info and song counts
165 lines
5.3 KiB
JavaScript
165 lines
5.3 KiB
JavaScript
import { SongMatchingService } from './src/services/songMatchingService.js';
|
|
|
|
async function testMatchingAlgorithm() {
|
|
console.log('🧪 Testing improved matching algorithm...');
|
|
|
|
const matchingService = new SongMatchingService();
|
|
|
|
// Test cases for filename matching
|
|
const testCases = [
|
|
{
|
|
musicFile: {
|
|
originalName: 'Artist Name - Song Title.mp3',
|
|
title: 'Song Title',
|
|
artist: 'Artist Name'
|
|
},
|
|
song: {
|
|
title: 'Song Title',
|
|
artist: 'Artist Name',
|
|
location: '/path/to/Artist Name - Song Title.mp3'
|
|
},
|
|
expectedScore: 1.0,
|
|
description: 'Exact Artist-Title pattern match'
|
|
},
|
|
{
|
|
musicFile: {
|
|
originalName: 'Song Title (Remix).mp3',
|
|
title: 'Song Title',
|
|
artist: 'Artist Name'
|
|
},
|
|
song: {
|
|
title: 'Song Title',
|
|
artist: 'Artist Name',
|
|
location: '/path/to/Song Title.mp3'
|
|
},
|
|
expectedScore: 0.95,
|
|
description: 'Filename variation match'
|
|
},
|
|
{
|
|
musicFile: {
|
|
originalName: 'Artist Name feat. Other Artist - Song Title.mp3',
|
|
title: 'Song Title',
|
|
artist: 'Artist Name'
|
|
},
|
|
song: {
|
|
title: 'Song Title',
|
|
artist: 'Artist Name',
|
|
location: '/path/to/Artist Name - Song Title.mp3'
|
|
},
|
|
expectedScore: 0.95,
|
|
description: 'Partial Artist-Title pattern match'
|
|
},
|
|
{
|
|
musicFile: {
|
|
originalName: 'Song Title.mp3',
|
|
title: 'Song Title',
|
|
artist: 'Artist Name'
|
|
},
|
|
song: {
|
|
title: 'Song Title',
|
|
artist: 'Artist Name',
|
|
location: '/path/to/Song Title.mp3'
|
|
},
|
|
expectedScore: 1.0,
|
|
description: 'Exact filename match'
|
|
},
|
|
{
|
|
musicFile: {
|
|
originalName: 'Different Name.mp3',
|
|
title: 'Song Title',
|
|
artist: 'Artist Name'
|
|
},
|
|
song: {
|
|
title: 'Song Title',
|
|
artist: 'Artist Name',
|
|
location: '/path/to/Song Title.mp3'
|
|
},
|
|
expectedScore: 0.9,
|
|
description: 'Title match when filename differs'
|
|
}
|
|
];
|
|
|
|
console.log('\n📊 Testing filename matching scenarios...');
|
|
|
|
for (const testCase of testCases) {
|
|
console.log(`\n🔍 Testing: ${testCase.description}`);
|
|
console.log(` Music File: ${testCase.musicFile.originalName}`);
|
|
console.log(` Song: ${testCase.song.title} by ${testCase.song.artist}`);
|
|
|
|
// Test the calculateMatch method directly
|
|
const matchResult = matchingService['calculateMatch'](testCase.musicFile, testCase.song, {
|
|
enableFuzzyMatching: true,
|
|
enablePartialMatching: true
|
|
});
|
|
|
|
const status = matchResult.confidence >= testCase.expectedScore * 0.9 ? '✅' : '❌';
|
|
console.log(` ${status} Confidence: ${(matchResult.confidence * 100).toFixed(1)}% (expected: ${(testCase.expectedScore * 100).toFixed(1)}%)`);
|
|
console.log(` Match Type: ${matchResult.matchType}`);
|
|
console.log(` Reason: ${matchResult.matchReason}`);
|
|
}
|
|
|
|
// Test filename matching function directly
|
|
console.log('\n🔍 Testing filename matching function...');
|
|
|
|
const filenameTests = [
|
|
{
|
|
filename: 'Artist - Song.mp3',
|
|
song: { title: 'Song', artist: 'Artist' },
|
|
expected: 'Exact Artist-Title pattern match'
|
|
},
|
|
{
|
|
filename: 'Song (Remix).mp3',
|
|
song: { title: 'Song', artist: 'Artist' },
|
|
expected: 'Filename variation matches title'
|
|
},
|
|
{
|
|
filename: 'Artist feat. Other - Song.mp3',
|
|
song: { title: 'Song', artist: 'Artist' },
|
|
expected: 'Exact Artist-Title pattern match'
|
|
}
|
|
];
|
|
|
|
for (const test of filenameTests) {
|
|
const result = matchingService['matchFilename'](test.filename, test.song);
|
|
const status = result.reason.includes(test.expected) ? '✅' : '❌';
|
|
console.log(`${status} "${test.filename}" -> "${test.expected}" (${(result.score * 100).toFixed(1)}%)`);
|
|
}
|
|
|
|
// Test location matching function
|
|
console.log('\n🔍 Testing location matching function...');
|
|
|
|
const locationTests = [
|
|
{
|
|
filename: 'Song.mp3',
|
|
location: '/path/to/Song.mp3',
|
|
expected: 'Exact location filename match'
|
|
},
|
|
{
|
|
filename: 'Song (Remix).mp3',
|
|
location: '/path/to/Song.mp3',
|
|
expected: 'Filename matches location variation'
|
|
},
|
|
{
|
|
filename: 'Artist - Song.mp3',
|
|
location: '/path/to/Song.mp3',
|
|
expected: 'Location filename contains match'
|
|
}
|
|
];
|
|
|
|
for (const test of locationTests) {
|
|
const result = matchingService['matchLocation'](test.filename, test.location);
|
|
const status = result.reason.includes(test.expected) ? '✅' : '❌';
|
|
console.log(`${status} "${test.filename}" in "${test.location}" -> "${test.expected}" (${(result.score * 100).toFixed(1)}%)`);
|
|
}
|
|
|
|
console.log('\n🎉 Matching algorithm tests completed!');
|
|
console.log('\n📋 Key improvements:');
|
|
console.log(' ✅ Filename matching is now the highest priority');
|
|
console.log(' ✅ Early termination for exact matches (95%+ confidence)');
|
|
console.log(' ✅ Comprehensive pattern matching for Artist-Title combinations');
|
|
console.log(' ✅ Better handling of filename variations (remix, edit, etc.)');
|
|
console.log(' ✅ Improved location matching for Rekordbox file paths');
|
|
console.log(' ✅ Weighted scoring system with filename bias');
|
|
}
|
|
|
|
testMatchingAlgorithm().catch(console.error);
|