public void BuildInferComboReports(PumpSystem ppSys) { using (var context = new PumpSystemContext()) { var reportsToSave = new List <InferComboReport>(); foreach (var comp in ppSys) { foreach (var icItem in comp.InferComboItems.Where(ic => ic.IsHappening)) { GradedCriterion.ForEachValidGradeRange(gradeRange => { var passedGcts = icItem.ExpressionCts.Where(ct => ct is GradedCriterion) .Where(gct => gct.IsHappening) .Cast <GradedCriterion>().ToList(); //假如range是3的话,那么通过的里面至少有个3,且只能有3,不能有1,2 //假如range是2,3的话, 那么通过的里面至少有个2,且只能有2,3 //假如range是1,2,3的话, 那么通过的里面至少有个1,且只能有1,2,3 var checkPass = passedGcts.Any(); checkPass &= passedGcts.Exists(g => (int)g.HappeningGrade == gradeRange[0]); checkPass &= passedGcts.All(g => gradeRange.Contains((int)g.HappeningGrade)); if (!checkPass) { return; } var newRpt = new InferComboReport(); //设置报告时间 var happenTime = passedGcts.Max(ct => ct.Time); newRpt.LibId = icItem.Id; newRpt.FirstTime = happenTime; newRpt.LatestTime = happenTime; //设置报告组件 newRpt.CompCode = comp.Code; //设置报告故障内容和建议 // var faultItem = Repo.FaultItems.First(fi => fi.IsSameFaultItem(icItem)); newRpt.DisplayText = icItem.FaultResult; newRpt.EventMode = icItem.EventMode; newRpt.Expression = icItem.Expression; newRpt.RtDatas = string.Join(Repo.Separator, icItem.ExpressionCts.Select(ct => $"{ct.LibId}:{(ct.IsHappening ? 1 : 0)}")); // newRpt.Advise = faultItem.Advise; newRpt.HappenCount = 1; //remark2 作为所用分档 newRpt.Remark2 = "Grade:" + string.Join(",", gradeRange); //把通过的(为1的)分别是几档写到remark3里 newRpt.Remark3 = "GradeRefer: " + string.Join(Repo.Separator, passedGcts.Select(g => $"{g.LibId}:{(int) g.HappeningGrade}")); var icReports = context.InferComboReports.ToList(); //判断是否存在报告,不存在则添加,存在则更新 var existRpts = icReports.Where(rptRecord => rptRecord.LibId == newRpt.LibId && rptRecord.EventMode == newRpt.EventMode && rptRecord.Expression == newRpt.Expression && rptRecord.Remark2 == newRpt.Remark2).ToArray(); if (!existRpts.Any()) { var intersects = icReports.Select(r => r.LibId).Intersect(icItem.PrevIds).ToList(); if (intersects.Any()) { newRpt.DisplayText += "(小概率)"; } reportsToSave.Add(newRpt); } else { var latestTime = existRpts.Max(rr => rr.LatestTime); var latestRpt = existRpts.First(r => r.LatestTime == latestTime); latestRpt.LatestTime = newRpt.FirstTime; latestRpt.HappenCount++; } }); } } if (reportsToSave.Any()) { context.InferComboReports.AddRange(reportsToSave); } context.SaveChanges(); } }
public static void ConstructRepo() { #region 读取故障项(组件和故障模式) Repo.FaultItems.Clear(); foreach (DataRow row in PumpSysLib.TableFaultItem.Rows) { Repo.FaultItems.Add(new FaultItem { CompType = Repo.Map.TypeToEnum[row["TypeName"].ToString()], EventMode = row["EventMode"].ToString(), Description = row["Description"].ToString(), Advise = row["Advise"].ToString() }); } #endregion #region 构建判据 //读取判据模板 var ctTemplates = new List <CriterionTemplate>(); foreach (DataRow row in PumpSysLib.TableCriterionTemplate.Rows) { ctTemplates.Add(new CriterionTemplate { Id = int.Parse(row["ID"].ToString()), Desciption = row["Description"].ToString(), FuncName = row["FuncName"].ToString(), ExpressionTemplate = row["ExpressionTemplate"].ToString(), GradeVar = row["GradeVar"].ToString(), FilteCount = int.Parse(row["FilteCount"].ToString()), ThresholdField = row["ThresholdField"].ToString(), AsReportResult = (bool)row["AsReportResult"] }); } //区分模板中带函数的和不带函数的, 并替换 函数名 为 表达式 var ctTemplates_Func = ctTemplates.Where(ct => !string.IsNullOrEmpty(ct.FuncName)).OrderByDescending(ct => ct.FuncName.Length).ToArray(); Debug.Assert(ctTemplates_Func.Distinct().Count() == ctTemplates_Func.Length, "判据模板函数必须没有重复"); Debug.Assert(ctTemplates_Func[0].FuncName.Length >= ctTemplates_Func[1].FuncName.Length, "判据模板函数名必须按函数名长度倒序"); var ctTemplates_all = ctTemplates; foreach (var cttemplate in ctTemplates_all) { foreach (var cttFunc in ctTemplates_Func) { if (cttemplate != cttFunc) { if (cttemplate.ExpressionTemplate.Contains(cttFunc.FuncName)) { cttemplate.ExpressionTemplate = cttemplate.ExpressionTemplate.Replace(cttFunc.FuncName, cttFunc.ExpressionTemplate); } } } } //读取要构建的判据表 var ctToBuildList = new List <CriterionToBuild>(); foreach (DataRow row in PumpSysLib.TableCriterionToBuild.Rows) { // var splitIndex = evMode.IndexOf("_", StringComparison.Ordinal); // var compStr = evMode.Substring(0, splitIndex); // var evModeStr = evMode.Substring() var fitem = Repo.FindFaultItem(row["EventMode"].ToString()); if (fitem != null) { var cttb = new CriterionToBuild { CompType = fitem.CompType, EventMode = fitem.EventMode, LibId = int.Parse(row["LibID"].ToString()), TemplateId = int.Parse(row["TemplateID"].ToString()), PosRemark = row["PosRemark"].ToString(), _VAR_A = row["_VAR_A"].ToString(), _VAR_B = row["_VAR_B"].ToString(), _VAR_C = row["_VAR_C"].ToString(), _VAR_D = row["_VAR_D"].ToString(), }; ctToBuildList.Add(cttb); } else { Log.Error( $"构建判据错误:Access中{nameof(PumpSysLib.TableCriterionToBuild)}故障模式无法读取: {row["EventMode"]}"); } } //设置判据 Repo.Criteria.Clear(); foreach (var ctToBuild in ctToBuildList) { var template = ctTemplates_all.FirstOrDefault(tpl => tpl.Id == ctToBuild.TemplateId); var fitem = Repo.FaultItems.FirstOrDefault(fi => fi.IsSameFaultItem(ctToBuild)); if (template == null) { Log.Error($"构建判据错误:ID为{ctToBuild.LibId}的判据模板未找到"); } else if (template.ExpressionTemplate.Contains("PREV")) { continue; //不加载带有PREV函数的判据) } else if (fitem == null) { Log.Error($"构建判据错误:{ctToBuild.CompType} AND {ctToBuild.EventMode}的故障项未找到"); } else { Criterion ct; if (string.IsNullOrEmpty(template.GradeVar)) { ct = new Criterion(); } else { ct = new GradedCriterion { ServerityGradeField = template.GradeVar }; } ct.LibId = ctToBuild.LibId; ct.TemplateId = template.Id; ct.CompType = ctToBuild.CompType; ct.EventMode = ctToBuild.EventMode; ct.Expression = template.ExpressionTemplate; #region 替换表达式中的_VAR_变量 ct.Expression = ct.Expression.Replace(nameof(ctToBuild._VAR_A), ctToBuild._VAR_A); ct.Expression = ct.Expression.Replace(nameof(ctToBuild._VAR_B), ctToBuild._VAR_B); ct.Expression = ct.Expression.Replace(nameof(ctToBuild._VAR_C), ctToBuild._VAR_C); ct.Expression = ct.Expression.Replace(nameof(ctToBuild._VAR_D), ctToBuild._VAR_D); #endregion ct.Description = $"{fitem.Description}({template.Desciption})"; ct.Advise = fitem.Advise; ct.ThresholdField = template.ThresholdField; ct.AsReportResult = template.AsReportResult; //加入到FaultItem中 fitem.Criteria.Add(ct); //设置faultitem的阈值字段 fitem.ThresholdField = ct.ThresholdField; ct.PosRemark = ctToBuild.PosRemark; Repo.Criteria.Add(ct); } } #endregion #region 构建推断组合项列表 Repo.InferCombos.Clear(); foreach (DataRow row in PumpSysLib.TableInferCombo.Rows) { var fItem = Repo.FindFaultItem(row["EventMode"].ToString()); var icitem = new InferComboItem { EventMode = fItem.EventMode, CompType = fItem.CompType, Id = int.Parse(row["ID"].ToString()), Expression = row["Expression"].ToString(), FaultResult = row["FaultResult"].ToString(), }; var prevIdsStr = row["PrevIds"].ToString(); if (!string.IsNullOrEmpty(prevIdsStr)) { icitem.PrevIds = prevIdsStr.Split(',').Select(int.Parse).ToArray(); } else { icitem.PrevIds = new int[] {}; } Repo.InferCombos.Add(icitem); } #endregion }
private void ParseGradedCriterion() { var gct = _ct as GradedCriterion; if (gct == null) { return; } string outputDetail = string.Empty; //先尝试判断判据能否正常解析 string parsedExp; if (!TryParseVariables(out parsedExp)) { return; } var curIsPassed = true; //判据无误能解析,那就进行分级解析 GradedCriterion.ForEachValidGradeRange(lvs => { //取一个最小的作为迭代条件 var lv = lvs.Min(); //当前等级没通过的话,之后的等级也就不用判断了,跳出循环 if (!curIsPassed) { return; } var gradePercent = Convert.ToDouble(lv) / Convert.ToDouble(GradedCriterion.GradeCount); //解析判据 TryParseVariables(out parsedExp, gradePercent); curIsPassed = EvaluateExpression(parsedExp); if (curIsPassed) { gct.HappeningGrade = (SeverityGrade)lv; } //不管通过与否,都要记录和输出。 通过的话,设置级别要在记录之前;没通过的话,跳出要在记录之后 RecordRtData(); outputDetail = $" 组件:{_compCode} 事件模式:{gct.EventMode} 实时数据: {gct.RtDataStr}"; }); var notHappenAction = new Action(() => { gct.IsHappening = false; gct.Time = null; Log.Inform($"---- 分级判据{_ct.LibId} 未发生 {outputDetail}"); }); var happenAction = new Action(() => { gct.IsHappening = true; gct.Time = TdUpdateTime; Log.Inform($">>>> 分级判据{_ct.LibId} 已发生 {outputDetail}"); }); //都没通过,判据没发生 if (gct.HappeningGrade == SeverityGrade.NotHappen) { notHappenAction(); } else { // if (Repo.ValidGrades.Contains((int) gct.HappeningGrade)) { // happenAction(); // } else { // notHappenAction(); // } happenAction(); } }