Class: Kotoshu::Suggestions::Suggestion
- Inherits:
-
Lutaml::Model::Serializable
- Object
- Lutaml::Model::Serializable
- Kotoshu::Suggestions::Suggestion
- Defined in:
- lib/kotoshu/suggestions/suggestion.rb
Overview
A single suggestion with associated metadata and behavior.
Serialized via lutaml-model. Use to_hash / Suggestion.as_json(instance) /
Suggestion.from_hash(hash) / Suggestion.from_json(string) for the
wire forms — no hand-rolled to_h / as_json on the model.
Class Method Summary collapse
-
.from_word(word, source: :unknown) ⇒ Suggestion
Create a suggestion from a simple word (convenience method).
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer?
Compare suggestions for sorting (higher combined score first).
- #==(other) ⇒ Object (also: #eql?)
-
#combined_score(distance_weight: 0.3, confidence_weight: 0.7) ⇒ Float
Calculate combined score considering distance and confidence.
-
#from_source?(source) ⇒ Boolean
Check if this suggestion comes from a specific source.
- #hash ⇒ Object
-
#high_confidence? ⇒ Boolean
Check if this is a high-confidence suggestion.
-
#initialize(word: nil, distance: 0, confidence: 1.0, source: "unknown", **metadata) ⇒ Suggestion
constructor
Support the legacy
**metadatakwarg catch-all so existing callers (e.g.,Suggestion.new(word:, distance:, source:, original_length: 5)) continue to work; extra kwargs land in themetadataattribute. -
#low_confidence? ⇒ Boolean
Check if this is a low-confidence suggestion.
-
#same_word?(other) ⇒ Boolean
Check if this suggestion is the same word as another.
- #to_s ⇒ Object (also: #inspect)
Constructor Details
#initialize(word: nil, distance: 0, confidence: 1.0, source: "unknown", **metadata) ⇒ Suggestion
Support the legacy **metadata kwarg catch-all so existing callers
(e.g., Suggestion.new(word:, distance:, source:, original_length: 5))
continue to work; extra kwargs land in the metadata attribute.
Source is stored as a string for clean serialization; from_source?
normalizes Symbol/String comparison so callers can pass either.
word defaults to nil purely to accommodate lutaml-model's
deserialization pathway, which allocates a shell via
new(lutaml_register:) before applying attribute values through
the deserialize pipeline. Direct callers must still pass word:
— a Suggestion without a word is degenerate and not user-facing.
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 30 def initialize(word: nil, distance: 0, confidence: 1.0, source: "unknown", **) lutaml_register = .delete(:lutaml_register) kwargs = { word: word, distance: distance, confidence: confidence, source: source.to_s, metadata: } kwargs[:lutaml_register] = lutaml_register if lutaml_register super(**kwargs) end |
Class Method Details
.from_word(word, source: :unknown) ⇒ Suggestion
Create a suggestion from a simple word (convenience method).
149 150 151 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 149 def self.from_word(word, source: :unknown) new(word: word, distance: 0, confidence: 1.0, source: source) end |
Instance Method Details
#<=>(other) ⇒ Integer?
Compare suggestions for sorting (higher combined score first).
Ranking priority (following CSpell/Hunspell approach):
- Combined score (higher is better)
- Edit distance (lower is better)
- Length similarity (prefer similar length to original word)
- N-gram similarity (more shared n-grams is better)
- Alphabetical (ONLY as final tiebreaker)
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 99 def <=>(other) return nil unless other.is_a?(Suggestion) score_cmp = other.combined_score <=> combined_score return score_cmp unless score_cmp.zero? distance_cmp = distance <=> other.distance return distance_cmp unless distance_cmp.zero? orig_len = [:original_length] || word.length other_orig_len = other.[:original_length] || other.word.length my_len_diff = (word.length - orig_len).abs other_len_diff = (other.word.length - other_orig_len).abs len_cmp = my_len_diff <=> other_len_diff return len_cmp unless len_cmp.zero? my_ngram = [:ngram_score] || 0 other_ngram = other.[:ngram_score] || 0 ngram_cmp = other_ngram <=> my_ngram return ngram_cmp unless ngram_cmp.zero? word.downcase <=> other.word.downcase end |
#==(other) ⇒ Object Also known as: eql?
126 127 128 129 130 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 126 def ==(other) return false unless other.is_a?(Suggestion) word.downcase == other.word.downcase end |
#combined_score(distance_weight: 0.3, confidence_weight: 0.7) ⇒ Float
Calculate combined score considering distance and confidence.
62 63 64 65 66 67 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 62 def combined_score(distance_weight: 0.3, confidence_weight: 0.7) normalized_distance = [distance, 5].min / 5.0 distance_score = 1.0 - normalized_distance (distance_score * distance_weight) + (confidence * confidence_weight) end |
#from_source?(source) ⇒ Boolean
Check if this suggestion comes from a specific source.
Source is stored as a string; comparison normalizes Symbol/String.
84 85 86 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 84 def from_source?(source) self.source == source.to_s end |
#hash ⇒ Object
133 134 135 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 133 def hash word.downcase.hash end |
#high_confidence? ⇒ Boolean
Check if this is a high-confidence suggestion.
46 47 48 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 46 def high_confidence? confidence >= 0.8 end |
#low_confidence? ⇒ Boolean
Check if this is a low-confidence suggestion.
53 54 55 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 53 def low_confidence? confidence < 0.5 end |
#same_word?(other) ⇒ Boolean
Check if this suggestion is the same word as another.
73 74 75 76 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 73 def same_word?(other) other_word = other.is_a?(Suggestion) ? other.word : other.to_s word.downcase == other_word.downcase end |
#to_s ⇒ Object Also known as: inspect
137 138 139 140 |
# File 'lib/kotoshu/suggestions/suggestion.rb', line 137 def to_s format("Suggestion(word: '%<word>s', distance: %<distance>d, confidence: %<confidence>.2f, source: %<source>s)", word: word, distance: distance, confidence: confidence, source: source) end |