- 实现智能排序:数字 -> 字母 -> 其他符号 - 添加 smartSort() 方法支持自然数值排序 - 默认启用排序功能,用户无需设置 - 支持多语言字符(中文、日文、英文等) - 添加完整的测试工具和文档 新增文件: - test_sort.html (可视化测试页面) - verify_sort.py (Python验证脚本) - verify_sort.js (Node.js验证脚本) - SORT_FEATURE.md (功能说明) - SORT_USAGE.md (使用指南) - QUICKSTART_SORT.md (快速开始) - IMPLEMENTATION_SUMMARY.md (实现总结) - CHANGELOG_SORT.md (更新日志) - UPDATE_SUMMARY.md (更新说明) 修改文件: - public/src/js/songselect.js (添加智能排序逻辑) - README.md (更新功能介绍)
189 lines
5.0 KiB
JavaScript
189 lines
5.0 KiB
JavaScript
/**
|
||
* 歌曲排序功能验证脚本
|
||
* 运行方式: node verify_sort.js
|
||
*/
|
||
|
||
// 智能排序函数(与实际代码完全相同)
|
||
function smartSort(titleA, titleB) {
|
||
// 辅助函数:判断字符类型
|
||
const getCharType = (char) => {
|
||
if (!char) return 3; // 空字符串排在最后
|
||
const code = char.charCodeAt(0);
|
||
|
||
// 数字 (0-9)
|
||
if (code >= 48 && code <= 57) return 0;
|
||
|
||
// 英文字母 (A-Z, a-z)
|
||
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) return 1;
|
||
|
||
// 其他所有字符(符号、中文、日文等)
|
||
return 2;
|
||
};
|
||
|
||
// 辅助函数:提取首字符并确定类型
|
||
const getFirstCharInfo = (title) => {
|
||
if (!title || title.length === 0) return { type: 3, char: '', title: '' };
|
||
const firstChar = title.charAt(0);
|
||
const type = getCharType(firstChar);
|
||
return { type, char: firstChar, title };
|
||
};
|
||
|
||
const infoA = getFirstCharInfo(titleA);
|
||
const infoB = getFirstCharInfo(titleB);
|
||
|
||
// 首先按字符类型排序:数字 < 字母 < 其他符号
|
||
if (infoA.type !== infoB.type) {
|
||
return infoA.type - infoB.type;
|
||
}
|
||
|
||
// 同类型字符,使用 localeCompare 进行自然排序
|
||
return titleA.localeCompare(titleB, undefined, {
|
||
numeric: true,
|
||
sensitivity: 'base'
|
||
});
|
||
}
|
||
|
||
// 测试数据
|
||
const testSongs = [
|
||
"太鼓の達人",
|
||
"Zyxwv Test",
|
||
"123 Song",
|
||
"abc melody",
|
||
"456 rhythm",
|
||
"*Special*",
|
||
"10 drums",
|
||
"あいうえお",
|
||
"2 beats",
|
||
"ZZZ Final",
|
||
"1st Place",
|
||
"100 percent",
|
||
"ドンだー!",
|
||
"Battle No.1",
|
||
"~奇跡~",
|
||
"777",
|
||
"Angel Beats",
|
||
"カノン",
|
||
"Don't Stop",
|
||
"零 -ZERO-",
|
||
"3pieces",
|
||
"Apple",
|
||
"燎原ノ舞",
|
||
"99 Balloons",
|
||
"Brave Heart",
|
||
"夏祭り",
|
||
"5 Elements",
|
||
"50音",
|
||
"Zephyr",
|
||
"α wave"
|
||
];
|
||
|
||
// 获取字符类型标签
|
||
function getTypeLabel(title) {
|
||
const firstChar = title.charAt(0);
|
||
const code = firstChar.charCodeAt(0);
|
||
|
||
if (code >= 48 && code <= 57) return '[数字]';
|
||
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) return '[字母]';
|
||
return '[其他]';
|
||
}
|
||
|
||
// 执行排序测试
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('🥁 Taiko Web - 歌曲智能排序功能测试');
|
||
console.log('='.repeat(60) + '\n');
|
||
|
||
console.log('📋 原始歌曲列表 (共 ' + testSongs.length + ' 首):');
|
||
console.log('-'.repeat(60));
|
||
testSongs.forEach((song, index) => {
|
||
console.log(`${(index + 1).toString().padStart(2, ' ')}. ${song}`);
|
||
});
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('⚙️ 执行智能排序...\n');
|
||
|
||
// 排序
|
||
const sortedSongs = [...testSongs].sort(smartSort);
|
||
|
||
console.log('✅ 排序后的歌曲列表:');
|
||
console.log('-'.repeat(60));
|
||
|
||
let currentType = null;
|
||
sortedSongs.forEach((song, index) => {
|
||
const typeLabel = getTypeLabel(song);
|
||
|
||
// 检测类型变化,添加分隔符
|
||
if (currentType !== typeLabel) {
|
||
if (currentType !== null) {
|
||
console.log(''); // 空行分隔不同类型
|
||
}
|
||
currentType = typeLabel;
|
||
}
|
||
|
||
console.log(`${(index + 1).toString().padStart(2, ' ')}. ${song.padEnd(25, ' ')} ${typeLabel}`);
|
||
});
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('📊 统计信息:');
|
||
console.log('-'.repeat(60));
|
||
|
||
// 统计各类型数量
|
||
let numberCount = 0;
|
||
let letterCount = 0;
|
||
let otherCount = 0;
|
||
|
||
sortedSongs.forEach(song => {
|
||
const label = getTypeLabel(song);
|
||
if (label === '[数字]') numberCount++;
|
||
else if (label === '[字母]') letterCount++;
|
||
else otherCount++;
|
||
});
|
||
|
||
console.log(`数字开头: ${numberCount} 首`);
|
||
console.log(`字母开头: ${letterCount} 首`);
|
||
console.log(`其他开头: ${otherCount} 首`);
|
||
console.log(`总计: ${sortedSongs.length} 首`);
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('✨ 排序规则验证:');
|
||
console.log('-'.repeat(60));
|
||
|
||
// 验证排序是否正确
|
||
let isValid = true;
|
||
let prevType = -1;
|
||
|
||
for (let i = 0; i < sortedSongs.length; i++) {
|
||
const song = sortedSongs[i];
|
||
const firstChar = song.charAt(0);
|
||
const code = firstChar.charCodeAt(0);
|
||
|
||
let currentType;
|
||
if (code >= 48 && code <= 57) currentType = 0;
|
||
else if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) currentType = 1;
|
||
else currentType = 2;
|
||
|
||
if (currentType < prevType) {
|
||
isValid = false;
|
||
console.log(`❌ 错误: "${song}" (类型 ${currentType}) 出现在类型 ${prevType} 之后`);
|
||
}
|
||
|
||
prevType = currentType;
|
||
}
|
||
|
||
if (isValid) {
|
||
console.log('✅ 排序规则验证通过!');
|
||
console.log(' - 数字优先');
|
||
console.log(' - 字母次之');
|
||
console.log(' - 其他符号最后');
|
||
} else {
|
||
console.log('❌ 排序规则验证失败!');
|
||
}
|
||
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log('🎵 测试完成!');
|
||
console.log('='.repeat(60) + '\n');
|
||
|
||
// 导出函数供其他模块使用
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
module.exports = { smartSort };
|
||
}
|