tangxu
2025-02-07 03a0d99de9c5fed6bea8bc83b49ce27786bda38c
WebApi/Controllers/ZyPrjController.cs
@@ -16,8 +16,6 @@
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
namespace IStation.ZyDto
{
@@ -28,14 +26,16 @@
        public string StartTime { get; set; }
        public string EndTime { get; set; }
        public int? StartOpenCount { get; set; } = -1;
        //public int? StartOpenCount { get; set; } = -1;//已作废
        public string StartReservoirLevel { get; set; }//开始水库水位(可空):单位m
        public string StartOpenPumpIndexArray { get; set; }//开始机泵开机状态(不可空)
        public string TotalFlowIn { get; set; }//取水总量 (单位 吨)
        public string StartReservoirLevel { get; set; }//开始水库水位(可空):单位m
        public string TotalFlowOut { get; set; }//供水总量 (单位 吨) 不输入就用预测值
        public string MaxReservoirLevel { get; set; }//最高水库水位限制(可空):单位m
        public string MaxReservoirLevelTime { get; set; }//最高水库水位限制时间(可空) 时间格式
        public string IsSubmit { get; set; }//计算完,是否推送
    }
}
@@ -48,7 +48,7 @@
    public class ZyPrjController : ApiController
    {
        /// <summary>
        ///
        ///  计算
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
@@ -56,7 +56,6 @@
        [HttpPost]
        public IStation.Dto.ApiResult Calc([FromBody] ZyPrjRequest request)
        {
            LogHelper.Info(JsonHelper.Object2Json(request));
            if (request == null)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "request is null" };
@@ -69,6 +68,9 @@
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "EndTime is null" };
            }
            //
            IStation.LogHelper.Info("--------------------------START-----------------------------------------");
            IStation.LogHelper.Info(string.Format("Zy Prj Calc Request:  {0}", JsonHelper.Object2Json(request)));
            DateTime start_timme = DateTime.Now;
            DateTime end_timme = DateTime.Now;
@@ -92,30 +94,24 @@
                IStation.LogHelper.Error(string.Format("ZyPrjRequest Time:{0}-{1} 时间范围错误,不能超过24小时", start_timme, end_timme));
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "时间范围错误,不能超过24小时" };
            }
            IStation.CalcModel.AnaRequest anaRequest = new AnaRequest();
            anaRequest.CalcOptType = (eCalcOptType)IStation.AnaGlobalParas.Setting.OptSortType;
            anaRequest.StartTime = start_timme;
            anaRequest.EndTime = end_timme;
            anaRequest.WaterLevels长江 = GetTide3Day(start_timme);
            if (string.IsNullOrEmpty(request.TotalFlowIn))
            {
                if (string.IsNullOrEmpty(request.MaxReservoirLevel))
                {
                    IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  请输入取水总量或水位要求",
                start_timme, end_timme));
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入取水总量或水位要求" };
                }
            anaRequest.WaterLevels长江 = GetTide3Day(_tideSouce, start_timme);
            if(anaRequest.WaterLevels长江 ==null || anaRequest.WaterLevels长江.Count()==0)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "无法获取长江水位数据" };
            }
            else
            {
                double TotalFlowIn = 0;
            #region 取水总量
            double TotalFlowIn = 0;
            if (!string.IsNullOrEmpty(request.TotalFlowIn) && !string.IsNullOrWhiteSpace(request.TotalFlowIn))
            {
                if (!double.TryParse(request.TotalFlowIn, out TotalFlowIn))
                {
                    IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  注意取水总量单位是吨,当前参数参数过小",
                start_timme, end_timme));
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "注意取水总量单位是吨,当前参数参数过小" };
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入数字型取水总量,接受到的输入值是:" + request.TotalFlowIn };
                }
                if (TotalFlowIn < 10000)
                {
@@ -126,12 +122,57 @@
                anaRequest.TotalFlowIn = TotalFlowIn;
            }
            if (!string.IsNullOrEmpty(request.MaxReservoirLevel))
            #endregion 取水总量
            #region 水位要求
            if (!string.IsNullOrEmpty(request.MaxReservoirLevelTime))
            {
                anaRequest.MaxLimitWaterBoxLevel = Convert.ToDouble(request.MaxReservoirLevel);
                anaRequest.MaxReservoirLevelTime = request.MaxReservoirLevelTime;
            }
            if (!string.IsNullOrEmpty(request.MaxReservoirLevel) && !string.IsNullOrWhiteSpace(request.MaxReservoirLevel))
            {
                double MaxReservoirLevel = 0;
                if (!double.TryParse(request.MaxReservoirLevel, out MaxReservoirLevel))
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入合理的水位要求值" };
                }
                if (MaxReservoirLevel < 1 || MaxReservoirLevel > 10)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入合理的水位要求值" };
                }
                anaRequest.MaxReservoirLevel = MaxReservoirLevel;
            }
            else
            {
                if (string.IsNullOrEmpty(request.TotalFlowIn) || string.IsNullOrWhiteSpace(request.TotalFlowIn))
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入取水总量或水位要求" };
                }
                if (TotalFlowIn < 1000)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "请输入取水总量,接受到的输入值是:" + request.TotalFlowIn };
                }
            }
            #endregion 水位要求
            #region 供水量
            double TotalFlowOut手动输入需求 = 0;//预测值的供水总量(单位 吨)
            double TotalFlowOut预测值的供水总量 = 0;//预测值的供水总量 (单位 吨)
            double FlowTotalOut需求 = 0;
            bool isPredictRecord = false; //是否是用到水量预测
            if (string.IsNullOrEmpty(request.TotalFlowOut) || string.IsNullOrWhiteSpace(request.TotalFlowOut))
            {//用预测值
                #region 用预测值
                anaRequest.PerHourFlowOut = new List<double>();
                IStation.DAL.WaterPredictRecord dal = new DAL.WaterPredictRecord();
                var water_records = dal.GetByHourRangle(start_timme, end_timme);
                LogHelper.Info(water_records.Count.ToString());
                //LogHelper.Info(water_records.Count.ToString());
                if (water_records == null)
                {
                    IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  水位预测数据为空,请先保持水位预测服务正常运行",
@@ -146,7 +187,6 @@
                    return new IStation.Dto.ApiResult<string>() { Code = ApiResultCode.Error, Data = "预测数据获取失败,数据条无法匹配, 检查是否预测服务中断" };
                }
                anaRequest.SpaceFlowOut = new List<double>();
                foreach (var r in water_records)
                {
                    if (r.States == 0)
@@ -160,110 +200,224 @@
                            Data = error_info11
                        };
                    }
                    anaRequest.SpaceFlowOut.Add(r.LastPredictValue / 10000);
                    TotalFlowOut预测值的供水总量 += r.LastPredictValue;
                    anaRequest.PerHourFlowOut.Add(r.LastPredictValue);//计算中用吨
                }
            }
            if (!string.IsNullOrEmpty(request.MaxReservoirLevelTime))
                anaRequest.MaxLimitWaterBoxTime = request.MaxReservoirLevelTime;
            //
            if (request.StartOpenCount == null)
            {
                anaRequest.StartOpenCount = -1;
                IStation.LogHelper.Info(
                    string.Format("获取水量预测值:  {0} ,  预测值总供水总量:{1} ",
                    string.Join(",", anaRequest.PerHourFlowOut), TotalFlowOut预测值的供水总量));
                FlowTotalOut需求 = TotalFlowOut预测值的供水总量;
                isPredictRecord = true ;
                #endregion 用预测值
            }
            else
            {
                anaRequest.StartOpenCount = request.StartOpenCount.Value;
                if (!double.TryParse(request.TotalFlowOut, out TotalFlowOut手动输入需求))
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "注意供水总量输入参数无法识别,参数是:" + request.TotalFlowOut };
                }
                if (TotalFlowOut手动输入需求 < 10000)
                {
                    IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  注意取水总量单位是吨,当前参数参数过小",
                start_timme, end_timme));
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "注意供水总量单位是吨,当前参数参数过小" };
                }
                //TotalFlowOut = TotalFlowOut / 10000;//计算中用吨
                List<double> list = new List<double>();
                var count = (end_timme - start_timme).TotalHours;
                for (var d = start_timme; d <= end_timme; d = d.AddHours(1))
                {
                    list.Add(Math.Round(TotalFlowOut手动输入需求 / count, 1));
                }
                anaRequest.PerHourFlowOut = list;
                FlowTotalOut需求 = TotalFlowOut手动输入需求;
                isPredictRecord = false ;
            }
            #endregion 供水量
            //开始时的开机状态
            List<int> StartOpenPumpIndexArray = new List<int>();
            if (!string.IsNullOrEmpty(request.StartOpenPumpIndexArray))
            {
                var sss = request.StartOpenPumpIndexArray.Split(',');
                foreach (var item in sss)
                {
                    if (int.TryParse(item, out int index))
                    {
                        if (index < 0 || index > 4)
                        {
                            return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "开始时的开机状态,机泵角标要求不超过4" };
                        }
                        StartOpenPumpIndexArray.Add(index);
                    }
                    else
                    {
                        return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "开始时的开机状态,参数不正确" };
                    }
                }
            }
            anaRequest.IsKnownStartOpenPump = true;
            anaRequest.StartOpenPumpIndexArray = StartOpenPumpIndexArray;
            //陈行水库水位
            if (!string.IsNullOrEmpty(request.StartReservoirLevel))
            if (string.IsNullOrEmpty(request.StartReservoirLevel))
            {
                anaRequest.CurrentWaterBoxLevel = Convert.ToDouble(request.StartReservoirLevel);
                IStation.LogHelper.Info(" 未设置开始时水库水位 (Error: StartReservoirLevel is null)");
                return new IStation.Dto.ApiResult<string>() { Code = ApiResultCode.Error, Data = "未设置开始时水库水位 (Error: StartReservoirLevel is null) " };
            }
            else
            anaRequest.StartReservoirLevel = Convert.ToDouble(request.StartReservoirLevel);
            if (anaRequest.StartReservoirLevel < 2)
            {
                anaRequest.CurrentWaterBoxLevel = ZyConnectHelper.GetRealReservoirWaterLevel();
                IStation.LogHelper.Info(string.Format("  设置开始时水库水位的数据过小 (Error: StartReservoirLevel is {0}})",
                    anaRequest.StartReservoirLevel));
                return new IStation.Dto.ApiResult<string>()
                {
                    Code = ApiResultCode.Error,
                    Data = string.Format("  设置开始时水库水位的数据过小 (Error: StartReservoirLevel is {0}})",
                    anaRequest.StartReservoirLevel)
                };
            }
            IStation.LogHelper.Info("kashi 计算取水总量 ");
            var calcHelper = new IStation.CalcPrjHelper();
            AnaPrj defaultPrj = null;
            string error_info = calcHelper.Calc(anaRequest, out defaultPrj);
            LogHelper.Info(error_info);
            if (!string.IsNullOrEmpty(error_info) || defaultPrj == null)
            {
                IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  计算错误, 原因是:{2} ,Request:::  ",
                start_timme, end_timme, error_info) + JsonHelper.Object2Json(anaRequest));
                IStation.LogHelper.Info(string.Format("Zy Prj  计算错误:  \r\n {0}  ", error_info));
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "计算错误, 原因是:" + error_info };
            }
            else
            {
                IStation.LogHelper.Info(string.Format("Zy Prj  Time:{0}-{1} ,  计算成功", start_timme, end_timme));
                //  IStation.LogHelper.Info(string.Format("Zy Prj  计算成功:  \r\n {0}  ",  JsonHelper.Object2Json(defaultPrj)));
            }
            IStation.LogHelper.Info("-----------------------------END--------------------------------------");
            //保存方案
            var ret = Common.HistoryAnaPrjFileHelper.SavePrj(IStation.AnaGlobalParas.Setting, anaRequest, defaultPrj);
            //保存方案
            var ret = Common.HistoryAnaPrjFileHelper.SavePrj(IStation.AnaGlobalParas.Setting, isPredictRecord, anaRequest, defaultPrj);
            //
            var dto_prj = ToPrjDto(defaultPrj);
            dto_prj.FlowTotalOut = FlowTotalOut需求;
            #region 推送
            if (!string.IsNullOrEmpty(request.IsSubmit) && Convert.ToBoolean(request.IsSubmit))
            {
                Task.Run(() =>
                {
                    _ = ZyProjectHelper.SubmitPrj(defaultPrj);
                });
            }
            //推送:代码保留
            //if (!string.IsNullOrEmpty(request.IsSubmit) && Convert.ToBoolean(request.IsSubmit))
            //{
            //    Task.Run(() =>
            //    {
            //        _ = ZyProjectHelper.SubmitPrj(defaultPrj);
            //    });
            //}
            #endregion 推送
            //IStation.LogHelper.Info(string.Format(" 产生计算方案:{0}", dto_prj.schemeID));
            //IStation.LogHelper.Info(string.Format("Zy Prj  计算成功:  \r\n {0}  ", JsonHelper.Object2Json(dto_prj)));
            return new IStation.Dto.ApiResult<IStation.ZyDto.SubmitPrj>(dto_prj) { Code = ApiResultCode.Success };
        }
        #region 换算成DTO
        private IStation.ZyDto.SubmitPrj ToPrjDto(AnaPrj defaultPrj)
        /// <summary>
        /// 获取初始水位,和当时的开机状态
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("GetAnaStartPara")]
        [HttpGet]
        public IStation.Dto.ApiResult GetAnaStartPara(string AnaStartTime)
        {
            IStation.ZyDto.SubmitPrj dto_prj = new ZyDto.SubmitPrj();
            if (string.IsNullOrEmpty(AnaStartTime)) { return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "day 格式不正确" }; }
            if (string.IsNullOrEmpty(defaultPrj.ID))
            try
            {
                var time = DateTime.Now;
                defaultPrj.ID = $"{time.Year}{time.Month}{time.Day}{time.Hour}{time.Minute}{time.Second}";
            }
            dto_prj.schemeID = defaultPrj.ID;
            dto_prj.Day = defaultPrj.StartTime.ToString("yyyy-MM-dd");
            dto_prj.StartTime = defaultPrj.StartTime.ToString("yyyy-MM-dd HH:mm:ss");
            dto_prj.EndTime = defaultPrj.EndTime.ToString("yyyy-MM-dd HH:mm:ss");
            dto_prj.FlowTotal = Math.Round(defaultPrj.SumFlow, 0);
            dto_prj.PowerTotal = Math.Round(defaultPrj.SumPower, 0);
            dto_prj.MoneyTotal = Math.Round(defaultPrj.SumMoney, 0);
            dto_prj.Items = new List<ZyDto.SubmitPrjItem>();
            foreach (var bt in defaultPrj.BlockTimes)
            {
                if (bt.OpenPumpCount == 0)
                    continue;
                ZyDto.SubmitPrjItem dto_item = new ZyDto.SubmitPrjItem();
                dto_item.StartTime = bt.StartTime;
                dto_item.EndTime = bt.EndTime;
                dto_item.OpenPumpCount = bt.OpenPumpCount;
                dto_item.OpenPumpIndexs = IStation.AnaGlobalParas.Setting.GetOpenPumpIndexArrays(bt.OpenPumpCount);
                dto_prj.Items.Add(dto_item);
            }
            if (defaultPrj.PointTimes != null)
            {
                dto_prj.Records = new List<SubmitPrjTime>();
                foreach (var bt in defaultPrj.PointTimes)
                DateTime last_end_time;
                if (!DateTime.TryParse(AnaStartTime, out last_end_time))
                {
                    dto_prj.Records.Add(new SubmitPrjTime(bt));
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "day 格式不正确" };
                }
                IStation.CalcModel.AnaRequestBase requestBase;
                var prj = Common.HistoryAnaPrjFileHelper.GetByEndTime大于(last_end_time, out requestBase);
                if (prj == null)
                {
                    IStation.LogHelper.Info(string.Format("GetAnaStartPara 未找到{0}结束的分析项目", AnaStartTime));
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = string.Format("未找到{0}结束的分析项目", AnaStartTime) };
                }
                IStation.CalcModel.ZyStartInfo zyStartInfo = new IStation.CalcModel.ZyStartInfo();
                //zyStartInfo.OpenPumpStatus = prj.EndTimeOpenPumpStatus;
                if (prj.EndTimeOpenPumpStatus != null && prj.EndTimeOpenPumpStatus.Count > 0)
                {
                    zyStartInfo.OpenPumpStatus = string.Join(",", prj.EndTimeOpenPumpStatus);
                }
                var near_pt = prj.NearPointTime(DateTime.Now);
                if (near_pt == null)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = string.Format("在项目中, 未找到{0}的水库水位数据", DateTime.Now) };
                }
                var new_yuce = near_pt.WaterLevelH;//昨天预测水位
                double now_level = ZyConnectHelper.GetRealReservoirWaterLevel();//实时水位
                if (prj.BlockTimes == null || prj.BlockTimes.Count() == 0)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "在项目中, BlockTimes值为空" };
                }
                if (prj.BlockTimes.Last().PointTimes == null || prj.BlockTimes.Last().PointTimes.Count() == 0)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "在项目中, 最后一个 BlockTime的 PointTimes 属性值为空" };
                }
                var lz = prj.BlockTimes.Last().PointTimes.Last().WaterLevelH;
                var lz_pt = prj.FindPointTime(last_end_time);
                if (lz_pt != null)
                {
                    lz = lz_pt.WaterLevelH;
                }
                double start_yuce = lz + now_level - new_yuce;
                IStation.LogHelper.Info(string.Format("GetAnaStartPara StartTime {0}    Level: {1},{2},{3} ,{4}  ", AnaStartTime, lz, now_level, new_yuce, start_yuce));
                zyStartInfo.ReservoirWaterLevel = Math.Round(start_yuce, 3);
                return new IStation.Dto.ApiResult<IStation.CalcModel.ZyStartInfo>(zyStartInfo) { Code = ApiResultCode.Success };
            }
            return dto_prj;
            catch (Exception ex)
            {
                IStation.LogHelper.Error("GetAnaStartPara line 277", ex);
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = string.Format("在项目中, 接口报错: {0} ", ex.Message) };
            }
        }
        #endregion 换算成DTO
        /// <summary>
        /// 确认调度方案
        /// </summary>
        /// <param name="ana"></param>
        /// <returns></returns>
        [Route("ConfirmSchemeByID")]
        [HttpPost]
        public IStation.Dto.ApiResult ConfirmSchemeByID(string ID)
        {
            if (string.IsNullOrEmpty(ID) || ID == "string")
            {
                return new IStation.Dto.ApiResult<bool>(false);
            }
            var dal = new IStation.DAL.AnaProject();
            var info = dal.SetConfirmStatusByID(ID);
            if (string.IsNullOrEmpty(info))
                return new IStation.Dto.ApiResult<bool>(true);
            else
            {
                IStation.LogHelper.Info(string.Format(" ConfirmSchemeByID error ID:{0}, reason:{1}", ID, info));
                return new IStation.Dto.ApiResult<bool>(false);
            }
        }
        /// <summary>
        ///  获取某一天,最近一条
@@ -283,22 +437,42 @@
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "day 格式不正确" };
            }
            IStation.CalcModel.AnaRequestBase requestBase = null;
            var prj = Common.HistoryAnaPrjFileHelper.GetByDay(d, out requestBase);
            IStation.CalcModel.AnaRequestBase requestBase = null;
            var prj = Common.HistoryAnaPrjFileHelper.GetByCreateDay(d, out requestBase);
            if (prj != null)
            {
                //IStation.LogHelper.Info(string.Format(" api GetHistoryByDay {0}    format: {1}  OK", day, d));
                var dto_prj = ToPrjDto(prj);
                if (requestBase != null && requestBase.PerHourFlowOut != null)
                {
                    var sumFlow = (from x in requestBase.PerHourFlowOut select x).Sum();
                    dto_prj.FlowTotalOut = sumFlow;
                }
                if(dto_prj.Switchs != null)
                {
                    var switch2 = from x in dto_prj.Switchs orderby x.Time select x;
                    int index = 1;
                    foreach (var sw in switch2)
                    {
                        sw.Index = index;
                        index++;
                    }
                    dto_prj.Switchs = switch2.ToList();
                }
                return new IStation.Dto.ApiResult<IStation.ZyDto.SubmitPrj>(dto_prj) { Code = ApiResultCode.Success };
            }
            else
            {
                IStation.LogHelper.Info(string.Format(" api GetHistoryByDay {0}    format: {1} (未找到项目) ", day, d));
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Alert, Message = "未找到项目" };
            }
        }
        /// <summary>
        ///  获取最近一条
        ///  获取最近一条(确认的)
        /// </summary>
        /// <param name="day"></param>
        /// <returns></returns>
@@ -307,22 +481,96 @@
        public IStation.Dto.ApiResult GetLastHistoryRecord()
        {
            var dal = new IStation.DAL.AnaProject();
            var record = dal.GetLastRecord();
            var record = dal.GetLastConfirmRecord();
            if (record == null)
            {
                IStation.LogHelper.Info(" api GetLastHistoryRecord is null ");
                return null;
            }
            IStation.CalcModel.AnaRequestBase requestBase = null;
            var prj = Common.HistoryAnaPrjFileHelper.GetByStartTime(record.StartTime, out requestBase);
            if (prj != null)
            {
            {
                var dto_prj = ToPrjDto(prj);
                if (requestBase != null && requestBase.PerHourFlowOut != null)
                {
                    var sumFlow = (from x in requestBase.PerHourFlowOut select x).Sum();
                    dto_prj.FlowTotalOut = sumFlow;
                }
                if (dto_prj.Switchs != null)
                {
                    var switch2 = from x in dto_prj.Switchs orderby x.Time select x;
                    int index = 1;
                    foreach (var sw in switch2)
                    {
                        sw.Index = index;
                        index++;
                    }
                    dto_prj.Switchs = switch2.ToList();
                }
                return new IStation.Dto.ApiResult<IStation.ZyDto.SubmitPrj>(dto_prj) { Code = ApiResultCode.Success };
            }
            else
            {
                IStation.LogHelper.Info(string.Format(
                    " api GetLastHistoryRecord is null (未找到项目) LastRecord 信息: ID:{0}, StartTime:{1}, EndTime:{2}",
                    record.ID,
                    record.StartTime, record.EndTime));
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Alert, Message = "未找到项目" };
            }
        }
        /// <summary>
        ///  获取最近一条(新建)
        /// </summary>
        /// <param name="day"></param>
        /// <returns></returns>
        [Route("GetLastCreateRecord")]
        [HttpGet]
        public IStation.Dto.ApiResult GetLastCreateRecord()
        {
            var dal = new IStation.DAL.AnaProject();
            var record = dal.GetLastRecord();
            if (record == null)
            {
                IStation.LogHelper.Info(" api GetLastHistoryRecord is null ");
                return null;
            }
            IStation.CalcModel.AnaRequestBase requestBase = null;
            var prj = Common.HistoryAnaPrjFileHelper.GetByStartTime(record.StartTime, out requestBase);
            if (prj != null)
            {
                var dto_prj = ToPrjDto(prj);
                if (requestBase != null && requestBase.PerHourFlowOut != null )
                {
                    var sumFlow = (from x in requestBase.PerHourFlowOut select x).Sum();
                    dto_prj.FlowTotalOut = sumFlow;
                }
                if (dto_prj.Switchs != null)
                {
                    var switch2 = from x in dto_prj.Switchs orderby x.Time select x;
                    int index = 1;
                    foreach (var sw in switch2)
                    {
                        sw.Index = index;
                        index++;
                    }
                    dto_prj.Switchs = switch2.ToList();
                }
                return new IStation.Dto.ApiResult<IStation.ZyDto.SubmitPrj>(dto_prj) { Code = ApiResultCode.Success };
            }
            else
            {
                IStation.LogHelper.Info(string.Format(
                    " api GetLastHistoryRecord is null (未找到项目) GetLastCreateRecord 信息: ID:{0}, StartTime:{1}, EndTime:{2}",
                    record.ID,
                    record.StartTime, record.EndTime));
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Alert, Message = "未找到项目" };
            }
        }
        /// <summary>
        ///
@@ -336,9 +584,42 @@
            IStation.Dto.ZyPrjAnaSetting dto_setting = new ZyPrjAnaSetting();
            dto_setting.MinOpenTimeMinute = model_setting.MinOpenTimeMinute;
            dto_setting.MinSwitchTimeMinute = model_setting.MinSwitchTimeMinute;
            dto_setting.MaxPumpSwitchCount = model_setting.MaxPumpSwitchCountQ;
            dto_setting.MaxPumpSwitchCount = model_setting.MaxPumpSwitchCount;
            dto_setting.OptSortType = model_setting.OptSortType;
            dto_setting.OpenPumpIndexs = model_setting.OpenPumpIndexs;
            dto_setting.SwitchPumpMinuteSpace = model_setting.SwitchPumpMinuteSpace;
            dto_setting.OpenPumpIndexSequence = IStation.Dto.ZyPrjAnaSetting.ListToString(model_setting.OpenPumpIndexSequence);
            dto_setting.ClosePumpIndexSequence = IStation.Dto.ZyPrjAnaSetting.ListToString(model_setting.ClosePumpIndexSequence);
            dto_setting.OptimalPumpIndexSequence = IStation.Dto.ZyPrjAnaSetting.ListToString(model_setting.OptimalPumpIndexSequence);
            //dto_setting.OpenPumpIndexSequence = BuildSequenceToDto(model_setting.OpenPumpIndexSequence);
            //dto_setting.ClosePumpIndexSequence = BuildSequenceToDto(model_setting.ClosePumpIndexSequence);
            //dto_setting.OptimalPumpIndexSequence = BuildSequenceToDto(model_setting.OptimalPumpIndexSequence);
            //检修泵的角标, 0 表示1号泵 1 表示二号泵 为空,表示没有检修
            try
            {
                var overhallStatus = ZyConnectHelper.GetOverhaulStatus();
                if (overhallStatus == null || overhallStatus.Count == 0)
                {
                    if (model_setting.UnablePumpIndexArray != null)
                    {
                        dto_setting.UnablePumpIndexArray = "";
                        model_setting.UnablePumpIndexArray = null;
                        IStation.Common.AnaSetting.SaveSetting(model_setting);
                    }
                }
                else
                {
                    model_setting.UnablePumpIndexArray = overhallStatus.ToArray();
                    dto_setting.UnablePumpIndexArray = string.Join(",", overhallStatus);
                    IStation.Common.AnaSetting.SaveSetting(model_setting);
                }
            }
            catch (Exception ex)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "无法链接工控服务器,错误原因:" + ex.Message };
            }
            if (model_setting.SwitchPumpIgnoreTimes != null)
            {
@@ -371,6 +652,8 @@
                }
            }
            IStation.LogHelper.Info("ZyPrj GetSetting : Content: " + JsonHelper.Object2Json(dto_setting));
            return new IStation.Dto.ApiResult<IStation.Dto.ZyPrjAnaSetting>(dto_setting);
        }
@@ -385,10 +668,12 @@
        {
            if (dto == null)
            {
                return new IStation.Dto.ApiResult<bool>(false);
                return new IStation.Dto.ApiResult<bool>(false) { Message = "入参为空" };
            }
            var model_setting = IStation.AnaGlobalParas.Setting;
            IStation.LogHelper.Info("ZyPrj SaveSetting");
            IStation.LogHelper.Info("ZyPrj SaveSetting : Content: " + JsonHelper.Object2Json(dto));
            if (dto.MinOpenTimeMinute < 5)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "最少开泵时间 设置过少" };
@@ -408,6 +693,11 @@
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "最少切泵时间 设置过长" };
            }
            model_setting.MinSwitchTimeMinute = dto.MinSwitchTimeMinute;
            if (dto.SwitchPumpMinuteSpace < 2 || dto.SwitchPumpMinuteSpace > 30)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "切换泵时间间隔 设置不合理" };
            }
            model_setting.SwitchPumpMinuteSpace = dto.SwitchPumpMinuteSpace;
            if (dto.MaxPumpSwitchCount < 1)
            {
@@ -417,7 +707,7 @@
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "最大切泵次数 设置过长" };
            }
            model_setting.MaxPumpSwitchCountQ = dto.MaxPumpSwitchCount;
            model_setting.MaxPumpSwitchCount = dto.MaxPumpSwitchCount;
            if (dto.OptSortType >= 2)
            {
                return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "OptSortType 只能设置 0 或者 1,  0代表 用电量最少  1代表 电费最少" };
@@ -511,32 +801,169 @@
                }
            }
            if (dto.OpenPumpIndexs != null)
            if (!string.IsNullOrEmpty(dto.OpenPumpIndexSequence))
            {
                List<int> penPumpIndexs = new List<int>();
                foreach (var ind in dto.OpenPumpIndexs)
                int[] new_set_sequence;
                var error = BuildSequenceFromDto(dto.OpenPumpIndexSequence, out new_set_sequence);
                if (!string.IsNullOrEmpty(error))
                {
                    if (ind < 0 || ind > 5)
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "开泵顺序 " + error };
                }
                model_setting.OpenPumpIndexSequence = new_set_sequence;
            }
            if (!string.IsNullOrEmpty(dto.ClosePumpIndexSequence))// if (dto.ClosePumpIndexSequence != null)
            {
                int[] new_set_sequence;
                var error = BuildSequenceFromDto(dto.ClosePumpIndexSequence, out new_set_sequence);
                if (!string.IsNullOrEmpty(error))
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "关泵顺序 " + error };
                }
                model_setting.ClosePumpIndexSequence = new_set_sequence;
            }
            if (!string.IsNullOrEmpty(dto.OptimalPumpIndexSequence))// if (dto.OptimalPumpIndexSequence != null)
            {
                int[] new_set_sequence;
                var error = BuildSequenceFromDto(dto.OptimalPumpIndexSequence, out new_set_sequence);
                if (!string.IsNullOrEmpty(error))
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "调度泵优先度顺序 " + error };
                }
                model_setting.OptimalPumpIndexSequence = new_set_sequence;
            }
            //检修状态, 直接读SCADA系统
            //if (dto.UnablePumpIndexArray != null && dto.UnablePumpIndexArray.Count()>0)
            //{
            //    if (dto.UnablePumpIndexArray.Count() > 2)
            //    {
            //        return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "检修泵数量不能超过2台 "  };
            //    }
            //    if (dto.UnablePumpIndexArray.Contains(5))
            //    {
            //        List<int> penPumpIndexs1 = new List<int>();
            //        foreach (var p in dto.UnablePumpIndexArray)
            //        {
            //            penPumpIndexs1.Add(p - 1);
            //        }
            //        model_setting.UnablePumpIndexArray = penPumpIndexs1.ToArray();
            //    }
            //    else
            //    {
            //        model_setting.UnablePumpIndexArray = dto.UnablePumpIndexArray;
            //    }
            //    model_setting.Check_Optimal_UnablePumpIndexArray();
            //}
            //else
            //{
            //    model_setting.UnablePumpIndexArray = null;
            //}
            return new IStation.Dto.ApiResult<bool>(IStation.Common.AnaSetting.SaveSetting(model_setting));
        }
        /// <summary>
        ///获取机泵检修状态
        /// </summary>
        /// <returns></returns>
        [Route("SynOverhaulStatus")]
        [HttpGet]
        public IStation.Dto.ApiResult SynOverhaulStatus()
        {
            var overhallStatus = ZyConnectHelper.GetOverhaulStatus();//检修泵的角标, 0 表示1号泵 1 表示二号泵 为空,表示没有检修
            return new IStation.Dto.ApiResult<List<int>>(overhallStatus);
        }
        private string BuildSequenceFromDto(string sequenceDto, out int[] sequenceDs)
        {
            sequenceDs = null;
            if (string.IsNullOrEmpty(sequenceDto))
                return null;
            List<int> list = new List<int>();
            if (!string.IsNullOrEmpty(sequenceDto))
            {
                var sss = sequenceDto.Split(',');
                foreach (var item in sss)
                {
                    if (int.TryParse(item, out int index))
                    {
                        return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "机泵开泵顺序设置参数不合理" };
                        list.Add(index);
                    }
                    else
                    {
                        penPumpIndexs.Add(ind);
                        return " 设置参数不合理,机泵序号有非数字";
                    }
                }
                if (penPumpIndexs.Distinct().Count() != 5)
                {
                    return new IStation.Dto.ApiResult() { Code = ApiResultCode.Error, Message = "机泵开泵顺序设置参数不合理" };
                }
                model_setting.OpenPumpIndexs = penPumpIndexs.ToArray();
            }
            return new IStation.Dto.ApiResult<bool>(IStation.Common.AnaSetting.SaveSetting(model_setting));
            return BuildSequenceFromDto(list, out sequenceDs);
        }
        private string BuildSequenceFromDto(List<int> sequenceDto, out int[] sequenceDs)
        {
            sequenceDs = null;
            if (sequenceDto == null || sequenceDto.Count() == 0)
                return null;
            List<int> penPumpIndexs = new List<int>();
            foreach (var ind in sequenceDto)
            {
                if (ind < 0)
                {
                    return " 设置参数不合理,机泵序号有负数";
                }
                else if (ind > 5)
                {
                    return " 设置参数不合理,机泵序号超过5";
                }
                else
                {
                    penPumpIndexs.Add(ind);
                }
            }
            if (penPumpIndexs.Distinct().Count() != 5)
            {
                return " 设置参数不合理";
            }
            if (penPumpIndexs.Contains(5))
            {//表示界面从1 2 3 4 5
                List<int> penPumpIndexs1 = new List<int>();
                foreach (var p in penPumpIndexs)
                {
                    penPumpIndexs1.Add(p - 1);
                }
                sequenceDs = penPumpIndexs1.ToArray();
            }
            else
            {
                sequenceDs = penPumpIndexs.ToArray();
            }
            return null;
        }
        private int[] BuildSequenceToDto(int[] sequenceDs)
        {
            if (sequenceDs == null || sequenceDs.Length == 0) return null;
            List<int> sequenceDto = new List<int>();
            foreach (var sequence in sequenceDs)
            {
                sequenceDto.Add(sequence + 1);
            }
            return sequenceDto.ToArray();
        }
        private Model.eTideSouce _tideSouce = Model.eTideSouce.Book;
        private List<Model.TimeWaterLevel> GetTide3Day(DateTime calc_day)
        public static List<Model.TimeWaterLevel> GetTide3Day(Model.eTideSouce tideSouce, DateTime calc_day)
        {
            DateTime _rangDay1, _rangDay2, _rangDay3;
            string error1, error2, error3;
@@ -559,9 +986,9 @@
                _rangDay2 = calc_day;
                _rangDay3 = calc_day.AddDays(1);
            }
            waterLevels长江1 = TideHelper.GetByDay(_tideSouce, _rangDay1, out error1);
            waterLevels长江2 = TideHelper.GetByDay(_tideSouce, _rangDay2, out error2);
            waterLevels长江3 = TideHelper.GetByDay(_tideSouce, _rangDay3, out error3);
            waterLevels长江1 = TideHelper.GetByDay(tideSouce, _rangDay1, out error1);
            waterLevels长江2 = TideHelper.GetByDay(tideSouce, _rangDay2, out error2);
            waterLevels长江3 = TideHelper.GetByDay(tideSouce, _rangDay3, out error3);
            List<Model.TimeWaterLevel> timeValues = new List<Model.TimeWaterLevel>();
            if (waterLevels长江1 != null)
@@ -581,5 +1008,127 @@
            return timeValues;
        }
        #region 换算成DTO
        private IStation.ZyDto.SubmitPrj ToPrjDto(AnaPrj defaultPrj)
        {
            IStation.ZyDto.SubmitPrj dto_prj = new ZyDto.SubmitPrj();
            if (string.IsNullOrEmpty(defaultPrj.ID))
            {
                var time = DateTime.Now;
                defaultPrj.ID = $"{time.Year}{time.Month}{time.Day}{time.Hour}{time.Minute}{time.Second}";
            }
            dto_prj.schemeID = defaultPrj.ID;
            dto_prj.schemeName = defaultPrj.Name;
            dto_prj.Day = defaultPrj.StartTime.ToString("yyyy-MM-dd");
            dto_prj.StartTime = defaultPrj.StartTime.ToString("yyyy-MM-dd HH:mm:ss");
            dto_prj.EndTime = defaultPrj.EndTime.ToString("yyyy-MM-dd HH:mm:ss");
            dto_prj.FlowTotalIn = Math.Round(defaultPrj.SumFlow, 0);
            dto_prj.FlowTotalOut = 0; //外面赋值
            dto_prj.PowerTotal = Math.Round(defaultPrj.SumPower, 0);
            dto_prj.MoneyTotal = Math.Round(defaultPrj.SumMoney, 0);
            dto_prj.BlockTimes = new List<ZyDto.SubmitPrjBlockTime>();
            double startHeight = 0;
            if (defaultPrj.BlockTimes != null)
            {
                startHeight = defaultPrj.BlockTimes.First().ReservoirStartHeight;
                foreach (var bt in defaultPrj.BlockTimes)
                {
                    if (bt.OpenPumpIndexs == null)
                        continue;
                    ZyDto.SubmitPrjBlockTime dto_item = new ZyDto.SubmitPrjBlockTime();
                    dto_item.StartTime = bt.StartTime;
                    dto_item.EndTime = bt.EndTime;
                    dto_item.OpenPumpCount = bt.OpenPumpIndexs.Count;
                    dto_item.OpenPumpIndexs = bt.OpenPumpIndexs;
                    dto_item.StartSwitchGroupID = bt.StartSwitchGroupID;
                    if (bt.PointTimes != null)
                    {
                        dto_item.Records = new List<SubmitPrjTime>();
                        foreach (var bt2 in bt.PointTimes)
                        {
                            //if(maxHeight < bt2.WaterLevelH)
                            //{
                            //    maxHeight = bt2.WaterLevelH;
                            //    //maxHeight = Math.Max(maxHeight, bt2.WaterLevelH);
                            //    maxHeightTime = bt2.Time;
                            //}
                            dto_item.Records.Add(new SubmitPrjTime(bt2));
                        }
                    }
                    dto_prj.BlockTimes.Add(dto_item);
                }
            }
            if (defaultPrj.MaxWaterLevelH <= 0)
            {
                double maxHeight = 0;
                DateTime maxHeightTime = defaultPrj.StartTime;
                if (defaultPrj.BlockTimes != null)
                {
                    foreach (var bt in defaultPrj.BlockTimes)
                    {
                        if (bt.OpenPumpIndexs == null)
                            continue;
                        if (bt.PointTimes != null)
                        {
                            foreach (var bt2 in bt.PointTimes)
                            {
                                if (maxHeight < bt2.WaterLevelH)
                                {
                                    maxHeight = bt2.WaterLevelH;
                                    //maxHeight = Math.Max(maxHeight, bt2.WaterLevelH);
                                    maxHeightTime = bt2.Time;
                                }
                            }
                        }
                    }
                }
                defaultPrj.MaxWaterLevelH = maxHeight;
                defaultPrj.MaxWaterLevelTime = maxHeightTime;
            }
            if(defaultPrj.MaxWaterLevelTime> defaultPrj.StartTime)
            dto_prj.MaxWaterLevelH = string.Format("{0:N2}  ({1})",  Math.Round( defaultPrj.MaxWaterLevelH,2) ,
                defaultPrj.MaxWaterLevelTime.ToString("HH:mm"));
            else
                dto_prj.MaxWaterLevelH = string.Format("{0:N2} ", Math.Round(defaultPrj.MaxWaterLevelH, 2));
            //dto_prj.MaxWaterLevelH = defaultPrj.MaxWaterLevelH;
            //dto_prj.MaxWaterLevelTime = defaultPrj.MaxWaterLevelTime;
            dto_prj.StartWaterLevelH = string.Format("{0:N2}  ({1})", Math.Round(startHeight, 2),
                defaultPrj.StartTime.ToString("HH:mm")); ;
            dto_prj.Switchs = new List<SubmitPrjSwitchInfo>();
            if (defaultPrj.PumpSwitchs != null)
            {
                var fi_PumpSwitchs = from x in defaultPrj.PumpSwitchs orderby x.Time select x;
                foreach (var bt in fi_PumpSwitchs)
                {
                    ZyDto.SubmitPrjSwitchInfo dto_item = new ZyDto.SubmitPrjSwitchInfo();
                    dto_item.Index = bt.Index;
                    dto_item.GroupID = bt.GroupID;//分组ID
                    dto_item.PumpIndex = bt.PumpIndex;//泵角标
                    dto_item.Time = bt.Time.ToString("yyyy-MM-dd HH:mm:ss");//时间
                    dto_item.SwitchType = bt.SwitchType;///1 开机 0 关机
                    dto_prj.Switchs.Add(dto_item);
                }
            }
            return dto_prj;
        }
        #endregion 换算成DTO
    }
}