From a575c1163d70c6288760e10a1f52c3c501d0feb5 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 3 Nov 2022 16:57:41 +0500 Subject: [PATCH] Add CyclycArray --- AsbCloudApp/CyclycArray.cs | 194 ++++++++++++++++++ .../Services/SAUB/TelemetryDataCache.cs | 23 +++ ConsoleApp1/Program.cs | 21 +- ConsoleApp1/ServiceFactory.cs | 2 +- 4 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 AsbCloudApp/CyclycArray.cs create mode 100644 AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs diff --git a/AsbCloudApp/CyclycArray.cs b/AsbCloudApp/CyclycArray.cs new file mode 100644 index 00000000..4a479f66 --- /dev/null +++ b/AsbCloudApp/CyclycArray.cs @@ -0,0 +1,194 @@ +#nullable enable +using System.Linq; + +namespace System.Collections.Generic +{ + /// + /// Цикличный массив + /// + /// + public class CyclycArray : IEnumerable + { + readonly T[] array; + int used, current = -1; + + /// + /// constructor + /// + /// + public CyclycArray(int capacity) + { + array = new T[capacity]; + } + + /// + /// Количество элементов в массиве + /// + public int Count => used; + + /// + /// Добавить новый элемент
+ /// Если capacity достигнуто, то вытеснит самый первый элемент + ///
+ /// + public void Add(T item) + { + current = (++current) % array.Length; + array[current] = item; + if (used < array.Length) + used++; + UpdatedInvoke(current, item); + } + + /// + /// Добавить новые элементы.
+ /// Если capacity достигнуто, то вытеснит самые первые элементы.
+ /// Не вызывает Updated! + ///
+ /// + public void AddRange(IEnumerable items) + { + var capacity = array.Length; + var newItems = items.TakeLast(capacity).ToArray(); + if (newItems.Length == capacity) + { + Array.Copy(newItems, array, capacity); + current = capacity - 1; + } + else + { + current = (++current) % capacity; + var countToEndOfArray = capacity - current; + if (newItems.Length <= countToEndOfArray) + { + Array.Copy(newItems, 0, array, current, newItems.Length); + current += newItems.Length - 1; + } + else + { + var firstStepLength = countToEndOfArray; + Array.Copy(newItems, 0, array, current, firstStepLength); + var secondStepCount = newItems.Length - firstStepLength; + Array.Copy(newItems, firstStepLength, array, 0, secondStepCount); + current = secondStepCount - 1; + } + } + + if (used < capacity) + { + used += newItems.Length; + used = used > capacity ? capacity : used; + } + } + + /// + /// Индекс + /// + /// + /// + public T this[int index] + { + get + { + var i = (current + 1 + index) % used; + return array[i]; + } + set + { + var i = (current + 1 + index) % used; + array[i] = value; + UpdatedInvoke(current, value); + } + } + + /// + /// событие на изменение элемента в массиве + /// + public event EventHandler<(int index, T value)>? Updated; + private void UpdatedInvoke(int index, T value) + { + Updated?.Invoke(this, (index, value)); + } + + /// + /// Агрегирование значения по всему массиву + /// + /// + /// + /// + /// + public Tout Aggregate(Func func, Tout startValue) + { + Tout result = startValue; + for (int i = 0; i < used; i++) + result = func(this[i], result); + return result; + } + + /// + public IEnumerator GetEnumerator() + => new CyclycListEnumerator(array, current, used); + + /// + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + class CyclycListEnumerator : IEnumerator + { + private readonly Te[] array; + private readonly int used; + private readonly int first; + private int current = -1; + + public CyclycListEnumerator(Te[] array, int first, int used) + { + this.array = new Te[array.Length]; + array.CopyTo(this.array, 0); + this.used = used; + this.first = first; + } + + public Te Current + { + get + { + if (IsCurrentOk()) + { + var i = (current + first + 1) % used; + return array[i]; + } + else + return default!; + } + } + + object? IEnumerator.Current => Current; + + public void Dispose() {; } + + private bool IsCurrentOk() => current >= 0 && current < used; + + public bool MoveNext() + { + if (current < used) + current++; + return IsCurrentOk(); + } + + public void Reset() + { + current = -1; + } + } + + /// + /// Очистить весь массив + /// + public void Clear() + { + used = 0; + current = -1; + } + } +} +#nullable disable \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs new file mode 100644 index 00000000..b96622fe --- /dev/null +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs @@ -0,0 +1,23 @@ +using AsbCloudDb.Model; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections; +using System; +using AsbCloudApp.Services; + +#nullable enable +namespace AsbCloudInfrastructure.Services.SAUB +{ + public class TelemetryDataCache + { + private readonly ConcurrentDictionary> caches; + private static TelemetryDataCache? instance; + + public TelemetryDataCache(IAsbCloudDbContext db) + { + caches = new (); + } + + } +} +#nullable disable \ No newline at end of file diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index b3d1d6fb..537b9f5a 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -18,6 +18,8 @@ using System.Threading.Tasks; namespace ConsoleApp1 { + + class Program { private static AsbCloudDbContext db = ServiceFactory.Context; @@ -25,12 +27,21 @@ namespace ConsoleApp1 // use ServiceFactory to make services static void Main(/*string[] args*/) { - var h = new Hashtable(); - h.Add("name", 1); - h.Add("name2", "66"); - var v = h["v"]; - var s = System.Text.Json.JsonSerializer.Serialize(h); + var set1 = new int[15].Select((v,i) => i.ToString()); + var set2 = new int[5].Select((v, i) => (i + 1000).ToString()); + var set3 = new int[5].Select((v, i) => (i + 2000).ToString()); + var set4 = new int[5].Select((v, i) => (i + 4000).ToString()); + var set5 = new int[8].Select((v, i) => (i + 5000).ToString()); + var set6 = new int[3].Select((v, i) => (i + 6000).ToString()); + + var ca = new CyclycArray(10); + ca.AddRange(set1); + ca.AddRange(set2); + ca.AddRange(set3); + ca.AddRange(set4); + ca.AddRange(set5); + ca.AddRange(set6); Console.WriteLine($"total time: ms"); Console.ReadLine(); diff --git a/ConsoleApp1/ServiceFactory.cs b/ConsoleApp1/ServiceFactory.cs index df7f8bb4..a1fb9d91 100644 --- a/ConsoleApp1/ServiceFactory.cs +++ b/ConsoleApp1/ServiceFactory.cs @@ -65,7 +65,7 @@ namespace ConsoleApp1 => new TelemetryTracker(CacheDb, ConfigurationService); public static TelemetryService MakeTelemetryService() - => new TelemetryService(Context, MakeTelemetryTracker(), TimezoneService, CacheDb); + => new TelemetryService(Context, MakeTelemetryTracker(), TimezoneService); public static WellService MakeWellService() => new WellService(Context, CacheDb, MakeTelemetryService(), TimezoneService);