PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Engine/NameGenerator.cs

http://ruction.codeplex.com
C# | 407 lines | 348 code | 40 blank | 19 comment | 59 complexity | 3d125ba61313a657e0c33b44bfbae9aa MD5 | raw file
  1. using System;
  2. using System.Globalization;
  3. using System.Linq;
  4. namespace Ruction
  5. {
  6. /// <summary>Handles the generation of random names.</summary>
  7. internal static class NameGenerator
  8. {
  9. #region Member Variables
  10. /// <summary>Private storage for letter proportions.</summary>
  11. private static int[] _letterPrp;
  12. /// <summary>Private storage for letter pecrentages.</summary>
  13. private static float[] _letterPct;
  14. /// <summary>Private storage for name 'spice'.</summary>
  15. private static string[] _nameSpice;
  16. /// <summary>Private randomizer.</summary>
  17. private static Random _rnd;
  18. #endregion Member Variables
  19. #region Constructors
  20. /// <summary>Static constructor for name generation data.</summary>
  21. static NameGenerator()
  22. {
  23. _rnd = new Random(DateTime.Now.Millisecond);
  24. _nameSpice = new string[26];
  25. _letterPct = new float[26];
  26. _letterPrp = new int[26];
  27. InitNameGen();
  28. }
  29. #endregion Constructors
  30. #region Properties
  31. #region NameSpice
  32. /// <summary>Gets the name spice string array.</summary>
  33. public static string[] NameSpice { get { return _nameSpice; } }
  34. #endregion NameSpice
  35. #endregion Properties
  36. #region Methods
  37. #region GenerateName
  38. /// <summary>Generates a random name.</summary>
  39. /// <param name="min">The minimum name length.</param>
  40. /// <param name="max">The maximum name length.</param>
  41. /// <param name="specials">True to use special strings in the name.</param>
  42. /// <returns>A string containing a randomly generated name.</returns>
  43. internal static string GenerateName(int min, int max, bool specials)
  44. {
  45. int i = 0;
  46. bool GoodWord = false;
  47. string retVal = string.Empty;
  48. char LastChar = char.MinValue, TwoCharsAgo = char.MinValue;
  49. do
  50. {
  51. retVal = Convert.ToChar(Convert.ToInt32(_rnd.NextDouble() * 26) + 65).ToString();
  52. LastChar = retVal[0];
  53. GoodWord = true;
  54. for (i = 0; i < (Convert.ToInt32(_rnd.NextDouble() * (max - min + 1)) + min) - 1; i++)
  55. {
  56. if (Consonant(LastChar))
  57. {
  58. if (Consonant(TwoCharsAgo))
  59. {
  60. if (LastChar.Equals('y') || LastChar.Equals('Y'))
  61. {
  62. retVal += AddChars("BCDFGKLMNPRSTVXZ");
  63. }
  64. else { retVal += AddChars("AEIOU"); }
  65. }
  66. else
  67. {
  68. if (_rnd.NextDouble() < 0.2)
  69. {
  70. if (LastChar.Equals('q') || LastChar.Equals('Q'))
  71. {
  72. retVal += AddChars("U");
  73. }
  74. else { retVal += AddChars("AEIOU"); }
  75. }
  76. else
  77. {
  78. #region BIG Switch Statement
  79. switch (LastChar)
  80. {
  81. case 'B':
  82. case 'b':
  83. retVal += AddChars("BLRSY");
  84. break;
  85. case 'C':
  86. case 'c':
  87. retVal += AddChars("CHKLRSTY");
  88. break;
  89. case 'D':
  90. case 'd':
  91. retVal += AddChars("DRSWY");
  92. break;
  93. case 'F':
  94. case 'f':
  95. retVal += AddChars("FLRSTY");
  96. break;
  97. case 'G':
  98. case 'g':
  99. retVal += AddChars("GHLRS");
  100. break;
  101. case 'H':
  102. case 'h':
  103. retVal += AddChars("AEIOUY");
  104. break;
  105. case 'J':
  106. case 'j':
  107. retVal += AddChars("AEIOU");
  108. break;
  109. case 'K':
  110. case 'k':
  111. retVal += AddChars("HKLNRSTW");
  112. break;
  113. case 'L':
  114. case 'l':
  115. retVal += AddChars("CDKLMNPSTY");
  116. break;
  117. case 'M':
  118. case 'm':
  119. retVal += AddChars("MPSY");
  120. break;
  121. case 'N':
  122. case 'n':
  123. retVal += AddChars("CDKNSTY");
  124. break;
  125. case 'P':
  126. case 'p':
  127. retVal += AddChars("HLPRSTY");
  128. break;
  129. case 'Q':
  130. case 'q':
  131. retVal += AddChars("U");
  132. break;
  133. case 'R':
  134. case 'r':
  135. retVal += AddChars("CDKMNPRSTY");
  136. break;
  137. case 'S':
  138. case 's':
  139. retVal += AddChars("CHKLMNPSTWY");
  140. break;
  141. case 'T':
  142. case 't':
  143. retVal += AddChars("HRSTWY");
  144. break;
  145. case 'V':
  146. case 'v':
  147. retVal += AddChars("LRS");
  148. break;
  149. case 'W':
  150. case 'w':
  151. retVal += AddChars("HKST");
  152. break;
  153. case 'X':
  154. case 'x':
  155. retVal += AddChars("CSYAEIOU");
  156. break;
  157. case 'Y':
  158. case 'y':
  159. retVal += AddChars("LSTKMNPC");
  160. break;
  161. case 'Z':
  162. case 'z':
  163. retVal += AddChars("HZZZ");
  164. break;
  165. }
  166. #endregion BIG Switch Statement
  167. }
  168. }
  169. }
  170. else
  171. {
  172. if (Consonant(TwoCharsAgo))
  173. {
  174. if (_rnd.NextDouble() < 0.9 && retVal.Length >= 2 && !retVal.Substring(retVal.Length - 2, 2).Equals("QU", StringComparison.OrdinalIgnoreCase))
  175. {
  176. retVal += AddChars("BCDFGHJKLMNPQRSTVWX");
  177. }
  178. else
  179. {
  180. switch (LastChar)
  181. {
  182. case 'A':
  183. case 'a':
  184. retVal += AddChars("IU");
  185. break;
  186. case 'E':
  187. case 'e':
  188. retVal += AddChars("AEIOU");
  189. break;
  190. case 'I':
  191. case 'i':
  192. retVal += AddChars("AEO");
  193. break;
  194. case 'O':
  195. case 'o':
  196. retVal += AddChars("AEIOU");
  197. break;
  198. case 'U':
  199. case 'u':
  200. retVal += AddChars("AEI");
  201. break;
  202. }
  203. }
  204. }
  205. else
  206. {
  207. retVal += AddChars("BCDFGKLMNPRST");
  208. }
  209. }
  210. TwoCharsAgo = LastChar;
  211. LastChar = retVal[retVal.Length - 1];
  212. }
  213. TwoCharsAgo = retVal[0];
  214. LastChar = retVal.Length > 1 ? retVal[1] : TwoCharsAgo;
  215. if (TwoCharsAgo.Equals(LastChar)) GoodWord = false;
  216. if ((LastChar.Equals('s') || LastChar.Equals('S')) || (LastChar.Equals('d') || LastChar.Equals('D')))
  217. {
  218. if (Consonant(TwoCharsAgo)) { GoodWord = false; }
  219. }
  220. char[] checkChars = new char[] { 'T', 't', 'K', 'k', 'M', 'm', 'N', 'n', 'P', 'p', 'C', 'c' };
  221. if (checkChars.Contains(LastChar))
  222. {
  223. if (Consonant(TwoCharsAgo) && (!TwoCharsAgo.Equals('S') && !TwoCharsAgo.Equals('s')))
  224. GoodWord = false;
  225. }
  226. if ((TwoCharsAgo.Equals('Y') || TwoCharsAgo.Equals('y')) && Consonant(LastChar)) GoodWord = false;
  227. if (retVal.Length >= 2 && !retVal.Substring(retVal.Length - 2, 2).Equals("QU", StringComparison.OrdinalIgnoreCase))
  228. GoodWord = false;
  229. if (retVal.Contains("IY") || retVal.Contains("WI") ||
  230. retVal.Contains("YI") || retVal.Contains("UY") ||
  231. retVal.Contains("UW") || retVal.Contains("IH") ||
  232. retVal.Contains("UH")) GoodWord = false;
  233. if ((TwoCharsAgo.Equals('X') || TwoCharsAgo.Equals('x')) || (retVal.Length >= 2 && retVal.Substring(0, 2).Equals("IL", StringComparison.OrdinalIgnoreCase)))
  234. GoodWord = false;
  235. }
  236. while (!GoodWord);
  237. LastChar = retVal[retVal.Length - 1];
  238. TwoCharsAgo = retVal[retVal.Length - 2];
  239. if ((Consonant(LastChar) && Consonant(TwoCharsAgo)) ||
  240. retVal.Length < 4 || _rnd.NextDouble() < 0.15)
  241. {
  242. if (Consonant(LastChar) && (!LastChar.Equals('Y') || !LastChar.Equals('y')))
  243. {
  244. retVal += _nameSpice[(Convert.ToInt32(_rnd.NextDouble() * 6) + 17)];
  245. }
  246. else { retVal += _nameSpice[(Convert.ToInt32(_rnd.NextDouble() * 6) + 11)]; }
  247. }
  248. if (specials)
  249. {
  250. if (_rnd.NextDouble() < 0.13)
  251. {
  252. retVal = _nameSpice[(Convert.ToInt32(_rnd.NextDouble() * 10) + 1)] + retVal;
  253. }
  254. }
  255. retVal = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(retVal.ToLower());
  256. return retVal;
  257. }
  258. #endregion GenerateName
  259. #region AddChars
  260. /// <summary>Selects a random character from a set of characters.</summary>
  261. /// <param name="letters">The characters to choose from.</param>
  262. /// <returns>A string containing a single character chosen at random.</returns>
  263. private static string AddChars(string letters)
  264. {
  265. int j = 0;
  266. string retVal = string.Empty;
  267. float letterTotal = 0, letterTresh = 0, randLetter = 0;
  268. for (j = 0; j < letters.Length; j++)
  269. {
  270. letterTotal += _letterPrp[Convert.ToInt32(letters[j]) - 65];
  271. }
  272. letterTresh = 0;
  273. for (j = 0; j < letters.Length; j++)
  274. {
  275. letterTresh += (_letterPrp[Convert.ToInt32(letters[j]) - 65] / letterTotal);
  276. _letterPct[j] = letterTresh;
  277. }
  278. randLetter = Convert.ToSingle(_rnd.NextDouble());
  279. for (j = 0; j < letters.Length; j++)
  280. {
  281. if (randLetter <= _letterPct[j])
  282. {
  283. retVal = letters[j].ToString();
  284. break;
  285. }
  286. }
  287. return retVal;
  288. }
  289. #endregion AddChars
  290. #region Consonant
  291. /// <summary>Determines if a given character is a consonant or not.</summary>
  292. /// <param name="c">The character to analyze.</param>
  293. /// <returns>True if the character is an english language consonant, otherwise false.</returns>
  294. private static bool Consonant(char c)
  295. {
  296. bool retVal = false;
  297. if (!c.Equals(char.MinValue))
  298. {
  299. retVal = !(c.Equals('a') || c.Equals('A') ||
  300. c.Equals('e') || c.Equals('E') ||
  301. c.Equals('i') || c.Equals('I') ||
  302. c.Equals('o') || c.Equals('O') ||
  303. c.Equals('u') || c.Equals('U'));
  304. }
  305. return retVal;
  306. }
  307. #endregion Consonant
  308. #region InitNameGen
  309. /// <summary>Initializes require name generation arrays.</summary>
  310. private static void InitNameGen()
  311. {
  312. _letterPrp[0] = 9;
  313. _letterPrp[1] = 2;
  314. _letterPrp[2] = 2;
  315. _letterPrp[3] = 4;
  316. _letterPrp[4] = 12;
  317. _letterPrp[5] = 2;
  318. _letterPrp[6] = 3;
  319. _letterPrp[7] = 2;
  320. _letterPrp[8] = 9;
  321. _letterPrp[9] = 1;
  322. _letterPrp[10] = 1;
  323. _letterPrp[11] = 4;
  324. _letterPrp[12] = 2;
  325. _letterPrp[13] = 6;
  326. _letterPrp[14] = 8;
  327. _letterPrp[15] = 2;
  328. _letterPrp[16] = 1;
  329. _letterPrp[17] = 6;
  330. _letterPrp[18] = 4;
  331. _letterPrp[19] = 6;
  332. _letterPrp[20] = 4;
  333. _letterPrp[21] = 2;
  334. _letterPrp[22] = 2;
  335. _letterPrp[23] = 1;
  336. _letterPrp[24] = 2;
  337. _letterPrp[25] = 1;
  338. _nameSpice[0] = "Upper";
  339. _nameSpice[1] = "Lower";
  340. _nameSpice[2] = "Old";
  341. _nameSpice[3] = "New";
  342. _nameSpice[4] = "San";
  343. _nameSpice[5] = "Costa";
  344. _nameSpice[6] = "North";
  345. _nameSpice[7] = "South";
  346. _nameSpice[8] = "East";
  347. _nameSpice[9] = "West";
  348. _nameSpice[10] = "tia";
  349. _nameSpice[11] = "lia";
  350. _nameSpice[12] = "way";
  351. _nameSpice[13] = "land";
  352. _nameSpice[14] = "ton";
  353. _nameSpice[15] = "burg";
  354. _nameSpice[16] = "ary";
  355. _nameSpice[17] = "age";
  356. _nameSpice[18] = "ia";
  357. _nameSpice[19] = "any";
  358. _nameSpice[20] = "ica";
  359. _nameSpice[21] = "ania";
  360. _nameSpice[22] = "Isle";
  361. _nameSpice[23] = "Island";
  362. _nameSpice[24] = "The Isle of";
  363. }
  364. #endregion InitNameGen
  365. #endregion Methods
  366. }
  367. }