Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.21 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Reflection;
  7.  
  8. namespace RemsReachWebServices.Helpers
  9. {
  10. #region Custom Attributes
  11. [AttributeUsage(AttributeTargets.Property)]
  12. public class DoNotCopyIntoTimeWindow : Attribute { } // leave default
  13.  
  14. [AttributeUsage(AttributeTargets.Property)]
  15. public class IsProcessedIntoTimeWindow : Attribute { } // calculate time window for this property
  16.  
  17. [AttributeUsage(AttributeTargets.Property)]
  18. public class IsTimeWindowDate : Attribute { } // attribute to mark property as the datetime
  19.  
  20. [AttributeUsage(AttributeTargets.Property)]
  21. public class IsTimeWindowIdentifier : Attribute { } // this is the time window property
  22. #endregion
  23.  
  24. public class TimeWindow
  25. {
  26. #region Structs
  27. public struct TimeWindowDictionary
  28. {
  29. public PropertyInfo PropertyInfo { get; set; }
  30. public Dictionary<NullObject<dynamic>, int> Dictionary { get; set; }
  31. }
  32.  
  33. public struct NullObject<T>
  34. {
  35. [DefaultValue(true)]
  36. private readonly bool isnull; // default property initializers are not supported for structs
  37.  
  38. private NullObject(T item, bool isnull) : this()
  39. {
  40. this.isnull = isnull;
  41. Item = item;
  42. }
  43.  
  44. public NullObject(T item) : this(item, item == null)
  45. {
  46. }
  47.  
  48. public static NullObject<T> Null()
  49. {
  50. return new NullObject<T>();
  51. }
  52.  
  53. public T Item { get; private set; }
  54.  
  55. public bool IsNull()
  56. {
  57. return isnull;
  58. }
  59.  
  60. public static implicit operator T(NullObject<T> nullObject)
  61. {
  62. return nullObject.Item;
  63. }
  64.  
  65. public static implicit operator NullObject<T>(T item)
  66. {
  67. return new NullObject<T>(item);
  68. }
  69.  
  70. public override string ToString()
  71. {
  72. return (Item != null) ? Item.ToString() : "NULL";
  73. }
  74.  
  75. public override bool Equals(object obj)
  76. {
  77. if (obj == null)
  78. return IsNull();
  79.  
  80. if (!(obj is NullObject<T>))
  81. return false;
  82.  
  83. var no = (NullObject<T>)obj;
  84.  
  85. if (IsNull())
  86. return no.IsNull();
  87.  
  88. if (no.IsNull())
  89. return false;
  90.  
  91. return Item.Equals(no.Item);
  92. }
  93.  
  94. public override int GetHashCode()
  95. {
  96. if (IsNull())
  97. return 0;
  98.  
  99. var result = Item.GetHashCode();
  100.  
  101. if (result >= 0)
  102. result++;
  103.  
  104. return result;
  105. }
  106. }
  107.  
  108. public struct Properties
  109. {
  110. public List<PropertyInfo> PropertiesToProcess { get; set; }
  111. public List<PropertyInfo> CopyProperties { get; set; }
  112. public PropertyInfo TimeWindowIdentifier { get; set; }
  113. public PropertyInfo DatePropertyInfo { get; set; }
  114. public int Size { get; set; }
  115. }
  116. #endregion
  117.  
  118. #region Class Members
  119. private static readonly ConcurrentDictionary<Type, Properties> PropertiesDictionary = new ConcurrentDictionary<Type, Properties>();
  120. #endregion
  121.  
  122. #region Methods
  123. public static IEnumerable<T> CalculateTimeWindows<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels) where T : new()
  124. {
  125. if (stateModels.Count() == 0)
  126. return new List<T>();
  127.  
  128. dateFrom = GetPropertiesAndDictionaries(
  129. dateFrom,
  130. stateModels,
  131. out PropertyInfo datePropertyInfo,
  132. out List<PropertyInfo> copyProperties,
  133. out PropertyInfo timeWindowIdentifier,
  134. out int size,
  135. out TimeWindowDictionary[] dictionaries);
  136.  
  137. byte[] windowDurations = { 5, 15, 60 };
  138.  
  139. return windowDurations.SelectMany(wd =>
  140. CalculateTimeWindow(
  141. dateFrom,
  142. dateTo,
  143. stateModels,
  144. wd,
  145. datePropertyInfo,
  146. copyProperties,
  147. timeWindowIdentifier,
  148. size,
  149. dictionaries));
  150. }
  151.  
  152. public static IEnumerable<T> CalculateTimeWindow<T>(DateTime dateFrom, DateTime dateTo, List<T> stateModels, byte timeWindowMinutes, PropertyInfo datePropertyInfo, List<PropertyInfo> copyProperties, PropertyInfo timeWindowIdentifier, int size, TimeWindowDictionary[] dictionaries) where T : new()
  153. {
  154. if (stateModels.Count() > 0)
  155. {
  156. DateTime currentWindowFrom, currentWindowTo, nextWindowFrom;
  157. nextWindowFrom = dateFrom;
  158. int itemPointer = 0;
  159. T prevItem = default;
  160. T prevTimeWindow = default;
  161.  
  162. int j = 1;
  163.  
  164. do // one time window
  165. {
  166. for (int i = 0; i < size; i++)
  167. dictionaries[i].Dictionary = new Dictionary<NullObject<dynamic>, int>();
  168.  
  169. currentWindowFrom = nextWindowFrom;
  170. nextWindowFrom = currentWindowFrom.AddMinutes(timeWindowMinutes);
  171. currentWindowTo = nextWindowFrom.AddSeconds(-1);
  172.  
  173. var calculateTime = currentWindowFrom;
  174.  
  175. for (; itemPointer < stateModels.Count(); itemPointer++)
  176. {
  177. var item = stateModels.ElementAt(itemPointer);
  178.  
  179. var date = (DateTime)datePropertyInfo.GetValue(item);
  180.  
  181. if (date >= currentWindowTo)
  182. break;
  183.  
  184. var endDate = (date > currentWindowTo) ? nextWindowFrom : date; // state might extend more than the end of the time window
  185. CalculateStateSeconds(prevItem, dictionaries, calculateTime, endDate);
  186.  
  187. prevItem = item;
  188. calculateTime = (date < currentWindowFrom) ? currentWindowFrom : date; // to fix the 'yesterday' date
  189. }
  190.  
  191. if (calculateTime < currentWindowTo)
  192. CalculateStateSeconds(prevItem, dictionaries, calculateTime, nextWindowFrom);
  193.  
  194. if (dictionaries[0].Dictionary.Count > 0)
  195. {
  196. bool sameAsPrevious = (prevTimeWindow != null);
  197. var output = new T();
  198.  
  199. foreach (var dictionary in dictionaries)
  200. {
  201. var maxValue = dictionary.Dictionary.First();
  202. for (j = 1; j < dictionary.Dictionary.Count; j++)
  203. {
  204. var valuePair = dictionary.Dictionary.ElementAt(j);
  205.  
  206. if (valuePair.Value > maxValue.Value)
  207. maxValue = valuePair;
  208. }
  209. var valToSet = maxValue.Key.Item;
  210.  
  211. if (sameAsPrevious)
  212. {
  213. var prevVal = GetValue(prevTimeWindow, dictionary.PropertyInfo);
  214.  
  215. if (!(valToSet == null && prevVal == null))
  216. sameAsPrevious = (valToSet == prevVal);
  217. }
  218.  
  219. SetValue(output, dictionary.PropertyInfo, valToSet);
  220. }
  221.  
  222. if (!sameAsPrevious)
  223. {
  224. foreach (var copyProperty in copyProperties)
  225. SetValue(output, copyProperty, copyProperty.GetValue(prevItem));
  226.  
  227. timeWindowIdentifier.SetValue(output, timeWindowMinutes);
  228.  
  229. datePropertyInfo.SetValue(output, currentWindowFrom);
  230.  
  231. prevTimeWindow = output;
  232.  
  233. yield return output;
  234. }
  235. }
  236. }
  237. while (nextWindowFrom <= dateTo);
  238. }
  239. }
  240.  
  241. private static DateTime GetPropertiesAndDictionaries<T>(DateTime dateFrom, List<T> stateModels, out PropertyInfo datePropertyInfo, out List<PropertyInfo> copyProperties, out PropertyInfo timeWindowIdentifier, out int size, out TimeWindowDictionary[] dictionaries) where T : new()
  242. {
  243. Type tType = typeof(T);
  244. if (!PropertiesDictionary.TryGetValue(tType, out Properties properties))
  245. {
  246. var propInfos = tType.GetProperties();
  247.  
  248. datePropertyInfo = propInfos.Single(p => p.GetCustomAttributes(typeof(IsTimeWindowDate), true).Any());
  249.  
  250. var propertiesToProcess = propInfos.Where(p => p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any()).ToList();
  251.  
  252. copyProperties = propInfos.Where(p => !p.GetCustomAttributes(typeof(IsTimeWindowIdentifier), true).Any() && !p.GetCustomAttributes(typeof(DoNotCopyIntoTimeWindow), true).Any() && !p.GetCustomAttributes(typeof(IsTimeWindowDate), true).Any() && !p.GetCustomAttributes(typeof(IsProcessedIntoTimeWindow), true).Any() && p.CanWrite && !p.GetMethod.IsVirtual).ToList();
  253. timeWindowIdentifier = propInfos.Single(p => p.GetCustomAttributes(typeof(IsTimeWindowIdentifier), true).Any());
  254.  
  255. size = propertiesToProcess.Count();
  256. properties = new Properties()
  257. {
  258. CopyProperties = copyProperties,
  259. DatePropertyInfo = datePropertyInfo,
  260. PropertiesToProcess = propertiesToProcess,
  261. TimeWindowIdentifier = timeWindowIdentifier,
  262. Size = size
  263. };
  264. PropertiesDictionary.TryAdd(tType, properties);
  265. }
  266. else
  267. {
  268. datePropertyInfo = properties.DatePropertyInfo;
  269. copyProperties = properties.CopyProperties;
  270. timeWindowIdentifier = properties.TimeWindowIdentifier;
  271. size = properties.Size;
  272. }
  273.  
  274. dictionaries = properties.PropertiesToProcess
  275. .Select(p => new TimeWindowDictionary { PropertyInfo = p })
  276. .ToArray();
  277.  
  278. var firstDate = (DateTime)datePropertyInfo.GetValue(stateModels.First());
  279.  
  280. if (firstDate < dateFrom)
  281. dateFrom = new DateTime(firstDate.Year, firstDate.Month, firstDate.Day, firstDate.Hour, 0, 0, DateTimeKind.Utc);
  282.  
  283. return dateFrom;
  284. }
  285.  
  286. private static dynamic GetValue(object inputObject, PropertyInfo propertyInfo)
  287. {
  288. return propertyInfo.GetValue(inputObject);
  289. }
  290.  
  291. //private static void SetValue(object inputObject, string propertyName, object propertyVal)
  292. private static void SetValue(object inputObject, PropertyInfo propertyInfo, object propertyVal)
  293. {
  294. if (propertyVal != null)
  295. {
  296. //find the property type
  297. Type propertyType = propertyInfo.PropertyType;
  298.  
  299. //Convert.ChangeType does not handle conversion to nullable types
  300. //if the property type is nullable, we need to get the underlying type of the property
  301. var targetType = IsNullableType(propertyType) ? Nullable.GetUnderlyingType(propertyType) : propertyType;
  302.  
  303. //Returns an System.Object with the specified System.Type and whose value is
  304. //equivalent to the specified object.
  305. propertyVal = Convert.ChangeType(propertyVal, targetType);
  306. }
  307.  
  308. //Set the value of the property
  309. propertyInfo.SetValue(inputObject, propertyVal, null);
  310.  
  311. }
  312.  
  313. private static bool IsNullableType(Type type)
  314. {
  315. return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
  316. }
  317.  
  318. private static void CalculateStateSeconds<T>(T prevItem, IEnumerable<TimeWindowDictionary> dictionaries, DateTime calculateTime, DateTime endDate)
  319. {
  320. if (prevItem != null)
  321. {
  322. var seconds = Convert.ToInt32(endDate.Subtract(calculateTime).TotalSeconds);
  323.  
  324. foreach (var dictionary in dictionaries)
  325. {
  326. var key = dictionary.PropertyInfo.GetValue(prevItem);
  327. dictionary.Dictionary.TryGetValue(key, out int existingSeconds);
  328. dictionary.Dictionary[key] = existingSeconds + seconds;
  329. }
  330. }
  331. }
  332. #endregion
  333. }
  334. }
  335.  
  336. myList1.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList1).ToList());
  337. myList2.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList2).ToList());
  338. myList3.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList3).ToList());
  339. myList4.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList4).ToList());
  340. myList5.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList5).ToList());
  341. myList6.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList6).ToList());
  342. myList7.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList7).ToList());
  343. myList8.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList8).ToList());
  344. myList9.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList9).ToList());
  345. myList10.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList10).ToList());
  346. myList11.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList11).ToList());
  347. myList12.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList12).ToList());
  348. myList13.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList13).ToList());
  349. myList14.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList14).ToList());
  350. myList15.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList15).ToList());
  351. myList16.AddRange(TimeWindow.CalculateTimeWindows(dateFrom, dateTo, myList16).ToList());
  352.  
  353. if (stateModels.Count() == 0)
  354. return new List<T>();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement