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