using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.Data;
|
using System.IO;
|
using System.Linq;
|
using System.Net;
|
using System.Net.Http;
|
using System.Net.Http.Headers;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
//using RestSharp;
|
|
namespace CommonBase
|
{
|
public class SolutionSelector
|
{
|
public static string url = null;
|
public class Files
|
{
|
public string inputFile;
|
public string file;
|
}
|
public static DataTable GetBestSolutionDict(bool is界面,string ConfigString,int hostID, out int ValidNum,DateTime dateTime=default(DateTime))
|
{
|
List<Files> FileList = new List<Files>();
|
List<string> files = new List<string>();
|
List<string> Inputfiles=new List<string>();
|
ValidNum = 0;
|
if (dateTime==default(DateTime)) { dateTime=DateTime.Now; }
|
//string currentDirectory = Directory.GetCurrentDirectory();
|
string resultPath = GlobalPath.resultPath;// Path.Combine(GlobalPath.resultPath, "result");
|
string currentDirectory = Directory.GetCurrentDirectory();
|
//string resultPath = GlobalPath.resultPath;
|
string userPathFile = resultPath + "UserPath.ini";
|
string userPath = null;
|
if (File.Exists(userPathFile))
|
{
|
userPath = File.ReadAllText(userPathFile);
|
}
|
if (userPath == null || !Directory.Exists(userPath))
|
{
|
userPath = resultPath;
|
}
|
bool flag = false;
|
|
int lastMinutes = 10;
|
double junfangK = 3;
|
int filter_times = 2;
|
string[] expressStrings = ConfigString.Split(',');
|
if (expressStrings.Length > 0) int.TryParse(expressStrings[0], out lastMinutes);
|
if (expressStrings.Length > 1) double.TryParse(expressStrings[1], out junfangK);
|
if (expressStrings.Length > 2) int.TryParse(expressStrings[2], out filter_times);
|
|
if (is界面)
|
{
|
IDataObject clipboardData = Clipboard.GetDataObject();
|
if (clipboardData != null && clipboardData.GetDataPresent(DataFormats.FileDrop))
|
{
|
files.AddRange((string[])clipboardData.GetData(DataFormats.FileDrop));
|
files.RemoveAll(f => f.ToLower().IndexOf(".json") < 0);
|
if (files.Count > 0) flag = true;
|
}
|
Clipboard.SetText(" ");
|
if (!flag)
|
{
|
if (MessageBox.Show("自动选择历史输出?\r\n是:自动\r\n否:手动", "方案择优", MessageBoxButtons.YesNo) == DialogResult.No)
|
{
|
OpenFileDialog openFileDialog = new OpenFileDialog();
|
|
openFileDialog.InitialDirectory = userPath;
|
openFileDialog.Filter = "JSON Files (*.json)|*.json";
|
openFileDialog.Multiselect = true;
|
|
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
{
|
string[] selectedFilePaths = openFileDialog.FileNames;
|
files.AddRange(selectedFilePaths);
|
}
|
}
|
else
|
{
|
// 获取当前时间
|
DateTime currentTime = dateTime;
|
|
// 计算时间范围,当前时间的十分钟之前
|
DateTime tenMinutesAgo = currentTime.AddMinutes(-lastMinutes);
|
|
// 查找目录下的所有.json文件,并根据修改时间进行筛选
|
string[] jsonFiles = Directory.GetFiles(userPath, "*.json")
|
.Where(file => File.GetLastWriteTime(file) >= tenMinutesAgo && File.GetLastWriteTime(file) <= currentTime)
|
.ToArray();
|
string[] inputFiles = Directory.GetFiles(userPath, "*.input")
|
.Where(file => File.GetLastWriteTime(file) >= tenMinutesAgo && File.GetLastWriteTime(file) <= currentTime)
|
.ToArray();
|
files = jsonFiles.ToList();
|
Inputfiles = inputFiles.ToList();
|
}
|
}
|
}
|
else
|
{
|
// 获取当前时间
|
DateTime currentTime = dateTime;
|
|
// 计算时间范围,当前时间的十分钟之前
|
DateTime tenMinutesAgo = currentTime.AddMinutes(-lastMinutes);
|
|
// 查找目录下的所有.json文件,并根据修改时间进行筛选
|
string[] jsonFiles = Directory.GetFiles(userPath, "*.json")
|
.Where(file => getTimeByFileName(file) >= tenMinutesAgo && getTimeByFileName(file) <= currentTime)
|
.OrderBy(file =>file)
|
.ToArray();
|
|
string[] inputFiles = Directory.GetFiles(userPath, "*.input")
|
.Where(file => getTimeByFileName(file) >= tenMinutesAgo && getTimeByFileName(file) <= currentTime)
|
.OrderBy(file=>file)
|
.ToArray();
|
|
files = jsonFiles.ToList();
|
Inputfiles = inputFiles.ToList();
|
}
|
|
string result = null;
|
|
List<PointF3D> points = new List<PointF3D>();
|
DataTable dt = new DataTable();
|
dt.Columns.Add("时间", typeof(DateTime));
|
if (Inputfiles.Count != 0)
|
{
|
dt.Columns.Add("接口文件");
|
dt.Columns.Add("结果文件");
|
}
|
List<double> RecentScada=null;
|
if (files.Count>0)
|
{
|
LogicModelParams param = null;
|
string file_full = files[files.Count-1];
|
double[] doubles = new double[5];
|
string name = new FileInfo(file_full).Name;
|
if (ParamBuffer.dict.ContainsKey(name))
|
{
|
param = ParamBuffer.dict[name];
|
}
|
else
|
{
|
try
|
{
|
param = MessageCompressHelper.ReadCompressedBase64FromFile<LogicModelParams>(file_full);
|
}
|
catch
|
{
|
// 读取文件内容
|
string fileContent = File.ReadAllText(file_full);
|
param = JsonConvert.DeserializeObject<LogicModelParams>(fileContent);
|
}
|
ParamBuffer.dict.TryAdd(name, param.CloneResult());
|
if (ParamBuffer.dict.Count> lastMinutes*3)
|
{
|
foreach(var key in ParamBuffer.dict.Keys.ToList())
|
{
|
if (getTimeByFileName(key) < DateTime.Now.AddMinutes(-lastMinutes)) ParamBuffer.dict.TryRemove(key,out LogicModelParams v);
|
}
|
}
|
}
|
|
param.dict_ID.TryGetValue(hostID, out variable obj);
|
if (obj == null) { obj = param.OFunction.variable; }
|
|
dict dict = new dict();
|
dict.LoadFromString(obj.objListString);
|
RecentScada = getScadaPumpStatusList(dict);
|
|
|
}
|
else
|
{
|
return new DataTable();
|
}
|
|
for (int i=0;i< files.Count;i++)
|
{
|
string file_full = files[i];
|
LogicModelParams param = null;
|
|
try
|
{
|
double[] doubles = new double[5];
|
List<double> currentScadaList = null;
|
string name = new FileInfo(file_full).Name;
|
if (ParamBuffer.dict.ContainsKey(name))
|
{
|
param = ParamBuffer.dict[name];
|
}
|
else
|
{
|
//try
|
//{
|
// param = MessageCompressHelper.ReadCompressedBase64FromFile<LogicModelParams>(file_full);
|
//}
|
//catch
|
//{
|
|
//}
|
string fileContent = File.ReadAllText(file_full);
|
param = JsonConvert.DeserializeObject<LogicModelParams>(fileContent);
|
// 读取文件内容
|
|
ParamBuffer.dict.TryAdd(name, param.CloneResult());
|
}
|
param.dict_ID.TryGetValue(hostID,out variable obj);
|
if (obj == null) { obj = param.OFunction.variable; }
|
|
dict dict = new dict();
|
dict.LoadFromString(obj.objListString);
|
foreach (var kp in dict)
|
{
|
if (!dt.Columns.Contains(kp.Key)) dt.Columns.Add(kp.Key, typeof(double));
|
}
|
FileInfo fi = new FileInfo(file_full);
|
string file = fi.Name;
|
DataRow dr = dt.NewRow();
|
|
DateTime time = getTimeByFileName(file);
|
|
dr["时间"] = time;
|
int k = 0;
|
foreach (var kp in dict)
|
{
|
dr[kp.Key] = kp.Value;
|
if (k < doubles.Length) doubles[k] = kp.Value;
|
k++;
|
}
|
currentScadaList = getScadaPumpStatusList(dict);
|
bool flagScadaStatus = true;
|
for (int l=0;l< RecentScada.Count;l++)
|
{
|
if (currentScadaList[l] != RecentScada[l])
|
{
|
flagScadaStatus = false;
|
break;
|
}
|
}
|
if (!flagScadaStatus) continue;
|
if (i==files.Count-1 && dt.Rows.Count==0 || (double)dr["福永目标"] < 4000 && 水泵未变化时水厂压力变化是否正常(doubles, int.Parse( dr["开关量维度值"].ToString())))
|
{
|
points.Add(new PointF3D(doubles[0], doubles[1], doubles[2], dt.Rows.Count));
|
if (Inputfiles.Count != 0)
|
{
|
dr["接口文件"] = Inputfiles[i];
|
dr["结果文件"] = files[i];
|
}
|
dt.Rows.Add(dr);
|
}
|
}
|
catch
|
{
|
continue;
|
}
|
}
|
dt.Columns.Add("标记");
|
if (Inputfiles.Count != 0)
|
{
|
dt.Columns["结果文件"].SetOrdinal(dt.Columns.Count - 1);
|
dt.Columns["接口文件"].SetOrdinal(dt.Columns.Count - 1);
|
|
}
|
|
|
if (points.Count <= 0) return new DataTable();
|
var filterpoints = points;
|
|
filterpoints = calcFilterPointsBySets(filterpoints, 1);
|
|
//filterpoints = filterByScoal(filterpoints);
|
for (int i = 0; i < filter_times; i++)
|
filterpoints = calcFilterPoints(filterpoints, junfangK);
|
|
var minP = calcMinPoint(filterpoints);
|
|
for (int i = 0; i < dt.Rows.Count; i++)
|
{
|
dt.Rows[i]["标记"] = "×";
|
}
|
|
foreach (var p in filterpoints)
|
{
|
dt.Rows[p.rowIndex]["标记"] = "";
|
}
|
dt.Rows[minP.rowIndex]["标记"] = "√";
|
|
ValidNum=filterpoints.Count;
|
return dt;
|
}
|
static List<double> getScadaPumpStatusList(dict di)
|
{
|
List<double> doubles = new List<double>();
|
doubles.Add(di["凤凰水厂1#泵状态_SCADA"]);
|
doubles.Add(di["凤凰水厂2#泵状态_SCADA"]);
|
doubles.Add(di["凤凰水厂3#泵状态_SCADA"]);
|
doubles.Add(di["凤凰水厂4#泵状态_SCADA"]);
|
doubles.Add(di["凤凰水厂5#泵状态_SCADA"]);
|
doubles.Add(di["立新水厂1#泵状态_SCADA"]);
|
doubles.Add(di["立新水厂2#泵状态_SCADA"]);
|
doubles.Add(di["立新水厂3#泵状态_SCADA"]);
|
doubles.Add(di["立新水厂4#泵状态_SCADA"]);
|
doubles.Add(di["立新水厂5#泵状态_SCADA"]);
|
return doubles;
|
}
|
static bool 水泵未变化时水厂压力变化是否正常(double[] doubles,int 开关量)
|
{
|
if (开关量 != 0) return true;
|
var 立新变化= doubles[0] - doubles[3];
|
var 凤凰变化 = doubles[1] - doubles[4];
|
|
if (立新变化* 凤凰变化<0 && (Math.Abs(立新变化) *101.972 > 1.2 || Math.Abs(凤凰变化) *101.972 > 1.2)) return false;
|
return true;
|
}
|
static DateTime getTimeByFileName(string filename)
|
{
|
if (File.Exists(filename))
|
filename = new FileInfo(filename).Name;
|
string format = "yyyy'年'MM'月'dd'日'HH'时'mm'分'";
|
DateTime time = default(DateTime);
|
DateTime.TryParseExact(filename.Split('_')[2], format, null, System.Globalization.DateTimeStyles.None, out time);
|
return time;
|
}
|
public static WdnmoParam GetWdnmoParam(DataView dv,int bestRowIndex)
|
{
|
int recentRowIndex = dv.Count - 1;
|
|
double num = (double)dv[bestRowIndex][3];
|
|
string path = dv[bestRowIndex]["接口文件"].ToString();
|
string json = File.ReadAllText(path);
|
try
|
{
|
var wp=JsonConvert.DeserializeObject<WdnmoParam>(json);
|
return wp;
|
}
|
catch { return null; }
|
}
|
static List<PointF3D> calcFilterPointsBySets(List<PointF3D> points, double maxDis)
|
{
|
// 计算每个点与其他所有点之间的距离和
|
List<List<PointF3D>> sets = new List<List<PointF3D>>();
|
foreach (var point in points)
|
{
|
bool flag = false;
|
foreach (var set in sets)
|
{
|
if (CalculateDistance(set[0], point) <= maxDis)
|
{
|
set.Add(point);
|
flag = true;
|
break;
|
}
|
}
|
if (!flag)
|
{
|
sets.Add(new List<PointF3D>() { point});
|
}
|
|
}
|
List<PointF3D> maxCountSet=new List<PointF3D>();
|
foreach(var set in sets)
|
{
|
if (maxCountSet.Count<=set.Count)
|
maxCountSet = set;
|
}
|
return maxCountSet;
|
//return ints;
|
}
|
static List<PointF3D> calcFilterPoints(List<PointF3D> points, double k)
|
{
|
// 计算每个点与其他所有点之间的距离和
|
List<double> distanceSums = new List<double>();
|
foreach (var point in points)
|
{
|
double distanceSum = 0;
|
foreach (var otherPoint in points)
|
{
|
if (point != otherPoint)
|
{
|
double distance = CalculateDistance(point, otherPoint);
|
distanceSum += distance;
|
}
|
}
|
distanceSums.Add(distanceSum);
|
}
|
|
// 计算平均值和标准差
|
double mean = distanceSums.Average();
|
double stdDev = CalculateStandardDeviation(distanceSums);
|
|
// 计算离群点的阈值
|
double threshold = mean + (k * stdDev);
|
|
// 剔除离群点
|
List<PointF3D> filteredPoints = new List<PointF3D>();
|
//List<int> ints = new List<int>();
|
for (int i = 0; i < points.Count; i++)
|
{
|
if (distanceSums[i] <= threshold)// ints.Add(i);
|
filteredPoints.Add(points[i]);
|
}
|
return filteredPoints;
|
//return ints;
|
}
|
static PointF3D calcMinPoint(List<PointF3D> points)
|
{
|
// 计算每个点与其他所有点之间的距离和
|
List<double> distanceSums = new List<double>();
|
foreach (var point in points)
|
{
|
double distanceSum = 0;
|
foreach (var otherPoint in points)
|
{
|
if (point != otherPoint)
|
{
|
double distance = CalculateDistance(point, otherPoint);
|
distanceSum += distance;
|
}
|
}
|
distanceSums.Add(distanceSum);
|
}
|
|
// 找到距离和最小的点的索引
|
int minDistanceIndex = distanceSums.LastIndexOf(distanceSums.Min());
|
|
// 获取距离和最小的点
|
PointF3D minDistancePoint = points[minDistanceIndex];
|
return minDistancePoint;
|
}
|
// 定义三维点类
|
|
|
// 计算两个点之间的欧氏距离
|
static double CalculateDistance(PointF3D point1, PointF3D point2)
|
{
|
double distance = Math.Sqrt(Math.Pow(point1.x - point2.x, 2) + Math.Pow(point1.y - point2.y, 2) + Math.Pow(point1.z - point2.z, 2));
|
return distance;
|
}
|
|
// 计算标准差
|
static double CalculateStandardDeviation(List<double> values)
|
{
|
double avg = values.Average();
|
double sumOfSquares = values.Sum(val => Math.Pow(val - avg, 2));
|
double stdDev = Math.Sqrt(sumOfSquares / values.Count);
|
return stdDev;
|
}
|
static string getOptString(double x)
|
{
|
if (x < 0) return "关闭";
|
else return "开启";
|
}
|
public static string getOrderTxt(DataView dv, int bestRowIndex)
|
{
|
if (bestRowIndex < 0) return null;
|
DataRowView row = dv[bestRowIndex];
|
int recentRowIndex = dv.Count - 1;
|
double num = (double)dv[bestRowIndex][3];
|
|
bool isChangePump = false;
|
if (num<-1000)
|
{
|
isChangePump = true;
|
}
|
string stateTxt = (num > 0) ? "开启" : "关闭";
|
int num1 = (int)Math.Abs(num);
|
int PumpNum = num1 / 100;
|
string facTxt = (PumpNum <= 5) ? "立新" : "凤凰";
|
int PumpNumShow = PumpNum > 5 ? PumpNum - 5 : PumpNum;
|
//string pumpChangeTxt = num == 0 ? "水泵开停不变" : $"{facTxt}{stateTxt}{PumpNumShow}#泵";
|
string pumpChangeTxt_lx = "";
|
string pumpChangeTxt_fh = "";
|
var time = DateTime.Now;
|
string PumpStateList_lx0 = "";
|
string PumpStateList_fh0 = "";
|
string PumpStateList_lx1 = "";
|
string PumpStateList_fh1 = "";
|
for (int i = 1; i <= 5; i++)
|
{
|
double d = 0;
|
if ((d = (double)dv[bestRowIndex][15 + i]) == 1) PumpStateList_lx0 += $"{i}#";
|
if ((d = (double)dv[bestRowIndex][20 + i]) == 1) PumpStateList_fh0 += $"{i}#";
|
if ((d = (double)dv[bestRowIndex][5 + i]) == 1) PumpStateList_lx1 += $"{i}#";
|
if ((d = (double)dv[bestRowIndex][10 + i]) == 1) PumpStateList_fh1 += $"{i}#";
|
if ((d=(double)dv[bestRowIndex][25 + i]) != 0) pumpChangeTxt_lx += $"{getOptString(d)}{i}#";
|
if ((d = (double)dv[bestRowIndex][30 + i]) != 0) pumpChangeTxt_fh += $"{getOptString(d)}{i}#";
|
}
|
if (pumpChangeTxt_lx != "") pumpChangeTxt_lx = "立新" + pumpChangeTxt_lx;
|
if (pumpChangeTxt_fh != "") pumpChangeTxt_fh = "凤凰" + pumpChangeTxt_fh;
|
//for (int i = 1; i <= 5; i++)
|
//{
|
// if ((double)dv[bestRowIndex][5 + i] == 1)
|
// {
|
// PumpStateList_lx1 += $"{i}#";
|
// if (i != PumpNum)
|
// {
|
// PumpStateList_lx0 += $"{i}#";
|
// }
|
// }
|
// else if (i == PumpNum)
|
// {
|
// PumpStateList_lx0 += $"{i}#";
|
// }
|
//}
|
|
//PumpNum = PumpNum - 5;
|
//for (int i = 1; i <= 5; i++)
|
//{
|
// if ((double)dv[bestRowIndex][10 + i] == 1)
|
// {
|
// PumpStateList_fh1 += $"{i}#";
|
// if (i != PumpNum)
|
// {
|
// PumpStateList_fh0 += $"{i}#";
|
// }
|
// }
|
// else if (i == PumpNum)
|
// {
|
// PumpStateList_fh0 += $"{i}#";
|
// }
|
//}
|
|
string txt = $@"{time:HH:mm}
|
方案内容:
|
当前运行方案:
|
立新:{PumpStateList_lx0} 出厂压力:{dv[recentRowIndex][4]:0.000}MPa 出厂流量:{dv[recentRowIndex][38]:0}m³/h
|
凤凰:{PumpStateList_fh0} 出厂压力:{dv[recentRowIndex][5]:0.000}MPa 出厂流量:{dv[recentRowIndex][39]:0}m³/h
|
推荐方案:
|
立新:{PumpStateList_lx1} 出厂压力:{dv[bestRowIndex][1]:0.000}MPa 出厂流量:{dv[recentRowIndex][36]:0}m³/h
|
凤凰:{PumpStateList_fh1} 出厂压力:{dv[bestRowIndex][2]:0.000}MPa 出厂流量:{dv[recentRowIndex][37]:0}m³/h
|
{pumpChangeTxt_lx}{pumpChangeTxt_fh}
|
";
|
txt = txt.Trim('\n').Trim(' ');
|
return txt;
|
}
|
|
public static string SendOrder(string txt)
|
{
|
|
//string url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=ad1996dd-37ac-4476-9f97-30616382593e";
|
string param = JsonConvert.SerializeObject(new
|
{
|
msgtype = "text",
|
text = new
|
{
|
content = txt
|
}
|
});
|
if (url == null) return "url is null";
|
foreach(var url0 in url.Split(';'))
|
{
|
using (HttpClient client = new HttpClient())
|
{
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
HttpContent content = new StringContent(param, Encoding.UTF8, "application/json");
|
|
HttpResponseMessage response = client.PostAsync(url0, content).Result;
|
|
if (!response.IsSuccessStatusCode)
|
{
|
// 发送失败
|
return response.ReasonPhrase;
|
}
|
}
|
}
|
// 发送成功
|
return null;
|
|
|
}
|
}
|
class PointF3D
|
{
|
public double x;
|
public double y;
|
public double z;
|
|
public PointF3D(double x, double y, double z, int rowIndex)
|
{
|
this.x = x;
|
this.y = y;
|
this.z = z;
|
this.rowIndex = rowIndex;
|
}
|
public int rowIndex = 0;
|
}
|
}
|