using Misc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FlyADBase
{
///
/// 高级timegrid助手
/// 使用说明:
/// ADPool 只能储存 1min数据, 其它XXXPool 保存1.5min数据
///
///
/// 获取最后一次运行动作的开始与结束时间
/// bool ret = mTimeGridAdvHelper.GetLastRunningTime(out DateTime beginTime, out DateTime endTime, out int marker, out DRIVE_MAN_ORDER order);
///
/// 获取 指定时间范围的 timegrid 数据
/// var adList = mTimeGridAdvHelper.GetAD(beginTime, endTime, out DateTime reponse_endTime);
///
/// 获取 指定时间范围的 pos 数据
/// var posList = mTimeGridAdvHelper.GetPos(reponse_endTime,adList.Count());
///
/// 获取 指定时间范围的 pos2 数据
/// var pos2List = mTimeGridAdvHelper.GetPos2(reponse_endTime,adList.Count());
///
/// 获取 指定时间范围的 输入口 数据
/// var istatusList = mTimeGridAdvHelper.GetIStatus(reponse_endTime,adList.Count());
///
/// 转为 grid 数据
/// int posLen = 8900;
/// var grid = ToGrid(adList, posList, posOfGrid = 10, gridLen = posLen/10);
///
///
public class TimeGridAdvHelper
{
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
#region 一分钟数据缓存池, 目标每个AD数据(1ms) 都有对应的其它数据
///
/// AD数据池时间间隔为1ms, 肯定最少有一个数据
/// 每个数据包(200个数据)理论间隔是200ms, 但实际上不是。
/// 数据输出时,输出的每个数据必须是1ms, 需要通过数据包的systick线性填充数据
///
public List ADPool = new List();
///
/// pos 数据池, 肯定最少有一个数据
///
public List PosPool = new List();
///
/// 输入端口 数据池, 肯定最少有一个数据
///
public List IStatusPool = new List();
///
/// pos2 数据池, 肯定最少有一个数据
///
public List Pos2Pool = new List();
///
/// DriveStatus 数据池, 肯定最少有一个数据
///
public List DriveStatusPool = new List();
#endregion
public DateTime NewestTime;
///
///
///
public void Init()
{
Clear();
}
///
/// 添加ad数据,且判断数据量是否够触发事件, 时间间隔为 1ms
///
///
///
public void AddAD(DateTime end_dt, int[] adArray)
{
if (adArray.Count() == 0)
return;
//------------------------------------------------------------------------------------------
//AD数据添加
//DateTime dt = DateTime.MinValue;
ADPool.Add(new DateTimeUnit3() { dt = end_dt, datas = adArray});
//long ticks = (long)((ts_ms * adArray.Count()) * TimeSpan.TicksPerMillisecond);
NewestTime = end_dt;
LimitPool();
}
void LimitPool()
{
if (NewestTime == DateTime.MinValue)
return;
if (ADPool.Count() == 0)
return;
//限制的时间
var limitTime_ad = NewestTime - TimeSpan.FromMinutes(1);
if (limitTime_ad - ADPool.First().dt < TimeSpan.FromMinutes(0.2))
{
//比限定的多了0.2min 才会动作
return;
}
//限制的时间
var limitTime_other = NewestTime - TimeSpan.FromMinutes(1.5);
LimitSimplePool(ADPool, limitTime_ad);
LimitSimplePool(PosPool, limitTime_other);
LimitSimplePool(Pos2Pool, limitTime_other);
LimitSimplePool(DriveStatusPool, limitTime_other);
LimitSimplePool(IStatusPool, limitTime_other);
}
///
///
///
/// IDateTimeUnit
/// 缓存区
/// 缓存区容量单位min
void LimitSimplePool(List pool, DateTime limitTime) where T : IDateTimeUnit
{
//删除Pos 数据池
int removeCnt = 0;
for (int i = 0; i < pool.Count(); i++)
{
var cell = pool[i];
if (cell.dt < limitTime)
{
//需要删除
removeCnt = i + 1;
}
else
{
break;
}
}
if (removeCnt > 0)
{
//不能全部数据删除完,必须留一个
if (removeCnt == pool.Count())
{
removeCnt--;
if (removeCnt <= 0)
return;//不用删除了
}
pool.RemoveRange(0, removeCnt);
}
}
///
/// 添加脉冲, 脉冲不一样,返回true
///
///
///
public bool AddPos(DateTime time, int pos)
{
return AddSimpleData(PosPool, time, pos);
}
///
/// 添加驱动状态, 返回true,则driveStatus变化了
///
///
///
///
///
public bool AddDriveStatus(DateTime time,DRIVE_MAN_ORDER order, DRIVE_MAN_STATUS driveStatus, int marker)
{
var pool = DriveStatusPool;
if (pool.Count > 0)
{
if (pool.Last().dt > time)
{
//异常,把之前的数据删除
pool.Clear();
}
else if (pool.Last().dt == time)
{
//删除之前那个
pool.RemoveAt(pool.Count() - 1);
}
}
pool.Add(new DateTimeUnit4() { dt = time, order = order, driveStatus = driveStatus, marker = marker });
if (pool.Count() > 1)
{
return pool[pool.Count() - 2].driveStatus != driveStatus;
}
return false;
}
///
/// 添加 基本数据,当数据与上一次不一样,返回true
///
///
///
///
///
bool AddSimpleData(List pool, DateTime time, int data) {
if (pool.Count > 0)
{
if (pool.Last().dt > time)
{
//异常,把之前的数据删除
//TODO, AD盒有bug, IO 推送, 的systick 比 pos 的systick 要慢,
//正常的操作,全删除
//pool.Clear();
//数据插入就算了
for (int i = 1; i < pool.Count(); i++) {
int index = pool.Count() - 1 - i;
if (time > pool[index].dt)
{
//找到了
pool.Insert(index, new DateTimeUnit() { dt = time, data = data });
}
else if (time == pool[index].dt) {
//什么都不干
return false;
}
}
//找完了,不插了
}
else if (pool.Last().dt == time)
{
//删除之前那个
//pool.RemoveAt(pool.Count() - 1);
return false;
}
}
pool.Add(new DateTimeUnit() { dt = time, data = data });
if (pool.Count > 1)
{
return pool[pool.Count() - 2].data != data;
}
else {
return false;
}
}
///
/// 添加脉冲2, 脉冲2不一样,返回true
///
///
///
public bool AddPos2(DateTime time, int pos2)
{
return AddSimpleData(Pos2Pool, time, pos2);
}
///
/// 添加输入口状态
///
///
///
public bool AddIStatus(DateTime time, UInt16 istatus)
{
var pool = IStatusPool;
if (pool.Count > 0)
{
if (pool.Last().dt >= time)
{
//异常,把之前的数据删除
pool.Clear();
}
}
IStatusPool.Add(new DateTimeUnit2() { dt = time, istatus = istatus });
if (IStatusPool.Count > 1)
return IStatusPool[IStatusPool.Count - 2].istatus != istatus;
else
return false;
}
///
/// 添加输入口状态
///
///
///
///
///
public bool AddIStatus(DateTime time, UInt16 istatus, int pos, int pos2, out UInt16 ichanged)
{
ichanged = 0;
var pool = IStatusPool;
if (pool.Count > 0)
{
if (pool.Last().dt >= time)
{
//异常,把之前的数据删除
pool.Clear();
}
}
IStatusPool.Add(new DateTimeUnit2() { dt = time, istatus = istatus, isPosValid = true, pos = pos, pos2 = pos2 });
AddPos(time, pos);
AddPos2(time, pos2);
if (IStatusPool.Count > 1)
{
ichanged = (UInt16)(IStatusPool[IStatusPool.Count - 2].istatus ^ istatus);
return IStatusPool[IStatusPool.Count - 2].istatus != istatus;
}
else
return false;
}
///
/// 添加开始位置
///
///
///
public void AddPos_Default(DateTime time, int pos)
{
if (PosPool.Count() == 0)
{
AddPos(time,pos);
}
}
///
/// 添加开始位置
///
///
///
public void AddPos2_Default(DateTime time, int pos)
{
if (Pos2Pool.Count() == 0)
{
AddPos2(time,pos);
}
}
///
/// 添加开始驱动状态
///
///
///
///
///
public void AddDriveStatus_Default(DateTime time, DRIVE_MAN_ORDER order, DRIVE_MAN_STATUS dirveStatus, int marker)
{
if (IStatusPool.Count() == 0)
{
AddDriveStatus(time, order, dirveStatus, marker);
}
}
///
/// 添加开始状态
///
///
///
public void AddIStatus_Default(DateTime time, UInt16 istatus)
{
if (IStatusPool.Count() == 0)
{
IStatusPool.Add(new DateTimeUnit2() { dt = time, istatus = istatus});
}
}
///
///
///
public void Clear()
{
PosPool.Clear();
ADPool.Clear();
IStatusPool.Clear();
Pos2Pool.Clear();
DriveStatusPool.Clear();
}
///
/// 获取最后一次运行的时间段
///
///
///
///
///
///
public bool GetLastRunningTime(out DateTime begin, out DateTime end, out int marker, out DRIVE_MAN_ORDER order) {
begin = DateTime.MinValue;
end = DateTime.MinValue;
marker = 0;
order = DRIVE_MAN_ORDER.IDLE;
//1. 找 最后一个 driveStatus!=running的
int idxOfStop = -1;
for (int i = DriveStatusPool.Count() - 1; i >= 0; i--)
{
var cell = DriveStatusPool[i];
if (cell.driveStatus != DRIVE_MAN_STATUS.RUNNING)
{
//对!!它是。但继续向前找找看
idxOfStop = i;
}
else
{
if (idxOfStop != -1)
{
//之前已经找到了,
break;
}
}
}
if (idxOfStop == -1)
{
//一直在running,还没停下来
return false;
}
//2. 最向前找running的
int idxOfRunning = -1;
for (int i = idxOfStop - 1; i >= 0; i--)
{
var cell = DriveStatusPool[i];
if (cell.driveStatus == DRIVE_MAN_STATUS.RUNNING)
{
//对!!它是。但继续向前找找看
idxOfRunning = i;
}
else
{
//没了
break;
}
}
if (idxOfRunning == -1)
{
//一直停着,没有运行过
return false;
}
begin = DriveStatusPool[idxOfRunning].dt;
end = DriveStatusPool[idxOfStop].dt;
order = DriveStatusPool[idxOfStop].order;
marker = DriveStatusPool[idxOfStop].marker;
return true;
}
///
/// 获取最后一次运行中的timegrid;
/// 找到最后一个 driveStatus!=running的, 最向前找running的
///
/// 开始时间
/// 结束时间
/// 返回数据的最后一个数据的时间,数据间隔为 TimeGridAdvHelperExt.ts_ad_ms
///
public List GetAD(DateTime begin, DateTime end, out DateTime reponse_endTime)
{
return TimeGridAdvHelperExt.GetAD(ADPool, begin, end, out reponse_endTime);
}
public List GetAD(DateTime begin)
{
return TimeGridAdvHelperExt.GetAD(ADPool, begin );
}
///
/// 输出以 1ms 为间隔脉冲列表
///
/// 结束时间点
/// 数据长度
///
public List GetPos(DateTime end_dt, int cnt) {
return TimeGridAdvHelperExt.GetPos(PosPool, end_dt, cnt);
}
public List GetPos2(DateTime end_dt, int cnt)
{
return TimeGridAdvHelperExt.GetPos(Pos2Pool, end_dt, cnt);
}
public List GetIStatus(DateTime end_dt, int cnt)
{
return TimeGridAdvHelperExt.GetIStatus(IStatusPool, end_dt, cnt);
}
public void GetIStatusRange(
int istatusIndex,
DateTime beginTime, DateTime endTime,
out List data0, out List data1)
{
TimeGridAdvHelperExt.GetIStatusRange(IStatusPool, PosPool, true, istatusIndex, beginTime, endTime, out data0, out data1);
}
}
public interface IDateTimeUnit
{
DateTime dt { get; set; }
}
public struct DateTimeUnit: IDateTimeUnit
{
public int data;
public DateTime dt { get; set; }
public override string ToString()
{
return $"{dt.Ticks} | {data}";
}
}
public struct DateTimeUnit4 : IDateTimeUnit
{
public DateTime dt { get; set; }
public DRIVE_MAN_ORDER order;
public DRIVE_MAN_STATUS driveStatus;
public int marker;
public override string ToString()
{
return $"{dt.Ticks} | {order} | {driveStatus} | {marker}";
}
}
public struct DateTimeUnit3 : IDateTimeUnit
{
///
/// 数据结束点
///
public DateTime dt { get; set; }
///
/// 数据列
///
public int[] datas;
public override string ToString()
{
return $"{dt.Ticks} | cnt={datas.Count()}";
}
}
public struct DateTimeUnit2: IDateTimeUnit
{
public DateTime dt { get; set; }
public UInt16 istatus;
public bool isPosValid;
public int pos;
public int pos2;
public override string ToString()
{
if(isPosValid)
return $"{dt.Ticks} | ({istatus:X2}) | 1={pos} | 2={pos2}";
else
return $"{dt.Ticks} | ({istatus:X2})";
}
}
public static class TimeGridAdvHelperExt
{
///
/// 导出的数据间隔是1ms 一个, 导出的数据量肯定比要求给的更多
///
/// AD缓存区(每个数据间隔1ms)
/// 开始时间点
/// 结束时间点
/// 实际导出的数据结束时间点
///
public static List GetAD(List adPool, DateTime begin, DateTime end, out DateTime reponse_endTime)
{
reponse_endTime = DateTime.MinValue;
var reponse2 = GetAD2(adPool, begin, end);
if (reponse2.Count() == 0)
return new List();
DateTime lastTime = reponse2.Last().dt;
reponse_endTime = lastTime;
return GetAD(reponse2);
}
///
/// 导出的数据间隔是1ms 一个
///
/// AD缓存区(每个数据间隔1ms)
///
public static List GetAD(List adPool)
{
return GetAD(adPool, DateTime.MinValue);
}
///
/// 导出的数据间隔是1ms 一个
///
/// AD缓存区
/// 开始时间点
///
public static List GetAD(List adPool, DateTime begin)
{
List reponse = new List();
//导出数据的时间
DateTime idealTime = adPool.Last().dt;
//每个ad包的每个数据不是准确的1ms,肯定比1.28ms大,每次需要准
for (int i = 0; i < adPool.Count(); i++)
{
int idx = adPool.Count() - 1 - i;
var adCell = adPool[idx];
//当前缓存区包,每个数据的时间间隔
//TimeSpan curr_ad_ts;
//计算这个包每个数据的时间间隔
DateTime actTime = adCell.dt;//从缓存区获取数据的时间
for (int j = 0; j < adCell.datas.Count(); j++)
{
int idx2 = adCell.datas.Count() - 1 - j;
int ad = adCell.datas[idx2];
actTime -= TimeSpan.FromMilliseconds(1);//导出数据时间累加
while (idealTime > actTime)
{
reponse.Add(ad);//导出数据
idealTime -= TimeSpan.FromMilliseconds(1);//导出数据时间累加
}
}
if (idealTime < begin)
goto _end;//完成
}
_end:
//反转
reponse.Reverse();
return reponse;
}
///
/// 获取 时间在 begin~end 的 AD数据包
///
/// AD缓存区
/// 开始时间点
/// 结束时间点
///
static List GetAD2(List adPool, DateTime begin, DateTime end)
{
//ad 包的总数量不可能多,从头找也没所谓
//TODO, 当ad包,每个包只有一个数据时,包数很庞大。 需要查找加速
List reponse = new List();
for (int i = 0; i < adPool.Count(); i++)
{
var cell = adPool[i];
if (cell.dt < begin)
continue;
else if (cell.dt <= end)
reponse.Add(cell);
else
break;
}
return reponse;
}
///
/// 获取平均速度, 单位 脉冲/min
///
/// 脉冲缓存区
/// 开始时间点
/// 结束时间点
///
public static double GetSpeed(List posPool, DateTime begin, DateTime end) {
int searchIdx = posPool.Count() - 1;
int end_pos = GetPos(posPool, end, ref searchIdx);
int begin_pos = GetPos(posPool, begin, ref searchIdx);
return (end_pos - begin_pos) / (end - begin).TotalMinutes;
}
///
/// 输出以 1ms 为间隔脉冲列表
///
/// 脉冲缓存区
/// 结束时间点
/// 数据长度
///
public static List GetPos(List posPool, DateTime end_dt, int cnt)
{
//从后面开始找
int searchIdx = posPool.Count() - 1;
List reponse = new List();
DateTime lastTime = end_dt;
for (int i = 0; i < cnt; i++)
{
reponse.Add(GetPos(posPool, lastTime, ref searchIdx));
lastTime -= TimeSpan.FromMilliseconds(1);
}
//反转
reponse.Reverse();
return reponse;
}
///
/// 获取时间对应的 位置点
///
///
/// 脉冲缓存池
/// 查询开始序号
///
public static int GetPos(List posPool, DateTime dt, ref int searchIdx)
{
//找到 时间落在 [idx,idx+1] 之间的 序号
int index = searchIndex(posPool, dt, searchIdx);
searchIdx = index;
if (index == posPool.Count() - 1)
{
//发生在未来,返回最后一个脉冲,不进行线性预测
return posPool[index].data;
}
else if (index < 0) {
//发生在过去,返回第一个脉冲,不进行线性预测
return posPool[0].data;
}
return GetPosLinear(posPool, dt, index);
}
///
/// 线性插值算 pos;
/// 以 [idx,idx+1] 的比例, 给出 time 计算 pos
///
///
///
///
///
static int GetPosLinear(List posPool, DateTime time, int idx)
{
if (posPool.Count() <= 0)//不应该存在
{
throw new Exception("没数据,还没准备好,不能获取");
}
if (posPool.Count() == 1)
return posPool.First().data;
if (idx < 0)
idx = 0;
if (idx >= posPool.Count() - 1)
idx = posPool.Count() - 2;
var cell0 = posPool[idx];
var cell1 = posPool[idx + 1];
double d_pos = cell0.data - cell1.data;
if (d_pos == 0)
return cell0.data;
TimeSpan ts = cell0.dt - cell1.dt;
double p = d_pos * (time - cell1.dt).Ticks / ts.Ticks;
return (int)(p + cell1.data);
}
enum SearchState
{
ContinueLastTime,
Back,
ForwToCheck
}
///
/// 找到 时间 dt 落在 [idx,idx+1] 之间的 idx;
/// 返回 -1,证明dt 在列表在前面, 或列表数据量为=0,
/// 当dt 大于 列表最后一个数, 返回最后一个数据的id
///
///
/// 列表
///
/// 从列表的某个位置开始向前查找
///
public static int searchIndex(List list, DateTime dt, int searchStartIdx) where T : IDateTimeUnit
{
if (list.Count() == 0)
return -1;
int max_index = list.Count() - 1;
if (dt >= list[max_index].dt)
return max_index;
if (dt < list[0].dt)
return -1;
int index = searchStartIdx;
SearchState state = SearchState.ContinueLastTime;
if ((index < 0) || (index >= max_index))//重新开始
{
index = max_index;
state = SearchState.Back;
}
else if (state == SearchState.ContinueLastTime)
{
if (list[index].dt <= dt)
{
//可能找到了
//再向正方向看看
state = SearchState.ForwToCheck;
}
else
{
state = SearchState.Back;
}
}
if (state == SearchState.ForwToCheck)
{
while (true)
{
DateTime time = list[index].dt;
if (time > dt)
{
//就是之前那个
index--;
return index;
}
else
{
index++;
}
if (index > max_index)
{
//最后一个就是了
throw new Exception("之前没有判断出 时间点在列表后,异常!!");
//return max_index;
}
}
}
else//SearchState.Back
{
while (true)
{
DateTime time = list[index].dt;
if (time <= dt)
{
//就是它
return index;
}
index--;
if (index < 0)
{
//不可能发生
throw new Exception("之前没有判断出 时间点在列表前,异常!!");
}
}
}
}
///
/// 输出以 1ms 为间隔 输入口状态 列表
///
///
///
///
///
public static List GetIStatus(List iStatusPool, DateTime end_dt, int cnt)
{
int searchIdx = iStatusPool.Count() - 1;
List reponse = new List();
DateTime lastTime = end_dt;
for (int i = 0; i < cnt; i++)
{
reponse.Add(GetIStatus(iStatusPool, lastTime, ref searchIdx));
lastTime -= TimeSpan.FromMilliseconds(1);
}
//反转
reponse.Reverse();
return reponse;
}
///
/// 根据时间点,获取输入口状态;
/// 时间 dt 落在 [searchIdx,searchIdx+1]
///
///
///
///
///
public static UInt16 GetIStatus(List iStatusPool, DateTime dt, ref int searchIdx)
{
int index = searchIndex(iStatusPool, dt, searchIdx);
if (index < 0)
index = 0;
searchIdx = index;
return (UInt16)iStatusPool[index].istatus;
}
///
/// data0 的 输入口=false 脉冲范围;data1 的 输入口=true 脉冲范围;
///
/// 输入口池
/// 脉冲池
/// 是pos1?
/// 输入口序号
/// 开始时间
/// 结束时间
/// false脉冲范围
/// true脉冲范围
public static void GetIStatusRange(
List iStatusPool, List posPool, bool isPos1,
int istatusIndex, DateTime beginTime, DateTime endTime, out List data0, out List data1)
{
int istatus_search_idx = iStatusPool.Count - 1;
int pos_search_idx = posPool.Count - 1;
data0 = new List();
data1 = new List();
UInt16 istatus = GetIStatus(iStatusPool, beginTime, ref istatus_search_idx);
int beginPos = GetPos(posPool, beginTime, ref pos_search_idx);
int endPos = GetPos(posPool, endTime, ref pos_search_idx);
DIRECTION direction = endPos > beginPos ? DIRECTION.FORWARD : DIRECTION.BACKWARD;
bool istatus_no_b = Misc.MyBase.CHECKBIT(istatus, istatusIndex);
Range r = new Range();
r.Begin = beginPos;
for (int i = istatus_search_idx + 1; i < iStatusPool.Count(); i++)
{
istatus = iStatusPool[i].istatus;
int pos;
if (isPos1)
pos = iStatusPool[i].pos;
else
pos = iStatusPool[i].pos2;
bool b = Misc.MyBase.CHECKBIT(istatus, istatusIndex);
if (iStatusPool[i].dt >= endTime)
{
//结束,这是最后!!!
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 = beginPos;
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();
}
}
///
/// data0 的 输入口=false 序号范围;data1 的 输入口=true 序号范围;
/// timeOffset 为时间偏移,用于多AD盒情况,iStatusPool内的全部时间都会+timeOffset
///
/// 输入口池
/// 输入口序号
/// 开始时间
/// 结束时间
/// false脉冲范围
/// true脉冲范围
public static void GetIStatusRange(
List iStatusPool,
int istatusIndex, DateTime beginTime, DateTime endTime,
out List data0, out List data1)
{
int istatus_search_idx = iStatusPool.Count - 1;
data0 = new List();
data1 = new List();
UInt16 istatus = GetIStatus(iStatusPool, beginTime, ref istatus_search_idx);
bool istatus_no_b = Misc.MyBase.CHECKBIT(istatus, istatusIndex);
Range_DateTime r = new Range_DateTime();
r.Begin = beginTime;
int i = istatus_search_idx + 1;
while (i < iStatusPool.Count()) {
istatus = iStatusPool[i].istatus;
bool b = Misc.MyBase.CHECKBIT(istatus, istatusIndex);
if (iStatusPool[i].dt >= endTime)
{
//结束,这是最后!!!
break;
}
else
{
if (b != istatus_no_b)
{
r.End = iStatusPool[i].dt;
if (istatus_no_b)
data1.Add(r);
else
data0.Add(r);
istatus_no_b = b;
r = new Range_DateTime();
r.Begin = iStatusPool[i].dt;
}
}
i++;
}
r.End = endTime;
if (istatus_no_b)
data1.Add(r);
else
data0.Add(r);
}
static void toGrid_step1(int[] grids_sum, int[] grids_cnt, int gridLen, int grid_idx, int ad)
{
if ((grid_idx < 0) || (grid_idx >= gridLen))
{
return;
}
if (!Misc.MyBase.ISVALIDATA(ad))
return;
grids_cnt[grid_idx]++;
grids_sum[grid_idx] += ad;
}
///
/// 输出 grid图。 adList[x-adLag] 对应 posList[x]
///
///
///
///
///
///
///
public static int[] ToGrid(List adList, List posList, int posOfGrid, int gridLen, int adLag=0)
{
return ToGrid(adList, posList, posOfGrid, gridLen, out int grid_start, out int grid_end, adLag);
}
///
/// 输出 grid图。 adList[x-adLag] 对应 posList[x]
///
///
///
///
///
///
///
public static int[] ToGrid(List adList, List posList, int posOfGrid, int gridLen, out int grid_start, out int grid_end, int adLag = 0, bool isMiniGrid=false)
{
int[] grids_sum = new int[gridLen];
int[] grids_cnt = new int[gridLen];
int grid_idx_last = -1;
grid_start = Misc.MyBase.NULL_VALUE;
grid_end = Misc.MyBase.NULL_VALUE;
//grid_idx 应该要连续变化,不是,那就插值
for (int j = 0; j < adList.Count() && j < posList.Count(); j++)
{
int index = j - adLag;
if (index < 0 || index >= adList.Count())
continue;
int ad = adList[index];
int pos = posList[j];
int grid_idx = pos / posOfGrid;
//grid不能小于0 或 大于等于 gridLen
if (grid_idx < 0 || grid_idx >= gridLen)
continue;
if (!Misc.MyBase.ISVALIDATA(grid_start))
{
grid_start = grid_idx;
grid_end = grid_idx;
}
else
{
if (grid_idx < grid_start)
grid_start = grid_idx;
if (grid_idx > grid_end)
grid_end = grid_idx;
}
if (grid_idx_last != -1 && (Math.Abs(grid_idx_last - grid_idx) > 1))
{
//步子太大,需要插值
if (grid_idx_last < grid_idx)
{
for (int i = grid_idx_last; i < grid_idx; i++)
{
toGrid_step1(grids_sum, grids_cnt, gridLen, i, ad);
}
}
else
{
for (int i = grid_idx_last; i > grid_idx; i--)
{
toGrid_step1(grids_sum, grids_cnt, gridLen, i, ad);
}
}
}
toGrid_step1(grids_sum, grids_cnt, gridLen, grid_idx, ad);
grid_idx_last = grid_idx;
}
for (int i = 0; i < gridLen; i++)
{
if (grids_cnt[i] == 0)
grids_sum[i] = Misc.MyBase.NULL_VALUE;
else
grids_sum[i] = (int)(grids_sum[i] / grids_cnt[i]);
}
if (isMiniGrid)
{
//只导出 grid_start~grid_end 数据
if (Misc.MyBase.ISVALIDATA(grid_start))
{
return grids_sum.Skip(grid_start).Take(grid_end - grid_start + 1).ToArray();
}
else {
return null;//一个数据都没有
}
}
else
{
return grids_sum;
}
}
}
public class Range_DateTime
{
public DateTime Begin;
public DateTime End;
}
}