Class: MarkovNameGen

Inherits:
Object
  • Object
show all
Defined in:
lib/markov_namegen/markov_namegen.rb

Overview

Builds a new name by constructing a MarkovDict from an array of namees. New instances take 2 parameters:

names(array): list of source names
chainlength(num 1-10): determines order of markov chain, defaulted to 2 for best mix of
  readability and uniqueness. Note: with a small source list, values of 3 or higher
  return names too similar to input

To generate a name after creating an instance of MarkovNameGen, call #new_name/1 #new_name(unique:) takes a single boolean parameter, defaulted to true.

if true: only output names that are not in the original list
if false: will output names even if they match names in original list

Constant Summary collapse

CHAIN_ERROR =
'Chain length must be between 1 and 10.'.freeze
DATA_ERROR =
'Invalid name data.'.freeze
REC_ERROR =
'Name list too small for given chainlength!'.freeze

Instance Method Summary collapse

Constructor Details

#initialize(names, chainlength = 2) ⇒ MarkovNameGen

Returns a new instance of MarkovNameGen.



35
36
37
38
39
40
# File 'lib/markov_namegen/markov_namegen.rb', line 35

def initialize(names, chainlength = 2)
  @mdict = MarkovDict.new
  @source_names = []
  @chainlen = chainlength
  build_dict(names)
end

Instance Method Details

#add_keys(str, namelen) ⇒ Object



60
61
62
63
# File 'lib/markov_namegen/markov_namegen.rb', line 60

def add_keys(str, namelen)
  0.upto(namelen - 1) { |i| @mdict.add_key(str[i..i + @chainlen - 1], str[i + @chainlen]) }
  @mdict.add_key(str[namelen..namelen + @chainlen - 1], "\n")
end

#add_name_to_dict(name) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/markov_namegen/markov_namegen.rb', line 51

def add_name_to_dict(name)
  name = name.strip
  namelen = name.length
  @source_names.push(name)
  str = ' ' * @chainlen + name

  add_keys(str, namelen)
end

#build_dict(names) ⇒ Object

Raises:



42
43
44
45
46
47
48
49
# File 'lib/markov_namegen/markov_namegen.rb', line 42

def build_dict(names)
  raise CHAIN_ERROR unless @chainlen.between?(1, 10)
  raise DATA_ERROR unless names.instance_of? Array

  names.each do |name|
    add_name_to_dict(name)
  end
end

#build_nameObject



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/markov_namegen/markov_namegen.rb', line 65

def build_name
  prefix = ' ' * @chainlen
  name = ''

  loop do
    suffix = @mdict.fetch_suffix(prefix)
    next if suffix == "\n" && name.length < 2
    break if suffix == "\n" || name.length > 9

    name += suffix
    prefix = prefix[1..] + suffix
  end
  namecase(name)
end

#namecase(string) ⇒ Object



95
96
97
98
99
# File 'lib/markov_namegen/markov_namegen.rb', line 95

def namecase(string)
  string.downcase.split(/(\s)/).map.with_index{ |x, i|
    i.zero? || x.match(/^(?:a|is|of|the|and)$/).nil? ? x.capitalize : x
  }.join
end

#new_name(unique: true, counter: 0) ⇒ Object

Raises:



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/markov_namegen/markov_namegen.rb', line 80

def new_name(unique: true, counter: 0)
  raise REC_ERROR if counter > 500

  name = build_name

  case [unique, @source_names.include?(name)]
  when [true, true] then new_name(counter: counter + 1)
  when [false, true] then name
  else
    add_name_to_dict(name)
    name
  end
end