468 lines
19 KiB

using BrilliantSightClient.Model.Entity.ApiEntity;
using BrilliantSightClient.Model.Extension;
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;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BrilliantSightClient.Model.GradeLevel;
public class GradeLevelCalculator
{
AlgorithmResultEntity _diamondResult;
public bool IsInitialized = false;
private JToken _diamondData;
GradeLevelMst _masterLevel;
private List<GradeLevelSet> _gradeLevelCutSets;
private List<GradeLevelSet> _gradeLevelSymSets;
public List<GradeLevelSet> GradeLevelCutSets
{
get => _gradeLevelCutSets;
}
public List<GradeLevelSet> GradeLevelSymSets
{
get => _gradeLevelSymSets;
}
private bool CutIsMultiDimensional = false;
private string CutMultiDimensionalSign = string.Empty;
private bool SymIsMultiDimensional = false;
private string SymMultiDimensionalSign = string.Empty;
private List<GradeLevelDataSet> _gradeLevelDataSets;
private List<GradeLevelTreeSet> _gradeLevelCutTreeSets;
private List<GradeLevelTreeSet> _gradeLevelSymTreeSets;
private List<GradeLevelSetDtl> _gradeLevelSetDtls;
private GradeLevelTotalSet _gradeLevelCutTotalSet;
private GradeLevelTotalSet _gradeLevelSymTotalSet;
public GradeLevelCalculator(AlgorithmResultEntity entity)
{
_diamondResult = entity;
_diamondData = JToken.Parse(JsonConvert.SerializeObject(entity.Measurements));
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.Replace("P","")}' and PAVILION = '{entity.PavType.Replace("P","")}'" ;
var masterLevel = DataBaseHelper.ExecuteQuery<GradeLevelMst>(masterSql);
if (masterLevel.Count == 0)
return;
_masterLevel = masterLevel.First();
var setsSql = $"select * from GRADE_LEVEL_SET where MST_SIGN = '{_masterLevel.Sign}'";
var levelSets = DataBaseHelper.ExecuteQuery<GradeLevelSet>(setsSql);
if (levelSets.Count == 0)
return;
_gradeLevelCutSets = levelSets.FindAll(x => x.Set_Type == GradeType.Cut.GetValue());
_gradeLevelSymSets = levelSets.FindAll(x => x.Set_Type == GradeType.Sym.GetValue());
var dataSetSql = $"select * from GRADE_LEVEL_DATA_SET where MST_SIGN = '{_masterLevel.Sign}'";
_gradeLevelDataSets = DataBaseHelper.ExecuteQuery<GradeLevelDataSet>(dataSetSql);
var treeSetSql = $"select * from GRADE_LEVEL_TREE_SET where MST_SIGN = '{_masterLevel.Sign}'";
var treeSets = DataBaseHelper.ExecuteQuery<GradeLevelTreeSet>(treeSetSql);
_gradeLevelCutTreeSets = treeSets.FindAll(x => x.NodeType - 1 == GradeType.Cut.GetValue());
_gradeLevelSymTreeSets = treeSets.FindAll(x => x.NodeType - 1 == GradeType.Sym.GetValue());
CutIsMultiDimensional = _gradeLevelCutTreeSets.Count() > 1;
SymIsMultiDimensional = _gradeLevelSymTreeSets.Count() > 1;
var setDtlSql = $"select * from GRADE_LEVEL_SET_DTL where MST_SIGN = '{_masterLevel.Sign}'";
_gradeLevelSetDtls = DataBaseHelper.ExecuteQuery<GradeLevelSetDtl>(setDtlSql);
var totalSetSql = $"select * from GRADE_LEVEL_TOTAL_SET where MST_SIGN = '{_masterLevel.Sign}'";
var totalSets = DataBaseHelper.ExecuteQuery<GradeLevelTotalSet>(totalSetSql);
_gradeLevelCutTotalSet = totalSets.FindAll(x => x.Set_Type == GradeType.Cut.GetValue()).First();
_gradeLevelSymTotalSet = totalSets.FindAll(x => x.Set_Type == GradeType.Sym.GetValue()).First();
IsInitialized = true;
}
public GradeLevelSet? GetCutGradeLevelSet(string key, DataInfo dataInfo)
{
if (IsInitialized == false) return null;
if("GIRDLE_VALLEY".Equals(key))key = "GIRDLE";
GradeLevelDataSet? dataSet = _gradeLevelDataSets.FirstOrDefault(x => x.KName.Equals(key));
if (dataSet == null) return null;
//检查是否多维度
if (CutIsMultiDimensional)
{
//多维度
List<GradeLevelTreeSet> cutTree = _gradeLevelCutTreeSets.FindAll(x => x.IsTop == 0);
if(cutTree.Count <= 0) return null;
GradeLevelDataSet? dimensionKey = _gradeLevelDataSets.FirstOrDefault(x => cutTree.First().DimensionSign == x.Sign);
if (dimensionKey == null) return null;
CutMultiDimensionalSign = string.IsNullOrWhiteSpace(CutMultiDimensionalSign)?DimensionTreeSign(dimensionKey, cutTree):CutMultiDimensionalSign;
if ("1".Equals(CutMultiDimensionalSign) || "-1".Equals(CutMultiDimensionalSign))
{
return _gradeLevelCutSets.OrderByDescending(set => set.Short).FirstOrDefault();
}
return GetFinalCutGrade(CutMultiDimensionalSign, key, dataInfo);
}
else
{
//单维度
return GetFinalCutGrade(_gradeLevelCutTreeSets.First().Sign, key, dataInfo);
}
}
public GradeLevelSet? GetCutTotalGradeLevelSet(List<DataInfo> dataInfos)
{
if (IsInitialized == false) return null;
return CalculateTotalGrade(dataInfos, _gradeLevelCutTotalSet, _gradeLevelCutSets);
}
public GradeLevelSet? GetSymGradeLevelSet(string key, DataInfo dataInfo)
{
if (IsInitialized == false) return null;
if("GIRDLE_VALLEY".Equals(key))key = "GIRDLE";
GradeLevelDataSet? dataSet = _gradeLevelDataSets.FirstOrDefault(x => x.KName.Equals(key));
if (dataSet == null) return null;
double value = string.IsNullOrWhiteSpace(dataInfo.Dev) ? dataInfo.Avg.ToDouble() : dataInfo.Dev.ToDouble();
// 检查是否多维度
if (SymIsMultiDimensional)
{
// 多维度
List<GradeLevelTreeSet> symTree = _gradeLevelSymTreeSets.FindAll(x => x.IsTop == 0);
if (symTree.Count <= 0) return null;
GradeLevelDataSet? dimensionKey = _gradeLevelDataSets.FirstOrDefault(x => symTree.First().DimensionSign == x.Sign);
if (dimensionKey == null) return null;
SymMultiDimensionalSign = string.IsNullOrWhiteSpace(SymMultiDimensionalSign)?DimensionTreeSign(dimensionKey, symTree):SymMultiDimensionalSign;
if ("1".Equals(SymMultiDimensionalSign) || "-1".Equals(SymMultiDimensionalSign))
{
return _gradeLevelSymSets.OrderByDescending(set => set.Short).FirstOrDefault();
}
return GetFinalSymGrade(SymMultiDimensionalSign, key, value);
}
else
{
// 单维度
return GetFinalSymGrade(_gradeLevelSymTreeSets.First().Sign, key, value);
}
}
public GradeLevelSet GetSymTotalGradeLevelSet(List<DataInfo> dataInfos)
{
if (IsInitialized == false) return null;
return CalculateTotalGrade(dataInfos, _gradeLevelSymTotalSet, _gradeLevelSymSets);
}
private string DimensionTreeSign(GradeLevelDataSet dimensionKey, List<GradeLevelTreeSet> cutTree)
{
string dimensionTreeSign = string.Empty;
try
{
// 从JToken中获取对应路径的值
JToken? dimensionValueToken = _diamondData.SelectToken(dimensionKey.KName);
if (dimensionValueToken == null)
return string.Empty;
// 转换为double并进行计算
if (double.TryParse(dimensionValueToken.ToString(), out double dimensionValue))
{
// 乘以100并四舍五入取整
int roundedValue = (int)Math.Round(dimensionValue*100, MidpointRounding.AwayFromZero);
// 循环查找有效树
int currentRoundedValue = roundedValue;
while (true)
{
// 获取所有维度值并排序
var dimensionValues = cutTree
.Where(x => !string.IsNullOrEmpty(x.DimensionValue))
.Select(x =>
{
if (int.TryParse(x.DimensionValue, out int value))
return new { Value = value, Sign = x.Sign };
return null;
})
.Where(x => x != null)
.OrderBy(x => x.Value)
.ToList();
if (!dimensionValues.Any()) break; // 无维度值时退出
// 判断当前roundedValue对应的树
var matchedDimension = dimensionValues.FirstOrDefault(x => x.Value == currentRoundedValue);
if (matchedDimension != null)
{
dimensionTreeSign = matchedDimension.Sign;
// 检查当前树是否有有效定级配置
if (HasValidGradeConfig(dimensionTreeSign))
{
return dimensionTreeSign;
}
}
else if (currentRoundedValue > dimensionValues.Max(x => x.Value))
{
dimensionTreeSign = "1";
if (HasValidGradeConfig(dimensionTreeSign))
{
return dimensionTreeSign;
}
break; // 最大树无效时不再查找
}
else if (currentRoundedValue < dimensionValues.Min(x => x.Value))
{
dimensionTreeSign = "-1";
if (HasValidGradeConfig(dimensionTreeSign))
{
return dimensionTreeSign;
}
break; // 最小树无效时不再查找
}
// 未找到有效树时,尝试下一个树(DimensionValue+1)
currentRoundedValue++;
if (currentRoundedValue > dimensionValues.Max(x => x.Value))
{
break; // 超出最大维度值时退出
}
}
}
}
catch
{
// 处理异常,返回空白
dimensionTreeSign = string.Empty;
}
return dimensionTreeSign;
}
// 检查树是否有有效定级配置
private bool HasValidGradeConfig(string treeSign)
{
var validConfigs = _gradeLevelSetDtls
.Where(dtl => dtl.Tree_Sign == treeSign)
.Where(dtl =>
!(dtl.Max_Value == double.MaxValue && dtl.Min_Value == double.MinValue) &&
!(dtl.Max_Value == 0 && dtl.Min_Value == 0)
)
.ToList();
return validConfigs.Any();
}
public GradeLevelSet? GetFinalCutGrade(string treeSign, string key, DataInfo dataInfo)
{
if (IsInitialized == false) return null;
// 通过TreeSign和Key关联获取子集
var dataSet = _gradeLevelDataSets.FirstOrDefault(ds => ds.KName == key);
if (dataSet == null) return null;
var filteredDtls = _gradeLevelSetDtls
.Where(dtl => dtl.Tree_Sign == treeSign && dtl.DataSet_Sign == dataSet.Sign)
.ToList();
if (!filteredDtls.Any()) return null;
// 查找最大值和最小值对应的区间
List<GradeLevelSetDtl> maxValDtls = new List<GradeLevelSetDtl>();
List<GradeLevelSetDtl> minValDtls = new List<GradeLevelSetDtl>();
if (dataInfo.Max.ToDouble() == 0 && dataInfo.Min.ToDouble() == 0)
{
maxValDtls = filteredDtls
.Where(dtl => dataInfo.Avg.ToDouble() >= dtl.Min_Value && dataInfo.Avg.ToDouble() <= dtl.Max_Value)
.ToList();
minValDtls = filteredDtls
.Where(dtl => dataInfo.Avg.ToDouble() >= dtl.Min_Value && dataInfo.Avg.ToDouble() <= dtl.Max_Value)
.ToList();
}
else
{
maxValDtls = filteredDtls
.Where(dtl => dataInfo.Max.ToDouble() >= dtl.Min_Value && dataInfo.Max.ToDouble() <= dtl.Max_Value)
.ToList();
minValDtls = filteredDtls
.Where(dtl => dataInfo.Min.ToDouble() >= dtl.Min_Value && dataInfo.Min.ToDouble() <= dtl.Max_Value)
.ToList();
}
// 获取对应的GradeLevelSet集合
var associatedLevelSets = _gradeLevelCutSets
.Where(ls => filteredDtls.Any(dtl => dtl.Level_Sign == ls.Sign))
.ToList();
// 处理最大值的情况
GradeLevelSet? maxLevel = null;
if (maxValDtls.Any())
{
// 若有多个区间,取最差的(Short值最大)
if (maxValDtls.Count > 1)
{
maxLevel = associatedLevelSets
.Where(ls => maxValDtls.Any(dtl => dtl.Level_Sign == ls.Sign))
.OrderBy(ls => ls.Short)
.FirstOrDefault();
}
else
{
maxLevel = associatedLevelSets
.FirstOrDefault(ls => ls.Sign == maxValDtls.First().Level_Sign);
}
}
// 处理最小值的情况
GradeLevelSet? minLevel = null;
if (minValDtls.Any())
{
// 若有多个区间,取最差的(Short值最大)
if (minValDtls.Count > 1)
{
minLevel = associatedLevelSets
.Where(ls => minValDtls.Any(dtl => dtl.Level_Sign == ls.Sign))
.OrderBy(ls => ls.Short)
.FirstOrDefault();
}
else
{
minLevel = associatedLevelSets
.FirstOrDefault(ls => ls.Sign == minValDtls.First().Level_Sign);
}
}
// 若最大值和最小值都找到对应的区间,返回较差的一个
if (maxLevel != null && minLevel != null)
{
return maxLevel.Short > minLevel.Short ? maxLevel : minLevel;
}
// 若只有一个找到区间,返回该区间对应的级别
if (maxLevel != null) return maxLevel;
if (minLevel != null) return minLevel;
// 若都没找到,返回子集中最差的级别
return associatedLevelSets.OrderBy(ls => ls.Short).FirstOrDefault();
}
private GradeLevelSet? GetFinalSymGrade(string treeSign, string key, double devVal)
{
// 通过TreeSign和Key关联获取子集
var dataSet = _gradeLevelDataSets.FirstOrDefault(ds => ds.KName == key);
if (dataSet == null) return null;
var filteredDtls = _gradeLevelSetDtls
.Where(dtl => dtl.Tree_Sign == treeSign && dtl.DataSet_Sign == dataSet.Sign)
.ToList();
if (!filteredDtls.Any()) return null;
// 查找偏差值对应的区间
var devValDtls = filteredDtls
.Where(dtl => devVal >= dtl.Min_Value && devVal <= dtl.Max_Value)
.ToList();
// 获取对应的GradeLevelSet集合
var associatedLevelSets = _gradeLevelSymSets
.Where(ls => filteredDtls.Any(dtl => dtl.Level_Sign == ls.Sign))
.ToList();
// 处理偏差值的情况
GradeLevelSet? devLevel = null;
if (devValDtls.Any())
{
// 若有多个区间,取最差的(Short值最大)
if (devValDtls.Count > 1)
{
devLevel = associatedLevelSets
.Where(ls => devValDtls.Any(dtl => dtl.Level_Sign == ls.Sign))
.OrderBy(ls => ls.Short)
.FirstOrDefault();
}
else
{
devLevel = associatedLevelSets
.FirstOrDefault(ls => ls.Sign == devValDtls.First().Level_Sign);
}
}
// 若找到对应的区间,返回该区间对应的级别
if (devLevel != null) return devLevel;
// 若没找到,返回子集中最差的级别
return associatedLevelSets.OrderByDescending(ls => ls.Short).FirstOrDefault();
}
private GradeLevelSet CalculateTotalGrade(List<DataInfo> dataInfos, GradeLevelTotalSet totalSet, List<GradeLevelSet> levelSets)
{
// 解析参与评级的数据签名
var dataSigns = totalSet.DataSigns.Split(',', StringSplitOptions.RemoveEmptyEntries);
// 找出所有参与评级的项目对应的评级
var gradeLevels = new List<GradeLevelSet>();
foreach (var dataSign in dataSigns)
{
var dataSet = _gradeLevelDataSets.FirstOrDefault(ds => ds.Sign == dataSign);
if (dataSet == null) continue;
var dataInfo = dataInfos.FirstOrDefault(di => di.TestItemId == dataSet.KName);
if (dataInfo == null) continue;
GradeLevelSet? gradeLevel = null;
if (totalSet.Set_Type == GradeType.Cut.GetValue())
{
// 切工评级
gradeLevel = GetCutGradeLevelSet(dataSet.KName, dataInfo);
}
else if (totalSet.Set_Type == GradeType.Sym.GetValue())
{
// 对称评级
gradeLevel = GetSymGradeLevelSet(dataSet.KName, dataInfo);
}
if (gradeLevel != null)
{
gradeLevels.Add(gradeLevel);
}
}
// 若没有找到任何评级,返回默认最差评级
if (!gradeLevels.Any())
{
return levelSets.OrderByDescending(ls => ls.Short).FirstOrDefault()
?? throw new NotGradeSetException("无法计算总评级,没有找到有效的评级数据");
}
// 根据统计方式聚合评级
switch (totalSet.Statistics)
{
case 0: // 最大值(最差)
return gradeLevels.OrderBy(ls => ls.Short).First();
case 1: // 最小值(最好)
return gradeLevels.OrderByDescending(ls => ls.Short).First();
case 2: // 平均值
// 计算平均Short值
double averageShort = gradeLevels.Average(ls => ls.Short);
// 找到最接近平均值的等级
return levelSets
.OrderBy(ls => Math.Abs(ls.Short - averageShort))
.FirstOrDefault()
?? throw new NotGradeSetException("无法计算平均评级,没有找到匹配的等级");
default:
throw new NotSupportedException($"不支持的统计方式: {totalSet.Statistics}");
}
}
}