using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FLY.FeedbackRenZiJia.OBJ_INTERFACE;
using System.Collections.ObjectModel;
using System.ComponentModel;
using FLY.FeedbackRenZiJia.Common;
using FLY.FeedbackRenZiJia.IService;
using PropertyChanged;
using AutoMapper;
using System.IO;
using Newtonsoft.Json;
using FLY.Thick.Blowing.IService;
using Misc;

namespace FLY.FeedbackRenZiJia.Server
{
    /// <summary>
    /// 以前 正反转加热分离,所以有两个 HeatCell
    /// 现在不分正反转,只有一个HeatCell
    /// </summary>
    public class HeatCell : IHeatCellService
    {
        #region IHeatCell 接口 成员变量

        #region 参数
        /// <summary>
        /// HeatOffset = ThickPercent * Kp
        /// </summary>
        public double Kp { get; set; } = 3;


        /// <summary>
        /// 平滑的阀值,只有超出阀值,才平滑
        /// </summary>
        public double ThresholdHeatSigma { get; set; } = 10;


        /// <summary>
        /// 自控时,不能调整总体上升下降
        /// </summary>
        public bool IsForbidUpDown { get; set; } = false;



        /// <summary>
        /// 厚度控制线 , 厚度% 大于 厚度控制线 自动才会加热控制  
        /// </summary>
        public int CtrlLine { get; set; } = 2;

        /// <summary>
        /// 最大加热量 默认100%
        /// </summary>
        public int MaxHeat { get; set; } = 100;

        #endregion

        #region 状态


        /// <summary>
        /// 对应的100% 数据,单位是% 数量是ChannelCnt, 数据肯定是完整的!!!!!
        /// </summary>
        [DoNotCheckEquality]
        public double[] ThickPercents { get; set; }



        /// <summary>
        /// 当前方向的加热策略,必须保证 0~100
        /// </summary>
        [DoNotCheckEquality]
        public int[] Heats { get; protected set; }


        private int Base { get; set; } = 0;




        /// <summary>
        /// 加热偏移量
        /// </summary>
        [DoNotCheckEquality]
        public int[] Offsets { get; protected set; }

        
        /// <summary>
        /// Heats+Offsets+Base
        /// </summary>
        [DoNotCheckEquality]
        public int[] PreHeats { get; protected set; }


        /// <summary>
        /// 加热量 每3个计算的sigma,最大值
        /// </summary>
        public double MaxHeatSigma { get; set; } = 0;


        /// <summary>
        /// 当前正在自动对位模式
        /// </summary>
        public bool IsInAutoONo { get; protected set; }


        #endregion

        #region 对位
        /// <summary>
        /// 自动对位
        /// </summary>
        public bool IsAutoONo { get; set; } = true;

        /// <summary>
        /// 当前正在自动对位模式
        /// </summary>
        public AutoONoStatusEnum AutoONoStatus { get; private set; }
        /// <summary>
        /// 自动对位模式 信息
        /// </summary>
        public string AutoONoMsg { get; private set; }
        /// <summary>
        /// 自动对位 那幅空的图
        /// </summary>
        public long AutoONoId0 { get; private set; } = -1;
        /// <summary>
        /// 自动对位 加热后生效的图
        /// </summary>
        public long AutoONoId1 { get; private set; } = -1;
        #endregion
        #endregion

        public int ChannelCnt { get; set; }
        int BoltCnt;
        HeatBuf mHeatBuf;
        IBlowingService blowingService;
        public Func<object,bool> PreHeatApplyEvent;
        public event Action<object> AfterHeatApplyEvent;
        public event Action<object> AfterClearOffsetsEvent;

        
        public HeatCell() 
        {
            if (!Load())
                Save();

            checkParamErr();
            Init2(88, 88);
            
        }
        void checkParamErr()
        {
            if (Kp < 1 || Kp > 10)
            {
                Kp = 3;
            }

            if (ThresholdHeatSigma < 1 || ThresholdHeatSigma > 50)
            {
                ThresholdHeatSigma = 10;
            }

            if (CtrlLine < 0 || CtrlLine > 10)
            {
                CtrlLine = 2;
            }
        }
        public void Init(HeatBuf heatBuf)
        {
            mHeatBuf = heatBuf;
        }
        public void Init3(IBlowingService blowingService)
        {
            this.blowingService = blowingService;
            this.blowingService.PropertyChanged += BlowingService_PropertyChanged;
        }

        private void BlowingService_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            //当复位区号改变了,同时也修改heatCell 的 thickPercents
            if (e.PropertyName == nameof(this.blowingService.OrgBoltNo)) {
                if (mHeatBuf.MoveThickPercents(this.blowingService.OrgBoltNo))
                    SetThickPercents(mHeatBuf.ThickPercents);
            }
        }

        public void Init2(int boltCnt, int channelCnt)
        {
            ChannelCnt = channelCnt;
            BoltCnt = boltCnt;

            Base = 0;
            MaxHeatSigma = 0;

            ThickPercents = new double[ChannelCnt];
            Heats = new int[ChannelCnt];
            PreHeats = new int[ChannelCnt];
            Offsets = new int[ChannelCnt];

            ResetAuto();
        }

        /// <summary>
        /// 复位自动状态
        /// </summary>
        public void ResetAuto()
        {
            AutoONoStatus = AutoONoStatusEnum.Init;
            AutoONoMsg = "等待 加热=0,厚度稳定";
            AutoONoId0 = -1;
            AutoONoId1 = 0;
        }

        void checkResetAuto() {
            if (mHeatBuf.Stability != STABILITY.OK_CORREL)
                return;

            if (Heats.All(h => h == 0))
            {
                //加热全部为0
                //复位状态
                ResetAuto();
            }
        }
        void AutoONoOnPoll()
        {
            checkResetAuto();


            switch (AutoONoStatus)
            {
                case AutoONoStatusEnum.Init:
                    {
                        if (mHeatBuf.Stability != STABILITY.OK_CORREL)
                            break;

                        if (Heats.All(h => h == 0))
                        {
                            //判断当前加热全部为空, 且稳定性大于>0.7

                            //转为 加热棒数量
                            double[] thickPercents = ThickPercents;

                            double autoONoKp = Kp;
                            if (autoONoKp < 1)
                                autoONoKp = 1;

                            int[] offsets = new int[ChannelCnt];
                            while (true)
                            {
                                for (int i = 0; i < ChannelCnt; i++)
                                {
                                    double percent = thickPercents[i];
                                    offsets[i] = (int)Math.Round(percent * autoONoKp);
                                }

                                int[] heatPercents = offsets;//放大数量为分区量
                                heatPercents = Common.MyMath.Filter(heatPercents, mHeatBuf.HeatEffectCurve);//平滑
                                int maxMin = Common.MyMath.CalMaxMin(heatPercents);

                                if (maxMin >= mHeatBuf.ThresholdMaxMin)
                                {
                                    AutoONoStatus = AutoONoStatusEnum.Step2;
                                    AutoONoMsg = "厚度已经稳定,对位加热,等待结果";
                                    AutoONoId0 = mHeatBuf.mData.Last().thickHeat.ID;
                                    AutoONoId1 = -1;
                                    break;
                                }
                                else {
                                    if (maxMin < 2) {
                                        //肯定是厚度太好
                                        AutoONoStatus = AutoONoStatusEnum.Fail;
                                        AutoONoMsg = "失败,加热变化量太小,转到正常模式";
                                        AutoONoId0 = -1;
                                        AutoONoId1 = -1;
                                        return;
                                    }
                                    //加热变化不够多, 变大Kp
                                    double k = autoONoKp * mHeatBuf.ThresholdMaxMin / maxMin - autoONoKp;
                                    if (k < 0.5)
                                        k = 0.5;
                                    autoONoKp += k;
                                }
                            }

                            Offsets = offsets;

                            UpdatePreHeats();//这句一定要加!!!! 不然没法平滑,没法加热

                            //上面已经有平滑,不需要再执行 Smooth()

                            ModifyBase();

                            HeatApply();
                        }
                        else
                        {
                            //虽然稳定了,但已经被人加热了,无法启动对位模式
                            AutoONoStatus = AutoONoStatusEnum.Fail;
                            AutoONoMsg = "加热不为0,无法启动对位模式";
                            return;
                        }
                    }
                    break;
                case AutoONoStatusEnum.Step2:
                    {
                        //不需要等 STABILITY.OK_CORREL
                        if (mHeatBuf.MaxR_Id1 == mHeatBuf.mData.Last().thickHeat.ID)//算出结果
                        {
                            string msg = "对位完成";
                            msg += $",[相关性]{mHeatBuf.MaxR:F2}";
                            msg += $",[极差]{mHeatBuf.MaxMin}%";
                            if (blowingService.OrgBoltNo != mHeatBuf.BestOrgBoltNo)
                            {
                                //调节 mHeatBuf.ThickPercents 移动到 mHeatBuf.BestOrgBoltNo
                                //使mHeatBuf状态为稳定
                                mHeatBuf.SetToBestThickPercents();
                                SetThickPercents(mHeatBuf.ThickPercents);


                                msg += $",[复位号]{blowingService.OrgBoltNo}->{mHeatBuf.BestOrgBoltNo}";
                                blowingService.OrgBoltNo = mHeatBuf.BestOrgBoltNo;
                                blowingService.Apply();
                            }
                            else
                            {
                                msg += $",[复位号]正确";
                            }

                            if (Math.Abs(Kp - mHeatBuf.BestKp) > 0.2)
                            {
                                msg += $",[Kp]{Kp:F1}->{mHeatBuf.BestKp:F1}";
                                Kp = mHeatBuf.BestKp;
                                Apply();
                            }
                            else
                            {
                                msg += $",[Kp]正确";
                            }
                            //对位完成
                            AutoONoStatus = AutoONoStatusEnum.Success;
                            AutoONoMsg = msg;
                            AutoONoId0 = mHeatBuf.MaxR_Id0;
                            AutoONoId1 = mHeatBuf.MaxR_Id1;
                            return;
                        }
                        else
                        {
                            if (AutoONoId0 < mHeatBuf.mData.First().thickHeat.ID)
                            {
                                //失败,对位过程有大波动, 全部数据被清除?
                                AutoONoStatus = AutoONoStatusEnum.Fail;
                                AutoONoMsg = "失败,对位过程有大波动";
                                return;
                            }

                            //数据稳定了,且加热变化量为0
                            if (mHeatBuf.Stability == STABILITY.OK_CORREL && mHeatBuf.LastHeatDiffMaxMin == 0)
                            {
                                //数据稳定了, 但没有出结果!!!!!
                                AutoONoStatus = AutoONoStatusEnum.Fail;
                                AutoONoMsg = "失败,对位加热相关性不够";
                                return;
                            }
                        }
                    }
                    break;
            }
        }

        /// <summary>
        /// 自动模式!!!!!
        /// </summary>
        public void Auto()
        {
            if (mHeatBuf.mData.Count() == 0)
                return;
            //&& mHeatBuf.IsStable()


            if (IsAutoONo)
            {
                AutoONoOnPoll();
            }



            if (
                (!IsAutoONo)
                || ((IsAutoONo) && (AutoONoStatus == AutoONoStatusEnum.Fail || AutoONoStatus == AutoONoStatusEnum.Success))
                )
            {
                if (mHeatBuf.Stability == STABILITY.OK_CORREL)//稳定 与 待定时 加热
                {
                    //转为 加热棒数量
                    var thickPercents = ThickPercents;

                    int[] offsets = new int[ChannelCnt];
                    for (int i = 0; i < ChannelCnt; i++)
                    {
                        if (mHeatBuf.BoltIsStable[i] && //稳定
                            (Math.Abs(thickPercents[i]) > CtrlLine))//在控制线已外
                        {
                            offsets[i] = (int)Math.Round(thickPercents[i] * Kp);
                        }
                    }

                    Offsets = offsets;
                    UpdatePreHeats();//这句一定要加!!!! 不然没法平滑,没法加热
                    
                    if (!IsForbidUpDown)//禁止整体上移下降
                        ModifyBase();//自动整体上移下降
                    
                    Smooth();//平滑,它会导致Offset被修改,<0的都被删除掉

                    HeatApply();//执行加热
                }
            }
        }


        public void SetThickPercents(double[] thkpercents)
        {
            thkpercents = MakeThickPercentsFull(thkpercents);
            for (int i = 0; i < thkpercents.Count(); i++)
                thkpercents[i] = Math.Round(thkpercents[i], 2);
            ThickPercents = thkpercents;
        }

        #region IHeatCell 接口 成员函数

        /// <summary>
        /// 把空的数据补齐
        /// </summary>
        /// <param name="thicks"></param>
        double[] MakeThickPercentsFull(double[] _thkpercents)
        {
            var thkpercents = _thkpercents.ToArray();

            List<Misc.Range> emptys = new List<Misc.Range>();
            int start = -1;//double.NaN 的段开始
            int end = -1;//double.NaN 的段结束
            //变成数列
            int thks_cnt = thkpercents.Count();
            for (int i = 0; i < thks_cnt; i++)
            {
                if (double.IsNaN(thkpercents[i]))
                {
                    if (start == -1)
                    {
                        start = i;
                    }
                    end = i;
                }
                else
                {
                    if (start != -1)
                    {
                        emptys.Add(new Misc.Range() { Begin = start, End = end });
                        start = -1;
                    }
                }
            }
            
            
            if (start != -1)//添加最后一个
            {
                emptys.Add(new Misc.Range() { Begin = start, End = end });
            }

            if (emptys.Count() > 0)
            {
                int e = emptys.Last().End;
                int b = emptys.First().Begin;
                if ((b == 0) && e == (thks_cnt - 1))
                {
                    //这是同一个
                    emptys.Last().End = emptys.First().End;
                    emptys.RemoveAt(0);
                }
                for (int i = 0; i < emptys.Count(); i++)
                {
                    Misc.Range r = emptys[i];
                    int idx = r.Begin - 1;
                    if (idx < 0)
                        idx += thks_cnt;

                    double b_thk = thkpercents[idx];

                    idx = r.End + 1;
                    if (idx >= thks_cnt)
                        idx -= thks_cnt;

                    double e_thk = thkpercents[idx];
                    //这个很重要, 当 结尾与开头重合, r.End < r.Begin, r.Width 会<0
                    int len = r.Width;
                    if (len < 0)
                        len += thks_cnt;

                    for (int j = 0; j < len; j++)
                    {
                        idx = r.Begin + j;
                        if (idx >= thks_cnt)
                            idx -= thks_cnt;
                        thkpercents[idx] = b_thk + (j + 1) * (e_thk - b_thk) / (len + 1);
                    }
                }
            }
            return thkpercents;
        }


        /// <summary>
        /// 手动调整加热增量
        /// </summary>
        /// <param name="idx"></param>
        /// <param name="change"></param>
        public void ModifyOffset(int idx, int change)
        {
            if (idx < ChannelCnt && idx >= 0)
            {
                Offsets[idx] += change;
                UpdatePreHeats();
            }
            NotifyPropertyChanged(nameof(Offsets));
        }

        /// <summary>
        /// 参数是 baseheatoffset 的增量
        /// </summary>
        /// <param name="change"></param>
        public void ModifyBase(int change)
        {
            Base += change;
            UpdatePreHeats();
        }

        /// <summary>
        /// 调整BaseHeatOffset,令Heats 在范围内
        /// </summary>
        void ModifyBase()
        {
            int[] preheat = new int[ChannelCnt];
            for (int i = 0; i < ChannelCnt; i++)
                preheat[i] = Heats[i] + Offsets[i] + Base;

            int min = preheat.Min();
            int max = preheat.Max();
            int avg = (int)preheat.Average();

            int base_offset;
            int maxHeat = MaxHeat;

            if ((min < 0) && (max > maxHeat))
            {
                //功率极限了
                //保存平均值为50
                base_offset = avg - maxHeat / 2;
            }
            else if (max > maxHeat)
            {

                //整体往下降
                base_offset = max - maxHeat;

                if (base_offset > (avg - maxHeat / 2))//移得太多
                    base_offset = (avg - maxHeat / 2);
            }
            else
            {
                base_offset = min;
                if (base_offset < 0)
                {
                    if (base_offset < (avg - maxHeat / 2))//升得太多
                        base_offset = (avg - maxHeat / 2);
                }
            }

            Base -= base_offset;

            UpdatePreHeats();
        }

        /// <summary>
        /// 清空HeatOffset
        /// </summary>
        public void ClearOffsets()
        {
            Base = 0;

            for (int i = 0; i < ChannelCnt; i++)
            {
                Offsets[i] = 0;
            }
            NotifyPropertyChanged(nameof(Offsets));
            UpdatePreHeats();

            AfterClearOffsetsEvent?.Invoke(this);
        }
        
        /// <summary>
        /// 清空Heats
        /// </summary>
        public void ClearPreHeats()
        {
            int[] heats = new int[ChannelCnt];
            Array.Clear(heats, 0, ChannelCnt);
            ModifyPreHeats(heats);
        }

        /// <summary>
        /// 调整PreHeats
        /// </summary>
        /// <param name="heats"></param>
        public void ModifyPreHeats(int[] heats)
        {
            
            if (heats.Count() != ChannelCnt)
                return;
            Base = 0;
            for (int i = 0; i < ChannelCnt; i++)
            {
                PreHeats[i] = heats[i];
                Offsets[i] = PreHeats[i] - Heats[i];
            }
            NotifyPropertyChanged(nameof(Offsets));
            NotifyPropertyChanged(nameof(PreHeats));
            UpdateHeatSigmas();
        }
        public void ModifyHeats(int[] heats)
        {
            if (heats.Count() != ChannelCnt)
                return;

            bool isChanged = false;
            Base = 0;
            for (int i = 0; i < ChannelCnt; i++)
            {
                if (Heats[i] != heats[i])
                {
                    isChanged = true;
                    Heats[i] = heats[i];
                    Offsets[i] = PreHeats[i] - Heats[i];
                }
            }
            if (isChanged)
            {
                NotifyPropertyChanged(nameof(Offsets));
                NotifyPropertyChanged(nameof(Heats));
            }
        }
        /// <summary>
        /// 利用测厚仪的数据,计算出HeatOffsets
        /// </summary>
        public void Cal()
        {
            var thickpercents = ThickPercents;// Common.MyMath.ZoomOut(ThickPercents, BoltCnt / ChannelCnt);
            int[] offsets = new int[ChannelCnt];
            for (int i = 0; i < ChannelCnt; i++)
            {
                offsets[i] = (int)Math.Round(thickpercents[i] * Kp);
            }
            Offsets = offsets;
            UpdatePreHeats();
        }

        #region PreHeats 平滑处理
        double[] GetHeatSigmas(int[] heats)
        {
            var heatsigmas = new double[ChannelCnt];
            for (int i = 0; i < ChannelCnt; i++)
            {
                var dat = getSubArray(heats, i);
                heatsigmas[i] = dat.Sigma();
            }
            return heatsigmas;
        }
        void UpdateHeatSigmas()
        {
            var heatsigmas = GetHeatSigmas(PreHeats);
            MaxHeatSigma = heatsigmas.Max();
        }

        T[] getSubArray<T>(T[] array, int index) {
            T[] dat = new T[3];
            for (int j = 0; j < 3; j++)
            {
                int idx = index - 1 + j;
                if (idx < 0)
                    idx += array.Count();
                else if (idx >= array.Count())
                    idx -= array.Count();

                dat[j] = array[idx];
            }
            return dat;
        }
        /// <summary>
        /// 平滑,不断修改PreHeats 直到HeatsSigma 合格
        /// </summary>
        public void Smooth()
        {
            int[] heats = PreHeats.ToArray();
            int[] heats2 = new int[ChannelCnt];
            bool hasChanged = false;
            bool hasChanged2 = false;
            double[] heatsigmas;
            do
            {
                //1.更新sigma
                heatsigmas = GetHeatSigmas(heats);

                //2.检测HeatsSigma, 哪里比较大,对该位置 滤波
                for (int i = 0; i < heats.Count(); i++)
                {
                    if (heatsigmas[i] > (ThresholdHeatSigma)) //不行,要滤波!!!
                    {
                        //连续3个滤波
                        int[] dat = getSubArray(heats, i);
                        heats2[i] = (int)Math.Round(dat.Average());

                        //if (heats2[i] == heats[i]) 
                        //{ 
                        //    //居然一样,修改旁边的两个的值
                        //    if (i > 0) {
                        //        int idx = i-1;
                        //        dat = getSubArray(heats, idx);
                        //        heats2[idx] = (int)Math.Round(dat.Average());
                        //    }

                        //    if (i == heats.Count() - 1)
                        //    {
                        //        int idx = 0;
                        //        dat = getSubArray(heats, idx);
                        //        heats2[idx] = (int)Math.Round(dat.Average());
                        //    }
                        //}
                    }
                    else
                    {
                        heats2[i] = heats[i];
                    }
                }

                //3.有滤波行为,继续求循环,求sigma,判断。。。。。
                hasChanged = false;
                for (int i = 0; i < heats.Count(); i++) {
                    if (heats[i]!=heats2[i]) {
                        heats[i] = heats2[i];
                        hasChanged = true;
                    }
                }
                if(hasChanged)
                    hasChanged2 = true;

            } while (hasChanged);

            if (hasChanged2)
            {
                for (int i = 0; i < ChannelCnt; i++)
                {
                    PreHeats[i] = heats[i];
                    Offsets[i] = PreHeats[i] - Heats[i] - Base;
                }
                NotifyPropertyChanged(nameof(PreHeats));
                NotifyPropertyChanged(nameof(Offsets));
                MaxHeatSigma = heatsigmas.Max();
            }
        }
        #endregion
        /// <summary>
        /// 加热输出应用
        /// </summary>
        public void HeatApply()
        {
            if (PreHeatApplyEvent != null)
            {
                if (!PreHeatApplyEvent(this))
                {
                    return;
                }
            }

            for (int i = 0; i < ChannelCnt; i++)
            {
                Offsets[i] = 0;

                int heat = PreHeats[i];
                if (heat < 0)
                {
                    //需要整体提升
                    heat = 0;
                }
                else if (heat > 100)
                {
                    //需要整体调低
                    heat = 100;
                }
                Heats[i] = heat;

            }
            NotifyPropertyChanged("Offsets");
            NotifyPropertyChanged("Heats");
            Base = 0;

            AfterHeatApplyEvent?.Invoke(this);
        }

        /// <summary>
        /// 修改Offsets, Base 后,执行PreHeats = Heats + Offsets + Base
        /// </summary>
        void UpdatePreHeats()
        {
            for (int i = 0; i < ChannelCnt; i++)
            {
                int preheat = Heats[i] + Offsets[i] + Base;

                if (preheat > 100)
                    preheat = 100;
                else if (preheat < 0)
                    preheat = 0;
                PreHeats[i] = preheat;
            }
            UpdateHeatSigmas();
            NotifyPropertyChanged(nameof(PreHeats));
        }

        public void Apply()
        {
            Save();
        }
        #endregion


        string file_path = "heatcell.json";
        bool Load()
        {
            if (File.Exists(file_path))
            {
                try
                {
                    string json = File.ReadAllText(file_path);
                    var jsonDb = JsonConvert.DeserializeObject<HeatCellJsonDb>(json);
                    HeatCellJsonDb.Mapper.Map(jsonDb, this);
                    return true;
                }
                catch
                {
                    //异常,没有json 解码失败

                }
                return false;
            }
            return false;
        }
        void Save()
        {
            try
            {
                var jsonDb = HeatCellJsonDb.Mapper.Map<HeatCellJsonDb>(this);
                string json = JsonConvert.SerializeObject(jsonDb, Formatting.Indented);
                File.WriteAllText(file_path, json);
            }
            catch
            {
                //异常,没有json 编码失败

            }
        }

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }


        #endregion
    }
    public class HeatCellJsonDb 
    {
        public static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => {
            c.CreateMap<HeatCell, HeatCellJsonDb>().ReverseMap();
        }));

        #region 参数
        /// <summary>
        /// HeatOffset = ThickPercent * Kp
        /// </summary>
        public double Kp= 3;


        /// <summary>
        /// 自动对位
        /// </summary>
        public bool IsAutoONo = true;

        /// <summary>
        /// 最大加热量
        /// </summary>
        public int MaxHeat = 100;

        /// <summary>
        /// 平滑的阀值,只有超出阀值,才平滑
        /// </summary>
        public double ThresholdHeatSigma= 10;


        /// <summary>
        /// 自控时,不能调整总体上升下降
        /// </summary>
        public bool IsForbidUpDown= false;



        /// <summary>
        /// 厚度控制线 , 厚度% 大于 厚度控制线 自动才会加热控制  
        /// </summary>
        public int CtrlLine= 2;



        #endregion
    }
}