From 3c3ab47233de0ab5b9d33a1ede2541fa8e27f881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E5=90=89=E5=96=B5?= Date: Mon, 20 Oct 2025 13:05:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9A=E6=97=B6=E7=BB=88?= =?UTF-8?q?=E6=AD=A2=EF=BC=8C=E4=BF=AE=E5=A4=8Dbug=EF=BC=8C=E5=AF=B9=20?= =?UTF-8?q?=E4=B8=8D=E8=A7=84=E8=8C=83=E5=91=BD=E5=90=8D=E7=9A=84=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E6=96=87=E4=BB=B6=E5=A4=B9=20=E9=80=82=E9=85=8D=20(#2?= =?UTF-8?q?188)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add files via upload * Add files via upload * Add files via upload * Add files via upload * Update 怪物.txt --- repo/js/背包材料统计/README.md | 29 +- repo/js/背包材料统计/assets/Pic/Pic14.png | Bin 0 -> 4119 bytes repo/js/背包材料统计/assets/Pic/Pic15.png | Bin 0 -> 4258 bytes repo/js/背包材料统计/assets/Pic/Pic16.png | Bin 0 -> 5293 bytes repo/js/背包材料统计/assets/Scroll.png | Bin 0 -> 1094 bytes repo/js/背包材料统计/assets/滚轮下翻.json | 6 +- repo/js/背包材料统计/lib/autoPick.js | 43 +- repo/js/背包材料统计/main.js | 510 ++++++++++++++++------ repo/js/背包材料统计/manifest.json | 2 +- repo/js/背包材料统计/materialsCD/怪物.txt | 3 +- repo/js/背包材料统计/settings.json | 7 +- 11 files changed, 445 insertions(+), 155 deletions(-) create mode 100644 repo/js/背包材料统计/assets/Pic/Pic14.png create mode 100644 repo/js/背包材料统计/assets/Pic/Pic15.png create mode 100644 repo/js/背包材料统计/assets/Pic/Pic16.png create mode 100644 repo/js/背包材料统计/assets/Scroll.png diff --git a/repo/js/背包材料统计/README.md b/repo/js/背包材料统计/README.md index aca28e379..84fc2575d 100644 --- a/repo/js/背包材料统计/README.md +++ b/repo/js/背包材料统计/README.md @@ -1,4 +1,4 @@ -# 背包材料统计 v2.52 +# 背包材料统计 v2.54 作者:吉吉喵 @@ -118,9 +118,10 @@ | 6. 仅 pathing 材料 | 仅扫描 `pathing` 文件夹内的材料,跳过其他分类,大幅缩短扫描时间 | 路径配置完成后开启,提升脚本运行效率 | | 7. 弹窗名 | 不填则默认循环执行 `assets\imageClick` 文件夹下所有弹窗;填写则仅执行指定弹窗 | 推荐默认,需单独适配某类弹窗时填写(例:月卡,复苏) | | 8. 采用的 CD 分类 | 不填则默认执行 `materialsCD` 文件夹内配置的CD分类;填写则仅执行指定CD分类 | 新增材料时,需在该文件夹同步配置CD规则(操作见「四、问题解答Q2」) | -| 9. 采用的识别名单 | 不填则默认执行 `targetText` 文件夹内配置的识别名单;填写则仅执行指定识别名单 | 新增名单时,需符合配置规则(操作见「四、问题解答Q4」) | -| 10. 超量阈值 | 首次扫描后,超量的路径材料,将从识别名单中剔除,默认5000 | 不推荐9999,怪物材料有几千就够了,采用默认数值,可自动避免爆背包 | -| 11. 拖动距离 | 解决非1080p分辨率下“划页过头”问题,需调整到“一次划页≤4行” | 拖动点建议选“第五行材料附近”;大于1080p屏可适当减小数值 | +| 9. 终止时刻 | 不填则不执行定时终止;路径无时间记录时,会预判路径耗时5分钟,且预留2分钟空闲 | 填写需要按24小时格式(例:4:10) | +| 10. 采用的识别名单 | 不填则默认执行 `targetText` 文件夹内配置的识别名单;填写则仅执行指定识别名单 | 新增名单时,需符合配置规则(操作见「四、问题解答Q4」) | +| 11. 超量阈值 | 首次扫描后,超量的路径材料,将从识别名单中剔除,默认5000 | 不推荐9999,怪物材料有几千就够了,采用默认数值,可自动避免爆背包 | +| 12. 拖动距离 | 解决非1080p分辨率下“划页过头”问题,需调整到“一次划页≤4行” | 拖动点建议选“第五行材料附近”;大于1080p屏可适当减小数值 | ## 四、注意事项 @@ -129,7 +130,7 @@ 3. **食物识别强制要求**:背包食物界面**第一行必须包含8种食物**(苹果、日落果、星蕈、活化的星蕈、枯焦的星蕈、泡泡桔、烛伞蘑菇、美味的宝石闪闪),缺少则这些食物无法识别; 4. **关键文件备份**:建议不定期备份 `pathing` 文件夹(路径文件)和 `pathing_record` 文件夹(路径运行记录),便于丢失后或记录被污染后恢复如初; 5. **OCR配置**:默认最新,调整识别名单时,用的是V5Auto; -6. **手动终止运行**:如果要终止JS运行,推荐在当前路径采集前,或者采集完进入背包扫描时终止,以保护当前记录;如果是【取消扫描】模式,不会储存当前记录的材料数目,就随意。 +6. **手动终止运行**:如果要终止JS运行,推荐在当前路径采集到当前材料前,或者采集完进入背包扫描时终止(会在扫描结束后终止),以保护当前记录;如果是【取消扫描】模式,不会储存当前记录的材料数目,就随意。 ## 五、问题解答 @@ -149,9 +150,18 @@ A:1. 打开 `materialsCD` 文件夹(脚本路径:`BetterGI\User\JsScript\ 添加新材料操作截图2 -### Q3:如何识别不规范命名的路径文件夹(如“纳塔食材一条龙”“果园.json”)? -A:将不规范的文件夹/文件,放入**适配的材料文件夹**中即可(路径CD由“所在材料文件夹”决定)。 - 例:“果园.json”放入“苹果”文件夹,将按“苹果”的CD规则执行。 +### Q3:如何识别不规范命名的路径文件夹(如“纳塔食材一条龙”、“果园.json”)? +A:1. 将不规范的文件夹/文件,放入**适配的材料文件夹**中即可(路径CD由“所在材料文件夹”决定)。 + 2. 例:看「四、问题解答Q2」,① 把“纳塔食材一条龙”作为标准名,选择一个CD,② 在「JS 自定义设置」【优先级材料】里填入:纳塔食材一条龙,③将“纳塔食材一条龙”的文件夹放置到`pathing` 文件夹;锄地路径可放置到“锄地”文件夹里(没有就新建一个)**此方法无法使用 背包材料统计 的优选路径功能!** + 3. 「JS 自定义设置」勾选【取消扫描】后,就可以运行了!**此项不勾,将无CD记录!**; + 4. 例:“果园.json”放入“苹果”文件夹,将按“苹果”的CD规则执行。 + 操作参考截图: +
+ 添加新路径文件夹操作截图1 + 添加新路径文件夹操作截图2 + 添加新路径文件夹操作截图2 +
+ ### Q4:如何自定义识别名单? A:1. 打开 `targetText` 文件夹(脚本路径:`BetterGI\User\JsScript\背包材料统计\targetText`); @@ -213,4 +223,5 @@ A:记录文件夹位于 `BetterGI\User\JsScript\背包材料统计\` 下,各 | v2.42 | 新增“无路径间扫描”“noRecord模式”(适合成熟路径);新增怪物材料CD文件 | | v2.50 | 新增独立名单拾取、弹窗模块;支持怪物名识别 | | v2.51 | 自定义设置新增“拖动距离/拖动点”;新增月卡弹窗识别;路径材料超量自动上黑名单;修复怪物0收获记录 | -| v2.52 | 自定义设置新增“超量阈值”和“识别名单”输入框;新增多层弹窗逻辑 | \ No newline at end of file +| v2.52 | 自定义设置新增“超量阈值”和“识别名单”输入框;新增多层弹窗逻辑 | +| v2.54 | 自定义设置新增“终止时刻”,修复bug,新增“添加不规范命名的路径文件夹”说明,新增一个“锄地”的怪物路径CD | \ No newline at end of file diff --git a/repo/js/背包材料统计/assets/Pic/Pic14.png b/repo/js/背包材料统计/assets/Pic/Pic14.png new file mode 100644 index 0000000000000000000000000000000000000000..84be9f70afec221da3248921c8f11c56e60ba255 GIT binary patch literal 4119 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 UP!3ij{^KZ~S!FHkl0OV literal 0 HcmV?d00001 diff --git a/repo/js/背包材料统计/assets/Pic/Pic15.png b/repo/js/背包材料统计/assets/Pic/Pic15.png new file mode 100644 index 0000000000000000000000000000000000000000..a0ff74ac7e76a0a66a7f78198f2e752a3f78bf38 GIT binary patch literal 4258 zcmZ9Qc|26@-^Y=Vy&`)=rR)(I49U(-y6t2vVKBDrL#R}D|cSVuFH ztsz_XEJIAl{u}r6yk5W8^ZfBW*LALQopY{puIu~xyw8D~n;CGh3bNAC(Qz0V>i$hD zH)-*dg^9KW3ja=^6&C^w?Skm&IJ?e*K3$qqh>nii(nwd^GCY@(=j6jr#^FmOD)UG&Bq7V*SqCgN3KAKEqkHjuHe?^BqX?@ig?#ojwwwOLLm9{)#ox(Rp% zzQqdDf+9v(Sztfd?|`&_-F8L8epqycpU0NHrX70-_4aiZiD_8yS2(cYez`sWS*rvb zUR%mg6f-p>WES}manD@-aoYN=rd$k`E%)oOiJK_nO_e;`c@d`wZBRWr{B) z6GeG&R9O4osvu%Zx4pHZsxTYs{#{m58n@nVQ8ci`!5Ew0$DOZ{umojuDfX^sH}mRR zjmhJ$7fWL!E~BlMe{z(KJ6Kspg$z>DjO$3FD-pOA4V<+mO3H~l0j@+kTz?eZUYO0C z^85Unz>7=r$=d!Oe7YT^h7rJ!-S3v<6~@{pB9GgdN1C>yFXtBK#jdDurra7DZQ4HR zzxp5@aRm2c5XlV6tUNZFE1cAE#d69a>&!)ODF2T0I)3>I9t+s?&K5cm*l653EQ_~$ zA~so$bx3BNxDz0&VgH zV#?qwfd|0i_c`!aWv`b7++P0)NZX=XJ^L__DRw2l&Pv|JWh;%BgmlyUaktRGAY4AA zOjj!N8l1i-=le2r*nB};RDWcH7a^YGmG>dgg1`1x^^3Q0@7Nw*+STwM1#nhoFEr_# z+6Qz`GNz`1Q2g4ZpZhOZTQ3VCuE4RVB=Xe&>#v5)FD`!6G@i_2bfI^F5ZmUmygz1> zab6&jakwS{VZ{QZFz)^Wz-I+%cHz8B7K@7E*_W`pLg8Fs;bPYtl=DD?<`!UVx^*o}ShOH+(6 z+5#cpla?sARWs&>tj$jw8Z1SFs>L+mG6%gP)j*X3YP6r-$BZxw=C^62#D;xs>DTVo zRfBz>X~1qN%4*O{;F5$%{;k)$gK`7)Ni%^V;U-*7;4SEo(cx z)Q!~$+saH(>#J>0{a3`qgJ>sW`!X-9F?e3qETu~R_4;tp8rw~$+vJKt!20C zh9{QOHW^Wr)U`MGsaE$?NkyOIsOiA_$1t|hJ`;G>3om8GlEGV4_v#%%MCRth%BIW5 zqbn7w%f&iF5f7~w)s$O(rYjv(S~6x$NXU&TLd0KMg3TH9Ldpsunw7u((0NwI$5n(R z+szixvd!uNzsm$w&T+c8akToEaOYmk50w0;q^L59D5z*2(&<_h7%1Tck*uAV_nKAd zu$uf9q4-v11cW1s zfUb#Hc+~eJF@xBxz<}|3aT(xzVn+SYg8dve?GemS?mO3Y^UrhOdftKLn-r;`QI)52 zm2xWOO{PgZbvu7XC*9}aYr)V;l0le$kU+;bameFO5wAhirnUtu${X$`c$DO8G-zqZPGK)Df)cmbT8ND`qFRm zo{NzP2Sn~`-O)VsDZPALtUahWcTiA(2bDJ_l1%t=#5cO2$R8EL zQx5FB*zF4*T)I&`ROcZYbKLMB{lZ+CPQyz%L=+)!zX;&#;&E}{jw@{ zqvta9WpT&oTl4~VWXz@h3b;4BNZ#BiLn{V7Jpybavhn?V{4964NvqV4BAcD*K16Z! zL7%MY#iuJvNw+oQ3DOhezV5-k$^`)4b=6@)N!T7LBv{ziXg+63*z0-Drk|@b!&no1 zA9{Ub@H0>SRMw=y@Ws%tgU}A># zcHGYrznoc)>S2DEn)bRabLJ-fP9=JV5$w6_+?tG&NC>9w#?-}|mmo%To90rybRaSB z!*A`qwXKOAK*)?37;#``_43ZUX#eP>n*A^4(CF@O9bhLTU19ip&ts`ixGXTvG~f@q z$ElHP=dJPXu)XMwbW1_G`)8DMka3c9} z$XAFy4|~bd$K^Bk}@{kZ=tdAqX#OTh$ zRc1=6Wevsn7Xn)0snp)CZ(b{zvvp$p&J$E?E3%>{z*j6Vl&G%pSMZ$FIYA4M>7}W4 zVatJZTA!aTGt{{6UhUtzbMs77UsJ?ORfh01P+*h$q*?0cgcVvWV zGhpTPArbI+v5Ra&Ve(2oME;=HyTl8e%x%kwhQZ(^)ZT%IJ0q`&!39^}s7axfzDd#= zFQYb{5ZKoJ-M@ZltBEtF0rZ1i6*kzzvnCp4Q)z&G@oeh;^~SVM(CO)b?;4K;@QwBv zydooBU#jwc&R&mdIaTRCiaLIY+Ju_YFnC1}ar-U)!S32LKX=JIcE}6P=vG8_ zn~h-0HXro?O~H@A)q_V|%ol);94XNTu09=J0^PqfS9_{d#8Ev6A~M6b+mo=Zx)aY0Kx0feH~j{V+mtO|mPi^tqnA{7xM1xk;f`(L#}Db-|?EW)>LEz;c|b)OR`*^I$VvBw6ot5f9sF# z?lP9Bg9xv-lx49?GL?KI;3t8|M2m{05R15t$ZX&f*($XsrfV9RXZe7$__#m93eSDf z8=s30Fw_1-i0(AP4Q}&9U?r3Q5k*|mI-W{XczX4RCs&SI6kFh4O)6&q%rlS6%4K} zh)V8RmfXik*_Jf*V~rWV%VK8hCAfZGXL8o_u;x?mG55w1R-Lb$zi00^j5%e@tMwpJ zt@Db)a5E&wdu12sxo96^`TBQN6Q_U4o}P$QB{{nI>tvG)n64hbnR&A)e|e>UaH7*W z?4;a=S#m#VyZOR>JFl^lE@SYgy~FZYZ+!id8_`xMi6X8L$Y-kuDcep`{wQnMs%50X z^9e(h@x}W6-JcJ*m{9U*0NXxEIUt78o>iNs=0gRdm2#J8pj($Xp7L`?qi=0WBQ&_S z^&-|#zUa^+kRpd18zggp(0sCX_KF3?7(!rNIt_jI|AqbB;%onhh5w%j{0|`iw{h{5 azH5y~?Vih93hk!@ospiIZq);4*na?EzK5Lv literal 0 HcmV?d00001 diff --git a/repo/js/背包材料统计/assets/Pic/Pic16.png b/repo/js/背包材料统计/assets/Pic/Pic16.png new file mode 100644 index 0000000000000000000000000000000000000000..5979aca2badba47a9ad89f603538660ac52feb00 GIT binary patch literal 5293 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 M07*qoM6N<$g384E=Kufz literal 0 HcmV?d00001 diff --git a/repo/js/背包材料统计/assets/滚轮下翻.json b/repo/js/背包材料统计/assets/滚轮下翻.json index 83995604b..6808800b8 100644 --- a/repo/js/背包材料统计/assets/滚轮下翻.json +++ b/repo/js/背包材料统计/assets/滚轮下翻.json @@ -1,3 +1,3 @@ -{"macroEvents":[{"type":6,"mouseX":0,"mouseY":-120,"time":0}, -{"type":6,"mouseX":0,"mouseY":0,"time":5}], -"info":{"name":"","description":"","x":0,"y":0,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file +{"macroEvents":[ +{"type":6,"mouseX":0,"mouseY":-120,"time":25} +],"info":{"name":"","description":"","x":0,"y":0,"width":1920,"height":1080,"recordDpi":1}} \ No newline at end of file diff --git a/repo/js/背包材料统计/lib/autoPick.js b/repo/js/背包材料统计/lib/autoPick.js index 941db67c4..73804d597 100644 --- a/repo/js/背包材料统计/lib/autoPick.js +++ b/repo/js/背包材料统计/lib/autoPick.js @@ -158,29 +158,42 @@ async function findFIcon(recognitionObject, timeout = 10, ra = null) { return { success: true, x: result.x, y: result.y, width: result.width, height: result.height }; } } catch (error) { - log.error(`识别图像时发生异常: ${error.message}`); + log.error(`识别图标异常: ${error.message}`); if (state.cancelRequested) { - break; // 如果请求了取消,则退出循环 + break; } return null; } await sleep(5); // 每次检测间隔 5 毫秒 } if (state.cancelRequested) { - log.info("图像识别任务已取消"); + log.info("图标识别任务已取消"); } return null; } -// 对齐并交互目标 -async function alignAndInteractTarget(targetTexts, fDialogueRo, textxRange, texttolerance, cachedFrame=null) { +// 定义Scroll.png识别对象(按需求使用TemplateMatch,包含指定范围) +const ScrollRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync("assets/Scroll.png"), + 1055, 521, 15, 35 // 识别范围:x=1055, y=521, width=15, height=35 +); + +/** + * 对齐并交互目标(直接用findFIcon识别Scroll.png) + * @param {string[]} targetTexts - 待匹配的目标文本列表 + * @param {Object} fDialogueRo - F图标的识别对象 + * @param {Object} textxRange - 文本识别的X轴范围 { min: number, max: number } + * @param {number} texttolerance - 文本与F图标Y轴对齐的容差 + * @param {Object} cachedFrame - 缓存的图像帧(可选) + */ +async function alignAndInteractTarget(targetTexts, fDialogueRo, textxRange, texttolerance, cachedFrame = null) { let lastLogTime = Date.now(); // 记录每个材料的识别次数(文本+坐标 → 计数) const recognitionCount = new Map(); while (!state.completed && !state.cancelRequested) { const currentTime = Date.now(); - if (currentTime - lastLogTime >= 10000) { // 每5秒记录一次日志 + if (currentTime - lastLogTime >= 10000) { log.info("检测中..."); lastLogTime = currentTime; } @@ -191,13 +204,15 @@ async function alignAndInteractTarget(targetTexts, fDialogueRo, textxRange, text // 尝试找到 F 图标 let fRes = await findFIcon(fDialogueRo, 10, cachedFrame); if (!fRes) { - continue; + const scrollRes = await findFIcon(ScrollRo, 10, cachedFrame); // 复用findFIcon函数 + if (scrollRes) { + await keyMouseScript.runFile(`assets/滚轮下翻.json`); // 调用翻滚脚本 + } + continue; // 继续下一轮检测 } // 获取 F 图标的中心点 Y 坐标 let centerYF = fRes.y + fRes.height / 2; - - // 在当前屏幕范围内进行 OCR 识别 let ocrResults = await performOcr(targetTexts, textxRange, { min: fRes.y - 3, max: fRes.y + 37 }, 10, cachedFrame); // 检查所有目标文本是否在当前页面中 @@ -206,31 +221,25 @@ async function alignAndInteractTarget(targetTexts, fDialogueRo, textxRange, text let targetResult = ocrResults.find(res => res.text.includes(targetText)); if (targetResult) { - // 生成唯一标识并更新识别计数(文本+Y坐标) const materialId = `${targetText}-${targetResult.y}`; recognitionCount.set(materialId, (recognitionCount.get(materialId) || 0) + 1); let centerYTargetText = targetResult.y + targetResult.height / 2; if (Math.abs(centerYTargetText - centerYF) <= texttolerance) { - // log.info(`目标文本 '${targetText}' 和 F 图标水平对齐`); if (recognitionCount.get(materialId) >= 1) { - keyPress("F"); // 执行交互操作 + keyPress("F"); log.info(`交互或拾取: ${targetText}`); - - // F键后清除计数,确保单次交互 recognitionCount.delete(materialId); } foundTarget = true; - break; // 成功交互后退出当前循环,但继续检测 + break; } } } - // 如果在当前页面中没有找到任何目标文本,则滚动到下一页 if (!foundTarget) { await keyMouseScript.runFile(`assets/滚轮下翻.json`); - // verticalScroll(-20); } if (state.cancelRequested) { break; diff --git a/repo/js/背包材料统计/main.js b/repo/js/背包材料统计/main.js index 5d294ed94..713cebb84 100644 --- a/repo/js/背包材料统计/main.js +++ b/repo/js/背包材料统计/main.js @@ -51,6 +51,9 @@ var state = { completed: false, cancelRequested: false }; const timeCost = Math.min(300, Math.max(0, Math.floor(Number(settings.TimeCost) || 30))); const notify = settings.notify || false; const noRecord = settings.noRecord || false; +const targetCount = Math.min(9999, Math.max(0, Math.floor(Number(settings.TargetCount) || 5000))); // 设定的目标数量 +const exceedCount = Math.min(9999, Math.max(0, Math.floor(Number(settings.ExceedCount) || 5000))); // 设定的超量目标数量 +const endTimeStr = settings.CurrentTime ? settings.CurrentTime : null; // 解析需要处理的CD分类 const allowedCDCategories = (settings.CDCategories || "") @@ -326,6 +329,32 @@ function getCurrentTimeInHours() { return now.getHours() + now.getMinutes() / 60 + now.getSeconds() / 3600; } +/** + * 计算当前时间到指定终止时间的剩余分钟数(处理跨天,单向倒计时) + * @param {string} endTimeStr - 指定终止时间(格式"HH:mm",如"4:00") + * @returns {number} 剩余分钟数(负数表示已过终止时间),无效格式返回-1 + */ +function getRemainingMinutesToEndTime(endTimeStr) { + // 1. 解析终止时间 + const [endHours, endMinutes] = endTimeStr.split(/[::]/).map(Number); + if (isNaN(endHours) || isNaN(endMinutes) || endHours < 0 || endHours >= 24 || endMinutes < 0 || endMinutes >= 60) { + log.error(`${CONSTANTS.LOG_MODULES.MAIN}无效终止时间格式:${endTimeStr},需为"HH:mm"(如"14:30")`); + return -1; // 无效格式视为“已过时间” + } + + // 2. 转换为时间戳(当天终止时间 & 次日终止时间,处理跨天) + const now = new Date(); + const todayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), endHours, endMinutes); + const tomorrowEnd = new Date(todayEnd.getTime() + 24 * 60 * 60 * 1000); // 加1天 + + // 3. 确定有效终止时间(若当天已过,取次日) + const targetEndTime = now <= todayEnd ? todayEnd : tomorrowEnd; + + // 4. 计算剩余分钟数(毫秒转分钟,保留整数) + const remainingMs = targetEndTime - now; + return Math.floor(remainingMs / (1000 * 60)); +} + // ============================================== // 记录管理 // ============================================== @@ -403,9 +432,6 @@ function recordRunTime(resourceName, pathName, startTime, endTime, runTime, reco try { if (runTime >= 3) { // 运行时间≥3秒才处理记录 - // ============================================== - // 新增:怪物路径专用逻辑(判断对应材料总数量是否为0) - // ============================================== const isMonsterPath = monsterToMaterials.hasOwnProperty(resourceName); // 是否为怪物路径 if (isMonsterPath) { // 1. 获取当前怪物对应的所有目标材料(从已有映射中取) @@ -424,9 +450,6 @@ function recordRunTime(resourceName, pathName, startTime, endTime, runTime, reco } } - // ============================================== - // 原有:普通材料0记录逻辑(完全保留,不做修改) - // ============================================== for (const [material, count] of Object.entries(materialCountDifferences)) { if (material === resourceName && count === 0) { const zeroMaterialPath = `${recordDir}/${material}${CONSTANTS.ZERO_COUNT_SUFFIX}`; @@ -436,9 +459,6 @@ function recordRunTime(resourceName, pathName, startTime, endTime, runTime, reco } } - // ============================================== - // 原有:正常记录生成逻辑(完全保留,不做修改) - // ============================================== const hasZeroMaterial = Object.values(materialCountDifferences).includes(0); const isFinalCumulativeDistanceZero = finalCumulativeDistance === 0; @@ -504,102 +524,194 @@ function getLastRunEndTime(resourceName, pathName, recordDir, noRecordDir) { * @param {string} recordDir - 记录目录 * @returns {number|null} 时间成本(秒/中级单位),null=无法计算 */ -function calculatePerTime(resourceName, pathName, recordDir) { - const recordPath = `${recordDir}/${resourceName}.txt`; +function getHistoricalPathRecords(resourceKey, pathName, recordDir, noRecordDir, isFood = false, cache = {}) { + // 1. 生成唯一缓存键(确保不同路径/不同文件的记录不混淆) + const isFoodSuffix = isFood ? CONSTANTS.FOOD_EXP_RECORD_SUFFIX : ".txt"; + const recordFile = `${recordDir}/${resourceKey}${isFoodSuffix}`; + const cacheKey = `${recordFile}|${pathName}`; // 键格式:文件路径|路径名 + + // 2. 优先从缓存获取,命中则直接返回(不读文件) + if (cache[cacheKey]) { + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}从缓存复用记录:${cacheKey}`); + return cache[cacheKey]; + } + + // 3. 缓存未命中,才读取文件 + const records = []; + let targetFile = recordFile; + let content = ""; + + // 读主目录→读备用目录 try { - const content = file.readTextSync(recordPath); - const lines = content.split('\n'); - const completeRecords = []; + content = file.readTextSync(targetFile); + } catch (mainErr) { + targetFile = `${noRecordDir}/${resourceKey}${isFoodSuffix}`; + try { + content = file.readTextSync(targetFile); + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}从备用目录读取记录:${targetFile}`); + } catch (backupErr) { + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}无${resourceKey}的历史记录:${targetFile}`); + // 空记录也写入缓存,避免下次重复尝试读文件 + cache[cacheKey] = records; + return records; + } + } - // ============================================== - // 怪物路径:改为以中级材料为基准(最低级÷3) - // ============================================== - if (monsterToMaterials.hasOwnProperty(resourceName)) { - const monsterMaterials = monsterToMaterials[resourceName]; // 映射顺序:[最高级, 中级, 最低级] - // 新比例:最高级×3(1最高级=3中级),中级×1(本身),最低级×1/3(3最低级=1中级 → 最低级÷3) - const gradeRatios = [3, 1, 1/3]; + // 解析记录(按原有格式提取runTime和quantityChange) + const lines = content.split('\n'); + for (let i = 0; i < lines.length; i++) { + if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) { + const runTimeLine = lines[i + 3]; + const quantityChangeLine = lines[i + 4] || ""; + let runTime = 0; + let quantityChange = {}; - for (let i = 0; i < lines.length; i++) { - if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) { - const runTimeLine = lines[i + 3]; - const quantityChangeLine = lines[i + 4]; - - if (runTimeLine?.startsWith('运行时间: ') && quantityChangeLine?.startsWith('数量变化: ')) { - // 1. 提取运行时间 - const runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('秒')[0], 10); - if (isNaN(runTime) || runTime <= 0) continue; - - // 2. 提取数量变化 - const quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]); - - // 3. 按新比例计算“总中级单位数量”(最低级÷3) - let totalMiddleCount = 0; // 变量名改为中级单位 - monsterMaterials.forEach((mat, index) => { - const count = quantityChange[mat] || 0; - const ratio = gradeRatios[index] || 1; - totalMiddleCount += count * ratio; // 最低级此处等价于 count ÷ 3 - }); - // 保留两位小数(处理1/3导致的无限小数) - totalMiddleCount = parseFloat(totalMiddleCount.toFixed(2)); - - // 4. 过滤无效数据 - if (totalMiddleCount <= 0) continue; - - // 5. 计算时间成本(秒/中级单位) - const perTime = parseFloat((runTime / totalMiddleCount).toFixed(2)); - completeRecords.push(perTime); - // 日志更新为中级单位 - log.debug(`${CONSTANTS.LOG_MODULES.RECORD}怪物【${resourceName}】路径${pathName}:${runTime}秒/${totalMiddleCount}中级单位 → ${perTime}秒/单位`); - } + // 提取运行时间(秒) + if (runTimeLine?.startsWith('运行时间: ')) { + runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('秒')[0], 10) || 0; + } + // 提取数量变化(JSON格式) + if (quantityChangeLine.startsWith('数量变化: ')) { + try { + quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]) || {}; + } catch (e) { + log.warn(`${CONSTANTS.LOG_MODULES.RECORD}解析数量变化失败:${quantityChangeLine}`); } } - } - // ============================================== - // 普通材料:完全保留原有逻辑 - // ============================================== - else { - for (let i = 0; i < lines.length; i++) { - if (lines[i].startsWith('路径名: ') && lines[i].split('路径名: ')[1] === pathName) { - const runTimeLine = lines[i + 3]; - const quantityChangeLine = lines[i + 4]; - if (runTimeLine?.startsWith('运行时间: ') && quantityChangeLine?.startsWith('数量变化: ')) { - const runTime = parseInt(runTimeLine.split('运行时间: ')[1].split('秒')[0], 10); - const quantityChange = JSON.parse(quantityChangeLine.split('数量变化: ')[1]); - - if (quantityChange[resourceName] !== undefined && quantityChange[resourceName] !== 0) { - completeRecords.push(parseFloat((runTime / quantityChange[resourceName]).toFixed(2))); - } - } - } + if (runTime > 0) { + records.push({ runTime, quantityChange }); } } + } - // ============================================== - // 统一的异常值过滤和平均值计算(不变) - // ============================================== - if (completeRecords.length < 3) { - log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}有效记录不足3条,无法计算时间成本`); - return null; - } + // 4. 将读取到的记录写入缓存,供后续复用 + cache[cacheKey] = records; + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}读取记录并缓存:${cacheKey}(${records.length}条)`); + return records; +} - const recentRecords = completeRecords.slice(-5).filter(record => !isNaN(record) && record !== Infinity); - log.debug(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}最近记录: ${JSON.stringify(recentRecords)}`); +/** + * 基于历史runTime预估路径总耗时(默认5分钟) + * @param {Object} entry - 路径条目 + * @param {string} recordDir - 记录目录 + * @param {string} noRecordDir - 备用目录 + * @param {Object} cache - 缓存对象 + * @returns {number} 预估耗时(秒) + */ +function estimatePathTotalTime(entry, recordDir, noRecordDir, cache = {}) { + const { resourceName, monsterName, path: pathingFilePath } = entry; + const pathName = basename(pathingFilePath); + const isFood = resourceName && isFoodResource(resourceName); + let resourceKey = isFood ? resourceName : (monsterName || resourceName); - const mean = recentRecords.reduce((acc, val) => acc + val, 0) / recentRecords.length; - const stdDev = Math.sqrt(recentRecords.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / recentRecords.length); - const filteredRecords = recentRecords.filter(record => Math.abs(record - mean) <= 1 * stdDev); + // 无资源关联时,默认5分钟(300秒) + if (!resourceKey) { + log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}无资源关联,默认按300秒(5分钟)预估`); + return 300; + } + + // 调用公共函数获取记录(复用缓存) + const historicalRecords = getHistoricalPathRecords( + resourceKey, + pathName, + recordDir, + noRecordDir, + isFood, + cache + ); + + // 无记录时,默认5分钟(300秒) + if (historicalRecords.length === 0) { + log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}无有效runTime记录,默认按300秒(5分钟)预估`); + return 300; + } + + // 取最近5条记录计算平均值 + const recentRecords = [...historicalRecords].reverse().slice(0, 5); + const avgRunTime = Math.round( + recentRecords.reduce((sum, record) => sum + record.runTime, 0) / recentRecords.length + ); + + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}历史runTime(最近5条):${recentRecords.map(r => r.runTime)}秒,预估耗时:${avgRunTime}秒`); + return avgRunTime; +} + +/** + * 计算单次时间成本(秒/单位材料)(复用缓存) + * @param {string} resourceName - 资源名 + * @param {string} pathName - 路径名 + * @param {string} recordDir - 记录目录 + * @param {string} noRecordDir - 备用目录 + * @param {boolean} isFood - 是否为狗粮路径 + * @param {Object} cache - 缓存对象 + * @returns {number|null} 时间成本 + */ +function calculatePerTime(resourceName, pathName, recordDir, noRecordDir, isFood = false, cache = {}) { + const isMonster = monsterToMaterials.hasOwnProperty(resourceName); + // 调用公共函数获取记录(复用缓存) + const historicalRecords = getHistoricalPathRecords( + resourceName, + pathName, + recordDir, + noRecordDir, + isFood, + cache + ); + + // 有效记录不足3条,返回null + if (historicalRecords.length < 3) { + log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}有效记录不足3条,无法计算时间成本`); + return null; + } + + const completeRecords = []; + if (isMonster) { + // 怪物路径:按中级单位计算 + const monsterMaterials = monsterToMaterials[resourceName]; + const gradeRatios = [3, 1, 1/3]; // 最高级×3,中级×1,最低级×1/3 + + historicalRecords.forEach(record => { + const { runTime, quantityChange } = record; + let totalMiddleCount = 0; + + monsterMaterials.forEach((mat, index) => { + const count = quantityChange[mat] || 0; + totalMiddleCount += count * (gradeRatios[index] || 1); + }); + + totalMiddleCount = parseFloat(totalMiddleCount.toFixed(2)); + if (totalMiddleCount > 0) { + completeRecords.push(parseFloat((runTime / totalMiddleCount).toFixed(2))); + } + }); + } else { + // 普通材料路径:直接按材料数量计算 + historicalRecords.forEach(record => { + const { runTime, quantityChange } = record; + if (quantityChange[resourceName] !== undefined && quantityChange[resourceName] !== 0) { + completeRecords.push(parseFloat((runTime / quantityChange[resourceName]).toFixed(2))); + } + }); + } + + // 异常值过滤与平均值计算(原有逻辑不变) + if (completeRecords.length < 3) { + log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}有效效率记录不足3条,无法计算时间成本`); + return null; + } + + const recentRecords = completeRecords.slice(-5).filter(r => !isNaN(r) && r !== Infinity); + const mean = recentRecords.reduce((acc, val) => acc + val, 0) / recentRecords.length; + const stdDev = Math.sqrt(recentRecords.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / recentRecords.length); + const filteredRecords = recentRecords.filter(r => Math.abs(r - mean) <= 1 * stdDev); if (filteredRecords.length === 0) { log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}记录数据差异过大,无法计算有效时间成本`); return null; } - return parseFloat((filteredRecords.reduce((acc, val) => acc + val, 0) / filteredRecords.length).toFixed(2)); - } catch (error) { - log.warn(`${CONSTANTS.LOG_MODULES.RECORD}路径${pathName}无有效记录,无法计算时间成本`); - } - return null; + return parseFloat((filteredRecords.reduce((acc, val) => acc + val, 0) / filteredRecords.length).toFixed(2)); } // ============================================== @@ -708,7 +820,7 @@ function matchImageAndGetCategory(resourceName, imagesDir) { const result = imageMapCache.get(imagesDir)[processedName] ?? null; if (result) { - log.debug(`${CONSTANTS.LOG_MODULES.MATERIAL}资源${resourceName}匹配分类:${result}`); + // log.debug(`${CONSTANTS.LOG_MODULES.MATERIAL}资源${resourceName}匹配分类:${result}`); } else { log.debug(`${CONSTANTS.LOG_MODULES.MATERIAL}资源${resourceName}未匹配到分类`); } @@ -720,6 +832,54 @@ function matchImageAndGetCategory(resourceName, imagesDir) { return result; } +// ============================================== +// 特殊材料与超量判断(核心新增逻辑) +// ============================================== +const specialMaterials = [ + "水晶块", "魔晶块", "星银矿石", "紫晶块", "萃凝晶", "虹滴晶", "铁块", "白铁块", + "精锻用魔矿", "精锻用良矿", "精锻用杂矿" +]; + +let excessMaterialNames = []; // 超量材料名单 + +// 筛选低数量材料(保留原逻辑+修正超量判断) +function filterLowCountMaterials(pathingMaterialCounts, materialCategoryMap) { + // 超量阈值(普通材料9999,矿石处理后也是9999) + const EXCESS_THRESHOLD = exceedCount; + // 临时存储本次超量材料 + const tempExcess = []; + + // 提取所有需要扫描的材料(含怪物材料) + const allMaterials = Object.values(materialCategoryMap).flat(); + + const filteredMaterials = pathingMaterialCounts + .filter(item => + allMaterials.includes(item.name) && + (item.count < targetCount || item.count === "?") + ) + .map(item => { + // 矿石数量÷10 + let processedCount = item.count; + if (specialMaterials.includes(item.name) && item.count !== "?") { + processedCount = Math.floor(Number(item.count) / 10); + } + + // 判断是否超量(用处理后数量对比阈值) + if (item.count !== "?" && processedCount >= EXCESS_THRESHOLD) { + tempExcess.push(item.name); // 记录超量材料名 + } + + return { ...item, count: processedCount }; + }); + + tempExcess.push("OCR启动"); // 添加特殊标记,用于终止OCR等待 + // 更新全局超量名单(去重) + excessMaterialNames = [...new Set(tempExcess)]; + log.info(`【超量材料更新】共${excessMaterialNames.length}种:${excessMaterialNames.join("、")}`); + + return filteredMaterials; +} + // ============================================== // 路径处理(拆分巨型函数) // ============================================== @@ -785,8 +945,16 @@ async function processMonsterPathEntry(entry, context) { CDCategories, timeCost, recordDir, noRecordDir, imagesDir, materialCategoryMap, flattenedLowCountMaterials, currentMaterialName: prevMaterialName, - materialAccumulatedDifferences, globalAccumulatedDifferences + materialAccumulatedDifferences, globalAccumulatedDifferences, + pathRecordCache // 新增:从上下文取缓存 } = context; + const monsterMaterials = monsterToMaterials[monsterName] || []; + const allExcess = monsterMaterials.every(mat => excessMaterialNames.includes(mat)); + if (allExcess) { + log.warn(`${CONSTANTS.LOG_MODULES.MONSTER}怪物【${monsterName}】所有材料已超量,跳过路径:${pathName}`); + await sleep(1); + return context; + } // 用怪物名查CD let refreshCD = null; @@ -811,7 +979,14 @@ async function processMonsterPathEntry(entry, context) { const currentTime = getCurrentTimeInHours(); const lastEndTime = getLastRunEndTime(monsterName, pathName, recordDir, noRecordDir); const isPathValid = checkPathNameFrequency(monsterName, pathName, recordDir); - const perTime = noRecord ? null : calculatePerTime(monsterName, pathName, recordDir); + const perTime = noRecord ? null : calculatePerTime( + monsterName, + pathName, + recordDir, + noRecordDir, + false, + pathRecordCache // 新增:传递缓存 + ); log.info(`${CONSTANTS.LOG_MODULES.PATH}怪物路径${pathName} 单个材料耗时:${perTime ?? '忽略'}`); @@ -930,7 +1105,8 @@ async function processNormalPathEntry(entry, context) { CDCategories, timeCost, recordDir, noRecordDir, materialCategoryMap, flattenedLowCountMaterials, currentMaterialName: prevMaterialName, - materialAccumulatedDifferences, globalAccumulatedDifferences + materialAccumulatedDifferences, globalAccumulatedDifferences, + pathRecordCache // 新增:从上下文取缓存 } = context; // 用材料名查CD @@ -956,7 +1132,14 @@ async function processNormalPathEntry(entry, context) { const currentTime = getCurrentTimeInHours(); const lastEndTime = getLastRunEndTime(resourceName, pathName, recordDir, noRecordDir); const isPathValid = checkPathNameFrequency(resourceName, pathName, recordDir); - const perTime = noRecord ? null : calculatePerTime(resourceName, pathName, recordDir); + const perTime = noRecord ? null : calculatePerTime( + resourceName, + pathName, + recordDir, + noRecordDir, + false, + pathRecordCache // 新增:传递缓存 + ); log.info(`${CONSTANTS.LOG_MODULES.PATH}材料路径${pathName} 单个材料耗时:${perTime ?? '忽略'}`); @@ -1066,42 +1249,84 @@ async function processNormalPathEntry(entry, context) { * @param {string} recordDir - 记录目录 * @param {string} noRecordDir - 无记录目录 * @param {string} imagesDir - 图像目录 + * @param {string} endTimeStr - 指定终止时间 * @returns {Object} 处理结果 */ -async function processAllPaths(allPaths, CDCategories, materialCategoryMap, timeCost, flattenedLowCountMaterials, currentMaterialName, recordDir, noRecordDir, imagesDir) { +async function processAllPaths(allPaths, CDCategories, materialCategoryMap, timeCost, flattenedLowCountMaterials, currentMaterialName, recordDir, noRecordDir, imagesDir, endTimeStr) { try { // 初始化累加器 let foodExpAccumulator = {}; const globalAccumulatedDifferences = {}; const materialAccumulatedDifferences = {}; + // 新增:单路径处理周期内的记录缓存(处理完所有路径后自动释放) + const pathRecordCache = {}; let context = { CDCategories, timeCost, recordDir, noRecordDir, imagesDir, materialCategoryMap, flattenedLowCountMaterials, currentMaterialName, materialAccumulatedDifferences, - globalAccumulatedDifferences + globalAccumulatedDifferences, + pathRecordCache // 上下文加入缓存,供子函数使用 }; for (const entry of allPaths) { - if (state.cancelRequested) break; + // 优先响应手动终止指令(原有逻辑保留) + if (state.cancelRequested) { + log.warn(`${CONSTANTS.LOG_MODULES.PATH}检测到手动终止指令,停止路径处理`); + break; + } + + // 核心修改:仅当endTimeStr有值时才执行定时终止判断(默认不执行) + let skipPath = false; + if (endTimeStr) { // 只有用户显式配置了终止时间,才进入判断 + const isValidEndTime = /^\d{1,2}[::]\d{1,2}$/.test(endTimeStr); + if (isValidEndTime) { + const remainingMinutes = getRemainingMinutesToEndTime(endTimeStr); + if (remainingMinutes <= 0) { + log.warn(`${CONSTANTS.LOG_MODULES.MAIN}已过指定终止时间(${endTimeStr}),停止路径处理`); + state.cancelRequested = true; + break; + } + + const pathTotalTimeSec = estimatePathTotalTime( + entry, + recordDir, + noRecordDir, + pathRecordCache + ); + const pathTotalTimeMin = pathTotalTimeSec / 60; + const requiredMin = pathTotalTimeMin + 2; + + if (remainingMinutes <= requiredMin) { + log.warn(`${CONSTANTS.LOG_MODULES.MAIN}时间不足:剩余${remainingMinutes}分钟,需${requiredMin}分钟(含2分钟空闲)`); + state.cancelRequested = true; + skipPath = true; + break; + } else { + log.debug(`${CONSTANTS.LOG_MODULES.MAIN}时间充足:剩余${remainingMinutes}分钟,需${requiredMin}分钟`); + } + } else { + log.warn(`${CONSTANTS.LOG_MODULES.MAIN}终止时间格式无效(${endTimeStr}),跳过定时判断`); + } + } // 若endTimeStr为null(默认),则完全跳过定时终止逻辑 + + if (skipPath) break; + + // 原有路径处理逻辑(仅新增缓存传递) + const { path: pathingFilePath, resourceName, monsterName } = entry; + log.info(`${CONSTANTS.LOG_MODULES.PATH}开始处理路径:${basename(pathingFilePath)}`); try { - const { path: pathingFilePath, resourceName, monsterName } = entry; - log.info(`${CONSTANTS.LOG_MODULES.PATH}开始处理路径:${basename(pathingFilePath)}`); - - // 区分路径类型并处理 if (resourceName && isFoodResource(resourceName)) { - // 狗粮路径 const result = await processFoodPathEntry(entry, { foodExpAccumulator, - currentMaterialName: context.currentMaterialName + currentMaterialName: context.currentMaterialName, + pathRecordCache // 传递缓存 }, recordDir, noRecordDir); foodExpAccumulator = result.foodExpAccumulator; context.currentMaterialName = result.currentMaterialName; } else if (monsterName) { - // 怪物路径 context = await processMonsterPathEntry(entry, context); } else if (resourceName) { - // 普通材料路径 context = await processNormalPathEntry(entry, context); } else { log.warn(`${CONSTANTS.LOG_MODULES.PATH}跳过无效路径条目:${JSON.stringify(entry)}`); @@ -1109,6 +1334,10 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time } catch (singleError) { log.error(`${CONSTANTS.LOG_MODULES.PATH}处理路径出错,已跳过:${singleError.message}`); await sleep(1); + if (state.cancelRequested) { + log.warn(`${CONSTANTS.LOG_MODULES.PATH}检测到终止指令,停止处理`); + break; + } } } @@ -1153,9 +1382,22 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time function classifyNormalPathFiles(pathingDir, targetResourceNames, lowCountMaterialNames, cdMaterialNames) { const pathingFilePaths = readAllFilePaths(pathingDir, 0, 3, ['.json']); const pathEntries = pathingFilePaths.map(path => { - const { materialName } = extractResourceNameFromPath(path, cdMaterialNames); - return { path, resourceName: materialName }; - }).filter(entry => entry.resourceName); + const { materialName, monsterName } = extractResourceNameFromPath(path, cdMaterialNames); + return { path, resourceName: materialName, monsterName }; // 新增monsterName字段 + }).filter(entry => { + // 新增:过滤超量材料对应的路径(包括怪物材料) + if (entry.monsterName) { + // 怪物路径:检查其所有材料是否都超量 + const monsterMaterials = monsterToMaterials[entry.monsterName] || []; + const allExcess = monsterMaterials.every(mat => excessMaterialNames.includes(mat)); + return !allExcess; // 若所有材料超量则过滤该路径 + } + if (entry.resourceName) { + // 普通材料路径:检查自身是否超量 + return !excessMaterialNames.includes(entry.resourceName); + } + return false; + }); if (pathEntries.length > 0) { log.info(`${CONSTANTS.LOG_MODULES.PATH}\n===== 匹配到的材料路径列表 =====`); @@ -1170,16 +1412,28 @@ function classifyNormalPathFiles(pathingDir, targetResourceNames, lowCountMateri const prioritizedPaths = []; const normalPaths = []; for (const entry of pathEntries) { - if (targetResourceNames.includes(entry.resourceName)) { - prioritizedPaths.push(entry); - } else if (lowCountMaterialNames.includes(entry.resourceName)) { - normalPaths.push(entry); + if (entry.monsterName) { + // 怪物路径:检查是否包含有效目标材料 + const monsterMaterials = monsterToMaterials[entry.monsterName] || []; + const hasValidTarget = monsterMaterials.some(mat => targetResourceNames.includes(mat) || lowCountMaterialNames.includes(mat)); + if (hasValidTarget) { + prioritizedPaths.push(entry); + } else { + normalPaths.push(entry); + } + } else if (entry.resourceName) { + // 普通材料路径 + if (targetResourceNames.includes(entry.resourceName)) { + prioritizedPaths.push(entry); + } else if (lowCountMaterialNames.includes(entry.resourceName)) { + normalPaths.push(entry); + } } } // 按低数量排序 normalPaths.sort((a, b) => { - const indexA = lowCountMaterialNames.indexOf(a.resourceName); - const indexB = lowCountMaterialNames.indexOf(b.resourceName); + const indexA = lowCountMaterialNames.indexOf(a.resourceName) || lowCountMaterialNames.indexOf(a.monsterName ? monsterToMaterials[a.monsterName]?.[0] : ''); + const indexB = lowCountMaterialNames.indexOf(b.resourceName) || lowCountMaterialNames.indexOf(b.monsterName ? monsterToMaterials[b.monsterName]?.[0] : ''); return indexA - indexB; }); return prioritizedPaths.concat(normalPaths); @@ -1237,14 +1491,25 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames let processedMonsterPaths = monsterPaths; let pathingMaterialCounts = []; - if (normalPaths.length > 0) { - log.info(`${CONSTANTS.LOG_MODULES.PATH}[普通材料] 执行背包扫描→低数量筛选`); - pathingMaterialCounts = await MaterialPath(materialCategoryMap); + if (normalPaths.length > 0 || monsterPaths.length > 0) { // 包含怪物路径时也需要扫描 + // 优化:一次扫描获取全量材料数量,同时服务于怪物和普通材料 + log.info(`${CONSTANTS.LOG_MODULES.PATH}[材料扫描] 执行一次全量背包扫描(服务于怪物+普通路径)`); + const allMaterialCounts = await MaterialPath(materialCategoryMap); // 仅一次扫描 + pathingMaterialCounts = allMaterialCounts; // 普通材料直接复用扫描结果 + + // 1. 怪物材料筛选(复用全量扫描结果) + log.info(`${CONSTANTS.LOG_MODULES.MONSTER}[怪物材料] 基于全量扫描结果筛选有效材料`); + const filteredMonsterMaterials = filterLowCountMaterials(allMaterialCounts.flat(), materialCategoryMap); // 复用结果 + const validMonsterMaterialNames = filteredMonsterMaterials.map(m => m.name); + log.info(`${CONSTANTS.LOG_MODULES.MONSTER}[怪物材料] 筛选后有效材料:${validMonsterMaterialNames.join('、')}`); + + // 2. 普通材料筛选(同样复用全量扫描结果,无需再次扫描) if (pathingMode.onlyCategory) { state.cancelRequested = true; return { allPaths: [], pathingMaterialCounts }; - } - const lowCountMaterialsFiltered = filterLowCountMaterials(pathingMaterialCounts.flat(), materialCategoryMap); +} + log.info(`${CONSTANTS.LOG_MODULES.PATH}[普通材料] 基于全量扫描结果筛选低数量材料`); + const lowCountMaterialsFiltered = filterLowCountMaterials(allMaterialCounts.flat(), materialCategoryMap); // 复用结果 const flattenedLowCountMaterials = lowCountMaterialsFiltered.flat().sort((a, b) => a.count - b.count); const lowCountMaterialNames = flattenedLowCountMaterials.map(material => material.name); @@ -1283,7 +1548,8 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames source: processedMonsterPaths, filter: e => { const materials = monsterToMaterials[e.monsterName] || []; - return !materials.some(mat => targetResourceNames.includes(mat)); + return !materials.some(mat => targetResourceNames.includes(mat)) && + materials.some(mat => !excessMaterialNames.includes(mat)); // 排除所有材料超量的怪物 } }, // 6. 剩余普通材料 @@ -1358,9 +1624,6 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个 =========================================\n\n`; writeContentToFile(summaryPath, content); log.info(`${CONSTANTS.LOG_MODULES.RECORD}最终汇总已记录至 ${summaryPath}`); - // ============================================== - // 新增:汇总后强制触发结束指令,确保程序终止 - // ============================================== state.completed = true; // 标记任务完全完成 state.cancelRequested = true; // 终止所有后台任务(如图像点击、OCR) } @@ -1504,7 +1767,8 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个 currentMaterialName, CONSTANTS.RECORD_DIR, CONSTANTS.NO_RECORD_DIR, - CONSTANTS.IMAGES_DIR + CONSTANTS.IMAGES_DIR, + endTimeStr // 传递终止时间 ); // 汇总结果 diff --git a/repo/js/背包材料统计/manifest.json b/repo/js/背包材料统计/manifest.json index ece08cf61..fa7ed6070 100644 --- a/repo/js/背包材料统计/manifest.json +++ b/repo/js/背包材料统计/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "背包统计采集系统", - "version": "2.53", + "version": "2.54", "bgi_version": "0.44.8", "description": "可统计背包养成道具、部分食物、素材的数量;根据设定数量、根据材料刷新CD执行挖矿、采集、刷怪等的路径。优势:\n+ 1. 自动判断材料CD,不需要管材料CD有没有好;\n+ 2. 可以随意添加路径,能自动排除低效、无效路径;\n+ 3. 有独立名单识别,不会交互路边的npc或是神像;可自定义识别名单,具体方法看【问题解答】增减识别名单\n+ 4. 有实时的弹窗模块,提供了常见的几种:路边信件、过期物品、月卡、调查;\n+ 5. 可识别爆满的路径材料,自动屏蔽;更多详细内容查看readme.md", "saved_files": [ diff --git a/repo/js/背包材料统计/materialsCD/怪物.txt b/repo/js/背包材料统计/materialsCD/怪物.txt index a25c9562d..327b276cc 100644 --- a/repo/js/背包材料统计/materialsCD/怪物.txt +++ b/repo/js/背包材料统计/materialsCD/怪物.txt @@ -1,2 +1,3 @@ -4点:丘丘人,丘丘萨满,丘丘人射手,丘丘暴徒,丘丘王,丘丘游侠,愚人众先遣队,萤术士,债务处理人,冬国仕女,愚人众风役人,愚人众特辖队,盗宝团,野伏众,海乱鬼,镀金旅团,黑蛇众,黯色空壳,部族龙形武士,遗迹机械,元能构装体,遗迹机兵,遗迹龙兽,发条机关,秘源机兵,巡陆艇,史莱姆,骗骗花,飘浮灵,蕈兽,浊水幻灵,原海异种,隙境原体,魔像禁卫,大灵显化身,熔岩游像,龙蜥,圣骸兽,玄文兽,纳塔龙众,炉壳山鼬,蕴光异兽,深渊法师,深渊使徒,兽境群狼,深邃拟覆叶,荒野狂猎,霜夜灵嗣,地脉花, +4点:丘丘人,丘丘萨满,丘丘人射手,丘丘暴徒,丘丘王,丘丘游侠,愚人众先遣队,萤术士,债务处理人,冬国仕女,愚人众风役人,愚人众特辖队,盗宝团,野伏众,海乱鬼,镀金旅团,黑蛇众,黯色空壳,部族龙形武士,遗迹机械,元能构装体,遗迹机兵,遗迹龙兽,发条机关,秘源机兵,巡陆艇,史莱姆,骗骗花,飘浮灵,蕈兽,浊水幻灵,原海异种,隙境原体,魔像禁卫,大灵显化身,熔岩游像,龙蜥,圣骸兽,玄文兽,纳塔龙众,炉壳山鼬,蕴光异兽,深渊法师,深渊使徒,兽境群狼,深邃拟覆叶,荒野狂猎,霜夜灵嗣,地脉花,锄地 + diff --git a/repo/js/背包材料统计/settings.json b/repo/js/背包材料统计/settings.json index a1dca168c..06e6dc5e4 100644 --- a/repo/js/背包材料统计/settings.json +++ b/repo/js/背包材料统计/settings.json @@ -109,10 +109,15 @@ "type": "input-text", "label": "====================\n\n采用的CD分类(默认:全部) 举例:采集,怪物,木材" }, + { + "name": "CurrentTime", + "type": "input-text", + "label": "根据CD分类来加载路径文件,具体看materialsCD目录\n====================\n\n终止时刻(默认:不执行) 例:4:00" + }, { "name": "PickCategories", "type": "input-text", - "label": "根据CD分类来加载路径文件,具体看materialsCD目录\n====================\n\n采用的识别名单(默认:全部) 举例:交互,采集,宝箱" + "label": "====================\n\n采用的识别名单(默认:全部) 举例:交互,采集,宝箱" }, { "name": "ExceedCount",