mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-05-17 09:36:55 +08:00
* feat: 优化路径 * feat: 优化路径 * feat: 矿石数量检测 * feat: 临时注释背包检测 * fix: 修复问题 * feat: 优化路线 * feat: 优化路线
174 lines
4.9 KiB
JavaScript
174 lines
4.9 KiB
JavaScript
const REFRESH_DATA_PATH = "local/refresh_records.json"
|
||
const FALLBACK_DURATION = 60
|
||
|
||
/**
|
||
* 从本地文件加载刷新记录数据
|
||
*
|
||
* @returns {Object} 刷新记录对象,文件不存在或读取失败返回空对象
|
||
*/
|
||
function loadRefreshData() {
|
||
try {
|
||
const raw = file.readTextSync(REFRESH_DATA_PATH)
|
||
return JSON.parse(raw) || {}
|
||
} catch {
|
||
return {}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将刷新记录数据保存到本地文件
|
||
*
|
||
* @param {Object} data - 刷新记录对象
|
||
*/
|
||
function saveRefreshData(data) {
|
||
file.writeTextSync(REFRESH_DATA_PATH, JSON.stringify(data, null, 2))
|
||
}
|
||
|
||
/**
|
||
* 清理过期路线记录,删除文件已不存在的路线对应的记录
|
||
*
|
||
* @param {Object} data - 刷新记录对象
|
||
* @param {string[]} routePaths - 当前实际存在的路线文件路径数组
|
||
* @returns {Object} 清理后的刷新记录对象
|
||
*/
|
||
function cleanupStaleRecords(data, routePaths) {
|
||
const pathSet = new Set(routePaths)
|
||
const keys = Object.keys(data)
|
||
let removed = 0
|
||
for (const key of keys) {
|
||
if (!pathSet.has(key)) {
|
||
delete data[key]
|
||
removed++
|
||
}
|
||
}
|
||
if (removed > 0) {
|
||
log.info(`清理了 ${removed} 条过期路线记录`)
|
||
saveRefreshData(data)
|
||
}
|
||
return data
|
||
}
|
||
|
||
/**
|
||
* 记录路线完成时间与运行时长
|
||
* 兼容旧版纯时间戳格式,自动迁移为对象格式
|
||
*
|
||
* @param {string} routePath - 路线文件路径
|
||
* @param {Object} data - 刷新记录对象
|
||
* @param {number} duration - 本次运行时长(秒),0 或负数时不记录时长
|
||
*/
|
||
function recordRoute(routePath, data, duration) {
|
||
const existing = data[routePath]
|
||
if (existing && typeof existing === 'object') {
|
||
existing.t = Date.now()
|
||
if (duration > 0) existing.d = Math.round(duration)
|
||
} else {
|
||
data[routePath] = { t: Date.now(), d: duration > 0 ? Math.round(duration) : null }
|
||
}
|
||
saveRefreshData(data)
|
||
}
|
||
|
||
/**
|
||
* 判断路线的矿石是否已刷新
|
||
* 刷新规则:取上次运行时间最近的 UTC 16:00(每日重置),加上 refreshDays 天
|
||
*
|
||
* @param {string} routePath - 路线文件路径
|
||
* @param {Object} data - 刷新记录对象
|
||
* @param {number} refreshDays - 矿石刷新天数,默认 3 天
|
||
* @returns {boolean} 矿石是否已刷新,记录不存在视为已刷新
|
||
*/
|
||
function isRouteReady(routePath, data, refreshDays = 3) {
|
||
const record = data[routePath]
|
||
const lastRun = record?.t || (typeof record === 'number' ? record : null)
|
||
if (!lastRun) return true
|
||
|
||
const t = lastRun / 1000
|
||
let t0 = Math.floor(t / 86400) * 86400 + 57600
|
||
if (t0 > t) {
|
||
t0 -= 86400
|
||
}
|
||
const respawnTime = t0 + 86400 * refreshDays
|
||
return respawnTime < Date.now() / 1000
|
||
}
|
||
|
||
/**
|
||
* 过滤出已刷新可运行的路线
|
||
*
|
||
* @param {string[]} routePaths - 路线文件路径数组
|
||
* @param {Object} data - 刷新记录对象
|
||
* @param {number} refreshDays - 矿石刷新天数,默认 3 天
|
||
* @returns {string[]} 已刷新的路线文件路径数组
|
||
*/
|
||
function filterRunnableRoutes(routePaths, data, refreshDays = 3) {
|
||
const runnable = []
|
||
for (const routePath of routePaths) {
|
||
if (isRouteReady(routePath, data, refreshDays)) {
|
||
runnable.push(routePath)
|
||
} else {
|
||
const fileName = routePath.split('\\').pop()
|
||
log.info(`跳过未刷新路线: ${fileName}`)
|
||
}
|
||
}
|
||
return runnable
|
||
}
|
||
|
||
/**
|
||
* 获取路线的历史运行时长
|
||
*
|
||
* @param {string} routePath - 路线文件路径
|
||
* @param {Object} data - 刷新记录对象
|
||
* @returns {number|null} 历史运行时长(秒),无记录返回 null
|
||
*/
|
||
function getRouteDuration(routePath, data) {
|
||
const record = data[routePath]
|
||
if (!record) return null
|
||
if (typeof record === 'object' && record.d) return record.d
|
||
return null
|
||
}
|
||
|
||
/**
|
||
* 估算多条路线的总运行时长
|
||
* 有历史记录的路线使用实际时长,无记录的按 1 分钟计算
|
||
*
|
||
* @param {string[]} routePaths - 路线文件路径数组
|
||
* @param {Object} data - 刷新记录对象
|
||
* @returns {number} 估算总时长(秒)
|
||
*/
|
||
function estimateRoutesDuration(routePaths, data) {
|
||
let total = 0
|
||
for (const routePath of routePaths) {
|
||
const d = getRouteDuration(routePath, data)
|
||
total += d !== null ? d : FALLBACK_DURATION
|
||
}
|
||
return total
|
||
}
|
||
|
||
/**
|
||
* 将秒数格式化为可读时长
|
||
* 不足 1 小时显示 "xx分xx秒",超过 1 小时显示 "xx小时xx分xx秒"
|
||
*
|
||
* @param {number} seconds - 秒数
|
||
* @returns {string} 格式化后的时长字符串
|
||
*/
|
||
function formatDuration(seconds) {
|
||
seconds = Math.max(0, Math.round(seconds))
|
||
const h = Math.floor(seconds / 3600)
|
||
const m = Math.floor((seconds % 3600) / 60)
|
||
const s = seconds % 60
|
||
const mm = String(m).padStart(2, '0')
|
||
const ss = String(s).padStart(2, '0')
|
||
if (h > 0) return `${h}小时${mm}分${ss}秒`
|
||
return `${mm}分${ss}秒`
|
||
}
|
||
|
||
export {
|
||
loadRefreshData,
|
||
saveRefreshData,
|
||
cleanupStaleRecords,
|
||
recordRoute,
|
||
isRouteReady,
|
||
filterRunnableRoutes,
|
||
getRouteDuration,
|
||
estimateRoutesDuration,
|
||
formatDuration
|
||
}
|