namespace IStation.Algorithm
{
#region ViewModel
///
/// 分析泵项
///
public class AnaPumpItem
{
public AnaPumpItem() { }
public AnaPumpItem(Pump rhs)
{
this.ID = rhs.ID;
this.Name = rhs.Name;
this.Code = rhs.Code;
this.IsBp = rhs.IsBp;
this.Qr = rhs.Qr;
this.Hr = rhs.Hr;
this.Nr = rhs.Nr;
this.Pr = rhs.Pr;
this.Er = rhs.Er;
if (rhs.CurveQH != null && rhs.CurveQP != null)
{
this.CurveQH = rhs.CurveQH.Clone();
this.CurveQP = rhs.CurveQP.Clone();
this.AllowCalc = true;
}
}
public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs)
{
this.CalcFrequencyItems(freDef, freMin, freMax, freSpace);
}
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public double Qr { get; set; }
public double Hr { get; set; }
public double Nr { get; set; }
public double Pr { get; set; }
public double Er { get; set; }
public bool IsBp { get; set; }
public Curve.CurveExpress CurveQH { get; set; }
public Curve.CurveExpress CurveQP { get; set; }
public List AnaFrequencyItems { get; set; }
public bool AllowCalc { get; set; }
void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace)
{
if (!this.AllowCalc)
return;
this.AnaFrequencyItems = new List();
for (double fre = freMax; fre >= freMin; fre -= freSpace)
{
var freItem = new AnaPumpFreItem();
freItem.Frequency = Math.Round(fre, 1);
freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre);
freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre);
this.AnaFrequencyItems.Add(freItem);
}
}
}
///
/// 分析泵变频项
///
public class AnaPumpFreItem
{
public double Frequency { get; set; }
public Curve.CurveExpress CurveQH { get; set; }
public Curve.CurveExpress CurveQP { get; set; }
}
#endregion
///
/// 调度分析辅助类
///
public class SchedulingAnaHelper
{
double _frequency_def = 50;
double _frequency_min = 25;
double _frequency_max = 50;
double _frequency_space = 0.1;//频率间隔
double _head_space = 0.1;//扬程间隔
#region RunFlag
string _falgFrePumpTag = "B";
string _falgFixPumpTag = "G";
string _falgSpaceMark = "_";
string GetRunFlag(List pumpItems)
{
var tableName = string.Empty;
var count = pumpItems.Count;
pumpItems = pumpItems.OrderBy(p => p.ID).ToList();
for (int i = 0; i < count; i++)
{
var pumpItem = pumpItems[i];
tableName += GetRunFlag(pumpItem);
if ((i + 1) != count)
{
tableName += _falgSpaceMark;
}
}
return tableName;
}
string GetRunFlag(AnaPumpItem pumpItem)
{
return (pumpItem.IsBp ? _falgFrePumpTag : _falgFixPumpTag) + pumpItem.ID;
}
#endregion
DAL.ScheduleCombine _dal = new DAL.ScheduleCombine();
DAL.ScheduleConclusion _dalScheduleConclusion = new DAL.ScheduleConclusion();
DAL.ScheduleAnaLog _dalAnaLog = new DAL.ScheduleAnaLog();
///
/// 分析泵组合
///
/// 泵列表
///
public void AnaCombine(List pumps)
{
InsertAnaLog("开始分析泵组合");
if (pumps == null || pumps.Count < 1)
{
InsertAnaLog("分析失败:pumps == null || pumps.Count < 1");
return;
}
var fre_def = _frequency_def;
var anaPumpItems = new List();
foreach (var pump in pumps)
{
if (pump.IsBp)
{
//变频泵
var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space);
if (anaPump.AllowCalc)
anaPumpItems.Add(anaPump);
}
else
{
//固频泵
var anaPump = new AnaPumpItem(pump);
if (anaPump.AllowCalc)
anaPumpItems.Add(anaPump);
}
}
if (anaPumpItems.Count < 1)
{
InsertAnaLog("分析失败:anaPumpItems.Count < 1");
return;
}
string runFlag;
List pump1, pump2, pump3;
var maxPumpCount = 2;
var anaPumpItemsArray = anaPumpItems.ToArray();
var parallelHelper = new ParallelConnectionHelper();
for (int pumpCount = 1; pumpCount <= maxPumpCount; pumpCount++)
{
var pumpCombineList = PermutationAndCombination.GetCombination(anaPumpItemsArray, pumpCount);
var pumpCombineCount = pumpCombineList.Count;
InsertAnaLog($"分析进度:{pumpCount}台泵,{pumpCombineCount}个组合");
switch (pumpCount)
{
case 1:
{
for (int i = 0; i < pumpCombineCount; i++)
{
var pumpCombine = pumpCombineList[i].ToList();
pump1 = pumpCombine[0].AnaFrequencyItems;
runFlag = GetRunFlag(pumpCombine);
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag},第{i + 1}个组合");
if (ExistTable(runFlag))
{
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag}已存在");
continue;
}
var list = new List(pump1.Count);
foreach (var freItem in pump1)
{
var scheduleCombine = new Entity.ScheduleCombine();
scheduleCombine.RunFlag = runFlag;
scheduleCombine.RunCount = pumpCount;
scheduleCombine.Pump1 = freItem.Frequency;
scheduleCombine.CurveQH = freItem.CurveQH.ToJson();
scheduleCombine.CurveQP = freItem.CurveQP.ToJson();
scheduleCombine.AnaStatus = false;
list.Add(scheduleCombine);
}
InsertCombine(i + 1, runFlag, list);
}
InsertAnaLog($"分析进度:{pumpCount}台泵,分析完毕!");
}
break;
case 2:
{
for (int i = 0; i < pumpCombineCount; i++)
{
var pumpCombine = pumpCombineList[i].ToList();
pump1 = pumpCombine[0].AnaFrequencyItems;
pump2 = pumpCombine[1].AnaFrequencyItems;
runFlag = GetRunFlag(pumpCombine);
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag},第{i + 1}个组合");
if (ExistTable(runFlag))
{
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag}已存在");
continue;
}
var list = new List(pump1.Count * pump2.Count);
for (int pump1Index = 0; pump1Index < pump1.Count; pump1Index++)
{
for (int pump2Index = 0; pump2Index < pump2.Count; pump2Index++)
{
var freItem1 = pump1[pump1Index];
var freItem2 = pump2[pump2Index];
parallelHelper.ClearCurve();
parallelHelper.AddCurve(freItem1.CurveQH, freItem1.CurveQP);
parallelHelper.AddCurve(freItem2.CurveQH, freItem2.CurveQP);
var allowParallel = parallelHelper.CalculateParallel(out List pointQH, out List pointQE, out List pointQP);
if (!allowParallel)
continue;
var scheduleCombine = new Entity.ScheduleCombine();
scheduleCombine.RunFlag = runFlag;
scheduleCombine.RunCount = pumpCount;
scheduleCombine.Pump1 = freItem1.Frequency;
scheduleCombine.Pump2 = freItem2.Frequency;
scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH).ToJson();
scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP).ToJson();
scheduleCombine.AnaStatus = false;
list.Add(scheduleCombine);
}
}
InsertCombine(i + 1, runFlag, list);
}
InsertAnaLog($"分析进度:{pumpCount}台泵,分析完毕!");
}
break;
case 3:
{
for (int i = 0; i < pumpCombineCount; i++)
{
var pumpCombine = pumpCombineList[i].ToList();
pump1 = pumpCombine[0].AnaFrequencyItems;
pump2 = pumpCombine[1].AnaFrequencyItems;
pump3 = pumpCombine[2].AnaFrequencyItems;
runFlag = GetRunFlag(pumpCombine);
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag},第{i + 1}个组合");
if (ExistTable(runFlag))
{
InsertAnaLog($"分析进度:{pumpCount}台泵,{runFlag}已存在");
continue;
}
var list = new List(pump1.Count * pump2.Count * pump3.Count);
for (int pump1Index = 0; pump1Index < pump1.Count; pump1Index++)
{
for (int pump2Index = 0; pump2Index < pump2.Count; pump2Index++)
{
for (int pump3Index = 0; pump3Index < pump3.Count; pump3Index++)
{
var freItem1 = pump1[pump1Index];
var freItem2 = pump2[pump2Index];
var freItem3 = pump3[pump3Index];
parallelHelper.ClearCurve();
parallelHelper.AddCurve(freItem1.CurveQH, freItem1.CurveQP);
parallelHelper.AddCurve(freItem2.CurveQH, freItem2.CurveQP);
parallelHelper.AddCurve(freItem3.CurveQH, freItem3.CurveQP);
var allowParallel = parallelHelper.CalculateParallel(out List pointQH, out List pointQE, out List pointQP);
if (!allowParallel)
continue;
var scheduleCombine = new Entity.ScheduleCombine();
scheduleCombine.RunFlag = runFlag;
scheduleCombine.RunCount = pumpCount;
scheduleCombine.Pump1 = freItem1.Frequency;
scheduleCombine.Pump2 = freItem2.Frequency;
scheduleCombine.Pump3 = freItem3.Frequency;
scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH).ToJson();
scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP).ToJson();
scheduleCombine.AnaStatus = false;
list.Add(scheduleCombine);
}
}
}
InsertCombine(i + 1, runFlag, list);
}
InsertAnaLog($"分析进度:{pumpCount}台泵,分析完毕!");
}
break;
default: break;
}
}
}
///
/// 分析结论
///
public void AnaConclusion()
{
InsertAnaLog($"开始分析泵组合结论!");
_dalScheduleConclusion.DeleteAllTable();
var scheduleCombineTableNames = _dal.GetAllTableName();
if (scheduleCombineTableNames == null || !scheduleCombineTableNames.Any())
{
InsertAnaLog($"无泵组合表!");
return;
}
var tableCount = scheduleCombineTableNames.Count();
InsertAnaLog($"分析{tableCount}个组合!");
for (int tableIndex = 0; tableIndex < tableCount; tableIndex++)
{
var tableName = scheduleCombineTableNames[tableIndex];
var scheduleCombineList = _dal.GetAllUnanalyzedAnaByTableName(tableName);
if (scheduleCombineList == null || !scheduleCombineList.Any())
{
InsertAnaLog($"分析进度:{tableName},第{tableIndex + 1}个,分析完毕");
continue;
}
var scheduleCombineListCount = scheduleCombineList.Count();
var scheduleConclusionList = new List>(scheduleCombineListCount);
var scheduleCombineIds = new List(scheduleCombineListCount);
for (int combineIndex = 0; combineIndex < scheduleCombineListCount; combineIndex++)
{
var scheduleCombine = scheduleCombineList[combineIndex];
var scheduleCombineID = scheduleCombine.ID;
scheduleCombineIds.Add(scheduleCombineID);
var curveQH = JsonHelper.Json2Object(scheduleCombine.CurveQH);
var curveQP = JsonHelper.Json2Object(scheduleCombine.CurveQP);
var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY);
if (!bol)
return;
var maxHead = Math.Ceiling(maxY);
var minHead = Math.Floor(minY);
var currentListCount = (int)((maxHead - minHead) / _head_space) + 1;
var currentScheduleConclusionList = new List(currentListCount);
for (double head = minHead; head <= maxHead; head += _head_space)
{
var flow = curveQH.GetInterPointLastX(head);
if (!flow.HasValue)
{
continue;
}
var scheduleConclusion = new Entity.ScheduleConclusion();
scheduleConclusion.ScheduleCombineID = scheduleCombineID;
scheduleConclusion.RunFlag = scheduleCombine.RunFlag;
scheduleConclusion.Pump1 = scheduleCombine.Pump1;
scheduleConclusion.Pump2 = scheduleCombine.Pump2;
scheduleConclusion.Pump3 = scheduleCombine.Pump3;
scheduleConclusion.Head = head;
scheduleConclusion.Flow = flow.Value;
scheduleConclusion.Power = curveQP.GetFitPointY(flow.Value);
scheduleConclusion.UWP = PumpCalculateHelper.CalculateUWP(scheduleConclusion.Power, scheduleConclusion.Flow, scheduleConclusion.Head);
scheduleConclusion.WP = PumpCalculateHelper.CalculateWP(scheduleConclusion.Power, scheduleConclusion.Flow);
scheduleConclusion.Round();
currentScheduleConclusionList.Add(scheduleConclusion);
}
scheduleConclusionList.Add(currentScheduleConclusionList);
}
SetAnaStatus(tableName, scheduleCombineIds);
var list = scheduleConclusionList.SelectMany(x => x.ToList()).ToList();
var runFlag = list[0].RunFlag;
InsertConclusion(tableIndex + 1, runFlag, list);
}
}
///
/// 插入分析日志
///
private void InsertAnaLog(string info)
{
var entity = new Entity.ScheduleAnaLog(info);
_dalAnaLog.Insert(entity);
}
///
/// 判断表是否存在
///
public bool SetAnaStatus(string tableName, List ids)
{
if (ids == null || !ids.Any())
{
return false;
}
return _dal.SetAnaStatus(tableName, ids);
}
///
/// 判断表是否存在
///
public bool ExistTable(string runFlag)
{
return _dal.ExistTable(runFlag);
}
public void InsertCombine(int index, string runFlag, List list)
{
if (list == null || !list.Any())
{
var log = $"{runFlag}:下标:{index},无数据";
InsertAnaLog(log);
return;
}
Task.Run(() =>
{
var sw = Stopwatch.StartNew();
var db = new DAL.ScheduleCombine();
db.BulkInserts_Create(runFlag, list);
var log = $"{runFlag}:下标:{index},数量:{list.Count},插入耗时:{sw.ElapsedMilliseconds / 1000}m";
InsertAnaLog(log);
});
}
public void InsertConclusion(int index, string runFlag, List list)
{
if (list == null || !list.Any())
{
var log = $"{runFlag}:下标:{index},无数据";
InsertAnaLog(log);
return;
}
Task.Run(() =>
{
var sw = Stopwatch.StartNew();
var db = new DAL.ScheduleConclusion();
db.BulkInserts_Create(runFlag, list);
var log = $"分析进度:{runFlag},下标:{index},数量:{list.Count},插入耗时:{sw.ElapsedMilliseconds / 1000}m";
InsertAnaLog(log);
});
}
}
}
//public void Run(Action action, string description)
//{
// Stopwatch sw = Stopwatch.StartNew();
// action();
// var log = $"--> {description}:{sw.ElapsedMilliseconds / 1000}m";
// InsertAnaLog(log);
//}
//public T Run(Func func, string description)
//{
// var sw = Stopwatch.StartNew();
// T result = func();
// var log = $"--> {description}:{sw.ElapsedMilliseconds / 1000}m";
// InsertAnaLog(log);
// return result;
//}