From 0e545bdd3f0f395f3eba61082a0a80aaffeed0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E5=90=89=E5=96=B5?= Date: Thu, 2 Apr 2026 12:39:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BB=88=E6=AD=A2=E7=BF=BB?= =?UTF-8?q?=E9=A1=B5=E9=80=BB=E8=BE=91=EF=BC=8C=E6=B5=8B=E7=AE=97=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E8=B0=83=E6=95=B4=EF=BC=8C=E5=8E=8B=E7=BC=A9log=20(#3?= =?UTF-8?q?058)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复终止翻页逻辑,测算模式调整,压缩log --- repo/js/背包材料统计/README.md | 15 ++-- repo/js/背包材料统计/lib/autoPick.js | 12 ++-- repo/js/背包材料统计/lib/file.js | 4 +- repo/js/背包材料统计/lib/imageClick.js | 8 +-- repo/js/背包材料统计/lib/pathProcessor.js | 27 +++----- repo/js/背包材料统计/lib/recordManager.js | 43 ++++++++++-- repo/js/背包材料统计/lib/updateSettings.js | 17 ++--- repo/js/背包材料统计/main.js | 81 ++++++++++++++-------- repo/js/背包材料统计/manifest.json | 2 +- repo/js/背包材料统计/materialsCD/怪物.txt | 2 +- 10 files changed, 126 insertions(+), 85 deletions(-) diff --git a/repo/js/背包材料统计/README.md b/repo/js/背包材料统计/README.md index 4c5426462..552271394 100644 --- a/repo/js/背包材料统计/README.md +++ b/repo/js/背包材料统计/README.md @@ -1,4 +1,4 @@ -# 背包材料统计 v2.62 +# 背包材料统计 v2.68 作者:吉吉喵 @@ -208,21 +208,21 @@ A:记录文件夹位于 `BetterGI\User\JsScript\背包材料统计\` 下,各 | v1.3 | 优化:加速材料寻找(新增前位材料识别) | | v1.31 | 调整本地记录存储逻辑 | | v1.32 | 新增后位材料识别功能 | -| v2.0 | 开发版:支持多组材料、多个分类;移除前/后位材料识别 | +| v2.0 | 开发版:支持多组材料、多个分类;移除前/后位材料识别 | | v2.1 | 新增CD管理功能 | | v2.2 | 优化路径顺序、材料数量判断逻辑 | | v2.21 | 修改路径储存路径 | | v2.22 | 精简日志输出内容 | | v2.23 | 优化部分函数性能 | | v2.24 | 修复“空路径无法使用背包统计”等bug | -| v2.25 | 恢复前/后位材料识别(加速扫描);新增“仅扫描路径材料”选项(降低内存占用) | +| v2.25 | 恢复前/后位材料识别(加速扫描);新增“仅扫描路径材料”选项(降低内存占用)| | v2.26 | 修复材料时间读取错误;新增路径材料时间成本计算功能 | | v2.27 | 修复“材料数计算错误”“目标数量临界值异常”“3识别成三”等bug | | v2.28 | 材料变更时自动更新初始数量;排除0位移/0数量路径记录;新增材料名0后缀本地记录;新增背包弹窗识别 | -| v2.29 | 新增排除提示;调整平均时间成本计算逻辑;过滤异常值记录 | -| v2.30 | 更改路径专注模式默认值;增加日志提示;移除调试日志 | +| v2.29 | 新增排除提示;调整平均时间成本计算逻辑;过滤异常值记录 | +| v2.30 | 更改路径专注模式默认值;增加日志提示;移除调试日志 | | v2.40 | 优化背包识别时的内存占用;新增通知功能 | -| v2.41 | 修复“勾选分类的本地记录”bug;新增“仅背包统计”选项;补充记录损坏处理说明 | +| v2.41 | 修复“勾选分类的本地记录”bug;新增“仅背包统计”选项;补充记录损坏处理说明 | | v2.42 | 新增“无路径间扫描”“noRecord模式”(适合成熟路径);新增怪物材料CD文件 | | v2.50 | 新增独立名单拾取、弹窗模块;支持怪物名识别 | | v2.51 | 自定义设置新增“拖动距离/拖动点”;新增月卡弹窗识别;路径材料超量自动上黑名单;修复怪物0收获记录 | @@ -240,4 +240,5 @@ A:记录文件夹位于 `BetterGI\User\JsScript\背包材料统计\` 下,各 | v2.64 | 移除位移检测模块 | | v2.65 | 修复测算模式、0记录检测码等bug,优化汇总日志,调整默认目标数量至1000 | | v2.66 | 修复翻页兜底逻辑,增加材料数量模板匹配,材料数量OCR失败后截图保存,【扫描额外的分类】联动超量材料 | -| v2.67 | 修复怪物材料映射斜杠逻辑,更新OCR错字映射表,优先级材料按自定义顺序,修复怪物材料过滤bug | \ No newline at end of file +| v2.67 | 修复怪物材料映射斜杠逻辑,更新OCR错字映射表,优先级材料按自定义顺序,修复怪物材料过滤bug | +| v2.68 | 修复终止翻页逻辑,测算模式调整,压缩log | \ No newline at end of file diff --git a/repo/js/背包材料统计/lib/autoPick.js b/repo/js/背包材料统计/lib/autoPick.js index 297fb86aa..32acc445e 100644 --- a/repo/js/背包材料统计/lib/autoPick.js +++ b/repo/js/背包材料统计/lib/autoPick.js @@ -39,13 +39,13 @@ function readtargetTextCategories(targetTextDir) { let availablePickCategories = []; try { availablePickCategories = targetTextFilePaths.map(filePath => basename(filePath).replace('.txt', '')); - log.info(`可用识别名单:${availablePickCategories.join(', ')}`); + if (debugLog) log.info(`可用识别名单:${availablePickCategories.join(', ')}`); } catch (e) { log.error(`扫描识别名单目录失败: ${e.message}`); } if (pickTextNames.length === 0) { - log.info("未指定识别名单,将加载所有文件"); + if (debugLog) log.info("未指定识别名单,将加载所有文件"); } else { const invalidCategories = pickTextNames.filter(name => !availablePickCategories.includes(name)); if (invalidCategories.length > 0) { @@ -54,7 +54,7 @@ function readtargetTextCategories(targetTextDir) { } } - log.info(`筛选名单状态:${pickTextNames.length === 0 ? '未指定(空),将加载所有文件' : '指定了:' + pickTextNames.join(',')}`); + if (debugLog) log.info(`筛选名单状态:${pickTextNames.length === 0 ? '未指定(空),将加载所有文件' : '指定了:' + pickTextNames.join(',')}`); for (const filePath of targetTextFilePaths) { if (state.cancelRequested) break; @@ -76,7 +76,7 @@ function readtargetTextCategories(targetTextDir) { materialCategories[sourceCategory] = parseCategoryContent(content); } - log.info(`完成读取,加载的分类:${Object.keys(materialCategories).join(',')}`); + if (debugLog) log.info(`完成读取,加载的分类:${Object.keys(materialCategories).join(',')}`); return materialCategories; } @@ -196,7 +196,9 @@ async function alignAndInteractTarget(targetTextsOrFunc, fDialogueRo, textxRange for (const res of ocrResults) { const centerY = res.y + res.height / 2; const yDiff = Math.abs(centerY - fCenterY); - log.debug(`未匹配: "${res.text}" Y中心: ${centerY.toFixed(1)}, F图标Y中心: ${fCenterY.toFixed(1)}, 差值: ${yDiff.toFixed(1)}, 容忍度: ${texttolerance}`); + const logText = `未匹配: "${res.text}" Y中心: ${centerY.toFixed(1)}, F图标Y中心: ${fCenterY.toFixed(1)}, 差值: ${yDiff.toFixed(1)}, 容忍度: ${texttolerance}`; + log.debug(logText); + writeFile("user/OCR未匹配记录.txt", logText); } } await keyMouseScript.runFile(`assets/滚轮下翻.json`); diff --git a/repo/js/背包材料统计/lib/file.js b/repo/js/背包材料统计/lib/file.js index 352b4c64d..ea8fed1a2 100644 --- a/repo/js/背包材料统计/lib/file.js +++ b/repo/js/背包材料统计/lib/file.js @@ -116,7 +116,7 @@ function safeReadTextSync(filePath, defaultValue = "") { try { // 第一步:校验文件是否存在 if (!fileExists(filePath)) { - log.debug(`${CONSTANTS.LOG_MODULES.RECORD}文件不存在,跳过读取: ${filePath}`); + // log.debug(`${CONSTANTS.LOG_MODULES.RECORD}文件不存在,跳过读取: ${filePath}`); return defaultValue; } // 第二步:读取文件(捕获读取异常) @@ -226,7 +226,7 @@ function matchImageAndGetCategory(resourceName, imagesDir) { const processedName = (MATERIAL_ALIAS[resourceName] || resourceName).toLowerCase(); if (!imageMapCache.has(imagesDir)) { - log.debug(`${CONSTANTS.LOG_MODULES.MATERIAL}初始化图像分类缓存:${imagesDir}`); + // log.debug(`${CONSTANTS.LOG_MODULES.MATERIAL}初始化图像分类缓存:${imagesDir}`); imageMapCache.set(imagesDir, createImageCategoryMap(imagesDir)); } diff --git a/repo/js/背包材料统计/lib/imageClick.js b/repo/js/背包材料统计/lib/imageClick.js index 603e836b0..91d8d638f 100644 --- a/repo/js/背包材料统计/lib/imageClick.js +++ b/repo/js/背包材料统计/lib/imageClick.js @@ -264,11 +264,11 @@ async function imageClickBackgroundTask() { // 打印资源检测结果 log.info("\n==================== 现有弹窗加载结果 ===================="); - log.info("1. 一级弹窗(共" + firstLevelDirs.length + "个):"); - firstLevelDirs.forEach((res, idx) => log.info(` ${idx+1}. 【${res.dirName}】`)); + const firstLevelNames = firstLevelDirs.map(res => res.dirName).join('、'); + log.info("1. 一级弹窗(共" + firstLevelDirs.length + "个):" + firstLevelNames); const secondLevelResources = preloadedResources.filter(res => !res.isFirstLevel); - log.info("\n2. 二级弹窗(共" + secondLevelResources.length + "个):"); - secondLevelResources.forEach((res, idx) => log.info(` ${idx+1}. 【${res.dirName}】`)); + const secondLevelNames = secondLevelResources.map(res => res.dirName).join('、'); + log.info("2. 二级弹窗(共" + secondLevelResources.length + "个):" + secondLevelNames); log.info("=============================================================\n"); // 核心逻辑:外循环遍历所有一级弹窗 diff --git a/repo/js/背包材料统计/lib/pathProcessor.js b/repo/js/背包材料统计/lib/pathProcessor.js index ed16d3262..5438012df 100644 --- a/repo/js/背包材料统计/lib/pathProcessor.js +++ b/repo/js/背包材料统计/lib/pathProcessor.js @@ -366,7 +366,7 @@ async function processMonsterPathEntry(entry, context) { if (startTime) { const endTime = new Date().toLocaleString(); runTime = (new Date(endTime) - new Date(startTime)) / 1000; - await handlePathError(error, pathingFilePath, pathName, monsterName, startTime, endTime, runTime, shouldRunAsNoRecord, false); + await handlePathError(error, pathingFilePath, pathName, monsterName, startTime, endTime, runTime, shouldRunAsNoRecord, state.cancelRequested); } throw error; } @@ -589,7 +589,8 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time noRecordDir, isFood, pathRecordCache, - pathingFilePath + pathingFilePath, + true ); const isTimeCostOk = perTime === null || isTimeCostQualified( @@ -655,17 +656,6 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time } } - log.info(`${CONSTANTS.LOG_MODULES.PATH}\n===== 测算模式分析结果 =====`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}时间成本:${timeCost}%`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}总路径数:${totalPaths}`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}未通过(CD未刷新):${failedCD}条`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}未通过(0记录超限):${failedFrequency}条`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}未达标(时间成本不合格):${failedTimeCost}条`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}直通达标(记录不足):${insufficientRecords}条`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}达标路径数:${totalQualifiedPaths}条(同时通过三个校验)`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}达标占比:${totalPaths > 0 ? ((totalQualifiedPaths / totalPaths) * 100).toFixed(1) : 0}%`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}预计耗时:${formatTime(totalEstimatedTime)}`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}\n各材料平均时间成本及达标情况:`); for (const [resourceKey, data] of Object.entries(resourceAnalysis)) { const avgThresholdPerTime = data.thresholdPerTimeCount > 0 ? (data.thresholdPerTimeSum / data.thresholdPerTimeCount).toFixed(4) : '无记录'; @@ -675,7 +665,6 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time const avgThresholdPercentile = thresholdPercentileTimes.length > 0 ? (thresholdPercentileTimes.reduce((sum, t) => sum + t, 0) / thresholdPercentileTimes.length).toFixed(4) : '无达标'; - const qualifiedRatio = data.thresholdPerTimeCount > 0 ? ((data.qualified / data.thresholdPerTimeCount) * 100).toFixed(1) : '0.0'; const totalEstimatedTime = formatTime(data.estimatedTimeSum); const avgQualifiedPerTime = data.qualified > 0 ? (data.qualifiedPerTimeSum / data.qualified).toFixed(4) : '无达标'; @@ -687,15 +676,21 @@ async function processAllPaths(allPaths, CDCategories, materialCategoryMap, time } else if (isMonster) { unit = '秒/中位材料'; } + const totalPassedPaths = data.qualified; + const totalPathsForMaterial = data.total; + const directPassPaths = totalPassedPaths; + const displayRatio = `${totalPassedPaths}/${totalPathsForMaterial}`; log.info(`${CONSTANTS.LOG_MODULES.PATH} --------------------------------------`); log.info(`${CONSTANTS.LOG_MODULES.PATH} ${resourceKey}:`); log.info(`${CONSTANTS.LOG_MODULES.PATH} 达标平均:${avgQualifiedPerTime}${unit}`); log.info(`${CONSTANTS.LOG_MODULES.PATH} 所有记录平均(排除0记录超限):${avgThresholdPerTime}${unit}`); log.info(`${CONSTANTS.LOG_MODULES.PATH} 设置的${timeCost}%分位阈值:${avgThresholdPercentile}${unit}`); - log.info(`${CONSTANTS.LOG_MODULES.PATH} 达标:${qualifiedRatio}% (${data.qualified}/${data.thresholdPerTimeCount}),总耗时:${totalEstimatedTime}`); + log.info(`${CONSTANTS.LOG_MODULES.PATH} 达标:${displayRatio},总耗时:${totalEstimatedTime}`); } - log.info(`${CONSTANTS.LOG_MODULES.PATH}=============================\n`); + + const qualifiedRatio = totalPaths > 0 ? ((totalQualifiedPaths / totalPaths) * 100).toFixed(1) : 0; + log.info(`${CONSTANTS.LOG_MODULES.PATH}===== 测算模式分析结果 =====\n时间成本:${timeCost}%,总路径:${totalPaths}\nCD冷却中:${failedCD},0记录超限:${failedFrequency},cost不达标:${failedTimeCost}\n达标:${totalQualifiedPaths}(${qualifiedRatio}%),预计耗时:${formatTime(totalEstimatedTime)}\n`); if (notify) { const estimateMsg = `【测算模式】分析完成\n总路径数:${totalPaths}\n达标路径数:${totalQualifiedPaths}\n达标占比:${totalPaths > 0 ? ((totalQualifiedPaths / totalPaths) * 100).toFixed(1) : 0}%\n预计耗时:${formatTime(totalEstimatedTime)}`; diff --git a/repo/js/背包材料统计/lib/recordManager.js b/repo/js/背包材料统计/lib/recordManager.js index 628cbc772..50ec357a8 100644 --- a/repo/js/背包材料统计/lib/recordManager.js +++ b/repo/js/背包材料统计/lib/recordManager.js @@ -138,7 +138,7 @@ function checkPathNameFrequency(resourceName, pathName, recordDir, isFood = fals if (line.startsWith('路径名: ')) { currentPathName = line.split('路径名: ')[1]; } else if (line.startsWith('内容检测码: ')) { - recordContentCode = line.split('内容检测码: ')[1]; + recordContentCode = line.split('内容检测码: ')[1].trim(); } else if (line === '' && currentPathName && recordContentCode) { if (hasValidContentCode) { if (recordContentCode === currentContentCode) { @@ -266,11 +266,11 @@ function getLastRunEndTime(resourceName, pathName, recordDir, noRecordDir, pathi blockLines.forEach(line => { if (line.startsWith('路径名: ')) { - blockPathName = line.split('路径名: ')[1]; + blockPathName = line.split('路径名: ')[1].trim(); } else if (line.startsWith('内容检测码: ')) { - blockContentCode = line.split('内容检测码: ')[1] || '00000000'; + blockContentCode = line.split('内容检测码: ')[1].trim() || '00000000'; } else if (line.startsWith('结束时间: ')) { - blockEndTime = line.split('结束时间: ')[1]; + blockEndTime = line.split('结束时间: ')[1].trim(); } }); @@ -308,7 +308,7 @@ function getLastRunEndTime(resourceName, pathName, recordDir, noRecordDir, pathi * @param {Object} cache - 缓存对象(单次路径处理周期内有效) * @returns {Array} 结构化记录列表(含runTime、quantityChange) */ -function getHistoricalPathRecords(resourceKey, pathName, recordDir, noRecordDir, isFood = false, cache = {}, pathingFilePath) { +function getHistoricalPathRecords(resourceKey, pathName, recordDir, noRecordDir, isFood = false, cache = {}, pathingFilePath, filterExcessMaterials = false) { const contentCode = pathingFilePath ? generatePathContentCode(pathingFilePath) : null; const hasValidContentCode = contentCode && contentCode !== "00000000"; @@ -353,14 +353,14 @@ function getHistoricalPathRecords(resourceKey, pathName, recordDir, noRecordDir, blockLines.forEach(line => { if (line.startsWith('路径名: ')) { - const recordPathName = line.split('路径名: ')[1]; + const recordPathName = line.split('路径名: ')[1].trim(); const cleanRecordPathName = recordPathName.replace(/_[0-9a-fA-F]{8}\.json$/, '.json'); if (cleanRecordPathName === cleanPathName) { isTargetPath = true; } } if (line.startsWith('内容检测码: ')) { - recordContentCode = line.split('内容检测码: ')[1] || "00000000"; + recordContentCode = line.split('内容检测码: ')[1].trim() || "00000000"; } if (line.startsWith('运行时间: ')) { runTime = parseInt(line.split('运行时间: ')[1].split('秒')[0], 10) || 0; @@ -391,6 +391,35 @@ function getHistoricalPathRecords(resourceKey, pathName, recordDir, noRecordDir, cache[cacheKey] = records; if (debugLog) log.debug(`${CONSTANTS.LOG_MODULES.RECORD}读取记录并缓存:${cacheKey}(${records.length}条)`); + + if (filterExcessMaterials && excessMaterialNames.length > 0) { + const filteredRecords = records.filter(record => { + const { quantityChange } = record; + + if (isFood) { + return true; + } + + if (monsterToMaterials[resourceKey]) { + const monsterMaterials = monsterToMaterials[resourceKey]; + const allExcess = monsterMaterials.every(mat => excessMaterialNames.includes(mat)); + return !allExcess; + } + + if (quantityChange[resourceKey] !== undefined) { + return !excessMaterialNames.includes(resourceKey); + } + + return true; + }); + + if (debugLog && filteredRecords.length !== records.length) { + log.debug(`${CONSTANTS.LOG_MODULES.RECORD}过滤超量材料记录:${records.length}条 -> ${filteredRecords.length}条`); + } + + return filteredRecords; + } + return records; } diff --git a/repo/js/背包材料统计/lib/updateSettings.js b/repo/js/背包材料统计/lib/updateSettings.js index 0a4c20ab2..1ed93954d 100644 --- a/repo/js/背包材料统计/lib/updateSettings.js +++ b/repo/js/背包材料统计/lib/updateSettings.js @@ -7,9 +7,8 @@ function updateSettingsOptions() { log.info("开始更新settings.json..."); try { var settingsContent = file.readTextSync(SETTINGS_FILE); - log.info("settings.json内容长度: " + settingsContent.length); var settings = JSON.parse(settingsContent); - log.info("settings.json解析成功,配置项数量: " + settings.length); + if (debugLog) log.info("settings.json解析成功,配置项数量: " + settings.length); var hasChanges = false; @@ -27,7 +26,6 @@ function updateSettingsOptions() { return basename(dirPath); }) .sort(); - log.info("扫描到弹窗目录数量: " + popupDirs.length); var cdCategories = readAllFilePaths("materialsCD", 0, 1, ['.txt']) .map(function(filePath) { @@ -56,9 +54,7 @@ function updateSettingsOptions() { } } if (popupSetting) { - log.info("找到PopupNames配置项"); var existingOptions = popupSetting.options || []; - log.info("现有options数量: " + existingOptions.length); var existingSet = {}; for (var k = 0; k < existingOptions.length; k++) { @@ -83,23 +79,20 @@ function updateSettingsOptions() { } } - log.info("新增options数量: " + newOptions.length); - log.info("删除options数量: " + removedOptions.length); - if (newOptions.length > 0 || removedOptions.length > 0) { popupSetting.options = popupDirs; hasChanges = true; if (newOptions.length > 0) { - log.info("PopupNames新增选项: " + newOptions.join(', ')); + log.info("PopupNames新增: " + newOptions.join('、')); } if (removedOptions.length > 0) { - log.info("PopupNames删除选项: " + removedOptions.join(', ')); + log.info("PopupNames删除: " + removedOptions.join('、')); } } else { - log.info("PopupNames无新增选项"); + if (debugLog) log.info("PopupNames(现有" + existingOptions.length + "个)无需更新"); } } else { - log.info("未找到PopupNames配置项"); + log.warn("未找到PopupNames配置项"); } if (cdSetting) { diff --git a/repo/js/背包材料统计/main.js b/repo/js/背包材料统计/main.js index eeea6af47..0af1dbcf9 100644 --- a/repo/js/背包材料统计/main.js +++ b/repo/js/背包材料统计/main.js @@ -36,6 +36,12 @@ const CONSTANTS = { // 引入外部脚本(源码不变) // ============================================== eval(file.readTextSync("lib/file.js")); + +// 提前读取 settings.json 以便定义 debugLog +var settingsContent = file.readTextSync("settings.json"); +var settings = JSON.parse(settingsContent); +var debugLog = settings.debugLog || false; + eval(safeReadTextSync("lib/updateSettings.js")); eval(safeReadTextSync("lib/ocr.js")); eval(safeReadTextSync("lib/writeImage.js")); @@ -70,7 +76,6 @@ const timeCost = Math.min(100, Math.max(1, Math.floor(Number(settings.TimeCost) const notify = settings.notify || false; const noRecord = settings.noRecord || false; const noMonsterFilter = !settings.noMonsterFilter; -const debugLog = settings.debugLog || false; const targetCount = Math.min(9999, Math.max(0, Math.floor(Number(settings.TargetCount) || 1000))); // 设定的目标数量 const exceedCount = Math.min(9999, Math.max(0, Math.floor(Number(settings.ExceedCount) || 9000))); // 设定的超量目标数量 const endTimeStr = settings.CurrentTime ? settings.CurrentTime : null; @@ -87,7 +92,7 @@ let availableCDCategories = []; try { const cdFilePaths = readAllFilePaths(CONSTANTS.MATERIAL_CD_DIR, 0, 1, ['.txt']); availableCDCategories = cdFilePaths.map(filePath => basename(filePath).replace('.txt', '')); - log.info(`${CONSTANTS.LOG_MODULES.INIT}可用CD分类:${availableCDCategories.join(', ')}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.INIT}可用CD分类:${availableCDCategories.join(', ')}`); } catch (e) { log.error(`${CONSTANTS.LOG_MODULES.INIT}扫描CD目录失败: ${e.message}`); } @@ -100,7 +105,7 @@ if (allowedCDCategories.length > 0) { } log.info(`${CONSTANTS.LOG_MODULES.INIT}已配置只处理以下CD分类:${allowedCDCategories.join('、')}`); } else { - log.info(`${CONSTANTS.LOG_MODULES.INIT}未配置CD分类过滤,将处理所有分类`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.INIT}未配置CD分类过滤,将处理所有分类`); } // ============================================== @@ -463,8 +468,8 @@ function filterLowCountMaterials(pathingMaterialCounts, materialCategoryMap, onl // onlyCategory模式下,检查所有扫描到的材料,而不仅仅是materialCategoryMap中的材料 const shouldCheckAll = onlyCategoryMode || allMaterials.length === 0; - log.info(`【材料基准】onlyCategoryMode=${onlyCategoryMode}, allMaterials长度=${allMaterials.length}, shouldCheckAll=${shouldCheckAll}, pathingMaterialCounts长度=${pathingMaterialCounts.length}`); - log.info(`【扫描结果】${pathingMaterialCounts.map(item => `${item.name}:${item.count}`).join(', ')}`); + if (debugLog) log.info(`【材料基准】onlyCategoryMode=${onlyCategoryMode}, allMaterials长度=${allMaterials.length}, shouldCheckAll=${shouldCheckAll}, pathingMaterialCounts长度=${pathingMaterialCounts.length}`); + if (debugLog) log.info(`【扫描结果】${pathingMaterialCounts.map(item => `${item.name}:${item.count}`).join(', ')}`); // ========== 第一步:平行判断超量材料(原始数据,不经过低数量过滤) ========== pathingMaterialCounts.forEach(item => { @@ -486,7 +491,6 @@ function filterLowCountMaterials(pathingMaterialCounts, materialCategoryMap, onl // 超量判断(平行逻辑:只要≥阈值就标记,和低数量无关) if (processedCount >= EXCESS_THRESHOLD) { tempExcess.push(item.name); - log.info(`${CONSTANTS.LOG_MODULES.MATERIAL}[超量标记] ${item.name} 原始:${item.count} → ${processedCount} ≥ ${EXCESS_THRESHOLD}`); } }); @@ -512,7 +516,7 @@ function filterLowCountMaterials(pathingMaterialCounts, materialCategoryMap, onl // ========== 第三步:更新全局超量名单(去重) ========== excessMaterialNames = [...new Set(tempExcess)]; const realExcessCount = excessMaterialNames.filter(name => name !== "OCR启动").length; - log.info(`【超量材料更新】共${realExcessCount}种:${excessMaterialNames.filter(name => name !== "OCR启动").join("、")}`); + if (debugLog) log.info(`【超量材料更新】共${realExcessCount}种:${excessMaterialNames.filter(name => name !== "OCR启动").join("、")}`); if (debugLog) log.info(`【低数量材料】筛选后共${filteredLowCountMaterials.length}种:${filteredLowCountMaterials.map(m => m.name).join("、")}`); // 返回低数量材料(超量名单已独立生成) @@ -610,11 +614,11 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames return { path, resourceName: materialName, monsterName }; }).filter(entry => (entry.resourceName || entry.monsterName) && entry.path.trim() !== ""); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[路径初始化] 共读取有效路径 ${pathEntries.length} 条`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[路径初始化] 共读取有效路径 ${pathEntries.length} 条`); // 测算模式:不执行背包扫描,直接返回所有路径 if (pathingMode.estimateMode) { - log.info(`${CONSTANTS.LOG_MODULES.PATH}[测算模式] 跳过背包扫描,直接进行路径分析`); + log.info(`${CONSTANTS.LOG_MODULES.PATH}[测算模式] 将执行背包扫描以筛选低数量材料`); } // 分类路径(狗粮 > 怪物 > 普通材料) @@ -622,13 +626,9 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames const monsterPaths = pathEntries.filter(entry => entry.monsterName && entry.monsterName !== '地脉花'); const normalPaths = pathEntries.filter(entry => entry.resourceName && !entry.monsterName && entry.resourceName !== '锄地'); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[路径分类] 狗粮:${foodPaths.length} 怪物:${monsterPaths.length} 普通:${normalPaths.length}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[路径分类] 狗粮:${foodPaths.length} 怪物:${monsterPaths.length} 普通:${normalPaths.length}`); - // 测算模式:直接返回所有路径 - if (pathingMode.estimateMode) { - const allPaths = [...monsterPaths, ...normalPaths, ...foodPaths]; - return { allPaths, pathingMaterialCounts: [] }; - } + // 测算模式不再直接返回所有路径,而是继续执行背包扫描以筛选低数量材料 // 怪物路径关联材料到分类(扫描用)- 仅includeBoth和onlyPathing模式 if (pathingMode.includeBoth || pathingMode.onlyPathing) { @@ -663,7 +663,7 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames if (normalPaths.length > 0 || monsterPaths.length > 0 || pathingMode.onlyCategory) { // 优化:一次扫描获取全量材料数量,同时服务于怪物和普通材料 log.info(`${CONSTANTS.LOG_MODULES.PATH}[材料扫描] 执行一次全量背包扫描(服务于怪物+普通路径)`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[材料扫描] materialCategoryMap内容:${JSON.stringify(materialCategoryMap)}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[材料扫描] materialCategoryMap内容:${JSON.stringify(materialCategoryMap)}`); const allMaterialCounts = await MaterialPath(materialCategoryMap); pathingMaterialCounts = allMaterialCounts; // log.info(`${CONSTANTS.LOG_MODULES.PATH}[材料扫描] 扫描返回数据:${JSON.stringify(allMaterialCounts)}`); @@ -675,6 +675,16 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames const validMonsterMaterialNames = filteredMaterials.map(m => m.name); if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.MONSTER}[怪物材料] 筛选后有效材料:${validMonsterMaterialNames.join('、')}`); + // includeBoth模式:更新超量名单并保存到文件 + if (pathingMode.includeBoth) { + const finalExcessList = excessMaterialNames.filter(name => name !== "OCR启动"); + if (finalExcessList.length > 0) { + log.info(`${CONSTANTS.LOG_MODULES.PATH}[includeBoth模式] 更新超量名单,共${finalExcessList.length}种:${finalExcessList.join('、')}`); + } + const fullContent = finalExcessList.length > 0 ? `超量名单:${finalExcessList.join(',')}\n` : ""; + file.writeTextSync(CONSTANTS.EXCESS_MATERIALS_PATH, fullContent, false); + } + // onlyCategory模式:只扫描,不处理路径 if (pathingMode.onlyCategory) { // 先读取txt超量名单 @@ -684,10 +694,13 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames const scannedMaterials = allMaterialCounts.flat(); const updatedExcessMaterials = new Set(txtExcessMaterials); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] txt超量名单长度:${txtExcessMaterials.length}, 内容:${txtExcessMaterials.join('、')}`); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] updatedExcessMaterials初始长度:${updatedExcessMaterials.size}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] txt超量名单长度:${txtExcessMaterials.length}, 内容:${txtExcessMaterials.join('、')}`); + // log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] updatedExcessMaterials初始长度:${updatedExcessMaterials.size}`); // 逐一检查txt超量名单中的每个材料 + const keptMaterials = []; + const removedMaterials = []; + txtExcessMaterials.forEach(name => { const found = scannedMaterials.find(m => m.name === name); if (found) { @@ -700,29 +713,37 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames } // 用处理后的数量判断是否超量 if (rawCount >= exceedCount) { - log.info(`${CONSTANTS.LOG_MODULES.PATH}[比对] ${name} 原始:${originalCount} 处理后:${rawCount} ≥ ${exceedCount} → 保留在超量名单`); + keptMaterials.push(name); } else { - log.info(`${CONSTANTS.LOG_MODULES.PATH}[比对] ${name} 原始:${originalCount} 处理后:${rawCount} < ${exceedCount} → 从超量名单剔除`); + removedMaterials.push(name); updatedExcessMaterials.delete(name); } } else { // 没扫描到,保留在超量名单 - log.info(`${CONSTANTS.LOG_MODULES.PATH}[比对] ${name} 未扫描到 → 保留在超量名单`); + keptMaterials.push(name); } }); const finalExcessList = Array.from(updatedExcessMaterials); - log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 更新后超量名单,共${finalExcessList.length}种:${finalExcessList.join('、')}`); + + // 输出汇总日志 + if (keptMaterials.length > 0) { + log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 保留在超量名单:${keptMaterials.join('、')}`); + } + if (removedMaterials.length > 0) { + log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 从超量名单剔除:${removedMaterials.join('、')}`); + } + log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 更新后超量名单,共${finalExcessList.length}种`); // 保存更新后的超量名单(直接覆盖,不合并) const fullContent = finalExcessList.length > 0 ? `超量名单:${finalExcessList.join(',')}\n` : ""; file.writeTextSync(CONSTANTS.EXCESS_MATERIALS_PATH, fullContent, false); - log.info(`${CONSTANTS.LOG_MODULES.RECORD}超量名单已保存至 ${CONSTANTS.EXCESS_MATERIALS_PATH},共${finalExcessList.length}种`); + // log.info(`${CONSTANTS.LOG_MODULES.RECORD}超量名单已保存至 ${CONSTANTS.EXCESS_MATERIALS_PATH},共${finalExcessList.length}种`); // 过滤只保留超量名单中的材料 const filteredByExcess = scannedMaterials.filter(item => finalExcessList.includes(item.name)); pathingMaterialCounts = [filteredByExcess]; - log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 过滤后保留超量材料:${filteredByExcess.map(m => m.name).join('、') || '无'}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[onlyCategory模式] 过滤后保留超量材料:${filteredByExcess.map(m => m.name).join('、') || '无'}`); return { allPaths: [], pathingMaterialCounts }; } @@ -737,9 +758,9 @@ async function generateAllPaths(pathingDir, targetResourceNames, cdMaterialNames if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[普通材料] 筛选后保留路径 ${processedNormalPaths.length} 条`); } else if (foodPaths.length > 0) { // 只有狗粮路径时,也需要初始化超量名单(OCR启动需要) - log.info(`${CONSTANTS.LOG_MODULES.PATH}[狗粮模式] 初始化超量名单`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.PATH}[狗粮模式] 初始化超量名单`); excessMaterialNames = ["OCR启动"]; - log.info(`【超量材料更新】共${excessMaterialNames.length}种:${excessMaterialNames.join("、")}`); + if (debugLog) log.info(`【超量材料更新】共${excessMaterialNames.length}种:${excessMaterialNames.join("、")}`); } // 按TargetresourceName顺序处理路径(优先级1-3按目标顺序,同类型内也按目标顺序) @@ -1015,7 +1036,7 @@ function loadExcessMaterialsList() { } const materials = match[1].split(',').map(name => name.trim()).filter(name => name); - log.info(`${CONSTANTS.LOG_MODULES.RECORD}读取超量名单成功,共${materials.length}种:${materials.join('、')}`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.RECORD}读取超量名单成功,共${materials.length}种:${materials.join('、')}`); return materials; } catch (error) { log.error(`${CONSTANTS.LOG_MODULES.RECORD}读取超量名单失败:${error.message}`); @@ -1145,7 +1166,7 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个 // 并行任务:路径处理 const pathTask = (async () => { - log.info(`${CONSTANTS.LOG_MODULES.MAIN}开始路径处理流程`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.MAIN}开始路径处理流程`); // 加载CD分类 const CDCategories = readMaterialCD(); @@ -1169,7 +1190,7 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个 }); } else { if (pathingMode.onlyPathing) { - log.warn(`${CONSTANTS.LOG_MODULES.MATERIAL}onlyPathing模式:将自动扫描pathing材料的实际分类`); + if (debugLog) log.warn(`${CONSTANTS.LOG_MODULES.MATERIAL}onlyPathing模式:将自动扫描pathing材料的实际分类`); } else { log.warn(`${CONSTANTS.LOG_MODULES.MATERIAL}未选择【材料分类】,采用【路径材料】专注模式`); } @@ -1338,7 +1359,7 @@ ${Object.entries(totalDifferences).map(([name, diff]) => ` ${name}: +${diff}个 const imageTask = pathingMode.estimateMode ? null : imageClickBackgroundTask(); const tasks = pathingMode.estimateMode ? [pathTask] : [ocrTask, pathTask, imageTask].filter(t => t !== null); - log.info(`${CONSTANTS.LOG_MODULES.MAIN}任务列表已创建,共${tasks.length}个任务`); + if (debugLog) log.info(`${CONSTANTS.LOG_MODULES.MAIN}任务列表已创建,共${tasks.length}个任务`); try { await Promise.allSettled(tasks); diff --git a/repo/js/背包材料统计/manifest.json b/repo/js/背包材料统计/manifest.json index 1e48b97c6..e9632f5d6 100644 --- a/repo/js/背包材料统计/manifest.json +++ b/repo/js/背包材料统计/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "背包统计采集系统", - "version": "2.67", + "version": "2.68", "bgi_version": "0.55", "description": "可统计背包养成道具、部分食物、素材的数量;根据设定数量、根据材料刷新CD执行挖矿、采集、刷怪等的路径。优势:\n+ 1. 自动判断材料CD,不需要管材料CD有没有好;\n+ 2. 可以随意添加路径,能自动排除低效、无效路径;\n+ 3. 有独立名单识别,不会交互路边的npc或是神像;可自定义识别名单,具体方法看【问题解答】增减识别名单\n+ 4. 有实时的弹窗模块,提供了常见的几种:路边信件、过期物品、月卡、调查;\n+ 5. 可识别爆满的路径材料,自动屏蔽;更多详细内容查看readme.md;可在我的主页下载 路径重命名 工具JS,给路径名批量添加检测码,方便识别。", "saved_files": [ diff --git a/repo/js/背包材料统计/materialsCD/怪物.txt b/repo/js/背包材料统计/materialsCD/怪物.txt index 929c1067e..1ab9a7bd5 100644 --- a/repo/js/背包材料统计/materialsCD/怪物.txt +++ b/repo/js/背包材料统计/materialsCD/怪物.txt @@ -1,2 +1,2 @@ -4点:丘丘人,丘丘萨满,丘丘人射手,丘丘暴徒,丘丘王,丘丘游侠,愚人众先遣队,萤术士,债务处理人,冬国仕女,愚人众风役人,愚人众特辖队,盗宝团,野伏众,海乱鬼,镀金旅团,黑蛇众,黯色空壳,部族龙形武士,遗迹机械,元能构装体,遗迹机兵,遗迹龙兽,发条机关,秘源机兵,巡陆艇,史莱姆,骗骗花,飘浮灵,蕈兽,浊水幻灵,原海异种,隙境原体,魔像禁卫,大灵显化身,熔岩游像,龙蜥,圣骸兽,玄文兽,纳塔龙众,炉壳山鼬,蕴光异兽,深渊法师,深渊使徒,兽境群狼,深邃拟覆叶,荒野狂猎,霜夜灵嗣,深黯钓客,地脉花,锄地 +4点:丘丘人,丘丘萨满,丘丘人射手,丘丘暴徒,丘丘王,丘丘游侠,愚人众先遣队,萤术士,债务处理人,冬国仕女,愚人众风役人,愚人众特辖队,盗宝团,野伏众,海乱鬼,镀金旅团,黑蛇众,黯色空壳,部族龙形武士,遗迹机械,元能构装体,遗迹机兵,遗迹龙兽,发条机关,秘源机兵,巡陆艇,史莱姆,骗骗花,飘浮灵,蕈兽,浊水幻灵,原海异种,隙境原体,魔像禁卫,大灵显化身,熔岩游像,龙蜥,圣骸兽,玄文兽,纳塔龙众,炉壳山鼬,蕴光异兽,深渊法师,深渊使徒,兽境群狼,深邃拟覆叶,荒野狂猎,霜夜灵嗣,深黯钓客,地脉花,锄地,飞萤