PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Utilities/Helpers/RandomHelper.cs

#
C# | 379 lines | 216 code | 33 blank | 130 comment | 24 complexity | 9b166b6a5ea79fcc0ee4fbedd8367826 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Security.Cryptography;
  4. using Delta.Utilities.Datatypes;
  5. namespace Delta.Utilities.Helpers
  6. {
  7. /// <summary>
  8. /// Random helper, which mostly provides methods to quickly generate random
  9. /// values for ints, floats, bytes, Vectors, Colors, etc. and some methods
  10. /// for more complex cases (strings, ids, random values with factors, etc.)
  11. /// </summary>
  12. public static class RandomHelper
  13. {
  14. #region GetNewRandomGenerator (Static)
  15. /// <summary>
  16. /// Get new random generator with help of
  17. /// Win32Function.GetPerformanceCounter.
  18. /// </summary>
  19. /// <returns>Random</returns>
  20. public static Random GetNewRandomGenerator()
  21. {
  22. lastUsedRandomGenerator = new Random((int)DateTime.Now.Ticks);
  23. //lastUsedRandomGenerator = new Random250Algorithm();
  24. return lastUsedRandomGenerator;
  25. }
  26. #endregion
  27. #region RandomInt (Static)
  28. /// <summary>
  29. /// Gets a random int between '0' and the given (exclusive) maximum.
  30. /// </summary>
  31. /// <param name="max">The max. (exclusive) Limit</param>
  32. /// <returns>Int</returns>
  33. public static int RandomInt(int max)
  34. {
  35. if (max <= 0)
  36. {
  37. return 0;
  38. }
  39. return lastUsedRandomGenerator.Next(max);
  40. }
  41. /// <summary>
  42. /// Gets a random int between the given minimum and (exclusive) maximum.
  43. /// </summary>
  44. /// <param name="min">Min</param>
  45. /// <param name="max">Max</param>
  46. /// <returns>Random int</returns>
  47. public static int RandomInt(int min, int max)
  48. {
  49. if (max <= 0 ||
  50. min > max)
  51. {
  52. return 0;
  53. }
  54. return lastUsedRandomGenerator.Next(min, max);
  55. }
  56. #endregion
  57. #region RandomFloat (Static)
  58. /// <summary>
  59. /// Get random float between min and max (exclusive max)
  60. /// </summary>
  61. /// <param name="rnd">Rnd</param>
  62. /// <param name="min">Min</param>
  63. /// <param name="max">Max</param>
  64. /// <returns>Float</returns>
  65. public static float RandomFloat(this Random rnd, float min, float max)
  66. {
  67. return (float)rnd.NextDouble() * (max - min) + min;
  68. }
  69. /// <summary>
  70. /// Get random float between min and max (exclusive max)
  71. /// </summary>
  72. /// <param name="min">Minimum</param>
  73. /// <param name="max">Maximum</param>
  74. /// <returns>Float</returns>
  75. public static float RandomFloat(float min, float max)
  76. {
  77. return (float)lastUsedRandomGenerator.NextDouble() * (max - min) + min;
  78. }
  79. #endregion
  80. #region RandomByte (Static)
  81. /// <summary>
  82. /// Get random byte between min and max (exclusive max)
  83. /// </summary>
  84. /// <param name="rnd">Rnd</param>
  85. /// <param name="min">Min</param>
  86. /// <param name="max">Max</param>
  87. /// <returns>Byte</returns>
  88. public static byte RandomByte(this Random rnd, byte min, byte max)
  89. {
  90. return (byte)(rnd.Next(min, max));
  91. }
  92. #endregion
  93. #region RandomVector (Static)
  94. /// <summary>
  95. /// Get random vector between min and max for all components.
  96. /// </summary>
  97. /// <param name="min">Minimum</param>
  98. /// <param name="max">Maximum</param>
  99. /// <returns>Vector</returns>
  100. public static Vector RandomVector(float min, float max)
  101. {
  102. return new Vector(RandomFloat(min, max), RandomFloat(min, max),
  103. RandomFloat(min, max));
  104. }
  105. /// <summary>
  106. /// Get random vector between min and max for each component separated.
  107. /// </summary>
  108. /// <param name="minX">Minimum X</param>
  109. /// <param name="maxX">Maximum X</param>
  110. /// <param name="minY">Minimum Y</param>
  111. /// <param name="maxY">Maximum Y</param>
  112. /// <param name="minZ">Minimum Z</param>
  113. /// <param name="maxZ">Maximum Z</param>
  114. /// <returns>Vector</returns>
  115. public static Vector RandomVector(float minX, float maxX,
  116. float minY, float maxY, float minZ, float maxZ)
  117. {
  118. return new Vector(RandomFloat(minX, maxX), RandomFloat(minY, maxY),
  119. RandomFloat(minZ, maxZ));
  120. }
  121. #endregion
  122. #region CreateRandomBytes (Static)
  123. /// <summary>
  124. /// Creates random byte array with given length. Used to generate private
  125. /// keys and crypto IV values.
  126. /// </summary>
  127. /// <param name="length">Length of the byte array we return</param>
  128. /// <returns>Byte array with random byte data</returns>
  129. public static byte[] CreateRandomBytes(int length)
  130. {
  131. byte[] random = new byte[length];
  132. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  133. // The array is now filled with cryptographically strong random bytes.
  134. rng.GetBytes(random);
  135. return random;
  136. }
  137. #endregion
  138. #region CreateRandomString (Static)
  139. /// <summary>
  140. /// Create random string, helper for GetFreeUnusedSerial()
  141. /// and RequestActivationKey(), use SerialLength or
  142. /// ActivationKeyLength as lengths!
  143. /// </summary>
  144. public static string CreateRandomString(int length)
  145. {
  146. // RNGCryptoServiceProvider is an implementation of a random number
  147. // generator. It will produce strong random numbers, so this is very
  148. // useful for us ^^
  149. byte[] random = new byte[length];
  150. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  151. // The array is now filled with cryptographically strong random bytes.
  152. rng.GetBytes(random);
  153. string s = "";
  154. for (int i = 0; i < length; i++)
  155. {
  156. // We assume Win32Function.GetPerformanceCounter()
  157. // will change VERY often, so we never get the same values!
  158. Random rnd = new Random(i + (int)DateTime.Now.Ticks);
  159. int type = (rnd.Next(36 * 7) + random[i]) % (10 + 26);
  160. char charType = (char)(type < 10
  161. ? '0' + type
  162. : 'A' + (type - 10));
  163. // Update 2004-10-21: Don't allow any 0 (Zero) or O (Oh) symbols
  164. if (charType == '0')
  165. {
  166. // Replace 0 with random number from 1 to 9
  167. charType = (char)('1' + rnd.Next(9));
  168. }
  169. else if (charType == 'O')
  170. {
  171. // Replace O with random letter from A to A+10
  172. charType = (char)('A' + rnd.Next(10));
  173. }
  174. s += charType;
  175. // Do some random execution to make next random value more random
  176. int rndExecutions = rnd.Next(200);
  177. for (int j = 0; j < rndExecutions; j++)
  178. {
  179. type++;
  180. }
  181. }
  182. return s;
  183. }
  184. #endregion
  185. #region CreateRandomStringNoNumbers (Static)
  186. /// <summary>
  187. /// Create random string, helper for GetFreeUnusedSerial()
  188. /// and RequestActivationKey(), use SerialLength or
  189. /// ActivationKeyLength as lengths!
  190. /// </summary>
  191. public static string CreateRandomStringNoNumbers(int length)
  192. {
  193. // RNGCryptoServiceProvider is an implementation of a random number
  194. // generator. It will produce strong random numbers, so this is very
  195. // useful for us ^^
  196. byte[] random = new byte[length];
  197. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  198. // The array is now filled with cryptographically strong random bytes.
  199. rng.GetBytes(random);
  200. string s = "";
  201. for (int i = 0; i < length; i++)
  202. {
  203. // We assume Win32Function.GetPerformanceCounter()
  204. // will change VERY often, so we never get the same values!
  205. Random rnd = new Random(i + (int)DateTime.Now.Ticks);
  206. int type = (rnd.Next(26 * 7) + random[i]) % (26);
  207. char charType = (char)('A' + type);
  208. s += charType;
  209. // Do some random execution to make next random value more random
  210. int rndExecutions = rnd.Next(200);
  211. for (int j = 0; j < rndExecutions; j++)
  212. {
  213. type++;
  214. }
  215. }
  216. return s;
  217. }
  218. #endregion
  219. #region RandomizeIds (Static)
  220. /// <summary>
  221. /// Randomize ids
  222. /// </summary>
  223. /// <param name="inputIds">Input ids</param>
  224. /// <returns>List</returns>
  225. public static List<int> RandomizeIds(List<int> inputIds)
  226. {
  227. // Just go through the whole list and swap entries randomly (good enough
  228. // approach here, will not be 100% even, but looks pretty random).
  229. for (int num = inputIds.Count - 1; num > 0; num--)
  230. {
  231. int newIndex = RandomInt(num);
  232. // Swap the values
  233. int swapId = inputIds[newIndex];
  234. inputIds[newIndex] = inputIds[num];
  235. inputIds[num] = swapId;
  236. }
  237. // Return the results
  238. return inputIds;
  239. }
  240. /// <summary>
  241. /// Randomize ids
  242. /// </summary>
  243. /// <param name="inputIds">Input ids</param>
  244. /// <param name="maxCount">Maximum count</param>
  245. /// <returns>List</returns>
  246. public static List<int> RandomizeIds(List<int> inputIds,
  247. int maxCount)
  248. {
  249. // Just go through the whole list and swap entries randomly (good enough
  250. // approach here, will not be 100% even, but looks pretty random).
  251. for (int num = maxCount - 1; num > 0; num--)
  252. {
  253. int newIndex = RandomInt(num);
  254. // Swap the values
  255. int swapId = inputIds[newIndex];
  256. inputIds[newIndex] = inputIds[num];
  257. inputIds[num] = swapId;
  258. }
  259. // Return the results
  260. return inputIds;
  261. }
  262. #endregion
  263. #region GetRandomValueWithFactors (Static)
  264. /// <summary>
  265. /// Very nice function to calc random value with help of
  266. /// factors, e.g. when calling with { 0.1f, 0.1f, 2.0f }
  267. /// we will most likly (in >99% of all cases) get 2 as
  268. /// result and not 0 or 1!
  269. /// </summary>
  270. public static int GetRandomValueWithFactors(List<int> factorArray)
  271. {
  272. if (factorArray == null ||
  273. factorArray.Count == 0)
  274. {
  275. return 0;
  276. }
  277. // Count all factor values
  278. int allValuesTogether = 0;
  279. for (int i = 0; i < factorArray.Count; i++)
  280. {
  281. allValuesTogether += factorArray[i];
  282. }
  283. // Now calc random value from 0 to allValuesTogehter
  284. int rndValue = RandomInt(allValuesTogether);
  285. // Now all we have to do is to check out to which entry
  286. // the rndValue belongs to
  287. int currentValue = 0;
  288. for (int i = 0; i < factorArray.Count; i++)
  289. {
  290. if (rndValue >= currentValue &&
  291. rndValue < currentValue + factorArray[i])
  292. {
  293. return i;
  294. }
  295. currentValue += factorArray[i];
  296. }
  297. return 0;
  298. }
  299. #endregion
  300. #region RandomizeList (Static)
  301. /// <summary>
  302. /// Randomize list
  303. /// </summary>
  304. /// <param name="list">List</param>
  305. /// <param name="maxCount">Maximum count</param>
  306. /// <returns>List</returns>
  307. public static List<ListType> RandomizeList<ListType>(
  308. List<ListType> list, int maxCount)
  309. {
  310. List<ListType> ret = new List<ListType>();
  311. int maximum = 0;
  312. for (int i = list.Count - 1; i > 0; i--)
  313. {
  314. int swapIndex = RandomInt(i + 1);
  315. if (swapIndex != i)
  316. {
  317. ListType tmp = list[swapIndex];
  318. list[swapIndex] = list[i];
  319. list[i] = tmp;
  320. }
  321. }
  322. if (maxCount > list.Count)
  323. {
  324. maximum = list.Count;
  325. }
  326. else
  327. {
  328. maximum = maxCount;
  329. }
  330. for (int j = 0; j < maximum; j++)
  331. {
  332. ret.Add(list[j]);
  333. }
  334. return ret;
  335. }
  336. #endregion
  337. #region Private
  338. #region lastUsedRandomGenerator (Private)
  339. /// <summary>
  340. /// Last used random generator
  341. /// </summary>
  342. private static Random lastUsedRandomGenerator = GetNewRandomGenerator();
  343. #endregion
  344. #endregion
  345. }
  346. }