Module: SecID::Suggestable

Included in:
CEI, CUSIP, DTI, FIGI, IBAN, ISIN, LEI, SEDOL, UPI
Defined in:
lib/sec_id/concerns/suggestable.rb

Overview

Repair engine for checksum-failing identifiers: enumerates plausible single-character edits (homoglyph/OCR substitutions and adjacent transpositions), keeps only those that re-validate, and returns them as confidence-ranked Suggestion objects.

Included by the 9 checksum types. The candidate space is the human-error net — HOMOGLYPHS plus adjacent transpositions — never a full coincidental net. valid? is the oracle, so no checksum-invalid candidate ever escapes (a valid candidate is not necessarily the intended correction); the HOMOGLYPHS table bounds recall.

Examples:

SecID::ISIN.suggest('US5949181O45')
#=> [#<SecID::Suggestion edit=:substitution ...>, #<SecID::Suggestion edit=:checksum ...>]

See Also:

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

HOMOGLYPHS =

Homoglyph / OCR confusion table (KTD5 seed): each character maps to the characters it is commonly mistyped as or misread from. A bidirectional expansion of the seed pairs 0/Q, 0/D, 1/I, 1/L, I/L, 2/Z, 5/S, 6/G, 8/B. Membership bounds recall — widen it (see benchmark/suggest_precision.rb) to raise it.

{
  '0' => %w[O Q D], 'O' => %w[0], 'Q' => %w[0], 'D' => %w[0],
  '1' => %w[I L], 'I' => %w[1 L], 'L' => %w[1 I],
  '2' => %w[Z], 'Z' => %w[2], '5' => %w[S], 'S' => %w[5],
  '6' => %w[G], 'G' => %w[6], '8' => %w[B], 'B' => %w[8]
}.freeze
RANK =

Rank weight per edit kind: body substitutions first, then adjacent transpositions, then the checksum-recompute fallback last (R6/R7).

{ substitution: 0, transposition: 1, checksum: 2 }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Extends the including identifier class with the concern's class methods.

Parameters:

  • base (Class)

    the identifier class including this concern



39
40
41
# File 'lib/sec_id/concerns/suggestable.rb', line 39

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

#suggestArray<Suggestion>

Enumerates plausible edits and returns the re-validating ones, confidence-ranked.

Returns:

  • (Array<Suggestion>)

    ranked candidates; empty when already valid or unparseable



58
59
60
61
62
63
64
# File 'lib/sec_id/concerns/suggestable.rb', line 58

def suggest
  return [] if valid?
  return [] unless valid_format?

  surviving = candidate_strings.uniq.map { |candidate| self.class.new(candidate) }.select(&:valid?)
  surviving.filter_map { |candidate| classify(candidate) }.sort_by { |suggestion| RANK.fetch(suggestion.edit) }
end