private void reCalculateLink(string calculateName, DateTimeOffset date) { try { //生成拓扑图 ALGraph.MyGraph graph = new ALGraph.MyGraph(); constructGraph(calculateName, graph, date); System.Collections.ArrayList toplist = graph.topSort(); if (toplist.Count != graph.Vexnum) { throw new Exception("仪器公式存在循环依赖"); } //根据拓扑顺序依次更新 for (int i = 0; i < toplist.Count; i++) { string csn = (string)toplist[i]; //不必更新本身 if (csn != calculateName) { AppIntegratedInfo otherApp = new AppIntegratedInfo(csn, date); reCalcValues(otherApp, null, date); //要更新数据 otherApp.Update(); } } } catch (Exception ex) { throw new Exception("计算关联测点错误 " + ex.Message); } }
public AppIntegratedInfo(AppIntegratedInfo clonedAppInfo, int topNum, DateTimeOffset?startDate, DateTimeOffset?endDate) { _dbContext = clonedAppInfo.DbContext; _currentApp = clonedAppInfo.CurrentApp; _calcParams = clonedAppInfo.CalcParams; SetInfo(_currentApp.AppName, topNum, startDate, endDate); }
/// <summary> /// 查询离指定时间最近的数据的记录 /// </summary> /// <param name="preConcertDate">指定的时间,也就是预定时间</param> /// <param name="days">"最近"这个词所允许的与预期时间相隔最大的天数</param> /// <returns></returns> public AppIntegratedInfo getAppInfoNearTime(DateTimeOffset preConcertDate, double days) { AppIntegratedInfo appInfo = null; AppIntegratedInfo infoSuffix = new AppIntegratedInfo(this, 1, preConcertDate, null); AppIntegratedInfo infoPrefix = new AppIntegratedInfo(this, 1, null, preConcertDate); if (infoSuffix.CalcValues.Count == 0 && infoPrefix.CalcValues.Count == 0) { return(null); } long after = long.MaxValue, before = long.MaxValue; if (infoSuffix.CalcValues.Count != 0) { after = (infoSuffix.CalcValues[0].Date).Ticks - preConcertDate.Ticks; } if (infoPrefix.CalcValues.Count != 0) { before = preConcertDate.Ticks - (infoPrefix.CalcValues[0].Date).Ticks; } long cha = 0; if (after > before) { cha = before; appInfo = infoPrefix; } else { cha = after; appInfo = infoSuffix; } if (cha > TimeSpan.TicksPerDay * days) { appInfo = null; } return(appInfo); }
/// <summary> /// 将实际的值填充到参数列表中,如果参数没有相应的值,将被赋初值0 /// </summary> /// <param name="list">参数列表</param> /// <param name="appCalcName">测点的计算名称</param> /// <param name="date">日期</param> /// <param name="appendDot">是否将计算名称和点加在参数的前面</param> /// <param name="simpleInfo">测点数据信息</param> internal static void fillListByCalcName_Date(hammergo.caculator.MyList list, DateTimeOffset date, bool appendDot, AppIntegratedInfo simpleInfo) { string appCalcName = simpleInfo.CurrentApp.CalculateName; foreach (ConstantParam cp in simpleInfo.ConstantParams) { string key = cp.ParamSymbol; if (appendDot) { key = String.Format("{0}.{1}", appCalcName, key); } list.add(key, cp.Val); } //赋初值0 foreach (MessureParam mp in simpleInfo.MesParams) { string key = mp.ParamSymbol; if (appendDot) { key = String.Format("{0}.{1}", appCalcName, key); } list.add(key, 0); } //赋初值0 foreach (CalculateParam cp in simpleInfo.CalcParams) { string key = cp.ParamSymbol; if (appendDot) { key = String.Format("{0}.{1}", appCalcName, key); } list.add(key, 0); } //加快速度 foreach (MessureValue mv in simpleInfo.MesValues.Where(s => s.Date == date)) { MessureParam mp = simpleInfo.MesParams.Find(delegate(MessureParam item) { return(item.Id == mv.ParamId); }); string key = mp.ParamSymbol; if (appendDot) { key = String.Format("{0}.{1}", appCalcName, key); } list[key] = mv.Val.Value; } //加快速度 foreach (CalculateValue cv in simpleInfo.CalcValues.Where(s => s.Date == date)) { CalculateParam cp = simpleInfo.CalcParams.Find(delegate(CalculateParam item) { return(item.Id == cv.ParamId); }); string key = cp.ParamSymbol; if (appendDot) { key = String.Format("{0}.{1}", appCalcName, key); } list[key] = cv.Val.Value; } }
/// <summary> /// 由于messure values更改了,需要重新计算calc values的值 /// </summary> /// <param name="appInfo"></param> /// <param name="currentRow"></param> /// <param name="date"></param> internal static void reCalcValues(AppIntegratedInfo appInfo, DataRow currentRow, DateTimeOffset date) { hammergo.caculator.CalcFunction calc = new hammergo.caculator.CalcFunction(); hammergo.caculator.MyList list = new hammergo.caculator.MyList(); //填充自身,要求在appInfo中的数据是更新后的数据 fillListByCalcName_Date(list, date, false, appInfo); //分析此仪器是否引用了其它仪器的数据 hammergo.caculator.MyList appCalcNameList = new hammergo.caculator.MyList();//引用的其它仪器名称的集合 var sortedParams = new SortedDictionary <byte, ParamHelper>(); //这里必须按照calc order 的顺序 foreach (CalculateParam cp in appInfo.CalcParams) { Formula formulaEntity = appInfo.AllFormulae.SingleOrDefault(s => s.ParamId == cp.Id && s.StartDate <= date && date < s.EndDate); if (formulaEntity == null) { throw new Exception(string.Format("找不到对应时间:{0:u}的工式,请检查测点的参数信息", date)); } sortedParams.Add(formulaEntity.CalculateOrder, new ParamHelper { FormulaEntity = formulaEntity, Param = cp }); string formulaString = formulaEntity.FormulaExpression;//获取表达式 System.Collections.ArrayList vars = calc.getVaribles(formulaString); //为了避免对某个测点的数据重复查询,将一次性填充一支仪器的数据 for (int j = 0; j < vars.Count; j++) { string vs = (string)vars[j]; int pos = vs.IndexOf('.'); if (pos != -1) { //引用了其它测点 string otherID = vs.Substring(0, pos); appCalcNameList.add(otherID, 0); //避免由于计算时依赖其它仪器,而其它仪器没有此刻的记录时,导致异常 list.add(vs, 0); } } } //填充带点的参数 for (int i = 0; i < appCalcNameList.Length; i++) { AppIntegratedInfo simpleAppInfo = new AppIntegratedInfo(appCalcNameList.getKey(i), date); fillListByCalcName_Date(list, date, true, simpleAppInfo); } //可以进行表达式求值了 //根据计算顺序 for (int i = 0; i < sortedParams.Count; i++) { var helperobj = sortedParams.ElementAt(i).Value; var cp = helperobj.Param; //顺序是以order 升序排列 string formula = helperobj.FormulaEntity.FormulaExpression;//获取表达式 double v = calc.compute(formula, list); byte precision = cp.PrecisionNum; if (precision >= 0) { v = Helper.Round(v, precision); } CalculateValue calcValue = appInfo.CalcValues.Find(delegate(CalculateValue item) { return(item.Date == date && item.ParamId == cp.Id); }); if (calcValue == null) { //create new object calcValue = new CalculateValue(); calcValue.Date = date; calcValue.ParamId = cp.Id; appInfo.CalcValues.Add(calcValue); //添加到dbcontext中 appInfo.DbContext.AddToCalculateValues(calcValue); } calcValue.Val = v; appInfo.DbContext.UpdateObject(calcValue); //在填充时已添加,这里就不能添加 list[cp.ParamSymbol] = v; if (currentRow != null) { currentRow[cp.ParamName] = v; } } }
//重新计算相关值,并反映在gridview中 public static void redirectToObjects(AppIntegratedInfo appInfo, DataRow row, string feildName) { DateTimeOffset date = (DateTimeOffset)row[PubConstant.timeColumnName]; MessureParam mp = appInfo.MesParams.FirstOrDefault(s => s.ParamName == feildName); if (mp != null) { MessureValue editedValue = appInfo.MesValues.Find(delegate(MessureValue item) { return(item.Date == date && item.ParamId == mp.Id); }); if (editedValue == null) { //create new object editedValue = new MessureValue(); editedValue.Date = date; editedValue.ParamId = mp.Id; appInfo.MesValues.Add(editedValue); appInfo.DbContext.AddToMessureValues(editedValue); } editedValue.Val = (double)row[feildName]; appInfo.DbContext.UpdateObject(editedValue); //recalculate the calc values reCalcValues(appInfo, row, date); } else { //直接编辑成果值,所有不用计算本测点的数据,但需要更新引用测点的数据 CalculateParam cp = appInfo.CalcParams.Find(delegate(CalculateParam item) { return(item.ParamName == feildName); }); if (cp != null) { CalculateValue calcValue = appInfo.CalcValues.Find(delegate(CalculateValue item) { return(item.Date == date && item.ParamId == cp.Id); }); if (calcValue == null) { //create new object calcValue = new CalculateValue(); calcValue.Date = date; calcValue.ParamId = cp.Id; appInfo.CalcValues.Add(calcValue); appInfo.DbContext.AddToCalculateValues(calcValue); } calcValue.Val = (double)row[feildName]; //dbcontext标记要更新 appInfo.DbContext.UpdateObject(calcValue); } } //may be need reset the filter to null }