using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace IStation.WinFrmUI
{
///
/// 导出 分析系数
///
public partial class ExportScadaAnalysisFactorHelper
{
public class PumpModel
{
public DateTime Time { get; set; }
public int Flag { get; set; }
public double Rpm { get; set; }
public double Hz { get; set; }
public double Hz0 { get; set; }
public double Flow { get; set; }
public double Head { get; set; }
public double CurveHead { get; set; }
public double HeadDiff { get; set; }
public double CorrectCurveHead { get; set; }
public double CorrectHeadDiff { get; set; }
}
///
/// 分析系数
///
public class AnalysisFactor
{
///
/// 泵标志
///
public int Flag { get; set; }
///
/// 频率
///
public double Hz { get; set; }
///
/// 扬程标准差
///
public double? HeadSTDP { get; set; }
///
/// 扬程偏差
///
public double? HeadDeviation { get; set; }
///
/// 准确度
///
public double Accuracy { get; set; }
}
static BLL.StationSignalRecordPacket _packet = new BLL.StationSignalRecordPacket();
///
/// 绑定数据
///
public static bool Export(long monitorDataSourcesId, long stationId, string name)
{
var packets = _packet.Get(monitorDataSourcesId, stationId);
if (packets == null || !packets.Any())
return false;
var eq_list = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, stationId);
if (eq_list == null || !eq_list.Any())
return false;
var flag_list = eq_list.Select(x => x.SortCode).OrderBy(x => x).ToList();
var flag_pump_dict = eq_list.ToDictionary(x => x.SortCode, x => x.RatedParas);
var flag_curve_dict = new Dictionary();
var bll_curve = new BLL.PumpCurve();
foreach (var pump in eq_list)
{
Model.CurveExpress qh = null;
var curve_info = bll_curve.GetDefaultWorkingByPumpID(pump.ID)?.CurveInfo;
if (curve_info != null)
{
qh = curve_info.CurveQH;
}
flag_curve_dict.Add(pump.SortCode, qh);
}
var vm_pump_list = new List();
foreach (var packet in packets)
{
var station_signal_records = packet.StationSignalRecords;
if (station_signal_records == null || !station_signal_records.Any())
continue;
foreach (var record in station_signal_records)
{
var pump_signal_records = record.PumpSignalRecords;
if (pump_signal_records == null || !pump_signal_records.Any())
continue;
pump_signal_records = pump_signal_records.OrderBy(x => x.Flag).ToList();
foreach (var pump_record in pump_signal_records)
{
if (pump_record.Rpm == IStation.Error.Default || pump_record.Head == IStation.Error.Default)
{
continue;
}
var flag = pump_record.Flag;
var pump = flag_pump_dict[flag];
var curve_qh = flag_curve_dict[flag];
var hz = pump_record.Rpm / pump.Nr * 50;
hz = Math.Round(hz, 2);
var curve_head = GetCurveHead(curve_qh, pump.Nr, pump_record.Rpm, pump_record.FlowRate);
curve_head = Math.Round(curve_head, 2);
var pump_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(pump_record.Head, hz);
var curve_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(curve_head, hz);
var head_diff = pump_head50hz - curve_head50hz;
var vm_pump = new PumpModel();
vm_pump.Time = record.Time;
vm_pump.Flag = flag;
vm_pump.Rpm = pump_record.Rpm;
vm_pump.Hz = hz;
vm_pump.Hz0 = Math.Round(hz, 0);
vm_pump.Head = pump_record.Head;
vm_pump.Flow = pump_record.FlowRate;
vm_pump.CurveHead = curve_head;
vm_pump.HeadDiff = head_diff;
vm_pump_list.Add(vm_pump);
}
}
}
if (!vm_pump_list.Any())
return false;
var analysis_facotr_list = new List();
var group_by_flag_hz = vm_pump_list.GroupBy(x => new { x.Flag, x.Hz0 });
foreach (var flag_item in group_by_flag_hz)
{
var hz = flag_item.Key.Hz0;
if (hz < 20)
{
continue;
}
var flag = flag_item.Key.Flag;
var pump = flag_pump_dict[flag];
var qh = flag_curve_dict[flag];
var head_diff_list = flag_item.Select(x => x.HeadDiff).ToList();
double head_diff_avg = 0d, std_dev_pop = 0d, std_dev_pop_head_avg = 0d;
var filter_std_dev_pop_tuple = FilterBySTDP(head_diff_list.ToArray(), 0.3, 0);
var filter_std_dev_pop_array = filter_std_dev_pop_tuple.Item1;
std_dev_pop = filter_std_dev_pop_tuple.Item2;
std_dev_pop_head_avg = filter_std_dev_pop_array.Average();
head_diff_avg = std_dev_pop_head_avg;
if (Math.Abs(head_diff_avg) > 5)
{
continue;
}
if (std_dev_pop>1)
{
continue;
}
if (std_dev_pop > 0.5 && flag_item.Count() < 5)
{
continue;
}
var analysis_facotr = new AnalysisFactor();
analysis_facotr.Flag = flag;
analysis_facotr.Hz = hz;
analysis_facotr.HeadSTDP = std_dev_pop;
analysis_facotr.HeadDeviation = std_dev_pop_head_avg;
analysis_facotr.Accuracy = 0;
analysis_facotr_list.Add(analysis_facotr);
}
analysis_facotr_list = analysis_facotr_list.OrderBy(x => x.Flag).ThenBy(x => x.Hz).ToList();
var flag_range5_hz_factor_dict = new Dictionary>>();
var group_by_flag = vm_pump_list.GroupBy(x => x.Flag);
foreach (var flag_item in group_by_flag)
{
var flag = flag_item.Key;
var pump = flag_pump_dict[flag];
var qh = flag_curve_dict[flag];
if (!pump.IsBp)
{
continue;
}
flag_range5_hz_factor_dict.Add(flag, new Dictionary>());
for (double i = 5; i <= 50; i += 5)
{
var min_hz = i - 5;
double max_hz = i;
var list = flag_item.Where(x => x.Hz >= min_hz && x.Hz <= max_hz).ToList();
if (list == null || list.Count() < 5)
continue;
var head_diff_list = list.Select(x => x.HeadDiff).ToList();
double std_dev_pop = 0d, std_dev_pop_head_avg = 0d;
var filter_tuple = FilterBySTDP(head_diff_list.ToArray(), 0.3, 0);
var filter_array = filter_tuple.Item1;
std_dev_pop = filter_tuple.Item2;
std_dev_pop_head_avg = filter_array.Average();
flag_range5_hz_factor_dict[flag].Add(max_hz, new Tuple(std_dev_pop, std_dev_pop_head_avg, filter_array.Count()));
}
}
var not_hz_list = new List();
foreach (var eq in eq_list)
{
var flag = eq.SortCode;
var pump = flag_pump_dict[flag];
if (!pump.IsBp)
{
continue;
}
var qh = flag_curve_dict[flag];
var dict_item = flag_range5_hz_factor_dict[flag];
for (int hz = 1; hz <= 50; hz++)
{
if (analysis_facotr_list.Exists(x => x.Flag == flag && x.Hz == hz))
{
continue;
}
var num = hz / 5;
var hz_key = (num + 1) * 5;
if (hz_key > 50)
hz_key = 50;
if (dict_item.ContainsKey(hz_key))
{
var tuple = dict_item[hz_key];
var analysis_facotr = new AnalysisFactor();
analysis_facotr.Flag = flag;
analysis_facotr.Hz = hz;
analysis_facotr.HeadSTDP = tuple.Item1;
analysis_facotr.HeadDeviation = tuple.Item2;
analysis_facotr.Accuracy = 0;
not_hz_list.Add(analysis_facotr);
}
else
{
var key_list = dict_item.Select(x => x.Key).ToList();
var key = key_list.Where(x => x >= hz_key)?.OrderBy(x => x).FirstOrDefault();
if (key == null)
{
key = key_list.OrderByDescending(x => x).FirstOrDefault();
}
if (key == null)
{
throw new Exception("error");
}
var tuple = dict_item[key.Value];
double ratio = hz / key.Value;
double head_dev = tuple.Item2 * ratio;
double head_stdp = tuple.Item1 * ratio;
var analysis_facotr = new AnalysisFactor();
analysis_facotr.Flag = flag;
analysis_facotr.Hz = hz;
analysis_facotr.HeadSTDP = head_stdp;
analysis_facotr.HeadDeviation = head_dev;
analysis_facotr.Accuracy = -1;
not_hz_list.Add(analysis_facotr);
}
}
}
var analysis_factor_list = new List();
analysis_factor_list.AddRange(analysis_facotr_list);
analysis_factor_list.AddRange(not_hz_list);
var root_folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "分析系数");
if (!Directory.Exists(root_folder))
{
Directory.CreateDirectory(root_folder);
}
var fileName = root_folder + "\\" + name + ".json";
var json = JsonHelper.Object2Json(analysis_factor_list);
File.WriteAllText(fileName, json);
return true;
}
#region Function
private static Tuple FilterBySTDP(double[] array, double min_dev, int count)
{
if (array == null || !array.Any())
{
return default;
}
var array_avg = array.Average();
var array_count = array.Count();
FilterOutliersHelper.STDEV(array, out double std_dev, out double std_dev_pop);
if (Math.Abs(std_dev_pop) < min_dev)
{
return new Tuple(array, std_dev_pop);
}
if (count > 3)
{
return new Tuple(array, std_dev_pop);
}
var filter_array = array.Where(x => !(Math.Abs(x - array_avg) > Math.Abs(std_dev_pop * 2))).ToArray();
if (filter_array == null || !filter_array.Any())
{
return default;
}
count++;
return FilterBySTDP(filter_array, min_dev, count);
}
private static double GetCurveHead(Model.CurveExpress curve_qh, double nr, double rpm, double flow)
{
if (curve_qh == null)
return default;
var similar_qh = Model.CurveCalcuHelper.CalculateSimilarQH(curve_qh, nr, rpm);
if (similar_qh == null)
return default;
var head = similar_qh.GetFitPointY(flow);
return head;
}
#endregion
}
}