From f7779af01b1829cc2146a1b0e7e8f6cfc80a38a5 Mon Sep 17 00:00:00 2001 From: zjl Date: Thu, 23 Jan 2025 22:53:59 +0800 Subject: [PATCH 01/13] =?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?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/LogParse/LogParse.cs | 83 +++++++++++++++++-- .../GameTask/LogParse/LogParseConfig.cs | 1 + .../GameTask/LogParse/MoraStatistics.cs | 7 +- .../ViewModel/Pages/ScriptControlViewModel.cs | 16 +++- 4 files changed, 97 insertions(+), 10 deletions(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index 83ef540e..0286e277 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.ReviveCount++; + } + + + 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,24 @@ 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 GenerHtmlByConfigGroupEntity(List configGroups, GameInfo gameInfo,LogParseConfig.ScriptGroupLogParseConfig scriptGroupLogParseConfig) { (string name, Func value)[] colConfigs = [ @@ -316,20 +377,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")), ]; @@ -344,7 +413,7 @@ namespace LogParse actionItems = TravelsDiaryDetailManager.loadAllActionItems(gameInfo, configGroups); } - return GenerHtmlByConfigGroupEntity(configGroups, "日志分析", colConfigs,col2Configs, actionItems, msColConfigs); + return GenerHtmlByConfigGroupEntity(configGroups, "日志分析", colConfigList.ToArray(),col2Configs, actionItems, msColConfigs); } public static string ConcatenateStrings(string a, string b) { diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs index 7588ab5d..63a9004a 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs @@ -14,5 +14,6 @@ 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; } } \ 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/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs index c1bf7ab8..2d522250 100644 --- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs @@ -11,6 +11,7 @@ using System.Text.Json; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.Core.Script.Group; @@ -174,6 +175,16 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware dayRangeComboBox.SelectedValuePath = "Value"; // 绑定的值 dayRangeComboBox.SelectedIndex = 0; stackPanel.Children.Add(dayRangeComboBox); + + // 开关控件:ToggleButton 或 CheckBox + CheckBox faultStatsSwitch = new CheckBox + { + Content = "异常情况统计", + VerticalAlignment = VerticalAlignment.Center + }; + stackPanel.Children.Add(faultStatsSwitch); + + // 开关控件:ToggleButton 或 CheckBox @@ -245,7 +256,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware dayRangeComboBox.SelectedValue = sgpc.DayRangeValue; cookieTextBox.Text = config.Cookie; hoeingStatsSwitch.IsChecked = sgpc.HoeingStatsSwitch; - + faultStatsSwitch.IsChecked = sgpc.FaultStatsSwitch; MessageBoxResult result = await uiMessageBox.ShowDialogAsync(); @@ -259,6 +270,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware sgpc.DayRangeValue=dayRangeValue; sgpc.RangeValue = rangeValue; sgpc.HoeingStatsSwitch = hoeingStatsSwitch.IsChecked ?? false; + sgpc.FaultStatsSwitch = faultStatsSwitch.IsChecked ?? false; config.Cookie = cookieValue; config.ScriptGroupLogDictionary[_selectedScriptGroup.Name]=sgpc; @@ -343,7 +355,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware configGroupEntities.Reverse(); //realGameInfo //小怪摩拉统计 - win.NavigateToHtml(LogParse.LogParse.GenerHtmlByConfigGroupEntity(configGroupEntities,hoeingStats ? realGameInfo : null)); + win.NavigateToHtml(LogParse.LogParse.GenerHtmlByConfigGroupEntity(configGroupEntities,hoeingStats ? realGameInfo : null,sgpc)); win.ShowDialog(); } From 07efcbde4f6830976ee63fd6c54d6907d6d5ccfd Mon Sep 17 00:00:00 2001 From: zjl Date: Thu, 23 Jan 2025 22:58:38 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E8=B5=8B=E5=80=BC=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/GameTask/LogParse/LogParse.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index 0286e277..c76ad3be 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -124,7 +124,7 @@ namespace LogParse //重试一次路线或放弃此路线! if (logstr.EndsWith("重试一次路线或放弃此路线!")) { - configTask.Fault.ReviveCount++; + configTask.Fault.RetryCount++; } From d70ed4314afe28256683a0f675afdbc1875160aa Mon Sep 17 00:00:00 2001 From: zjl Date: Thu, 23 Jan 2025 23:04:58 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=88=86=E6=9E=90?= =?UTF-8?q?=E8=A1=A8=E6=A0=BC=EF=BC=8C=E4=BD=BF=E9=9A=94=E8=A1=8C=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E6=A0=B7=E5=BC=8F=E4=B8=8D=E4=B8=80=E6=A0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/GameTask/LogParse/LogParse.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index c76ad3be..b2ceb51b 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -442,6 +442,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(""); From 7c620429c325f8495f50cfb99688a66cc1374891 Mon Sep 17 00:00:00 2001 From: zjl Date: Fri, 24 Jan 2025 19:19:09 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E9=94=84?= =?UTF-8?q?=E5=9C=B0=E5=BB=B6=E6=97=B6=EF=BC=8C=E9=80=9A=E8=BF=87=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=BB=B6=E6=97=B6=E7=9B=B8=E5=AF=B9=E7=B2=BE=E7=A1=AE?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA=E6=80=AA=E7=89=A9=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/LogParse/LogParse.cs | 29 ++++++++++++++- .../GameTask/LogParse/LogParseConfig.cs | 1 + .../ViewModel/Pages/ScriptControlViewModel.cs | 35 ++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index b2ceb51b..fcf60d15 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -368,6 +368,24 @@ namespace LogParse // 如果数字为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 = @@ -409,8 +427,17 @@ 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); + Console.WriteLine(); + } + } + } return GenerHtmlByConfigGroupEntity(configGroups, "日志分析", colConfigList.ToArray(),col2Configs, actionItems, msColConfigs); diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs index 63a9004a..688a01ff 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParseConfig.cs @@ -15,5 +15,6 @@ public partial class LogParseConfig : ObservableObject [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/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs index 2d522250..0fd06377 100644 --- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs @@ -223,9 +223,39 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware secondRow.Children.Add(questionButton); + StackPanel threeRow = new StackPanel + { + Orientation = Orientation.Horizontal, + Margin = new Thickness(0, 0, 0, 10) + }; + + // 创建一个 TextBlock + TextBlock hoeingDelayBlock = new TextBlock + { + Text = "锄地延时(秒):", + VerticalAlignment = VerticalAlignment.Center, + FontSize = 16, + Margin = new Thickness(0, 0, 10, 0) + }; + + + TextBox hoeingDelayTextBox = new TextBox + { + Width = 100, + FontSize = 16, + VerticalContentAlignment = VerticalAlignment.Center + }; + + threeRow.Children.Add(hoeingDelayBlock); + threeRow.Children.Add(hoeingDelayTextBox); + + + + + // 将第二行添加到 StackPanel stackPanel.Children.Add(secondRow); - + stackPanel.Children.Add(threeRow); //PrimaryButtonText var uiMessageBox = new Wpf.Ui.Controls.MessageBox { @@ -257,6 +287,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware cookieTextBox.Text = config.Cookie; hoeingStatsSwitch.IsChecked = sgpc.HoeingStatsSwitch; faultStatsSwitch.IsChecked = sgpc.FaultStatsSwitch; + hoeingDelayTextBox.Text = sgpc.HoeingDelay; MessageBoxResult result = await uiMessageBox.ShowDialogAsync(); @@ -271,6 +302,8 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware sgpc.RangeValue = rangeValue; sgpc.HoeingStatsSwitch = hoeingStatsSwitch.IsChecked ?? false; sgpc.FaultStatsSwitch = faultStatsSwitch.IsChecked ?? false; + sgpc.HoeingDelay = hoeingDelayTextBox.Text; + config.Cookie = cookieValue; config.ScriptGroupLogDictionary[_selectedScriptGroup.Name]=sgpc; From 39b7176b4d6006ce6e26c3c51f4731154d858642 Mon Sep 17 00:00:00 2001 From: zjl Date: Fri, 24 Jan 2025 19:20:47 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/GameTask/LogParse/LogParse.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index fcf60d15..d5b4b058 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -434,7 +434,6 @@ namespace LogParse foreach (var actionItem in actionItems) { actionItem.Time = SubtractFiveSeconds(actionItem.Time,hoeingDelay); - Console.WriteLine(); } } From d0f985408ea579c8230392c878300954d8ca6dec Mon Sep 17 00:00:00 2001 From: zjl Date: Sat, 25 Jan 2025 22:29:37 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E8=B0=83=E5=BA=A6=E5=99=A8=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=EF=BC=8C=E5=A2=9E=E5=8A=A0=20=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=80=92=E5=BA=8F=E6=8E=92=E5=88=97=E5=8A=9F=E8=83=BD=E3=80=82?= =?UTF-8?q?=E8=B0=83=E5=BA=A6=E5=99=A8=E9=85=8D=E7=BD=AE=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E2=80=9C=E4=B8=8D=E5=9C=A8=E6=9F=90=E6=97=B6=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E2=80=9D=EF=BC=8C=E5=BD=93=E6=89=A7=E8=A1=8C=E5=AE=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E8=B7=AF=E7=BA=BF=E5=90=8E=EF=BC=8C=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E4=B8=BA=E5=BD=93=E5=89=8D=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E9=97=B4=EF=BC=88=E8=8C=83=E5=9B=B4=EF=BC=9A?= =?UTF-8?q?0-23=EF=BC=89=EF=BC=8C=E5=88=99=E6=AD=A4=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E8=BF=BD=E8=B8=AA=E4=BB=BB=E5=8A=A1=E5=90=8E=E7=BB=AD=E9=83=BD?= =?UTF-8?q?=E5=B0=86=E9=83=BD=E8=B7=B3=E8=BF=87=EF=BC=8C=E9=80=82=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E8=BF=9E=E7=BB=AD=E6=89=A7=E8=A1=8C=E7=9A=84=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E4=BB=BB=E5=8A=A1=EF=BC=8C=E4=BE=8B=E5=A6=82=E6=83=B3?= =?UTF-8?q?=E9=80=9A=E5=AE=B5=E6=8C=82=E6=9C=BA=EF=BC=8C=E5=B9=B6=E4=B8=94?= =?UTF-8?q?=E5=9C=A84=E7=82=B9=E5=90=8E=EF=BC=8C=E5=BC=80=E5=A7=8B?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E6=96=B0=E7=9A=84=E4=BB=BB=E5=8A=A1=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core/Config/PathingPartyConfig.cs | 4 +++ BetterGenshinImpact/Service/ScriptService.cs | 33 +++++++++++++++++++ .../View/Pages/ScriptControlPage.xaml | 1 + .../Pages/View/ScriptGroupConfigView.xaml | 26 +++++++++++++++ .../ViewModel/Pages/ScriptControlViewModel.cs | 11 ++++++- 5 files changed, 74 insertions(+), 1 deletion(-) 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/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 02acc783..1fa3787c 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 10cb31af5742ed3000d1ee489ae6dea757db8dc0 Mon Sep 17 00:00:00 2001 From: zjl Date: Sun, 26 Jan 2025 18:46:42 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=BD=93=E6=88=98?= =?UTF-8?q?=E6=96=97=E8=84=9A=E6=9C=AC=E4=B8=AD=E4=BA=BA=E5=91=98=E4=B8=8D?= =?UTF-8?q?=E5=9C=A8=E9=98=9F=E4=BC=8D=E6=98=AF=E5=BC=95=E5=8F=91=E7=9A=84?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/AutoFight/AutoFightTask.cs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs index 16ab96c9..20a50084 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs +++ b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs @@ -249,21 +249,30 @@ public class AutoFightTask : ISoloTask if (lastFightName != command.Name && actionSchedulerByCd.TryGetValue(command.Name,out skillCd)) { var avatar = combatScenes.Avatars.FirstOrDefault(a => a.Name == command.Name); - if (skillCd < 0) + if (avatar!=null) { - skillCd = FindMax([avatar.SkillCd,avatar.SkillHoldCd]); - } - var dif=(DateTime.UtcNow - avatar.LastSkillTime); - //当技能未冷却时,跳过此次出招 - if ((DateTime.UtcNow -avatar.LastSkillTime).TotalSeconds < skillCd) - { - if (skipFightName != command.Name) + if (skillCd < 0) { - Logger.LogInformation($"{command.Name}cd冷却为{skillCd}秒,剩余{skillCd-dif.TotalSeconds}秒,跳过此次行动"); + skillCd = FindMax([avatar.SkillCd,avatar.SkillHoldCd]); } - skipFightName = command.Name; + var dif=(DateTime.UtcNow - avatar.LastSkillTime); + //当技能未冷却时,跳过此次出招 + if ((DateTime.UtcNow -avatar.LastSkillTime).TotalSeconds < skillCd) + { + if (skipFightName != command.Name) + { + Logger.LogInformation($"{command.Name}cd冷却为{skillCd}秒,剩余{skillCd-dif.TotalSeconds}秒,跳过此次行动"); + } + skipFightName = command.Name; + continue; + } + } + else + { + Logger.LogInformation($"{command.Name}未在队伍中找到,跳过此次出手!"); continue; } + } From 54e062d4907d93afe348a32ad2b03850dda6c15b Mon Sep 17 00:00:00 2001 From: zjl Date: Sun, 26 Jan 2025 18:48:28 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E4=B8=8A=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/AutoFight/AutoFightTask.cs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs index 20a50084..16ab96c9 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs +++ b/BetterGenshinImpact/GameTask/AutoFight/AutoFightTask.cs @@ -249,30 +249,21 @@ public class AutoFightTask : ISoloTask if (lastFightName != command.Name && actionSchedulerByCd.TryGetValue(command.Name,out skillCd)) { var avatar = combatScenes.Avatars.FirstOrDefault(a => a.Name == command.Name); - if (avatar!=null) + if (skillCd < 0) { - if (skillCd < 0) - { - skillCd = FindMax([avatar.SkillCd,avatar.SkillHoldCd]); - } - var dif=(DateTime.UtcNow - avatar.LastSkillTime); - //当技能未冷却时,跳过此次出招 - if ((DateTime.UtcNow -avatar.LastSkillTime).TotalSeconds < skillCd) - { - if (skipFightName != command.Name) - { - Logger.LogInformation($"{command.Name}cd冷却为{skillCd}秒,剩余{skillCd-dif.TotalSeconds}秒,跳过此次行动"); - } - skipFightName = command.Name; - continue; - } + skillCd = FindMax([avatar.SkillCd,avatar.SkillHoldCd]); } - else + var dif=(DateTime.UtcNow - avatar.LastSkillTime); + //当技能未冷却时,跳过此次出招 + if ((DateTime.UtcNow -avatar.LastSkillTime).TotalSeconds < skillCd) { - Logger.LogInformation($"{command.Name}未在队伍中找到,跳过此次出手!"); + if (skipFightName != command.Name) + { + Logger.LogInformation($"{command.Name}cd冷却为{skillCd}秒,剩余{skillCd-dif.TotalSeconds}秒,跳过此次行动"); + } + skipFightName = command.Name; continue; } - } From 3019d1aefa81376fb9718b9e2710a0949bd78774 Mon Sep 17 00:00:00 2001 From: zjl Date: Mon, 27 Jan 2025 08:14:14 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E5=BC=95=E5=8F=91=E7=A9=BA=E6=8C=87=E9=92=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/Service/ScriptService.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index f3e9b10a..6f46bc06 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -76,12 +76,15 @@ public partial class ScriptService : IScriptService foreach (var project in list) { - - if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + if (project.GroupInfo != null) { - _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); - continue; + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + { + _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); + continue; + } } + if (project.Status != "Enabled") { From bdaace9c8b3273e52c42abd81954b29424a4bddc Mon Sep 17 00:00:00 2001 From: zjl Date: Mon, 27 Jan 2025 08:14:14 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E5=BC=95=E5=8F=91=E7=A9=BA=E6=8C=87=E9=92=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/Service/ScriptService.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index f3e9b10a..8e5f7356 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -76,12 +76,13 @@ public partial class ScriptService : IScriptService foreach (var project in list) { - - if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + + if (project.GroupInfo!=null && project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) { _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); continue; } + if (project.Status != "Enabled") { @@ -109,9 +110,9 @@ public partial class ScriptService : IScriptService stopwatch.Reset(); stopwatch.Start(); await ExecuteProject(project); - + //多次执行时及时中断 - if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + if (project.GroupInfo!=null && project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) { _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); break; From 9de4fd4dfa5bdc996592b997936055a516706958 Mon Sep 17 00:00:00 2001 From: zjl Date: Mon, 27 Jan 2025 08:17:41 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E4=BB=A3=E7=A0=81=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/Service/ScriptService.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 8e5f7356..f3e9b10a 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -76,13 +76,12 @@ public partial class ScriptService : IScriptService foreach (var project in list) { - - if (project.GroupInfo!=null && project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) { _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); continue; } - if (project.Status != "Enabled") { @@ -110,9 +109,9 @@ public partial class ScriptService : IScriptService stopwatch.Reset(); stopwatch.Start(); await ExecuteProject(project); - + //多次执行时及时中断 - if (project.GroupInfo!=null && project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) { _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); break; From 8fdc664400dcfd66e98cfef30a0b859ba65842d2 Mon Sep 17 00:00:00 2001 From: zjl Date: Mon, 27 Jan 2025 08:42:33 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact/Service/ScriptService.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 6f46bc06..f3e9b10a 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -76,15 +76,12 @@ public partial class ScriptService : IScriptService foreach (var project in list) { - if (project.GroupInfo != null) + + if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) { - if (project.GroupInfo.Config.PathingConfig.Enabled && IsCurrentHourEqual(project.GroupInfo.Config.PathingConfig.SkipDuring)) - { - _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); - continue; - } + _logger.LogInformation($"{project.Name}任务已到禁止执行时段,将跳过!"); + continue; } - if (project.Status != "Enabled") { From 6a14a8c342090e0ebc181129c8e8b602ee1cdcb6 Mon Sep 17 00:00:00 2001 From: zjl Date: Mon, 27 Jan 2025 15:14:28 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=87=A0?= =?UTF-8?q?=E4=B8=AAwarning=E8=AD=A6=E5=91=8A=E7=9A=84=E5=9C=B0=E6=96=B9?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=B7=AF=E5=BE=84=E8=BF=BD=E8=B8=AA?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=97=B6=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=8E=92?= =?UTF-8?q?=E9=99=A4=E5=B7=B2=E9=80=89=E6=8B=A9=E7=9B=AE=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E6=9D=A1=E4=BB=B6=EF=BC=8C=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E5=99=A8=E4=BB=BB=E5=8A=A1=E5=8F=B3=E9=94=AE=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=96=87=E4=BB=B6=E5=A4=B9=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/LogParse/LogParse.cs | 2 +- .../Helpers/Ui/FileTreeNodeHelper.cs | 104 ++++++++++++- .../View/Pages/ScriptControlPage.xaml | 16 ++ .../ViewModel/Pages/ScriptControlViewModel.cs | 138 +++++++++++++----- 4 files changed, 225 insertions(+), 35 deletions(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index d5b4b058..ad3e83b1 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -386,7 +386,7 @@ namespace LogParse return "Invalid input time format. Please use 'yyyy-MM-dd HH:mm:ss'."; } } - public static string GenerHtmlByConfigGroupEntity(List configGroups, GameInfo gameInfo,LogParseConfig.ScriptGroupLogParseConfig scriptGroupLogParseConfig) + public static string GenerHtmlByConfigGroupEntity(List configGroups, GameInfo? gameInfo,LogParseConfig.ScriptGroupLogParseConfig scriptGroupLogParseConfig) { (string name, Func value)[] colConfigs = [ diff --git a/BetterGenshinImpact/Helpers/Ui/FileTreeNodeHelper.cs b/BetterGenshinImpact/Helpers/Ui/FileTreeNodeHelper.cs index 574cc437..554fe52c 100644 --- a/BetterGenshinImpact/Helpers/Ui/FileTreeNodeHelper.cs +++ b/BetterGenshinImpact/Helpers/Ui/FileTreeNodeHelper.cs @@ -1,4 +1,7 @@ -using BetterGenshinImpact.Model; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using BetterGenshinImpact.Model; using System.IO; using System.Linq; @@ -54,4 +57,103 @@ public class FileTreeNodeHelper parentNode.Children.Add(fileNode); } } + + /// + /// 根据路径过滤树形结构,排除指定路径的节点 + /// + /// 节点数据类型 + /// 树形结构的根节点集合 + /// 要排除的路径集合 + /// 过滤后的树形结构 + public static ObservableCollection> FilterTree( + ObservableCollection> nodes, + List folderNames) + { + // 递归过滤节点 + ObservableCollection> FilterNodes(ObservableCollection> inputNodes, List paths) + { + var filteredNodes = new ObservableCollection>(); + + foreach (var node in inputNodes) + { + // 获取当前层需要排除的路径 + var matchedPaths = paths + .Where(path => IsPathMatch(node.FileName ??"", path)) + .Select(path => GetRemainingPath(node.FileName ?? "" , path)) + .Where(remainingPath => remainingPath != null) + .ToList(); + + // 如果当前路径完全匹配,跳过当前节点 + if (matchedPaths.Any(path => path == "")) + { + continue; + } + + // 递归对子节点过滤 + node.Children = FilterNodes(node.Children, matchedPaths); + + // 添加过滤后的节点 + filteredNodes.Add(node); + } + + return filteredNodes; + } + + return FilterNodes(nodes, folderNames); + } + + /// + /// 判断文件路径是否匹配多级路径的前缀 + /// + /// 当前节点路径 + /// 目标路径 + /// 是否匹配 + private static bool IsPathMatch(string fileName, string path) + { + // 匹配路径是否以指定前缀开始,路径分隔符对齐 + return path.StartsWith(fileName, StringComparison.OrdinalIgnoreCase) + && (path.Length == fileName.Length || path[fileName.Length] == '\\'); + } + + /// + /// 获取路径中去掉当前节点后的剩余路径 + /// + /// 当前节点路径 + /// 完整路径 + /// 剩余路径,如果不匹配返回 null + private static string? GetRemainingPath(string fileName, string path) + { + if (IsPathMatch(fileName, path)) + { + return path.Length > fileName.Length ? path.Substring(fileName.Length + 1) : ""; + } + return null; + } + public static ObservableCollection> FilterEmptyNodes(ObservableCollection> nodes) + { + // 递归过滤节点 + ObservableCollection> Filter(ObservableCollection> inputNodes) + { + var filteredNodes = new ObservableCollection>(); + + foreach (var node in inputNodes) + { + // 递归处理子节点 + node.Children = Filter(node.Children); + + // 如果是目录并且没有子节点,跳过当前节点 + if (node.IsDirectory && !node.Children.Any()) + { + continue; + } + + // 其他情况保留节点 + filteredNodes.Add(node); + } + + return filteredNodes; + } + + return Filter(nodes); + } } diff --git a/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml b/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml index 1c5b8769..6c615f85 100644 --- a/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml +++ b/BetterGenshinImpact/View/Pages/ScriptControlPage.xaml @@ -331,6 +331,22 @@ + + + + + diff --git a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs index 83979c9f..1ef7337d 100644 --- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs @@ -11,7 +11,6 @@ using System.Text.Json; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.Core.Script.Group; @@ -30,6 +29,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using LogParse; using Microsoft.Extensions.Logging; +using SharpCompress; using Wpf.Ui; using Wpf.Ui.Controls; using Wpf.Ui.Violeta.Controls; @@ -107,25 +107,32 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware [RelayCommand] private void ClearTasks() { + if (SelectedScriptGroup == null) + { + return; + } SelectedScriptGroup.Projects.Clear(); WriteScriptGroup(SelectedScriptGroup); } [RelayCommand] private async Task OpenLogParse() { - - GameInfo gameInfo = null; + if (SelectedScriptGroup == null) + { + return; + } + GameInfo? gameInfo = null; var config = LogParse.LogParse.LoadConfig(); if (!string.IsNullOrEmpty(config.Cookie)) { config.CookieDictionary.TryGetValue(config.Cookie, out gameInfo); } - LogParseConfig.ScriptGroupLogParseConfig sgpc; - if (!config.ScriptGroupLogDictionary.TryGetValue(_selectedScriptGroup.Name,out sgpc)) + LogParseConfig.ScriptGroupLogParseConfig? sgpc; + if (!config.ScriptGroupLogDictionary.TryGetValue(SelectedScriptGroup.Name,out sgpc)) { sgpc=new LogParseConfig.ScriptGroupLogParseConfig(); } - + // 创建 StackPanel var stackPanel = new StackPanel @@ -265,9 +272,9 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware PrimaryButtonText = "确定", Owner = Application.Current.MainWindow, }; - questionButton.Click += (sender, args) => - { + void OnQuestionButtonOnClick(object sender, RoutedEventArgs args) + { WebpageWindow cookieWin = new() { Title = "日志分析", @@ -278,8 +285,9 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware }; cookieWin.NavigateToHtml(TravelsDiaryDetailManager.generHtmlMessage()); cookieWin.Show(); + } - }; + questionButton.Click += OnQuestionButtonOnClick; //对象赋值 rangeComboBox.SelectedValue = sgpc.RangeValue; @@ -305,7 +313,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware sgpc.HoeingDelay = hoeingDelayTextBox.Text; config.Cookie = cookieValue; - config.ScriptGroupLogDictionary[_selectedScriptGroup.Name]=sgpc; + config.ScriptGroupLogDictionary[SelectedScriptGroup.Name]=sgpc; LogParse.LogParse.WriteConfigFile(config); @@ -339,7 +347,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware Toast.Warning("未填写cookie,此次将不启用锄地统计!"); } //真正存储的gameinfo - GameInfo realGameInfo = gameInfo; + GameInfo? realGameInfo = gameInfo; //统计锄地开关打开,并且不为cookie不为空 if ((hoeingStatsSwitch.IsChecked ?? false) && !string.IsNullOrEmpty(cookieValue)) { @@ -350,7 +358,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware Toast.Success($"米游社数据获取成功,开始进行解析,请耐心等待!"); } - catch (Exception e) + catch (Exception) { if (realGameInfo!=null) { @@ -378,7 +386,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware var configGroupEntities = LogParse.LogParse.ParseFile(fs); if (rangeValue == "CurrentConfig") { //Toast.Success(_selectedScriptGroup.Name); - configGroupEntities =configGroupEntities.Where(item => _selectedScriptGroup.Name == item.Name).ToList(); + configGroupEntities =configGroupEntities.Where(item => SelectedScriptGroup.Name == item.Name).ToList(); } if (configGroupEntities.Count == 0) { @@ -414,11 +422,11 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware ScriptRepoUpdater.Instance.OpenLocalRepoInWebView(); } [RelayCommand] - private async Task UpdateTasks() + private void UpdateTasks() { List projects = new(); List oldProjects = new(); - oldProjects.AddRange(SelectedScriptGroup?.Projects); + oldProjects.AddRange(SelectedScriptGroup?.Projects ?? []); var oldcount = oldProjects.Count; List folderNames = new(); foreach (var project in oldProjects) @@ -451,25 +459,25 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware } } - SelectedScriptGroup.Projects.Clear(); + SelectedScriptGroup?.Projects.Clear(); foreach (var scriptGroupProject in projects) { SelectedScriptGroup?.AddProject(scriptGroupProject); } Toast.Success($"增加了{projects.Count - oldcount}个路径追踪任务"); - WriteScriptGroup(SelectedScriptGroup); - + if (SelectedScriptGroup != null) WriteScriptGroup(SelectedScriptGroup); } [RelayCommand] private void ReverseTaskOrder() { + List projects = new(); - projects.AddRange(SelectedScriptGroup?.Projects.Reverse()); - SelectedScriptGroup.Projects.Clear(); - projects.ForEach(item=>SelectedScriptGroup.Projects.Add(item)); - WriteScriptGroup(SelectedScriptGroup); + projects.AddRange(SelectedScriptGroup?.Projects.Reverse() ?? []); + SelectedScriptGroup?.Projects.Clear(); + projects.ForEach(item=>SelectedScriptGroup?.Projects.Add(item)); + if (SelectedScriptGroup != null) WriteScriptGroup(SelectedScriptGroup); } [RelayCommand] @@ -498,8 +506,12 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware else { var newScriptGroup =JsonSerializer.Deserialize(JsonSerializer.Serialize(item)) ; - newScriptGroup.Name = str; - ScriptGroups.Add(newScriptGroup); + if (newScriptGroup != null) + { + newScriptGroup.Name = str; + ScriptGroups.Add(newScriptGroup); + } + //WriteScriptGroup(newScriptGroup); } } @@ -628,12 +640,26 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware private ScrollViewer CreatePathingScriptSelectionPanel(IEnumerable> list) { var stackPanel = new StackPanel(); + CheckBox excludeCheckBox = new CheckBox + { + Content = "排除已选择过的目录", + VerticalAlignment = VerticalAlignment.Center, + }; + stackPanel.Children.Add(excludeCheckBox); + var filterTextBox = new TextBox { Margin = new Thickness(0, 0, 0, 10), - PlaceholderText = "输入筛选条件..." + PlaceholderText = "输入筛选条件...", + }; + filterTextBox.TextChanged += delegate + { + ApplyFilter(stackPanel, list, filterTextBox.Text, excludeCheckBox.IsChecked); + }; + excludeCheckBox.Click += delegate + { + ApplyFilter(stackPanel, list, filterTextBox.Text, excludeCheckBox.IsChecked); }; - filterTextBox.TextChanged += (s, e) => ApplyFilter(stackPanel, list, filterTextBox.Text); stackPanel.Children.Add(filterTextBox); AddNodesToPanel(stackPanel, list, 0, filterTextBox.Text); @@ -647,14 +673,50 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware return scrollViewer; } - private void ApplyFilter(StackPanel parentPanel, IEnumerable> nodes, string filter) + private void ApplyFilter(StackPanel parentPanel, IEnumerable> nodes, string filter,bool? excludeSelectedFolder = false) { - if (parentPanel.Children.Count > 0 && parentPanel.Children[0] is TextBox filterTextBox) + if (parentPanel.Children.Count > 0) + { + List removeElements = new List(); + foreach (UIElement parentPanelChild in parentPanel.Children) + { + if (parentPanelChild is FrameworkElement frameworkElement && frameworkElement.Name.StartsWith("dynamic_")) + { + removeElements.Add(frameworkElement); + } + + } + removeElements.ForEach(parentPanel.Children.Remove); + } + + if (excludeSelectedFolder ?? false) + { + + List skipFolderNames = SelectedScriptGroup?.Projects.ToList().Select(item=>item.FolderName).Distinct().ToList() ?? []; + //复制Nodes + string jsonString = JsonSerializer.Serialize(nodes); + var copiedNodes = JsonSerializer.Deserialize>>(jsonString); + if (copiedNodes!=null) + { + //路径过滤 + copiedNodes = FileTreeNodeHelper.FilterTree(copiedNodes, skipFolderNames); + copiedNodes = FileTreeNodeHelper.FilterEmptyNodes(copiedNodes); + AddNodesToPanel(parentPanel, copiedNodes, 0,filter); + } + + } + else + { + AddNodesToPanel(parentPanel, nodes, 0,filter); + } + + + /*if (parentPanel.Children.Count > 0 && parentPanel.Children[1] is TextBox filterTextBox) { parentPanel.Children.Clear(); parentPanel.Children.Add(filterTextBox); // 保留筛选框 AddNodesToPanel(parentPanel, nodes, 0, filter); - } + }*/ } private void AddNodesToPanel(StackPanel parentPanel, IEnumerable> nodes, int depth, string filter) @@ -671,6 +733,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware Content = node.FileName, Tag = node.FilePath, Margin = new Thickness(depth * 30, 0, 0, 0) // 根据深度计算Margin + ,Name = "dynamic_"+Guid.NewGuid().ToString().Replace("-","_") }; if (node.IsDirectory) @@ -683,6 +746,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware Header = checkBox, Content = childPanel, IsExpanded = false // 默认不展开 + ,Name = "dynamic_"+Guid.NewGuid().ToString().Replace("-","_") }; checkBox.Checked += (s, e) => SetChildCheckBoxesState(childPanel, true); @@ -793,7 +857,7 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware [RelayCommand] private void AddNextFlag(ScriptGroupProject? item) { - if (item == null) + if (item == null || SelectedScriptGroup == null) { return; } @@ -805,8 +869,8 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware nextScheduledTask.Remove(nst); } - nextScheduledTask.Add((SelectedScriptGroup?.Name, item.Index, item.FolderName, item.Name)); - foreach (var item1 in SelectedScriptGroup.Projects) + nextScheduledTask.Add((SelectedScriptGroup?.Name ?? "", item.Index, item.FolderName, item.Name)); + foreach (var item1 in SelectedScriptGroup?.Projects ?? []) { item1.NextFlag = false; } @@ -878,7 +942,15 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware Toast.Warning("只有JS脚本才有自定义配置"); } } - + [RelayCommand] + public void OnDeleteScriptByFolder(ScriptGroupProject? item) + { + if (item == null) + { + return; + } + SelectedScriptGroup?.Projects.ToList().Where(item2=>item2.FolderName == item.FolderName).ForEach(OnDeleteScript); + } [RelayCommand] public void OnDeleteScript(ScriptGroupProject? item) {