Class: ClaimFastTracking::FlashPicker

Inherits:
Object
  • Object
show all
Defined in:
app/services/claim_fast_tracking/flash_picker.rb

Constant Summary collapse

DEFAULT_FUZZY_TOLERANCE =
0.2
MIN_FUZZY_MATCH_LENGTH =
6
MIN_LENGTH_RATIO =
0.9
ALS_DC =
8017
ALS_PARTIAL_MATCH_TERMS =
[
  'amyotrophic lateral sclerosis',
  '(als)'
].freeze
ALS_MATCH_TERMS =
(ALS_PARTIAL_MATCH_TERMS + [
  'als',
  'lou gehrig disease',
  'lou gehrigs disease',
  'lou gehrig\'s disease',
  'lou gehrig',
  'lou gehrigs',
  'lou gehrig\'s'
]).freeze

Class Method Summary collapse

Class Method Details

.als?(claimed_disabilities) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
30
# File 'app/services/claim_fast_tracking/flash_picker.rb', line 24

def self.als?(claimed_disabilities)
  return if claimed_disabilities.pluck('diagnosticCode').include?(ALS_DC)

  claimed_disabilities.map { |disability| disability['name']&.downcase }.compact.any? do |name|
    partial_matches?(name, ALS_PARTIAL_MATCH_TERMS) || matches?(name, ALS_MATCH_TERMS)
  end
end

.fuzzy_match?(name, term, longer_length, tolerance = DEFAULT_FUZZY_TOLERANCE) ⇒ Boolean (private)

Returns:

  • (Boolean)


64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/services/claim_fast_tracking/flash_picker.rb', line 64

def self.fuzzy_match?(name, term, longer_length, tolerance = DEFAULT_FUZZY_TOLERANCE)
  threshold = (longer_length * tolerance).ceil
  distance = StringHelpers.levenshtein_distance(name, term)

  if distance - 1 == threshold
    Rails.logger.info(
      'FlashPicker close fuzzy match for condition',
      { name: name, match_term: term, distance: distance, threshold: threshold }
    )
  end
  distance <= threshold
end

.matches?(name, match_terms, tolerance = DEFAULT_FUZZY_TOLERANCE, min_length_ratio = MIN_LENGTH_RATIO, min_length_limit = MIN_FUZZY_MATCH_LENGTH) ⇒ Boolean (private)

Returns:

  • (Boolean)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'app/services/claim_fast_tracking/flash_picker.rb', line 38

def self.matches?(name,
                  match_terms,
                  tolerance = DEFAULT_FUZZY_TOLERANCE,
                  min_length_ratio = MIN_LENGTH_RATIO,
                  min_length_limit = MIN_FUZZY_MATCH_LENGTH)
  match_terms = [match_terms] unless match_terms.is_a?(Array)

  match_terms.any? do |term|
    # Early exact match check (case insensitive)
    return true if name.casecmp?(term)

    # Prevent fuzzy matching for very short terms (e.g., less than min_length_limit)
    next false if name.length < min_length_limit || term.length < min_length_limit

    # Calculate the length ratio based on the shorter and longer lengths
    shorter_length = [name.length, term.length].min
    longer_length = [name.length, term.length].max

    # Skip comparison if the length ratio is below minimum length ratio, indicating a significant length difference
    next false if shorter_length.to_f / longer_length < min_length_ratio

    # Calculate the Levenshtein threshold based on tolerance and maximum length
    return true if fuzzy_match?(name, term, longer_length, tolerance)
  end
end

.partial_matches?(name, match_terms) ⇒ Boolean (private)

Returns:

  • (Boolean)


32
33
34
35
36
# File 'app/services/claim_fast_tracking/flash_picker.rb', line 32

def self.partial_matches?(name, match_terms)
  match_terms = [match_terms] unless match_terms.is_a?(Array)

  match_terms.any? { |term| name.include?(term) }
end