refactor: 移除执行记录相关功能

删除 ExecutionRecord、DailyExecutionRecord 和 ExecutionRecordStorage 类及相关代码
移除 ScriptService 和 ScriptGroupProject 中与执行记录相关的逻辑,包括任务跳过检查和记录保存
简化项目执行流程,专注于核心功能
This commit is contained in:
辉鸭蛋
2026-05-03 19:39:45 +08:00
parent f0e4ac4db2
commit b15012ffcd
5 changed files with 1 additions and 409 deletions

View File

@@ -18,7 +18,6 @@ using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum;
using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.GameTask.FarmingPlan;
using BetterGenshinImpact.GameTask.LogParse;
using BetterGenshinImpact.Helpers;
using Microsoft.Extensions.Logging;
@@ -194,20 +193,6 @@ public partial class ScriptGroupProject : ObservableObject
public async Task Run()
{
//执行记录
ExecutionRecord executionRecord = new ExecutionRecord()
{
ServerStartTime =
GroupInfo?.Config.PathingConfig.TaskCompletionSkipRuleConfig.IsBoundaryTimeBasedOnServerTime ?? false
? ServerTimeHelper.GetServerTimeNow()
: DateTimeOffset.Now,
StartTime = DateTime.Now,
GroupName = GroupInfo?.Name ?? "",
FolderName = FolderName,
ProjectName = Name,
Type = Type
};
ExecutionRecordStorage.SaveExecutionRecord(executionRecord);
if (Type == "Javascript")
{
if (Project == null)
@@ -245,7 +230,6 @@ public partial class ScriptGroupProject : ObservableObject
await pathingTask.Pathing(task);
executionRecord.IsSuccessful = pathingTask.SuccessEnd;
OtherConfig.AutoRestart autoRestart = TaskContext.Instance().Config.OtherConfig.AutoRestartConfig;
if (!pathingTask.SuccessEnd)
{
@@ -311,18 +295,6 @@ public partial class ScriptGroupProject : ObservableObject
var task = new ShellTask(ShellTaskParam.BuildFromConfig(Name, shellConfig ?? new ShellConfig()));
await task.Start(CancellationContext.Instance.Cts.Token);
}
if (Type != "Pathing")
{
executionRecord.IsSuccessful = true;
}
executionRecord.ServerEndTime =
GroupInfo?.Config.PathingConfig.TaskCompletionSkipRuleConfig.IsBoundaryTimeBasedOnServerTime ?? false
? ServerTimeHelper.GetServerTimeNow()
: DateTimeOffset.Now;
executionRecord.EndTime = DateTime.Now;
ExecutionRecordStorage.SaveExecutionRecord(executionRecord);
}
partial void OnTypeChanged(string value)

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BetterGenshinImpact.GameTask.LogParse;
public class DailyExecutionRecord
{
[JsonProperty("name")]
public string Name { get; set; }=string.Empty;
[JsonProperty("execution_records")]
public List<ExecutionRecord> ExecutionRecords { get; set; } = new();
}

View File

@@ -1,44 +0,0 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace BetterGenshinImpact.GameTask.LogParse;
public class ExecutionRecord
{
[JsonProperty("guid")] public Guid Id { get; set; } = Guid.NewGuid();
[JsonProperty("group_name")] public string GroupName { get; set; } = string.Empty;
[JsonProperty("project_name")] public string ProjectName { get; set; } = string.Empty;
[JsonProperty("folder_name")] public string FolderName { get; set; } = string.Empty;
[JsonProperty("type")] public string Type = string.Empty;
/// <summary>
/// 执行开始时间(服务器时间,包含时区信息)
/// </summary>
[JsonProperty("server_start_time")]
public DateTimeOffset? ServerStartTime { get; set; }
/// <summary>
/// 执行开始时间的本地时间表示(用于向后兼容的统计显示)
/// </summary>
[JsonProperty("start_time")]
public DateTime StartTime { get; set; }
/// <summary>
/// 执行结束时间(服务器时间,包含时区信息)
/// </summary>
[JsonProperty("server_end_time")]
public DateTimeOffset? ServerEndTime { get; set; }
/// <summary>
/// 执行结束时间的本地时间表示(用于向后兼容的统计显示)
/// </summary>
[JsonProperty("end_time")]
public DateTime EndTime { get; set; }
/// <summary>
/// 是否执行成功
/// </summary>
[JsonProperty("is_successful")]
public bool IsSuccessful { get; set; } = false;
}

View File

@@ -1,310 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Script.Group;
using BetterGenshinImpact.Helpers;
using Newtonsoft.Json;
namespace BetterGenshinImpact.GameTask.LogParse;
public class ExecutionRecordStorage
{
private static readonly string StorageDirectory = Path.Combine(Global.Absolute(@"log"), "ExecutionRecords");
/// <summary>
/// 保存执行记录到对应日期的文件中
/// </summary>
public static void SaveExecutionRecord(ExecutionRecord record)
{
// 创建存储目录
Directory.CreateDirectory(StorageDirectory);
// 获取基于StartTime的日期文件名
string dateKey = record.StartTime.ToString("yyyyMMdd");
string fileName = $"{dateKey}.json";
string filePath = Path.Combine(StorageDirectory, fileName);
// 读取或创建当天的记录
DailyExecutionRecord dailyRecord;
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
dailyRecord = JsonConvert.DeserializeObject<DailyExecutionRecord>(json);
}
else
{
dailyRecord = new DailyExecutionRecord
{
Name = dateKey
};
}
// 更新或添加记录
var existingIndex = dailyRecord.ExecutionRecords.FindIndex(r => r.Id == record.Id);
if (existingIndex >= 0)
{
dailyRecord.ExecutionRecords[existingIndex] = record;
}
else
{
dailyRecord.ExecutionRecords.Add(record);
}
// 保存更新后的文件
string updatedJson = JsonConvert.SerializeObject(dailyRecord, Formatting.Indented);
File.WriteAllText(filePath, updatedJson);
}
public static List<DailyExecutionRecord> GetRecentExecutionRecordsByConfig(TaskCompletionSkipRuleConfig config)
{
// 确定边界时间是否有效0-23之间
bool boundaryTimeEnable = config.BoundaryTime >= 0 && config.BoundaryTime <= 23;
// 默认获取最近1天的执行记录
int dayCount = 1;
// 如果边界时间有效需要获取2天的记录可能跨越边界
if (boundaryTimeEnable)
{
dayCount = 2;
}
// 如果配置了有效的间隔秒数,根据秒数计算需要获取的天数(向上取整)
if (config.LastRunGapSeconds >= 0)
{
dayCount = ConvertSecondsToDaysUp(config.LastRunGapSeconds);
}
return GetRecentExecutionRecords(dayCount);
}
/// <summary>
/// 读取最近N天的执行记录
/// </summary>
public static List<DailyExecutionRecord> GetRecentExecutionRecords(int days)
{
if (days <= 0)
throw new ArgumentException("Days must be a positive integer", nameof(days));
var results = new List<DailyExecutionRecord>();
var storageDir = new DirectoryInfo(StorageDirectory);
// 确保目录存在
if (!storageDir.Exists) return results;
// 计算日期范围
var endDate = DateTime.Today;
var startDate = endDate.AddDays(-days + 1);
// 遍历日期范围
for (var date = startDate; date <= endDate; date = date.AddDays(1))
{
string fileName = $"{date:yyyyMMdd}.json";
string filePath = Path.Combine(StorageDirectory, fileName);
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
var record = JsonConvert.DeserializeObject<DailyExecutionRecord>(json);
results.Add(record);
}
}
//实际使用中,使用倒序,反转记录列表,变为倒序
results.Reverse();
foreach (var dailyRecord in results)
{
var records = dailyRecord.ExecutionRecords;
// 反转执行记录,变为倒序
records.Reverse();
}
return results;
}
/// <summary>
/// 将秒数转换为天数(向上取整)
/// </summary>
/// <param name="seconds">总秒数</param>
/// <returns>向上取整后的天数</returns>
private static int ConvertSecondsToDaysUp(int seconds)
{
if (seconds <= 0) return 0;
const int secondsPerDay = 86400; // 24 * 60 * 60
double days = (double)seconds / secondsPerDay;
return (int)Math.Ceiling(days);
}
/// <summary>
/// 根据自定义的一天开始时间判断日期是否属于"今天"
/// </summary>
/// <param name="boundaryHour">分界时间小时0-23之间基于<paramref name="isBoundaryTimeBasedOnServerTime"/>参数决定的时间参考系</param>
/// <param name="targetDate">要判断的日期(本地时间)</param>
/// <param name="isBoundaryTimeBasedOnServerTime">true表示使用服务器时间计算false表示使用本地时间计算</param>
/// <returns>如果目标日期在根据分界时间定义的"今天"范围内则返回true否则返回false</returns>
private static bool IsTodayByBoundary(int boundaryHour, DateTimeOffset targetDate, bool isBoundaryTimeBasedOnServerTime)
{
// 验证分界时间是否有效
if (boundaryHour < 0 || boundaryHour > 23)
throw new ArgumentOutOfRangeException(nameof(boundaryHour), "分界时间必须在0-23之间");
DateTimeOffset now = isBoundaryTimeBasedOnServerTime
? ServerTimeHelper.GetServerTimeNow()
: DateTimeOffset.Now;
// 计算今天的开始时间(根据分界时间)
DateTime todayStart;
if (now.Hour >= boundaryHour)
{
// 今天已经过了分界时间,今天的开始是今天的分界时间
todayStart = new DateTime(now.Year, now.Month, now.Day, boundaryHour, 0, 0);
}
else
{
// 今天还没过分界时间,今天的开始是昨天的分界时间
todayStart = new DateTime(now.Year, now.Month, now.Day, boundaryHour, 0, 0).AddDays(-1);
}
// 计算今天的结束时间(明天的开始时间)
DateTime todayEnd = todayStart.AddDays(1);
// 判断目标日期是否在今天的范围内
return targetDate >= todayStart && targetDate < todayEnd;
}
public static bool IsSkipTask(ScriptGroupProject project, out string message,List<DailyExecutionRecord>? dailyRecords=null)
{
// 初始化消息字符串
message = "";
// 获取任务完成跳过规则配置
var config = project.GroupInfo?.Config?.PathingConfig.TaskCompletionSkipRuleConfig;
// 检查配置是否有效:配置不存在、未启用、边界时间无效且间隔时间无效
if (config == null ||
!config.Enable ||
(config.BoundaryTime < 0 || config.BoundaryTime > 23) && config.LastRunGapSeconds < 0)
{
return false; // 配置无效,不执行跳过检查
}
// 确定边界时间是否有效0-23之间
bool boundaryTimeEnable = config.BoundaryTime >= 0 && config.BoundaryTime <= 23;
// 获取项目相关信息
var groupName = project.GroupInfo?.Name ?? "";
var folderName = project.FolderName;
var projectName = project.Name;
var projectType = project.Type;
// 获取最近指定天数的执行记录
dailyRecords ??= GetRecentExecutionRecordsByConfig(config);
// 遍历每日记录
foreach (var dailyRecord in dailyRecords)
{
var records = dailyRecord.ExecutionRecords;
// 反转执行记录,变为倒序
// records.Reverse();
// 遍历每条执行记录
foreach (var record in records)
{
// 跳过未成功的执行记录
if (!record.IsSuccessful) continue;
// 跳过类型或项目名称不匹配的记录
if (record.Type != projectType || record.ProjectName != projectName) continue;
var calcTime = record.EndTime;
if (config.ReferencePoint == "StartTime")
{
calcTime = record.StartTime;
}
// 如果配置了间隔时间,检查记录是否在时间间隔内
if (config.LastRunGapSeconds >= 0)
{
double secondsSinceLastRun = (DateTime.Now - calcTime).TotalSeconds;
// 跳过超过配置间隔时间的记录
if (secondsSinceLastRun > config.LastRunGapSeconds) continue;
}
// 检查记录是否在"今天"(根据边界时间定义)
if (boundaryTimeEnable)
{
// 如果记录不在"今天",则跳过
if (!IsTodayByBoundary(config.BoundaryTime,
record.ServerStartTime ??
new DateTimeOffset(record.StartTime).ToOffset(ServerTimeHelper.GetServerTimeOffset()),
config.IsBoundaryTimeBasedOnServerTime)) continue;
}
bool isMatchFound = false;
string matchReason = "";
// 检查匹配策略
if (config.SkipPolicy == "GroupPhysicalPathSkipPolicy" &&
groupName == record.GroupName &&
folderName == record.FolderName)
{
// 组和物理路径匹配策略
matchReason = "组和物理路径匹配一致";
isMatchFound = true;
}
else if (config.SkipPolicy == "PhysicalPathSkipPolicy" &&
folderName == record.FolderName)
{
// 物理路径匹配策略
matchReason = "物理路径相同";
isMatchFound = true;
}
else if (config.SkipPolicy == "SameNameSkipPolicy")
{
// 名称匹配策略(只需要项目名称相同)
matchReason = "名称相同";
isMatchFound = true;
}
else
{
// 未知的跳过策略
Console.WriteLine("ExecutionRecordStorage: 未预期的跳过策略!");
continue; // 继续检查下一条记录
}
if (isMatchFound)
{
// 构建匹配消息
message = $"检查出满足跳过条件: {matchReason}";
// 添加时间相关信息
if (config.LastRunGapSeconds >= 0)
{
// 计算下次可执行时间
DateTime nextExecutionTime = calcTime.AddSeconds(config.LastRunGapSeconds);
message += $", 需在 {nextExecutionTime:yyyy-M-d H:mm:ss} 之后才能开始执行";
}
else if (boundaryTimeEnable)
{
message += $", 需在下一日 {config.BoundaryTime} 点后才能开始执行";
}
// 添加匹配记录的ID
message += $", 匹配记录 GUID={record.Id}";
return true; // 找到匹配记录返回true
}
}
}
// 未找到匹配记录
return false;
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -17,7 +17,6 @@ using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.GameTask.Common.BgiVision;
using BetterGenshinImpact.GameTask.Common.Job;
using BetterGenshinImpact.GameTask.FarmingPlan;
using BetterGenshinImpact.GameTask.LogParse;
using BetterGenshinImpact.GameTask.TaskProgress;
using BetterGenshinImpact.Service.Interface;
using BetterGenshinImpact.Service.Notification;
@@ -100,12 +99,6 @@ public partial class ScriptService : IScriptService
}
}
string skipMessage;
if (ExecutionRecordStorage.IsSkipTask(project,out skipMessage))
{
TaskControl.Logger.LogInformation($"{project.Name}:{skipMessage},跳过此任务!");
return true;
}
return false; // 不跳过
}
@@ -209,15 +202,8 @@ public partial class ScriptService : IScriptService
var preExecutionProjects = new List<ScriptGroupProject>();
foreach (var group in scriptGroups)
{
var skipConfig = group.Config.PathingConfig.TaskCompletionSkipRuleConfig;
var records = ExecutionRecordStorage.GetRecentExecutionRecordsByConfig(skipConfig);
foreach (var p in group.Projects)
{
// 检查是否应该跳过任务
if (ExecutionRecordStorage.IsSkipTask(p, out _, records))
continue;
// 生成项目唯一标识
var projectKey = $"{p.Name}|{p.FolderName}|{p.GroupInfo?.Name}";