PageRenderTime 84ms CodeModel.GetById 40ms app.highlight 15ms RepoModel.GetById 25ms app.codeStats 0ms

/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}