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();
}
}
}