using FlyADBase;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace Flyad7_WPF
{
    public class WdGridAdvAnalyzeVm : INotifyPropertyChanged
    {
        public double R { get; set; }
        public double CurrR { get; set; }
        public double CurrGroupR { get; set; }
        public double Speed { get; set; }
        public ObservableCollection<double> KsP { get; } = new ObservableCollection<double>();
        public ObservableCollection<double> Ks { get; } = new ObservableCollection<double>();


        public int CellCnt { get; private set; }
        public int SampleCellIdx { get; set; }



        public RelayCommand LoadCmd { get; private set; }
        public RelayCommand AutoCmd { get; private set; }
        public RelayCommand Auto2Cmd { get; private set; }
        public RelayCommand ManualCmd { get; private set; }
        public RelayCommand NextIdxCmd { get; private set; }
        public RelayCommand PreIdxCmd { get; private set; }
        public RelayCommand ClearRCmd { get; private set; }

        public RelayCommand ConvDebugCmd { get; private set; }
        List<GridAdvAnalyzeCell> gridAdvAnalyzeCells = new List<GridAdvAnalyzeCell>();
        List<GridAdvAnalyzeCellGroup> groups = new List<GridAdvAnalyzeCellGroup>();
        int[] Target;
        int[] Roller;

        System.Windows.Forms.DataVisualization.Charting.Chart chart;
        System.Windows.Forms.DataVisualization.Charting.Chart chart1;
        System.Windows.Forms.DataVisualization.Charting.Chart chart2;
        FlyAD7 flyad;

        public event PropertyChangedEventHandler PropertyChanged;

        public WdGridAdvAnalyzeVm()
        {
            LoadCmd = new RelayCommand(Load);
            AutoCmd = new RelayCommand(AutoCal);
            Auto2Cmd = new RelayCommand(AutoCal2);
            ManualCmd = new RelayCommand(ManualCal);
            ClearRCmd = new RelayCommand(DrawClear);
            NextIdxCmd = new RelayCommand(NextIdx);
            PreIdxCmd = new RelayCommand(PreIdx);
            ConvDebugCmd = new RelayCommand(ConvDebug);


            for (int i = 0; i < 5; i++)
            {
                KsP.Add(0);
                Ks.Add(0);
            }
            Ks[0] = 1;
        }

        public void Init(
            FlyAD7 flyad,
            System.Windows.Forms.DataVisualization.Charting.Chart chart0,
            System.Windows.Forms.DataVisualization.Charting.Chart chart1,
            System.Windows.Forms.DataVisualization.Charting.Chart chart2
            )
        {
            this.flyad = flyad;
            this.chart = chart0;
            this.chart1 = chart1;
            this.chart2 = chart2;
        }

        private void ConvDebug()
        {
            WdConvolution w = new WdConvolution();
            w.Init(Target);
            w.ShowDialog();
        }

        private void PreIdx()
        {
            SampleCellIdx--;
            ManualCal();
        }

        private void NextIdx()
        {
            SampleCellIdx++;
            ManualCal();
        }

        void Load()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.DefaultExt = ".json";
            if (ofd.ShowDialog() != true)
                return;

            List<TimeGridAdv2EventArgs> timeGridAdv2Datas;
            string path = ofd.FileName;
            try
            {
                string json = File.ReadAllText(path);
                timeGridAdv2Datas = Newtonsoft.Json.JsonConvert.DeserializeObject<List<TimeGridAdv2EventArgs>>(json);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return;
            }
            if (timeGridAdv2Datas == null || timeGridAdv2Datas.Count() < 4)
            {
                MessageBox.Show("数量为空，或者太少了");
                return;
            }

            toGridAdvAnalyzeCells(timeGridAdv2Datas);


            MessageBox.Show(
                $"共加载 {gridAdvAnalyzeCells.Count()}幅数据 " + System.Environment.NewLine
                + $"速度从 {gridAdvAnalyzeCells.First().speed:F1}pps -> {gridAdvAnalyzeCells.Last().speed:F1}pps"
                );
            return;
        }

        //void createRollerView()
        //{
        //    int roller_begin = 20;
        //    int roller_end = 60;
        //    Roller = new int[Target.Count()];



        //    //把 Target 的 测到不锈钢部分删除， 剩下求平均值
        //    int sum =0;
        //    int cnt=0;
        //    for (int i = 0; i < Target.Count(); i++) 
        //    {
        //        if (i >= roller_begin && i <= roller_end)
        //            continue;
        //        if (Misc.MyBase.ISVALIDATA(Target[i]))
        //        {
        //            sum += Target[i];
        //            cnt++;
        //        }
        //    }

        //    airAd = sum / cnt;
        //    int sensorGridWidth = (int)(25 / mmpp / flyad.PosOfGrid);
        //    int rollerGridWidth = (int)(rollerWidth / mmpp / flyad.PosOfGrid);

        //    //通过相关性，找到中心位置
        //    int rollerGridPos = 40;

        //    var roller = new int[rollerGridWidth + sensorGridWidth * 4];
        //    int idx = 0;
        //    for (int i = 0; i < sensorGridWidth*2; i++)
        //    {
        //        roller[idx] = airAd;
        //        idx++;
        //    }
        //    for (int i = 0; i < rollerGridWidth; i++)
        //    {
        //        roller[idx] = airAd;
        //        idx++;
        //    }
        //    for (int i = 0; i < sensorGridWidth * 2; i++)
        //    {
        //        roller[idx] = airAd;
        //        idx++;
        //    }

        //    //找到最大相关性对应的位置
        //    CurrR = Misc.MyMath.Correl(Target, ad_x);
        //}
        async void toGridAdvAnalyzeCells(List<TimeGridAdv2EventArgs> timeGridAdv2Datas)
        {
            gridAdvAnalyzeCells.Clear();
            foreach (var gridAdvUnit in timeGridAdv2Datas)
            {
                var cell = new GridAdvAnalyzeCell()
                {
                    units = gridAdvUnit
                };
                gridAdvAnalyzeCells.Add(cell);
            }

            //计算速度
            foreach (var cell in gridAdvAnalyzeCells)
            {
                //计算中间1/3数据的平均速度
                int cnt = cell.units.AdList.Count();
                int range = cnt / 20;
                int idx_last = (cnt + range) / 2;
                int idx_first = (cnt - range) / 2;
                int delta_pos = cell.units.PosList[idx_last] - cell.units.PosList[idx_first];
                double delta_sec = (idx_last - idx_first) * 1.28 / 1000;
                cell.speed = delta_pos / delta_sec;
            }

            //画出速度
            //await Draw2(gridAdvAnalyzeCells.Select(c => Math.Abs(c.speed)).ToArray());

            //把相同速度的，放在一起
            double speed_diff = 25;
            groups.Clear();
            for (int i = 0; i < gridAdvAnalyzeCells.Count(); i++)
            {
                var cell = gridAdvAnalyzeCells[i];
                GridAdvAnalyzeCellGroup group;
                if (groups.Count() == 0)
                {
                    group = new GridAdvAnalyzeCellGroup() { speed = Math.Abs(cell.speed) };
                    groups.Add(group);
                    if (cell.speed > 0)
                    {
                        group.fCellIdxs.Add(i);
                    }
                    else
                    {
                        group.bCellIdxs.Add(i);
                    }
                    group.range.Begin = i;
                    group.range.End = i;
                }
                else
                {
                    group = groups.Last();
                    if (Math.Abs(group.speed - Math.Abs(cell.speed)) < speed_diff)
                    {
                        //同一个
                        if (cell.speed > 0)
                        {
                            group.fCellIdxs.Add(i);
                        }
                        else
                        {
                            group.bCellIdxs.Add(i);
                        }
                        group.range.End = i;
                    }
                    else
                    {
                        group = new GridAdvAnalyzeCellGroup() { speed = Math.Abs(cell.speed) };
                        groups.Add(group);
                        if (cell.speed > 0)
                        {
                            group.fCellIdxs.Add(i);
                        }
                        else
                        {
                            group.bCellIdxs.Add(i);
                        }
                        group.range.Begin = i;
                        group.range.End = i;
                    }
                }
            }
            GetTarget();
            CellCnt = gridAdvAnalyzeCells.Count();
            SampleCellIdx = CellCnt * 3 / 4;
            ManualCal();
        }
        int GetGroupIdxFromCellIdx(int cellidx)
        {
            return groups.FindIndex(group => group.range.Contain(cellidx));
        }

        int[] CalGroupData(int groupIdx)
        {
            int[] ad_sum = new int[1000];
            int[] ad_cnt = new int[1000];
            foreach (var cal_cell_idx in groups[groupIdx].fCellIdxs)
            {
                Filter2(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs, Ks);
                
                var ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
                for (int i = 0; i < 1000; i++)
                {
                    if (Misc.MyBase.ISVALIDATA(ad_x[i]))
                    {
                        ad_sum[i] += ad_x[i];
                        ad_cnt[i]++;
                    }
;
                }
            }
            foreach (var cal_cell_idx in groups[groupIdx].bCellIdxs)
            {
                Filter2(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs, Ks);
                var ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);

                for (int i = 0; i < 1000; i++)
                {
                    if (Misc.MyBase.ISVALIDATA(ad_x[i]))
                    {
                        ad_sum[i] += ad_x[i];
                        ad_cnt[i]++;
                    }
                }
            }

            for (int i = 0; i < 1000; i++)
            {
                if (ad_cnt[i] > 0)
                {
                    ad_sum[i] /= ad_cnt[i];
                }
                else
                {
                    ad_sum[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return ad_sum;
            //await Chart1DrawData(3, ad_sum);
        }

        int[] CalGroupDataAvg(int groupIdx)
        {
            int[] ad_sum = new int[1000];
            int[] ad_cnt = new int[1000];
            foreach (var cal_cell_idx in groups[groupIdx].fCellIdxs)
            {
                var Xs = gridAdvAnalyzeCells[cal_cell_idx].units;
                var ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
                for (int i = 0; i < 1000; i++)
                {
                    if (Misc.MyBase.ISVALIDATA(ad_x[i]))
                    {
                        ad_sum[i] += ad_x[i];
                        ad_cnt[i]++;
                    }
;
                }
            }
            foreach (var cal_cell_idx in groups[groupIdx].bCellIdxs)
            {
                Filter2(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs, Ks);
                
                var ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);

                for (int i = 0; i < 1000; i++)
                {
                    if (Misc.MyBase.ISVALIDATA(ad_x[i]))
                    {
                        ad_sum[i] += ad_x[i];
                        ad_cnt[i]++;
                    }
                }
            }

            for (int i = 0; i < 1000; i++)
            {
                if (ad_cnt[i] > 0)
                {
                    ad_sum[i] /= ad_cnt[i];
                }
                else
                {
                    ad_sum[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return ad_sum;
            //await Chart1DrawData(3, ad_sum);
        }


        async void DrawClear()
        {
            await Task.Yield();
            //画图
            App.Current.Dispatcher.Invoke(() =>
            {
                System.Windows.Forms.DataVisualization.Charting.Series series = chart.Series[0];
                series.Points.Clear();
                //chart.ChartAreas[0].AxisX.Minimum = double.NaN;
                //chart.ChartAreas[0].AxisX.Maximum = double.NaN;
            });
        }
        async Task DrawR(int index, double r)
        {
            //画图
            await Task.Yield();
            await Task.Factory.StartNew(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    System.Windows.Forms.DataVisualization.Charting.Series series = chart.Series[index];
                    series.Points.AddY(r * 10000);
                    double max = series.Points.Max(p => p.YValues[0]);
                    double min = series.Points.Min(p => p.YValues[0]);
                    if (max != min)
                    {
                        double range = (max - min) / 10;
                        chart.ChartAreas[0].AxisY.Minimum = min - range;
                        chart.ChartAreas[0].AxisY.Maximum = max + range;
                    }
                });
            });
        }

        async Task Draw2(double[] data)
        {
            var chart = chart2;
            //画图
            await Task.Yield();
            await Task.Factory.StartNew(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    System.Windows.Forms.DataVisualization.Charting.Series series = chart.Series[0];

                    series.Points.Clear();
                    for (int i = 0; i < data.Count(); i++)
                    {
                        series.Points.AddXY(i, data[i]);
                    }

                    double max = series.Points.Max(p => p.YValues[0]);
                    double min = series.Points.Min(p => p.YValues[0]);
                    if (max != min)
                    {
                        double range = (max - min) / 10;
                        chart.ChartAreas[0].AxisY.Minimum = min - range;
                        chart.ChartAreas[0].AxisY.Maximum = max + range;
                    }
                });
            });
        }


        async Task Chart1DrawData(int index, int[] data)
        {
            var chart = chart1;
            await Task.Yield();
            //画图
            await Task.Factory.StartNew(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    System.Windows.Forms.DataVisualization.Charting.Series series = chart.Series[index];
                    series.Points.Clear();
                    for (int i = 0; i < data.Count(); i++)
                    {
                        if (Misc.MyBase.ISVALIDATA(data[i]))
                            series.Points.AddXY(i, data[i]);
                    }
                    //if (series.Points.Count() > 0)
                    //{
                    //    double max = series.Points.Max(p => p.YValues[0]);
                    //    double min = series.Points.Min(p => p.YValues[0]);
                    //    if (max != min)
                    //    {
                    //        double range = (max - min) / 10;
                    //        chart.ChartAreas[0].AxisY.Minimum = min - range;
                    //        chart.ChartAreas[0].AxisY.Maximum = max + range;
                    //    }
                    //}
                });
            });
        }

        async Task Chart2DrawData(int index, int[] data)
        {
            var chart = chart2;
            await Task.Yield();
            //画图
            await Task.Factory.StartNew(() =>
            {
                App.Current.Dispatcher.Invoke(() =>
                {
                    System.Windows.Forms.DataVisualization.Charting.Series series = chart.Series[index];
                    series.Points.Clear();
                    for (int i = 0; i < data.Count(); i++)
                    {
                        if (Misc.MyBase.ISVALIDATA(data[i]))
                            series.Points.AddXY(i, data[i]);
                    }
                    //if (series.Points.Count() > 0)
                    //{
                    //    double max = series.Points.Max(p => p.YValues[0]);
                    //    double min = series.Points.Min(p => p.YValues[0]);
                    //    if (max != min)
                    //    {
                    //        double range = (max - min) / 10;
                    //        chart.ChartAreas[0].AxisY.Minimum = min - range;
                    //        chart.ChartAreas[0].AxisY.Maximum = max + range;
                    //    }
                    //}
                });
            });
        }

        async void GetTarget()
        {

            int[] sum = new int[1000];
            int[] cnt = new int[1000];
            int[] targets = new int[1000];

            for (int i = 0; i < 4; i++)
            {
                
                var Xs = gridAdvAnalyzeCells[i].units;
                var datas = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);

                for (int j = 0; j < 1000; j++)
                {
                    if (Misc.MyBase.ISVALIDATA(datas[j]))
                    {
                        sum[j] += datas[j];
                        cnt[j]++;
                    }
                }
            }

            for (int j = 0; j < 1000; j++)
            {
                if (cnt[j] > 0)
                {
                    targets[j] = sum[j] / cnt[j];
                }
                else
                {
                    targets[j] = Misc.MyBase.NULL_VALUE;
                }
            }
            Target = targets;

            await Chart1DrawData(0, Target);
            await Chart2DrawData(0, Target);
        }
        async void ManualCal()
        {
            if (SampleCellIdx < 0)
                SampleCellIdx = 0;
            else if (SampleCellIdx >= CellCnt)
                SampleCellIdx = CellCnt - 1;

            int cal_cell_idx = SampleCellIdx;
            Speed = gridAdvAnalyzeCells[cal_cell_idx].speed;
            //1. 找中间的图

            var Xs = gridAdvAnalyzeCells[cal_cell_idx].units;
            var orgs0 = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);


            await Chart1DrawData(1, orgs0);
            await Chart2DrawData(1, orgs0);
            //2. 算出相关性
            R = Misc.MyMath.Correl(Target, orgs0);


            if (Ks.Sum() != 1)
            {
                Ks[4] = 1 - (Ks.Sum() - Ks[4]);
            }
            Filter2(gridAdvAnalyzeCells[cal_cell_idx].units, out Xs, Ks);
            var ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
            CurrR = Misc.MyMath.Correl(Target, ad_x);

            await DrawR(0, CurrR);
            await Chart1DrawData(2, ad_x);
            int groupIdx = GetGroupIdxFromCellIdx(SampleCellIdx);

            int[] group_ad = CalGroupDataAvg(groupIdx);
            await Chart2DrawData(2, group_ad);


            group_ad = CalGroupData(groupIdx);
            CurrGroupR = Misc.MyMath.Correl(Target, group_ad);
            await Chart1DrawData(3, group_ad);
            await Chart2DrawData(3, group_ad);
            //await Draw2(gridAdvAnalyzeCells.Select(c => Math.Abs(c.speed)).ToArray());


        }

        private async void AutoCal()
        {
            if (SampleCellIdx < 4)
                SampleCellIdx = 4;
            else if (SampleCellIdx >= CellCnt)
                SampleCellIdx = CellCnt - 1;

            int cal_cell_idx = SampleCellIdx;

            //1. 找中间的图
            var Xs = gridAdvAnalyzeCells[cal_cell_idx].units;
            var orgs0 = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
            await Chart1DrawData(1, orgs0);

            //2. 算出相关性
            R = Misc.MyMath.Correl(Target, orgs0);

            DrawClear();
            Ks[0] = 1;
            for (int i = 0; i < 4; i++)
            {
                await AutoSearchKn(cal_cell_idx, 0, Ks[i], 0.1, 0.000001, Ks.Take(i).ToArray());
            }

            int groupIdx = GetGroupIdxFromCellIdx(SampleCellIdx);
            int[] group_ad = CalGroupData(groupIdx);
            CurrGroupR = Misc.MyMath.Correl(Target, group_ad);
            await Chart1DrawData(3, group_ad);

            //await AutoSearchKn(cal_cell_idx, 0, 1, 0.1, 0.000001);

            //await AutoSearchKn(cal_cell_idx, 0, Ks[1], 0.1, 0.000001, Ks.Take(1).ToArray());

            //await AutoSearchKn(cal_cell_idx, 0, Ks[2], 0.1, 0.000001, Ks.Take(2).ToArray());

            //await AutoSearchKn(cal_cell_idx, 0, Ks[3], 0.1, 0.000001, Ks.Take(3).ToArray());
        }

        private async void AutoCal2()
        {
            
            if (SampleCellIdx < 4)
                SampleCellIdx = 4;
            else if (SampleCellIdx >= CellCnt)
                SampleCellIdx = CellCnt - 1;

            int cal_cell_idx = SampleCellIdx;

            //1. 找中间的图
            var Xs = gridAdvAnalyzeCells[cal_cell_idx].units;
            var orgs0 = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
            await Chart1DrawData(1, orgs0);

            //2. 算出相关性
            R = Misc.MyMath.Correl(Target, orgs0);

            DrawClear();
            await AutoSearchKn2(cal_cell_idx, 0.000001, Ks.ToArray());

        }
        async Task<double> AutoSearchKn(int cal_cell_idx, double min, double max, double step, double min_step, params double[] kn)
        {
            double[] Ks = new double[5];
            int cnt = kn.Count();
            if (cnt > 3)
            {
                throw new Exception("AutoSearchKn 输出 参数太多");
            }
            double k_sum = 0;
            for (int i = 0; i < cnt; i++)
            {
                Ks[i] = kn[i];
                k_sum += kn[i];
            }

            double max_r = -1;
            double best_k = -1;
            int[] ad_x = null;
            for (double k = max; k >= min; k -= step)
            {
                Ks[cnt] = k;
                Ks[cnt + 1] = 1 - k_sum - Ks[cnt];

                Filter2(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs, Ks[0], Ks[1], Ks[2], Ks[3], Ks[4]);
                
                ad_x = TimeGridAdvHelperExt.ToGrid(Xs.AdList, Xs.PosList, flyad.PosOfGrid, flyad.GridLen);
                double r = Misc.MyMath.Correl(Target, ad_x);
                if (r > max_r)
                {
                    max_r = r;
                    CurrR = max_r;
                    best_k = k;
                    for (int i = 0; i < Ks.Count(); i++)
                    {
                        this.Ks[i] = Ks[i];
                    }
                }
            }
            if (ad_x != null)
            {
                await DrawR(0, max_r);
                await Chart1DrawData(2, ad_x);
            }
            if (step <= min_step)
                return best_k;

            step = step / 10;
            double next_min = best_k - step * 2;
            double next_max = best_k + step * 2;
            if (next_max <= min)
                return best_k;
            if (next_min >= max)
                return best_k;
            if (next_min < min)
                next_min = min;
            if (next_max > max)
                next_max = max;
            return await AutoSearchKn(cal_cell_idx, next_min, next_max, step / 10, min_step, kn);
        }


        async Task AutoSearchKn2(int cal_cell_idx, double step, double[] Ks)
        {
            if (Ks.Count() != 5)
            {
                throw new Exception("AutoSearchKn2 初始值数量不为5");
            }
            int step_i = 0;
            int[] ad_x;
            while (true)
            {
                Filter2Avg(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs0, Ks);
                ad_x = TimeGridAdvHelperExt.ToGrid(Xs0.AdList, Xs0.PosList, flyad.PosOfGrid, flyad.GridLen);
                double r0 = Misc.MyMath.Correl(Target, ad_x);

                bool hasChanged = false;
                double[] ks = Ks.Clone() as double[];
                double r = r0;
                await Task.Factory.StartNew(() =>
                {
                    //每个参数改变 step, 确定方向
                    for (int i = 0; i < Ks.Count(); i++)
                    {
                        double curr_step = step;
                        double r1;
                        double r2;
                        int[] ad_x1;
                        int[] ad_x2;
                        while (true)
                        {
                            ks[i] = Ks[i] + curr_step;
                            Filter2Avg(gridAdvAnalyzeCells[cal_cell_idx].units, out var Xs1, ks);
                            ad_x1 = TimeGridAdvHelperExt.ToGrid(Xs1.AdList, Xs1.PosList, flyad.PosOfGrid, flyad.GridLen);
                            
                            r1 = Misc.MyMath.Correl(Target, ad_x1);


                            ks[i] = Ks[i] - curr_step;
                            Filter2Avg(gridAdvAnalyzeCells[cal_cell_idx].units, out Xs1, ks);
                            
                            ad_x2 = TimeGridAdvHelperExt.ToGrid(Xs1.AdList, Xs1.PosList, flyad.PosOfGrid, flyad.GridLen);
                            r2 = Misc.MyMath.Correl(Target, ad_x2);

                            if ((r1 == r0) || (r2 == r0))
                            {
                                //居然没有变化，把step翻倍
                                curr_step *= 1.5;
                            }
                            else
                            {
                                //有变化了
                                break;
                            }
                        }

                        if (r1 > r0)
                        {
                            //方向正确
                            ks[i] = Ks[i] + curr_step;
                            hasChanged = true;
                            r = r1;
                            ad_x = ad_x1;
                            continue;
                        }
                        else if (r2 > r0)
                        {
                            //方向正确
                            ks[i] = Ks[i] - curr_step;
                            hasChanged = true;
                            r = r2;
                            ad_x = ad_x2;
                            continue;
                        }
                        else
                        {
                            //方向错误，回到以前
                            ks[i] = Ks[i];
                        }
                    }
                });

                step_i++;
                CurrR = r;
                //if(step_i%10==0)
                await DrawR(0, r);

                ks.CopyTo(Ks, 0);
                //K1 = Ks[0];
                //K2 = Ks[1];
                //K3 = Ks[2];
                //K4 = Ks[3];
                //K5 = Ks[4];

                Kp2Ks(ks, out double[] kkkkk);
                for (int i = 0; i < kkkkk.Count(); i++)
                {
                    this.Ks[i] = kkkkk[i];
                };
                if (!hasChanged)
                {
                    //已经计算完毕
                    break;
                }
            }
            if (ad_x != null)
            {
                await Chart1DrawData(2, ad_x);
            }
        }



        /// <summary>
        /// 一阶滤波 Y(n)=k1*X(n) + k2*Y(n-1) 
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        /// <param name=""></param>
        void Filter1(TimeGridAdv2EventArgs Ys, out TimeGridAdv2EventArgs Xs, double k1)
        {
            double k2 = 1 - k1;
            Xs = new TimeGridAdv2EventArgs()
            {
                AdList = new List<int>(),
                PosList = Ys.PosList.ToList(),
                EndTime = Ys.EndTime,
                Direction = Ys.Direction,
                Marker = Ys.Marker
            };
            for (int i = 0; i < Ys.AdList.Count(); i++)
            {
                double y = Ys.AdList[i - 0];
                double y_1 = i >= 1 ? Ys.AdList[i - 1] : y;
                double x = (y - k2 * y_1) / k1;

                Xs.AdList.Add((int)x);
            }
        }

        /// <summary>
        /// 二阶滤波 Y(n)=k1*X(n) + k2*Y(n-1) + k3*X(n-1)+ k4*Y(n-2) + k5*X(n-2)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        /// <param name=""></param>
        void Filter2(TimeGridAdv2EventArgs Ys, out TimeGridAdv2EventArgs Xs, double k1, double k2, double k3, double k4, double k5)
        {
            Xs = new TimeGridAdv2EventArgs()
            {
                AdList = new List<int>(),
                PosList = Ys.PosList.ToList(),
                EndTime = Ys.EndTime,
                Direction = Ys.Direction,
                Marker = Ys.Marker
            };
            for (int i = 0; i < Ys.AdList.Count(); i++)
            {
                double y = Ys.AdList[i - 0];
                double y_1 = i >= 1 ? Ys.AdList[i - 1] : y;
                double y_2 = i >= 2 ? Ys.AdList[i - 2] : y_1;

                double x_1 = i >= 1 ? Xs.AdList[i - 1] : y_1;
                double x_2 = i >= 2 ? Xs.AdList[i - 2] : x_1;

                double x = (y - (k2 * y_1 + k3 * x_1 + k4 * y_2 + k5 * x_2)) / k1;
                Xs.AdList.Add((int)x);
            }
        }

        /// <summary>
        /// 二阶滤波 Y(n)=k1*X(n) + k2*Y(n-1) + k3*X(n-1)+ k4*Y(n-2) + k5*X(n-2)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        /// <param name=""></param>
        void Filter2(TimeGridAdv2EventArgs Ys, out TimeGridAdv2EventArgs Xs, IEnumerable<double> ks)
        {
            Xs = new TimeGridAdv2EventArgs()
            {
                AdList = new List<int>(),
                PosList = Ys.PosList.ToList(),
                EndTime = Ys.EndTime,
                Direction = Ys.Direction,
                Marker = Ys.Marker
            };
            for (int i = 0; i < Ys.AdList.Count(); i++)
            {
                double y = Ys.AdList[i - 0];
                double y_1 = i >= 1 ? Ys.AdList[i - 1] : y;
                double y_2 = i >= 2 ? Ys.AdList[i - 2] : y_1;

                double x_1 = i >= 1 ? Xs.AdList[i - 1] : y_1;
                double x_2 = i >= 2 ? Xs.AdList[i - 2] : x_1;

                double x = (y - (ks.ElementAt(1) * y_1 + ks.ElementAt(2) * x_1 + ks.ElementAt(3) * y_2 + ks.ElementAt(4) * x_2)) / ks.ElementAt(0);

                Xs.AdList.Add((int)x);
            }
        }

        void Kp2Ks(double[] kp, out double[] Ks)
        {
            Ks = new double[5];

            if (kp.Count() != 5)
                throw new Exception("Filter2Avg kp.Count()!=5");
            if (kp.All(p => p == 0))
            {
                for (int i = 0; i < 5; i++)
                    Ks[i] = 1.0 / 5;
            }
            else
            {
                for (int i = 0; i < 5; i++)
                    Ks[i] = kp[i] / kp.Sum();
            }
        }
        /// <summary>
        /// 二阶滤波 Y(n)=k1*X(n) + k2*Y(n-1) + k3*X(n-1)+ k4*Y(n-2) + k5*X(n-2)
        /// </summary>
        /// <param name="y"></param>
        /// <param name="x"></param>
        /// <param name=""></param>
        void Filter2Avg(TimeGridAdv2EventArgs Ys, out TimeGridAdv2EventArgs Xs, double[] kp)
        {
            Kp2Ks(kp, out double[] Ks);
            Xs = new TimeGridAdv2EventArgs()
            {
                AdList = new List<int>(),
                PosList = Ys.PosList.ToList(),
                EndTime = Ys.EndTime,
                Direction = Ys.Direction,
                Marker = Ys.Marker
            };
            for (int i = 0; i < Ys.AdList.Count(); i++)
            {
                double y = Ys.AdList[i - 0];
                double y_1 = i >= 1 ? Ys.AdList[i - 1] : y;
                double y_2 = i >= 2 ? Ys.AdList[i - 2] : y_1;

                double x_1 = i >= 1 ? Xs.AdList[i - 1] : y_1;
                double x_2 = i >= 2 ? Xs.AdList[i - 2] : x_1;

                double x = (y - (Ks[1] * y_1 + Ks[2] * x_1 + Ks[3] * y_2 + Ks[4] * x_2)) / Ks[0];
                Xs.AdList.Add((int)x);
            }
        }



    }
    public class GridAdvAnalyzeCell
    {
        public TimeGridAdv2EventArgs units;
        public double speed;// 平均速度


    }
    public class GridAdvAnalyzeCellGroup
    {
        public List<int> fCellIdxs = new List<int>();
        public List<int> bCellIdxs = new List<int>();
        public double speed = 0;
        public Misc.Range range = new Misc.Range();
    }
}
