using Misc; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlyADBase { public class TimeGridAdvHelper { /// /// AD数据池时间间隔为1.28ms, 肯定最少有一个数据 /// RList ADPool = new RList(60000); /// /// pos 数据池, 肯定最少有一个数据 /// RList PosPool = new RList(60000); /// /// 输入端口 数据池, 肯定最少有一个数据 /// RList IStatusPool = new RList(60000); public void Init() { Clear(); } /// /// 添加ad数据,且判断数据量是否够触发事件 /// /// /// public void AddAD(int[] ads, DateTime start_dt, double ts_ms) { //------------------------------------------------------------------------------------------ //AD数据添加 for (int i = 0; i < ads.Count(); i++) { DateTime dt = start_dt + TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * i * ts_ms)); ADPool.RAdd(new DataTimeUnit() { data = ads[i], dt = dt }); } } public void AddPos(int pos, DateTime time) { if (PosPool.Count() > 0) { if (time < PosPool.Last().dt) { //异常 //把前面的都删除 PosPool.Clear(); } else if (time == PosPool.Last().dt) { return; } } PosPool.RAdd(new DataTimeUnit() { data = pos, dt = time }); } public void AddIStatus(UInt16 istatus, int pos, DateTime time) { if (IStatusPool.Count() > 0) { if (time < IStatusPool.Last().dt) { //异常 //把前面的都删除 IStatusPool.Clear(); } } IStatusPool.RAdd(new DataTimeUnit2() { istatus = istatus, pos = pos, dt = time }); //也添加到 PosPool //AddPos(pos, time); } public void AddPos_Default(int pos, DateTime time) { if (PosPool.Count() == 0) { AddPos(pos, time); } } public void AddIStatus_Default(UInt16 istatus, int pos, DateTime time) { if (IStatusPool.Count() == 0) { AddIStatus(istatus, pos, time); } } public void Clear() { PosPool.Clear(); ADPool.Clear(); IStatusPool.Clear(); istatus_start_idx = -1; } /// /// 给定结束时间点,开始grid, 找到pos数据池 对应的开始序号 与 结束序号 /// /// 开始脉冲 /// 结束时间点 /// 输出 pos数据池开始序号 /// 输出 pos数据池结束序号 /// false 发生在数据池前面, true成功获取 bool GetIdxFromPosPool(int start_pos, DateTime endtime, out int start_idx, out int end_idx) { start_idx = -1; end_idx = -1; for (int i = 0; i < PosPool.Count(); i++) { int idx = PosPool.Count() - 1 - i; if (PosPool[idx].dt <= endtime) { //从这个点开始找 end_idx = idx; break; } } if (end_idx == -1) { //endtime 发生在过去很久以前 return false; } int pos_last = int.MinValue; int i_last = -1; for (int i = end_idx; i >= 0; i--) { int pos = PosPool[i].data; //if (pos == start_pos)//找到了!!!! //{ // pos_last = pos; // continue; //} if (pos_last == int.MinValue) { pos_last = pos; i_last = i; continue; } if (pos_last == pos) { continue; } if (Math.Abs(pos - start_pos) > Math.Abs(pos_last - start_pos)) { //越找越远, //上一个就是了 start_idx = i_last; return true; } else if (Math.Abs(pos - start_pos) == Math.Abs(pos_last - start_pos)) { //跨过了 start_idx = i_last; return true; } pos_last = pos; i_last = i; } //找完 start_idx = 0; return true; } /// /// 上一次查找istatus的序号 /// int istatus_start_idx = -1; /// /// 根据时间点,获取输入口状态 /// /// /// 用于加快查找速度 /// UInt16 GetIStatus(DateTime time) { int start_idx = istatus_start_idx; if (start_idx >= 0 && start_idx < IStatusPool.Count()) { for (int i = start_idx; i >= 0; i--) { int idx = i; if (time >= IStatusPool[idx].dt) { if (idx == start_idx)//有可能start_idx 位置 本来就在前面,看看后面再决定 { for (int j = start_idx + 1; j < IStatusPool.Count(); j++) { idx = j; if (time < IStatusPool[idx].dt) { //找到了 istatus_start_idx = idx - 1; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } //找到最后 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } //找到 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } } else { //没有以前的记录 //从列表的后面向前查找 for (int i = 0; i < IStatusPool.Count(); i++) { int idx = IStatusPool.Count() - 1 - i; if (time >= IStatusPool[idx].dt) { //找到 istatus_start_idx = idx; return (UInt16)IStatusPool[istatus_start_idx].istatus; } } } //在前面发生的!!! if (IStatusPool.Count() > 0) { istatus_start_idx = 0; return (UInt16)IStatusPool[istatus_start_idx].istatus; } else { //异常,一个数据都没有 istatus_start_idx = -1; return (UInt16)0xff; } } /// /// 根据时间点,获取输入口状态 /// /// /// 用于加快查找速度 /// UInt16 GetIStatus(DateTime time, out int istatus_idx) { UInt16 istatus = GetIStatus(time); istatus_idx = istatus_start_idx; return istatus; } /// /// 以 [idx,idx+1] 的比例, 给出 time 计算 pos /// /// /// /// int GetPos(DateTime time, int idx) { if (PosPool.Count() < 0) return int.MinValue; if (PosPool.Count() == 1) return PosPool[0].data; if (idx < 0) idx = 0; if (idx >= PosPool.Count()) idx = PosPool.Count() - 2; double d_pos = PosPool[idx].data - PosPool[idx + 1].data; TimeSpan ts = PosPool[idx].dt - PosPool[idx + 1].dt; double p = d_pos * (time - PosPool[idx + 1].dt).Ticks / ts.Ticks; return (int)(p + PosPool[idx + 1].data); } /// /// 获取时间对应的 位置点 /// /// /// int GetPos(DateTime dt) { int index = -1; for (int i = 0; i < PosPool.Count(); i++)//从后面开始查找 { int idx = PosPool.Count() - 1 - i; if (PosPool[idx].dt <= dt) { //找到了 index = idx; break; } } if (index == PosPool.Count() - 1) { index = index - 1; } else if (index == -1) { index = 0; } return GetPos(dt, index); } public List GetGridAdv(DateTime start_dt, DateTime end_dt) { List result = new List(); for (int i = 0; i < ADPool.Count(); i++) { int idx = ADPool.Count() - 1 - i; if (ADPool[idx].dt < start_dt) { break; } else if (ADPool[idx].dt <= end_dt) { GridAdvUnit u = new GridAdvUnit(); u.dt = ADPool[idx].dt; u.ad = ADPool[idx].data; u.pos = GetPos(u.dt); u.istatus = GetIStatus(u.dt); result.Add(u); } } result.Reverse(); return result; } #region 子功能,grid 的 istatus 变化 class gridistatuspush { public int istatus_no; public event GridIStatusEventHander GridIStatusEvent; public void Notify(object sender, GridIStatusEventArgs e) { GridIStatusEvent?.Invoke(sender, e); } public bool IsNoEvent() { if (GridIStatusEvent == null) return true; else return false; } } List mGridIStatusEventList = new List(); /// /// 添加事件 /// /// /// public void GridIStatusEventAdd(int istatus_no, GridIStatusEventHander func) { var gs = from _g in mGridIStatusEventList where _g.istatus_no == istatus_no select _g; gridistatuspush g; if (gs.Count() > 0) { g = gs.First(); g.GridIStatusEvent += func; } else { g = new gridistatuspush() { istatus_no = istatus_no }; g.GridIStatusEvent += func; mGridIStatusEventList.Add(g); } } /// /// 删除事件 /// /// /// public void GridIStatusEventDel(int istatus_no, GridIStatusEventHander func) { var gs = from _g in mGridIStatusEventList where _g.istatus_no == istatus_no select _g; gridistatuspush g; if (gs.Count() > 0) { g = gs.First(); g.GridIStatusEvent -= func; if (g.IsNoEvent()) { mGridIStatusEventList.Remove(g); } } } /// /// 触发GridIStatusEvent事件 /// /// /// /// /// /// public void NotifyGridIStatusEvent(DIRECTION direction, int pos_start, int pos_len, int marker, DateTime dt, object sender) { if (mGridIStatusEventList.Count() <= 0) return; int start_idx; int end_idx; int start_pos; int end_pos; if (direction == DIRECTION.FORWARD) { start_pos = pos_start; end_pos = pos_start + pos_len - 1; } else { start_pos = pos_start + pos_len - 1; end_pos = pos_start; } bool ret = GetIdxFromPosPool( start_pos, dt, out start_idx, out end_idx); if (ret == false)//异常 return; DateTime start_dt = PosPool[start_idx].dt; DateTime end_dt = dt; foreach (gridistatuspush g in mGridIStatusEventList) { List data0; List data1; GetIStatusRange( g.istatus_no, start_dt, end_dt, direction, start_pos, end_pos, out data0, out data1); g.Notify(sender, new GridIStatusEventArgs() { direction = direction, istatus_no = g.istatus_no, marker = marker, pos_start = pos_start, pos_len = pos_len, data_0 = data0, data_1 = data1 }); } } void GetIStatusRange( int istatus_no, DateTime start_dt, DateTime end_dt, DIRECTION direction, int start_pos, int end_pos, out List data0, out List data1) { data0 = new List(); data1 = new List(); istatus_start_idx = -1; int istatus_idx; UInt16 istatus = GetIStatus(start_dt, out istatus_idx); if (istatus_idx == -1)//异常,列表没有数据 { //全部都是1 if (direction == DIRECTION.FORWARD) data1.Add(new Range() { Begin = start_pos, End = end_pos }); else data1.Add(new Range() { Begin = end_pos, End = start_pos }); return; } bool istatus_no_b = Misc.MyBase.CHECKBIT(istatus, istatus_no ); Range r = new Range(); r.Begin = start_pos; for (int i = istatus_idx + 1; i < IStatusPool.Count(); i++) { istatus = IStatusPool[i].istatus; int pos = IStatusPool[i].pos; bool b = Misc.MyBase.CHECKBIT(istatus, istatus_no ); if (IStatusPool[i].dt >= end_dt) { //结束,这是最后!!! break; } else { if (b != istatus_no_b) { r.End = pos; if (istatus_no_b) data1.Add(r); else data0.Add(r); istatus_no_b = b; r = new Range(); r.Begin = pos; } } } r.End = end_pos; if (istatus_no_b) data1.Add(r); else data0.Add(r); if (direction == DIRECTION.FORWARD) { for (int i = 0; i < data0.Count(); i++) { data0[i].End -= 1; } for (int i = 0; i < data1.Count(); i++) { data1[i].End -= 1; } } else { for (int i = 0; i < data0.Count(); i++) { data0[i].End += 1; int t = data0[i].End; data0[i].End = data0[i].Begin; data0[i].Begin = t; } data0.Reverse(); for (int i = 0; i < data1.Count(); i++) { data1[i].End += 1; int t = data1[i].End; data1[i].End = data1[i].Begin; data1[i].Begin = t; } data1.Reverse(); } } #endregion } struct DataTimeUnit { public int data; public DateTime dt; public override string ToString() { return data.ToString() + " |" + dt.Ticks.ToString(); } } struct DataTimeUnit2 { public UInt16 istatus; public int pos; public DateTime dt; public override string ToString() { return pos.ToString() + "(" + istatus.ToString("X2") + ") |" + dt.ToString(); } } }