//==============================================================
// Copyright (C) 2019 Inc. All rights reserved.
//
//==============================================================
// Create by 种道洋 at 2019/12/27 18:45:02.
// Version 1.0
// 种道洋
// 1. 2020/7/1 三沙永兴岛 优化斜率压缩算法 种道洋
//==============================================================
using DBRuntime.His;
using DBRuntime.His.Compress;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Cdy.Tag
{
///
/// 斜率压缩算法
/// 斜率压缩采用数据块有多个数据段组成,每个数据段以数据段的字节数。遇到无效数据后新启一个数据段
///
public class SlopeCompressUnit2 : LosslessCompressUnit2
{
#region ... Variables ...
protected MemoryBlock mAvaiableDatabuffer;
///
///
///
protected CustomQueue usedIndex = new CustomQueue(604);
protected ProtoMemory mVarintMemory2;
#endregion ...Variables...
#region ... Events ...
#endregion ...Events...
#region ... Constructor...
#endregion ...Constructor...
#region ... Properties ...
///
///
///
public override string Desc => "斜率死区";
///
///
///
public override int TypeCode => 3;
#endregion ...Properties...
#region ... Methods ...
///
///
///
///
public override CompressUnitbase2 Clone()
{
return new SlopeCompressUnit2();
}
///
///
///
///
///
///
protected Memory CompressTimers(List timerVals, CustomQueue usedIndex)
{
usedIndex.ReadIndex = 0;
int preids = 0;
int ig = usedIndex.ReadIndex <= usedIndex.WriteIndex ? usedIndex.IncRead() : -1;
bool isFirst = true;
mVarintMemory2.Reset();
for (int i = 0; i < timerVals.Count; i++)
{
if (i == ig)
{
var id = timerVals[i];
if (isFirst)
{
isFirst = false;
mVarintMemory2.WriteInt32(id);
}
else
{
mVarintMemory2.WriteInt32(id - preids);
}
preids = id;
ig = usedIndex.ReadIndex <= usedIndex.WriteIndex ? usedIndex.IncRead() : -1;
}
}
return mVarintMemory2.DataBuffer.AsMemory(0, (int)mVarintMemory2.WritePosition);
}
///
///
///
///
private void GetEmpityTimers(List timerVals)
{
emptys.Reset();
for (int i = 1; i < timerVals.Count; i++)
{
if (timerVals[i] <= 0)
{
emptys.Insert(i);
}
}
}
///
///
///
///
///
///
///
///
protected new Memory CompressQulitys(IMemoryBlock source, long offset, int totalcount, CustomQueue usedIndex)
{
usedIndex.ReadIndex = 0;
int count = 0;
byte qus = 0;
mVarintMemory.Reset();
int ig = usedIndex.ReadIndex <= usedIndex.WriteIndex ? usedIndex.IncRead() : -1;
bool isFirst = true;
for (int i = 0; i < totalcount; i++)
{
if (i == ig)
{
byte bval = source.ReadByte(offset + i);
if (isFirst)
{
isFirst = false;
qus = bval;
mVarintMemory.WriteInt32(qus);
count++;
}
else
{
if (bval == qus)
{
count++;
}
else
{
mVarintMemory.WriteInt32(count);
qus = bval;
mVarintMemory.WriteInt32(qus);
count = 1;
}
}
ig = usedIndex.ReadIndex <= usedIndex.WriteIndex ? usedIndex.IncRead() : -1;
}
}
mVarintMemory.WriteInt32(count);
return mVarintMemory.DataBuffer.AsMemory(0, (int)mVarintMemory.WritePosition);
}
///
///
///
///
///
///
///
///
private double CalSlope(object fval, object lastVal,int timSpan)
{
//转换成以秒为时间单位的斜率计算
//timesSpan是以100ms为单位的时间间隔
return (Convert.ToDouble(lastVal) - Convert.ToDouble(fval)) / timSpan * 10;
}
///
///
///
///
///
///
///
///
private bool CheckIsNeedRecord(double preVal, double newVal, double area, int type)
{
if (type == 0)
{
return Math.Abs(newVal - preVal) > area;
}
else
{
return Math.Abs((newVal - preVal) / preVal) > area;
}
}
#region SlopeCompress
///
///
///
///
///
///
private Memory SlopeCompressByte(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
byte mLastValue = 0;
int mStartTime = 0;
byte mStartValue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadByte();
mMarshalMemory.Write(mLastValue);
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadByte();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
mMarshalMemory.Write(mLastValue);
}
mMarshalMemory.Write(vval);
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressShort(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
short mLastValue = 0;
int mStartTime = 0;
short mStartValue = 0;
bool isFirst = true;
short mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadShort();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt32(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mStartValue - mPrevalue);
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadShort();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt32(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(vval - mPrevalue);
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressUShort(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
ushort mLastValue = 0;
int mStartTime = 0;
ushort mStartValue = 0;
bool isFirst = true;
ushort mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadUShort();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt32(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mStartValue - mPrevalue);
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadUShort();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt32(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(vval - mPrevalue);
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressInt(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
int mLastValue = 0;
int mStartTime = 0;
int mStartValue = 0;
bool isFirst = true;
int mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadInt();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt32(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mStartValue - mPrevalue);
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadInt();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt32(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(vval - mPrevalue);
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32(mLastValue - mPrevalue);
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressUInt(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
uint mLastValue = 0;
int mStartTime = 0;
uint mStartValue = 0;
bool isFirst = true;
uint mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadUInt();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt32(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32((int)(mStartValue - mPrevalue));
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadUInt();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32((int)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt32(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32((int)(vval - mPrevalue));
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32((int)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt32(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt32((int)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
private Memory SlopeCompressLong(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
long mLastValue = 0;
int mStartTime = 0;
long mStartValue = 0;
bool isFirst = true;
long mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadLong();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt64(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((mStartValue - mPrevalue));
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadLong();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt64(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((vval - mPrevalue));
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
private Memory SlopeCompressULong(MemoryBlock values,CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
ulong mLastValue = 0;
int mStartTime = 0;
ulong mStartValue = 0;
bool isFirst = true;
ulong mPrevalue = 0;
mMarshalMemory.Position = 0;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadULong();
//mMarshalMemory.Write(mLastValue);
if (isFirst)
{
mVarintMemory.WriteInt64(mStartValue);
mPrevalue = mStartValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((long)(mStartValue - mPrevalue));
mPrevalue = mStartValue;
}
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadULong();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((long)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
//mMarshalMemory.Write(mLastValue);
}
// mMarshalMemory.Write(vval);
if (isFirst)
{
mVarintMemory.WriteInt64(vval);
mPrevalue = vval;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((long)(vval - mPrevalue));
mPrevalue = vval;
}
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((long)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
if (isFirst)
{
mVarintMemory.WriteInt64(mLastValue);
mPrevalue = mLastValue;
isFirst = false;
}
else
{
mVarintMemory.WriteSInt64((long)(mLastValue - mPrevalue));
mPrevalue = mLastValue;
}
// mMarshalMemory.Write(mLastValue);
}
}
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressDouble(MemoryBlock values,CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
//emptys.ReadIndex = 0;
//int ig = emptys.ReadIndex < emptyIds.WriteIndex ? emptys.IncRead() : -1;
int mLastTime = 0;
double mLastValue = 0;
int mStartTime = 0;
double mStartValue = 0;
mVarintMemory.Reset();
mMarshalMemory.Position = 0;
mDCompress.Reset();
mDCompress.Precision = this.Precision;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadDouble();
mDCompress.Append(mLastValue);
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadDouble();
if ((id-mlastid)>1)
{
//说明之间有无效值,需要重新计算斜率
if(mLastTime!=mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
mDCompress.Append(mLastValue);
}
mDCompress.Append(vval);
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
mDCompress.Append(mLastValue);
// mMarshalMemory.Write((mLastValue));
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
mDCompress.Append(mLastValue);
}
}
mDCompress.Compress();
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
///
///
///
///
///
///
///
private Memory SlopeCompressFloat(MemoryBlock values, CustomQueue mUsedTimerIndex)
{
double slopeArea = this.Parameters.ContainsKey("SlopeArea") ? this.Parameters["SlopeArea"] : 0;
int slopeType = (int)(this.Parameters.ContainsKey("SlopeType") ? this.Parameters["SlopeType"] : 0);
double minslope = 0;
double maxslope = 0;
bool isStarted = false;
int count = values.ReadInt(0);
int mLastTime = 0;
float mLastValue = 0;
int mStartTime = 0;
float mStartValue = 0;
mVarintMemory.Reset();
mMarshalMemory.Position = 0;
mFCompress.Reset();
mFCompress.Precision = this.Precision;
int id = 0;
int mlastid = 0;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
if (!isStarted)
{
isStarted = true;
mlastid = id = values.ReadInt();
mLastTime = mStartTime = values.ReadInt();
mLastValue = mStartValue = values.ReadFloat();
mFCompress.Append(mLastValue);
mUsedTimerIndex.Insert(id);
minslope = double.MinValue;
}
else
{
id = values.ReadInt();
var vkey = values.ReadInt();
var vval = values.ReadFloat();
if ((id - mlastid) > 1)
{
//说明之间有无效值,需要重新计算斜率
if (mLastTime != mStartTime)
{
mUsedTimerIndex.Insert(mlastid);
mFCompress.Append(mLastValue);
}
mFCompress.Append(vval);
mUsedTimerIndex.Insert(id);
mLastTime = mStartTime = vkey;
mLastValue = mStartValue = vval;
mlastid = id;
minslope = double.MinValue;
continue;
}
else
{
if (minslope == double.MinValue)
{
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
else
{
var ds = CalSlope(mStartValue, vval, vkey - mStartTime);
minslope = Math.Min(ds, minslope);
maxslope = Math.Max(ds, maxslope);
if (CheckIsNeedRecord(minslope, maxslope, slopeArea, slopeType))
{
mUsedTimerIndex.Insert(mlastid);
mFCompress.Append(mLastValue);
mStartTime = mLastTime;
mStartValue = mLastValue;
maxslope = minslope = CalSlope(mStartValue, vval, vkey - mStartTime);
}
}
}
mLastTime = vkey;
mLastValue = vval;
mlastid = id;
}
}
if (!mUsedTimerIndex.Contains(count) && isStarted)
{
int i = count;
mUsedTimerIndex.Insert(mlastid);
mFCompress.Append(mLastValue);
}
}
mFCompress.Compress();
return mMarshalMemory.StartMemory.AsMemory(0, (int)mMarshalMemory.Position);
}
#endregion
///
///
///
///
///
///
///
///
///
///
///
protected Memory CompressValues(IMemoryBlock source, long offset, int count,List mTimers,TagType type)
{
int ig = -1;
emptys.ReadIndex = 0;
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
int ac = 0;
mAvaiableDatabuffer.Position = 0;
mAvaiableDatabuffer.Write((int)0);
switch (type)
{
case TagType.Byte:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadByte((int)offset + i);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
// return null;
return SlopeCompressByte(mAvaiableDatabuffer, usedIndex);
case TagType.Short:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadShort((int)offset + i);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
return SlopeCompressShort(mAvaiableDatabuffer, usedIndex);
case TagType.UShort:
Dictionary mavaibleValues = new Dictionary();
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadUShort((int)offset + i);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
return SlopeCompressUShort(mAvaiableDatabuffer, usedIndex);
case TagType.Int:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadInt((int)offset + i);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
// return null;
return SlopeCompressInt(mAvaiableDatabuffer, usedIndex);
case TagType.UInt:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadUInt((int)offset + i);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
return SlopeCompressUInt(mAvaiableDatabuffer, usedIndex);
case TagType.Long:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadLong((int)offset + i * 8);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
return SlopeCompressLong(mAvaiableDatabuffer, usedIndex);
case TagType.ULong:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadULong((int)offset + i * 8);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
//return null;
return SlopeCompressULong(mAvaiableDatabuffer, usedIndex);
case TagType.Double:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
ac++;
var id = source.ReadDouble((int)offset + i * 8);
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
return SlopeCompressDouble(mAvaiableDatabuffer, usedIndex);
case TagType.Float:
for (int i = 0; i < count; i++)
{
if (i != ig)
{
var id = source.ReadFloat((int)offset + i * 4);
ac++;
mAvaiableDatabuffer.Write(i);
mAvaiableDatabuffer.Write(mTimers[i]);
mAvaiableDatabuffer.Write(id);
}
else
{
ig = emptys.ReadIndex <= emptys.WriteIndex ? emptys.IncRead() : -1;
}
}
mAvaiableDatabuffer.WriteInt(0, ac);
//return null;
return SlopeCompressFloat(mAvaiableDatabuffer, usedIndex);
default:
usedIndex = null;
return null;
}
}
///
///
///
///
///
///
///
///
///
private long FillData(Memory valuedata,Memory qualitydata, Memory timedata,MarshalMemoryBlock target, long targetAddr)
{
int rsize = 0;
target.WriteInt(targetAddr, usedIndex.WriteIndex);
rsize += 4;
target.Write((int)timedata.Length);
target.Write(timedata);
rsize += 4;
rsize += timedata.Length;
target.Write(valuedata.Length);
target.WriteMemory(target.Position, valuedata, 0, valuedata.Length);
rsize += 4;
rsize += valuedata.Length;
target.Write(qualitydata.Length);
target.Write(qualitydata);
rsize += 4;
rsize += qualitydata.Length;
return rsize;
}
///
///
///
///
///
///
///
///
///
///
protected override long Compress(IMemoryBlock source, long sourceAddr, MarshalMemoryBlock target, long targetAddr, long size, TagType type)
{
var count = (int)(size - this.QulityOffset);
byte tlen = (source as HisDataMemoryBlock).TimeLen;
List tims = new List(count);
if (tlen == 2)
{
for (int i = 0; i < count; i++)
{
tims.Add(source.ReadUShort(sourceAddr + i * 2));
}
}
else
{
for (int i = 0; i < count; i++)
{
tims.Add(source.ReadInt(sourceAddr + i * 4));
}
}
//tims = tlen == 2 ? source.ReadUShorts(sourceAddr, (int)count).Select(e => (int)e).ToList() : source.ReadInts(sourceAddr, (int)count);
if (mMarshalMemory == null)
{
mMarshalMemory = new MemoryBlock(count * 10);
}
if (mVarintMemory == null)
{
mVarintMemory = new ProtoMemory(count * 10);
}
if (mVarintMemory2 == null)
{
mVarintMemory2 = new ProtoMemory(count * 10);
}
//
if (mAvaiableDatabuffer == null)
{
mAvaiableDatabuffer = new MemoryBlock(count * 20);
}
if (usedIndex.Length < count)
{
usedIndex = new CustomQueue(count * 2);
}
else
{
usedIndex.Reset();
}
GetEmpityTimers(tims);
long rsize = 0;
switch (type)
{
case TagType.Byte:
var cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
var timeData = CompressTimers(tims, usedIndex);
var cqus = CompressQulitys(source, count * 3 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.Short:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 4 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.UShort:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 4 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.Int:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 6 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.UInt:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 6 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.Long:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 10 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.ULong:
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 10 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.Double:
if (mDCompress == null)
{
mDCompress = new DoubleCompressBuffer(count) { MemoryBlock = mMarshalMemory, VarintMemory = mVarintMemory };
}
else
{
mDCompress.CheckAndResizeTo(count);
}
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 10 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
case TagType.Float:
if (mFCompress == null)
{
mFCompress = new FloatCompressBuffer(count) { MemoryBlock = mMarshalMemory, VarintMemory = mVarintMemory };
}
else
{
mFCompress.CheckAndResizeTo(count);
}
cval = CompressValues(source, count * 2 + sourceAddr, count, tims, type);
timeData = CompressTimers(tims, usedIndex);
cqus = CompressQulitys(source, count * 6 + sourceAddr, count, usedIndex);
rsize = FillData(cval, cqus, timeData, target, targetAddr);
break;
default:
base.Compress(source, sourceAddr, target, targetAddr, size, type);
break;
}
return rsize;
}
#endregion ...Methods...
#region ... Interfaces ...
#endregion ...Interfaces...
}
}