mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-25 04:59:52 +08:00
feat(auto-tools): 添加路径记录功能和时间差计算
- 新增 RecordPath 对象用于记录路径信息 - 实现 saveRecordPaths 函数保存路径记录到文件 - 添加 getTimeDifference 函数计算时间差值 - 在路径执行完成后记录时间戳和路径信息 - 从 PathRecord.json 文件读取和解析路径记录 - 将 Set 数据结构转换为数组进行 JSON 序列化 - 重构 RecordLast 对象的 name 字段为 uid 字段 refactor(FullyAutoAndSemiAutoTools): 优化战斗队伍切换逻辑 - 修复了代码缩进和空格格式问题 - 重构了队伍切换条件判断逻辑 - 添加了战斗模式下的队伍切换功能 - 统一了代码风格和命名规范 feat(team): 添加战斗策略配置和队伍切换逻辑 - 在team对象中添加fightName属性用于存储战斗策略名称 - 实现战斗模式下的队伍切换功能,当fight为true时使用fightName进行队伍切换 - 添加战斗策略配置验证,未配置战斗策略时抛出错误 - 保留原有的七元素队伍切换逻辑,在非战斗模式下继续使用 - 添加详细的日志记录以跟踪队伍切换过程 feat(auto-tool): 添加战斗需求检测和自动战斗功能 - 实现战斗需求检查逻辑,检测路径是否需要配置战斗策略 - 添加战斗状态标记和管理机制 - 集成自动战斗任务执行功能 - 优化路径执行流程,在需要时自动启动战斗模式 - 添加战斗状态重置机制确保正确清理 - 完善错误处理和日志记录功能
This commit is contained in:
@@ -17,9 +17,10 @@ let PATH_JSON_LIST = new Array()
|
||||
const config_root = 'config'
|
||||
// 定义记录文件的路径
|
||||
let RecordText = `${config_root}\\record.json`
|
||||
let RecordPathText = `${config_root}\\PathRecord.json`
|
||||
let RecordList = new Array()
|
||||
let RecordLast = {
|
||||
name: "",
|
||||
uid: "",
|
||||
data: undefined,
|
||||
timestamp: 0,
|
||||
paths: new Set(), // 记录路径
|
||||
@@ -34,6 +35,11 @@ const Record = {
|
||||
errorPaths: new Set(), // 记录错误路径
|
||||
groupPaths: new Set(), // 记录分组路径
|
||||
}
|
||||
let RecordPath = {
|
||||
uid: "",
|
||||
paths: new Set(), // 记录路径
|
||||
//{timestamp,path}
|
||||
}
|
||||
const config_list = {
|
||||
black: [],
|
||||
white: [],
|
||||
@@ -57,10 +63,31 @@ const SevenElement = {
|
||||
const team = {
|
||||
current: undefined,
|
||||
fight: false,
|
||||
fightName: settings.teamFight,
|
||||
fightKeys: ['锄地专区', "敌人与魔物"],
|
||||
SevenElements: settings.teamSevenElements ? settings.teamSevenElements.split(',').map(item => item.trim()) : [],
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录路径的函数
|
||||
* 该函数将RecordPath对象中的Set类型数据转换为数组后保存到文件
|
||||
*/
|
||||
async function saveRecordPaths() {
|
||||
// 保存前将 Set 转换为数组,因为JSON不支持Set类型
|
||||
// 创建一个新的记录对象,包含原始记录的所有属性
|
||||
const recordToSave = {
|
||||
// 使用展开运算符复制Record对象的所有属性,保持其他数据不变
|
||||
...RecordPath,
|
||||
// 将paths Set转换为数组,以便能够序列化为JSON
|
||||
paths: [...RecordPath.paths].map(item => ({
|
||||
// 保留name属性
|
||||
timestamp: item.timestamp,
|
||||
// 将item中的paths Set转换为数组
|
||||
path: item.path
|
||||
}))
|
||||
};
|
||||
// 将记录列表转换为JSON字符串并同步写入文件
|
||||
file.writeTextSync(RecordText, JSON.stringify(recordToSave))
|
||||
}
|
||||
/**
|
||||
* 保存当前记录到记录列表并同步到文件
|
||||
* 该函数在保存前会将Set类型的数据转换为数组格式,确保JSON序列化正常进行
|
||||
@@ -89,6 +116,98 @@ function saveRecord() {
|
||||
file.writeTextSync(RecordText, JSON.stringify(RecordList))
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个时间之间的差值,并返回指定格式的JSON
|
||||
* @param {number|Date} startTime - 开始时间(时间戳或Date对象)
|
||||
* @param {number|Date} endTime - 结束时间(时间戳或Date对象)
|
||||
* @returns {Object} diff_json - 包含info和total的对象
|
||||
*/
|
||||
function getTimeDifference(startTime, endTime) {
|
||||
// 确保输入是时间戳
|
||||
const start = typeof startTime === 'object' ? startTime.getTime() : startTime;
|
||||
const end = typeof endTime === 'object' ? endTime.getTime() : endTime;
|
||||
|
||||
// 计算总差值(毫秒)
|
||||
const diffMs = Math.abs(end - start);
|
||||
|
||||
// 计算总时间(小数)
|
||||
const totalSeconds = diffMs / 1000;
|
||||
const totalMinutes = totalSeconds / 60;
|
||||
const totalHours = totalSeconds / 3600;
|
||||
|
||||
// 计算info部分(整数)
|
||||
const infoHours = Math.floor(totalHours % 24);
|
||||
const remainingAfterHours = (totalHours % 24) - infoHours;
|
||||
const infoMinutes = Math.floor(remainingAfterHours * 60);
|
||||
const remainingAfterMinutes = (remainingAfterHours * 60) - infoMinutes;
|
||||
const infoSeconds = Math.floor(remainingAfterMinutes * 60);
|
||||
// 输出类似:
|
||||
// {
|
||||
// info: { hours: 1, minutes: 0, seconds: 0 },
|
||||
// total: { hours: 1, minutes: 60, seconds: 3600 }
|
||||
// }
|
||||
const diff_json = {
|
||||
info: {
|
||||
hours: infoHours,
|
||||
minutes: infoMinutes,
|
||||
seconds: infoSeconds
|
||||
},
|
||||
total: {
|
||||
hours: parseFloat(totalHours.toFixed(6)),
|
||||
minutes: parseFloat(totalMinutes.toFixed(6)),
|
||||
seconds: parseFloat(totalSeconds.toFixed(6))
|
||||
}
|
||||
};
|
||||
|
||||
return diff_json;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算两个时间之间的差值,并返回指定格式的JSON
|
||||
* @param {number|Date} startTime - 开始时间(时间戳或Date对象)
|
||||
* @param {number|Date} endTime - 结束时间(时间戳或Date对象)
|
||||
* @returns {Object} diff_json - 包含info和total的对象
|
||||
*/
|
||||
function getTimeDifference(startTime, endTime) {
|
||||
// 确保输入是时间戳
|
||||
const start = typeof startTime === 'object' ? startTime.getTime() : startTime;
|
||||
const end = typeof endTime === 'object' ? endTime.getTime() : endTime;
|
||||
|
||||
// 计算总差值(毫秒)
|
||||
const diffMs = Math.abs(end - start);
|
||||
|
||||
// 计算总小时、分钟、秒(允许小数)
|
||||
const totalSeconds = diffMs / 1000;
|
||||
const totalHours = totalSeconds / 3600;
|
||||
const totalMinutes = totalSeconds / 60;
|
||||
// 计算剩余小时、分钟、秒(即去掉完整天数后的部分)
|
||||
const infoHours = totalHours % 24;
|
||||
const infoMinutes = totalMinutes;
|
||||
const infoSeconds = totalSecs;
|
||||
|
||||
const diff_json = {
|
||||
info: {
|
||||
hours: infoHours,
|
||||
minutes: infoMinutes,
|
||||
seconds: infoSeconds
|
||||
},
|
||||
total: {
|
||||
hours: totalHours,
|
||||
minutes: totalMinutes,
|
||||
seconds: totalSecs
|
||||
}
|
||||
};
|
||||
|
||||
return diff_json;
|
||||
}
|
||||
|
||||
// 输出类似:
|
||||
// {
|
||||
// info: { hours: 整数, minutes: 小时后的整数, seconds: 分种后的整数 },
|
||||
// total: {全是小数 hours: 1.1, minutes: 算出总分钟, seconds: 算出总秒 }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 初始化记录函数
|
||||
* 该函数用于初始化一条新的记录,包括设置UID、时间戳和调整后的日期数据
|
||||
@@ -122,7 +241,28 @@ async function initRecord() {
|
||||
} catch (e) {
|
||||
// 如果读取文件出错,则忽略错误(可能是文件不存在或格式错误)
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试读取记录文件
|
||||
// 读取后将数组转换回 Set,处理特殊的数据结构
|
||||
RecordPath = JSON.parse(file.readTextSync(RecordPathText), (key, value) => {
|
||||
// 处理分组路径集合,保持嵌套的Set结构
|
||||
if (key === 'paths') {
|
||||
return new Set(value.map(item => ({
|
||||
timestamp: item.timestamp,
|
||||
path: item.path
|
||||
})));
|
||||
}
|
||||
return value;
|
||||
}).find(item => item.uid === Record.uid)
|
||||
} catch (e) {
|
||||
// 如果读取文件出错,则忽略错误(可能是文件不存在或格式错误)
|
||||
}
|
||||
if (RecordPath?.uid) {
|
||||
RecordPath.uid = Record.uid
|
||||
}
|
||||
if (RecordPath?.paths) {
|
||||
RecordPath.paths = new Set()
|
||||
}
|
||||
// 如果记录列表不为空,则查找最新记录
|
||||
if (RecordList.length > 0) {
|
||||
// 最优解:一次遍历找到最新的记录
|
||||
@@ -663,59 +803,81 @@ async function runPath(path, stopKey = AUTO_STOP) {
|
||||
log.info(`[{mode}] 路径已执行: {path},跳过执行`, settings.mode, path)
|
||||
return
|
||||
}
|
||||
|
||||
const entry = [...SevenElement.SevenElementsMap.entries()].find(([key, val]) => {
|
||||
return val.some(item => path.includes(`\\${item}\\`));
|
||||
});
|
||||
if (entry) {
|
||||
const [key, val] = entry;
|
||||
const index = SevenElement.SevenElements.indexOf(key);
|
||||
const teamName = team.SevenElements.length > index && index >= 0 ?
|
||||
team.SevenElements[index] : undefined;
|
||||
|
||||
if (!teamName || teamName === "") {
|
||||
log.debug(`[{mode}] 没有设置队伍: {teamName},跳过切换`, settings.mode, teamName);
|
||||
} else if (team.current === teamName) {
|
||||
log.debug(`[{mode}] 当前队伍为: {teamName},无需切换`, settings.mode, teamName);
|
||||
} else {
|
||||
log.info(`[{mode}] 检测到需要: {key},切换至{val}`, settings.mode, key, teamName);
|
||||
const teamSwitch = await switchUtil.SwitchPartyMain(teamName);
|
||||
//检查战斗需求
|
||||
try {
|
||||
if (!team.fight) {
|
||||
const one = JSON.parse(file.readTextSync(path))
|
||||
if (one.info?.description?.includes("请配置好战斗策略")) {
|
||||
log.warn(`[{mode}] 路径需要配置好战斗策略: {path},如已配置请忽略`, settings.mode, path)
|
||||
team.fight = true
|
||||
} else if (team.fightKeys.some(item => path.includes(`\\${item}\\`))) {
|
||||
team.fight = true
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
log.error("检查战斗需求失败: {error}", error.message);
|
||||
}
|
||||
//切换队伍
|
||||
if (team.fight) {
|
||||
if (!team.fightName) {
|
||||
log.error(`[{mode}] 路径需要配置好战斗策略: {path}`, settings.mode, path)
|
||||
throw new Error(`路径需要配置好战斗策略: ` + path)
|
||||
} else if (team.current !== team.fightName) {
|
||||
log.info(`[{mode}] 检测到需要战斗,切换至{teamName}`, team.fightName);
|
||||
const teamSwitch = await switchUtil.SwitchPartyMain(team.fightName);
|
||||
if (teamSwitch) {
|
||||
team.current = teamSwitch;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const entry = [...SevenElement.SevenElementsMap.entries()].find(([key, val]) => {
|
||||
return val.some(item => path.includes(`\\${item}\\`));
|
||||
});
|
||||
if (entry) {
|
||||
const [key, val] = entry;
|
||||
const index = SevenElement.SevenElements.indexOf(key);
|
||||
const teamName = team.SevenElements.length > index && index >= 0 ?
|
||||
team.SevenElements[index] : undefined;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
if (!team.fight){
|
||||
// const entry = team.fightKeys.find(([key, val]) => {
|
||||
// return val.some(item => path.includes(`\\${item}\\`));
|
||||
// });
|
||||
// if (entry) {
|
||||
// dispatcher.addTrigger(new RealtimeTimer("AutoPick", {"forceInteraction": true}));
|
||||
// await dispatcher.runAutoFightTask(new AutoFightParam());
|
||||
// team.fight = true;
|
||||
// }
|
||||
const one = JSON.parse(file.readTextSync(path))
|
||||
if (one.info && one.info.description.includes("请配置好战斗策略")) {
|
||||
log.warn(`[{mode}] 路径需要配置好战斗策略: {path},如已配置请忽略`, settings.mode, path)
|
||||
if (!teamName || teamName === "") {
|
||||
log.debug(`[{mode}] 没有设置队伍: {teamName},跳过切换`, settings.mode, teamName);
|
||||
} else if (team.current === teamName) {
|
||||
log.debug(`[{mode}] 当前队伍为: {teamName},无需切换`, settings.mode, teamName);
|
||||
} else {
|
||||
log.info(`[{mode}] 检测到需要: {key},切换至{val}`, settings.mode, key, teamName);
|
||||
const teamSwitch = await switchUtil.SwitchPartyMain(teamName);
|
||||
if (teamSwitch) {
|
||||
team.current = teamSwitch;
|
||||
}
|
||||
}
|
||||
} else if (team.current !== team.fightName) {
|
||||
const teamSwitch = await switchUtil.SwitchPartyMain(team.fightName);
|
||||
if (teamSwitch) {
|
||||
team.current = teamSwitch;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// log.error("路径执行失败: {path}, 错误: {error}", path, error.message)
|
||||
// return
|
||||
}
|
||||
|
||||
//切换队伍-end
|
||||
try {
|
||||
log.debug("开始执行路径: {path}", path)
|
||||
await pathingScript.runFile(path)
|
||||
if (team.fight) {
|
||||
//启用战斗
|
||||
await dispatcher.runAutoFightTask(new AutoFightParam());
|
||||
}
|
||||
log.debug("路径执行完成: {path}", path)
|
||||
RecordPath.paths.add({timestamp: Date.now(), path: path})
|
||||
await saveRecordPaths()
|
||||
Record.paths.add(path)
|
||||
Record.errorPaths.delete(path)
|
||||
} catch (error) {
|
||||
Record.errorPaths.add(path)
|
||||
log.error("路径执行失败: {path}, 错误: {error}", path, error.message)
|
||||
} finally {
|
||||
if (team.fight) {
|
||||
// 重置战斗状态
|
||||
team.fight = false
|
||||
}
|
||||
}
|
||||
|
||||
if (SEMI_AUTO) {
|
||||
|
||||
@@ -46,6 +46,11 @@
|
||||
],
|
||||
"default": "全自动"
|
||||
},
|
||||
{
|
||||
"name": "teamFight",
|
||||
"type": "input-text",
|
||||
"label": "战斗队伍配置(同时也是行走队伍配置)"
|
||||
},
|
||||
{
|
||||
"name": "teamSevenElements",
|
||||
"type": "input-text",
|
||||
|
||||
Reference in New Issue
Block a user