using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace REG_MARK_LIB
{
public class REG_MARK_LIB
{
//Список номеров регионов государства
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,
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,
166, 774, 797, 178, 193, 124, 196, 799, 198};
///
/// Метод, направленный на проверку корректности номера автомобиля
///
/// номер
/// true - номер авто правильный, false - номер авто не правильный
public static bool CheckMark(string mark)
{
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);
if (!regex.IsMatch(mark)) return false;
if (mark[6..mark.Length].Length == 2) return true;
if (mark[6..mark.Length].Length == 3 && REG.Where(i => i == Convert.ToInt32(mark[6..mark.Length])).FirstOrDefault() != default) return true;
return false;
}
///
/// Метод, для получения следующего номера по порядку
///
/// номер
/// следующий по порядку номер
/// Возникает, когда номер не правильный
/// Возникает, когда следующий номер найти невозможно
public static string GetNextMarkAfter(string mark)
{
if (!CheckMark(mark)) throw new ArgumentException();
int[] numbers = ConvertMarkToInts(mark);
//Проверки существования номера
if (numbers[1] == 999)
{
if (numbers[0] == 21)
{
if (numbers[3] == 21)
{
if (numbers[2] == 21) throw new Exception("Следующего номера не существует!");
else
{
numbers[2] += 1;
numbers[3] = 10;
numbers[1] = 1;
numbers[0] = 10;
}
}
else
{
numbers[3] += 1;
numbers[1] = 1;
numbers[0] = 10;
}
}
else
{
numbers[0] += 1;
numbers[1] = 1;
}
}
else numbers[1] += 1;
return ConvertIntsMarkToString(numbers);
}
///
/// Метод, для получения следующего по порядку номера, в заданных границах
///
/// номер, для которого будет осуществляться поиск
/// нижняя граница
/// верхняя граница
/// следующий номер по порядку
/// Возникает, когда строка аргумента не является валидным номером
/// Возникает, когда следующий номер найти невозможно
public static string GetNextMarkAfterInRange(string prevMark, string rangeStart, string rangeEnd)
{
if (!CheckMark(prevMark) || !CheckMark(rangeStart) || !CheckMark(rangeEnd)) throw new ArgumentException();
if (CompareMarks(rangeStart, rangeEnd) == -1) return "out of stock";
string newMark = GetNextMarkAfter(prevMark);
if (CompareMarks(rangeStart, prevMark) == -1 || CompareMarks(prevMark, rangeEnd) == -1) return "out of stock";
return newMark;
}
///
/// Метод, для поиска количества номеров, в заданных границах
///
/// первая граница счета
/// вторая граница счета
/// количество номеров в диапазоне, включая границы
/// Границы не являются правильными автомобильными номерами
public static int GetCombinationsCountInRange(string markone, string marktwo)
{
if (!CheckMark(markone) || !CheckMark(marktwo)) throw new ArgumentException();
int counter = 1;
string codeone, codetwo;
switch (CompareMarks(markone, marktwo))
{
case 1:
{
codeone = markone;
codetwo = marktwo;
break;
}
case -1:
{
codeone = marktwo;
codetwo = markone;
break;
}
default: return 1;
}
while (codeone != codetwo)
{
codeone = GetNextMarkAfter(codeone);
counter++;
}
return counter;
}
///
/// Метод, преобразовывающий номер в массив чисел
///
/// номер
/// массив чисел
private static int[] ConvertMarkToInts(string mark)
{
mark = mark.ToUpper();
int[] result = new int[mark.Length - 2];
//Коллекция с ключами и значениями. Ключи - буквы номера. Значения - цифры номера
Dictionary keyValuePairs = new Dictionary { { '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 } };
result[0] = keyValuePairs[mark[0]];
result[1] = Convert.ToInt32(mark[1..4]);
for (int i = 4; i < mark.Length; i++) result[i - 2] = keyValuePairs[mark[i]];
return result;
}
///
/// Метод, преобразующий массив на основе номера в текстовый вариант номера
///
/// массив на основе номера
/// номер
private static string ConvertIntsMarkToString(int[] mark)
{
StringBuilder markString = new StringBuilder();
Dictionary keyValuePairs = new Dictionary { { 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' } };
markString.Append(keyValuePairs[mark[0]]);
StringBuilder sb = new StringBuilder(mark[1].ToString());
while (sb.Length < 3)
{
sb = new StringBuilder("0" + sb.ToString());
}
markString.Append(sb.ToString());
for (int i = 2; i < mark.Length; i++) markString.Append(keyValuePairs[mark[i]]);
return markString.ToString();
}
///
/// Метод, сравнивающий два номера в соответствии с установленным порядком
///
/// Номер для сравнения 1
/// Номер для сравнения 2
/// 1 - номер 2 больше; -1 - номер 1 больше; 0 - номера одинаковы
private static int CompareMarks(string strForCompOne, string strForCompTwo)
{
int[] codeone = ConvertMarkToInts(strForCompOne);
int[] codetwo = ConvertMarkToInts(strForCompTwo);
if (codetwo[2] > codeone[2]) return 1;
else if (codetwo[2] < codeone[2]) return -1;
else
{
if (codetwo[3] > codeone[3]) return 1;
else if (codetwo[3] < codeone[3]) return -1;
else
{
if (codetwo[0] > codeone[0]) return 1;
else if (codetwo[0] < codeone[0]) return -1;
else
{
if (codetwo[1] > codeone[1]) return 1;
else if (codetwo[1] < codeone[1]) return -1;
else return 0;
}
}
}
}
}
}