using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Misc;
using System.Data;
using System.Xml;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
namespace FLY.Thick.Base.Server
{

    public class BoltMapImg : IBoltMapService, INotifyPropertyChanged, Misc.ISaveToXml, IBoltMapBase
    {
        #region 成员变量

        #region 数据文件需要保存的数据项


        private int _firstBoltNo;
        /// <summary>
        /// 1st 分区号,之后的不断加1
        /// </summary>
        public int FirstBoltNo 
        {
            get { return _firstBoltNo; }
            set {
                _firstBoltNo = value;
                NotifyPropertyChanged("FirstBoltNo");
            }
        }

        private BORDER_TYPE bordertype;
        /// <summary>
        /// 找边界,边界类型
        /// </summary>
        public BORDER_TYPE BorderType 
        {
            get { return bordertype; }
            set {
                if (bordertype != value) 
                {
                    bordertype = value;
                    NotifyPropertyChanged("BorderType");
                }
            }
        }
        
        private int borderboltno_b;
        /// <summary>
        /// 开始边界分区号 
        /// </summary>
        public int BorderBoltNo_B 
        {
            get { return borderboltno_b; }
            set
            {
                if (borderboltno_b != value)
                {
                    borderboltno_b = value;
                    NotifyPropertyChanged("BorderBoltNo_B");
                }
            }
        }
        private int borderboltno_e;
        /// <summary>
        /// 结束边界分区号
        /// </summary>
        public int BorderBoltNo_E
        {
            get { return borderboltno_e; }
            set
            {
                if (borderboltno_e != value)
                {
                    borderboltno_e = value;
                    NotifyPropertyChanged("BorderBoltNo_E");
                }
            }
        }
        public ObservableCollection<Range> _bolts = new ObservableCollection<Range>();
        public ObservableCollection<Range> Bolts
        {
            get
            {
                return _bolts;
            }
        }
        private int smooth;
        public int Smooth
        {
            get { return smooth; }
            set {
                if (smooth != value) 
                {
                    smooth = value;
                    NotifyPropertyChanged("Smooth");
                }
            }
        }

        
        #endregion

        #region 只用于描述 Bolts,没什么用
        private int lastboltno;
        /// <summary>
        /// 最后一个分区号
        /// </summary>
        public int LastBoltNo { 
            get {
                return lastboltno;
            }
            protected set
            {
                if (lastboltno != value) 
                {
                    lastboltno = value;
                    NotifyPropertyChanged("LastBoltNo");
                }
            }
        }
        private int boltinterval;
        /// <summary>
        /// 平均分区间隔
        /// </summary>
        public int BoltInterval { 
            get 
            {
                return boltinterval;
            }
            set {
                if (boltinterval != value) 
                {
                    boltinterval = value;
                    NotifyPropertyChanged("BoltInterval");
                }
            }
        }
        private int boltwidth;
        /// <summary>
        /// 平均分区宽度
        /// </summary>
        public int BoltWidth {
            get {
                return boltwidth;
            }
            protected set {
                if (boltwidth != value) 
                {
                    boltwidth = value;
                    NotifyPropertyChanged("BoltWidth");
                }
            }
        }
        private int posbegin;
        /// <summary>
        /// 脉冲范围 开始
        /// </summary>
        public int PosBegin {
            get {
                return posbegin;
            }
            protected set {
                if (posbegin != value) 
                {
                    posbegin = value;
                    NotifyPropertyChanged("PosBegin");
                }
            }
        }
        private int posend;
        /// <summary>
        /// 脉冲范围 结束
        /// </summary>
        public int PosEnd { 
            get {
            return posend;
            }
            protected set {
                if (posend != value) 
                {
                    posend = value;
                    NotifyPropertyChanged("PosEnd");
                }
            }
        }
        #endregion


        #endregion
        /// <summary>
        /// 动态分区
        /// </summary>
        private DynBoltAD dyn;
        private BoltMapHelper helper;
        public event ActiveEventHandler ActiveEvent;

        public BoltMapImg()
        {
            dyn = new DynBoltAD(this);
            helper = new BoltMapHelper(this);
        }

        public BoltMapImg(string param_path)
        {
            if (!string.IsNullOrEmpty(param_path))
                Path = param_path;
            else
                Path = "boltmap.xml";

            //设置默认值----------------------------------------------------------------
            EasyCreate(1, 50, 9000);
            //-------------------------------------------------------------------------------
            if (!Load(null))
            {

            }
            apply2();
        }
        
        static BoltMapImg() 
        {
            Misc.SaveToXmlHepler.Regist(typeof(BoltMapImg));
            
        }

        private void apply2() 
        {
            LastBoltNo = FirstBoltNo + Bolts.Count() - 1;
            PosBegin = Bolts.First().Begin;
            PosEnd = Bolts.Last().End;
            BoltWidth = (int)Bolts.Average((r) => r.Width);
            List<int> buf = new List<int>();
            for (int i = 1; i < Bolts.Count(); i++)
            {
                int interval = Bolts[i].Mid - Bolts[i - 1].Mid;
                buf.Add(interval);
            }
            BoltInterval = (int)buf.Average();

            //检测 膜边界参数
            if (BorderBoltNo_B < FirstBoltNo)
                BorderBoltNo_B = FirstBoltNo;
            if (BorderBoltNo_E > LastBoltNo)
                BorderBoltNo_E = LastBoltNo;
            if (BorderBoltNo_B > BorderBoltNo_E) 
            {
                BorderBoltNo_B = FirstBoltNo;
                BorderBoltNo_E = LastBoltNo;
            }
        }
        public void Apply() 
        {
            apply2();
            Save(null);
            //触发事件!!!!
            //TODO
            if (ActiveEvent != null)
                ActiveEvent(this);
        }
        public void ApplyWithoutSave() 
        {
            apply2();
            //触发事件!!!!
            //TODO
            if (ActiveEvent != null)
                ActiveEvent(this); 
        }
        public void ApplyBorder() 
        {
            Save(null);
        }
        public void Clear()
        {
            Bolts.Clear();
        }

        public int NBolts
        {
            get
            {
                return Bolts.Count;
            }
        }

        public void EasyCreate(int boltno1st, int boltcnt, int poslen) 
        {
            Bolts.Clear();
            int b = 0;
            for (int i = 0; i < boltcnt; i++)
            {
                Bolts.Add(new Range() { Begin = b, End = b + poslen / boltcnt - 1 });
                b = Bolts.Last().End + 1;
            }
            FirstBoltNo = boltno1st;
            BorderType = BORDER_TYPE.Null;
            BorderBoltNo_B = boltno1st;
            BorderBoltNo_E = boltno1st + boltcnt - 1;
            //Apply();
        }
        public void EasyCreate2(int boltno1st, int boltwidth, int poslen)
        {
            Bolts.Clear();
            int b = 0;
            int e = b + boltwidth-1;
            while (e < poslen) 
            {
                Bolts.Add(new Range() { Begin = b, End = e });
                b = e + 1;
                e = b + boltwidth - 1;
                
            }
            FirstBoltNo = boltno1st;
            BorderType = BORDER_TYPE.Null;
            BorderBoltNo_B = boltno1st;
            BorderBoltNo_E = boltno1st + Bolts.Count - 1;
            //Apply();
        }


        #region INotifyPropertyChanged 成员
        protected void NotifyPropertyChanged(string propertyName) 
        {
            if (PropertyChanged != null) 
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region ISaveToXml 成员

        public string[] GetSavePropertyNames()
        {
            return new string[]{
                "FirstBoltNo",
                "Bolts",
                "BorderType",
                "BorderBoltNo_B",
                "BorderBoltNo_E",
                "BorderBoltNo_M",
                "Smooth"
            };
        }

        #endregion

        #region ITDParam 成员

        public string FileName
        {
            get;
            set;
        }

        public string DirectoryName
        {
            get;
            set;
        }

        public string Path
        {
            get
            {
                if (string.IsNullOrEmpty(DirectoryName))
                    return FileName;
                else
                    return DirectoryName + @"\" + FileName;
            }
            set
            {
                DirectoryName = System.IO.Path.GetDirectoryName(value);
                FileName = System.IO.Path.GetFileName(value);
            }
        }

        public bool Load(string name)
        {
            if (name != null)
                FileName = name;

            return Misc.SaveToXmlHepler.Load(Path, this);
        }

        public bool Save(string name)
        {
            if (name != null)
                FileName = name;

            return Misc.SaveToXmlHepler.Save(Path, this);
        }

        #endregion

        #region IBoltMapBase
        public void GetBolts(out int boltno1st, out IEnumerable<Range> bolts)
        {
            boltno1st = FirstBoltNo;
            bolts = Bolts;
        }

        public void GetScanRange(Range boltno, out int posBegin, out int posEnd)
        {
            int boltindex = boltno.Begin - FirstBoltNo;
            if (boltindex < 0)
                boltindex = 0;
            else if (boltindex >= NBolts)
                boltindex = NBolts - 1;
            posBegin = Bolts[boltindex].Begin;

            boltindex = boltno.End - FirstBoltNo;
            if (boltindex < 0)
                boltindex = 0;
            else if (boltindex >= NBolts)
                boltindex = NBolts - 1;
            posEnd = Bolts[boltindex].End;
        }

        public int GetBoltIndex_fromPos(int pos)
        {
            return pos / BoltWidth;
        }
        #region 用于动态生成分区数据
        public void InitBoltAD()
        {
            dyn.Init();
        }
        public bool UpdateBoltAD(int[] data, int start_pos, int posOfGrid, Misc.DIRECTION direction, out int start_boltIndex, out int[] boltAD)
        {
            return dyn.UpdateBoltAD(data, start_pos, posOfGrid, direction, out start_boltIndex, out boltAD);
        }
        #endregion

        #region 根据边界调整分区
        public void InitExChange()
        {
            this.helper.InitExChange();
        }
        public void CalExChange(Misc.DIRECTION direction, Range bolt_r)
        {
            CalExChange(direction, bolt_r.Begin, bolt_r.End);
        }
        public void CalExChange(Misc.DIRECTION direction, int borderPosBegin, int borderPosEnd)
        {
            int idx = 0;
            if (direction == Misc.DIRECTION.BACKWARD)
                idx = 1;
            FLY.Thick.Base.Server.BoltMapHelper.ExChange exchange = helper.mExChange[idx];
            exchange.Init();

            int borderPosMid = (borderPosBegin + borderPosEnd) / 2;

            int org_borderPosBegin;
            int org_borderPosEnd;
            int org_borderPosMid;

            int borderboltindex_b = BorderBoltNo_B - FirstBoltNo;
            int borderboltindex_e = BorderBoltNo_E - FirstBoltNo;



            if (borderboltindex_b < 0)
                borderboltindex_b = 0;
            else if (borderboltindex_b >= NBolts)
                borderboltindex_b = 0;

            if (borderboltindex_e < borderboltindex_b)
                borderboltindex_e = NBolts;
            else if (borderboltindex_e >= NBolts)
                borderboltindex_e = NBolts;


            switch (BorderType)
            {
                case BORDER_TYPE.Null:
                    {

                    } break;
                case BORDER_TYPE.BeginEnd:
                    {

                        org_borderPosBegin = Bolts[borderboltindex_b].Begin;
                        org_borderPosEnd = Bolts[borderboltindex_e].End;
                        exchange.Amp = ((double)(borderPosEnd - borderPosBegin)) / (org_borderPosEnd - org_borderPosBegin);

                        exchange.Offset = (int)(borderPosBegin - org_borderPosBegin * exchange.Amp);

                    } break;
                case BORDER_TYPE.Begin:
                    {
                        org_borderPosBegin = Bolts[borderboltindex_b].Begin;

                        exchange.Offset = (int)(borderPosBegin - org_borderPosBegin * exchange.Amp);
                    } break;
                case BORDER_TYPE.End:
                    {
                        org_borderPosEnd = Bolts[borderboltindex_e].End;

                        exchange.Offset = (int)(borderPosEnd - org_borderPosEnd * exchange.Amp);
                    } break;
                case BORDER_TYPE.Mid:
                    {

                        org_borderPosMid = (Bolts[borderboltindex_b].Begin + Bolts[borderboltindex_e].End) / 2;

                        exchange.Offset = (int)(borderPosMid - org_borderPosMid * exchange.Amp);
                    } break;
            }

        }
        public int PositionExchange(Misc.DIRECTION direction, int position)
        {
            return helper.PositionExchange(direction, position);
        }
        public int BoltExchange(Misc.DIRECTION direction, int bolt_pos)
        {
            return helper.BoltExchange(direction, bolt_pos);
        }
        #endregion

        public int[] Map(Misc.DIRECTION direction, int posBegin, int posOfGrid, int[] dat)
        {
            return helper.Map(direction, posBegin, posOfGrid, dat);
        }

        #endregion
    }

    public class DynBoltAD
    {
        #region 动态扫描时,提前算分区的AD值,正常时 通过 grid数据划分的
        private const int NBOLTS_AD = 20;
        private int[] boltADIndex = new int[NBOLTS_AD];
        private int[] boltADSum = new int[NBOLTS_AD];
        private int[] boltADCnt = new int[NBOLTS_AD];

        #endregion
        IBoltMapBase boltmap;
        public DynBoltAD(IBoltMapBase boltmap)
        {
            this.boltmap = boltmap;
        }

        public void Init()
        {
            for (int i = 1; i < NBOLTS_AD; i++)
            {
                boltADIndex[i] = -1;
                boltADSum[i] = boltADCnt[i] = 0;
            }
        }

        private bool UpdateBoltAD(int ad, int position, Misc.DIRECTION direction, out int boltIndex, out int boltAD)
        {
            boltAD = Misc.MyBase.NULL_VALUE;
            boltIndex = -1;
            bool ret = false;
            int min, max;
            int i, j;

            int curr_boltno1st;//当前分区表 1st分区号
            IEnumerable<Range> curr_bolts;//当前分区表
            int curr_nbolts;//当前分区总数
            boltmap.GetBolts(out curr_boltno1st, out curr_bolts);
            curr_nbolts = curr_bolts.Count();


            
            position = boltmap.PositionExchange(direction, position);

            switch (direction)
            {
                case Misc.DIRECTION.FORWARD:
                    max = int.MinValue;
                    for (i = 1; i < NBOLTS_AD; i++)
                    {
                        int end;
                        if (boltADIndex[i] < 0) continue;
                        if (boltADIndex[i] >= curr_nbolts)
                        {
                            //这个是有问题的
                            continue;
                        }
                        if (boltADIndex[i] > max)
                            max = boltADIndex[i];
                        
                        end = curr_bolts.ElementAt(boltADIndex[i]).End;

                        if (position > end)
                        {
                            int temp = Misc.MyBase.NULL_VALUE;
                            if (boltADCnt[i] > 0)
                                temp = boltADSum[i] / boltADCnt[i];

                            boltAD = temp;
                            boltIndex = boltADIndex[i];
                            ret = true;

                            boltADIndex[i] = -1;
                            boltADSum[i] = boltADCnt[i] = 0;
                        }
                        else
                        {
                            if (ad != Misc.MyBase.NULL_VALUE)
                            {
                                boltADSum[i] += ad;
                                boltADCnt[i]++;
                            }
                        }
                    }

                    if (max == int.MinValue)
                    {
                        FindBolt(position);
                    }
                    else
                    {
                        for (i = 1; max + i < curr_nbolts; i++)
                        {
                            if (position > curr_bolts.ElementAt(max + i).Begin)
                            {
                                if ((j = GetFreeBoltAD()) < 0)
                                {
                                    break;
                                }
                                else
                                {
                                    boltADIndex[j] = max + i;

                                    if (ad != Misc.MyBase.NULL_VALUE)
                                    {
                                        boltADCnt[j] = 1;
                                        boltADSum[j] = ad;
                                    }
                                    else
                                    {
                                        boltADCnt[j] = 0;
                                        boltADSum[j] = 0;
                                    }
                                }
                            }
                            else
                                break;
                        }
                    }
                    break;
                case Misc.DIRECTION.BACKWARD:
                    min = int.MaxValue;
                    for (i = 1; i < NBOLTS_AD; i++)
                    {
                        if (boltADIndex[i] < 0) continue;
                        if (boltADIndex[i] >= curr_nbolts)
                        {
                            //这个是有问题的
                            continue;
                        }
                        if (boltADIndex[i] < min) 
                            min = boltADIndex[i];
                        if ((position < (curr_bolts.ElementAt(boltADIndex[i]).Begin)) || (position <= 0))
                        {
                            int temp = Misc.MyBase.NULL_VALUE;
                            if (boltADCnt[i] > 0)
                            {
                                temp = boltADSum[i] / boltADCnt[i];
                            }

                            boltAD = temp;
                            boltIndex = boltADIndex[i];
                            ret = true;

                            boltADIndex[i] = -1;
                            boltADSum[i] = boltADCnt[i] = 0;


                        }
                        else
                        {
                            if (ad != Misc.MyBase.NULL_VALUE)
                            {
                                boltADSum[i] += ad;
                                boltADCnt[i]++;
                            }
                        }
                    }

                    if (min == int.MaxValue)
                        FindBolt(position);
                    else
                    {
                        for (i = 1; min - i >= 0; i++)
                        {
                            if (position < curr_bolts.ElementAt(min - i).End)
                            {
                                if ((j = GetFreeBoltAD()) < 0)
                                    break;
                                else
                                {

                                    boltADIndex[j] = min - i;
                                    if (ad != Misc.MyBase.NULL_VALUE)
                                    {
                                        boltADCnt[j] = 1;
                                        boltADSum[j] = ad;
                                    }
                                    else
                                    {
                                        boltADCnt[j] = 0;
                                        boltADSum[j] = 0;
                                    }
                                }
                            }
                            else
                                break;
                        }
                    }
                    break;
            }

            return ret;
        }
        

        private void FindBolt(int position)
        {
            int curr_boltno1st;//当前分区表 1st分区号
            IEnumerable<Range> curr_bolts;//当前分区表
            int curr_nbolts;
            boltmap.GetBolts(out curr_boltno1st, out curr_bolts);
            curr_nbolts = curr_bolts.Count();


            int i, j = 1;
            for (i = 0; i < curr_nbolts; i++)
            {
                if (position > (curr_bolts.ElementAt(i).End))
                    continue;
                if ((position < (curr_bolts.ElementAt(i).Begin)) || (position <= 0)) 
                    break;

                boltADIndex[j] = i;
                boltADSum[j] = boltADCnt[j] = 0;
                j++;
                if (j >= NBOLTS_AD) break;
            }
        }
        private int GetFreeBoltAD()
        {
            for (int i = 1; i < NBOLTS_AD; i++)
                if (boltADIndex[i] < 0)
                    return i;
            return -1;
        }

        public bool UpdateBoltAD(int[] data, int start_pos, int posOfGrid, Misc.DIRECTION direction, out int start_boltIndex, out int[] boltAD)
        {

            int nbolts = boltmap.NBolts;

            int start_grid = start_pos / posOfGrid;
            start_boltIndex = -1;
            List<int> boltdata = new List<int>();
            for (int i = 0; i < data.Length; i++)
            {
                int boltIndex;
                int boltad;
                bool ret = UpdateBoltAD(data[i], (start_grid + i) * posOfGrid, direction, out boltIndex, out boltad);
                if (ret == true)
                {
                    if (start_boltIndex == -1)
                        start_boltIndex = boltIndex;
                    boltdata.Add(boltad);
                }
            }
            if (boltdata.Count() == 0)
            {
                boltAD = null;
                return false;
            }

            start_boltIndex = GetInfoBoltIndex(start_boltIndex);

            while (start_boltIndex < 0 && boltdata.Count()>0)
            {
                boltdata.RemoveAt(0);
                start_boltIndex--;
            }

            while ((start_boltIndex + boltdata.Count() > nbolts) && boltdata.Count() > 0)
            {
                boltdata.RemoveAt(boltdata.Count() - 1);
            }

            boltAD = boltdata.ToArray();
            if (boltAD.Count() > 0)
                return true;
            return false;
        }

        /// <summary>
        /// 转换总分区表 的序号
        /// </summary>
        /// <param name="curr_boltindex">当前分区表的序号</param>
        /// <returns></returns>
        int GetInfoBoltIndex(int curr_boltindex)
        {
            int curr_boltno1st;
            IEnumerable<Range> curr_bolts;
            boltmap.GetBolts(out curr_boltno1st, out curr_bolts);

            int offset = curr_boltno1st - boltmap.FirstBoltNo;
            return curr_boltindex + offset;
        }
    }
    public class BoltMapHelper
    {
        IBoltMapBase boltmap;
        public BoltMapHelper(IBoltMapBase boltmap)
        {
            this.boltmap = boltmap;
        }



        public int[] Map(Misc.DIRECTION direction, int posBegin, int posOfGrid, int[] dat)
        {
            int boltno1st = boltmap.FirstBoltNo;
            int nbolts = boltmap.NBolts;

            int curr_boltno1st;//当前分区表 1st分区号
            IEnumerable<Range> curr_bolts;//当前分区表
            int curr_nbolts;
            boltmap.GetBolts(out curr_boltno1st, out curr_bolts);
            curr_nbolts = curr_bolts.Count();


            int[] frame = new int[curr_nbolts];
            int gridbegin = posBegin / posOfGrid;
            int len = dat.Length;

            for (int i = 0; i < curr_nbolts; i++)
            {
                int sum = 0;
                int cnt = 0;
                int total = 0;
                int j;

                int begin = curr_bolts.ElementAt(i).Begin;
                int end = curr_bolts.ElementAt(i).End;

                begin = boltmap.BoltExchange(direction, begin);
                end = boltmap.BoltExchange(direction, end);

                int begin_grid = begin / posOfGrid;
                int end_grid = end / posOfGrid;

                for (j = begin_grid; j <= end_grid; j++)
                {
                    int index = j - gridbegin;
                    if ((index >= 0) && (index < len))
                    {
                        if (Misc.MyBase.ISVALIDATA(dat[index]))
                        {
                            sum += dat[index];
                            cnt++;
                        }
                        total++;
                    }
                }
                //数据有效必须是 有效数据 多于 一个分区总数的 1/3 
                if (cnt > (total / 3))
                {
                    frame[i] = sum / cnt;
                }
                else
                {
                    frame[i] = Misc.MyBase.NULL_VALUE;
                }
            }







            //数据平滑
            int smooth = boltmap.Smooth;
            if (smooth < 0)
                smooth = 0;
            else if (smooth > 10)
                smooth = 10;
            int[] frame2;
            if (smooth > 0)
            {
                frame2 = new int[curr_nbolts];
                for (int i = 0; i < curr_nbolts; i++)
                {
                    int sum = 0;
                    int cnt = 0;
                    int index_b = i - smooth;
                    int index_e = i + smooth;
                    for (int j = index_b; j <= index_e; j++)
                    {
                        if ((j >= 0) && (j < curr_nbolts))
                        {
                            if (Misc.MyBase.ISVALIDATA(frame[j]))
                            {
                                sum += frame[j];
                                cnt++;
                            }
                        }
                    }
                    if (cnt > 0)
                    {
                        frame2[i] = sum / cnt;
                    }
                    else
                    {
                        frame2[i] = Misc.MyBase.NULL_VALUE;
                    }
                }
            }
            else
            {
                frame2 = frame;
            }


            frame = new int[nbolts];

            int offset = curr_boltno1st - boltno1st;
            for (int i = 0; i < nbolts; i++)
            {
                if (i < offset)
                {
                    frame[i] = Misc.MyBase.NULL_VALUE;
                }
                else if (i < offset + curr_nbolts)
                {
                    frame[i] = frame2[i - offset];
                }
                else
                {
                    frame[i] = Misc.MyBase.NULL_VALUE;
                }
            }
            return frame;
        }


        #region 根据边界调整分区
        public class ExChange
        {
            /// <summary>
            /// 平移
            /// </summary>
            public int Offset { get; set; }
            /// <summary>
            /// 比例
            /// </summary>
            public double Amp { get; set; } = 1;

            /// <summary>
            /// 初始化
            /// </summary>
            public void Init()
            {
                Offset = 0;
                Amp = 1;
            }
        }
        public ExChange[] mExChange = new ExChange[2] { new ExChange(), new ExChange() };
        public void InitExChange()
        {
            for (int i = 0; i < 2; i++)
            {
                ExChange exchange = mExChange[i];
                exchange.Init();
            }
        }
        public int PositionExchange(Misc.DIRECTION direction, int position)
        {
            int idx = 0;
            if (direction == Misc.DIRECTION.BACKWARD)
                idx = 1;
            ExChange exchange = mExChange[idx];
            return (int)((position - exchange.Offset) / exchange.Amp);
        }
        public int BoltExchange(Misc.DIRECTION direction, int bolt_pos)
        {
            int idx = 0;
            if (direction == Misc.DIRECTION.BACKWARD)
                idx = 1;
            ExChange exchange = mExChange[idx];
            return (int)(bolt_pos * exchange.Amp) + exchange.Offset;
        }
        #endregion
    }
}