Class: PossibleKey

Inherits:
Object
  • Object
show all
Includes:
Stats
Defined in:
lib/spellr/key_tuner/possible_key.rb

Overview

rubocop:disable Metrics/ClassLength

Constant Summary collapse

VOWELS =
%i{
  a e i o u
  A E I O U
}.freeze
CONSONANTS =
%i{
  b c d f g h j k l m n p q r s t v w x y z
  B C D F G H J K L M N P Q R S T V W X Y Z
}.freeze
BASE_64 =
VOWELS + CONSONANTS + %i{0 1 2 3 4 5 6 7 8 9 - _ + / =}.freeze
LETTER_COUNT_HASH =
letter_count_hash
FEATURE_LETTERS =
%i{+ - _ / A z Z q Q X x}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Stats

gaussian_probability, max, mean, min, standard_deviation, variance

Constructor Details

#initialize(string, key = nil) ⇒ PossibleKey

Returns a new instance of PossibleKey.



28
29
30
31
# File 'lib/spellr/key_tuner/possible_key.rb', line 28

def initialize(string, key = nil)
  @string = string
  @key = key
end

Instance Attribute Details

#string ⇒ Object (readonly)

Returns the value of attribute string.



26
27
28
# File 'lib/spellr/key_tuner/possible_key.rb', line 26

def string
  @string
end

Instance Method Details

#alnum_chunks ⇒ Object



155
156
157
# File 'lib/spellr/key_tuner/possible_key.rb', line 155

def alnum_chunks
  @alnum_chunks ||= string.scan(/[A-Za-z0-9]+/)
end

#alpha_chunks ⇒ Object



151
152
153
# File 'lib/spellr/key_tuner/possible_key.rb', line 151

def alpha_chunks
  @alpha_chunks ||= string.scan(/[A-Za-z]+/)
end

#character_set ⇒ Object



82
83
84
85
86
87
88
89
# File 'lib/spellr/key_tuner/possible_key.rb', line 82

def character_set
  @character_set ||= case string
  when /^[a-fA-F0-9\-]+$/ then :hex
  when /^[a-z0-9]+$/ then :lower36
  when /^[A-Z0-9]+$/ then :upper36
  when %r{^[A-Za-z0-9\-_+/]+={0,2}$} then :base64
  end
end

#character_set_total ⇒ Object

rubocop:disable Metrics/MethodLength



91
92
93
94
95
96
97
98
99
# File 'lib/spellr/key_tuner/possible_key.rb', line 91

def character_set_total # rubocop:disable Metrics/MethodLength
  case character_set
  when :hex then 16
  when :lower36 then 36
  when :upper36 then 36
  when :base64 then 64
  else 0
  end
end

#classification ⇒ Object



69
70
71
72
# File 'lib/spellr/key_tuner/possible_key.rb', line 69

def classification
  key_class = key? ? 'key' : 'not_key'
  "#{key_class}_#{character_set}"
end

#digit_chunks ⇒ Object



135
136
137
# File 'lib/spellr/key_tuner/possible_key.rb', line 135

def digit_chunks
  @digit_chunks ||= string.scan(/\d+/)
end

#features ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/MethodLength



33
34
35
36
37
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
63
# File 'lib/spellr/key_tuner/possible_key.rb', line 33

def features # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  {
    **letter_frequency_difference_features,
    equal: letter_count[:'='],
    length: length,
    hex: character_set == :hex ? 1 : 0,
    lower36: character_set == :lower36 ? 1 : 0,
    upper36: character_set == :upper36 ? 1 : 0,
    base64: character_set == :base64 ? 1 : 0,
    mean_title_chunk_size: mean(title_chunks, &:length),
    variance_title_chunk_size: variance(title_chunks, &:length),
    max_title_chunk_size: max(title_chunks, &:length),
    mean_lower_chunk_size: mean(lower_chunks, &:length),
    variance_lower_chunk_size: variance(lower_chunks, &:length),
    mean_upper_chunk_size: mean(upper_chunks, &:length),
    variance_upper_chunk_size: variance(upper_chunks, &:length),
    mean_alpha_chunk_size: mean(alpha_chunks, &:length),
    variance_alpha_chunk_size: variance(alpha_chunks, &:length),
    mean_alnum_chunk_size: mean(alnum_chunks, &:length),
    variance_alnum_chunk_size: variance(alnum_chunks, &:length),
    mean_digit_chunk_size: mean(digit_chunks, &:length),
    variance_digit_chunk_size: variance(digit_chunks, &:length),
    vowel_consonant_ratio: vowel_consonant_ratio,
    alpha_chunks: alpha_chunks.length,
    alnum_chunks: alnum_chunks.length,
    digit_chunks: digit_chunks.length,
    title_chunks: title_chunks.length,
    mean_letter_frequency_difference: mean(letter_frequency_difference.values),
    variance_letter_frequency_difference: max(letter_frequency_difference.values)
  }
end

#ideal_letter_frequency ⇒ Object



101
102
103
# File 'lib/spellr/key_tuner/possible_key.rb', line 101

def ideal_letter_frequency
  1.0 / character_set_total * length
end

#key? ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/spellr/key_tuner/possible_key.rb', line 65

def key?
  @key
end

#length ⇒ Object



74
75
76
# File 'lib/spellr/key_tuner/possible_key.rb', line 74

def length
  string.length
end

#letter_count ⇒ Object



105
106
107
108
109
110
111
# File 'lib/spellr/key_tuner/possible_key.rb', line 105

def letter_count
  @letter_count ||= begin
    string.chars.each_with_object(LETTER_COUNT_HASH.dup) do |letter, hash|
      hash[letter.to_sym] += 1
    end
  end
end

#letter_frequency ⇒ Object



113
114
115
116
117
118
119
# File 'lib/spellr/key_tuner/possible_key.rb', line 113

def letter_frequency
  @letter_frequency ||= begin
    l = letter_count.dup
    l.each { |k, v| l[k] = v.to_f / string.length }
    l
  end
end

#letter_frequency_difference ⇒ Object



121
122
123
124
125
126
127
# File 'lib/spellr/key_tuner/possible_key.rb', line 121

def letter_frequency_difference
  @letter_frequency_difference ||= begin
    l = letter_frequency.dup
    l.each { |k, v| l[k] = (v - ideal_letter_frequency).abs }
    l
  end
end

#letter_frequency_difference_features ⇒ Object



78
79
80
# File 'lib/spellr/key_tuner/possible_key.rb', line 78

def letter_frequency_difference_features
  letter_frequency_difference.slice(*FEATURE_LETTERS)
end

#lower_chunks ⇒ Object



143
144
145
# File 'lib/spellr/key_tuner/possible_key.rb', line 143

def lower_chunks
  @lower_chunks ||= string.scan(/[a-z]+/)
end

#title_chunks ⇒ Object



139
140
141
# File 'lib/spellr/key_tuner/possible_key.rb', line 139

def title_chunks
  @title_chunks ||= string.scan(/[A-Z][a-z]+/)
end

#upper_chunks ⇒ Object



147
148
149
# File 'lib/spellr/key_tuner/possible_key.rb', line 147

def upper_chunks
  @upper_chunks ||= string.scan(/[A-Z]+/)
end

#vowel_consonant_ratio ⇒ Object



129
130
131
132
133
# File 'lib/spellr/key_tuner/possible_key.rb', line 129

def vowel_consonant_ratio
  vowels = letter_count.fetch_values(*VOWELS).sum
  consonants = letter_count.fetch_values(*CONSONANTS).sum
  vowels / (consonants.nonzero? || 1)
end