diff --git a/repo/js/AutoHoeingOneDragon/README.md b/repo/js/AutoHoeingOneDragon/README.md index a4ffc0630..bca22ce7a 100644 --- a/repo/js/AutoHoeingOneDragon/README.md +++ b/repo/js/AutoHoeingOneDragon/README.md @@ -24,7 +24,7 @@ ### 一、**快速使用指南 ✅** 1. 添加脚本 -在 BGI 配置组中点击 +添加 → 选择 “锄地一条龙”脚本。不要直接运行js。 +在 BGI 配置组中点击 +添加 → 选择 “锄地一条龙”脚本。不要直接在调度器外运行。 2. 配置组设置(⚙️) - ⚠️ 关键设置,请务必检查! @@ -160,8 +160,7 @@ - - 环境伤害 :路线处于雪山或挪德卡莱苦壑崖区域,环境伤害会持续扣血 - - 分组逻辑:不含路径组1排除标签和任何其他组标签的路径会进入路径组1,剩余路径若含有路径组x的标签之一,则会进入路径组x - - 新增支持自定义标签,将会尝试将未知的标签通过文件路径,description匹配,含有对应关键词的路线即视为含有这些标签 - - **路线效率计算权重:** 影响js评估路线价值,计算公式如下,权重越大越看重总收益 - - $$ 怪均^k \times 秒均 $$ + - **摩拉/耗时权衡因数:** 影响js评估路线价值,含义为为了多赚1摩拉愿意多花多少秒 - **自动优化:** js将根据运行记录调整每条路线的预期运行时间,具体逻辑为,至多7条记录,去除一个最大值、一个最小值后,每条记录占据20%的权重,剩余权重由默认数据填充。如果你不想要这个功能,请禁用。 - **目标数量:** 选取路线目标达到的精英怪数量,默认为400,同理小怪数量默认为2000 - **优先关键词:** 含有关键词的路线会被视为拥有最高效率,例如填写600来让所有600怪物优先考虑,填写骗骗花来优先考虑骗骗花 diff --git a/repo/js/AutoHoeingOneDragon/assets/搜索成功点击.png b/repo/js/AutoHoeingOneDragon/assets/搜索成功点击.png new file mode 100644 index 000000000..89ba2bc86 Binary files /dev/null and b/repo/js/AutoHoeingOneDragon/assets/搜索成功点击.png differ diff --git a/repo/js/AutoHoeingOneDragon/main.js b/repo/js/AutoHoeingOneDragon/main.js index 13dacd8d2..71f8f10f3 100644 --- a/repo/js/AutoHoeingOneDragon/main.js +++ b/repo/js/AutoHoeingOneDragon/main.js @@ -1,4 +1,4 @@ -//当前js版本2.2.1 +//当前js版本2.5.0 //自定义配置变量预声明 let accountName; @@ -14,8 +14,7 @@ let timeMoveDown; let priorityTags; let excludeTags; let operationMode; -let k1; -let k2; +let efficiencyIndex; let targetEliteNum; let targetMonsterNum; let partyName; @@ -88,7 +87,7 @@ let currentFood = ""; //按照用户配置标记路线 await markPathings(pathings, groupTags, priorityTags, excludeTags); //找出最优组合 - await findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonsterNum); + await findBestRouteGroups(pathings, efficiencyIndex, targetEliteNum, targetMonsterNum); //分配到不同路径组 await assignGroups(pathings, groupTags); @@ -145,8 +144,7 @@ async function loadConfig() { tagsForGroup9: settings.tagsForGroup9 || '', tagsForGroup10: settings.tagsForGroup10 || '', disableSelfOptimization: settings.disableSelfOptimization ?? false, - eEfficiencyIndex: settings.eEfficiencyIndex ?? 2.5, - mEfficiencyIndex: settings.mEfficiencyIndex ?? 0.5, + efficiencyIndex: settings.efficiencyIndex ?? 2.5, curiosityFactor: settings.curiosityFactor ?? '0', ignoreRate: settings.ignoreRate ?? 0, targetEliteNum: settings.targetEliteNum ?? 400, @@ -209,11 +207,11 @@ async function loadConfig() { log.warn("拾取模式不是模板匹配,无法处理沙暴路线,自动排除所有沙暴路线"); } - k1 = +settings.eEfficiencyIndex || 2.5; - k1 = Math.max(0, Math.min(10, Number.isNaN(k1) ? 2.5 : k1)); - - k2 = +settings.mEfficiencyIndex || 0.5; - k2 = Math.max(0, Math.min(4, Number.isNaN(k2) ? 0.5 : k2)); + efficiencyIndex = settings.efficiencyIndex === undefined ? 0.25 : + isNaN(Number(settings.efficiencyIndex)) || + String(Number(settings.efficiencyIndex)) !== String(settings.efficiencyIndex) ? 0.25 : + Number(settings.efficiencyIndex) < 0 ? 0 : + Number(settings.efficiencyIndex); targetEliteNum = Math.max(0, +settings.targetEliteNum || 400) + 5; // 预留漏怪 targetMonsterNum = Math.max(0, +(settings.targetMonsterNum ?? 2000)) + 25; // 预留漏怪 @@ -483,7 +481,7 @@ async function markPathings(pathings, groupTags, priorityTags, excludeTags) { * 返回:pathings[] 各元素新增 selected(bool)及排序 * 依赖:pathings(已含 mora_e/mora_m/t/e/available/prioritized) */ -async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonsterNum) { +async function findBestRouteGroups(pathings, efficiencyIndex, targetEliteNum, targetMonsterNum) { log.info("开始根据配置寻找路线组合"); /* ========== 0. 原初始化不动 ========== */ let nextTargetEliteNum = targetEliteNum; @@ -495,30 +493,41 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst let totalTimeCombined = 0; let monsterRouteElite = 0; - let maxE1 = 0, maxE2 = 0; - const ratio = targetEliteNum / Math.max(targetMonsterNum, 1); // 防 0 - const f = (Number((1 - Math.exp(-ratio * ratio)).toFixed(3)) + 1) / 2; + let maxE1 = -Infinity, maxE2 = -Infinity; + let minE1 = Infinity, minE2 = Infinity; pathings.forEach(p => { p.selected = false; - const G1 = p.mora_e + p.mora_m, G2 = p.mora_m; - p.G1 = G1; p.G2 = G2; - /* 收益 */ - const eliteGain = p.e === 0 ? 200 : (G1 - G2) / p.e; - const normalGain = p.m === 0 ? 40.5 : G2 / p.m; + if (p.e !== 0) { + p.E1 = (efficiencyIndex * p.mora_e - p.t) / p.e; + } else { + p.E1 = null; + } - p.E1 = (eliteGain ** k1) * (G1 / p.t); - if (p.e === 0) p.E1 = 0; + if (p.m !== 0) { + p.E2 = (efficiencyIndex * p.mora_m - p.t) / p.m; + } else { + p.E2 = null; + } - p.E2 = (normalGain ** k2) * (G2 / p.t); - - maxE1 = Math.max(maxE1, p.E1); - maxE2 = Math.max(maxE2, p.E2); + if (p.e !== 0) maxE1 = Math.max(maxE1, p.E1); + if (p.m !== 0) maxE2 = Math.max(maxE2, p.E2); + if (p.e !== 0) minE1 = Math.min(minE1, p.E1 ?? Infinity); + if (p.m !== 0) minE2 = Math.min(minE2, p.E2 ?? Infinity); }); pathings.forEach(p => { - if (p.prioritized) { p.E1 += maxE1; p.E2 += maxE2; } + if (p.e === 0) { + p.E1 = minE1 - 1; + } + if (p.m === 0) { + p.E2 = minE2 - 1; + } + if (p.prioritized) { + p.E1 += (maxE1 - minE1 + 2); + p.E2 += (maxE2 - minE2 + 2); + } }); /* ========== 1. 原两轮选择逻辑照搬,只是去掉“提前 break” ========== */ @@ -529,12 +538,12 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst pathings.sort((a, b) => b.E1 - a.E1); for (const p of pathings) { - if (p.E1 > 0 && p.available && + if (p.e > 0 && p.available && (totalSelectedElites + p.e <= targetEliteNum + 2)) { // 留一点余量 p.selected = true; totalSelectedElites += p.e; totalSelectedMonsters += p.m; - totalGainCombined += p.G1; + totalGainCombined += p.mora_e + p.mora_m; totalTimeCombined += p.t; } } @@ -544,12 +553,12 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst monsterRouteElite = 0; pathings.sort((a, b) => b.E2 - a.E2); for (const p of pathings) { - if (p.E2 > 0 && p.available && !p.selected && + if (p.m > 0 && p.available && !p.selected && (totalSelectedMonsters + p.m < targetMonsterNum + 5)) { p.selected = true; totalSelectedElites += p.e; monsterRouteElite += p.e; totalSelectedMonsters += p.m; - totalGainCombined += p.G2; + totalGainCombined += p.mora_m; totalTimeCombined += p.t; } } @@ -576,22 +585,14 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst } /* ========== 3. 最小不可再减集合(贪心逆筛,不碰优先路线) ========== */ - // 1. 只留非优先的已选路线,按性价比升序排 + // 1. 只留非优先的已选路线,按E1升序、E2升序排(差的先删) const selectedList = pathings .filter(p => p.selected && !p.prioritized && !p.tags.includes('精英高收益') ) - .sort((a, b) => { - const score = p => { - const eliteGain = p.e === 0 ? 200 : (p.G1 - p.G2) / p.e; - const normalGain = p.m === 0 ? 40.5 : p.G2 / p.m; - const perSec = p.t === 0 ? 0 : p.G1 / p.t; - return ((eliteGain / 200) ** k1 + (normalGain / 40.5) ** k2) * perSec; - }; - return score(a) - score(b); // 升序:差的先删 - }); + .sort((a, b) => a.E1 - b.E1 || a.E2 - b.E2); // 2. 试删 for (const p of selectedList) { @@ -602,7 +603,7 @@ async function findBestRouteGroups(pathings, k1, k2, targetEliteNum, targetMonst p.selected = false; totalSelectedElites = newE; totalSelectedMonsters = newM; - totalGainCombined -= p.G1; + totalGainCombined -= p.mora_e + p.mora_m; totalTimeCombined -= p.t; } } @@ -802,7 +803,7 @@ async function validateTeamAndConfig() { /** * 调试-分组汇总打印 - * 仅统计 group=1..10 且 selected 的路线,累加精英数、小怪数、总收益(G1)与总时长 + * 仅统计 group=1..10 且 selected 的路线,累加精英数、小怪数、总收益与总时长 * 输出每组的路线条数、精英/小怪数量、预计收益(摩拉)与预计用时(时:分:秒) * 用于“调试路线分配”模式快速核对各组工作量 * 将汇总结果写入 调试结果/路线分配结果.txt 文件 @@ -833,7 +834,7 @@ async function printGroupSummary() { for (const p of groupPath) { elites += p.e || 0; monsters += p.m || 0; - gain += p.G1 || 0; + gain += p.mora_e + p.mora_m || 0; time += p.t || 0; ignoredElites += (p.original_e || 0) - (p.e || 0); } @@ -896,8 +897,7 @@ async function printGroupSummary() { // 其他配置信息 resultText += "配置参数:\n"; - resultText += ` 精英效率指数: ${settings.eEfficiencyIndex || 2.5}\n`; - resultText += ` 小怪效率指数: ${settings.mEfficiencyIndex || 0.5}\n`; + resultText += ` 摩拉/耗时权衡因数: ${settings.efficiencyIndex || 2.5}\n`; resultText += ` 好奇系数: ${settings.curiosityFactor || 0}\n`; resultText += ` 忽略比例: ${settings.ignoreRate || 0}\n`; resultText += ` 目标精英数: ${settings.targetEliteNum || 400}\n`; @@ -1616,7 +1616,7 @@ async function processPathingsByGroup(pathings, accountName) { if (pathing.group === targetGroup) { totalElites += pathing.e || 0; // 精英怪数量 totalMonsters += pathing.m || 0; // 小怪数量 - totalGain += pathing.G1 || 0; // 收益 + totalGain += pathing.mora_e + pathing.mora_m || 0; // 收益 totalEstimatedTime += pathing.t || 0; // 预计时间 } } @@ -1638,13 +1638,7 @@ async function processPathingsByGroup(pathings, accountName) { const groupStartTime = new Date(); let remainingEstimatedTime = totalEstimatedTime; let skippedTime = 0; - //移除不必要的属性 - { - const keysToDelete = ['monsterInfo', 'mora_m', 'mora_e', 'available', 'prioritized', 'G1', 'G2', 'index', 'folderPathArray', 'E1', 'E2']; // 删除的字段列表 - pathings.forEach(p => { - keysToDelete.forEach(k => delete p[k]); - }); - } + // 遍历 pathings 数组 for (const pathing of pathings) { // 检查路径是否属于指定的组 diff --git a/repo/js/AutoHoeingOneDragon/manifest.json b/repo/js/AutoHoeingOneDragon/manifest.json index 81801c78b..78ffa00b8 100644 --- a/repo/js/AutoHoeingOneDragon/manifest.json +++ b/repo/js/AutoHoeingOneDragon/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "锄地一条龙", - "version": "2.4.0", + "version": "2.5.0", "description": "一站式解决自动化锄地,支持只拾取狗粮,请仔细阅读README.md后使用", "authors": [ { diff --git a/repo/js/AutoHoeingOneDragon/settings.json b/repo/js/AutoHoeingOneDragon/settings.json index eaa71391d..f34353c8a 100644 --- a/repo/js/AutoHoeingOneDragon/settings.json +++ b/repo/js/AutoHoeingOneDragon/settings.json @@ -149,16 +149,10 @@ "label": "勾选后禁用根据运行记录优化路线选择的功能\n完全使用路线原有信息\n【注意】启用该选项将导致无法根据个人运行清空自动优化路线选择" }, { - "name": "eEfficiencyIndex", + "name": "efficiencyIndex", "type": "input-text", - "label": "精英计算权重,填0以上的数字\n越大越倾向于花费较多时间提高总收益", - "default": "2.5" - }, - { - "name": "mEfficiencyIndex", - "type": "input-text", - "label": "小怪计算权重,填0以上的数字\n越大越倾向于花费较多时间提高总收益", - "default": "0.5" + "label": "摩拉/耗时权衡因数,填0及以上的数字\n越大越倾向于花费较多时间提高总收益\n含义为愿意为1摩拉多花多少秒", + "default": "0.25" }, { "name": "curiosityFactor",