REG_MARK_LIB.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. namespace REG_MARK_LIB
  7. {
  8. public class REG_MARK_LIB
  9. {
  10. //Список номеров регионов государства
  11. public static int[] REG = { 190, 177, 199, 977, 102, 103, 277, 297, 299, 111, 113, 116, 118, 121, 122, 125, 126, 130, 134, 136, 142, 147, 750, 152, 154, 155, 156,
  12. 158, 161, 163, 164, 172, 173, 174, 197, 777, 180, 181, 777, 184, 185, 186, 702, 716, 123, 725, 138, 150, 790, 252, 754, 159, 761, 763,
  13. 166, 774, 797, 178, 193, 124, 196, 799, 198};
  14. /// <summary>
  15. /// Метод, направленный на проверку корректности номера автомобиля
  16. /// </summary>
  17. /// <param name="mark">номер</param>
  18. /// <returns>true - номер авто правильный, false - номер авто не правильный</returns>
  19. public static bool CheckMark(string mark)
  20. {
  21. Regex regex = new Regex(@"^[a,b,e,k,m,h,o,p,c,t,y,x]{1}[0-9]{3}[a,b,e,k,m,h,o,p,c,t,y,x]{2}[0-9]{2,3}$", RegexOptions.IgnoreCase);
  22. if (!regex.IsMatch(mark)) return false;
  23. if (mark[6..mark.Length].Length == 2) return true;
  24. if (mark[6..mark.Length].Length == 3 && REG.Where(i => i == Convert.ToInt32(mark[6..mark.Length])).FirstOrDefault() != default) return true;
  25. return false;
  26. }
  27. /// <summary>
  28. /// Метод, для получения следующего номера по порядку
  29. /// </summary>
  30. /// <param name="mark">номер</param>
  31. /// <returns>следующий по порядку номер</returns>
  32. /// <exception cref="ArgumentException">Возникает, когда номер не правильный</exception>
  33. /// <exception cref="Exception">Возникает, когда следующий номер найти невозможно</exception>
  34. public static string GetNextMarkAfter(string mark)
  35. {
  36. if (!CheckMark(mark)) throw new ArgumentException();
  37. int[] numbers = ConvertMarkToInts(mark);
  38. //Проверки существования номера
  39. if (numbers[1] == 999)
  40. {
  41. if (numbers[0] == 21)
  42. {
  43. if (numbers[3] == 21)
  44. {
  45. if (numbers[2] == 21) throw new Exception("Следующего номера не существует!");
  46. else
  47. {
  48. numbers[2] += 1;
  49. numbers[3] = 10;
  50. numbers[1] = 1;
  51. numbers[0] = 10;
  52. }
  53. }
  54. else
  55. {
  56. numbers[3] += 1;
  57. numbers[1] = 1;
  58. numbers[0] = 10;
  59. }
  60. }
  61. else
  62. {
  63. numbers[0] += 1;
  64. numbers[1] = 1;
  65. }
  66. }
  67. else numbers[1] += 1;
  68. return ConvertIntsMarkToString(numbers);
  69. }
  70. /// <summary>
  71. /// Метод, для получения следующего по порядку номера, в заданных границах
  72. /// </summary>
  73. /// <param name="prevMark">номер, для которого будет осуществляться поиск</param>
  74. /// <param name="rangeStart">нижняя граница</param>
  75. /// <param name="rangeEnd">верхняя граница</param>
  76. /// <returns>следующий номер по порядку</returns>
  77. /// <exception cref="ArgumentException">Возникает, когда строка аргумента не является валидным номером</exception>
  78. /// <exception cref="Exception">Возникает, когда следующий номер найти невозможно</exception>
  79. public static string GetNextMarkAfterInRange(string prevMark, string rangeStart, string rangeEnd)
  80. {
  81. if (!CheckMark(prevMark) || !CheckMark(rangeStart) || !CheckMark(rangeEnd)) throw new ArgumentException();
  82. if (CompareMarks(rangeStart, rangeEnd) == -1) return "out of stock";
  83. string newMark = GetNextMarkAfter(prevMark);
  84. if (CompareMarks(rangeStart, prevMark) == -1 || CompareMarks(prevMark, rangeEnd) == -1) return "out of stock";
  85. return newMark;
  86. }
  87. /// <summary>
  88. /// Метод, для поиска количества номеров, в заданных границах
  89. /// </summary>
  90. /// <param name="markone">первая граница счета</param>
  91. /// <param name="marktwo">вторая граница счета</param>
  92. /// <returns>количество номеров в диапазоне, включая границы</returns>
  93. /// <exception cref="ArgumentException">Границы не являются правильными автомобильными номерами</exception>
  94. public static int GetCombinationsCountInRange(string markone, string marktwo)
  95. {
  96. if (!CheckMark(markone) || !CheckMark(marktwo)) throw new ArgumentException();
  97. int counter = 1;
  98. string codeone, codetwo;
  99. switch (CompareMarks(markone, marktwo))
  100. {
  101. case 1:
  102. {
  103. codeone = markone;
  104. codetwo = marktwo;
  105. break;
  106. }
  107. case -1:
  108. {
  109. codeone = marktwo;
  110. codetwo = markone;
  111. break;
  112. }
  113. default: return 1;
  114. }
  115. while (codeone != codetwo)
  116. {
  117. codeone = GetNextMarkAfter(codeone);
  118. counter++;
  119. }
  120. return counter;
  121. }
  122. /// <summary>
  123. /// Метод, преобразовывающий номер в массив чисел
  124. /// </summary>
  125. /// <param name="mark">номер</param>
  126. /// <returns>массив чисел</returns>
  127. private static int[] ConvertMarkToInts(string mark)
  128. {
  129. mark = mark.ToUpper();
  130. int[] result = new int[mark.Length - 2];
  131. //Коллекция с ключами и значениями. Ключи - буквы номера. Значения - цифры номера
  132. Dictionary<char, int> keyValuePairs = new Dictionary<char, int> { { 'A', 10 }, { 'B', 11 }, { 'E', 12 }, { 'K', 13 }, { 'M', 14 }, { 'H', 15 }, { 'O', 16 }, { 'P', 17 }, { 'C', 18 }, { 'T', 19 }, { 'Y', 20 }, { 'X', 21 }, { '0', 0 }, { '1', 1 }, { '2', 2 }, { '3', 3 }, { '4', 4 }, { '5', 5 }, { '6', 6 }, { '7', 7 }, { '8', 8 }, { '9', 9 } };
  133. result[0] = keyValuePairs[mark[0]];
  134. result[1] = Convert.ToInt32(mark[1..4]);
  135. for (int i = 4; i < mark.Length; i++) result[i - 2] = keyValuePairs[mark[i]];
  136. return result;
  137. }
  138. /// <summary>
  139. /// Метод, преобразующий массив на основе номера в текстовый вариант номера
  140. /// </summary>
  141. /// <param name="mark">массив на основе номера</param>
  142. /// <returns>номер</returns>
  143. private static string ConvertIntsMarkToString(int[] mark)
  144. {
  145. StringBuilder markString = new StringBuilder();
  146. Dictionary<int, char> keyValuePairs = new Dictionary<int, char> { { 10, 'A' }, { 11, 'B' }, { 12, 'E' }, { 13, 'K' }, { 14, 'M' }, { 15, 'H' }, { 16, 'O' }, { 17, 'P' }, { 18, 'C' }, { 19, 'T' }, { 20, 'Y' }, { 21, 'X' }, { 0, '0' }, { 1, '1' }, { 2, '2' }, { 3, '3' }, { 4, '4' }, { 5, '5' }, { 6, '6' }, { 7, '7' }, { 8, '8' }, { 9, '9' } };
  147. markString.Append(keyValuePairs[mark[0]]);
  148. StringBuilder sb = new StringBuilder(mark[1].ToString());
  149. while (sb.Length < 3)
  150. {
  151. sb = new StringBuilder("0" + sb.ToString());
  152. }
  153. markString.Append(sb.ToString());
  154. for (int i = 2; i < mark.Length; i++) markString.Append(keyValuePairs[mark[i]]);
  155. return markString.ToString();
  156. }
  157. /// <summary>
  158. /// Метод, сравнивающий два номера в соответствии с установленным порядком
  159. /// </summary>
  160. /// <param name="strForComp1">Номер для сравнения 1</param>
  161. /// <param name="strForComp2">Номер для сравнения 2</param>
  162. /// <returns>1 - номер 2 больше; -1 - номер 1 больше; 0 - номера одинаковы</returns>
  163. private static int CompareMarks(string strForCompOne, string strForCompTwo)
  164. {
  165. int[] codeone = ConvertMarkToInts(strForCompOne);
  166. int[] codetwo = ConvertMarkToInts(strForCompTwo);
  167. if (codetwo[2] > codeone[2]) return 1;
  168. else if (codetwo[2] < codeone[2]) return -1;
  169. else
  170. {
  171. if (codetwo[3] > codeone[3]) return 1;
  172. else if (codetwo[3] < codeone[3]) return -1;
  173. else
  174. {
  175. if (codetwo[0] > codeone[0]) return 1;
  176. else if (codetwo[0] < codeone[0]) return -1;
  177. else
  178. {
  179. if (codetwo[1] > codeone[1]) return 1;
  180. else if (codetwo[1] < codeone[1]) return -1;
  181. else return 0;
  182. }
  183. }
  184. }
  185. }
  186. }
  187. }