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

#stringObject (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_chunksObject



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_chunksObject



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_setObject



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_totalObject

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

#classificationObject



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_chunksObject



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

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

#featuresObject

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_frequencyObject



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

#lengthObject



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

def length
  string.length
end

#letter_countObject



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_frequencyObject



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_differenceObject



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_featuresObject



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_chunksObject



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

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

#title_chunksObject



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_chunksObject



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_ratioObject



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