cloudflight
2024-07-06 6fc98fca9a6e5883cdeaf5051cfdae5a101b5a43
[结构]删除不必要部分
已修改2个文件
630 ■■■■■ 文件已修改
Hydraulic/Hydro.CommonBase/Helper/SolutionSelector.cs 518 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Hydraulic/Hydro.HydraulicHelper/controller/ParrelController_Search.cs 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Hydraulic/Hydro.CommonBase/Helper/SolutionSelector.cs
@@ -24,525 +24,17 @@
        }
        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<string,double> dict = new dict<string, double>();
                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<string, double> dict = new dict<string, double>();
                    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;
            return null;
        }
        static List<double> getScadaPumpStatusList(dict<string,double> 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;
            string txt = $@"{time:HH:mm}
方案内容:
    当前运行方案:
立新:{PumpStateList_lx0} 出厂压力:{dv[recentRowIndex][4]:0.000}MPa
凤凰:{PumpStateList_fh0} 出厂压力:{dv[recentRowIndex][5]:0.000}MPa
    推荐方案:
立新:{PumpStateList_lx1} 出厂压力:{dv[bestRowIndex][1]:0.000}MPa
凤凰:{PumpStateList_fh1} 出厂压力:{dv[bestRowIndex][2]:0.000}MPa
{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
    {
Hydraulic/Hydro.HydraulicHelper/controller/ParrelController_Search.cs
@@ -501,94 +501,7 @@
                    {
                        if (gParam.isNeedOutput)
                        {
                            if (gParam.GlobalConfig.Ext.方案择优)
                            {
                                var host = param.dict_Name.Get("方案择优");
                                int validNum = 0;
                                var dt = SolutionSelector.GetBestSolutionDict(false, host.expressString, host.ID, out validNum, wParam.time);
                                if (dt != null)
                                {
                                    var dv = dt.DefaultView;
                                    dv.Sort = "时间 asc";
                                    int recentRowIndex = dv.Count - 1;
                                    int bestRowIndex = 0;
                                    for (int i = 0; i < dv.Count; i++)
                                    {
                                        if (dv[i]["标记"].ToString() == "√")
                                        {
                                            bestRowIndex = i;
                                            break;
                                        }
                                    }
                                    if (gParam.GlobalConfig.Ext.自动发送指令)
                                    {
                                        var txt = SolutionSelector.getOrderTxt(dv, bestRowIndex);
                                        bool isActPump = (txt.IndexOf("开启") >= 0 || txt.IndexOf("关闭") >= 0);
                                        //wdnmoParam.OrderTxt = txt;
                                        if (isActPump && validNum < 3) txt = "(该指令有效样本数不足,不发送)\r\n" + txt;
                                        SolutionSelector.url = gParam.GlobalConfig.Ext.OrderUrl;
                                        SolutionSelector.SendOrder(txt);
                                        if (isActPump && validNum >= 3)
                                        {
                                            SolutionSelector.url = gParam.GlobalConfig.Ext.AlarmUrl;
                                            SolutionSelector.SendOrder(txt);
                                        }
                                        Log.Add("==============微信============\r\n" + txt, "推送日志");
                                    }
                                    DataRowView bestrow = dv[bestRowIndex];
                                    bool NoSendFlag = (validNum < 2 || bestrow["开关量维度值"].ToString() != "0" && validNum < 3);
                                    if (NoSendFlag)
                                    {
                                        WdnmoParam wdnmoParam = null;
                                        gParam.onFinished(wdnmoParam);
                                    }
                                    else
                                    {
                                        WdnmoParam wdnmoParam = SolutionSelector.GetWdnmoParam(dv, bestRowIndex);
                                        if (wdnmoParam != null)
                                        {
                                            //wdnmoParam.RunTimes = HydraulicHelper.times;
                                            double v1 = wdnmoParam.ResultPoints.Find(v => v.Name == "立新出厂压力_方案").Value / 101.972;
                                            double v2 = wdnmoParam.ResultPoints.Find(v => v.Name == "凤凰出厂压力_方案").Value / 101.972;
                                            Log.Add($"==============入库============\r\n立新:{v1}\t凤凰:{v2}", "推送日志");
                                            if (gParam.GlobalConfig.Ext.显示详细日志)
                                                Log.Output();
                                            string lastSelectPath = GlobalPath.resultPath + "lastSelect.ini";
                                            string path1 = dv[bestRowIndex]["结果文件"].ToString();
                                            string path2 = dv[bestRowIndex]["接口文件"].ToString();
                                            try
                                            {
                                                File.WriteAllText(lastSelectPath, path1 + "\r\n" + path2);
                                            }
                                            catch { }
                                            gParam.onFinished(wdnmoParam);
                                        }
                                        else
                                        {
                                            finish();
                                        }
                                    }
                                }
                                else
                                {
                                    finish();
                                }
                            }
                            else
                            {
                                finish();
                            }
                            gParam.onFinished(wParam);
                        }
                        else
                            gParam.onFinished(bestValue);
@@ -599,33 +512,12 @@
                    gParam.onFinished(param);
                }
            }
            void finish()
            {
                //wParam.RunTimes = HydraulicHelper.times;
                gParam.onFinished(wParam);
            }
        }
        private ISelectionMethod GetSelectionMethod()
        {
            ISelectionMethod selectionMethod;
            //if (gParam.selectionMethod != 0)
            //{
            //    if (gParam.selectionMethod != 1)
            //    {
            //        selectionMethod = new RouletteWheelSelection();
            //    }
            //    else
            //    {
            //        selectionMethod = new RankSelection();
            //    }
            //}
            //else
            //{
            //    selectionMethod = new EliteSelection() { SelectMode = gParam.optimizationMode == 1 };
            //}
            return new EliteSelection() { SelectMode = gParam.optimizationMode == 1 };
        }