mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-16 03:33:25 +08:00
js:锄地一条龙2.5.0 (#2934)
* Create 搜索成功点击.png 补充模板图片 * 微调路线选择算法 修改后只有一个参数,且对结果影响更加平滑可控
This commit is contained in:
@@ -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怪物优先考虑,填写骗骗花来优先考虑骗骗花
|
||||
|
||||
BIN
repo/js/AutoHoeingOneDragon/assets/搜索成功点击.png
Normal file
BIN
repo/js/AutoHoeingOneDragon/assets/搜索成功点击.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -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) {
|
||||
// 检查路径是否属于指定的组
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "锄地一条龙",
|
||||
"version": "2.4.0",
|
||||
"version": "2.5.0",
|
||||
"description": "一站式解决自动化锄地,支持只拾取狗粮,请仔细阅读README.md后使用",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user