示例#1
0
        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();
            }
        }