Files
taiko-web/verify_sort.py
AnthonyDuan 25c26b2b2e feat: 添加歌曲智能排序功能(默认启用)
- 实现智能排序:数字 -> 字母 -> 其他符号
- 添加 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 (更新功能介绍)
2025-11-15 15:59:08 +08:00

210 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
歌曲排序功能验证脚本
运行方式: python verify_sort.py
"""
import locale
from functools import cmp_to_key
# 设置本地化以支持多语言排序
locale.setlocale(locale.LC_ALL, '')
def smart_sort(title_a, title_b):
"""
智能排序函数(与 JavaScript 版本逻辑相同)
"""
def get_char_type(char):
"""判断字符类型"""
if not char:
return 3 # 空字符串排在最后
code = ord(char)
# 数字 (0-9)
if 48 <= code <= 57:
return 0
# 英文字母 (A-Z, a-z)
if (65 <= code <= 90) or (97 <= code <= 122):
return 1
# 其他所有字符(符号、中文、日文等)
return 2
# 获取首字符类型
type_a = get_char_type(title_a[0] if title_a else None)
type_b = get_char_type(title_b[0] if title_b else None)
# 首先按字符类型排序:数字 < 字母 < 其他符号
if type_a != type_b:
return type_a - type_b
# 同类型字符,使用自然排序
# Python 的 locale.strcoll 提供类似 localeCompare 的功能
try:
# 尝试数值比较(对于纯数字开头的字符串)
if type_a == 0: # 数字类型
# 提取开头的数字部分进行比较
num_a = ''
num_b = ''
for c in title_a:
if c.isdigit():
num_a += c
else:
break
for c in title_b:
if c.isdigit():
num_b += c
else:
break
if num_a and num_b:
num_cmp = int(num_a) - int(num_b)
if num_cmp != 0:
return num_cmp
# 字符串比较(忽略大小写)
return locale.strcoll(title_a.lower(), title_b.lower())
except:
# 如果 locale 比较失败,使用简单的字符串比较
if title_a.lower() < title_b.lower():
return -1
elif title_a.lower() > title_b.lower():
return 1
return 0
def get_type_label(title):
"""获取字符类型标签"""
if not title:
return '[空]'
code = ord(title[0])
if 48 <= code <= 57:
return '[数字]'
if (65 <= code <= 90) or (97 <= code <= 122):
return '[字母]'
return '[其他]'
def main():
# 测试数据
test_songs = [
"太鼓の達人",
"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"
]
print('\n' + '=' * 60)
print('🥁 Taiko Web - 歌曲智能排序功能测试')
print('=' * 60 + '\n')
print(f'📋 原始歌曲列表 (共 {len(test_songs)} 首):')
print('-' * 60)
for i, song in enumerate(test_songs, 1):
print(f'{i:2d}. {song}')
print('\n' + '=' * 60)
print('⚙️ 执行智能排序...\n')
# 排序
sorted_songs = sorted(test_songs, key=cmp_to_key(smart_sort))
print('✅ 排序后的歌曲列表:')
print('-' * 60)
current_type = None
for i, song in enumerate(sorted_songs, 1):
type_label = get_type_label(song)
# 检测类型变化,添加分隔符
if current_type != type_label:
if current_type is not None:
print() # 空行分隔不同类型
current_type = type_label
print(f'{i:2d}. {song:25s} {type_label}')
print('\n' + '=' * 60)
print('📊 统计信息:')
print('-' * 60)
# 统计各类型数量
number_count = sum(1 for song in sorted_songs if get_type_label(song) == '[数字]')
letter_count = sum(1 for song in sorted_songs if get_type_label(song) == '[字母]')
other_count = sum(1 for song in sorted_songs if get_type_label(song) == '[其他]')
print(f'数字开头: {number_count}')
print(f'字母开头: {letter_count}')
print(f'其他开头: {other_count}')
print(f'总计: {len(sorted_songs)}')
print('\n' + '=' * 60)
print('✨ 排序规则验证:')
print('-' * 60)
# 验证排序是否正确
is_valid = True
prev_type = -1
for song in sorted_songs:
code = ord(song[0])
if 48 <= code <= 57:
current_type = 0
elif (65 <= code <= 90) or (97 <= code <= 122):
current_type = 1
else:
current_type = 2
if current_type < prev_type:
is_valid = False
print(f'❌ 错误: "{song}" (类型 {current_type}) 出现在类型 {prev_type} 之后')
prev_type = current_type
if is_valid:
print('✅ 排序规则验证通过!')
print(' - 数字优先')
print(' - 字母次之')
print(' - 其他符号最后')
else:
print('❌ 排序规则验证失败!')
print('\n' + '=' * 60)
print('🎵 测试完成!')
print('=' * 60 + '\n')
if __name__ == '__main__':
main()