打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

用户:RedDragon/Test:修订间差异

来自Rizline中文维基
RedDragon
RedDragon留言 | 贡献 (修复匹配问题,增加关联字符库)
第18行: 第18行:
             <div id="custom-filter-container">
             <div id="custom-filter-container">
                 <label for="score-filter" style="margin-right: 0.5rem;">筛选匹配度 ≥</label>
                 <label for="score-filter" style="margin-right: 0.5rem;">筛选匹配度 ≥</label>
                 <input type="number" id="score-filter" value="3" min="1" max="100"
                 <input type="number" id="score-filter" value="4" min="1" max="100"
                     style="width: 4rem; padding: 0.3rem;">
                     style="width: 4rem; padding: 0.3rem;">
             </div>
             </div>
第48行: 第48行:


         document.getElementById('alias-btn').addEventListener('click', searchSongs)
         document.getElementById('alias-btn').addEventListener('click', searchSongs)
         document.getElementById('alias-input').addEventListener('keypress', function (e) {
         document.getElementById('alias-input').addEventListener('keypress', function (e) {
             if (e.key == 'Enter') searchSongs()
             if (e.key == 'Enter') searchSongs()
第139行: 第140行:


         if (!input || !target) return { score: 0, matched: "" }
         if (!input || !target) return { score: 0, matched: "" }
         const originalInput = input
         const originalInput = input
         const originalTarget = target
         const originalTarget = target
         input = input.toLowerCase()
         input = input.toLowerCase()
         target = target.toLowerCase()
         target = target.toLowerCase()
第171行: 第174行:
         function calculateScore(src, tgt, originalSrc, originalTgt) {
         function calculateScore(src, tgt, originalSrc, originalTgt) {
             let score = 0, matched = "", lastPos = -1, bonus = 0, pos = 0, caseBonus = 0
             let score = 0, matched = "", lastPos = -1, bonus = 0, pos = 0, caseBonus = 0
            let skipCount = 0
            const maxSkip = 2
             for (let i = 0; i < src.length; i++) {
             for (let i = 0; i < src.length; i++) {
                 let found = false
                 let found = false
                const srcChar = src[i]
                const associatedChars = getAssociatedChars(srcChar)
                 for (let j = pos; j < tgt.length; j++) {
                 for (let j = pos; j < tgt.length; j++) {
                     if (src[i] == tgt[j]) {
                     const tgtChar = tgt[j]
 
                    if (srcChar === tgtChar || associatedChars.includes(tgtChar)) {
                         score++
                         score++
                         matched += originalTgt[j]
                         matched += originalTgt[j]
第180行: 第191行:
                         if (originalSrc[i] == originalTgt[j]) {
                         if (originalSrc[i] == originalTgt[j]) {
                             caseBonus += 0.3
                             caseBonus += 0.3
                        }
                        else if (associatedChars.includes(tgtChar)) {
                            caseBonus += 0.1  // 关联匹配加分较少
                         }
                         }


第193行: 第208行:
                     }
                     }
                 }
                 }
                 if (!found) break
 
                 if (!found) {
                    skipCount++
                    if (skipCount > maxSkip) {
                        break
                    }
                }
             }
             }


第202行: 第223行:
                 }
                 }
             }
             }
             return {
             return {
                 score: score + bonus + caseBonus + startBonus + containBonus,
                 score: score + bonus + caseBonus + startBonus + containBonus,
第237行: 第259行:


         } else {
         } else {
             const resc = Number(document.getElementById('score-filter').value) || 3
             const resc = Number(document.getElementById('score-filter').value) || 4
 
             results = songlist.map(function (song) {
             results = songlist.map(function (song) {
                 let best = getMatchScore(searchText, song.title || '')
                 let best = getMatchScore(searchText, song.title || '')
                 let bestAlias = ""
                 let bestAlias = ""
                 if (song.aliases) {
                 if (song.aliases) {
                     if (song.aliases.length > 0) {
                     if (song.aliases.length > 0) {
第252行: 第276行:
                     }
                     }
                 }
                 }
                 return {
                 return {
                     song: song,
                     song: song,
第288行: 第313行:
     }
     }


    function getAssociatedChars(char) {
        const associations = new Set([char])
        if (charAssociations[char]) {
            charAssociations[char].forEach(assocChar => associations.add(assocChar))
        }
        for (const [key, values] of Object.entries(charAssociations)) {
            if (values.includes(char)) {
                associations.add(key)
            }
        }
        return Array.from(associations)
    }
    // 关联字符库,冒号前的字符可通过中括号里的字符匹配
    const charAssociations = {
        'ィ': ['イ', '亻', 'ィ'],
        'イ': ['ィ', '亻', 'イ'],
        'ェ': ['エ', '工', 'ェ'],
        'エ': ['ェ', '工', 'エ'],
        '的': ['得', '地'],
        '得': ['的', '地'],
        '地': ['的', '得'],
        'Α': ['α', 'A', 'a', 'alpha'],
        'α': ['Α', 'a', 'A', 'alpha'],
        'alpha': ['Α', 'α', 'A', 'a'],
    }
    // 别名库
     const songlist = [
     const songlist = [
         {
         {

2025年9月15日 (一) 19:30的版本

搜索结果:

别名列表: