From 35e40c6dd880c812db317e814f7e6806455edb38 Mon Sep 17 00:00:00 2001
From: tongg <tongguibina@163.com>
Date: Mon, 2 Jun 2025 23:10:29 +0800
Subject: [PATCH] grade level custom

---
 Language/zh_Pro.xaml                          |   3 +
 .../Exceptions/NotGradeSetException.cs        |  10 ++
 Model/GradeLevel/GradeLevelCalculator.cs      |  34 +++++-
 Model/GradeResult/Entity/Enums/Accuracy.cs    |  12 +--
 .../GradeResult/Entity/Enums/DiamondShape.cs  |   6 +-
 .../Helper/DoubleDataFormatHelper.cs          |  78 +++++++++++++-
 .../GradeResult/Helper/ViewDataInfoHelper.cs  | 100 +++++++++++++++++-
 Model/Helper/DataBaseHelper.cs                |   2 +-
 Views/Dialog/ImageSelect.xaml                 |   2 +-
 9 files changed, 228 insertions(+), 19 deletions(-)
 create mode 100644 Model/GradeLevel/Exceptions/NotGradeSetException.cs

diff --git a/Language/zh_Pro.xaml b/Language/zh_Pro.xaml
index d4178d7..0a18973 100644
--- a/Language/zh_Pro.xaml
+++ b/Language/zh_Pro.xaml
@@ -249,4 +249,7 @@
     <sys:String x:Key="NetworkSpeedCheckedText">取消网络质量检测</sys:String>
     <sys:String x:Key="NetworkSpeedCheckedMessage">当前网络传输效率低,可能影响检测效率!</sys:String>
     
+    
+    <sys:String x:Key="ColumnNameBase">Name</sys:String>
+    
 </ResourceDictionary>
\ No newline at end of file
diff --git a/Model/GradeLevel/Exceptions/NotGradeSetException.cs b/Model/GradeLevel/Exceptions/NotGradeSetException.cs
new file mode 100644
index 0000000..746ef13
--- /dev/null
+++ b/Model/GradeLevel/Exceptions/NotGradeSetException.cs
@@ -0,0 +1,10 @@
+namespace BrilliantSightClient.Model.GradeLevel.Exceptions;
+
+public class NotGradeSetException : Exception
+{
+    public NotGradeSetException()
+        :base("Not Grade Set!")
+    {
+        
+    }
+}
\ No newline at end of file
diff --git a/Model/GradeLevel/GradeLevelCalculator.cs b/Model/GradeLevel/GradeLevelCalculator.cs
index 6126305..a375542 100644
--- a/Model/GradeLevel/GradeLevelCalculator.cs
+++ b/Model/GradeLevel/GradeLevelCalculator.cs
@@ -1,17 +1,45 @@
 using BrilliantSightClient.Model.Entity.ApiEntity;
+using BrilliantSightClient.Model.GradeLevel.Entity;
 using BrilliantSightClient.Model.GradeLevel.Entity.DatabaseEntity;
+using BrilliantSightClient.Model.GradeLevel.Entity.Enum;
+using BrilliantSightClient.Model.GradeLevel.Exceptions;
+using BrilliantSightClient.Model.GradeLevel.Helper;
 using BrilliantSightClient.Model.GradeResult.Entity;
+using BrilliantSightClient.Model.GradeResult.Entity.Enums;
+using BrilliantSightClient.Model.Helper;
 
 namespace BrilliantSightClient.Model.GradeLevel;
 
 public class GradeLevelCalculator
 {
+    AlgorithmResultEntity _diamondResult;
+    
+    GradeLevelMst _masterLevel;
+
+    private List<GradeLevelSet> _gradeLevelCutSets;
+    private List<GradeLevelSet> _gradeLevelSymSets;
+    
+    
     public GradeLevelCalculator(AlgorithmResultEntity entity)
     {
-        
+        _diamondResult = entity;
+
+        var masterSql = $"select * from GRADE_LEVEL_MST where NAME = '{entity.Standard}' and RUNMODE = {Common.RunMode} or RUNMODE = -1 " +
+                        $" and SHAPE = {EntityHelper.GetValueFromName<DiamondShape>(entity.Shape)} and CROWN = {entity.CrownType} and PAVILION = {entity.PavType}" ;
+        var masterLevel = DataBaseHelper.ExecuteQuery<GradeLevelMst>(masterSql);
+        if (masterLevel.Count == 0)
+            throw new NotGradeSetException();
+        _masterLevel = masterLevel.First();
+
+        var setsSql = $"select * from GRADE_LEVEL_SET where MST_SIGN = '{_masterLevel.Sign}'";
+        var levelSets = DataBaseHelper.ExecuteQuery<GradeLevelSet>(setsSql);
+        if (masterLevel.Count == 0)
+            throw new NotGradeSetException();
+        _gradeLevelCutSets = levelSets.FindAll(x => x.Set_Type == GradeType.Cut.GetValue());
+        _gradeLevelSymSets = levelSets.FindAll(x => x.Set_Type == GradeType.Sym.GetValue());
     }
 
-    public GradeLevelSet GetCutGradeLevelSet(double maxVal, double minVal)
+    public GradeLevelSet GetCutGradeLevelSet(string key, double maxVal, double minVal)
     {
         return null;
     }
@@ -21,7 +49,7 @@ public class GradeLevelCalculator
         return null;
     }
     
-    public GradeLevelSet GetSymGradeLevelSet(double devVal)
+    public GradeLevelSet GetSymGradeLevelSet(string key, double devVal)
     {
         return null;
     }
diff --git a/Model/GradeResult/Entity/Enums/Accuracy.cs b/Model/GradeResult/Entity/Enums/Accuracy.cs
index f941822..7f252d1 100644
--- a/Model/GradeResult/Entity/Enums/Accuracy.cs
+++ b/Model/GradeResult/Entity/Enums/Accuracy.cs
@@ -5,15 +5,15 @@ namespace BrilliantSightClient.Model.GradeResult.Entity.Enums;
 public enum Accuracy
 {
     [Description("强制保留两位小数,向下取整(ZDZ1)")]
-    ForceTwoDecimals,
+    ForceTwoDecimals = 1,
     [Description("强制保留一位小数,向下取整(ZD1)")]
-    ForceOneDecimal,
+    ForceOneDecimal = 2,
     [Description("将数值舍入到最近的 0.5 倍数(ZD5)")]
-    HalfStepRounding,
+    HalfStepRounding = 3,
     [Description("将数值舍入到最近的 5 的整数倍(Z5)")]
-    MultipleOfFive,
+    MultipleOfFive = 4,
     [Description("将数值舍入到最近的0.2倍数(ZD2)")] 
-    DecimalTwoStepRounding,
+    DecimalTwoStepRounding = 5,
     [Description("强制向下取整为整数(Floor)")] 
-    IntegerFloor
+    IntegerFloor = 6
 }
\ No newline at end of file
diff --git a/Model/GradeResult/Entity/Enums/DiamondShape.cs b/Model/GradeResult/Entity/Enums/DiamondShape.cs
index b667d9d..2a76698 100644
--- a/Model/GradeResult/Entity/Enums/DiamondShape.cs
+++ b/Model/GradeResult/Entity/Enums/DiamondShape.cs
@@ -4,10 +4,10 @@ namespace BrilliantSightClient.Model.GradeResult.Entity.Enums;
 
 public enum DiamondShape
 {
-    [Description("强制保留两位小数,向下取整(ZDZ1)")]
+    [Description("圆形")]
     Round = 0,
-    [Description("强制保留一位小数,向下取整(ZD1)")]
+    [Description("椭圆形")]
     Oval = 1,
-    [Description("将数值舍入到最近的 0.5 倍数(ZD5)")]
+    [Description("梨形")]
     Pear = 2,
 }
\ No newline at end of file
diff --git a/Model/GradeResult/Helper/DoubleDataFormatHelper.cs b/Model/GradeResult/Helper/DoubleDataFormatHelper.cs
index 28e7a00..21591fd 100644
--- a/Model/GradeResult/Helper/DoubleDataFormatHelper.cs
+++ b/Model/GradeResult/Helper/DoubleDataFormatHelper.cs
@@ -1,4 +1,5 @@
 using BrilliantSightClient.Model.Attributes;
+using BrilliantSightClient.Model.Extension;
 using BrilliantSightClient.Model.GradeResult.Entity.Enums;
 
 namespace BrilliantSightClient.Model.GradeResult.Helper;
@@ -95,6 +96,65 @@ public static class DoubleDataFormatHelper
         return result;
     }
     
+    /// <summary>
+    /// 百分比用的小数格式化
+    /// </summary>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    [Log]
+    public static  string FormatDouble(object? value, Accuracy accuracy)
+    {
+        string result = "";
+
+        double dvalue = Double.NaN;
+        if (!Double.TryParse(value.ToSafeString(), out dvalue))
+        {
+            return string.Empty;
+        }
+
+        if (Model.Helper.Common.RunMode == 0)
+        {
+            switch (accuracy)
+            {
+                case Accuracy.ForceTwoDecimals:
+                    result = (Math.Floor(dvalue * 100) / 100).ToString("f2");
+                    break;
+                case Accuracy.ForceOneDecimal:
+                    result = (Math.Floor(dvalue * 10) / 10).ToString("f1");
+                    break;
+                case Accuracy.HalfStepRounding:
+                    result = (RoundFiveDownSixUp(dvalue * 2) / 2).ToString("f1");
+                    break;
+                case Accuracy.MultipleOfFive:
+                    result = (RoundFiveDownSixUp(dvalue / 5) * 5).ToString();
+                    break;
+                case Accuracy.DecimalTwoStepRounding:
+                    result = RoundToPointTwo(dvalue).ToString("f1"); // 保留1位小数
+                    break;
+                case Accuracy.IntegerFloor:
+                    result = Math.Floor(dvalue).ToString("F1"); // 直接取整
+                    break;
+            }
+        }
+        else
+        {
+            //工厂模式不量化
+            switch (accuracy)
+            {
+                case Accuracy.ForceTwoDecimals:
+                    result = (Math.Floor(dvalue * 100) / 100).ToString("f2");
+                    break;
+                case Accuracy.HalfStepRounding:
+                case Accuracy.ForceOneDecimal:
+                case Accuracy.DecimalTwoStepRounding:
+                case Accuracy.IntegerFloor:
+                case Accuracy.MultipleOfFive:
+                    result = (Math.Floor(dvalue * 10) / 10).ToString("f1");
+                    break;
+            }
+        }
+        return result;
+    }
     
     [Log]
     public static double RoundFiveDownSixUp(double value)
@@ -132,6 +192,22 @@ public static class DoubleDataFormatHelper
     {
         return (Math.Floor(value * 100) / 100).ToString("f2");
     }
-    
+    public static Accuracy ToAccuracy(this string value)
+    {
+        if (string.IsNullOrEmpty(value))
+            throw new ArgumentNullException(nameof(value), "输入值不能为空");
+
+        if (int.TryParse(value, out int numericValue))
+        {
+            if (Enum.IsDefined(typeof(Accuracy), numericValue))
+                return (Accuracy)numericValue;
+        }
+
+        // 尝试按名称转换(处理ForceTwoDecimals等情况)
+        if (Enum.TryParse<Accuracy>(value, true, out var result))
+            return result;
+
+        throw new ArgumentException($"无法将值 '{value}' 转换为有效的Accuracy枚举", nameof(value));
+    }
     
 }
\ No newline at end of file
diff --git a/Model/GradeResult/Helper/ViewDataInfoHelper.cs b/Model/GradeResult/Helper/ViewDataInfoHelper.cs
index 2cf286b..6b5ca9a 100644
--- a/Model/GradeResult/Helper/ViewDataInfoHelper.cs
+++ b/Model/GradeResult/Helper/ViewDataInfoHelper.cs
@@ -1,4 +1,6 @@
 using BrilliantSightClient.Model.Entity.ApiEntity;
+using BrilliantSightClient.Model.Extension;
+using BrilliantSightClient.Model.GradeLevel;
 using BrilliantSightClient.Model.GradeLevel.Helper;
 using BrilliantSightClient.Model.GradeResult.Entity;
 using BrilliantSightClient.Model.GradeResult.Entity.Enums;
@@ -15,7 +17,7 @@ public class ViewDataInfoHelper
 {
     public static List<DataInfo> GenerateDataInfos(AlgorithmResultEntity result)
     {
-        JToken measurements = JToken.Parse(JsonConvert.SerializeObject(result.Measurements));
+        JToken jData = JToken.Parse(JsonConvert.SerializeObject(result.Measurements));
         List<DataInfo> dataInfos = new List<DataInfo>();
         int shape = EntityHelper.GetValueFromName<DiamondShape>(result.Shape)??-1;
         if(shape == -1) throw new Exception("Unsupported shapes");
@@ -24,11 +26,101 @@ public class ViewDataInfoHelper
         foreach (var viewData in showViewData)
         {
             DataInfo dataInfo = new DataInfo();
-            
+            dataInfo.TestItemId = viewData.InfoPath;
+            dataInfo.TestItemName = "Name".Equals(MultilingualHelper.getString("ColumnNameBase"))? viewData.Name : viewData.EName;
+            if(!viewData.AvgKey.IsNullOrEmpty())
+                dataInfo.Avg = DoubleDataFormatHelper.FormatDouble(jData[viewData.AvgKey], viewData.AvgType.ToAccuracy());
+            if(!viewData.DevKey.IsNullOrEmpty())
+                dataInfo.Dev = DoubleDataFormatHelper.FormatDouble(jData[viewData.DevKey], viewData.DevType.ToAccuracy());
+            if(!viewData.MaxKey.IsNullOrEmpty())
+                dataInfo.Max = DoubleDataFormatHelper.FormatDouble(jData[viewData.MaxKey], viewData.MaxType.ToAccuracy());
+            if(!viewData.MinKey.IsNullOrEmpty())
+                dataInfo.Min = DoubleDataFormatHelper.FormatDouble(jData[viewData.MinKey], viewData.MinType.ToAccuracy());
+            if (!viewData.DtlKey.IsNullOrEmpty())
+            {
+                List<string> dtlDoubles = GenerateDtlDoubles(jData, viewData);
+                dataInfo.Dtl1 = dtlDoubles[0];
+                dataInfo.Dtl2 = dtlDoubles[1];
+                dataInfo.Dtl3 = dtlDoubles[2];
+                dataInfo.Dtl4 = dtlDoubles[3];
+                dataInfo.Dtl5 = dtlDoubles[4];
+                dataInfo.Dtl6 = dtlDoubles[5];
+                dataInfo.Dtl7 = dtlDoubles[6];
+                dataInfo.Dtl8 = dtlDoubles[7];
+            }
+
+            GradeLevelCalculator levelCalculator = new GradeLevelCalculator(result);
+            dataInfos.Add(dataInfo);
         }
         
         return dataInfos;
     }
-    
-    
+
+    public static List<string> GenerateDtlDoubles(JToken data, ViewData viewData)
+    {
+        List<string> result = new List<string>();
+        int.TryParse(viewData.DtlCt, out int dtlCt);
+        JToken? jToken = data[viewData.DtlKey];
+        if (jToken == null) return result;
+
+        for (int i = 1; i <= dtlCt; i++)
+        {
+            result.Add(DoubleDataFormatHelper.FormatDouble(jToken[$"{viewData.DtlAttr}_{i}"], viewData.DtlType.ToAccuracy()));
+        }
+        return ProcessList(result);
+    }
+    /// <summary>
+    /// 处理字符串列表,确保返回列表长度为8
+    /// 超过8个元素时保留最大值和最小值并缩减到8个元素
+    /// 不足8个元素时用空字符串补足
+    /// </summary>
+    /// <param name="result">输入的字符串列表,所有元素应可转换为double</param>
+    /// <returns>处理后的字符串列表,长度固定为8</returns>
+    public static List<string> ProcessList(List<string> result)
+    {
+        if (result == null)
+            throw new ArgumentNullException(nameof(result));
+        if (result.Count < 8)
+        {
+            var paddedList = new List<string>(result);
+            while (paddedList.Count < 8)
+            {
+                paddedList.Add(string.Empty);
+            }
+            return paddedList;
+        }
+        var indexedValues = result
+            .Select((value, index) => new { Value = double.Parse(value), Index = index })
+            .ToList();
+        var max = indexedValues.OrderByDescending(x => x.Value).First();
+        var min = indexedValues.OrderBy(x => x.Value).First();
+        var remaining = indexedValues
+            .Where(x => x.Index != max.Index && x.Index != min.Index)
+            .ToList();
+        if (remaining.Count <= 6)
+        {
+            var resultList = new List<string>
+            {
+                result[max.Index],
+                result[min.Index]
+            };
+            resultList.AddRange(remaining.Select(x => result[x.Index]));
+            while (resultList.Count < 8)
+            {
+                resultList.Add(string.Empty);
+            }
+            return resultList;
+        }
+        var sampledIndices = new List<int>();
+        for (int i = 0; i < 6; i++)
+        {
+            int index = (int)Math.Round(i * (remaining.Count - 1) / 5.0);
+            sampledIndices.Add(remaining[index].Index);
+        }
+        var finalList = new List<string> { result[max.Index] };
+        finalList.AddRange(sampledIndices.Select(i => result[i]));
+        finalList.Add(result[min.Index]);
+
+        return finalList;
+    }
 }
\ No newline at end of file
diff --git a/Model/Helper/DataBaseHelper.cs b/Model/Helper/DataBaseHelper.cs
index bf86d4b..cc6d9d5 100644
--- a/Model/Helper/DataBaseHelper.cs
+++ b/Model/Helper/DataBaseHelper.cs
@@ -203,6 +203,6 @@ public class DataBaseHelper
             Logger.Error($"全局异常捕获:{ex.Message}", ex);
             System.Windows.MessageBox.Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
         }
-        return null;
+        return new List<T>();
     }
 }
\ No newline at end of file
diff --git a/Views/Dialog/ImageSelect.xaml b/Views/Dialog/ImageSelect.xaml
index 1f74b38..8f6aec5 100644
--- a/Views/Dialog/ImageSelect.xaml
+++ b/Views/Dialog/ImageSelect.xaml
@@ -66,7 +66,7 @@
                     <Label Grid.Row="2" Grid.Column="1" HorizontalAlignment="right" Content="文件名格式" Background="Transparent"
                            BorderBrush="Transparent"
                            FontSize="16" FontFamily="AlibabaPuHui-regular" />
-                    <TextBox Grid.Row="2" Grid.ColumnSpan="1" TextWrapping="Wrap" x:Name ="FileName" Grid.Column="2" Text="%d.bmp"/>
+                    <TextBox Grid.Row="2" Grid.ColumnSpan="1" TextWrapping="Wrap" x:Name ="FileName" Grid.Column="2" Text="image_%d.bmp"/>
                 </Grid>
                 <Grid>
                     <Grid.ColumnDefinitions>