From e47ae3d5bf2de70533c63aa1dd99971de1bd6340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Wed, 22 Dec 2021 10:09:01 +0100 Subject: [PATCH] Swinging door handles the end of the data stream correctly (#72) * Fix xml doc comment for ICompression.ArchiveIncoming * Tests * Renamed state field * Store the previous snapshot too, as it's need for considering the penultimate datapoint * Handle the archiving of the penultimate point --- data/swinging-door/trend3.plt | 19 +++ data/swinging-door/trend3_compressed.csv | 7 + data/swinging-door/trend3_mini.plt | 19 +++ data/swinging-door/trend3_mini_compressed.csv | 5 + data/swinging-door/trend3_mini_raw.csv | 6 + data/swinging-door/trend3_raw.csv | 10 ++ .../DataPointIndexedIterator.cs | 130 +++++++++++++----- .../DataPointIterator.Async.cs | 33 +++-- .../DataPointIterator.Enumerable.cs | 73 +++++++--- .../DataPointIterator.cs | 41 ++++-- source/gfoidl.DataCompression/ICompression.cs | 4 +- .../SwingingDoorCompressionTests/Base.cs | 25 ++-- 12 files changed, 287 insertions(+), 85 deletions(-) create mode 100644 data/swinging-door/trend3.plt create mode 100644 data/swinging-door/trend3_compressed.csv create mode 100644 data/swinging-door/trend3_mini.plt create mode 100644 data/swinging-door/trend3_mini_compressed.csv create mode 100644 data/swinging-door/trend3_mini_raw.csv create mode 100644 data/swinging-door/trend3_raw.csv diff --git a/data/swinging-door/trend3.plt b/data/swinging-door/trend3.plt new file mode 100644 index 0000000..a982c2e --- /dev/null +++ b/data/swinging-door/trend3.plt @@ -0,0 +1,19 @@ +reset + +#set terminal dumb + +set grid +set title 'Swinging door compression -- Trend3' +set xlabel 'Time' +set ylabel 'Value' + +set xrange [0:10] +set yrange [-3:6] + +set style line 2 lc rgb 'green' pt 9 # triangle + +#set datafile separator ";" + +# replot is also possible for the second plot +plot 'trend3_raw.csv' with linespoints title 'raw', \ + 'trend3_compressed.csv' with points ls 2 title 'compressed' diff --git a/data/swinging-door/trend3_compressed.csv b/data/swinging-door/trend3_compressed.csv new file mode 100644 index 0000000..95d4073 --- /dev/null +++ b/data/swinging-door/trend3_compressed.csv @@ -0,0 +1,7 @@ +#x y +1 0 +4 5 +5 -2 +6 5 +8 3 +9 5 diff --git a/data/swinging-door/trend3_mini.plt b/data/swinging-door/trend3_mini.plt new file mode 100644 index 0000000..364be3f --- /dev/null +++ b/data/swinging-door/trend3_mini.plt @@ -0,0 +1,19 @@ +reset + +#set terminal dumb + +set grid +set title 'Swinging door compression -- Trend3 (minimal repro)' +set xlabel 'Time' +set ylabel 'Value' + +set xrange [4:10] +set yrange [-3:6] + +set style line 2 lc rgb 'green' pt 9 # triangle + +#set datafile separator ";" + +# replot is also possible for the second plot +plot 'trend3_mini_raw.csv' with linespoints title 'raw', \ + 'trend3_mini_compressed.csv' with points ls 2 title 'compressed' diff --git a/data/swinging-door/trend3_mini_compressed.csv b/data/swinging-door/trend3_mini_compressed.csv new file mode 100644 index 0000000..0f3c159 --- /dev/null +++ b/data/swinging-door/trend3_mini_compressed.csv @@ -0,0 +1,5 @@ +#x y +5 -2 +6 5 +8 3 +9 5 diff --git a/data/swinging-door/trend3_mini_raw.csv b/data/swinging-door/trend3_mini_raw.csv new file mode 100644 index 0000000..517ba0b --- /dev/null +++ b/data/swinging-door/trend3_mini_raw.csv @@ -0,0 +1,6 @@ +#x y +5 -2 +6 5 +7 4 +8 3 +9 5 diff --git a/data/swinging-door/trend3_raw.csv b/data/swinging-door/trend3_raw.csv new file mode 100644 index 0000000..cbc6891 --- /dev/null +++ b/data/swinging-door/trend3_raw.csv @@ -0,0 +1,10 @@ +#x y +1 0 +2 1 +3 2 +4 5 +5 -2 +6 5 +7 4 +8 3 +9 5 diff --git a/source/gfoidl.DataCompression/DataPointIndexedIterator.cs b/source/gfoidl.DataCompression/DataPointIndexedIterator.cs index 80ecd54..15a7f38 100644 --- a/source/gfoidl.DataCompression/DataPointIndexedIterator.cs +++ b/source/gfoidl.DataCompression/DataPointIndexedIterator.cs @@ -13,9 +13,20 @@ internal sealed class DataPointIndexedIterator : DataPointIterator private DataPointIterator? _wrapperIterator; private TList? _list; private int _snapShotIndex; + private int _previousSnapshotIndex; private int _lastArchivedIndex; private int _incomingIndex; - //----------------------------------------------------------------- + //--------------------------------------------------------------------- + private int SnapShotIndex + { + get => _snapShotIndex; + set + { + _previousSnapshotIndex = _snapShotIndex; + _snapShotIndex = value; + } + } + //--------------------------------------------------------------------- public void SetData(Compression compression, DataPointIterator wrappedIterator, TList source) { Debug.Assert(wrappedIterator is not null); @@ -37,7 +48,7 @@ public override DataPointIterator Clone() return clone; } - //----------------------------------------------------------------- + //--------------------------------------------------------------------- public override bool MoveNext() { Debug.Assert(_list is not null); @@ -58,17 +69,16 @@ public override bool MoveNext() this.Init(_incoming); _lastArchivedIndex = 0; - _snapShotIndex = 0; + this.SnapShotIndex = 0; _state = IterateState; _incomingIndex = 1; return true; } case IterateState: { - TList source = _list; - int snapShotIndex = _snapShotIndex; - int incomingIndex = _incomingIndex; - int lastArchivedIndex = _lastArchivedIndex; + TList source = _list; + int incomingIndex = _incomingIndex; + int lastArchivedIndex = _lastArchivedIndex; while (true) { @@ -87,32 +97,50 @@ public override bool MoveNext() if (!archive.Archive) { this.UpdateFilters(_incoming, _lastArchived); - snapShotIndex = incomingIndex++; + this.SnapShotIndex = incomingIndex++; continue; } - if (!archive.MaxDelta && _lastArchivedIndex != snapShotIndex && (uint)snapShotIndex < (uint)source.Count) + if (!archive.MaxDelta && _lastArchivedIndex != this.SnapShotIndex && (uint)this.SnapShotIndex < (uint)source.Count) { - _lastArchived = source[snapShotIndex]; - _lastArchivedIndex = snapShotIndex; - _snapShotIndex = incomingIndex; + _lastArchived = source[this.SnapShotIndex]; + _lastArchivedIndex = this.SnapShotIndex; + this.SnapShotIndex = incomingIndex; _incomingIndex = incomingIndex; - _state = _archiveIncomingState; + _state = _stateAfterArchive; return true; } - _snapShotIndex = snapShotIndex; _incomingIndex = incomingIndex; goto case ArchivePointState; } - _state = EndOfDataState; incomingIndex--; if (incomingIndex != _lastArchivedIndex) // sentinel check { - _lastArchived = source[incomingIndex]; - return true; + _incomingIndex = incomingIndex; + + if (_previousSnapshotIndex != _lastArchivedIndex) + { + // Construct a door from the last archived point to the + // incoming (final point), and check whether the penultimate + // point is to archive or not. + this.Init(_incoming); + this.UpdateFilters(_incoming, _lastArchived); + _previousSnapShot = _list[_previousSnapshotIndex]; + ref var archive = ref this.IsPointToArchive(_previousSnapShot, _lastArchived); + + if (archive.Archive) + { + _lastArchived = _previousSnapShot; + _state = EndOfDataState; + return true; + } + } + + goto case EndOfDataState; } + goto default; } case ArchiveIncomingState: @@ -128,7 +156,7 @@ public override bool MoveNext() int incomingIndex = _incomingIndex; this.Init(_incoming); this.UpdateFilters(_incoming, _lastArchived); - _incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, _snapShotIndex); + _incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, this.SnapShotIndex); goto case IterateState; } case ArchivePointState: @@ -136,13 +164,28 @@ public override bool MoveNext() int incomingIndex = _incomingIndex; _lastArchived = _list[incomingIndex]; _lastArchivedIndex = incomingIndex; - _snapShotIndex = incomingIndex; + this.SnapShotIndex = incomingIndex; _state = IterateState; this.Init(_incoming); - incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, _snapShotIndex); + incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, this.SnapShotIndex); _incomingIndex = incomingIndex + 1; return true; } + case EndOfDataState: + { + if ((uint)_incomingIndex < (uint)_list.Count) + { + DataPoint incoming = _list[_incomingIndex]; + if (incoming != _lastArchived) // sentinel check + { + _lastArchived = _list[_incomingIndex]; + _state = FinalState; + return true; + } + } + + goto default; + } case InitialState: { ThrowHelper.ThrowInvalidOperation(ThrowHelper.ExceptionResource.GetEnumerator_must_be_called_first); @@ -173,7 +216,7 @@ public override DataPoint[] ToArray() return arrayBuilder.ToArray(); } - //----------------------------------------------------------------- + //--------------------------------------------------------------------- public override List ToList() { Debug.Assert(_list is not null); @@ -198,7 +241,7 @@ private void BuildCollection(TList source, ref TBuilder builder) where TBuilder : ICollectionBuilder { int incomingIndex = 0; - int snapShotIndex = 0; + this.SnapShotIndex = 0; int lastArchivedIndex = 0; if ((uint)incomingIndex >= (uint)source.Count) return; @@ -227,16 +270,16 @@ private void BuildCollection(TList source, ref TBuilder builder) if (!archive.Archive) { this.UpdateFilters(incoming, _lastArchived); - snapShotIndex = incomingIndex++; + this.SnapShotIndex = incomingIndex++; continue; } - if (!archive.MaxDelta && lastArchivedIndex != snapShotIndex && (uint)snapShotIndex < (uint)source.Count) + if (!archive.MaxDelta && lastArchivedIndex != this.SnapShotIndex && (uint)this.SnapShotIndex < (uint)source.Count) { - DataPoint snapShot = source[snapShotIndex]; + DataPoint snapShot = source[this.SnapShotIndex]; _lastArchived = snapShot; - lastArchivedIndex = snapShotIndex; - snapShotIndex = incomingIndex; + lastArchivedIndex = this.SnapShotIndex; + this.SnapShotIndex = incomingIndex; builder.Add(snapShot); if (_archiveIncoming) @@ -249,22 +292,38 @@ private void BuildCollection(TList source, ref TBuilder builder) this.Init(incoming); this.UpdateFilters(incoming, _lastArchived); incomingIndex++; - incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, snapShotIndex); + incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, this.SnapShotIndex); continue; } - _lastArchived = incoming; - lastArchivedIndex = incomingIndex; - snapShotIndex = incomingIndex; + _lastArchived = incoming; + lastArchivedIndex = incomingIndex; + this.SnapShotIndex = incomingIndex; builder.Add(incoming); this.Init(incoming); - incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, snapShotIndex); + incomingIndex = this.HandleSkipMinDeltaX(incomingIndex, this.SnapShotIndex); incomingIndex++; } incomingIndex--; if (incomingIndex != lastArchivedIndex && (uint)incomingIndex < (uint)source.Count) { + if (_previousSnapshotIndex != lastArchivedIndex && (uint)_previousSnapshotIndex < (uint)source.Count) + { + // Construct a door from the last archived point to the + // incoming (final point), and check whether the penultimate + // point is to archive or not. + this.Init(incoming); + this.UpdateFilters(incoming, _lastArchived); + _previousSnapShot = source[_previousSnapshotIndex]; + ref var archive = ref this.IsPointToArchive(_previousSnapShot, _lastArchived); + + if (archive.Archive) + { + builder.Add(_previousSnapShot); + } + } + builder.Add(source[incomingIndex]); } } @@ -322,9 +381,10 @@ protected override void DisposeCore() _wrapperIterator = null; } - _snapShotIndex = -1; - _lastArchivedIndex = -1; - _incomingIndex = -1; + _snapShotIndex = -1; + _previousSnapshotIndex = -1; + _lastArchivedIndex = -1; + _incomingIndex = -1; base.DisposeCore(); } diff --git a/source/gfoidl.DataCompression/DataPointIterator.Async.cs b/source/gfoidl.DataCompression/DataPointIterator.Async.cs index c98c819..e771451 100644 --- a/source/gfoidl.DataCompression/DataPointIterator.Async.cs +++ b/source/gfoidl.DataCompression/DataPointIterator.Async.cs @@ -76,14 +76,14 @@ private async IAsyncEnumerator IterateCore(CancellationToken cancella cancellationToken.ThrowIfCancellationRequested(); _lastArchived = incoming; - _snapShot = incoming; + this.SnapShot = incoming; this.Init(incoming); continue; } if (isSkipMinDeltaX) { - if ((incoming.X - _snapShot.X) < _minDeltaX) + if ((incoming.X - this.SnapShot.X) < _minDeltaX) continue; isSkipMinDeltaX = false; @@ -96,17 +96,17 @@ private async IAsyncEnumerator IterateCore(CancellationToken cancella if (!_archive.Archive) { this.UpdateFilters(incoming, _lastArchived); - _snapShot = incoming; + this.SnapShot = incoming; continue; } - if (!_archive.MaxDelta && _lastArchived != _snapShot) + if (!_archive.MaxDelta && _lastArchived != this.SnapShot) { - yield return _snapShot; + yield return this.SnapShot; cancellationToken.ThrowIfCancellationRequested(); - _lastArchived = _snapShot; - _snapShot = incoming; + _lastArchived = this.SnapShot; + this.SnapShot = incoming; if (_archiveIncoming) { @@ -127,14 +127,31 @@ private async IAsyncEnumerator IterateCore(CancellationToken cancella cancellationToken.ThrowIfCancellationRequested(); _lastArchived = incoming; - _snapShot = incoming; + this.SnapShot = incoming; isSkipMinDeltaX = _minDeltaX.HasValue; this.Init(incoming); } cancellationToken.ThrowIfCancellationRequested(); if (_incoming != _lastArchived) // sentinel-check + { + if (_previousSnapShot != _lastArchived) + { + // Construct a door from the last archived point to the + // incoming (final point), and check whether the penultimate + // point is to archive or not. + this.Init(_incoming); + this.UpdateFilters(_incoming, _lastArchived); + this.IsPointToArchive(_previousSnapShot, _lastArchived); + + if (_archive.Archive) + { + yield return _previousSnapShot; + } + } + yield return _incoming; + } } //--------------------------------------------------------------------- private protected virtual async ValueTask BuildCollectionAsync(TBuilder builder, CancellationToken cancellationToken) diff --git a/source/gfoidl.DataCompression/DataPointIterator.Enumerable.cs b/source/gfoidl.DataCompression/DataPointIterator.Enumerable.cs index da36168..56e4943 100644 --- a/source/gfoidl.DataCompression/DataPointIterator.Enumerable.cs +++ b/source/gfoidl.DataCompression/DataPointIterator.Enumerable.cs @@ -42,7 +42,7 @@ public virtual bool MoveNext() if (!_enumerator.MoveNext()) return false; _incoming = _enumerator.Current; _lastArchived = _incoming; - _snapShot = _incoming; + this.SnapShot = _incoming; _state = IterateState; this.Init(_incoming); return true; @@ -57,15 +57,15 @@ public virtual bool MoveNext() if (!archive.Archive) { this.UpdateFilters(_incoming, _lastArchived); - _snapShot = _incoming; + this.SnapShot = _incoming; continue; } - if (!archive.MaxDelta && _lastArchived != _snapShot) + if (!archive.MaxDelta && _lastArchived != this.SnapShot) { - _lastArchived = _snapShot; - _snapShot = _incoming; - _state = _archiveIncomingState; + _lastArchived = this.SnapShot; + this.SnapShot = _incoming; + _state = _stateAfterArchive; return true; } @@ -73,12 +73,28 @@ public virtual bool MoveNext() goto case ArchivePointState; } - _state = EndOfDataState; if (_incoming != _lastArchived) // sentinel check { - _lastArchived = _incoming; - return true; + if (_previousSnapShot != _lastArchived) + { + // Construct a door from the last archived point to the + // incoming (final point), and check whether the penultimate + // point is to archive or not. + this.Init(_incoming); + this.UpdateFilters(_incoming, _lastArchived); + ref var archive = ref this.IsPointToArchive(_previousSnapShot, _lastArchived); + + if (archive.Archive) + { + _lastArchived = _previousSnapShot; + _state = EndOfDataState; + return true; + } + } + + goto case EndOfDataState; } + goto default; } case ArchiveIncomingState: @@ -97,12 +113,18 @@ public virtual bool MoveNext() case ArchivePointState: { _lastArchived = _incoming; - _snapShot = _incoming; + this.SnapShot = _incoming; _state = IterateState; this.Init(_incoming); this.HandleSkipMinDeltaX(_enumerator); return true; } + case EndOfDataState: + { + _lastArchived = _incoming; + _state = FinalState; + return true; + } case InitialState: { ThrowHelper.ThrowInvalidOperation(ThrowHelper.ExceptionResource.GetEnumerator_must_be_called_first); @@ -155,7 +177,7 @@ private void BuildCollection(IEnumerator enumerator, ref TB DataPoint incoming = enumerator.Current; _lastArchived = incoming; - DataPoint snapShot = incoming; + this.SnapShot = incoming; this.Init(incoming); builder.Add(incoming); @@ -168,15 +190,15 @@ private void BuildCollection(IEnumerator enumerator, ref TB if (!archive.Archive) { this.UpdateFilters(incoming, _lastArchived); - snapShot = incoming; + this.SnapShot = incoming; continue; } - if (!archive.MaxDelta && _lastArchived != snapShot) + if (!archive.MaxDelta && _lastArchived != this.SnapShot) { - builder.Add(snapShot); - _lastArchived = snapShot; - snapShot = incoming; + builder.Add(this.SnapShot); + _lastArchived = this.SnapShot; + this.SnapShot = incoming; if (_archiveIncoming) { @@ -191,7 +213,7 @@ private void BuildCollection(IEnumerator enumerator, ref TB } _lastArchived = incoming; - snapShot = incoming; + this.SnapShot = incoming; builder.Add(incoming); this.Init(incoming); this.HandleSkipMinDeltaX(enumerator); @@ -199,6 +221,21 @@ private void BuildCollection(IEnumerator enumerator, ref TB if (incoming != _lastArchived) // sentinel-check { + if (_previousSnapShot != _lastArchived) + { + // Construct a door from the last archived point to the + // incoming (final point), and check whether the penultimate + // point is to archive or not. + this.Init(incoming); + this.UpdateFilters(incoming, _lastArchived); + ref var archive = ref this.IsPointToArchive(_previousSnapShot, _lastArchived); + + if (archive.Archive) + { + builder.Add(_previousSnapShot); + } + } + builder.Add(incoming); } } @@ -218,7 +255,7 @@ private void SkipMinDeltaX(IEnumerator enumerator) Debug.Assert(_minDeltaX.HasValue); double minDeltaX = _minDeltaX.GetValueOrDefault(); - double snapShotX = _snapShot.X; + double snapShotX = this.SnapShot.X; while (enumerator.MoveNext()) { diff --git a/source/gfoidl.DataCompression/DataPointIterator.cs b/source/gfoidl.DataCompression/DataPointIterator.cs index 784470e..3a3c6b5 100644 --- a/source/gfoidl.DataCompression/DataPointIterator.cs +++ b/source/gfoidl.DataCompression/DataPointIterator.cs @@ -19,20 +19,22 @@ public abstract partial class DataPointIterator : IEnumerable, IEnume { private protected const int DisposedState = -3; private protected const int InitialState = -2; - private protected const int EndOfDataState = -1; private protected const int StartOfDataState = 0; private protected const int IterateState = 1; private protected const int ArchiveIncomingState = 2; private protected const int PostArchiveState = 3; private protected const int ArchivePointState = 4; + private protected const int EndOfDataState = 5; + private protected const int FinalState = -1; //--------------------------------------------------------------------- private protected Compression? _algorithm; private protected int _state = InitialState; private protected (bool Archive, bool MaxDelta) _archive; private protected DataPoint _lastArchived; - private protected DataPoint _snapShot; + private protected DataPoint _previousSnapShot; private protected DataPoint _incoming; + private DataPoint _snapShot; private int _threadId; @@ -40,7 +42,17 @@ public abstract partial class DataPointIterator : IEnumerable, IEnume private protected double? _maxDeltaX; private protected double? _minDeltaX; private protected bool _archiveIncoming; - private protected int _archiveIncomingState; + private protected int _stateAfterArchive; + //--------------------------------------------------------------------- + private protected DataPoint SnapShot + { + get => _snapShot; + set + { + _previousSnapShot = _snapShot; + _snapShot = value; + } + } //--------------------------------------------------------------------- /// /// Sets the algorithm for this . @@ -49,13 +61,13 @@ protected void SetData(Compression algorithm) { if (algorithm is null) ThrowHelper.ThrowArgumentNull(ThrowHelper.ExceptionArgument.algorithm); - _state = InitialState; - _threadId = Environment.CurrentManagedThreadId; - _algorithm = algorithm; - _maxDeltaX = algorithm.MaxDeltaX; - _minDeltaX = algorithm.MinDeltaX; - _archiveIncoming = algorithm.ArchiveIncoming; - _archiveIncomingState = _archiveIncoming ? ArchiveIncomingState : PostArchiveState; + _state = InitialState; + _threadId = Environment.CurrentManagedThreadId; + _algorithm = algorithm; + _maxDeltaX = algorithm.MaxDeltaX; + _minDeltaX = algorithm.MinDeltaX; + _archiveIncoming = algorithm.ArchiveIncoming; + _stateAfterArchive = _archiveIncoming ? ArchiveIncomingState : PostArchiveState; } //--------------------------------------------------------------------- /// @@ -187,10 +199,11 @@ protected virtual void DisposeCore() _threadId = -1; _state = DisposedState; - _snapShot = default; - _lastArchived = default; - _incoming = default; - _archive = default; + _snapShot = default; + _previousSnapShot = default; + _lastArchived = default; + _incoming = default; + _archive = default; #if NETSTANDARD2_1 _asyncSource = null; diff --git a/source/gfoidl.DataCompression/ICompression.cs b/source/gfoidl.DataCompression/ICompression.cs index 55d95b7..5b2a0e7 100644 --- a/source/gfoidl.DataCompression/ICompression.cs +++ b/source/gfoidl.DataCompression/ICompression.cs @@ -11,13 +11,13 @@ namespace gfoidl.DataCompression public interface ICompression { /// - /// When set to true the incoming is value archived in addition + /// When set to true the incoming value is archived in addition /// to the last snapshot. /// /// /// For instance in the the last snapshot /// is archived, as well as the current incoming value, therefore this property - /// is set to true. + /// is set to true.
/// In the only the last snapshot is /// archived, so this property is set to false. ///
diff --git a/tests/gfoidl.DataCompression.Tests/Compression/SwingingDoorCompressionTests/Base.cs b/tests/gfoidl.DataCompression.Tests/Compression/SwingingDoorCompressionTests/Base.cs index c3df51d..edc4c46 100644 --- a/tests/gfoidl.DataCompression.Tests/Compression/SwingingDoorCompressionTests/Base.cs +++ b/tests/gfoidl.DataCompression.Tests/Compression/SwingingDoorCompressionTests/Base.cs @@ -21,16 +21,23 @@ protected static IEnumerable IEnumerableTestCases() yield return new TestCaseData(1.0, RawDataForTrend() , ExpectedForTrend()) .SetName("{m} trend"); yield return new TestCaseData(0.1, RawDataForTrend1(), ExpectedForTrend1()).SetName("{m} trend1"); yield return new TestCaseData(0.1, RawDataForTrend2(), ExpectedForTrend2()).SetName("{m} trend2"); + yield return new TestCaseData(2.0, RawDataForTrend3(), ExpectedForTrend3()).SetName("{m} trend3"); + yield return new TestCaseData(2.0, RawDataForTrend3Mini(), ExpectedForTrend3Mini()).SetName("{m} trend3_mini"); } //--------------------------------------------------------------------- - protected static IEnumerable RawDataForTrend() => s_ser.Read("data/swinging-door/trend_raw.csv"); - protected static IEnumerable ExpectedForTrend() => s_ser.Read("data/swinging-door/trend_compressed.csv"); - protected static IEnumerable RawDataForTrend1() => s_ser.Read("data/swinging-door/trend1_raw.csv"); - protected static IEnumerable ExpectedForTrend1() => s_ser.Read("data/swinging-door/trend1_compressed.csv"); - protected static IEnumerable RawDataForTrend2() => s_ser.Read("data/swinging-door/trend2_raw.csv"); - protected static IEnumerable ExpectedForTrend2() => s_ser.Read("data/swinging-door/trend2_compressed.csv"); - protected static IEnumerable RawDataForMaxDelta() => s_ser.Read("data/swinging-door/maxDelta_raw.csv"); - protected static IEnumerable ExpectedForMaxDelta() => s_ser.Read("data/swinging-door/maxDelta_compressed.csv"); + protected static IEnumerable RawDataForTrend() => s_ser.Read("data/swinging-door/trend_raw.csv"); + protected static IEnumerable RawDataForTrend1() => s_ser.Read("data/swinging-door/trend1_raw.csv"); + protected static IEnumerable RawDataForTrend2() => s_ser.Read("data/swinging-door/trend2_raw.csv"); + protected static IEnumerable RawDataForTrend3() => s_ser.Read("data/swinging-door/trend3_raw.csv"); + protected static IEnumerable RawDataForTrend3Mini() => s_ser.Read("data/swinging-door/trend3_mini_raw.csv"); + protected static IEnumerable RawDataForMaxDelta() => s_ser.Read("data/swinging-door/maxDelta_raw.csv"); + + protected static IEnumerable ExpectedForTrend() => s_ser.Read("data/swinging-door/trend_compressed.csv"); + protected static IEnumerable ExpectedForTrend1() => s_ser.Read("data/swinging-door/trend1_compressed.csv"); + protected static IEnumerable ExpectedForTrend2() => s_ser.Read("data/swinging-door/trend2_compressed.csv"); + protected static IEnumerable ExpectedForTrend3() => s_ser.Read("data/swinging-door/trend3_compressed.csv"); + protected static IEnumerable ExpectedForTrend3Mini() => s_ser.Read("data/swinging-door/trend3_mini_compressed.csv"); + protected static IEnumerable ExpectedForMaxDelta() => s_ser.Read("data/swinging-door/maxDelta_compressed.csv"); //--------------------------------------------------------------------- protected static IEnumerable RawMinDeltaX() { @@ -64,6 +71,8 @@ protected static IEnumerable IAsyncEnumerableTestCases() yield return new TestCaseData(1.0, RawDataAsync(RawDataForTrend()) , ExpectedForTrend()) .SetName("{m} trend"); yield return new TestCaseData(0.1, RawDataAsync(RawDataForTrend1()), ExpectedForTrend1()).SetName("{m} trend1"); yield return new TestCaseData(0.1, RawDataAsync(RawDataForTrend2()), ExpectedForTrend2()).SetName("{m} trend2"); + yield return new TestCaseData(2.0, RawDataAsync(RawDataForTrend3()), ExpectedForTrend3()).SetName("{m} trend3"); + yield return new TestCaseData(2.0, RawDataAsync(RawDataForTrend3Mini()), ExpectedForTrend3Mini()).SetName("{m} trend3_mini"); } //--------------------------------------------------------------------- protected static async IAsyncEnumerable RawDataAsync(IEnumerable rawData, [EnumeratorCancellation] CancellationToken ct = default)