Skip to content

Commit ae2bad0

Browse files
committed
read me
1 parent 0649284 commit ae2bad0

File tree

11 files changed

+361
-25
lines changed

11 files changed

+361
-25
lines changed

Directory.Build.props

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
<Project>
22
<!--NuGet-->
33
<PropertyGroup>
4-
<EmbedUntrackedSources>true</EmbedUntrackedSources>
5-
<PublishRepositoryUrl>true</PublishRepositoryUrl>
64
<Authors>ManagedCode</Authors>
75
<Copyright>Copyright © 2021-$([System.DateTime]::Now.ToString(`yyyy`)) ManagedCode SAS</Copyright>
8-
<RepositoryUrl>https://github.com/managed-code-hub/Storage</RepositoryUrl>
9-
<PackageProjectUrl>https://github.com/managed-code-hub/Storage</PackageProjectUrl>
6+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
7+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
8+
<IncludeSymbols>true</IncludeSymbols>
9+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
1010
<RepositoryType>Github</RepositoryType>
1111
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
1212
<PackageIcon>logo.png</PackageIcon>
1313
<PackageLicenseExpression>MIT</PackageLicenseExpression>
14+
<EnablePackageValidation>true</EnablePackageValidation>
1415
<PackageReadmeFile>README.md</PackageReadmeFile>
16+
17+
<RepositoryUrl>https://github.com/managedcode/TimeSeries</RepositoryUrl>
18+
<PackageProjectUrl>https://github.com/managedcode/TimeSeries</PackageProjectUrl>
1519
<Product>Managed Code - TimeSeries</Product>
16-
<Version>0.0.12</Version>
17-
<PackageVersion>0.0.12</PackageVersion>
20+
<Version>0.0.15</Version>
21+
<PackageVersion>0.0.15</PackageVersion>
22+
1823
</PropertyGroup>
1924
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
2025
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
@@ -23,4 +28,10 @@
2328
<None Include="$(SolutionDir)\logo.png" Pack="true" Visible="false" PackagePath="\"/>
2429
<None Include="$(SolutionDir)\README.md" Pack="true" Visible="false" PackagePath="\"/>
2530
</ItemGroup>
31+
<ItemGroup>
32+
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.1.1">
33+
<PrivateAssets>all</PrivateAssets>
34+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
35+
</PackageReference>
36+
</ItemGroup>
2637
</Project>

ManagedCode.TimeSeries.Benchmark/ManagedCode.TimeSeries.Benchmark.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>net7.0</TargetFramework>
6+
<LangVersion>11</LangVersion>
67
<ImplicitUsings>enable</ImplicitUsings>
78
<Nullable>enable</Nullable>
89
<IsPackable>false</IsPackable>
9-
<LangVersion>11</LangVersion>
1010
</PropertyGroup>
1111

1212
<ItemGroup>
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
using FluentAssertions;
2+
using ManagedCode.TimeSeries.Accumulators;
3+
using Xunit;
4+
5+
namespace ManagedCode.TimeSeries.Tests;
6+
7+
public class AccumulatorsTests
8+
{
9+
10+
[Fact]
11+
public async Task IntTimeSeriesAccumulator()
12+
{
13+
int count = 1050;
14+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1));
15+
for (int i = 0; i < count; i++)
16+
{
17+
await Task.Delay(new Random().Next(1, 5));
18+
series.AddNewData(i);
19+
}
20+
21+
series.DataCount.Should().Be(Convert.ToUInt64(count));
22+
23+
var step = 0;
24+
foreach (var queue in series.Samples)
25+
{
26+
foreach (var item in queue.Value)
27+
{
28+
item.Should().Be(step);
29+
step++;
30+
}
31+
}
32+
}
33+
34+
[Fact]
35+
public async Task IntTimeSeriesAccumulatorMaxSamplesCount()
36+
{
37+
int samplesCount = 105;
38+
int count = 1050;
39+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), samplesCount);
40+
for (int i = 0; i < count; i++)
41+
{
42+
await Task.Delay(new Random().Next(1, 5));
43+
series.AddNewData(i);
44+
}
45+
46+
series.DataCount.Should().Be(Convert.ToUInt64(count)); //because it's total; number of samples
47+
series.Samples.Count.Should().Be(samplesCount); //because it's total; number of samples
48+
49+
var step = count - samplesCount - 1;
50+
foreach (var queue in series.Samples)
51+
{
52+
foreach (var item in queue.Value)
53+
{
54+
item.Should().Be(step);
55+
step++;
56+
}
57+
}
58+
}
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+
70+
71+
[Fact]
72+
public async Task Accumulator()
73+
{
74+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1));
75+
for (var i = 0; i < 1000; i++)
76+
{
77+
await Task.Delay(new Random().Next(1, 5));
78+
series.AddNewData(i);
79+
}
80+
81+
series.DataCount.Should().Be(1000);
82+
83+
var step = 0;
84+
foreach (var queue in series.Samples)
85+
{
86+
foreach (var item in queue.Value)
87+
{
88+
item.Should().Be(step);
89+
step++;
90+
}
91+
}
92+
}
93+
94+
// [Fact]
95+
// public async Task AccumulatorByString()
96+
// {
97+
// var rnd = new Random();
98+
// var series = new StringTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1));
99+
//
100+
// var dt = DateTimeOffset.Now;
101+
// series.AddNewData(dt, "1");
102+
// series.AddNewData(dt, "1");
103+
// series.AddNewData(dt, "2");
104+
// series.AddNewData(dt, "3");
105+
// series.AddNewData(dt, "3");
106+
// series.AddNewData(dt, "2");
107+
//
108+
//
109+
// dt = dt.AddHours(5);
110+
// series.AddNewData(dt, "1");
111+
// series.AddNewData(dt, "1");
112+
// series.AddNewData(dt, "2");
113+
// series.AddNewData(dt, "3");
114+
// series.AddNewData(dt, "3");
115+
// series.AddNewData(dt, "2");
116+
//
117+
// series.DataCount.Should().Be(12);
118+
// series.Samples.First().Value.Count.Should().Be(3);
119+
// series.Samples.Last().Value.Count.Should().Be(3);
120+
// }
121+
122+
[Fact]
123+
public async Task AccumulatorLimit()
124+
{
125+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), 10);
126+
127+
for (var i = 0; i < 1000; i++)
128+
{
129+
await Task.Delay(new Random().Next(1, 5));
130+
series.AddNewData(i);
131+
}
132+
133+
series.Samples.Count.Should().Be(10);
134+
}
135+
136+
[Fact]
137+
public async Task IsFull()
138+
{
139+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), 10);
140+
141+
for (var i = 0; i < 1000; i++)
142+
{
143+
await Task.Delay(new Random().Next(1, 5));
144+
145+
if (series.IsFull)
146+
{
147+
break;
148+
}
149+
150+
series.AddNewData(i);
151+
}
152+
153+
series.IsFull.Should().BeTrue();
154+
}
155+
156+
[Fact]
157+
public void IsEmpty()
158+
{
159+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), 10);
160+
series.IsEmpty.Should().BeTrue();
161+
}
162+
163+
[Fact]
164+
public async Task AccumulatorMerge()
165+
{
166+
Func<Task<IntTimeSeriesAccumulator>> FillFunc = async () =>
167+
{
168+
var series = new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), 10);
169+
for (var i = 0; i < 1000; i++)
170+
{
171+
await Task.Delay(new Random().Next(1, 5));
172+
series.AddNewData(i);
173+
}
174+
175+
return series;
176+
};
177+
178+
var seriesA = FillFunc();
179+
var seriesB = FillFunc();
180+
181+
await Task.WhenAll(seriesA, seriesB);
182+
183+
seriesA.Result.Samples.Count.Should().Be(10);
184+
seriesB.Result.Samples.Count.Should().Be(10);
185+
186+
seriesA.Result.Merge(seriesB.Result);
187+
188+
seriesA.Result.Samples.Count.Should().Be(10);
189+
190+
var seriesList = new List<IntTimeSeriesAccumulator>();
191+
seriesList.Add(await FillFunc());
192+
seriesList.Add(await FillFunc());
193+
seriesList.Add(await FillFunc());
194+
seriesList.Add(new IntTimeSeriesAccumulator(TimeSpan.FromSeconds(0.1), 10));
195+
196+
IntTimeSeriesAccumulator onlineExpertsPerHourTimeSeries = null;
197+
foreach (var item in seriesList.ToArray())
198+
{
199+
if (onlineExpertsPerHourTimeSeries == null)
200+
{
201+
onlineExpertsPerHourTimeSeries = item;
202+
}
203+
else
204+
{
205+
onlineExpertsPerHourTimeSeries.Merge(item);
206+
}
207+
}
208+
209+
onlineExpertsPerHourTimeSeries.Samples.Count.Should().Be(10);
210+
}
211+
212+
213+
[Fact]
214+
public async Task Resample()
215+
{
216+
var seriesFeature = new IntTimeSeriesAccumulator(TimeSpan.FromMilliseconds(2), 100);
217+
218+
for (var i = 0; i < 100; i++)
219+
{
220+
seriesFeature.AddNewData(i);
221+
222+
await Task.Delay(1);
223+
}
224+
225+
seriesFeature.Resample(TimeSpan.FromMilliseconds(4), 100);
226+
var sad = seriesFeature;
227+
}
228+
229+
230+
231+
[Fact]
232+
public void MarkupAllSamples()
233+
{
234+
var seriesFeature = new IntTimeSeriesAccumulator(TimeSpan.FromMilliseconds(10), 100);
235+
seriesFeature.MarkupAllSamples(MarkupDirection.Feature);
236+
seriesFeature.AddNewData(1);
237+
(seriesFeature.Samples.Keys.Max() - seriesFeature.Samples.Keys.Min()).TotalMilliseconds.Should().BeGreaterThanOrEqualTo(990);
238+
(seriesFeature.Samples.Keys.Max() - seriesFeature.Samples.Keys.Min()).TotalMilliseconds.Should().BeLessThanOrEqualTo(1000);
239+
var seriesFeatureOrdered = seriesFeature.Samples.OrderBy(o => o.Key).Take(10);
240+
seriesFeatureOrdered.Any(a => a.Value.Count == 1).Should().BeTrue();
241+
242+
var seriesPast = new IntTimeSeriesAccumulator(TimeSpan.FromMilliseconds(10));
243+
seriesPast.MarkupAllSamples();
244+
seriesPast.AddNewData(1);
245+
(seriesPast.Samples.Keys.Max() - seriesPast.Samples.Keys.Min()).TotalMilliseconds.Should().BeGreaterThanOrEqualTo(990);
246+
(seriesPast.Samples.Keys.Max() - seriesPast.Samples.Keys.Min()).TotalMilliseconds.Should().BeLessThanOrEqualTo(1000);
247+
var seriesPastOrdered = seriesPast.Samples.OrderBy(o => o.Key).TakeLast(10);
248+
seriesPastOrdered.Any(a => a.Value.Count == 1).Should().BeTrue();
249+
250+
var seriesMiddle = new IntTimeSeriesAccumulator(TimeSpan.FromMilliseconds(10), 100);
251+
seriesMiddle.MarkupAllSamples(MarkupDirection.Middle);
252+
seriesMiddle.AddNewData(1);
253+
(seriesMiddle.Samples.Keys.Max() - seriesMiddle.Samples.Keys.Min()).TotalMilliseconds.Should().BeGreaterThanOrEqualTo(990);
254+
(seriesMiddle.Samples.Keys.Max() - seriesMiddle.Samples.Keys.Min()).TotalMilliseconds.Should().BeLessThanOrEqualTo(1000);
255+
var seriesMiddleOrdered = seriesMiddle.Samples.OrderBy(o => o.Key).Skip(45).Take(10);
256+
seriesMiddleOrdered.Any(a => a.Value.Count == 1).Should().BeTrue();
257+
}
258+
}

ManagedCode.TimeSeries.Tests/ManagedCode.TimeSeries.Tests.csproj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
<PropertyGroup>
44
<TargetFramework>net7.0</TargetFramework>
5+
<LangVersion>11</LangVersion>
56
<ImplicitUsings>enable</ImplicitUsings>
67
<Nullable>enable</Nullable>
7-
88
<IsPackable>false</IsPackable>
9-
10-
<LangVersion>11</LangVersion>
119
</PropertyGroup>
1210

1311
<ItemGroup>

ManagedCode.TimeSeries.Tests/TimeSeriesTests.cs renamed to ManagedCode.TimeSeries.Tests/SummersTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace ManagedCode.TimeSeries.Tests;
77

8-
public class TimeSeriesTests
8+
public class SummersTests
99
{
1010
[Fact]
1111
public async Task Accumulator()

ManagedCode.TimeSeries/Abstractions/BaseGroupTimeSeriesSummer.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,17 @@
22

33
namespace ManagedCode.TimeSeries.Abstractions;
44

5-
public abstract class BaseGroupTimeSeriesSummer<TNumber, TSummer, TSelf>
5+
public abstract class BaseGroupTimeSeriesSummer<TNumber, TSummer, TSelf> : IDisposable
66
where TSummer : BaseTimeSeriesSummer<TNumber, TSelf>
77
where TNumber : INumber<TNumber>
88
where TSelf : BaseTimeSeries<TNumber, TNumber, TSelf>
99
{
10-
private readonly Strategy _strategy;
11-
private readonly bool _deleteOverdueSamples;
12-
private readonly Timer _timer;
10+
private readonly Timer? _timer;
1311
public readonly Dictionary<string, TSummer> TimeSeries = new();
1412

1513
protected BaseGroupTimeSeriesSummer(TimeSpan sampleInterval, bool deleteOverdueSamples)
1614
{
17-
if (deleteOverdueSamples)
18-
{
19-
_timer = new Timer(Callback, null, sampleInterval, sampleInterval);
20-
}
15+
_timer = deleteOverdueSamples ? new Timer(Callback, null, sampleInterval, sampleInterval) : null;
2116
}
2217

2318
private void Callback(object? state)

ManagedCode.TimeSeries/Abstractions/BaseTimeSeries.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
namespace ManagedCode.TimeSeries.Abstractions;
55

6-
public abstract class BaseTimeSeries<T, TSample, TSelf> : ITimeSeries<T, TSelf> where TSelf : BaseTimeSeries<T, TSample, TSelf>
6+
public abstract class BaseTimeSeries<T, TSample, TSelf> :
7+
ITimeSeries<T, TSelf> where TSelf : BaseTimeSeries<T, TSample, TSelf>
78
{
89
private const int DefaultSampleCount = 100;
9-
protected readonly object _sync = new();
10+
private readonly object _sync = new();
1011

1112
protected BaseTimeSeries(TimeSpan sampleInterval, int maxSamplesCount)
1213
{

ManagedCode.TimeSeries/Abstractions/BaseTimeSeriesSummer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ public virtual void Decrement()
9797
public virtual TNumber Average()
9898
{
9999
var sum = Sum();
100-
101100
return TNumber.CreateChecked(sum) / TNumber.CreateChecked(Samples.Count);
102101
}
103102

0 commit comments

Comments
 (0)