From 8c45a02deb8aeac8098761377862299d28cab83a Mon Sep 17 00:00:00 2001 From: mfkvfhpdx Date: Sun, 26 Jan 2025 11:17:19 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=88=86=E6=9E=90=E4=B8=80=E4=BA=9B=E5=AD=97=E6=AE=B5=E4=B8=BA?= =?UTF-8?q?0=E6=97=B6=E6=98=BE=E7=A4=BA=E4=B8=BA=E7=A9=BA=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=BC=82=E5=B8=B8=E6=83=85=E5=86=B5?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=EF=BC=88=E5=A4=8D=E6=B4=BB=E3=80=81=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E3=80=81=E4=BC=A0=E9=80=81=E5=A4=B1=E8=B4=A5=E3=80=81?= =?UTF-8?q?=E6=88=98=E6=96=97=E8=B6=85=E6=97=B6=EF=BC=89=E3=80=82=20(#1056?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 调整日志分析一些字段为0时显示为空,增加了异常情况统计(复活、重试、传送失败、战斗超时)。 * 修正一个赋值错误 * 日志分析表格,使隔行颜色样式不一样 * 增加了锄地延时,通过控制延时相对精确的显示怪物数量 * 删除不必要的输出 * 调度器任务,增加 任务倒序排列功能。调度器配置增加“不在某时执行”,当执行完一个路线后,如果时间为当前配置的时间(范围:0-23),则此路径追踪任务后续都将都跳过,适用于连续执行的兜底任务,例如想通宵挂机,并且在4点后,开始执行新的任务。 --- .../Core/Config/PathingPartyConfig.cs | 4 + .../GameTask/LogParse/LogParse.cs | 113 ++++++++++++++++-- .../GameTask/LogParse/LogParseConfig.cs | 2 + .../GameTask/LogParse/MoraStatistics.cs | 7 +- BetterGenshinImpact/Service/ScriptService.cs | 33 +++++ .../View/Pages/ScriptControlPage.xaml | 1 + .../Pages/View/ScriptGroupConfigView.xaml | 26 ++++ .../ViewModel/Pages/ScriptControlViewModel.cs | 62 +++++++++- 8 files changed, 235 insertions(+), 13 deletions(-) diff --git a/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs b/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs index a753eae5..47e0a059 100644 --- a/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs +++ b/BetterGenshinImpact/Core/Config/PathingPartyConfig.cs @@ -69,6 +69,10 @@ public partial class PathingPartyConfig : ObservableObject [ObservableProperty] private bool _soloTaskUseFightEnabled = false; + //不在某时执行 + [ObservableProperty] + private string _skipDuring = ""; + // 使用小道具的间隔时间 [ObservableProperty] private int _useGadgetIntervalMs = 0; diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index 83ef540e..d5b4b058 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -102,6 +102,33 @@ namespace LogParse if (configTask != null) { + + //前往七天神像复活 + if (logstr.EndsWith("前往七天神像复活")) + { + configTask.Fault.ReviveCount++; + } + //传送失败,重试 n 次 + result = parseBgiLine($@"传送失败,重试 (\d+) 次", logstr); + if (result.Item1) + { + configTask.Fault.TeleportFailCount = int.Parse(result.Item2[1]); + + } + //战斗超时结束 + if (logstr == "战斗超时结束") + { + configTask.Fault.BattleTimeoutCount ++; + } + + //重试一次路线或放弃此路线! + if (logstr.EndsWith("重试一次路线或放弃此路线!")) + { + configTask.Fault.RetryCount++; + } + + + if (logstr.StartsWith("→ 脚本执行结束: \"" + configTask.Name + "\"")) { configTask.EndDate = parsePreDataTime(logLines, i - 1, logrq); @@ -182,6 +209,8 @@ namespace LogParse //配置人物列表xxx.json public List ConfigTaskList { get; } = new(); + + public class ConfigTask { public string Name { get; set; } @@ -204,6 +233,21 @@ namespace LogParse Picks[val] = Picks[val] + 1; } + public FaultScenario Fault { get; set; } = new(); + + public class FaultScenario + { + //复活次数 + public int ReviveCount { get; set; } = 0; + //传送失败次数 + public int TeleportFailCount { get; set; } = 0; + //重试次数 + public int RetryCount { get; set; } = 0; + //战斗超时 + public int BattleTimeoutCount { get; set; } = 0; + + } + } } @@ -307,7 +351,42 @@ namespace LogParse return customDayStart; } - public static string GenerHtmlByConfigGroupEntity(List configGroups, GameInfo gameInfo) + public static string FormatNumberWithStyle(int a, int b=3) + { + if (a== 0) + { + return ""; + } + // Determine the style based on the condition + string colorStyle = a >= b ? "color:red;" : string.Empty; + + // Return the formatted HTML string + return $"{a}"; + } + public static string GetNumberOrEmptyString(int number) + { + // 如果数字为0,返回空字符串,否则返回数字的字符串形式 + return number == 0 ? string.Empty : number.ToString(); + } + public static string SubtractFiveSeconds(string inputTime,int seconds) + { + try + { + // 将输入的字符串解析为 DateTime + DateTime parsedTime = DateTime.ParseExact(inputTime, "yyyy-MM-dd HH:mm:ss", null); + + // 减去 5 秒 + DateTime resultTime = parsedTime.AddSeconds(-seconds); + + // 转换回指定格式的字符串并返回 + return resultTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + catch (FormatException) + { + return "Invalid input time format. Please use 'yyyy-MM-dd HH:mm:ss'."; + } + } + public static string GenerHtmlByConfigGroupEntity(List configGroups, GameInfo gameInfo,LogParseConfig.ScriptGroupLogParseConfig scriptGroupLogParseConfig) { (string name, Func value)[] colConfigs = [ @@ -316,20 +395,28 @@ namespace LogParse (name: "结束日期", value: task => task.EndDate?.ToString("yyyy-MM-dd HH:mm:ss") ?? ""), (name: "耗时", value: task => ConvertSecondsToTime((task.EndDate - task.StartDate)?.TotalSeconds ?? 0)) ]; - - + List<(string name, Func value)> colConfigList = new(); + colConfigList.AddRange(colConfigs); + if (scriptGroupLogParseConfig.FaultStatsSwitch) + { + colConfigList.Add((name: "复活次数", value: task => FormatNumberWithStyle(task.Fault.ReviveCount))); + colConfigList.Add((name: "重试次数", value: task => FormatNumberWithStyle(task.Fault.RetryCount))); + colConfigList.Add((name: "战斗超时次数", value: task => FormatNumberWithStyle(task.Fault.BattleTimeoutCount))); + colConfigList.Add((name: "传送失败次数", value: task => FormatNumberWithStyle(task.Fault.TeleportFailCount))); + } + (string name, Func value)[] msColConfigs = [ - (name: "日期", value: ms => ms.Name), (name: "小怪", value: ms => ms.SmallMonsterStatistics.ToString()), + (name: "日期", value: ms => ms.Name), (name: "小怪", value: ms => GetNumberOrEmptyString(ms.SmallMonsterStatistics)), (name: "最后小怪日期", value: ms => ms.LastSmallTime), - (name: "精英", value: ms => ms.EliteGameStatistics.ToString()), + (name: "精英", value: ms => GetNumberOrEmptyString(ms.EliteGameStatistics)), (name: "精英详细", value: ms => ms.EliteDetails), (name: "最后精英日期", value: ms => ms.LastEliteTime), (name: "总计锄地摩拉", value: ms => ms.TotalMoraKillingMonstersMora.ToString()), (name: "突发事件获取摩拉", value: ms => ms.EmergencyBonus) ]; //锄地部分新曾字段 - (string name, Func value)[] col2Configs=[..msColConfigs.ToList().Where(item=>item.name!="日期" && item.name!="最后小怪日期" && item.name!="最后精英日期"), + (string name, Func value)[] col2Configs=[..msColConfigs.ToList().Where(item=>item.name!="日期" && item.name!="最后小怪日期" && item.name!="最后精英日期" && item.name!="突发事件获取摩拉"), (name: "摩拉(每秒)", value: ms => (ms.TotalMoraKillingMonstersMora/(ms.StatisticsEnd-ms.StatisticsStart)?.TotalSeconds ?? 0).ToString("F2")), ]; @@ -340,11 +427,19 @@ namespace LogParse List actionItems = new(); if (gameInfo != null) { - actionItems = TravelsDiaryDetailManager.loadAllActionItems(gameInfo, configGroups); + int hoeingDelay; + if (int.TryParse(scriptGroupLogParseConfig.HoeingDelay, out hoeingDelay)) + { + foreach (var actionItem in actionItems) + { + actionItem.Time = SubtractFiveSeconds(actionItem.Time,hoeingDelay); + } + } + } - return GenerHtmlByConfigGroupEntity(configGroups, "日志分析", colConfigs,col2Configs, actionItems, msColConfigs); + return GenerHtmlByConfigGroupEntity(configGroups, "日志分析", colConfigList.ToArray(),col2Configs, actionItems, msColConfigs); } public static string ConcatenateStrings(string a, string b) { @@ -373,6 +468,8 @@ namespace LogParse html.AppendLine(" table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }"); html.AppendLine(" th, td { border: 1px solid black; padding: 8px; text-align: left; }"); html.AppendLine(" th { background-color: #f2f2f2; }"); + html.AppendLine(" tr:nth-child(odd) { background-color: #eaeaea; /* 奇数行颜色 */ }"); + html.AppendLine(" tr:nth-child(even) { background-color: #f9f9f9; /* 偶数行颜色 */}"); html.AppendLine(" "); html.AppendLine(""); html.AppendLine(""); diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs index 7588ab5d..688a01ff 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs @@ -14,5 +14,7 @@ public partial class LogParseConfig : ObservableObject [ObservableProperty] private string _rangeValue = "CurrentConfig"; [ObservableProperty] private string _dayRangeValue = "7"; [ObservableProperty] private bool _hoeingStatsSwitch = false; + [ObservableProperty] private bool _faultStatsSwitch = false; + [ObservableProperty] private string _hoeingDelay= "0"; } } \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/LogParse/MoraStatistics.cs b/BetterGenshinImpact/GameTask/LogParse/MoraStatistics.cs index ae62e5ea..843039bd 100644 --- a/BetterGenshinImpact/GameTask/LogParse/MoraStatistics.cs +++ b/BetterGenshinImpact/GameTask/LogParse/MoraStatistics.cs @@ -31,7 +31,12 @@ namespace LogParse { var ls = this.ActionItems.Where(item => item.ActionId == 28).ToList(); var count = ls.Count(); - return ls.Sum(item=>item.Num)+((count==0 || count>=10)?"":$"({count}/10)"); + if (count == 0) + { + return ""; + } + + return ls.Sum(item=>item.Num)+(count>=10?"":$"({count}/10)"); } } diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 69b1ca29..f3e9b10a 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -21,7 +21,24 @@ namespace BetterGenshinImpact.Service; public partial class ScriptService : IScriptService { private readonly ILogger _logger = App.GetLogger(); + private static bool IsCurrentHourEqual(string input) + { + // 尝试将输入字符串转换为整数 + if (int.TryParse(input, out int hour)) + { + // 验证小时是否在合法范围内(0-23) + if (hour >= 0 && hour <= 23) + { + // 获取当前小时数 + int currentHour = DateTime.Now.Hour; + // 判断是否相等 + return currentHour == hour; + } + } + // 如果输入非数字或不合法,返回 false + return false; + } public async Task RunMulti(IEnumerable projectList, string? groupName = null) { groupName ??= "默认"; @@ -59,6 +76,13 @@ public partial class ScriptService : IScriptService foreach (var project in list) { + + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + { + _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); + continue; + } + if (project.Status != "Enabled") { _logger.LogInformation("脚本 {Name} 状态为禁用,跳过执行", project.Name); @@ -85,6 +109,14 @@ public partial class ScriptService : IScriptService stopwatch.Reset(); stopwatch.Start(); await ExecuteProject(project); + + //多次执行时及时中断 + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + { + _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); + break; + } + } catch (NormalEndException e) { @@ -175,6 +207,7 @@ public partial class ScriptService : IScriptService private async Task ExecuteProject(ScriptGroupProject project) { + if (project.Type == "Javascript") { if (project.Project == null) diff --git a/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml b/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml index 21912df1..1c5b8769 100644 --- a/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml +++ b/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml @@ -217,6 +217,7 @@ + diff --git a/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml b/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml index 970e8715..fe9cf668 100644 --- a/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml +++ b/BetterGenshinImpact/View/Pages/View/ScriptGroupConfigView.xaml @@ -282,6 +282,32 @@ IsChecked="{Binding PathingConfig.SoloTaskUseFightEnabled, Mode=TwoWay}" /> + + + + + + + + + + + + + projects = new(); + projects.AddRange(SelectedScriptGroup?.Projects.Reverse()); + SelectedScriptGroup.Projects.Clear(); + projects.ForEach(item=>SelectedScriptGroup.Projects.Add(item)); + WriteScriptGroup(SelectedScriptGroup); + } [RelayCommand] public void OnCopyScriptGroup(ScriptGroup? item) From bd72e6420d0e7f8f112f509b02e5ffc26737e2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 26 Jan 2025 12:55:57 +0800 Subject: [PATCH 2/4] fist run old version clear --- .../ViewModel/MainWindowViewModel.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs index dcbb3988..ef9e1895 100644 --- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs @@ -102,12 +102,12 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel { // 预热OCR await OcrPreheating(); - + if (Environment.GetCommandLineArgs().Length > 1) { return; } - + // 自动处理目录配置 await Patch1(); @@ -158,19 +158,26 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel */ private async Task Patch1() { - if (Directory.Exists(Global.Absolute("BetterGI")) - // && File.Exists(Global.Absolute("BetterGI/BetterGI.exe")) - && Directory.Exists(Global.Absolute("BetterGI/User")) + var embeddedPath = Global.Absolute("BetterGI"); + var embeddedUserPath = Global.Absolute("BetterGI/User"); + var exePath = Global.Absolute("BetterGI/BetterGI.exe"); + if (Directory.Exists(embeddedPath) + && File.Exists(exePath) + && Directory.Exists(embeddedUserPath) ) { - var res = await MessageBox.ShowAsync("检测到旧的 BetterGI 配置,是否迁移配置并清理旧目录?", "BetterGI", System.Windows.MessageBoxButton.YesNo, MessageBoxImage.Question); - if (res == System.Windows.MessageBoxResult.Yes) + var fileVersionInfo = FileVersionInfo.GetVersionInfo(exePath); + // 低版本才需要迁移 + if (fileVersionInfo.FileVersion != null && !Global.IsNewVersion(fileVersionInfo.FileVersion)) { - var dir = Global.Absolute("BetterGI/User"); - // 迁移配置,拷贝整个目录并覆盖 - DirectoryHelper.CopyDirectory(dir, Global.Absolute("User")); - // 删除旧目录 - DirectoryHelper.DeleteDirectoryRecursively(Global.Absolute("BetterGI")); + var res = await MessageBox.ShowAsync("检测到旧的 BetterGI 配置,是否迁移配置并清理旧目录?", "BetterGI", System.Windows.MessageBoxButton.YesNo, MessageBoxImage.Question); + if (res == System.Windows.MessageBoxResult.Yes) + { + // 迁移配置,拷贝整个目录并覆盖 + DirectoryHelper.CopyDirectory(embeddedUserPath, Global.Absolute("User")); + // 删除旧目录 + DirectoryHelper.DeleteReadOnlyDirectory(embeddedPath); + } } } } From f0baf74dc871bc30c260c6329515a8ba17376994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 26 Jan 2025 14:02:17 +0800 Subject: [PATCH 3/4] 0.40.0 --- BetterGenshinImpact/BetterGenshinImpact.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index 2805db08..9e81a682 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -10,7 +10,7 @@ true Assets\Images\logo.ico BetterGI - 0.39.7 + 0.40.0 x64 embedded From af0a869c7099ce62949ec160d637ec267c5fa877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 26 Jan 2025 17:09:19 +0800 Subject: [PATCH 4/4] shutdown when user config migrate --- BetterGenshinImpact/ViewModel/MainWindowViewModel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs index ef9e1895..2ba43d9c 100644 --- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs @@ -177,6 +177,8 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel DirectoryHelper.CopyDirectory(embeddedUserPath, Global.Absolute("User")); // 删除旧目录 DirectoryHelper.DeleteReadOnlyDirectory(embeddedPath); + await MessageBox.InformationAsync("迁移配置成功, 软件将自动退出,请手动重新启动 BetterGI!"); + Application.Current.Shutdown(); } } }