Class: Ast::Merge::MatchScoreBase

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/ast/merge/match_score_base.rb

Overview

Base class for computing match scores between two nodes.

Match scores help determine which nodes from a template should be linked to which nodes in a destination document. This is particularly useful for complex nodes like tables where simple signature matching is insufficient.

The scoring algorithm is provided as a callable object (lambda, Proc, or any object responding to :call) which receives the two nodes and returns a score between 0.0 (no match) and 1.0 (perfect match).

Includes Comparable for sorting and comparison operations.

Examples:

Basic usage with a lambda

algorithm = ->(node_a, node_b) { node_a.type == node_b.type ? 1.0 : 0.0 }
scorer = MatchScoreBase.new(template_node, dest_node, algorithm: algorithm)
puts scorer.score # => 1.0 if types match

With a custom algorithm class

class TableMatcher
  def call(table_a, table_b)
    # Complex matching logic
    compute_similarity(table_a, table_b)
  end
end

scorer = MatchScoreBase.new(table1, table2, algorithm: TableMatcher.new)

Comparing and sorting scorers

scorers = [scorer1, scorer2, scorer3]
best = scorers.max
sorted = scorers.sort

Constant Summary collapse

DEFAULT_THRESHOLD =

Minimum score threshold for considering two nodes as a potential match

Returns:

  • (Float)
0.5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node_a, node_b, algorithm:, threshold: DEFAULT_THRESHOLD) ⇒ MatchScoreBase

Initialize a match scorer.

Parameters:

  • node_a (Object)

    First node to compare

  • node_b (Object)

    Second node to compare

  • algorithm (#call)

    Callable that computes the score (receives node_a, node_b)

  • threshold (Float) (defaults to: DEFAULT_THRESHOLD)

    Minimum score to consider a match (default: 0.5)

Raises:

  • (ArgumentError)

    If algorithm doesn’t respond to :call



64
65
66
67
68
69
70
71
72
# File 'lib/ast/merge/match_score_base.rb', line 64

def initialize(node_a, node_b, algorithm:, threshold: DEFAULT_THRESHOLD)
  raise ArgumentError, "algorithm must respond to :call" unless algorithm.respond_to?(:call)

  @node_a = node_a
  @node_b = node_b
  @algorithm = algorithm
  @threshold = threshold
  @score = nil
end

Instance Attribute Details

#algorithm#call (readonly)

Returns The algorithm used to compute the match score.

Returns:

  • (#call)

    The algorithm used to compute the match score



52
53
54
# File 'lib/ast/merge/match_score_base.rb', line 52

def algorithm
  @algorithm
end

#node_aObject (readonly)

Returns The first node to compare (typically from template).

Returns:

  • (Object)

    The first node to compare (typically from template)



46
47
48
# File 'lib/ast/merge/match_score_base.rb', line 46

def node_a
  @node_a
end

#node_bObject (readonly)

Returns The second node to compare (typically from destination).

Returns:

  • (Object)

    The second node to compare (typically from destination)



49
50
51
# File 'lib/ast/merge/match_score_base.rb', line 49

def node_b
  @node_b
end

#thresholdFloat (readonly)

Returns The minimum score to consider a match.

Returns:

  • (Float)

    The minimum score to consider a match



55
56
57
# File 'lib/ast/merge/match_score_base.rb', line 55

def threshold
  @threshold
end

Instance Method Details

#<=>(other) ⇒ Integer

Compare two scorers by their scores.

Required by Comparable. Enables <, <=, ==, >=, >, and between? operators.

Parameters:

Returns:

  • (Integer)

    -1, 0, or 1 for comparison



96
97
98
# File 'lib/ast/merge/match_score_base.rb', line 96

def <=>(other)
  score <=> other.score
end

#eql?(other) ⇒ Boolean

Check equality for Hash key compatibility.

Two scorers are eql? if they have the same node_a, node_b, and score. This is stricter than == from Comparable (which only compares scores).

Parameters:

Returns:

  • (Boolean)

    True if equivalent



117
118
119
120
121
# File 'lib/ast/merge/match_score_base.rb', line 117

def eql?(other)
  return false unless other.is_a?(MatchScoreBase)

  node_a == other.node_a && node_b == other.node_b && score == other.score
end

#hashInteger

Generate a hash code for this scorer.

Required for Hash key compatibility. Two scorers with the same node_a, node_b, and score should have the same hash.

Returns:

  • (Integer)

    Hash code



106
107
108
# File 'lib/ast/merge/match_score_base.rb', line 106

def hash
  [node_a, node_b, score].hash
end

#match?Boolean

Check if the score meets the threshold for a match.

Returns:

  • (Boolean)

    True if score >= threshold



86
87
88
# File 'lib/ast/merge/match_score_base.rb', line 86

def match?
  score >= threshold
end

#scoreFloat

Compute and return the match score.

The score is cached after first computation.

Returns:

  • (Float)

    Score between 0.0 and 1.0



79
80
81
# File 'lib/ast/merge/match_score_base.rb', line 79

def score
  @score ||= compute_score
end