using System.ComponentModel;
using System.Data;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Input;
using Newtonsoft.Json;
using SparkClient.Model.Entity.ApiEntity;
using SparkClient.Model.Helper;
using SparkClient.Views.UserControl.ViewportData;
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using SparkClient.Views.Dialog;
using NPOI.HPSF;
using Application = System.Windows.Application;
using MessageBox = SparkClient.Views.Dialog.MessageBox;
using System.Windows;
using SharpDX;
using SparkClient.Views.UserControl.ViewportData.Entity;
using SparkClient.ViewModel.Configuration.SettingsPages;
using SparkClient.Views.UserControl.ViewportData.Helper;
using System.Diagnostics.Metrics;
using log4net;
using SparkClient.ViewModel.Configuration;
using System.Drawing.Printing;
using System.Drawing;
using RectangleF = System.Drawing.RectangleF;
using FontFamily = System.Drawing.FontFamily;
using FontStyle = System.Drawing.FontStyle;
using NPOI.SS.Formula.Functions;
using System.Windows.Media;
using Brush = System.Drawing.Brush;
using Brushes = System.Drawing.Brushes;

namespace SparkClient.ViewModel.Grading;
/// <summary>
/// 检测结果画面VM
/// </summary>
public class GradingResultVM : BaseViewModel
{
    private static readonly ILog Logger = LogManager.GetLogger(typeof(GradingResultVM));
    /// <summary>
    /// 钻石编码
    /// </summary>
    private string DiamondCode { get; set; }
    private List<DataInfo> _dtResults;
    // ViewportData
    private DataTable _dsList;
    private DataTable _gradeList;
    private ViewportData _viewportData;
    
    private string _standard;
    private string _shape;
    private string _crownType;
    private string _pavType;
    private string _wight;
    private string _cutLevelTotal;
    private string _symLevelTotal;
    private string _ds;
    private RowDetail _selRowDataDetail;
    private bool _isEnabled;
    /// <summary>
    /// 保存按钮状态
    /// </summary>
    public bool isSaved = false;

    public ICommand SaveFileCommand { get; }
    public ICommand SaveAsCommand { get; }
    /// <summary>
    /// 左侧计算结果展示数据
    /// </summary>
    public List<DataInfo> DtResults { get { return _dtResults;  } set { _dtResults = value; OnPropertyChanged(nameof(DtResults));  } }
    /// <summary>
    /// 右侧钻石3D模型展示控件
    /// </summary>
    public ViewportData ViewportData { get { return _viewportData;  } set { _viewportData = value; OnPropertyChanged(nameof(ViewportData));  } }
    /// <summary>
    /// 画面上方定级标准
    /// </summary>
    public string Standard { get { return _standard; } set { _standard = value; OnPropertyChanged(nameof(Standard)); } }
    /// <summary>
    /// 形状
    /// </summary>
    public string Shape { get { return _shape; } set { _shape = value; OnPropertyChanged(nameof(Shape)); } }
    /// <summary>
    /// 冠面类型
    /// </summary>
    public string CrownType { get { return _crownType; } set { _crownType = value; OnPropertyChanged(nameof(CrownType)); } }
    /// <summary>
    /// 亭面类型
    /// </summary>
    public string PavType { get { return _pavType; } set { _pavType = value; OnPropertyChanged(nameof(PavType)); } }
    /// <summary>
    /// 画面明细展示数据
    /// </summary>
    public RowDetail SelRowDataDetail { get { return _selRowDataDetail; } set { _selRowDataDetail = value; OnPropertyChanged(nameof(SelRowDataDetail)); } }
    /// <summary>
    /// 重量
    /// </summary>
    public string Wight { get { return _wight; } set { _wight = value; OnPropertyChanged(nameof(Wight)); } }
    /// <summary>
    /// 切工等级(整体 画面上部显示)
    /// </summary>
    public string CutLevelTotal { get { return _cutLevelTotal; } set { _cutLevelTotal = value; OnPropertyChanged(nameof(CutLevelTotal)); } }
    /// <summary>
    /// 对称性等级(整体 画面上部显示)
    /// </summary>
    public string SymLevelTotal { get { return _symLevelTotal; } set { _symLevelTotal = value; OnPropertyChanged(nameof(SymLevelTotal)); } }
    /// <summary>
    /// 下拉列表DS
    /// </summary>
    public DataTable DSList { get { return _dsList; } set { _dsList = value; OnPropertyChanged(nameof(DSList)); } }
    /// <summary>
    /// 下拉列表DS 选择的值
    /// </summary>
    public string DS { get { return _ds; } set { _ds = value; OnPropertyChanged(nameof(DS)); } }
    /// <summary>
    /// 定级下拉列表
    /// </summary>
    public DataTable GradeList { get { return _gradeList; } set { _gradeList = value; OnPropertyChanged(nameof(GradeList)); } }
    /// <summary>
    /// 保存和导出的按钮可用性
    /// </summary>
    public bool IsEnabled { get{ return _isEnabled; } set { _isEnabled = value; OnPropertyChanged(nameof(IsEnabled)); } }

    /// <summary>
    /// 格式为小数点后一位
    /// </summary>
    private readonly static string digitsFormat = "f1";

    /// <summary>
    /// 切工总等级(辅助计算用)
    /// </summary>
    private int totalCutGrade = 0;
    /// <summary>
    /// 对称行总等级(辅助计算用)
    /// </summary>
    private decimal totalSymGrade = 0;
    /// <summary>
    /// 计算数据
    /// </summary>
    private AlgorithmResultEntity algorithmResult;
    /// <summary>
    /// 用户名
    /// </summary>
    private string username = "";
    /// <summary>
    /// 机器号
    /// </summary>
    private string machine = "";
    /// <summary>
    /// 形状id
    /// </summary>
    private string shapeId = string.Empty;
    /// <summary>
    /// 规则id
    /// </summary>
    private string ruleId = string.Empty;
    /// <summary>
    /// 构造
    /// </summary>
    /// <param name="result">检测结果</param>
    public GradingResultVM(object result)
    {
        try
        {
            SaveAsCommand = new RelayCommand(SaveAs);
            SaveFileCommand = new RelayCommand(SaveFile);
        
            if (result != null)
            {
                algorithmResult = result as AlgorithmResultEntity?? new AlgorithmResultEntity();
                InitView(algorithmResult);
                machine = algorithmResult.DeviceId;
                username = Settings.SelectValueById("PERMISSIONS");
                if (ruleId.StartsWith("IGI"))
                {
                    IsEnabled = true;
                }
                else
                {
                    IsEnabled = false;
                }
            }
            DS = "NA";
            if (IsEnabled)
            {
                AutoSave();
            }
            SaveTestResult(SaveStatus.AutoSave);
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }

    #region 画面初始化相关操作
    private void InitCombobox()
    {
        // DS下拉列表初始化
        InitDSlist();
        
        string sql = $"SELECT GRADE_NAME AS NAME, GRADE_EN_S_NAME AS EN_NAME, GRADE_EN_NAME AS EN_ALL_NAME, GRADE_ORDER FROM GRADE WHERE SHAPE_ID = '{shapeId}' AND RULE_ID LIKE '{ruleId}%' GROUP BY GRADE_NAME,GRADE_EN_NAME,GRADE_ORDER ORDER BY GRADE_ORDER; ";
        GradeList = DataBaseHelper.ExecuteQuery(sql);
    }
    private void InitViewportData(AlgorithmResultEntity result)
    {
        Dictionary<string,string> colorProperty = new Dictionary<string,string>();
        colorProperty.Add("FACET_COLOR", "MainFacetColor");
        colorProperty.Add("BORDER_COLOR", "MainBorderColor");
        colorProperty.Add("SELECTED_FACET_COLOR", "SelFacetColor");
        colorProperty.Add("SELECTED BORDER COLOR", "SelBorderColor");
        colorProperty.Add("SELECTED_TYPE_COLOR", "SelTypeColor");
        colorProperty.Add("SELECTED_FONT_COLOR", "SelFontColor");
        colorProperty.Add("RULER_COLOR", "SelLineColor");
        colorProperty.Add("ARROW_COLOR", "SelFrontColor");
        colorProperty.Add("BLEMISH_FACET_COLOR", "ErrFacetColor");
        colorProperty.Add("TABLE_FACET_COLOR", "TableFacetColor");
        colorProperty.Add("UPPER_MAIN_FACET_COLOR", "UpperMainFacetColor");
        colorProperty.Add("STAR_FACET_COLOR", "StarFacetColor");
        colorProperty.Add("UPPER_GIRDLE_FACET_COLOR", "UpperGirdleFacetColor");
        colorProperty.Add("GIRDLE_FACET_COLOR", "GirdleFacetColor");
        colorProperty.Add("PAVILION_MAIN_FACET_COLOR", "PavilionFacetColor");
        colorProperty.Add("LOWER_GIRDLE_FACET_COLOR", "LowerGirdleFacetColor");
        colorProperty.Add("CULET_COLOR", "CuletFacetColor");

        ColorConfigEntity colorConfigEntity =  new ColorConfigEntity();
        Type type = colorConfigEntity.GetType();
        foreach (var property in colorProperty)
        {
            var value = Settings.SelectValueById(property.Key);
            PropertyInfo? p = type.GetProperty(property.Value);
            if (p != null && !string.IsNullOrEmpty(value))
            {
                p.SetValue(colorConfigEntity, CommonHelper.HexToColor4(value));
            }
        }
        string data = JsonConvert.SerializeObject(result);
        ViewportData = new ViewportData(result.DiamondCode, data,colorConfigEntity);
        ViewportData.LoadData();
    }
    private void InitDSlist()
    {
        DSList = new DataTable();
        DSList.Columns.Add("Key");
        DSList.Columns.Add("Value");
        DSList.Rows.Add("N/A", "NA");
        DSList.Rows.Add("pass", "pass");
        DSList.Rows.Add("refer", "refer");
    }
 
    private void InitView(AlgorithmResultEntity result)
    {
        try
        {
            InitViewportData(result);
            totalCutGrade = 0;
            totalSymGrade = 0;
            ruleId = getRuleId();
            Standard = result.Standard;
            shapeId = result.Shape;
            InitCombobox();
            Shape = GetName(result.Shape);
            CrownType = result.CrownType;
            PavType = result.PavType;
            DiamondCode = result.DiamondCode;
            CalWight(result);
            DtResults = new List<DataInfo>();
            var testItemList = GetTestItemList();
            Type type = this.GetType();
            foreach (var testItem in testItemList)
            {
                string methodName = "get" + testItem;
                MethodInfo? methodInfo = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
                if (methodInfo != null)
                {
                    object[] parameters = new object[] { result };
                    DataInfo? dataInfo = methodInfo.Invoke(this, parameters) as DataInfo;
                    if (dataInfo != null)
                    {
                        dataInfo.GradeList = GradeList;
                        DtResults.Add(dataInfo);
                    }
                }
            }
            CutLevelTotal = GetGradeName(totalCutGrade);
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }
    private string getRuleId()
    {
        return Settings.SelectValueById("RuleId");
    }
    #endregion
    /// <summary>
    /// 参数列表测试内容获取
    /// </summary>
    /// <returns></returns>
    private List<string> GetTestItemList()
    {
        // DB 没关联
        List<string> list = new List<string>();
        list.Add("DIAMETER");
        list.Add("TOTAL_DEPTH");
        list.Add("TABLE");
        list.Add("CROWN_ANGLE");
        list.Add("CROWN_HEIGHT");
        list.Add("GIRDLE_BEZEL");
        list.Add("GIRDLE_BONE");
        list.Add("GIRDLE");
        list.Add("PAV_ANGLE");
        list.Add("PAV_DEPTH");
        list.Add("STAR");
        list.Add("LOWER_HALVES_RATIO");
        list.Add("CULET");
        list.Add("TOC");
        list.Add("COC");
        list.Add("TWIST");
        list.Add("CULET_TO_TABLE");
        return list;
    }
    #region 定级计算
    private string getActualRuleId()
    {
        string ruleIdForSelect = "";
        if (ruleId.StartsWith("IGI"))
        {
            ruleIdForSelect = ruleId;
        }
        else if (ruleId.StartsWith("GB"))
        {
            double ta = algorithmResult.measurements.TABLE * 100;
            ta = (RoundFiveDownSixUp(ta * 2) / 2);
            if (ta < 49)
            {
                ruleIdForSelect = ruleId + "_TA_49";
            }
            else if (ta > 71)
            {
                ruleIdForSelect = ruleId + "_TA_71";
            }
            else
            {
                ruleIdForSelect = ruleId + "_TA_" + Math.Floor(ta);
            }
        }
        else
        {
            ruleIdForSelect = ruleId;
        }
        return ruleIdForSelect;
    }
    private List<CalGradeInfo> GetCalGradeInfos(string item)
    {
        string ruleIdForSelect = getActualRuleId();
        string sql = $"Select GRADE_ORDER as gradeOrder,CAST(STANDARD_MIN AS NUMERIC) Min, CAST(STANDARD_MAX AS NUMERIC) Max,IS_MAX_EXIST as isMaxExist,IS_MIN_EXIST as isMinExist from STANDARD where TEST_ITEM_ID = '{item}' AND SHAPE_ID = UPPER('{shapeId}') AND RULE_ID = '{ruleIdForSelect}' ";
        List<CalGradeInfo> calGrades = DataBaseHelper.ExecuteQuery<CalGradeInfo>(sql);
        return calGrades;
    }
    private int calGrade(string item ,double value)
    {
        int order = 1;
        try
        {
            decimal cValue = Convert.ToDecimal(value);
            List<CalGradeInfo> calGrades = GetCalGradeInfos(item);
            if (calGrades == null || calGrades.Count == 0)
            {
                return 0;
            }
            foreach (CalGradeInfo gradeInfo in calGrades) 
            {
                bool isThisGrade = true;
            
                if (gradeInfo.Max!= null) { 
                    if ( gradeInfo.isMaxExist == 1 && cValue.CompareTo(gradeInfo.Max)<=0)
                    {
                    }else if(gradeInfo.isMaxExist == 0 && cValue.CompareTo(gradeInfo.Max) < 0)
                    {
                    }
                    else
                    {
                        isThisGrade = false;
                    }
                }
                if (gradeInfo.Min != null)
                {
                    if (gradeInfo.isMinExist == 1 && cValue.CompareTo(gradeInfo.Min) >= 0)
                    {
                    }
                    else if (gradeInfo.isMinExist == 0 && cValue.CompareTo(gradeInfo.Min) > 0)
                    {
                    }
                    else
                    {
                        isThisGrade = false;
                    }
                }
                if (isThisGrade)
                {
                    order = gradeInfo.gradeOrder;
                    break;
                }
                else
                {
                    order = gradeInfo.gradeOrder;
                }
            }
            totalCutGrade = Math.Max(order, totalCutGrade);
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
        return order;
    }
    private string calGrade_TOTAL_DEPTH(double avg)
    {
        string result = "";
        int order = calGrade("TOTAL_DEPTH", avg * 100);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_TABLE(double min,double max)
    {
        string result = "";
        int order1 = calGrade("TABLE", min * 100);
        int order2 = calGrade("TABLE", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_CROWN_ANGLE(double min, double max)
    {
        string result = "";
        int order1 = calGrade("CROWN_ANGLE", min);
        int order2 = calGrade("CROWN_ANGLE", max);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_CROWN_HEIGHT(double min, double max)
    {
        string result = "";
        int order1 = calGrade("CROWN_HEIGHT", min * 100);
        int order2 = calGrade("CROWN_HEIGHT", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_GIRDLE(double min, double max)
    {
        string result = "";
        int order1 = calGrade("GIRDLE", min * 100);
        int order2 = calGrade("GIRDLE", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_PAV_ANGLE(double min, double max)
    {
        string result = "";
        int order1 = calGrade("PAV_ANGLE", min);
        int order2 = calGrade("PAV_ANGLE", max);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_PAV_DEPTH(double min, double max)
    {
        string result = "";
        int order1 = calGrade("PAV_DEPTH", min * 100);
        int order2 = calGrade("PAV_DEPTH", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_CULET(double avg)
    {
        string result = "";
        int order = calGrade("CULET", avg * 100);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_STAR(double min, double max)
    {
        string result = "";
        int order1 = calGrade("STAR", min * 100);
        int order2 = calGrade("STAR", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    private string calGrade_LOWER_HALVES_RATIO(double min, double max)
    {
        string result = "";
        int order1 = calGrade("LOWER_HALVES_RATIO", min * 100);
        int order2 = calGrade("LOWER_HALVES_RATIO", max * 100);
        int order = Math.Max(order1, order2);
        result = GetGradeName(order);
        return result;
    }
    #endregion
    #region 参数列表行编辑
    private DataInfo getDIAMETER(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "DIAMETER";
        info.TestItemName = GetName("DIAMETER");
        info.Avg = FormatDouble_D(result.measurements.DIAMETER);
        info.Dev = result.measurements.DIAMETER_DEV.ToString(digitsFormat);
        info.Min = FormatDouble_D(result.measurements.M1);
        info.Max = FormatDouble_D(result.measurements.M2);
        return info;
    }
    private DataInfo getTOTAL_DEPTH(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "TOTAL_DEPTH";
        info.TestItemName = GetName("TOTAL_DEPTH");
        info.Avg = FormatDouble_Avg(result.measurements.TOTAL_DEPTH*100,Accuracy.ZD1);
        info.CutLevel = calGrade_TOTAL_DEPTH(result.measurements.TOTAL_DEPTH);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getTABLE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "TABLE";
        info.TestItemName = GetName("TABLE");
        info.Avg = FormatDouble_Avg(result.measurements.TABLE*100, Accuracy.ZD5);
        info.Min = FormatDouble_P(result.measurements.TABLE_MIN);
        info.Max = FormatDouble_P(result.measurements.TABLE_MAX);
        info.CutLevel = calGrade_TABLE(result.measurements.TABLE_MIN, result.measurements.TABLE_MAX);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getCROWN_ANGLE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "CROWN_ANGLE";
        info.TestItemName = GetName("CROWN_ANGLE");
        info.Avg = FormatDouble_Avg(result.measurements.CROWN_ANGLE, Accuracy.ZD5);
        info.Dev = FormatDouble_A(result.measurements.CROWN_ANGLE_DEV);
        info.Min = FormatDouble_A(result.measurements.CROWN_ANGLE_MIN);
        info.Max = FormatDouble_A(result.measurements.CROWN_ANGLE_MAX);
        info.CutLevel = calGrade_CROWN_ANGLE(result.measurements.CROWN_ANGLE_MIN, result.measurements.CROWN_ANGLE_MAX);
        return info;
    }

    private DataInfo getCROWN_HEIGHT(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "CROWN_HEIGHT";
        info.TestItemName = GetName("CROWN_HEIGHT");
        info.Avg = FormatDouble_Avg(result.measurements.CROWN_HEIGHT * 100, Accuracy.ZD5);
        info.Dev = FormatDouble_P(result.measurements.CROWN_H_DEV);
        info.Min = FormatDouble_P(result.measurements.CROWN_H_MIN);
        info.Max = FormatDouble_P(result.measurements.CROWN_H_MAX);
        info.CutLevel = calGrade_CROWN_HEIGHT(result.measurements.CROWN_H_MIN, result.measurements.CROWN_H_MAX);
        return info;
    }

    private DataInfo getGIRDLE_BEZEL(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "GIRDLE_BEZEL";
        info.TestItemName = GetName("GIRDLE_BEZEL");
        info.Avg = FormatDouble_Avg(result.measurements.GIRDLE_BEZEL * 100, Accuracy.ZD1);
        info.Dev = FormatDouble_P(result.measurements.GIRDLE_BEZEL_DEV);
        info.Min = FormatDouble_P(result.measurements.GIRDLE_BEZEL_MIN);
        info.Max = FormatDouble_P(result.measurements.GIRDLE_BEZEL_MAX);
        return info;
    }

    private DataInfo getGIRDLE_BONE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "GIRDLE_BONE";
        info.TestItemName = GetName("GIRDLE_BONE");
        info.Avg = FormatDouble_Avg(result.measurements.GIRDLE_BONE * 100, Accuracy.ZD1);
        info.Min = FormatDouble_P(result.measurements.GIRDLE_BONE_MIN);
        info.Max = FormatDouble_P(result.measurements.GIRDLE_BONE_MAX);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getGIRDLE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "GIRDLE";
        info.TestItemName = GetName("GIRDLE");
        info.Avg = FormatDouble_Avg(result.measurements.GIRDLE_VALLEY * 100, Accuracy.ZD1);
        info.Dev = FormatDouble_P(result.measurements.GIRDLE_VALLEY_DEV);
        info.Min = FormatDouble_P(result.measurements.GIRDLE_VALLEY_MIN);
        info.Max = FormatDouble_P(result.measurements.GIRDLE_VALLEY_MAX);
        info.CutLevel = calGrade_GIRDLE(result.measurements.GIRDLE_VALLEY_MIN, result.measurements.GIRDLE_VALLEY_MAX);
        return info;
    }

    private DataInfo getPAV_ANGLE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "PAV_ANGLE";
        info.TestItemName = GetName("PAV_ANGLE");
        info.Avg = FormatDouble_Avg(result.measurements.PAV_ANGLE, Accuracy.ZD1);
        info.Dev = FormatDouble_A(result.measurements.PAV_ANGLE_DEV);
        info.Min = FormatDouble_A(result.measurements.PAV_ANGLE_MIN);
        info.Max = FormatDouble_A(result.measurements.PAV_ANGLE_MAX);
        info.CutLevel = calGrade_PAV_ANGLE(result.measurements.PAV_ANGLE_MIN, result.measurements.PAV_ANGLE_MAX);
        return info;
    }

    private DataInfo getPAV_DEPTH(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "PAV_DEPTH";
        info.TestItemName = GetName("PAV_DEPTH");
        info.Avg = FormatDouble_Avg(result.measurements.PAV_DEPTH*100, Accuracy.ZD5);
        info.Dev = FormatDouble_P(result.measurements.PAV_DEPTH_DEV);
        info.Min = FormatDouble_P(result.measurements.PAV_DEPTH_MIN);
        info.Max = FormatDouble_P(result.measurements.PAV_DEPTH_MAX);
        info.CutLevel = calGrade_PAV_DEPTH(result.measurements.PAV_DEPTH_MIN, result.measurements.PAV_DEPTH_MAX);
        return info;
    }

    private DataInfo getSTAR(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "STAR";
        info.TestItemName = GetName("STAR");
        info.Avg = FormatDouble_Avg(result.measurements.STAR*100, Accuracy.Z5);
        info.Min = FormatDouble_P(result.measurements.STAR_MIN);
        info.Max = FormatDouble_P(result.measurements.STAR_MAX);
        info.CutLevel = calGrade_STAR(result.measurements.STAR_MIN, result.measurements.STAR_MAX);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getLOWER_HALVES_RATIO(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "LOWER_HALVES_RATIO";
        info.TestItemName = GetName("LOWER_HALVES_RATIO");
        info.Avg = FormatDouble_Avg(result.measurements.LOWER_HALVES_RATIO*100, Accuracy.Z5);
        info.Min = FormatDouble_P(result.measurements.LOWER_HALVES_RATIO_MIN);
        info.Max = FormatDouble_P(result.measurements.LOWER_HALVES_RATIO_MAX);
        info.CutLevel = calGrade_LOWER_HALVES_RATIO(result.measurements.LOWER_HALVES_RATIO_MIN, result.measurements.LOWER_HALVES_RATIO_MAX);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getCULET(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "CULET";
        info.TestItemName = GetName("CULET");
        info.Avg = FormatDouble_Avg(result.measurements.CULET * 100, Accuracy.ZD1);
        info.CutLevel = calGrade_CULET(result.measurements.CULET);
        info.isEnabled = false;
        return info;
    }

    private DataInfo getTOC(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "TOC";
        info.TestItemName = GetName("TOC");
        info.Avg = FormatDouble_Avg(result.measurements.TOC * 100, Accuracy.ZD1);
        return info;
    }

    private DataInfo getCOC(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "COC";
        info.TestItemName = GetName("COC");
        info.Avg = FormatDouble_Avg(result.measurements.COC*100, Accuracy.ZD1);
        return info;
    }

    private DataInfo getTWIST(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "TWIST";
        info.TestItemName = GetName("TWIST");
        info.Avg = FormatDouble_Avg(result.measurements.TWIST, Accuracy.ZD1);
        info.Dev = FormatDouble_A(result.measurements.TWIST_DEV);
        info.Min = FormatDouble_A(result.measurements.TWIST_MIN);
        info.Max = FormatDouble_A(result.measurements.TWIST_MAX);
        return info;
    }

    private DataInfo getCULET_TO_TABLE(AlgorithmResultEntity result)
    {
        DataInfo info = new DataInfo();
        info.TestItemId = "CULET_TO_TABLE";
        info.TestItemName = GetName("CULET_TO_TABLE");
        info.Avg = FormatDouble_Avg(result.measurements.CULET_TO_TABLE*100,Accuracy.ZD1);
        return info;
    }
#endregion
    private double CalWight(AlgorithmResultEntity result)
    {
        // var M1 = result.measurements.M1;
        // var M2 = result.measurements.M2;
        // var M3 = result.measurements.M3;
        // var wight = Square((M1+M2)/2)*M3*0.0061;
        var VOLUME = result.measurements.VOLUME;
        var wight = VOLUME/57;
        Wight = wight.ToString("f3");
        return wight;
    }

    private double Square(double m)
    {
        return m*m;
    }
    private void AutoSave()
    {
        if (string.IsNullOrEmpty(DiamondCode))
        {
            return;
        }
        else
        {
            string fullPath = Path.Combine(getFilePath(), this.DiamondCode);
            if (FileSaveEnabled("Txt"))
            {
                TxtFile(fullPath);
            }
            if (FileSaveEnabled("Excel"))
            {
                ExcelFile(fullPath);
            }
        }
        
    }
    public void SaveFile(object param)
    {
        if (string.IsNullOrEmpty(DiamondCode))
        {
            MessageBox messageBox = new MessageBox();
            MessageBoxResult boxResult = messageBox.ShowInput(MultilingualHelper.getString("UpdateDiamondCode"), out string inputStr,
                MultilingualHelper.getString("ok"),
                MultilingualHelper.getString("Cancel")
                );
            if (boxResult == MessageBoxResult.OK && inputStr.Length > 0)
            {
                this.DiamondCode = inputStr;
            }
            else
            {
                return;
            }
        }
        if (!Directory.Exists(getFilePath()))
        {
            new MessageBox().Show(MultilingualHelper.getString("FilePathNotExists"));
            return;
        }
        string fullPath = Path.Combine(getFilePath(), this.DiamondCode);
        ExportFile(fullPath);
        SaveTestResult(SaveStatus.Save);
        isSaved = true;
    }
    private string getFilePath()
    {
        string defultFilePath = "D://DTest//";
        string sql = $"SELECT SETTING_P FROM SETTING WHERE SETTING_ID = 'FilePath'";
        DataTable data = DataBaseHelper.ExecuteQuery(sql);
        if (data!= null && data.Rows.Count>0)
        {
            defultFilePath = data.Rows[0]["SETTING_P"].ToString();
        }
        if(File.Exists(defultFilePath)){
            return defultFilePath;
        }
        else
        {
            Directory.CreateDirectory(defultFilePath);
            return defultFilePath;
        }
    }
    #region 文件导出相关
    public void SaveAs(object param)
    {
        try
        {
            if (string.IsNullOrEmpty(DiamondCode))
            {
                MessageBox messageBox = new MessageBox();
                MessageBoxResult boxResult = messageBox.ShowInput(MultilingualHelper.getString("UpdateDiamondCode"), out string inputStr,
                    MultilingualHelper.getString("ok"),
                    MultilingualHelper.getString("Cancel")
                    );

                if (boxResult == MessageBoxResult.OK && inputStr.Length > 0)
                {
                    this.DiamondCode = inputStr;
                }
                else
                {
                    return;
                }
            }
            using (var folderBrowserDlg = new FolderBrowserDialog())
            {
                // 创建SaveFileDialog实例
                SaveFileDialog saveFileDialog = new()
                {
                    Filter = "所有文件 (*.*)|*.*", // 文件类型过滤器
                    FileName = this.DiamondCode // 默认文件名
                };

                // 显示对话框并检查结果
                bool? result = saveFileDialog.ShowDialog();
                if (result == true)
                {
                    // 获取用户选择的文件路径
                    string filePath = saveFileDialog.FileName;
                    if (!saveFileDialog.CheckPathExists)
                    {
                        new MessageBox().Show(MultilingualHelper.getString("FilePathNotExists"));
                        return;
                    }
                    //ExportFile(filePath);
                    TxtFile(filePath);
                }
            }
            SaveTestResult(SaveStatus.SaveAs);
            //PrintLabel();
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }
    private async void ExportFile(string filePath)
    {
        try { 
            ExportDialog exportDialog = new ExportDialog();
            var tcs = new TaskCompletionSource<bool>();
            var progressTask = Task.Run(() => Application.Current.Dispatcher.Invoke(() => {
                exportDialog.Closed += (s, e) => tcs.SetResult(true);
                exportDialog.ShowDialog();
            }
             ));
            await Task.Run(async () =>
            {
                int count = saveFileCount();
                int index = 1;
                if (FileSaveEnabled("Txt")) {
                    exportDialog.Dispatcher.Invoke(() =>
                    {
                        exportDialog.setValue($"Txt File({index++}/{count})");
                    });
                    TxtFile(filePath);
                }
                if (FileSaveEnabled("Excel"))
                {
                    exportDialog.Dispatcher.Invoke(() =>
                    {
                        exportDialog.setValue($"Excel File({index++}/{count})");
                    });
                    ExcelFile(filePath);
                }
                if (FileSaveEnabled("Stl"))
                {
                    exportDialog.Dispatcher.Invoke(() =>
                    {
                        exportDialog.setValue($"STL File({index++}/{count})");
                    });
                    await Task.Delay(100);
                    STLFile(filePath);
                }
                if (FileSaveEnabled("Dat"))
                {
                    exportDialog.Dispatcher.Invoke(() =>
                    {
                        exportDialog.setValue($"DAT File({index++}/{count})");
                    });
                    await DatFile(filePath);
                }
                exportDialog.Dispatcher.Invoke(() =>
                {
                    exportDialog.setValue("Success");
                });
                //DataConver(filePath);
                // exportDialog.Dispatcher.Invoke(() =>
                // {
                //     exportDialog.setValue("Success");
                // });
            });
            await Task.Delay(500);
            exportDialog.Close();
        }
        catch(Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }
    private bool FileSaveEnabled(string Key)
    {
        bool result = false;
        string sql = $"SELECT SETTING_P FROM SETTING WHERE SETTING_ID = '{Key}FileChecked'";
        DataTable data = DataBaseHelper.ExecuteQuery(sql);
        if (data != null && data.Rows.Count>0)
        {
            bool.TryParse(data.Rows[0]["SETTING_P"].ToString(),out result);
        }
        return result;
    }
    private int saveFileCount()
    {
        int result = 0;
        string sql = $"SELECT SETTING_P FROM SETTING WHERE SETTING_ID LIKE '%FileChecked'";
        DataTable data = DataBaseHelper.ExecuteQuery(sql);
        if (data != null)
        {
            result = data.Rows.Count;
        }
        return result;
    }
    /// <summary>
    /// txt文件导出
    /// </summary>
    /// <param name="filePath"></param>
    private void TxtFile(string filePath)
    {
        try
        {
            string fileName = filePath + ".txt";
            using (var file = File.Create(fileName))
            {
                Measurements info = algorithmResult.measurements;
                StreamWriter stream = new StreamWriter(file);
                stream.WriteLine($"IGI REPORT NUMBER={DiamondCode}");
                stream.WriteLine($"SARIN WEIGHT={Wight}");
                stream.WriteLine($"M1={info.M1}");
                stream.WriteLine($"M2={info.M2}");
                stream.WriteLine($"M3={info.M3}");
                stream.WriteLine($"TABLE={info.TABLE*100}");
                stream.WriteLine($"TABLE MIN={info.TABLE_MIN * 100}");
                stream.WriteLine($"TABLE MAX={info.TABLE_MAX * 100}");
                stream.WriteLine($"CROWN HEIGHT={info.CROWN_HEIGHT * 100}");
                stream.WriteLine($"CROWN H MIN={info.CROWN_H_MIN * 100}");
                stream.WriteLine($"CROWN H MAX={info.CROWN_H_MAX * 100}");
                stream.WriteLine($"CROWN ANGLE={info.CROWN_ANGLE}");
                stream.WriteLine($"CROWN ANGLE MIN={info.CROWN_ANGLE_MIN}");
                stream.WriteLine($"CROWN ANGLE MAX={info.CROWN_ANGLE_MAX}");
                stream.WriteLine($"PAV DEPTH={info.PAV_DEPTH * 100}");
                stream.WriteLine($"PAV DEPTH MIN={info.PAV_DEPTH_MIN * 100}");
                stream.WriteLine($"PAV DEPTH MAX={info.PAV_DEPTH_MAX * 100}");
                stream.WriteLine($"PAV ANGLE={info.PAV_ANGLE}");
                stream.WriteLine($"PAV ANGLE MIN={info.PAV_ANGLE_MIN}");
                stream.WriteLine($"PAV ANGLE MAX={info.PAV_ANGLE_MAX}");
                stream.WriteLine($"GIRDLE={info.GIRDLE * 100}");
                stream.WriteLine($"GIRDLE MIN={info.GIRDLE_MIN * 100}");
                stream.WriteLine($"GIRDLE MAX={info.GIRDLE_MAX * 100}");
                stream.WriteLine($"TOTAL DEPTH={info.TOTAL_DEPTH * 100}");
                stream.WriteLine($"CULET={info.CULET*100}");
                stream.WriteLine($"MACHINE={machine}");
                stream.WriteLine($"CUTGRADE={GetGradeEnName(totalCutGrade.ToString())}");
                stream.WriteLine($"LW RATIO={info.LW_RATIO}");
                stream.WriteLine($"DS={DS}");
                stream.WriteLine($"COC={info.COC * 100}");
                stream.WriteLine($"USER={username}");
                string TABLE_GRADE = DtResults.Where(x => "TABLE".Equals(x.TestItemId)).Select(x=>x.CutLevel).First()??"";
                stream.WriteLine($"TABLE GRADE={GetGradeEnName(GetGradeOrder(TABLE_GRADE))}");
                string CROWN_H_GRADE = DtResults.Where(x => "CROWN_HEIGHT".Equals(x.TestItemId)).Select(x => x.CutLevel).First() ?? "";
                stream.WriteLine($"CROWN H GRADE={GetGradeEnName(GetGradeOrder(CROWN_H_GRADE))}");
                string CROWN_ANGLE_GRADE = DtResults.Where(x => "CROWN_ANGLE".Equals(x.TestItemId)).Select(x => x.CutLevel).First() ?? "";
                stream.WriteLine($"CROWN ANGLE GRADE={GetGradeEnName(GetGradeOrder(CROWN_ANGLE_GRADE))}");
                string PAV_DEPTH_GRADE = DtResults.Where(x => "PAV_DEPTH".Equals(x.TestItemId)).Select(x => x.CutLevel).First() ?? "";
                stream.WriteLine($"PAV DEPTH GRADE={GetGradeEnName(GetGradeOrder(PAV_DEPTH_GRADE))}");
                string PAV_ANGLE_GRADE = DtResults.Where(x => "PAV_ANGLE".Equals(x.TestItemId)).Select(x => x.CutLevel).First() ?? "";
                stream.WriteLine($"PAV ANGLE GRADE={GetGradeEnName(GetGradeOrder(PAV_ANGLE_GRADE))}");
                string TD_GRADE = DtResults.Where(x => "TOTAL_DEPTH".Equals(x.TestItemId)).Select(x => x.CutLevel).First() ?? "";
                stream.WriteLine($"TD GRADE={GetGradeEnName(GetGradeOrder(TD_GRADE))}");
                stream.WriteLine($"TA={info.TA}");
                stream.WriteLine($"LGF={info.LGF * 100}");
                stream.WriteLine($"STAR={info.STAR * 100}");
                stream.Close();
            }
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }
    /// <summary>
    /// excel文件导出
    /// </summary>
    /// <param name="filePath"></param>
    private void ExcelFile(string filePath)
    {
        try
        {
            string fileName = filePath + ".xlsx";
            IWorkbook workbook = new XSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("Sheet1");

            int col = 0;
            int row = 0;
            var dataRow = sheet.CreateRow(row);
            dataRow.CreateCell(col++).SetCellValue("Measurement1");
            dataRow.CreateCell(col++).SetCellValue("Measurement2");
            dataRow.CreateCell(col++).SetCellValue("Measurement3");
            dataRow.CreateCell(col++).SetCellValue("Table");
            dataRow.CreateCell(col++).SetCellValue("Crown Height");
            dataRow.CreateCell(col++).SetCellValue("Pavilion Depth");
            dataRow.CreateCell(col++).SetCellValue("Total Depth");
            dataRow.CreateCell(col++).SetCellValue("Crown Angle");
            dataRow.CreateCell(col++).SetCellValue("Pavilion Angle");
            dataRow.CreateCell(col++).SetCellValue("Culet Size");
            dataRow.CreateCell(col++).SetCellValue("Girdle Percent");
            dataRow.CreateCell(col++).SetCellValue("Girdle Name");
            dataRow.CreateCell(col++).SetCellValue("POL or Pol/Sym");
            dataRow.CreateCell(col++).SetCellValue("SYM");
            dataRow.CreateCell(col++).SetCellValue("CUT-PROP");
            row++;
            col = 0;
            dataRow = sheet.CreateRow(row);
            Measurements info = algorithmResult.measurements;
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.M1)}(mm)");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.M2)}(mm)");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.M3)}(mm)");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_P(info.TABLE)}%");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_P(info.CROWN_HEIGHT)}%");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_P(info.PAV_DEPTH)}%");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_P(info.TOTAL_DEPTH)}%");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.CROWN_ANGLE)}°");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.PAV_ANGLE)}°");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_A(info.CULET_SIZE)}(mm)");
            dataRow.CreateCell(col++).SetCellValue($"{FormatDouble_P(info.GIRDLE)}%");
            // 腰部厚度英文
            dataRow.CreateCell(col++).SetCellValue($"{calGirdleName(info)}");
            dataRow.CreateCell(col++).SetCellValue($"");
            string sysmlevel = "";
            if (!string.IsNullOrEmpty(SymLevelTotal))
            {
                sysmlevel = GetGradeEnName(GetGradeOrder(SymLevelTotal ?? ""));
            }
            dataRow.CreateCell(col++).SetCellValue($"{sysmlevel}");
            dataRow.CreateCell(col++).SetCellValue($"{GetGradeEnName(GetGradeOrder(CutLevelTotal))}");

            // 保存Excel文件
            using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            {
                workbook.Write(stream);
            }
        }
        catch (Exception ex)
        {
            new MessageBox().Show($"{MultilingualHelper.getString("ApplicationError")}{ex.Message}");
            Logger.Error($"全局异常捕获:{ex.Message}", ex);
        }
    }

    private string calGirdleName(Measurements info)
    {
        string girdleName = "";
        // 有问题 问题1 1.6时为thin to slight thick,那么 thin为什么时刻出现
        // 问题2 假如最小值为very thin,最大值为thick时用哪个 
        decimal min = Convert.ToDecimal(info.GIRDLE_MIN * 100);
        girdleName += calGirdleName(min,true);
        girdleName += " to ";
        decimal max = Convert.ToDecimal(info.GIRDLE_MAX * 100);
        girdleName += calGirdleName(max,false);
        return girdleName;
    }
    private string calGirdleName(decimal cValue,bool isMin)
    {
        string girdleName = "";
        List<CalGradeInfo> calGrades = GetCalGradeInfos("GIRDLE");
        int order = 1;
        bool isthin = false;
        bool isthick = false;
        foreach (CalGradeInfo gradeInfo in calGrades)
        {
            bool isThisGrade = true;

            if (gradeInfo.Max != null)
            {
                if (gradeInfo.isMaxExist == 1 && cValue.CompareTo(gradeInfo.Max) <= 0)
                {
                }
                else if (gradeInfo.isMaxExist == 0 && cValue.CompareTo(gradeInfo.Max) < 0)
                {
                }
                else
                {
                    isthick = true;
                    isThisGrade = false;
                }
            }
            if (gradeInfo.Min != null)
            {
                if (gradeInfo.isMinExist == 1 && cValue.CompareTo(gradeInfo.Min) >= 0)
                {
                }
                else if (gradeInfo.isMinExist == 0 && cValue.CompareTo(gradeInfo.Min) > 0)
                {
                }
                else
                {
                    isthin = true;
                    isThisGrade = false;
                }
            }
            if (isThisGrade)
            {
                break;
            }
            else
            {
                order++;
            }
        }
        Dictionary<int, string> thinDic = new Dictionary<int, string>();
        thinDic.Add(1, "Thin");
        thinDic.Add(2,"Thin");
        thinDic.Add(3, "Very Thin");
        thinDic.Add(4, "Extremely Thin");
        Dictionary<int, string> thickDic = new Dictionary<int, string>();
        thickDic.Add(1, "Slightly Thick");
        thickDic.Add(2, "Slightly Thick");
        thickDic.Add(3, "Thick");
        thickDic.Add(4, "VeryThick");
        if (order == 1)
        {
            if (isMin)
            {
                girdleName = thinDic[order];
            }
            else
            {
                girdleName = thickDic[order];
            }
        }
        else if (isthin) 
        {
            if (order > 4) {
                girdleName = "Extremely Thin";
            }
            else
            {
                girdleName = thinDic[order];
            }
        }
        else if (isthick)
        {
            if (order > 4)
            {
                girdleName = "VeryThick";
            }
            else
            { 
                girdleName = thickDic[order];
            }
        }
        return girdleName;
    }
    /// <summary>
    /// 直径的小数格式化
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private string FormatDouble_D(double value)
    {
        return value.ToString("f2");
    }
    /// <summary>
    /// 百分比用的小数格式化
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private string FormatDouble_P(double value)
    {
        return (Math.Floor(value*1000)/10).ToString(digitsFormat);
    }
    private string FormatDouble_P2(double value)
    {
        return (Math.Floor(value * 10000) / 100).ToString("f2");
    }
    /// <summary>
    /// 百分比用的小数格式化
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private string FormatDouble_Avg(double value, Accuracy accuracy)
    {
        string result = "";
        switch (accuracy)
        {
            case Accuracy.ZDZ1:
                result = (Math.Floor(value * 100) / 100).ToString("f2");
                break;
            case Accuracy.ZD1:
                result = (Math.Floor(value * 10) / 10).ToString(digitsFormat);
                break;
            case Accuracy.ZD5:
                result = (RoundFiveDownSixUp(value * 2) / 2).ToString("f1");
                break;
            case Accuracy.Z5:
                result = (RoundFiveDownSixUp(value / 5) * 5).ToString();
                break;
        }
        return result;
    }
    private static double RoundFiveDownSixUp(double value)
    {
        // 提取整数部分
        double integerPart = Math.Truncate(value);
        // 提取小数部分
        double fractionalPart = value - integerPart;

        // 判断小数部分是否大于 0.5
        if (fractionalPart > 0.5)
        {
            return integerPart + 1; // 大于 0.5,进一
        }
        else
        {
            return integerPart; // 小于或等于 0.5,舍去
        }
    }
    /// <summary>
    /// 直接值(角度,直径)用的小数格式化
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private string FormatDouble_A(double value)
    {
        return (Math.Floor(value * 10) / 10).ToString(digitsFormat);
    }
    private async Task DatFile(string filePath)
    {
        //File.Create(filePath + ".dat").Close();
        await ViewportData.SaveAsToVedioFile(filePath + ".mp4");
    }
    private async Task STLFile(string filePath)
    {
        //File.Create(filePath + ".stl").Close();
        await ViewportData.SaveAsToStlFile(filePath + ".stl");
    } 
    private void DataConver(string filePath)
    {
        //File.Create(filePath + ".stl").Close();
        ViewportData.ConvertMp4ToDat(filePath + ".mp4",filePath + ".dat");
    }
    #endregion

    #region 各类名称取得
    private string GetName(string id)
    {
        return Name.getNameById(id);
    }
    private string GetGradeName(decimal order)
    {
        
        string name = GradeList.AsEnumerable().Where(x => order.ToString().Equals(x["GRADE_ORDER"].ToString()))
            .Select(x=>x[MultilingualHelper.getString("NameType")].ToString()).FirstOrDefault("");
        // DB没关联
        // Dictionary<int, string> dictionary = new();
        // dictionary.Add(0, "");
        // dictionary.Add(1,"极好");
        // dictionary.Add(2, "很好");
        // dictionary.Add(3, "好");
        // dictionary.Add(4, "一般");
        // dictionary.Add(5, "差");
        // return dictionary[order];
        return name;
    }
    private string GetGradeOrder(string Grade)
    {
        string order = GradeList.AsEnumerable().Where(x => Grade.Equals(x[MultilingualHelper.getString("NameType")].ToString()))
            .Select(x=>x["GRADE_ORDER"].ToString()).FirstOrDefault("");
        // DB没关联
        // Dictionary<string, int> dictionary = new();
        // dictionary.Add("极好", 1);
        // dictionary.Add("很好", 2);
        // dictionary.Add("好", 3);
        // dictionary.Add("一般", 4);
        // dictionary.Add("差", 5);
        // return dictionary[Grade];
        return order;
    }
    private string GetGradeEnName(string order)
    {
        string name = GradeList.AsEnumerable().Where(x => order.Equals(x["GRADE_ORDER"].ToString()))
            .Select(x=>x["EN_ALL_NAME"].ToString()).FirstOrDefault("");
        // DB没关联
        // Dictionary<int, string> dictionary = new();
        // dictionary.Add(1, "EXCELLENT-Ideal");
        // dictionary.Add(2, "EXCELLENT");
        // dictionary.Add(3, "VERY GOOD");
        // dictionary.Add(4, "GOOD");
        // dictionary.Add(5, "FAIR-POOR");
        // return dictionary[order];
        return name;
    }
    #endregion

    /// <summary>
    /// 修改对称性等级
    /// </summary>
    /// <param name="norm"></param>
    public void ChangeSym(object norm)
    {
        decimal? order = this.DtResults.Select(x => x.SymLevel).Max();
        if (order.HasValue)
        {
            totalSymGrade = order.Value;
            SymLevelTotal = GetGradeName((decimal)order.Value);
        }
        else
        {
            SymLevelTotal = string.Empty;
        }
    }

    public RowDetail getSelectData(string testItemId)
    {
        RowDetail row = new RowDetail();
        row.itemName = GetName(testItemId);
        ViewportData.mockSel(testItemId);
        var data = DtResults.Where(x => x.TestItemId == testItemId).FirstOrDefault();
        row.Avg = data != null ? data.Avg : "";
        row.Dev = data != null ? data.Dev : "";
        row.Max = data != null ? data.Max : "";
        row.Min = data != null ? data.Min : "";
        row.CutLevel = data != null ? data.CutLevel : "";
        row.SymLevel = GetGradeName(data != null ? data.SymLevel??0 : 0);
        setDetailItems(row, testItemId);
        this.SelRowDataDetail = row;
        return row;
    }
    private void setDetailItems(RowDetail row,string TestItemId)
    {
        if ("DIAMETER".Equals(TestItemId))
        {
            setDIAMETER_DETAIL(row);
        }
        else if ("TABLE".Equals(TestItemId))
        {
            setTABLE_DETAIL(row);
        }
        else if ("CROWN_HEIGHT".Equals(TestItemId))
        {
            setCROWN_HEIGHT_DETAIL(row);
        }
        else if ("CROWN_ANGLE".Equals(TestItemId))
        {
            setCROWN_ANGLE_DETAIL(row);
        }
        else if ("PAV_DEPTH".Equals(TestItemId))
        {
            setPAV_DEPTH_DETAIL(row);
        }
        else if ("PAV_ANGLE".Equals(TestItemId))
        {
            setPAV_ANGLE_DETAIL(row);
        }
        else if ("GIRDLE_BEZEL".Equals(TestItemId))
        {
            setGIRDLE_BEZEL_DETAIL(row);
        }
        else if ("GIRDLE_BONE".Equals(TestItemId))
        {
            setGIRDLE_BONE_DETAIL(row);
        }
        else if ("GIRDLE".Equals(TestItemId))
        {
            setGIRDLE_VALLEY_DETAIL(row);
        }
        else if ("STAR".Equals(TestItemId))
        {
            setSTAR_DETAIL(row);
        }
        else if ("LOWER_HALVES_RATIO".Equals(TestItemId))
        {
            setLOWER_HALVES_RATIO_DETAIL(row);
        }
        else if ("TWIST".Equals(TestItemId))
        {
            setTWIST_DETAIL(row);
        }
    }
    private void calIndex(RowDetail row)
    {
        // 最大值的Index计算
        if (row.Max.Equals(row.item1))
        {
            row.MaxIndex = 0;
        }
        else if(row.Max.Equals(row.item2))
        {
            row.MaxIndex = 1;
        }
        else if (row.Max.Equals(row.item3))
        {
            row.MaxIndex = 2;
        }
        else if (row.Max.Equals(row.item4))
        {
            row.MaxIndex = 3;
        }
        else if (row.Max.Equals(row.item5))
        {
            row.MaxIndex = 4;
        }
        else if (row.Max.Equals(row.item6))
        {
            row.MaxIndex = 5;
        }
        else if (row.Max.Equals(row.item7))
        {
            row.MaxIndex = 6;
        }
        else if (row.Max.Equals(row.item8))
        {
            row.MaxIndex = 7;
        }
        // 最小值的Index计算
        if (row.Min.Equals(row.item1))
        {
            row.MinIndex = 0;
        }
        else if (row.Min.Equals(row.item2))
        {
            row.MinIndex = 1;
        }
        else if (row.Min.Equals(row.item3))
        {
            row.MinIndex = 2;
        }
        else if (row.Min.Equals(row.item4))
        {
            row.MinIndex = 3;
        }
        else if (row.Min.Equals(row.item5))
        {
            row.MinIndex = 4;
        }
        else if (row.Min.Equals(row.item6))
        {
            row.MinIndex = 5;
        }
        else if (row.Min.Equals(row.item7))
        {
            row.MinIndex = 6;
        }
        else if (row.Min.Equals(row.item8))
        {
            row.MinIndex = 7;
        }
    }
    private void setDIAMETER_DETAIL(RowDetail row)
    {
        DiameterDetail diameterDetail = algorithmResult.measurements.DIAMETER_DETAIL;
        row.item1 = FormatDouble_D(diameterDetail.DIAMETER_1);
        row.item2 = FormatDouble_D(diameterDetail.DIAMETER_2);
        row.item3 = FormatDouble_D(diameterDetail.DIAMETER_3);
        row.item4 = FormatDouble_D(diameterDetail.DIAMETER_4);
        row.item5 = FormatDouble_D(diameterDetail.DIAMETER_5);
        row.item6 = FormatDouble_D(diameterDetail.DIAMETER_6);
        row.item7 = FormatDouble_D(diameterDetail.DIAMETER_7);
        row.item8 = FormatDouble_D(diameterDetail.DIAMETER_8);
        calIndex(row);
    }
    private void setTABLE_DETAIL(RowDetail row)
    {
        TableDetail diameterDetail = algorithmResult.measurements.TABLE_DETAIL;
        row.item1 = FormatDouble_P(diameterDetail.TABLE_1);
        row.item2 = FormatDouble_P(diameterDetail.TABLE_2);
        row.item3 = FormatDouble_P(diameterDetail.TABLE_3);
        row.item4 = FormatDouble_P(diameterDetail.TABLE_4);
        calIndex(row);
    }
    private void setCROWN_HEIGHT_DETAIL(RowDetail row)
    {
        CrownHeightDetail crownHeightDetail = algorithmResult.measurements.CROWN_HEIGHT_DETAIL;
        row.item1 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_1);
        row.item2 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_2);
        row.item3 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_3);
        row.item4 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_4);
        row.item5 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_5);
        row.item6 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_6);
        row.item7 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_7);
        row.item8 = FormatDouble_P(crownHeightDetail.CROWN_HEIGHT_8);
        calIndex(row);
    }
    private void setCROWN_ANGLE_DETAIL(RowDetail row)
    {
        CrownAngleDetail crownAngleDetail = algorithmResult.measurements.CROWN_ANGLE_DETAIL;
        row.item1 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_1);
        row.item2 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_2);
        row.item3 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_3);
        row.item4 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_4);
        row.item5 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_5);
        row.item6 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_6);
        row.item7 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_7);
        row.item8 = FormatDouble_A(crownAngleDetail.CROWN_ANGLE_8);
        calIndex(row);
    }
    private void setPAV_DEPTH_DETAIL(RowDetail row)
    {
        PavDepthDetail pavDepthDetail = algorithmResult.measurements.PAV_DEPTH_DETAIL;
        row.item1 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_1);
        row.item2 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_2);
        row.item3 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_3);
        row.item4 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_4);
        row.item5 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_5);
        row.item6 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_6);
        row.item7 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_7);
        row.item8 = FormatDouble_P(pavDepthDetail.PAV_DEPTH_8);
        calIndex(row);
    }
    private void setPAV_ANGLE_DETAIL(RowDetail row)
    {
        PavAngleDetail pavAngleDetail = algorithmResult.measurements.PAV_ANGLE_DETAIL;
        row.item1 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_1);
        row.item2 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_2);
        row.item3 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_3);
        row.item4 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_4);
        row.item5 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_5);
        row.item6 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_6);
        row.item7 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_7);
        row.item8 = FormatDouble_A(pavAngleDetail.PAV_ANGLE_8);
        calIndex(row);
    }
    private void setGIRDLE_BEZEL_DETAIL(RowDetail row)
    {
        GirdleBezelDetail girdleBezelDetail = algorithmResult.measurements.GIRDLE_BEZEL_DETAIL;
        row.item1 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_1);
        row.item2 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_2);
        row.item3 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_3);
        row.item4 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_4);
        row.item5 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_5);
        row.item6 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_6);
        row.item7 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_7);
        row.item8 = FormatDouble_P(girdleBezelDetail.GIRDLE_BEZEL_8);
        calIndex(row);
    }
    private void setGIRDLE_BONE_DETAIL(RowDetail row)
    {
        GirdleBoneDetail girdleBoneDetail = algorithmResult.measurements.GIRDLE_BONE_DETAIL;
        row.item1 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_1);
        row.item2 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_2);
        row.item3 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_3);
        row.item4 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_4);
        row.item5 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_5);
        row.item6 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_6);
        row.item7 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_7);
        row.item8 = FormatDouble_P(girdleBoneDetail.GIRDLE_BONE_8);
        calIndex(row);
    }

    private void setGIRDLE_VALLEY_DETAIL(RowDetail row)
    {
        GirdleValleyDetail girdleValleyDetail = algorithmResult.measurements.GIRDLE_VALLEY_DETAIL;
        List<double> doubles = new List<double>();
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_1);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_2);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_3);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_4);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_5);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_6);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_7);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_8);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_9);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_10);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_11);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_12);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_13);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_14);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_15);
        doubles.Add(girdleValleyDetail.GIRDLE_VALLEY_16);
        doubles.Sort();
        row.item1 = FormatDouble_P2(doubles[0]);
        row.item2 = FormatDouble_P2(doubles[1]);
        row.item3 = FormatDouble_P2(doubles[2]);
        row.item4 = FormatDouble_P2(doubles[3]);
        row.item5 = FormatDouble_P2(doubles[12]);
        row.item6 = FormatDouble_P2(doubles[13]);
        row.item7 = FormatDouble_P2(doubles[14]);
        row.item8 = FormatDouble_P2(doubles[15]);
        calIndex(row);
    }
    private void setSTAR_DETAIL(RowDetail row)
    {
        StarDetail starDetail = algorithmResult.measurements.STAR_DETAIL;
        row.item1 = FormatDouble_P(starDetail.STAR_1);
        row.item2 = FormatDouble_P(starDetail.STAR_2);
        row.item3 = FormatDouble_P(starDetail.STAR_3);
        row.item4 = FormatDouble_P(starDetail.STAR_4);
        row.item5 = FormatDouble_P(starDetail.STAR_5);
        row.item6 = FormatDouble_P(starDetail.STAR_6);
        row.item7 = FormatDouble_P(starDetail.STAR_7);
        row.item8 = FormatDouble_P(starDetail.STAR_8);
        calIndex(row);
    }
    private void setLOWER_HALVES_RATIO_DETAIL(RowDetail row)
    {
        LowerHalvesRatioDetail lowerHalvesRatioDetail = algorithmResult.measurements.LOWER_HALVES_RATIO_DETAIL;
        row.item1 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_1);
        row.item2 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_2);
        row.item3 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_3);
        row.item4 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_4);
        row.item5 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_5);
        row.item6 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_6);
        row.item7 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_7);
        row.item8 = FormatDouble_P(lowerHalvesRatioDetail.LOWER_HALVES_RATIO_8);
        calIndex(row);
    }
    private void setTWIST_DETAIL(RowDetail row)
    {
        TwistDetail twistDetail = algorithmResult.measurements.TWIST_DETAIL;
        row.item1 = FormatDouble_A(twistDetail.TWIST_1);
        row.item2 = FormatDouble_A(twistDetail.TWIST_2);
        row.item3 = FormatDouble_A(twistDetail.TWIST_3);
        row.item4 = FormatDouble_A(twistDetail.TWIST_4);
        row.item5 = FormatDouble_A(twistDetail.TWIST_5);
        row.item6 = FormatDouble_A(twistDetail.TWIST_6);
        row.item7 = FormatDouble_A(twistDetail.TWIST_7);
        row.item8 = FormatDouble_A(twistDetail.TWIST_8);
        calIndex(row);
    }

    #region 履历保存
    private void SaveTestResult(SaveStatus saveStatus)
    {
        string ALGORITHM_RESULT = JsonConvert.SerializeObject(algorithmResult);
        string DATA_RESULT = JsonConvert.SerializeObject(DtResults);
        string STATUS = saveStatus.ToString();
        string STONE_ID = DiamondCode;
        string TIMESTAMPVALUE = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:fff");
        string sql = $"INSERT INTO TEST_RESULT (GUID,ALGORITHM_RESULT,DATA_RESULT,STATUS,STONE_ID,TIMESTAMPVALUE)VALUES" +
            $"('{Guid.NewGuid()}','{ALGORITHM_RESULT}','{DATA_RESULT}','{STATUS}','{STONE_ID}','{TIMESTAMPVALUE}');";
        DataBaseHelper.ExecuteNonQuery(sql);
    }
    #endregion

    public void PrintLabel()
    {
        PrintDocument printDoc = new PrintDocument();
        printDoc.PrintPage += new PrintPageEventHandler(PrintPageHandler);
        printDoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", 550, 300);

        PrintDialog printDialog = new PrintDialog();
        printDialog.Document = printDoc;

        if (printDialog.ShowDialog() == DialogResult.OK)
        {
            printDoc.Print();
        }
    }

    private void PrintPageHandler(object sender, PrintPageEventArgs e)
    {
        var result = algorithmResult.measurements;
        int startX = 10;
        int startY = 10;
        var col2X = startX + 90;
        var col3X = col2X + 70;
        // 设置字体
        Font font = new Font(FontFamily.GenericSerif, 12, FontStyle.Bold);

        // 设置颜色
        Brush brush = Brushes.Black;

        // 设置对齐方式
        StringFormat format = new StringFormat();
        format.Alignment = StringAlignment.Center; // 水平居中
        format.LineAlignment = StringAlignment.Center; // 垂直居中

        // 绘制文本 
        // 第一行
        int X = startX;
        int Y = startY;
        e.Graphics.DrawString(Standard, font, brush, new PointF(X, Y));
        X += 70;
        e.Graphics.DrawString(Shape, font, brush, new PointF(X, Y));
        X += 50;
        e.Graphics.DrawString($"ID:{DiamondCode}", font, brush, new PointF(X, Y));
        X += 100;
        e.Graphics.DrawString($"Weight:{Wight}ct.", font, brush, new PointF(X, Y));
        X += 120;
        Brush backgroundBrush = new SolidBrush(System.Drawing.Color.Black); // 背景色为黄色
        e.Graphics.FillRectangle(backgroundBrush, new RectangleF(X, Y, 200, font.Height));
        e.Graphics.DrawString(CutLevelTotal, font, Brushes.White, new PointF(X, Y));

        // 第二行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Diameter", font, brush, new PointF(X, Y));

        e.Graphics.DrawString($"{FormatDouble_D(result.DIAMETER)}mm", font, brush, new PointF(col2X, Y));

        e.Graphics.DrawString($"({FormatDouble_D(result.M1)}mm-{FormatDouble_D(result.M2)}mm)", font, brush, new PointF(col3X, Y));
        e.Graphics.DrawString($"0.3%", font, brush, new PointF(310, Y));
        e.Graphics.FillRectangle(backgroundBrush, new RectangleF(350, Y, 200, font.Height));
        e.Graphics.DrawString(SymLevelTotal, font, Brushes.White, new PointF(X, Y));

        // 第三行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Total Dep.", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_D(result.DIAMETER * result.TOTAL_DEPTH)}mm", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"{FormatDouble_P(result.TOTAL_DEPTH)}%", font, brush, new PointF(X, Y));
        e.Graphics.DrawString($"{DtResults.Where(X=> "TOTAL_DEPTH".Equals(X.TestItemId)).Select(X=>X.CutLevel).FirstOrDefault()}", font, brush, new PointF(480, Y));
        // 第四行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Table", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_D(result.DIAMETER * result.TABLE)}mm", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"{FormatDouble_P(result.TABLE)}%", font, brush, new PointF(X, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "TABLE".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(480, Y));
        // 第五行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Crown", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_A(result.CROWN_ANGLE)}°", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"({FormatDouble_A(result.CROWN_ANGLE_MIN)}°-{FormatDouble_A(result.CROWN_ANGLE_MAX)}°)", font, brush, new PointF(X, Y));
        X += 120;
        e.Graphics.DrawString($"({FormatDouble_A(result.CROWN_HEIGHT)}%)", font, brush, new PointF(X, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "CROWN_ANGLE".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(410, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "CROWN_HEIGHT".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(480, Y));
        // 第六行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Pavil.", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_A(result.PAV_ANGLE)}°", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"({FormatDouble_A(result.PAV_ANGLE_MIN)}°-{FormatDouble_A(result.PAV_ANGLE_MAX)}°)", font, brush, new PointF(X, Y));
        X += 120;
        e.Graphics.DrawString($"({FormatDouble_A(result.PAV_DEPTH)}%)", font, brush, new PointF(X, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "PAV_ANGLE".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(410, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "PAV_DEPTH".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(480, Y));
        // 第七行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Culet", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_P(result.CULET)}%", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"Twist", font, brush, new PointF(X, Y));
        X += 60;
        e.Graphics.DrawString($"({FormatDouble_A(result.TWIST_MIN)}°-{FormatDouble_A(result.TWIST_MAX)}°)", font, brush, new PointF(X, Y));
        // 第八行
        X = startX;
        Y += font.Height;
        e.Graphics.DrawString("Girdle 16M", font, brush, new PointF(X, Y));
        X = col2X;
        e.Graphics.DrawString($"{FormatDouble_D(result.GIRDLE_VALLEY)}", font, brush, new PointF(X, Y));
        X = col3X;
        e.Graphics.DrawString($"({FormatDouble_P(result.GIRDLE_VALLEY_MIN)}%-{FormatDouble_P(result.GIRDLE_VALLEY_MAX)}%)", font, brush, new PointF(X, Y));
        e.Graphics.DrawString($"{DtResults.Where(X => "GIRDLE".Equals(X.TestItemId)).Select(X => X.CutLevel).FirstOrDefault()}", font, brush, new PointF(480, Y));

    }
    #region 钻石操作相关
    //暂略
    //部分代码(直接操作控件)需要在xaml.cs里边写
    //涉及到计算部分,这里做一个中转
    #endregion
}
public class CalGradeInfo{
    public int gradeOrder { get; set; }
    public decimal? Min { get; set; }
    public decimal? Max { get; set; }
    public int isMaxExist { get; set; }
    public int isMinExist { get; set; }
}
public class DataInfo
{
    public string? TestItemId { get; set; }
    public string? TestItemName { get; set; }
    public string? Avg { get; set; }
    public string? Dev { get; set; }
    public string? Min { get; set; }
    public string? Max { get; set; }
    public string? CutLevel { get; set; }
    private Int64? _symLevel;
    //public int? SymLevel { get; set;  }
    public Int64? SymLevel
    {
        get { return _symLevel; }
        set
        {
            if (_symLevel != value)
            {
                _symLevel = value;
                OnPropertyChanged(nameof(SymLevel));
            }
        }
    }
    public bool isEnabled { get; set; } = true;
    private DataTable? _gradeList;
    public DataTable GradeList {
        get
        {
            return _gradeList;
        }
        set
        {
            _gradeList = value;
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class Name
{
    public string Id { get; set; }
    public string name { get; set; }

    public static string getNameById(string id)
    {
        string sql = $"SELECT NAME, EN_NAME FROM NAME WHERE ID = '{id}'";
        DataTable data = DataBaseHelper.ExecuteQuery(sql);
        string nameType = MultilingualHelper.getString("NameType");
        if (data.Rows.Count>0)
        {
            return data.Rows[0][nameType].ToString();
        }
        else
        {
            return "";
        }
    }
}
public class RowDetail
{
    public string? itemName { get; set; }
    public string? Avg { get; set; }
    public string? Dev { get; set; }
    public string? Min { get; set; }
    public string? Max { get; set; }
    public string? item1 { get; set; }
    public string? item2 { get; set; }
    public string? item3 { get; set; }
    public string? item4 { get; set; }
    public string? item5 { get; set; }
    public string? item6 { get; set; }
    public string? item7 { get; set; }
    public string? item8 { get; set; }
    public string? CutLevel { get; set; }
    public string? SymLevel { get; set; }
    public int? MaxIndex { get; set; }
    public int? MinIndex { get; set; }
}
public enum SaveStatus
{
    AutoSave = 0,
    Save=1,
    SaveAs=2
}

public enum Accuracy
{
    ZDZ1 = 0,
    ZD1 = 1,
    ZD5 = 2,
    Z5 = 3
}