| | | 1 | | using Services.ApiServices._1CApi.OData; |
| | | 2 | | |
| | | 3 | | namespace Services.ProducerAliases; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Словарь алиасов производителей, приведённый к нормализованному виду: «KAYABA» → «KYB». |
| | | 7 | | /// Позволяет сравнивать бренд запроса и бренд ответа API, не завися от написания. |
| | | 8 | | /// </summary> |
| | | 9 | | public sealed class ProducerBrandAliasMap |
| | | 10 | | { |
| | | 11 | | /// <summary>Пустая карта — поведение как до появления алиасов (сравнение по нормализации).</summary> |
| | 1 | 12 | | public static readonly ProducerBrandAliasMap Empty = new(new Dictionary<string, string>()); |
| | | 13 | | |
| | | 14 | | private readonly IReadOnlyDictionary<string, string> _aliasToCanonical; |
| | | 15 | | private readonly IReadOnlyDictionary<string, IReadOnlyList<string>> _canonicalToVariants; |
| | | 16 | | |
| | 16 | 17 | | public ProducerBrandAliasMap(IReadOnlyDictionary<string, string> aliasToCanonical) |
| | | 18 | | { |
| | 16 | 19 | | _aliasToCanonical = aliasToCanonical; |
| | 16 | 20 | | _canonicalToVariants = aliasToCanonical |
| | 19 | 21 | | .GroupBy(pair => pair.Value, StringComparer.Ordinal) |
| | 16 | 22 | | .ToDictionary( |
| | 17 | 23 | | group => group.Key, |
| | 36 | 24 | | group => (IReadOnlyList<string>)group.Select(pair => pair.Key).Append(group.Key) |
| | 17 | 25 | | .Distinct(StringComparer.Ordinal).ToArray(), |
| | 16 | 26 | | StringComparer.Ordinal); |
| | 16 | 27 | | } |
| | | 28 | | |
| | | 29 | | /// <summary>Нормализованное каноническое написание бренда. Незнакомый бренд остаётся собой.</summary> |
| | | 30 | | public string Canonicalize(string? brand) |
| | | 31 | | { |
| | 114 | 32 | | var normalized = Normalize(brand); |
| | 114 | 33 | | return _aliasToCanonical.TryGetValue(normalized, out var canonical) ? canonical : normalized; |
| | | 34 | | } |
| | | 35 | | |
| | | 36 | | /// <summary>Один и тот же бренд с точностью до написания и алиаса.</summary> |
| | | 37 | | public bool AreSame(string? left, string? right) => |
| | 32 | 38 | | Canonicalize(left) is { Length: > 0 } canonical && canonical == Canonicalize(right); |
| | | 39 | | |
| | | 40 | | /// <summary> |
| | | 41 | | /// Все известные написания бренда в нормализованном виде: «Kayaba» → [«KAYABA», «KYB»]. |
| | | 42 | | /// Нужно там, где бренд ищется вхождением в чужой текст и точное сравнение невозможно. |
| | | 43 | | /// </summary> |
| | | 44 | | public IReadOnlyList<string> GetVariants(string? brand) |
| | | 45 | | { |
| | 18 | 46 | | var canonical = Canonicalize(brand); |
| | 18 | 47 | | if (canonical.Length == 0) |
| | 10 | 48 | | return Array.Empty<string>(); |
| | | 49 | | |
| | 8 | 50 | | return _canonicalToVariants.TryGetValue(canonical, out var variants) ? variants : new[] { canonical }; |
| | | 51 | | } |
| | | 52 | | |
| | | 53 | | /// <summary>Нормализация повторяет ту, которой заполнялась таблица алиасов.</summary> |
| | 210 | 54 | | public static string Normalize(string? value) => OneCNomenclatureService.NormalizeProducerName(value); |
| | | 55 | | } |