atlas_engine 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +497 -33
  3. data/app/countries/atlas_engine/be/country_profile.yml +2 -0
  4. data/app/countries/atlas_engine/be/validation_transcriber/address_parser.rb +84 -0
  5. data/app/countries/atlas_engine/bm/address_importer/corrections/open_address/city_alias_corrector.rb +12 -11
  6. data/app/countries/atlas_engine/bm/synonyms.yml +6 -0
  7. data/app/countries/atlas_engine/ch/country_profile.yml +2 -0
  8. data/app/countries/atlas_engine/ch/locales/de/country_profile.yml +0 -1
  9. data/app/countries/atlas_engine/ch/locales/fr/country_profile.yml +3 -0
  10. data/app/countries/atlas_engine/ch/locales/fr/validation_transcriber/address_parser.rb +29 -0
  11. data/app/countries/atlas_engine/cz/address_validation/es/query_builder.rb +43 -0
  12. data/app/countries/atlas_engine/cz/country_profile.yml +2 -1
  13. data/app/countries/atlas_engine/cz/validation_transcriber/address_parser.rb +26 -0
  14. data/app/countries/atlas_engine/it/address_importer/open_address/mapper.rb +1 -1
  15. data/app/countries/atlas_engine/it/country_profile.yml +1 -0
  16. data/app/countries/atlas_engine/sa/country_profile.yml +4 -1
  17. data/app/countries/atlas_engine/us/country_profile.yml +0 -2
  18. data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +1 -1
  19. data/app/lib/atlas_engine/validation_transcriber/formatter.rb +2 -2
  20. data/app/models/atlas_engine/address_validation/datastore_base.rb +3 -0
  21. data/app/models/atlas_engine/address_validation/es/datastore.rb +11 -6
  22. data/app/models/atlas_engine/address_validation/es/query_builder.rb +40 -29
  23. data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +1 -1
  24. data/app/models/atlas_engine/address_validation/log_emitter.rb +1 -0
  25. data/app/models/atlas_engine/address_validation/normalizer.rb +0 -9
  26. data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +7 -23
  27. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +42 -16
  28. data/app/models/atlas_engine/address_validation/validators/full_address/comparison_helper.rb +109 -109
  29. data/app/models/atlas_engine/address_validation/validators/full_address/{components_to_validate.rb → relevant_components.rb} +26 -18
  30. data/app/models/atlas_engine/country_profile_validation_subset.rb +5 -0
  31. data/app/tasks/maintenance/atlas_engine/elasticsearch_index_create_task.rb +1 -1
  32. data/db/data/country_profiles/default.yml +0 -2
  33. data/lib/atlas_engine/version.rb +1 -1
  34. metadata +11 -5
@@ -11,22 +11,23 @@ module AtlasEngine
11
11
  extend T::Sig
12
12
 
13
13
  BM_PARISH_AND_CITY_NAMES = {
14
- "Devonshire" => "Devonshire Parish",
15
- "Hamilton" => "Hamilton Parish",
16
- "Paget" => "Paget Parish",
17
- "Pembroke" => "Pembroke Parish",
18
- "Sandys" => "Sandys Parish",
19
- "Smiths" => "Smiths Parish",
20
- "Southampton" => "Southampton Parish",
21
- "St. George's" => "St. George's Parish",
22
- "Town of St. George" => "St. George",
23
- "Warwick" => "Warwick Parish",
14
+ "City of Hamilton" => ["City of Hamilton", "Hamilton"],
15
+ "Devonshire" => ["Devonshire Parish", "Devonshire"],
16
+ "Hamilton" => ["Hamilton Parish", "Hamilton"],
17
+ "Paget" => ["Paget Parish", "Paget"],
18
+ "Pembroke" => ["Pembroke Parish", "Pembroke"],
19
+ "Sandys" => ["Sandys Parish", "Sandys"],
20
+ "Smiths" => ["Smiths Parish", "Smiths"],
21
+ "Southampton" => ["Southampton Parish", "Southampton"],
22
+ "St. George's" => ["St. George's Parish", "St. George's"],
23
+ "Town of St. George" => ["Town of St. George", "St. George"],
24
+ "Warwick" => ["Warwick Parish", "Warwick"],
24
25
  }.freeze
25
26
 
26
27
  sig { params(address: Hash).void }
27
28
  def apply(address)
28
29
  if BM_PARISH_AND_CITY_NAMES.key?(address[:city][0])
29
- address[:city] << BM_PARISH_AND_CITY_NAMES[address[:city][0]]
30
+ address[:city] = BM_PARISH_AND_CITY_NAMES[address[:city][0]]
30
31
  end
31
32
  end
32
33
  end
@@ -0,0 +1,6 @@
1
+ street_synonyms:
2
+ - lane, ln
3
+ - road, rd
4
+ - street, st
5
+ - avenue, ave
6
+ - drive, drv, dr
@@ -2,6 +2,8 @@ id: CH
2
2
  validation:
3
3
  enabled: true
4
4
  default_matching_strategy: local
5
+ has_provinces: false
6
+ address_parser: AtlasEngine::De::ValidationTranscriber::AddressParser
5
7
  index_locales:
6
8
  - de
7
9
  - fr
@@ -2,7 +2,6 @@ id: CH_DE
2
2
  ingestion:
3
3
  data_mapper: AtlasEngine::AddressValidation::Es::DataMappers::DecompoundingDataMapper
4
4
  validation:
5
- address_parser: AtlasEngine::De::ValidationTranscriber::AddressParser
6
5
  normalized_components:
7
6
  - region2
8
7
  - region3
@@ -0,0 +1,3 @@
1
+ id: CH_FR
2
+ validation:
3
+ address_parser: AtlasEngine::Ch::Locales::Fr::ValidationTranscriber::AddressParser
@@ -0,0 +1,29 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ # French address in Switzerland can be written in the following ways:
5
+ # 1. thoroughfare type[ ]Thoroughfare name[ ]number
6
+ # 2. number[ ]thoroughfare type[ ]Thoroughfare name
7
+
8
+ module AtlasEngine
9
+ module Ch
10
+ module Locales
11
+ module Fr
12
+ module ValidationTranscriber
13
+ class AddressParser < AtlasEngine::ValidationTranscriber::AddressParserBase
14
+ private
15
+
16
+ sig { returns(T::Array[Regexp]) }
17
+ def country_regex_formats
18
+ @country_regex_formats ||=
19
+ [
20
+ /^#{BUILDING_NUM}?\s*#{STREET_NO_COMMAS}$/o,
21
+ /^#{STREET_NO_COMMAS}?\s*#{BUILDING_NUM}$/o,
22
+ ]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Cz
6
+ module AddressValidation
7
+ module Es
8
+ class QueryBuilder < AtlasEngine::AddressValidation::Es::DefaultQueryBuilder
9
+ private
10
+
11
+ sig { returns(Hash) }
12
+ def street_clause
13
+ street_queries = [build_street_queries, empty_street_clause]
14
+
15
+ {
16
+ "dis_max" => {
17
+ "queries" => street_queries.flatten,
18
+ },
19
+ }
20
+ end
21
+
22
+ sig { returns(Hash) }
23
+ def empty_street_clause
24
+ {
25
+ "bool" => {
26
+ "must_not" => {
27
+ "exists" => {
28
+ "field" => "street",
29
+ },
30
+ },
31
+ },
32
+ }
33
+ end
34
+
35
+ sig { returns(T::Array[String]) }
36
+ def street_query_values
37
+ street_names.presence || []
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -2,5 +2,6 @@ id: CZ
2
2
  validation:
3
3
  enabled: true
4
4
  default_matching_strategy: es
5
- address_parser: AtlasEngine::Dk::ValidationTranscriber::AddressParser
5
+ address_parser: AtlasEngine::Cz::ValidationTranscriber::AddressParser
6
+ query_builder: AtlasEngine::Cz::AddressValidation::Es::QueryBuilder
6
7
  has_provinces: false
@@ -0,0 +1,26 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Cz
6
+ module ValidationTranscriber
7
+ class AddressParser < AtlasEngine::ValidationTranscriber::AddressParserBase
8
+ private
9
+
10
+ sig { returns(T::Array[Regexp]) }
11
+ def country_regex_formats
12
+ @country_regex_formats ||= [
13
+ /^#{BUILDING_NUM}$/,
14
+ /^#{STREET_NO_COMMAS}\s+#{BUILDING_NUM}?$/,
15
+ ]
16
+ end
17
+
18
+ def ridiculous?(captures, address)
19
+ return false if captures[:street].blank?
20
+
21
+ address.city == captures[:street]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -29,7 +29,7 @@ module AtlasEngine
29
29
  city: [city.titleize],
30
30
  suburb: nil,
31
31
  zip: postcode,
32
- street: street.titleize,
32
+ street: street,
33
33
  building_and_unit_ranges: housenumber_and_unit(number, unit),
34
34
  latitude: geometry(feature)&.at(1),
35
35
  longitude: geometry(feature)&.at(0),
@@ -2,6 +2,7 @@ id: IT
2
2
  validation:
3
3
  enabled: true
4
4
  default_matching_strategy: es
5
+ address_parser: AtlasEngine::Dk::ValidationTranscriber::AddressParser
5
6
  ingestion:
6
7
  open_address:
7
8
  feature_mapper: AtlasEngine::It::AddressImporter::OpenAddress::Mapper
@@ -3,7 +3,10 @@ validation:
3
3
  enabled: false
4
4
  default_matching_strategy: es
5
5
  has_provinces: false
6
- restrictions:
6
+ normalized_components:
7
+ - region1
8
+ - city_aliases.alias
9
+ - street
7
10
  restrictions:
8
11
  - class: AtlasEngine::Restrictions::UnsupportedScript
9
12
  params:
@@ -2,8 +2,6 @@ id: US
2
2
  validation:
3
3
  enabled: true
4
4
  default_matching_strategy: es_street
5
- city_fields:
6
- - city_aliases
7
5
  address_parser: AtlasEngine::ValidationTranscriber::AddressParserNorthAmerica
8
6
  ingestion:
9
7
  settings:
@@ -42,7 +42,7 @@ module AtlasEngine
42
42
 
43
43
  sig { returns(T::Array[String]) }
44
44
  def potential_building_numbers
45
- parsings.pluck(:building_num).compact.uniq
45
+ parsings.pluck(:building_num).compact.uniq.reject { |n| n.match?(/\d{7,}/) }
46
46
  end
47
47
 
48
48
  sig { params(address_input: AddressValidation::AbstractAddress).void }
@@ -13,8 +13,8 @@ module AtlasEngine
13
13
 
14
14
  sig { params(haystack: String, needle: String).returns(String) }
15
15
  def strip_word(haystack, needle)
16
- string = haystack.sub(/[\s](#{Regexp.escape(needle)})([\s]|$)/i, " ").strip
17
- string = string.sub(/[\s,](#{Regexp.escape(needle)})([\s,]|$)/i, "").strip
16
+ string = haystack.sub(/([\s]|^)(#{Regexp.escape(needle)})([\s]|$)/i, " ").strip
17
+ string = string.sub(/([\s,]|^)(#{Regexp.escape(needle)})([\s,]|$)/i, "").strip
18
18
  string = strip_trailing_punctuation(string)
19
19
  string || ""
20
20
  end
@@ -20,6 +20,9 @@ module AtlasEngine
20
20
  sig { abstract.returns(T::Hash[T.untyped, T.untyped]) }
21
21
  def validation_response; end
22
22
 
23
+ sig { abstract.returns(CountryProfile) }
24
+ def country_profile; end
25
+
23
26
  sig { abstract.returns(ValidationTranscriber::AddressParsings) }
24
27
  def parsings; end
25
28
  end
@@ -10,7 +10,12 @@ module AtlasEngine
10
10
  include DatastoreBase
11
11
  extend T::Sig
12
12
 
13
+ sig { override.returns(CountryProfile) }
14
+ attr_reader :country_profile
15
+
16
+ sig { override.returns(ValidationTranscriber::AddressParsings) }
13
17
  attr_reader :parsings
18
+
14
19
  attr_writer :candidates # meant for test setup only
15
20
 
16
21
  sig { params(address: AbstractAddress, locale: T.nilable(String)).void }
@@ -21,9 +26,9 @@ module AtlasEngine
21
26
  raise ArgumentError, "address has no country_code" if address.country_code.blank?
22
27
 
23
28
  @country_code = T.must(address.country_code.to_s)
24
- @profile = CountryProfile.for(country_code.to_s.upcase)
29
+ @country_profile = CountryProfile.for(country_code.to_s.upcase, @locale)
25
30
 
26
- if locale.nil? && @profile.validation.multi_locale?
31
+ if locale.nil? && @country_profile.validation.multi_locale?
27
32
  raise ArgumentError, "#{country_code} is a multi-locale country and requires a locale"
28
33
  end
29
34
 
@@ -107,7 +112,7 @@ module AtlasEngine
107
112
 
108
113
  private
109
114
 
110
- attr_reader :address, :country_code, :locale, :profile, :query_builder
115
+ attr_reader :address, :country_code, :locale, :query_builder
111
116
 
112
117
  sig { returns(Token::Sequence) }
113
118
  def fetch_city_sequence_internal
@@ -153,7 +158,7 @@ module AtlasEngine
153
158
 
154
159
  sig { params(candidates: T::Array[Candidate]).void }
155
160
  def assign_term_vectors_to_candidates(candidates)
156
- return if profile.validation.normalized_components.blank?
161
+ return if country_profile.validation.normalized_components.blank?
157
162
 
158
163
  candidate_term_vectors = measure_es_validation_request_time(method: "term_vectors") do
159
164
  repository.term_vectors(term_vectors_query(candidates))
@@ -167,7 +172,7 @@ module AtlasEngine
167
172
  {
168
173
  ids: candidates.map(&:id),
169
174
  parameters: {
170
- fields: profile.validation.normalized_components,
175
+ fields: country_profile.validation.normalized_components,
171
176
  field_statistics: false,
172
177
  },
173
178
  }
@@ -219,7 +224,7 @@ module AtlasEngine
219
224
  FieldDecompounder.new(
220
225
  field: :street,
221
226
  value: street_value,
222
- country_profile: profile,
227
+ country_profile:,
223
228
  ).call,
224
229
  )
225
230
  end
@@ -37,22 +37,15 @@ module AtlasEngine
37
37
  sig { returns(CountryProfile) }
38
38
  attr_reader :profile
39
39
 
40
- sig { returns(Hash) }
40
+ sig { returns(T.nilable(Hash)) }
41
41
  def building_number_clause
42
- potential_building_numbers = @parsings.potential_building_numbers.filter_map do |n|
43
- AddressNumber.new(value: n).to_i
44
- end.uniq
42
+ building_number_clause = approx_building_clauses
45
43
 
46
- building_number_queries = [empty_approx_building_clause]
47
- building_number_queries.unshift(
48
- *T.unsafe(potential_building_numbers.map do |value|
49
- approx_building_clause(value)
50
- end),
51
- ) if potential_building_numbers.any?
44
+ return if building_number_clause.nil?
52
45
 
53
46
  {
54
47
  "dis_max" => {
55
- "queries" => building_number_queries,
48
+ "queries" => building_number_clause,
56
49
  },
57
50
  }
58
51
  end
@@ -68,6 +61,19 @@ module AtlasEngine
68
61
  }
69
62
  end
70
63
 
64
+ sig { returns(T.nilable(Array)) }
65
+ def approx_building_clauses
66
+ potential_building_numbers = @parsings.potential_building_numbers.filter_map do |n|
67
+ AddressNumber.new(value: n).to_i
68
+ end.uniq
69
+
70
+ if potential_building_numbers.any?
71
+ potential_building_numbers.map do |value|
72
+ approx_building_clause(value)
73
+ end
74
+ end
75
+ end
76
+
71
77
  sig { returns(Hash) }
72
78
  def empty_approx_building_clause
73
79
  {
@@ -85,25 +91,30 @@ module AtlasEngine
85
91
  def street_clause
86
92
  {
87
93
  "dis_max" => {
88
- "queries" => street_query_values.map do |value|
89
- {
90
- "match" => {
91
- "street" => { "query" => value, "fuzziness" => "auto" },
92
- },
93
- }
94
- end.union(
95
- stripped_street_query_values.map do |value|
96
- {
97
- "match" => {
98
- "street_stripped" => { "query" => value, "fuzziness" => "auto" },
99
- },
100
- }
101
- end,
102
- ),
94
+ "queries" => build_street_queries,
103
95
  },
104
96
  }
105
97
  end
106
98
 
99
+ sig { returns(Array) }
100
+ def build_street_queries
101
+ street_query_values.map do |value|
102
+ {
103
+ "match" => {
104
+ "street" => { "query" => value, "fuzziness" => "auto" },
105
+ },
106
+ }
107
+ end.union(
108
+ stripped_street_query_values.map do |value|
109
+ {
110
+ "match" => {
111
+ "street_stripped" => { "query" => value, "fuzziness" => "auto" },
112
+ },
113
+ }
114
+ end,
115
+ )
116
+ end
117
+
107
118
  sig { returns(T::Array[String]) }
108
119
  def street_query_values
109
120
  street_names.presence || [address.address1.to_s, address.address2.to_s].compact_blank.uniq
@@ -149,10 +160,10 @@ module AtlasEngine
149
160
  sig { returns(T.nilable(Hash)) }
150
161
  def province_clause
151
162
  {
152
- "term" => {
153
- "province_code" => { "value" => address.province_code.to_s.downcase },
163
+ "match" => {
164
+ "province_code" => { "query" => address.province_code.to_s.downcase },
154
165
  },
155
- } if profile.attributes.dig("validation", "has_provinces")
166
+ } if profile.attributes.dig("validation", "has_provinces") && address.province_code.present?
156
167
  end
157
168
  end
158
169
  end
@@ -80,7 +80,7 @@ module AtlasEngine
80
80
  .returns(T.untyped)
81
81
  end
82
82
  def publish_notification(candidate_result: nil)
83
- ActiveSupport::Notifications.instrument("atlas-engine.address_validation.validation_completed", {
83
+ ActiveSupport::Notifications.instrument("atlas_engine.address_validation.validation_completed", {
84
84
  candidate_result: candidate_result,
85
85
  result: result,
86
86
  }.compact)
@@ -35,6 +35,7 @@ module AtlasEngine
35
35
  end
36
36
  data = {
37
37
  country_code: address.country_code,
38
+ matching_strategy: result.matching_strategy,
38
39
  formatted_address: formatted_address,
39
40
  concerns: concern_codes,
40
41
  suggestions: result.suggestions.map(&:attributes),
@@ -18,15 +18,6 @@ module AtlasEngine
18
18
  .gsub("æ", "ae")
19
19
  .gsub("œ", "oe")
20
20
  .gsub(" ", " ")
21
- # normalizes Arabic characters
22
- .tr("آ", "ا")
23
- .tr("أ", "ا")
24
- .tr("إ", "ا")
25
- .tr("ئ", "ي")
26
- .tr("ة", "ه")
27
- .tr("ى", "ي")
28
- # removes Arabic stretching characters and diacritics
29
- .gsub(/[\u064B|\u064C|\u064D|\u064E|\u064F|\u0650|\u0651|\u0652|\u0640]/, "")
30
21
  # TODO: Strip hyphens for USPS not zip
31
22
  .gsub(/[!@%&"'*,.();:]/, "")
32
23
  .downcase
@@ -9,34 +9,18 @@ module AtlasEngine
9
9
  extend T::Sig
10
10
  include Comparable
11
11
 
12
- attr_reader :street_comparison,
12
+ attr_reader :comparison_helper
13
+
14
+ delegate :street_comparison,
13
15
  :city_comparison,
14
- :zip_comparison,
15
16
  :province_code_comparison,
16
- :building_comparison
17
+ :zip_comparison,
18
+ :building_comparison,
19
+ to: :comparison_helper
17
20
 
18
21
  sig { params(address: AbstractAddress, candidate: Candidate, datastore: DatastoreBase).void }
19
22
  def initialize(address:, candidate:, datastore:)
20
- @street_comparison = ComparisonHelper.street_comparison(
21
- datastore: datastore,
22
- candidate: candidate,
23
- )
24
- @city_comparison = ComparisonHelper.city_comparison(
25
- datastore: datastore,
26
- candidate: candidate,
27
- )
28
- @zip_comparison = ComparisonHelper.zip_comparison(
29
- address: address,
30
- candidate: candidate,
31
- )
32
- @province_code_comparison = ComparisonHelper.province_code_comparison(
33
- address: address,
34
- candidate: candidate,
35
- )
36
- @building_comparison = ComparisonHelper.building_comparison(
37
- datastore: datastore,
38
- candidate: candidate,
39
- )
23
+ @comparison_helper = ComparisonHelper.new(address:, candidate:, datastore:)
40
24
  end
41
25
 
42
26
  sig { params(other: AddressComparison).returns(Integer) }
@@ -9,6 +9,8 @@ module AtlasEngine
9
9
  extend T::Sig
10
10
  include LogHelper
11
11
 
12
+ delegate :street_comparison, to: :address_comparison
13
+
12
14
  sig do
13
15
  params(
14
16
  candidate: AddressValidation::CandidateTuple,
@@ -25,8 +27,8 @@ module AtlasEngine
25
27
 
26
28
  sig { override.void }
27
29
  def update_result
28
- result.candidate = candidate&.serialize
29
- return if unmatched_components.empty?
30
+ result.candidate = candidate.serialize
31
+ return if unmatched_components_to_validate.empty?
30
32
 
31
33
  update_concerns_and_suggestions
32
34
  update_result_scope
@@ -39,8 +41,12 @@ module AtlasEngine
39
41
 
40
42
  private
41
43
 
44
+ sig { returns(Candidate) }
42
45
  attr_reader :candidate
43
46
 
47
+ sig { returns(AddressComparison) }
48
+ attr_reader :address_comparison
49
+
44
50
  sig { void }
45
51
  def update_concerns_and_suggestions
46
52
  if suggestable?
@@ -62,7 +68,7 @@ module AtlasEngine
62
68
 
63
69
  sig { void }
64
70
  def add_concerns_with_suggestions
65
- unmatched_components.keys.each do |unmatched_component|
71
+ unmatched_components_to_validate.keys.each do |unmatched_component|
66
72
  field_name = unmatched_field_name(unmatched_component)
67
73
  if field_name.nil?
68
74
  log_unknown_field_name
@@ -72,7 +78,7 @@ module AtlasEngine
72
78
  concern = ConcernBuilder.new(
73
79
  unmatched_component: unmatched_component,
74
80
  unmatched_field: field_name,
75
- matched_components: matched_components.keys,
81
+ matched_components: matched_components_to_validate.keys,
76
82
  address: session.address,
77
83
  suggestion_ids: [suggestion.id].compact,
78
84
  ).build
@@ -87,7 +93,7 @@ module AtlasEngine
87
93
 
88
94
  @suggestion ||= SuggestionBuilder.from_comparisons(
89
95
  session.address.to_h,
90
- unmatched_components,
96
+ unmatched_components_to_validate,
91
97
  candidate,
92
98
  unmatched_fields,
93
99
  )
@@ -103,11 +109,25 @@ module AtlasEngine
103
109
  @unmatched_components || split_matched_and_unmatched_components.second
104
110
  end
105
111
 
112
+ sig { returns(T::Hash[Symbol, AtlasEngine::AddressValidation::Token::Sequence::Comparison]) }
113
+ def matched_components_to_validate
114
+ matched_components.select do |k, _v|
115
+ components_to_validate.include?(k)
116
+ end
117
+ end
118
+
119
+ sig { returns(T::Hash[Symbol, AtlasEngine::AddressValidation::Token::Sequence::Comparison]) }
120
+ def unmatched_components_to_validate
121
+ unmatched_components.select do |k, _v|
122
+ components_to_validate.include?(k)
123
+ end
124
+ end
125
+
106
126
  sig { returns(T::Hash[Symbol, T.nilable(AtlasEngine::AddressValidation::Token::Sequence::Comparison)]) }
107
127
  def matched_and_unmatched_components
108
128
  components = {}
109
129
  @matched_and_unmatched_components ||= begin
110
- components_to_validate.each do |field|
130
+ components_to_compare.each do |field|
111
131
  components[field] = @address_comparison.send(:"#{field}_comparison")
112
132
  end
113
133
  components
@@ -116,7 +136,17 @@ module AtlasEngine
116
136
 
117
137
  sig { returns(T::Array[Symbol]) }
118
138
  def components_to_validate
119
- ComponentsToValidate.new(session, candidate, street_comparison).run
139
+ relevant_components.components_to_validate
140
+ end
141
+
142
+ sig { returns(T::Array[Symbol]) }
143
+ def components_to_compare
144
+ relevant_components.components_to_compare
145
+ end
146
+
147
+ sig { returns(RelevantComponents) }
148
+ def relevant_components
149
+ @relevant_components ||= RelevantComponents.new(session, candidate, street_comparison)
120
150
  end
121
151
 
122
152
  sig do
@@ -124,24 +154,20 @@ module AtlasEngine
124
154
  T.nilable(AtlasEngine::AddressValidation::Token::Sequence::Comparison)]])
125
155
  end
126
156
  def split_matched_and_unmatched_components
157
+ return @matched_components, @unmatched_components if defined?(@matched_components) &&
158
+ defined?(@unmatched_components)
159
+
127
160
  @matched_components, @unmatched_components = matched_and_unmatched_components.partition do |_, comparison|
128
161
  comparison&.match?
129
162
  end.map(&:to_h)
130
163
  end
131
164
 
132
- sig { returns(T.nilable(AtlasEngine::AddressValidation::Token::Sequence::Comparison)) }
133
- def street_comparison
134
- return @street_comparison if defined?(@street_comparison)
135
-
136
- @street_comparison = @address_comparison.street_comparison
137
- end
138
-
139
165
  sig { params(component: Symbol).returns(T.nilable(Symbol)) }
140
166
  def unmatched_field_name(component)
141
167
  return component unless component == :street
142
- return if unmatched_components[:street].nil?
168
+ return if unmatched_components_to_validate[:street].nil?
143
169
 
144
- original_street = T.must(unmatched_components[:street]).left_sequence.raw_value
170
+ original_street = T.must(unmatched_components_to_validate[:street]).left_sequence.raw_value
145
171
 
146
172
  if session.address.address1.to_s.include?(original_street)
147
173
  :address1