using IStation.DAL;
|
using System.Reflection;
|
|
namespace IStation.Algorithm
|
{
|
/// <summary>
|
/// 分析泵项
|
/// </summary>
|
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<AnaPumpFreItem> 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<AnaPumpFreItem>();
|
//var freItemDef = new AnaFrequencyItem();
|
//freItemDef.Frequency = freMax;
|
//freItemDef.CurveQH = this.CurveQH.Clone();
|
//freItemDef.CurveQP = this.CurveQP.Clone();
|
//this.AnaFrequencyItems.Add(freItemDef);
|
for (double fre = freMax; fre >= freMin; fre -= freSpace)
|
{
|
var freItem = new AnaPumpFreItem();
|
freItem.Frequency = fre;
|
freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre);
|
freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre);
|
this.AnaFrequencyItems.Add(freItem);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 分析泵变频项
|
/// </summary>
|
public class AnaPumpFreItem
|
{
|
public double Frequency { get; set; }
|
public Curve.CurveExpress CurveQH { get; set; }
|
public Curve.CurveExpress CurveQP { get; set; }
|
}
|
|
/// <summary>
|
/// 调度分析辅助类
|
/// </summary>
|
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;
|
|
ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper();
|
|
#region TableName
|
string _tableFrePumpTag = "B";
|
string _tableFixPumpTag = "G";
|
string _tableSpaceMark = "_";
|
|
string GetTableName(List<AnaPumpItem> 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 += GetTableName(pumpItem);
|
if ((i + 1) != count)
|
{
|
tableName += _tableSpaceMark;
|
}
|
}
|
return tableName;
|
}
|
|
string GetTableName(AnaPumpItem pumpItem)
|
{
|
return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID;
|
}
|
|
#endregion
|
|
public bool AnaOptList(List<Pump> pumps)
|
{
|
if (pumps == null || pumps.Count < 1)
|
return false;
|
var fre_def = _frequency_def;
|
var anaPumpItems = new List<AnaPumpItem>();
|
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)
|
return false;
|
|
var maxRunCount = 3;
|
var anaPumpItemsArray = anaPumpItems.ToArray();
|
for (int runCount = 1; runCount <= maxRunCount; runCount++)
|
{
|
var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount);
|
//if (runCount == 1)
|
//{
|
// foreach (var pumpCombine in pumpCombineList)
|
// {
|
// var start = DateTime.Now;
|
// AnaSinglePump(pumpCombine[0], _head_space);
|
// var end = DateTime.Now;
|
// var tabName = GetTableName(pumpCombine[0]);
|
// Db.Insert(tabName, 1, start, end);
|
// }
|
//}
|
//else
|
if (runCount == 2)
|
{
|
foreach (var pumpCombine in pumpCombineList)
|
{
|
var start = DateTime.Now;
|
var list = pumpCombine.ToList();
|
AnaTwoPumps(list, _head_space);
|
var end = DateTime.Now;
|
var tabName = GetTableName(list);
|
Db.Insert(tabName, 1, start, end);
|
}
|
}
|
//else if (runCount == 3)
|
//{
|
// foreach (var pumpCombine in pumpCombineList)
|
// {
|
// var start = DateTime.Now;
|
// var list = pumpCombine.ToList();
|
// AnaThreePumps(list, _head_space);
|
// var end = DateTime.Now;
|
// var tabName = GetTableName(list);
|
// Db.Insert(tabName, 1, start, end);
|
// }
|
//}
|
}
|
|
return true;
|
}
|
|
private void AnaSinglePump(AnaPumpItem anaPump, double headSpace)
|
{
|
if (anaPump == null)
|
return;
|
if (!anaPump.AllowCalc)
|
return;
|
//var runFlag = (int)Math.Pow(2, anaPump.ID);//运行标志
|
var runFlag = GetTableName(anaPump);//运行标志
|
var scheduleCombineList = new List<ScheduleCombine>();
|
var anaFreItems = anaPump.AnaFrequencyItems;
|
foreach (var anaFreItem in anaFreItems)
|
{
|
var curveQH = anaFreItem.CurveQH;
|
var curveQP = anaFreItem.CurveQP;
|
var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY);
|
if (!bol)
|
continue;
|
var maxHead = Math.Ceiling(maxY);
|
var minHead = Math.Floor(minY);
|
|
for (double head = minHead; head <= maxHead; head += headSpace)
|
{
|
var flow = curveQH.GetInterPointLastX(head);
|
if (!flow.HasValue)
|
continue;
|
|
var scheduleCombine = new ScheduleCombine();
|
scheduleCombine.RunFlag = runFlag;
|
scheduleCombine.Pump1 = anaFreItem.Frequency;
|
scheduleCombine.Head = head;
|
scheduleCombine.Flow = flow.Value;
|
scheduleCombine.Power = curveQP.GetFitPointY(flow.Value);
|
scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
|
scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
|
scheduleCombine.Round();
|
scheduleCombineList.Add(scheduleCombine);
|
}
|
}
|
|
var success = Db.BulkInserts(scheduleCombineList);
|
if (!success)
|
{
|
|
}
|
}
|
|
|
private void AnaTwoPumps(List<AnaPumpItem> anaPumps, double headSpace)
|
{
|
if (anaPumps == null || anaPumps.Count != 2)
|
return;
|
if (anaPumps.Exists(x => !x.AllowCalc))
|
return;
|
string runFlag = GetTableName(anaPumps); //运行标志
|
//foreach (var anaPump in anaPumps)
|
//{
|
// runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
|
//}
|
var scheduleCombineList = new List<ScheduleCombine>();
|
var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
|
var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
|
for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
|
{
|
for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
|
{
|
var anaFreItem1 = anaFreItems1[anaIndex1];
|
var anaFreItem2 = anaFreItems2[anaIndex2];
|
|
_parallelConnectionHelper.ClearCurve();
|
_parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
|
_parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
|
var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
|
if (!allowParallel)
|
continue;
|
var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
|
if (!bol)
|
continue;
|
var maxHead = Math.Ceiling(maxY);
|
var minHead = Math.Floor(minY);
|
|
for (double head = minHead; head <= maxHead; head += headSpace)
|
{
|
var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
|
if (!flow.HasValue)
|
continue;
|
var scheduleCombine = new ScheduleCombine();
|
scheduleCombine.RunFlag = runFlag;
|
scheduleCombine.Pump1 = anaFreItem1.Frequency;
|
scheduleCombine.Pump2 = anaFreItem2.Frequency;
|
scheduleCombine.Head = head;
|
scheduleCombine.Flow = flow.Value;
|
scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
|
scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
|
scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
|
scheduleCombine.Round();
|
scheduleCombineList.Add(scheduleCombine);
|
}
|
}
|
}
|
var success = Db.BulkInserts(scheduleCombineList);
|
if (!success)
|
{
|
|
}
|
}
|
|
private void AnaThreePumps(List<AnaPumpItem> anaPumps, double headSpace)
|
{
|
if (anaPumps == null || anaPumps.Count != 3)
|
return;
|
if (anaPumps.Exists(x => !x.AllowCalc))
|
return;
|
string runFlag = GetTableName(anaPumps);//运行标志
|
//foreach (var anaPump in anaPumps)
|
//{
|
// runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
|
//}
|
var scheduleCombineList = new List<ScheduleCombine>();
|
var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
|
var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
|
var anaFreItems3 = anaPumps[2].AnaFrequencyItems;
|
for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
|
{
|
for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
|
{
|
for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++)
|
{
|
var anaFreItem1 = anaFreItems1[anaIndex1];
|
var anaFreItem2 = anaFreItems2[anaIndex2];
|
var anaFreItem3 = anaFreItems3[anaIndex3];
|
|
_parallelConnectionHelper.ClearCurve();
|
_parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
|
_parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
|
var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
|
if (!allowParallel)
|
continue;
|
var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
|
if (!bol)
|
continue;
|
var maxHead = Math.Ceiling(maxY);
|
var minHead = Math.Floor(minY);
|
|
for (double head = minHead; head <= maxHead; head += headSpace)
|
{
|
var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
|
if (!flow.HasValue)
|
continue;
|
var scheduleCombine = new ScheduleCombine();
|
scheduleCombine.RunFlag = runFlag;
|
scheduleCombine.Pump1 = anaFreItem1.Frequency;
|
scheduleCombine.Pump2 = anaFreItem2.Frequency;
|
scheduleCombine.Pump3 = anaFreItem3.Frequency;
|
scheduleCombine.Head = head;
|
scheduleCombine.Flow = flow.Value;
|
scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
|
scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
|
scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
|
scheduleCombine.Round();
|
scheduleCombineList.Add(scheduleCombine);
|
}
|
}
|
}
|
}
|
var success = Db.BulkInserts(scheduleCombineList);
|
if (!success)
|
{
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
/// 数据库
|
/// </summary>
|
public class Db
|
{
|
/// <summary>
|
/// 连接配置
|
/// </summary>
|
public static ConnectionConfig ConnectionConfig
|
{
|
get
|
{
|
|
var filePath = DbInitial.DbFilePath;
|
if (!System.IO.File.Exists(filePath))
|
{
|
DAL.DbInitial.InitTables();
|
}
|
|
var config = new ConnectionConfig()
|
{
|
ConnectionString = $"DataSource={filePath}",
|
IsAutoCloseConnection = true,
|
DbType = SqlSugar.DbType.Sqlite
|
};
|
return config;
|
}
|
}
|
|
|
|
/// <summary>
|
/// 大批量插入
|
/// </summary>
|
public static bool BulkInserts(List<ScheduleCombine> list)
|
{
|
if (list == null || list.Count < 1)
|
return default;
|
using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
|
{
|
///自己来制定定义的规则
|
db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService();
|
db.CodeFirst
|
.SplitTables()//标识分表
|
.InitTables<ScheduleCombine>(); //程序启动时加这一行,如果一张表没有会初始化一张
|
|
//大数据写入+表不存在会建表
|
//自动找表大数据写入
|
return db.Fastest<ScheduleCombine>().SplitTable().BulkCopy(list) > 0;
|
}
|
}
|
|
/// <summary>
|
/// 插入
|
/// </summary>
|
public static bool Insert(string flag, int count, DateTime start, DateTime end)
|
{
|
var log = new AnaLog(flag, count, start, end);
|
using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
|
{
|
return db.Insertable(log).ExecuteCommand() > 0;
|
}
|
}
|
|
internal static object SplitHelper<T>()
|
{
|
throw new NotImplementedException();
|
}
|
}
|
|
/// <summary>
|
/// 分表规则
|
/// </summary>
|
public class RunFlagSubTableService : ISplitTableService
|
{
|
/// <summary>
|
/// 获取所有的数据库中的表
|
/// </summary>
|
/// <param name="db"></param>
|
/// <param name="EntityInfo"></param>
|
/// <param name="tableInfos"></param>
|
/// <returns></returns>
|
/// <exception cref="NotImplementedException"></exception>
|
public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
|
{
|
List<SplitTableInfo> result = new List<SplitTableInfo>();
|
foreach (var item in tableInfos)
|
{
|
if (item.Name.Contains("_Run_")) //区分标识如果不用正则符复杂一些,防止找错表
|
{
|
SplitTableInfo data = new SplitTableInfo()
|
{
|
TableName = item.Name //要用item.name不要写错了
|
};
|
result.Add(data);
|
}
|
}
|
return result.OrderBy(it => it.TableName).ToList();//打断点看一下有没有查出所有分表
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="db"></param>
|
/// <param name="entityInfo"></param>
|
/// <param name="splitType"></param>
|
/// <param name="entityValue"></param>
|
/// <returns></returns>
|
public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
|
{
|
var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
|
|
return splitColumn.PropertyInfo.GetValue(entityValue, null);
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="db"></param>
|
/// <param name="EntityInfo"></param>
|
/// <returns></returns>
|
public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
|
{
|
return EntityInfo.DbTableName + "_Run";
|
}
|
|
public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
|
{
|
return EntityInfo.DbTableName + "_Run";
|
}
|
|
/// <summary>
|
/// 确定生成数据库表的时候,表的名称
|
/// </summary>
|
/// <param name="db"></param>
|
/// <param name="entityInfo"></param>
|
/// <param name="splitType"></param>
|
/// <param name="fieldValue"></param>
|
/// <returns></returns>
|
public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
|
{
|
return entityInfo.DbTableName + "_Run_" + fieldValue.ToString();
|
}
|
}
|
|
/// <summary>
|
/// 调度组合
|
/// </summary>
|
[SplitTable(SplitType._Custom01)]
|
public class ScheduleCombine
|
{
|
public ScheduleCombine() { }
|
public ScheduleCombine(ScheduleCombine rhs)
|
{
|
this.Pump1 = rhs.Pump1;
|
this.Pump2 = rhs.Pump2;
|
this.Pump3 = rhs.Pump3;
|
this.Head = rhs.Head;
|
this.Flow = rhs.Flow;
|
this.Power = rhs.Power;
|
this.WP = rhs.WP;
|
this.UWP = rhs.UWP;
|
}
|
|
public void Round()
|
{
|
this.Pump1 = Math.Round(this.Pump1, 1);
|
this.Pump2 = Math.Round(this.Pump2, 1);
|
this.Pump3 = Math.Round(this.Pump3, 1);
|
this.Head = Math.Round(this.Head, 1);
|
this.Flow = Math.Round(this.Flow, 1);
|
this.Power = Math.Round(this.Power, 1);
|
this.WP = Math.Round(this.WP, 1);
|
this.UWP = Math.Round(this.UWP, 1);
|
|
}
|
|
/// <summary>
|
/// 运行标志 (标志枚举)
|
/// </summary>
|
[SplitField]
|
public string RunFlag { get; set; }
|
|
/// <summary>
|
/// 泵1
|
/// </summary>
|
public double Pump1 { get; set; }
|
|
/// <summary>
|
/// 泵2
|
/// </summary>
|
public double Pump2 { get; set; }
|
|
/// <summary>
|
/// 泵3
|
/// </summary>
|
public double Pump3 { get; set; }
|
|
/// <summary>
|
/// 扬程
|
/// </summary>
|
public double Head { get; set; }
|
|
/// <summary>
|
/// 总流量
|
/// </summary>
|
public double Flow { get; set; }
|
|
/// <summary>
|
/// 总功率
|
/// </summary>
|
public double Power { get; set; }
|
|
/// <summary>
|
/// 千吨水能耗
|
/// </summary>
|
public double WP { get; set; }
|
|
/// <summary>
|
/// 单位能耗
|
/// </summary>
|
public double UWP { get; set; }
|
|
/// <summary>
|
/// 创建时间
|
/// </summary>
|
public DateTime CreateTime { get; set; } = DateTime.Now;
|
|
|
}
|
}
|