@@ -1,81 +1,80 @@
( async function ( ) {
const folderA = 'assets/狗粮A线@Yang-z/' ;
const folderB = 'assets/狗粮B线@Yang-z/' ;
const folderE = 'assets/狗粮额外@Yang-z/' ;
const folderA = 'assets/狗粮A线@Yang-z/' ;
const folderB = 'assets/狗粮B线@Yang-z/' ;
const folderE = 'assets/狗粮额外@Yang-z/' ;
const pathingA = [
"狗粮-蒙德-龙脊雪山-西-3个-f.json" ,
"狗粮-璃月-碧水源-盐中之地-3个-f.json" ,
"狗粮-璃月-珉林-东北-9个-f.json" ,
"狗粮-璃月-珉林-北-5个.json" ,
"狗粮-璃月-珉林-奥藏山南-2个/ 3个-f.json" ,
"狗粮-璃月-珉林-绝云间-3个-m.json" ,
"(恢复)狗粮-璃月-琼玑野.json" ,
"狗粮-璃月-琼玑野-绿华池-3个-f.json" ,
"狗粮-须弥-须弥城-4个.json" ,
"狗粮-须弥-二净甸-七天神像-4个/ 8个.json" ,
"狗粮-须弥-二净甸-觉王之殿南-6个/ 7个-f.json" ,
"(恢复)狗粮-须弥-失落的苗圃.json" ,
"狗粮-须弥-失落的苗圃-南-8个-f.json" ,
"狗粮-纳塔-万火之瓯-竞技场东-2个/ 4个-f.json" ,
"狗粮-纳塔-涌流地-流泉之众-4个.json" ,
"(恢复)狗粮-纳塔-涌流地.json" ,
"狗粮-纳塔-镜璧山-南-9个-f.json" ,
"狗粮-纳塔-镜璧山-七天神像下-3个-f.json" ,
"狗粮-纳塔-翘枝崖-北-6个-f.json" ,
"狗粮-纳塔-奥奇卡纳塔-七天神像-14个.json" ,
"狗粮-纳塔-奥奇卡纳塔-流灰之街-4个-f.json" ,
"狗粮-纳塔-奥奇卡纳塔-托佐兹之岛-6个-f.json" ,
"(恢复)狗粮-稻妻-神无冢.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂①-6个/ 21个-f.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂②-7个/ 21个-f.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂③-8个/ 21个-f.json"
] ; // 98+21个
const pathingA = [
"狗粮-蒙德-龙脊雪山-西-3个-f.json" ,
"狗粮-璃月-碧水源-盐中之地-3个-f.json" ,
"狗粮-璃月-珉林-东北-9个-f.json" ,
"狗粮-璃月-珉林-北-5个.json" ,
"狗粮-璃月-珉林-奥藏山南-2个/ 3个-f.json" ,
"狗粮-璃月-珉林-绝云间-3个-m.json" ,
"(恢复)狗粮-璃月-琼玑野.json" ,
"狗粮-璃月-琼玑野-绿华池-3个-f.json" ,
"狗粮-须弥-须弥城-4个.json" ,
"狗粮-须弥-二净甸-七天神像-4个/ 8个.json" ,
"狗粮-须弥-二净甸-觉王之殿南-6个/ 7个-f.json" ,
"(恢复)狗粮-须弥-失落的苗圃.json" ,
"狗粮-须弥-失落的苗圃-南-8个-f.json" ,
"狗粮-纳塔-万火之瓯-竞技场东-2个/ 4个-f.json" ,
"狗粮-纳塔-涌流地-流泉之众-4个.json" ,
"(恢复)狗粮-纳塔-涌流地.json" ,
"狗粮-纳塔-镜璧山-南-9个-f.json" ,
"狗粮-纳塔-镜璧山-七天神像下-3个-f.json" ,
"狗粮-纳塔-翘枝崖-北-6个-f.json" ,
"狗粮-纳塔-奥奇卡纳塔-七天神像-14个.json" ,
"狗粮-纳塔-奥奇卡纳塔-流灰之街-4个-f.json" ,
"狗粮-纳塔-奥奇卡纳塔-托佐兹之岛-6个-f.json" ,
"(恢复)狗粮-稻妻-神无冢.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂①-6个/ 21个-f.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂②-7个/ 21个-f.json" ,
"【收尾】狗粮-稻妻-神无冢-踏鞴砂③-8个/ 21个-f.json"
] ; // 98+21个
const pathingB = [
"狗粮-枫丹-枫丹庭区-3个.json" ,
"狗粮-枫丹-白露区-秋分山东侧-2个-f~m.json" ,
"狗粮-枫丹-伊黎耶林区-欧庇克莱歌剧院东南-2个-f.json" ,
"(恢复)狗粮-枫丹-研究院区.json" ,
"狗粮-枫丹-研究院区-学术会堂-1个/ 2个-f.json" ,
"狗粮-枫丹-研究院区-中央实验室遗址-北侧屋内-4个.json" ,
"狗粮-枫丹-研究院区-新枫丹科学院-东南侧-8个-f.json" ,
"狗粮-枫丹-研究院区-西南偏南-6个-m-f.json" ,
"狗粮-枫丹-研究院区-西南偏西-4个-f.json" ,
"狗粮-枫丹-研究院区-西北-6个/ 7个.json" ,
"狗粮-枫丹-研究院区-中部塔内-9个.json" ,
"(恢复)狗粮-枫丹-黎翡区.json" ,
"狗粮-枫丹-黎翡区-七天神像-3个/ 5个.json" ,
"狗粮-枫丹-黎翡区-芒索斯山东-3个-f.json" ,
"狗粮-稻妻-神无冢-堇色之庭-4个.json" ,
"狗粮-稻妻-神无冢-九条阵屋-2个/ 3个-f.json" ,
"狗粮-稻妻-神无冢-东-5个/ 6个-f.json" ,
"(恢复)狗粮-稻妻-神无冢.json" ,
"狗粮-稻妻-海祇岛-东方小岛-2个-f.json" ,
"狗粮-稻妻-海祇岛-珊瑚宫东北-6个-f.json" ,
"狗粮-稻妻-海祇岛-望泷村西南-4个-f.json" ,
"狗粮-稻妻-清籁岛-浅濑神社-3个-f.json" ,
"狗粮-稻妻-清籁岛-越石村-8个-f.json" ,
"狗粮-稻妻-清籁岛-平海砦西-8个-f.json" ,
"狗粮-稻妻-鹤观-东偏中-2个-f.json" ,
"狗粮-稻妻-鹤观-南-2个-f.json" ,
"(恢复)狗粮-稻妻-清籁岛.json" ,
"【收尾】狗粮-稻妻-清籁岛-清籁丸-20个-f.json"
] ; // 97+20个
const pathingB = [
"狗粮-枫丹-枫丹庭区-3个.json" ,
"狗粮-枫丹-白露区-秋分山东侧-2个-f~m.json" ,
"狗粮-枫丹-伊黎耶林区-欧庇克莱歌剧院东南-2个-f.json" ,
"(恢复)狗粮-枫丹-研究院区.json" ,
"狗粮-枫丹-研究院区-学术会堂-1个/ 2个-f.json" ,
"狗粮-枫丹-研究院区-中央实验室遗址-北侧屋内-4个.json" ,
"狗粮-枫丹-研究院区-新枫丹科学院-东南侧-8个-f.json" ,
"狗粮-枫丹-研究院区-西南偏南-6个-m-f.json" ,
"狗粮-枫丹-研究院区-西南偏西-4个-f.json" ,
"狗粮-枫丹-研究院区-西北-6个/ 7个.json" ,
"狗粮-枫丹-研究院区-中部塔内-9个.json" ,
"(恢复)狗粮-枫丹-黎翡区.json" ,
"狗粮-枫丹-黎翡区-七天神像-3个/ 5个.json" ,
"狗粮-枫丹-黎翡区-芒索斯山东-3个-f.json" ,
"狗粮-稻妻-神无冢-堇色之庭-4个.json" ,
"狗粮-稻妻-神无冢-九条阵屋-2个/ 3个-f.json" ,
"狗粮-稻妻-神无冢-东-5个/ 6个-f.json" ,
"(恢复)狗粮-稻妻-神无冢.json" ,
"狗粮-稻妻-海祇岛-东方小岛-2个-f.json" ,
"狗粮-稻妻-海祇岛-珊瑚宫东北-6个-f.json" ,
"狗粮-稻妻-海祇岛-望泷村西南-4个-f.json" ,
"狗粮-稻妻-清籁岛-浅濑神社-3个-f.json" ,
"狗粮-稻妻-清籁岛-越石村-8个-f.json" ,
"狗粮-稻妻-清籁岛-平海砦西-8个-f.json" ,
"狗粮-稻妻-鹤观-东偏中-2个-f.json" ,
"狗粮-稻妻-鹤观-南-2个-f.json" ,
"(恢复)狗粮-稻妻-清籁岛.json" ,
"【收尾】狗粮-稻妻-清籁岛-清籁丸-20个-f.json"
] ; // 97+20个
const pathingE = [
"【额外】狗粮-纳塔-鸡屁股+8个/ 9个-f.json" , // 12小时刷新
] ; // 7个
const pathingE = [
"【额外】狗粮-纳塔-鸡屁股+8个/ 9个-f.json" , // 12小时刷新
] ; // 7个
const pathingE _A = [
"【额外】狗粮-须弥-水天丛林+7个-f.json" , // 24小时刷新
"【额外】狗粮-枫丹-研究院区-新枫丹科学院周边+3个-f.json" , // 24小时刷新
] ; // 10个
const pathingE _A = [
"【额外】狗粮-须弥-水天丛林+7个-f.json" , // 24小时刷新
"【额外】狗粮-枫丹-研究院区-新枫丹科学院周边+3个-f.json" , // 24小时刷新
] ; // 10个
const pathingE _B = [
"【额外】狗粮-纳塔-灵谜纹+13个.json" // 24小时刷新
] ; // 13个
const pathingE _B = [
"【额外】狗粮-纳塔-灵谜纹+13个.json" // 24小时刷新
] ; // 13个
// 每日拾取点位数及耗时
// A: (98 + 21) + (8 + 10) = 137 ~ 31 + 10 = 41 minutes
@@ -91,35 +90,49 @@
let autoSalvage4 = settings . autoSalvage4 != undefined && settings . autoSalvage4 != '否' ? true : false ;
let autoSalvageSpan = settings . autoSalvageSpan != undefined && ~ ~ settings . autoSalvageSpan > 0 ? ~ ~ settings . autoSalvageSpan : 10 ;
let activeRestore = settings . activeRestore != undefined && settings . activeRestore != '是' ? false : true ;
const activeProgress = settings . activeProgress != undefined && settings . activeProgress != '否' ? true : false ;
log . debug ( ` path: ${ path } ; swapPath: ${ swapPath } ; extra: ${ extra } ; extraAB: ${ extraAB } ; autoSalvage: ${ autoSalvage } ; autoSalvage4: ${ autoSalvage4 } ; autoSalvageSpan: ${ autoSalvageSpan } ; activeRestore: ${ activeRestore } ; ` ) ;
// await sleep(30000);
// 路线
function determinePath ( ) {
if ( path != 'A' && path != 'B' ) {
const benchmark = new Date ( "2024-11-20T04:00:00" ) ;
const now = new Date ( ) ;
const delta = now - benchmark ;
const days = delta / ( 1000 * 60 * 60 * 24 ) ;
path = days % 2 < 1 ? 'A' : 'B' ;
// 确定路径
function determinePath ( ) {
if ( path != 'A' && path != 'B' ) {
const benchmark = new Date ( "2024-11-20T04:00:00" ) ;
const now = new Date ( ) ;
const delta = now - benchmark ;
const days = delta / ( 1000 * 60 * 60 * 24 ) ;
path = days % 2 < 1 ? 'A' : 'B' ;
if ( swapPath ) path = path == 'A' ? 'B' : 'A' ;
}
if ( swapPath ) path = path == 'A' ? 'B' : 'A' ;
}
// 初始化
async function init ( shouldRestore = true , shouldResizeMap = false ) {
// close forced interaction just in case..
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : false } ) ) ;
// restore and alignment
if ( shouldRestore ) await genshin . tp ( "1468.0732421875" , "1998.04443359375" ) ; await sleep ( 3000 ) ;
// resize map here (not necessary after bgi v0.41.0)
if ( shouldResizeMap ) await resizeMap ( ) ;
// 如果路径切换,清理与当前路径无关的任务记录
if ( progress . path != = path ) {
progress . completedTasks = [ ] ;
progress . path = path ;
saveProgress ( ) ; // 保存新的路径和清理后的任务记录
}
}
// 初始化函数
async function init ( shouldRestore = true , shouldResizeMap = false ) {
// 关闭强制交互
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : false } ) ) ;
// 恢复和对齐
if ( shouldRestore ) {
await genshin . tp ( "1468.0732421875" , "1998.04443359375" ) ;
await sleep ( 3000 ) ;
}
// 调整地图缩放 (bgi[v0.41.0]后不需要)
if ( shouldResizeMap ) {
await resizeMap ( ) ;
}
}
// 调整地图
async function resizeMap ( level = 1 ) {
@@ -166,110 +179,208 @@
await genshin . tp ( data [ 'positions' ] [ 0 ] [ 'x' ] , data [ 'positions' ] [ 0 ] [ 'y' ] ) ;
}
// 分解圣遗物
async function salvage ( ) {
if ( ! autoSalvage ) return ;
// 分解圣遗物
async function salvage ( ) {
if ( ! autoSalvage ) return ;
await genshin . returnMainUi ( ) ;
keyPress ( "B" ) ;
await sleep ( 2000 ) ;
click ( 670 , 40 ) ;
await sleep ( 1000 ) ; // 圣遗物
click ( 660 , 1010 ) ;
await sleep ( 1000 ) ; // 分解
click ( 300 , 1020 ) ;
await sleep ( 1000 ) ; // 快速选择
await genshin . returnMainUi ( ) ;
keyPress ( "B" ) ; await sleep ( 200 0) ;
click ( 670 , 40 ) ; await sleep ( 10 00) ; // 圣遗物
click ( 660 , 1010 ) ; await sleep ( 1000 ) ; // 分解
click ( 300 , 1020 ) ; await sleep ( 1000 ) ; // 快速选择
// click(200, 140); await sleep(500); // 1
// click(200, 220); await sleep(500); // 2
// click(200, 300); await sleep(500); // 3
if ( ! autoSalvage4 ) { click ( 200 , 380 ) ; await sleep ( 500 ) ; } // 4
click ( 340 , 1000 ) ; await sleep ( 1000 ) ; // 确认选择
click ( 1720 , 1015 ) ; await sleep ( 1500 ) ; // 分解
click ( 1180 , 750 ) ; await sleep ( 1000 ) ; // 进行分解
click ( 1840 , 45 ) ; await sleep ( 1500 ) ; // 取消
click ( 1840 , 45 ) ; await sleep ( 1000 ) ; // 取消
click ( 1840 , 45 ) ; await sleep ( 1000 ) ; // 取消
// 点击4星圣遗物
if ( ! autoSalvage4 ) {
click ( 200 , 38 0) ;
await sleep ( 5 00) ;
}
// 单一脚本执行
let count = 0 ;
async function runFile ( filePath , times = 2 ) {
try {
-- times ;
click ( 340 , 1000 ) ;
await sleep ( 1000 ) ; // 确认选择
click ( 1720 , 1015 ) ;
await sleep ( 1500 ) ; // 分解
click ( 1320 , 750 ) ;
await sleep ( 1000 ) ; // 进行分解
// 如关闭主动去神像恢复, 则依赖队伍配置持续恢复角色, 及bgi的低血量被动恢复
let isToRestore = filePath . search ( "(恢复)" ) != - 1 ;
if ( isToRestore && ! activeRestore ) return ;
await genshin . returnMainUi ( ) ;
}
// 暂不支持关闭自动拾取
// if (isToRestore) dispatcher.removeTimer(...);
// else...
// 进度文件路径
const progressFile = "progress.json" ;
// 分解圣遗物
if ( ! isToRestore && count ++ % autoSalvageSpan == 0 ) await salvage ( ) ;
// 初始化进度
let progress = {
path : null ,
completedTasks : [ ] ,
lastRunDate : null // 记录上次运行的日期
} ;
// 调整地图缩放 (bgi[v0.41.0]后不需要)
// let shouldResizeMap = filePath.search("-m") != -1;
// if (shouldResizeMap) await resizeMap();
// 读取进度
async function loadProgress ( ) {
try {
const content = await file . readText ( progressFile ) ;
const loadedProgress = JSON . parse ( content ) ;
// 配置自动拾取,根据文件名指定信息,确定是否强制交互(快速拾取)
let forceInteraction = filePath . search ( "-f" ) != - 1 ; //
if ( ! isToRestore ) dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : forceInteraction } ) ) ;
//执行路径追踪脚本
log . info ( filePath ) ;
await pathingScript . runFile ( filePath ) ;
// 配置强制拾取为关闭状态
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : false } ) ) ;
// 地图缩放按键同某些地图标识重叠,导致识别失败(bgi[v0.43.0]后引入)
// // 完成路径后,放大地图,脚本中调用就近传送。仍可能被缩小回去。不可行
// let shouldResizeMap_after = filePath.search("~m") != -1;
// if (shouldResizeMap_after) {
// await resizeMap(0);
// await tpNearby(filePath);
// }
// 完成路径后,拖拽地图,脚本中调用就近传送。可行
let shouldDragMap _after = filePath . search ( "~m" ) != - 1 ;
if ( shouldDragMap _after ) {
await dragMap ( - 50 , 50 ) ;
await tpNearby ( filePath ) ;
}
// 检查日期是否一致
const now = new Date ( ) ;
const today = now . toISOString ( ) . split ( 'T' ) [ 0 ] ; // 当前日期( YYYY-MM-DD)
const lastRunDate = loadedProgress . lastRunDate ;
if ( lastRunDate && lastRunDate === today ) {
// 如果日期一致,加载进度
progress . path = loadedProgress . path ;
progress . completedTasks = Array . isArray ( loadedProgress . completedTasks ) ? loadedProgress . completedTasks : [ ] ;
} else {
// 如果日期不一致,重置进度
progress . path = null ;
progress . completedTasks = [ ] ;
}
catch ( error ) { // bgi已捕获可预期异常, 此处仅做兜底
log . error ( error . toString ( ) ) ;
await sleep ( 3000 ) ;
if ( times > 0 ) await runFile ( filePath , times ) ;
progress . lastRunDate = today ; // 更新当前日期
log . info ( "加载进度成功:" , progress ) ;
} catch ( error ) {
log . error ( "加载进度失败:" , error ) ;
}
}
// 保存进度
async function saveProgress ( ) {
try {
progress . lastRunDate = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ; // 更新当前日期
await file . writeText ( progressFile , JSON . stringify ( progress ) ) ;
log . info ( "进度已保存。" ) ;
} catch ( error ) {
log . error ( "保存进度失败:" , error ) ;
}
}
let count = 0 ; // 用于记录分解圣遗物的次数
async function runFile ( filePath , times = 2 ) {
try {
// 检查任务是否已经完成
if ( progress . completedTasks . includes ( filePath ) ) {
log . info ( ` 任务已跳过: ${ filePath } ` ) ;
return ;
}
// 记录任务开始时间
const startTime = Date . now ( ) ;
log . info ( ` 开始执行任务: ${ filePath } ` ) ;
// 检查是否是恢复任务
let isToRestore = filePath . search ( "(恢复)" ) != - 1 ;
if ( isToRestore && ! activeRestore ) {
log . info ( ` 跳过恢复任务: ${ filePath } ` ) ;
return ;
}
// 分解圣遗物
if ( ! isToRestore && count ++ % autoSalvageSpan == 0 ) {
await salvage ( ) ;
}
// 调整地图缩放 (bgi[v0.41.0]后不需要)
// let shouldResizeMap = filePath.search("-m") != -1;
// if (shouldResizeMap) await resizeMap();
// 配置自动拾取,根据文件名指定信息,确定是否强制交互(快速拾取)
let forceInteraction = filePath . search ( "-f" ) != - 1 ;
if ( ! isToRestore ) dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : forceInteraction } ) ) ;
// 执行任务
await pathingScript . runFile ( filePath ) ;
await sleep ( 1000 ) ;
// 配置强制拾取为关闭状态
dispatcher . addTimer ( new RealtimeTimer ( "AutoPick" , { "forceInteraction" : false } ) ) ;
// 记录任务结束时间
const endTime = Date . now ( ) ;
const duration = endTime - startTime ; // 任务运行时长(毫秒)
// 判断任务是否成功完成
if ( duration < 5000 ) { // 假设任务运行时长小于5秒则认为任务被取消或异常终止
log . info ( ` 任务运行时长过短( ${ duration } ms) , 可能被取消或异常终止, 不保存进度: ${ filePath } ` ) ;
return ;
}
// 任务成功完成,更新进度
progress . completedTasks . push ( filePath ) ;
await saveProgress ( ) ;
log . info ( ` 任务成功完成并保存进度: ${ filePath } ` ) ;
// 地图缩放按键同某些地图标识重叠,导致识别失败(bgi[v0.43.0]后引入)
// // 完成路径后,放大地图,脚本中调用就近传送。仍可能被缩小回去。不可行
// let shouldResizeMap_after = filePath.search("~m") != -1;
// if (shouldResizeMap_after) {
// await resizeMap(0);
// await tpNearby(filePath);
// }
// 完成路径后,拖拽地图,脚本中调用就近传送。可行
let shouldDragMap _after = filePath . search ( "~m" ) != - 1 ;
if ( shouldDragMap _after ) {
await dragMap ( - 50 , 50 ) ;
await tpNearby ( filePath ) ;
}
} catch ( error ) {
// 任务失败,记录错误但不保存进度
log . error ( ` 任务执行失败: ${ filePath } ` , error ) ;
await sleep ( 3000 ) ;
if ( times > 0 ) {
log . info ( ` 任务失败,尝试重新执行: ${ filePath } ` ) ;
await runFile ( filePath , times - 1 ) ;
} else {
log . info ( ` 任务失败,不再重试: ${ filePath } ` ) ;
}
}
}
// 批量执行
async function batch ( folder , files ) {
for ( let file of files ) {
const filePath = folder + file ;
await runFile ( filePath ) ;
// 批量执行
async function batch ( folder , files ) {
for ( let file of files ) {
const filePath = folder + file ;
await runFile ( filePath ) ;
}
}
// 主函数
( async function ( ) {
// 如果 activeProgress 为否,则直接写入一个空对象到进度文件
if ( ! activeProgress ) {
// 写入空对象到进度文件
const result = await file . writeText ( progressFile , JSON . stringify ( { } ) ) ;
if ( result ) {
log . info ( "进度文件已重置,重新开始任务。" ) ;
} else {
log . error ( "进度文件重置失败。" ) ;
}
} else {
// 如果 activeProgress 为是,则正常加载进度
await loadProgress ( ) ;
}
// main
setGameMetrics ( 1920 , 1080 , 1 ) ;
// 确定路径
determinePath ( ) ;
// A or B
// 初始化
await init ( ) ;
log . info ( ` 开始执行 ${ path } 线路。 ` ) ;
if ( path == 'A' ) await batch ( folderA , pathingA ) ;
else await batch ( folderB , pathingB ) ;
// Extra
// 执行主线任务
log . info ( ` 开始执行 ${ progress . path } 线路。 ` ) ;
if ( progress . path == 'A' ) {
await batch ( folderA , pathingA ) ;
} else {
await batch ( folderB , pathingB ) ;
}
// 执行额外任务
if ( extra ) {
await init ( ) ;
log . info ( ` 开始执行额外线路。` ) ;
// 12小时刷新的额外点位每天拾取
log . info ( " 开始执行额外线路。" ) ;
await batch ( folderE , pathingE ) ;
// 24小时刷新的额外点位隔天拾取, 避免空跑
@@ -278,7 +389,7 @@
}
await init ( ) ;
log . info ( ` 今日狗粮拾取任务完成。拾取路线: ${ path } ${ extra ? '+E' : '' } ` ) ;
log . info ( ` 今日狗粮拾取任务完成。拾取路线: ${ progress . path} ${ extra ? '+E' : '' } ` ) ;
await sleep ( 1000 ) ;
} ) ( ) ;
} ) ( ) ;