using FLY.OBJComponents.Common; using FLY.OBJComponents.IService; using FLY.Thick.RemoteHistory; using FObjBase; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace FLY.OBJComponents.Server { public class Buffer<T> : IBufferAdd<T> { public List<T> list = new List<T>(); #region property public int NewestID { get; set; } = -1; public int Count { get; private set; } = 0; /// <summary> /// 总容量,当总数量 大于等于 总容量的 100%, 前面的10%数据会被删除 /// </summary> public int Capacity { get; set; } #endregion public event NotifyBufferChangedEventHandler<T> BufferChanged; public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// /// </summary> /// <param name="filepath">数据存储路径, null 不保存</param> /// <param name="saveInterval">数据保存周期时间 单位:分钟</param> /// <param name="capacity">数据总容量</param> public Buffer(int capacity = 1000) { Capacity = capacity; } public int GetID(int idx) { int offset = (NewestID - (list.Count() - 1)); return offset + idx; } public int GetIndex(int id) { int offset = (NewestID - (list.Count() - 1)); return id - offset; } public void Add(T t) { list.Add(t); if (list.Count() > Capacity) { list.RemoveRange(0, Capacity / 10); } NewestID++; Count = list.Count(); BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>() { Action = NotifyBufferChangedAction.Add, Items = new T[] { t }, EndingID = NewestID }); } public void AddRange(IEnumerable<T> array) { list.AddRange(array); if (list.Count() > Capacity) { list.RemoveRange(0, Capacity / 10); } NewestID += array.Count(); Count = list.Count(); BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>() { Action = NotifyBufferChangedAction.Add, Items = array, EndingID = NewestID }); } public override string ToString() { return "{NewestID:" + NewestID.ToString() + ", " + "Count:" + Count.ToString() + "}"; } public void Replace(int id, T t) { int idx = GetIndex(id); if (idx < 0 || idx >= list.Count()) return; list[idx] = t; BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>() { Action = NotifyBufferChangedAction.Replace, Items = new T[] { t }, EndingID = id }); } public void Remove(int id) { int idx = GetIndex(id); if (idx < 0 || idx >= list.Count()) return; T t = list[idx]; list.RemoveAt(idx); Count--; BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>() { Action = NotifyBufferChangedAction.Remove, EndingID = id, Items = new T[] { t } }); } public void Reset() { list.Clear(); NewestID = -1; Count = 0; BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>() { Action = NotifyBufferChangedAction.Reset }); } /// <summary> /// 获取指定位置的N个数据 /// </summary> /// <param name="last_id">最后的ID</param> /// <param name="count">数量</param> /// <param name="asyncCB">回调</param> /// <param name="asyncContext">回调里面的上下文</param> public void GetRecord(int last_id, int count, AsyncCBHandler asyncCB, object asyncContext) { if (list.Count() == 0) { asyncCB(asyncContext, new GetRecordReponse<T>() { LastID = 0, Items = null }); return; } int firstID = last_id - count + 1; int lastID = last_id; int rFirstID = NewestID - list.Count() + 1; int rLastID = NewestID; //以 rFirstID 为偏移量 int offset = -rFirstID; firstID += offset; lastID += offset; rLastID += offset; rFirstID = 0; //返回交集 if (lastID < 0)//在前面 { //没有数据 asyncCB(asyncContext, new GetRecordReponse<T>() { LastID = 0, Items = null }); return; } else if (firstID > rLastID)//在后面 { //没有数据 asyncCB(asyncContext, new GetRecordReponse<T>() { LastID = 0, Items = null }); return; } else { if (firstID < 0) firstID = 0; if (lastID > rLastID) lastID = rLastID; int cnt = lastID - firstID + 1; T[] items = new T[cnt]; for (int i = 0; i < cnt; i++) items[i] = list[firstID + i]; asyncCB(asyncContext, new GetRecordReponse<T>() { LastID = lastID - offset, Items = items }); } } /// <summary> /// 获取最新的N个数据 /// </summary> /// <param name="count">数量</param> /// <param name="asyncCB">回调</param> /// <param name="asyncContext">回调里面的上下文</param> public void GetRecord(int count, AsyncCBHandler asyncCB, object asyncContext) { GetRecord(NewestID, count, asyncCB, asyncContext); } } }