using System.Dynamic;
using Nest;
using Newtonsoft.Json.Linq;
using SJZY.Expand.ABP.Core.PublicMethords;
using SJZY.Track.Application.Contract.Dtos.Forewarning;
using SJZY.Track.Domain.Aggregates.ForewarningAggregate;
using SJZY.Track.Domain.Dtos.Common;
using SJZY.Track.Domain.Dtos.Forewarning;
using SJZY.Track.Share.Enums;
namespace SJZY.Track.Application.Helpers;
public class ForewarningHelper
{
///
/// 递推分裂预警规则列表
///
///
///
///
public static List CalcRuleList(List statusSpans,
List factors)
{
if (statusSpans.Count == 0 || factors.Count == 0)
{
throw new BusinessException(message: "轨迹状态区间或因素列表为空");
}
var len = statusSpans.Count * factors.Select(f => f.FactorValue.Count).Aggregate((pre, cur) => pre * cur);
if (len == 0)
{
throw new BusinessException(message: "轨迹状态区间或因素列表为空");
}
var rules = Enumerable.Range(0, len).Select(_ => new WarningRuleEntity()).ToList();
var repeat = len / statusSpans.Count;
FillStatus(statusSpans, rules, repeat);
foreach (var factor in factors)
{
var factorValueCount = factor.FactorValue.Count;
// repeat梯度下降,与times成反比关系
repeat /= factorValueCount;
var times = len / repeat / factorValueCount;
FillFactor(factor, rules, repeat, times);
}
return rules;
}
private static void FillStatus(List statusSpans, List rules, int repeat)
{
var row = 0;
foreach (var span in statusSpans)
{
for (var i = 0; i < repeat; i++, row++)
{
rules[row].StartTrackStatusId = span.StartTrackStatusId;
rules[row].StartTrackStatus = span.StartTrackStatus;
rules[row].EndTrackStatusId = span.EndTrackStatusId;
rules[row].EndTrackStatus = span.EndTrackStatus;
}
}
}
private static void FillFactor(WarningFactorDto factor, List rules, int repeat, int times)
{
var row = 0;
for (var i = 0; i < times; i++)
{
foreach (var value in factor.FactorValue)
{
var strValue = value.ToString();
if (strValue.IsNullOrEmpty())
{
throw new BusinessException(message: "因素值不能为空");
}
for (var j = 0; j < repeat; j++, row++)
{
switch (factor.FactorType)
{
case RuleFactorType.CargoType:
if (value.Type is not JTokenType.String)
{
throw new BusinessException(message: "货物类型只接收字符串");
}
rules[row].CargoType = strValue;
break;
case RuleFactorType.Months:
foreach (var item in strValue.Split("/"))
{
if (!int.TryParse(item, out var month) || month < 1 || month > 12)
{
throw new BusinessException(message: "请输入合法的月份,多个月份请以'/'连接");
}
}
rules[row].Months = strValue;
break;
case RuleFactorType.Area:
if (value.Type is not JTokenType.Integer)
{
throw new BusinessException(message: "分区请传id");
}
rules[row].AreaId = int.Parse(strValue);
break;
case RuleFactorType.IsTransit:
if (value.Type is not JTokenType.Boolean)
{
throw new BusinessException(message: "是否中转只接收bool类型");
}
rules[row].IsTransit = bool.Parse(strValue);
break;
case RuleFactorType.LeavePort:
if (value.Type is not JTokenType.String)
{
throw new BusinessException(message: "起运港只接收字符串");
}
rules[row].LeavePort = strValue;
break;
case RuleFactorType.ProductCode:
if (value.Type is not JTokenType.String)
{
throw new BusinessException(message: "产品代码只接收字符串");
}
rules[row].ProductCode = strValue;
break;
default:
throw new BusinessException(message: $"不支持的因素:{factor.FactorType}");
}
}
}
}
}
public static List MapFactorEntities(List warningFactors)
{
return warningFactors.Select(x => new WarningFactorEntity
{
Type = x.FactorType,
Value = x.FactorValue.ToJson()
}).ToList();
}
public static List MapNotifyEntities(CreateWarningInput input)
{
return input.TrackStatusSpans.Select(x => new WarningNotifyEntity
{
StartTrackStatusId = x.StartTrackStatusId,
EndTrackStatusId = x.EndTrackStatusId,
NotifyMode = input.NotifyMode,
NotifyTemplate = input.NotifyTemplate,
NotifyUserId = x.NotifyUserId
}).ToList();
}
public static EditWarningOutput MapWarningSummary(WarningEntity warning, List statusList)
{
var statusDic = statusList.ToDictionary(x => x.Id, x => x.Name);
return new EditWarningOutput
{
Name = warning.Name,
SubSystemId = warning.SubSystemId,
CustomerId = warning.CustomerId,
NotifyMode = warning.WarningNotifies.First().NotifyMode,
NotifyTemplate = warning.WarningNotifies.First().NotifyTemplate,
TrackStatusSpans = warning.WarningNotifies.Select(x => new WarningNotifyWithIdDto
{
Id = x.Id,
StartTrackStatusId = x.StartTrackStatusId,
StartTrackStatus = statusDic.TryGetValue(x.StartTrackStatusId, out var start) ? start : "",
EndTrackStatusId = x.EndTrackStatusId,
EndTrackStatus = statusDic.TryGetValue(x.EndTrackStatusId, out var end) ? end : "",
NotifyUserId = x.NotifyUserId,
}).ToList(),
WarningFactors = warning.WarningFactors.Select(x => new WarningFactorWithIdDto
{
Id = x.Id,
FactorType = x.Type,
FactorValue = JArray.Parse(x.Value),
}).ToList()
};
}
public static List DynamicCalcRuleList(List rules, List factors)
{
var dynamicList = new List();
foreach (var rule in rules)
{
dynamic dynamicRule = new ExpandoObject();
var dynamicRuleDict = (IDictionary)dynamicRule;
dynamicRuleDict[nameof(Id)] = rule.Id;
dynamicRuleDict[nameof(rule.StartTrackStatus)] = rule.StartTrackStatus;
dynamicRuleDict[nameof(rule.EndTrackStatus)] = rule.EndTrackStatus;
foreach (var factor in factors)
{
switch (factor)
{
case RuleFactorType.CargoType:
dynamicRuleDict[nameof(rule.CargoType)] = rule.CargoType;
break;
case RuleFactorType.Months:
dynamicRuleDict[nameof(rule.Months)] = rule.Months;
break;
case RuleFactorType.Area:
dynamicRuleDict[nameof(rule.Area)] = rule.Area;
break;
case RuleFactorType.IsTransit:
dynamicRuleDict[nameof(rule.IsTransit)] = rule.IsTransit;
break;
case RuleFactorType.LeavePort:
dynamicRuleDict[nameof(rule.LeavePort)] = rule.LeavePort;
break;
case RuleFactorType.ProductCode:
dynamicRuleDict[nameof(rule.ProductCode)] = rule.ProductCode;
break;
default:
throw new BusinessException(message: $"不支持的因素:{factor}");
}
}
dynamicRuleDict[nameof(rule.TotalTimeSpan)] = rule.TotalTimeSpan;
dynamicRuleDict[nameof(rule.WarnTimeSpan)] = rule.WarnTimeSpan;
dynamicRuleDict[nameof(rule.WarnCount)] = rule.WarnCount;
dynamicList.Add(dynamicRule);
}
return dynamicList;
}
}