diff --git a/Alpha.sln b/Alpha.sln
new file mode 100644
index 0000000..b4b501f
--- /dev/null
+++ b/Alpha.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.13.35617.110 d17.13
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIShell", "UIShell\UIShell.csproj", "{25136FF5-345F-FE98-37AF-CBF690B70510}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Alpha", "Alpha\Alpha.csproj", "{EE9CA942-E12D-9230-D3D5-1B63E2F95A73}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {25136FF5-345F-FE98-37AF-CBF690B70510}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {25136FF5-345F-FE98-37AF-CBF690B70510}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {25136FF5-345F-FE98-37AF-CBF690B70510}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {25136FF5-345F-FE98-37AF-CBF690B70510}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EE9CA942-E12D-9230-D3D5-1B63E2F95A73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EE9CA942-E12D-9230-D3D5-1B63E2F95A73}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EE9CA942-E12D-9230-D3D5-1B63E2F95A73}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EE9CA942-E12D-9230-D3D5-1B63E2F95A73}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1132CA7C-2F80-4134-9EBC-7EC9A58C8769}
+ EndGlobalSection
+EndGlobal
diff --git a/Alpha/Alpha.csproj b/Alpha/Alpha.csproj
new file mode 100644
index 0000000..6fd6f2f
--- /dev/null
+++ b/Alpha/Alpha.csproj
@@ -0,0 +1,22 @@
+
+
+
+ WinExe
+ net9.0-windows
+ enable
+ enable
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Alpha/App.xaml b/Alpha/App.xaml
new file mode 100644
index 0000000..ee25f3c
--- /dev/null
+++ b/Alpha/App.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Alpha/App.xaml.cs b/Alpha/App.xaml.cs
new file mode 100644
index 0000000..60a484f
--- /dev/null
+++ b/Alpha/App.xaml.cs
@@ -0,0 +1,14 @@
+using System.Configuration;
+using System.Data;
+using System.Windows;
+
+namespace Alpha
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+
+}
diff --git a/Alpha/AssemblyInfo.cs b/Alpha/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/Alpha/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/Alpha/Converters/AlphaResultToColorConverter.cs b/Alpha/Converters/AlphaResultToColorConverter.cs
new file mode 100644
index 0000000..7a7f70e
--- /dev/null
+++ b/Alpha/Converters/AlphaResultToColorConverter.cs
@@ -0,0 +1,36 @@
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+using Alpha.Models;
+
+namespace Alpha.Converters
+{
+ public class AlphaResultToColorConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is AlphaResponse response)
+ {
+ List? checks;
+ checks = response.Is?.Checks;
+ if (checks != null)
+ {
+ return !checks.Any(delegate (AlphaCheck check)
+ {
+ string? result;
+ result = check.Result;
+ return result != null && (result.ToUpper()?.Equals("FAIL", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault();
+ })
+ ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2E7D32"))
+ : (object)new SolidColorBrush((Color)ColorConverter.ConvertFromString("#C62828"));
+ }
+ }
+ return new SolidColorBrush(Colors.Transparent);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/AlphaResultToTextConverter.cs b/Alpha/Converters/AlphaResultToTextConverter.cs
new file mode 100644
index 0000000..81ee8be
--- /dev/null
+++ b/Alpha/Converters/AlphaResultToTextConverter.cs
@@ -0,0 +1,35 @@
+using System.Globalization;
+using System.Windows.Data;
+using Alpha.Models;
+
+namespace Alpha.Converters
+{
+ public class AlphaResultToTextConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is AlphaResponse response)
+ {
+ List? checks;
+ checks = response.Is?.Checks;
+ if (checks != null)
+ {
+ return !checks.Any(delegate (AlphaCheck check)
+ {
+ string? result;
+ result = check.Result;
+ return result != null && (result.ToUpper()?.Equals("FAIL", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault();
+ })
+ ? "已通过"
+ : (object)"未通过";
+ }
+ }
+ return "未知状态";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/CheckResultColorConverter.cs b/Alpha/Converters/CheckResultColorConverter.cs
new file mode 100644
index 0000000..85b3ba1
--- /dev/null
+++ b/Alpha/Converters/CheckResultColorConverter.cs
@@ -0,0 +1,27 @@
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace Alpha.Converters
+{
+ public class CheckResultColorConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value is string result
+ ? result.ToUpper() switch
+ {
+ "PASS" => new SolidColorBrush(Color.FromRgb(40, 167, 69)),
+ "FAIL" => new SolidColorBrush(Color.FromRgb(220, 53, 69)),
+ "PENDING" => new SolidColorBrush(Color.FromRgb(byte.MaxValue, 193, 7)),
+ _ => new SolidColorBrush(Color.FromRgb(108, 117, 125)),
+ }
+ : (object)new SolidColorBrush(Color.FromRgb(108, 117, 125));
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/ExpiryToDateTimeConverter.cs b/Alpha/Converters/ExpiryToDateTimeConverter.cs
new file mode 100644
index 0000000..00959ed
--- /dev/null
+++ b/Alpha/Converters/ExpiryToDateTimeConverter.cs
@@ -0,0 +1,39 @@
+using Newtonsoft.Json;
+
+namespace Alpha.Converters
+{
+ public class ExpiryToDateTimeConverter : JsonConverter
+ {
+ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
+ {
+ if (value is DateTime)
+ {
+ writer.WriteValue(((DateTime)value - new DateTime(1970, 1, 1)).TotalSeconds);
+ }
+ else
+ {
+ writer.WriteNull();
+ }
+ }
+
+ public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+ if ((uint)(reader.TokenType - 7) <= 1u)
+ {
+ double totalSeconds;
+ totalSeconds = Convert.ToDouble(reader.Value);
+ return DateTime.Now.AddSeconds(totalSeconds);
+ }
+ throw new JsonSerializationException("Unexpected token type: " + reader.TokenType);
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(DateTime);
+ }
+ }
+}
diff --git a/Alpha/Converters/IgnoreStatusVisibilityMultiConverter.cs b/Alpha/Converters/IgnoreStatusVisibilityMultiConverter.cs
new file mode 100644
index 0000000..0380f11
--- /dev/null
+++ b/Alpha/Converters/IgnoreStatusVisibilityMultiConverter.cs
@@ -0,0 +1,87 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+using Alpha.Models;
+
+namespace Alpha.Converters
+{
+ public class IgnoreStatusVisibilityMultiConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length == 2 && values[0] is IgnoreStatus status && values[1] is SimulationCompletedData param)
+ {
+ if ((status & IgnoreStatus.Stop) == IgnoreStatus.Stop)
+ {
+ AlphaResponse? alphaResult;
+ alphaResult = param.AlphaResult;
+ if (alphaResult != null && (alphaResult.Is?.Checks?.Any(delegate (AlphaCheck check)
+ {
+ string? result2;
+ result2 = check.Result;
+ return result2 != null && (result2.ToUpper()?.Equals("FAIL", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault();
+ })).GetValueOrDefault())
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ if ((status & IgnoreStatus.Pass) == IgnoreStatus.Pass)
+ {
+ AlphaResponse? alphaResult2;
+ alphaResult2 = param.AlphaResult;
+ if (alphaResult2 != null && alphaResult2.Is?.Checks?.Any(delegate (AlphaCheck check)
+ {
+ string? result;
+ result = check.Result;
+ return result != null && (result.ToUpper()?.Equals("FAIL", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault();
+ }) == false)
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ if ((status & IgnoreStatus.Failure) == IgnoreStatus.Failure)
+ {
+ string? status2;
+ status2 = param.Status;
+ if (status2 != null && (status2.ToUpper()?.Equals("FAIL", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault())
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ if ((status & IgnoreStatus.Warning) == IgnoreStatus.Warning)
+ {
+ string? status3;
+ status3 = param.Status;
+ if (status3 != null && (status3.ToUpper()?.Equals("WARNING", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault())
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ if ((status & IgnoreStatus.Complete) == IgnoreStatus.Complete)
+ {
+ string? status4;
+ status4 = param.Status;
+ if (status4 != null && (status4.ToUpper()?.Equals("COMPLETE", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault())
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ if ((status & IgnoreStatus.Error) == IgnoreStatus.Error)
+ {
+ string? status5;
+ status5 = param.Status;
+ if (status5 != null && (status5.ToUpper()?.Equals("ERROR", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault())
+ {
+ return Visibility.Collapsed;
+ }
+ }
+ }
+ return Visibility.Visible;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/InverseUniversalComparisonConverter.cs b/Alpha/Converters/InverseUniversalComparisonConverter.cs
new file mode 100644
index 0000000..adad0dd
--- /dev/null
+++ b/Alpha/Converters/InverseUniversalComparisonConverter.cs
@@ -0,0 +1,86 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Alpha.Converters
+{
+ public class InverseUniversalComparisonConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter is string paramStr && paramStr == "NullToVisible")
+ {
+ return (value == null) ? Visibility.Collapsed : Visibility.Visible;
+ }
+ return parameter is string paramStr2 && paramStr2 == "NullToHidden"
+ ? (value != null) ? Visibility.Hidden : Visibility.Visible
+ : value == null
+ ? Visibility.Visible
+ : parameter == null
+ ? value is bool
+ ? ((bool)value) ? Visibility.Collapsed : Visibility.Visible
+ : value is int
+ ? ((int)value != 0) ? Visibility.Collapsed : Visibility.Visible
+ : value is double
+ ? (Math.Abs((double)value) > 0.0001) ? Visibility.Collapsed : Visibility.Visible
+ : value is string strValue2
+ ? (!string.IsNullOrEmpty(strValue2)) ? Visibility.Collapsed : Visibility.Visible
+ : value.GetType().IsEnum
+ ? (!value.Equals(Enum.GetValues(value.GetType()).GetValue(0))) ? Visibility.Collapsed : Visibility.Visible
+ : (object)Visibility.Collapsed
+ : (((value is not int && value is not double && value is not float) || 1 == 0) ? ((value is bool boolValue && parameter is bool) ? (boolValue == (bool)parameter) : ((value is string strValue && parameter is string paramStr3) ? string.Equals(strValue, paramStr3, StringComparison.InvariantCulture) : ((value.GetType().IsEnum && parameter.GetType().IsEnum) ? value.Equals(parameter) : value.Equals(parameter)))) : (Math.Abs(System.Convert.ToDouble(value) - System.Convert.ToDouble(parameter)) < 0.0001)) ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is Visibility)
+ {
+ if ((Visibility)value - 1 <= Visibility.Hidden)
+ {
+ if (targetType == typeof(bool))
+ {
+ return true;
+ }
+ if (targetType == typeof(int))
+ {
+ return parameter ?? 1;
+ }
+ if (targetType == typeof(double))
+ {
+ return parameter ?? 1.0;
+ }
+ if (targetType == typeof(string))
+ {
+ return parameter?.ToString() ?? string.Empty;
+ }
+ if (targetType.IsEnum && parameter != null)
+ {
+ return Enum.Parse(targetType, parameter.ToString() ?? string.Empty);
+ }
+ }
+ else
+ {
+ if (targetType == typeof(bool))
+ {
+ return false;
+ }
+ if (targetType == typeof(int) || targetType == typeof(double))
+ {
+ return 0;
+ }
+ if (targetType == typeof(string))
+ {
+ return string.Empty;
+ }
+ if (targetType.IsEnum)
+ {
+ Array values;
+ values = Enum.GetValues(targetType);
+ return values.Length <= 0 ? null : values.GetValue(0);
+ }
+ }
+ }
+ throw new InvalidOperationException("ConvertBack can only convert from Visibility.");
+ }
+ }
+}
diff --git a/Alpha/Converters/NullToVisibilityConverter.cs b/Alpha/Converters/NullToVisibilityConverter.cs
new file mode 100644
index 0000000..989f577
--- /dev/null
+++ b/Alpha/Converters/NullToVisibilityConverter.cs
@@ -0,0 +1,19 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Alpha.Converters
+{
+ public class NullToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return (value == null) ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/StatusToColorConverter.cs b/Alpha/Converters/StatusToColorConverter.cs
new file mode 100644
index 0000000..3dde17e
--- /dev/null
+++ b/Alpha/Converters/StatusToColorConverter.cs
@@ -0,0 +1,26 @@
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Alpha.Converters
+{
+ public class StatusToColorConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value is string status
+ ? status.ToUpper() switch
+ {
+ "COMPLETE" => "#2E7D32",
+ "WARNING" => "#F57C00",
+ "ERROR" => "#C62828",
+ _ => "#757575",
+ }
+ : (object)"#757575";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Alpha/Converters/UniversalComparisonConverter.cs b/Alpha/Converters/UniversalComparisonConverter.cs
new file mode 100644
index 0000000..5fcc0f9
--- /dev/null
+++ b/Alpha/Converters/UniversalComparisonConverter.cs
@@ -0,0 +1,84 @@
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Alpha.Converters
+{
+ public class UniversalComparisonConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return parameter is string paramStr && paramStr == "NullToVisible"
+ ? (value != null) ? Visibility.Collapsed : Visibility.Visible
+ : parameter is string paramStr2 && paramStr2 == "NullToHidden"
+ ? (value == null) ? Visibility.Hidden : Visibility.Visible
+ : value == null
+ ? Visibility.Collapsed
+ : parameter == null
+ ? value is bool
+ ? (!(bool)value) ? Visibility.Collapsed : Visibility.Visible
+ : value is int
+ ? ((int)value == 0) ? Visibility.Collapsed : Visibility.Visible
+ : value is double
+ ? (!(Math.Abs((double)value) > 0.0001)) ? Visibility.Collapsed : Visibility.Visible
+ : value is string strValue2
+ ? string.IsNullOrEmpty(strValue2) ? Visibility.Collapsed : Visibility.Visible
+ : value.GetType().IsEnum
+ ? value.Equals(Enum.GetValues(value.GetType()).GetValue(0)) ? Visibility.Collapsed : Visibility.Visible
+ : (object)Visibility.Visible
+ : (!(((value is not int && value is not double && value is not float) || 1 == 0) ? ((value is bool boolValue && parameter is bool) ? (boolValue == (bool)parameter) : ((value is string strValue && parameter is string paramStr3) ? string.Equals(strValue, paramStr3, StringComparison.InvariantCulture) : ((value.GetType().IsEnum && parameter.GetType().IsEnum) ? value.Equals(parameter) : value.Equals(parameter)))) : (Math.Abs(System.Convert.ToDouble(value) - System.Convert.ToDouble(parameter)) < 0.0001))) ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is Visibility visibility)
+ {
+ if (visibility == Visibility.Visible)
+ {
+ if (targetType == typeof(bool))
+ {
+ return true;
+ }
+ if (targetType == typeof(int))
+ {
+ return parameter ?? 1;
+ }
+ if (targetType == typeof(double))
+ {
+ return parameter ?? 1.0;
+ }
+ if (targetType == typeof(string))
+ {
+ return parameter?.ToString() ?? string.Empty;
+ }
+ if (targetType.IsEnum && parameter != null)
+ {
+ return Enum.Parse(targetType, parameter.ToString() ?? string.Empty);
+ }
+ }
+ else
+ {
+ if (targetType == typeof(bool))
+ {
+ return false;
+ }
+ if (targetType == typeof(int) || targetType == typeof(double))
+ {
+ return 0;
+ }
+ if (targetType == typeof(string))
+ {
+ return string.Empty;
+ }
+ if (targetType.IsEnum)
+ {
+ Array values;
+ values = Enum.GetValues(targetType);
+ return values.Length <= 0 ? null : values.GetValue(0);
+ }
+ }
+ }
+ throw new InvalidOperationException("ConvertBack只能从Visibility转换。");
+ }
+ }
+}
diff --git a/Alpha/FodyWeavers.xml b/Alpha/FodyWeavers.xml
new file mode 100644
index 0000000..63fc148
--- /dev/null
+++ b/Alpha/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/Alpha/Helpers/DirectiveReplacerExtension.cs b/Alpha/Helpers/DirectiveReplacerExtension.cs
new file mode 100644
index 0000000..bb99c91
--- /dev/null
+++ b/Alpha/Helpers/DirectiveReplacerExtension.cs
@@ -0,0 +1,48 @@
+using System.Text.RegularExpressions;
+
+namespace Alpha.Helpers
+{
+ public static class DirectiveReplacerExtension
+ {
+ public static IEnumerable ExpandPlaceholders(string input, Dictionary> replacements)
+ {
+ MatchCollection matches = Regex.Matches(input, @"\$(\d+)");
+ List placeholderKeys = [];
+ foreach (Match match in matches)
+ {
+ int key = int.Parse(match.Groups[1].Value);
+ if (!placeholderKeys.Contains(key))
+ {
+ placeholderKeys.Add(key);
+ }
+ }
+
+ // Start with an empty combination
+ IEnumerable> combos =
+ new List> { Enumerable.Empty<(int, string)>() };
+
+ // Build combinations
+ foreach (int key in placeholderKeys)
+ {
+ combos = combos.SelectMany(c =>
+ replacements[key].Select(val => c.Append((key, val))));
+ }
+
+ // Replace placeholders in each combination
+ foreach (IEnumerable<(int Key, string Value)> combo in combos)
+ {
+ string result = input;
+ foreach ((int k, string v) in combo)
+ {
+ result = Regex.Replace(result, @"\$" + k + @"\b", v);
+ }
+ yield return result;
+ }
+ }
+
+ public static bool HasPlaceholders(string input, int id)
+ {
+ return Regex.IsMatch(input, @"\$" + id + @"\b");
+ }
+ }
+}
diff --git a/Alpha/Helpers/PasswordBoxHelper.cs b/Alpha/Helpers/PasswordBoxHelper.cs
new file mode 100644
index 0000000..9f6e9b2
--- /dev/null
+++ b/Alpha/Helpers/PasswordBoxHelper.cs
@@ -0,0 +1,71 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Alpha.Helpers
+{
+ public static class PasswordBoxHelper
+ {
+ public static readonly DependencyProperty BoundPassword =
+ DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxHelper), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));
+
+ public static readonly DependencyProperty BindPassword =
+ DependencyProperty.RegisterAttached("BindPassword", typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, OnBindPasswordChanged));
+
+ private static readonly DependencyProperty UpdatingPassword =
+ DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false));
+
+ private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is PasswordBox passwordBox && !(bool)passwordBox.GetValue(UpdatingPassword))
+ {
+ passwordBox.Password = (string)e.NewValue;
+ }
+ }
+
+ private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
+ {
+ if (dp is PasswordBox passwordBox)
+ {
+ if ((bool)e.OldValue)
+ {
+ passwordBox.PasswordChanged -= HandlePasswordChanged;
+ }
+
+ if ((bool)e.NewValue)
+ {
+ passwordBox.PasswordChanged += HandlePasswordChanged;
+ }
+ }
+ }
+
+ private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
+ {
+ if (sender is PasswordBox passwordBox)
+ {
+ passwordBox.SetValue(UpdatingPassword, true);
+ passwordBox.SetValue(BoundPassword, passwordBox.Password);
+ passwordBox.SetValue(UpdatingPassword, false);
+ }
+ }
+
+ public static string GetBoundPassword(DependencyObject dp)
+ {
+ return (string)dp.GetValue(BoundPassword);
+ }
+
+ public static void SetBoundPassword(DependencyObject dp, string value)
+ {
+ dp.SetValue(BoundPassword, value);
+ }
+
+ public static bool GetBindPassword(DependencyObject dp)
+ {
+ return (bool)dp.GetValue(BindPassword);
+ }
+
+ public static void SetBindPassword(DependencyObject dp, bool value)
+ {
+ dp.SetValue(BindPassword, value);
+ }
+ }
+}
diff --git a/Alpha/Helpers/TimeHelper.cs b/Alpha/Helpers/TimeHelper.cs
new file mode 100644
index 0000000..fbd8aa4
--- /dev/null
+++ b/Alpha/Helpers/TimeHelper.cs
@@ -0,0 +1,37 @@
+namespace Alpha.Helpers
+{
+ public static class TimeHelper
+ {
+ public static string GetTimeSpan(DateTime start, DateTime end)
+ {
+ TimeSpan timeSpan = end - start;
+ return timeSpan.ToString(@"hh\:mm\:ss");
+ }
+
+ public static string FormatTime(this TimeSpan time)
+ {
+ if (time.TotalSeconds < 60)
+ {
+ return $"{time.Seconds}秒";
+ }
+ else if (time.TotalSeconds < 3600)
+ {
+ int minutes = time.Minutes;
+ int seconds = time.Seconds;
+ return $"{minutes}分 {seconds}秒";
+ }
+ else if (time.TotalSeconds < 86400)
+ {
+ int hours = time.Hours;
+ int minutes = time.Minutes;
+ return $"{hours}小时 {minutes}分";
+ }
+ else
+ {
+ int days = time.Days;
+ int hours = time.Hours;
+ return $"{days}天 {hours}小时";
+ }
+ }
+ }
+}
diff --git a/Alpha/Models/AlphaResponse.cs b/Alpha/Models/AlphaResponse.cs
new file mode 100644
index 0000000..d78a66d
--- /dev/null
+++ b/Alpha/Models/AlphaResponse.cs
@@ -0,0 +1,217 @@
+using Newtonsoft.Json;
+
+namespace Alpha.Models
+{
+ public class AlphaResponse
+ {
+ [JsonProperty("id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("type")]
+ public string? Type { get; set; }
+
+ [JsonProperty("author")]
+ public string? Author { get; set; }
+
+ [JsonProperty("settings")]
+ public AlphaSettings? Settings { get; set; }
+
+ [JsonProperty("regular")]
+ public AlphaRegular? Regular { get; set; }
+
+ [JsonProperty("dateCreated")]
+ public DateTime DateCreated { get; set; }
+
+ [JsonProperty("dateSubmitted")]
+ public DateTime? DateSubmitted { get; set; }
+
+ [JsonProperty("dateModified")]
+ public DateTime DateModified { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("favorite")]
+ public bool Favorite { get; set; }
+
+ [JsonProperty("hidden")]
+ public bool Hidden { get; set; }
+
+ [JsonProperty("color")]
+ public string? Color { get; set; }
+
+ [JsonProperty("category")]
+ public string? Category { get; set; }
+
+ [JsonProperty("tags")]
+ public List? Tags { get; set; }
+
+ [JsonProperty("classifications")]
+ public List? Classifications { get; set; }
+
+ [JsonProperty("grade")]
+ public string? Grade { get; set; }
+
+ [JsonProperty("stage")]
+ public string? Stage { get; set; }
+
+ [JsonProperty("status")]
+ public string? Status { get; set; }
+
+ [JsonProperty("is")]
+ public AlphaPerformanceMetrics? Is { get; set; }
+
+ [JsonProperty("os")]
+ public object? Os { get; set; }
+
+ [JsonProperty("train")]
+ public AlphaPerformanceMetrics? Train { get; set; }
+
+ [JsonProperty("test")]
+ public AlphaPerformanceMetrics? Test { get; set; }
+
+ [JsonProperty("prod")]
+ public object? Prod { get; set; }
+
+ [JsonProperty("competitions")]
+ public object? Competitions { get; set; }
+
+ [JsonProperty("themes")]
+ public object? Themes { get; set; }
+
+ [JsonProperty("pyramids")]
+ public object? Pyramids { get; set; }
+
+ [JsonProperty("team")]
+ public object? Team { get; set; }
+ }
+
+ public class AlphaSettings
+ {
+ [JsonProperty("instrumentType")]
+ public string? InstrumentType { get; set; }
+
+ [JsonProperty("region")]
+ public string? Region { get; set; }
+
+ [JsonProperty("universe")]
+ public string? Universe { get; set; }
+
+ [JsonProperty("delay")]
+ public int Delay { get; set; }
+
+ [JsonProperty("decay")]
+ public int Decay { get; set; }
+
+ [JsonProperty("neutralization")]
+ public string? Neutralization { get; set; }
+
+ [JsonProperty("truncation")]
+ public double Truncation { get; set; }
+
+ [JsonProperty("pasteurization")]
+ public string? Pasteurization { get; set; }
+
+ [JsonProperty("unitHandling")]
+ public string? UnitHandling { get; set; }
+
+ [JsonProperty("nanHandling")]
+ public string? NanHandling { get; set; }
+
+ [JsonProperty("language")]
+ public string? Language { get; set; }
+
+ [JsonProperty("visualization")]
+ public bool Visualization { get; set; }
+
+ [JsonProperty("testPeriod")]
+ public string? TestPeriod { get; set; }
+ }
+
+ public class AlphaRegular
+ {
+ [JsonProperty("code")]
+ public string? Code { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("operatorCount")]
+ public int OperatorCount { get; set; }
+ }
+
+ public class AlphaClassification
+ {
+ [JsonProperty("id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+ }
+
+ public class AlphaPerformanceMetrics
+ {
+ [JsonProperty("pnl")]
+ public int Pnl { get; set; }
+
+ [JsonProperty("bookSize")]
+ public int BookSize { get; set; }
+
+ [JsonProperty("longCount")]
+ public int LongCount { get; set; }
+
+ [JsonProperty("shortCount")]
+ public int ShortCount { get; set; }
+
+ [JsonProperty("turnover")]
+ public double Turnover { get; set; }
+
+ [JsonProperty("returns")]
+ public double Returns { get; set; }
+
+ [JsonProperty("drawdown")]
+ public double Drawdown { get; set; }
+
+ [JsonProperty("margin")]
+ public double Margin { get; set; }
+
+ [JsonProperty("sharpe")]
+ public double Sharpe { get; set; }
+
+ [JsonProperty("fitness")]
+ public double Fitness { get; set; }
+
+ [JsonProperty("startDate")]
+ public DateTime StartDate { get; set; }
+
+ [JsonProperty("checks")]
+ public List? Checks { get; set; }
+ }
+
+ public class AlphaCheck
+ {
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("result")]
+ public string? Result { get; set; }
+
+ [JsonProperty("limit")]
+ public double? Limit { get; set; }
+
+ [JsonProperty("value")]
+ public double? Value { get; set; }
+
+ [JsonProperty("competitions")]
+ public List? Competitions { get; set; }
+ }
+
+ public class AlphaCompetition
+ {
+ [JsonProperty("id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+ }
+}
diff --git a/Alpha/Models/DatasetResponse.cs b/Alpha/Models/DatasetResponse.cs
new file mode 100644
index 0000000..289cbc7
--- /dev/null
+++ b/Alpha/Models/DatasetResponse.cs
@@ -0,0 +1,91 @@
+using Newtonsoft.Json;
+
+namespace Alpha.Models
+{
+ public class DatasetResponse
+ {
+ [JsonProperty("count")]
+ public int Count { get; set; }
+
+ [JsonProperty("results")]
+ public List? Results { get; set; }
+ }
+
+ public class Dataset
+ {
+ [JsonProperty("id")]
+ public string? Id { get; set; }
+
+ [JsonProperty("name")]
+ public string? Name { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("category")]
+ public Category? Category { get; set; }
+
+ [JsonProperty("subcategory")]
+ public Subcategory? Subcategory { get; set; }
+
+ [JsonProperty("region")]
+ public string? Region { get; set; }
+
+ [JsonProperty("delay")]
+ public int Delay { get; set; }
+
+ [JsonProperty("universe")]
+ public string? Universe { get; set; }
+
+ [JsonProperty("coverage")]
+ public double Coverage { get; set; }
+
+ [JsonProperty("valueScore")]
+ public double ValueScore { get; set; }
+
+ [JsonProperty("userCount")]
+ public int UserCount { get; set; }
+
+ [JsonProperty("alphaCount")]
+ public int AlphaCount { get; set; }
+
+ [JsonProperty("fieldCount")]
+ public int FieldCount { get; set; }
+
+ [JsonProperty("themes")]
+ public List