class RandomWords::Generator

Random character, word, and sentence generator

def bad_length

@!visibility private
Define a bad length for testing purposes
def bad_length
  define_length(:bad_length)
end

def characters(min, max = nil, whole_words: true, whitespace: true, dead_switch: 0)

Returns:
  • (String) - The generated string of random words

Parameters:
  • dead_switch (Integer) -- (Optional) A counter to prevent infinite loops
  • whole_words (Boolean) -- (Optional) Whether to generate whole words or not
  • max (Integer) -- (Optional) The maximum length of the generated string
  • min (Integer) -- The minimum length of the generated string
def characters(min, max = nil, whole_words: true, whitespace: true, dead_switch: 0)
  result = ''
  max ||= min
  raise ArgumentError, 'Infinite loop detected' if dead_switch > 40
  whole_words = false if dead_switch > 15
  space = whitespace ? ' ' : ''
  current_part = 0
  while result.length < max && result.length < min
    word = send(SENTENCE_PARTS[current_part].to_sym)
    word.gsub!(/ +/, '') unless whitespace
    current_part = (current_part + 1) % SENTENCE_PARTS.length
    new_result = "#{result}#{space}#{word}".compress
    if new_result.length > max
      return handle_overflow(OverflowConfig.new(new_result, result, min, max, whole_words, whitespace,
                                                dead_switch))
    end
    return new_result if new_result.length == max
    result = new_result
  end
  result.strip
end

def code_lang

Returns:
  • (Symbol) - A randomly selected code language
def code_lang
  code_langs = %i[python ruby swift javascript css rust go java]
  code_langs[Random.rand(code_langs.count)]
end

def code_snippet(lang = nil)

Returns:
  • (String) - A randomly generated code snippet

Parameters:
  • lang (Symbol) -- The language of the code snippet
def code_snippet(lang = nil)
  code_snippets = {
    python: %(def hello_world():\n    print("Hello, World!")),
    ruby: %(def hello_world\n  puts "Hello, World!"\nend),
    swift: %(func helloWorld() {\n    print("Hello, World!")\n}),
    javascript: %(function helloWorld() {\n    console.log("Hello, World!");\n}),
    css: %(body {\n    background-color: #f0f0f0;\n    font-family: Arial, sans-serif;\n}\nh1 {\n    color: #333;\n}),
    rust: %(fn main() {\n    println!("Hello, World!");\n}),
    go: %(package main\nimport "fmt"\nfunc main() {\n    fmt.Println("Hello, World!")\n}),
    java: %(public class HelloWorld {\n    public static void main(String[] args) {\n        System.out.println("Hello, World!");\n    }\n})
  }
  lang ||= code_lang
  code_snippets[lang.to_sym]
end

def create_dictionary(title)

Returns:
  • (Symbol) - The symbolized name of the dictionary

Parameters:
  • title (String) -- The title of the user dictionary
def create_dictionary(title)
  @config.create_user_dictionary(title)
end

def debug(msg)

Display debug message
def debug(msg)
  return unless @debug
  "%#{msg}%"
end

def define_all_lengths

@!visibility private
define all lengths for testing purposes
def define_all_lengths
  @lengths = {
    short: 20,
    medium: 60,
    long: 100,
    very_long: 300
  }
  res = []
  res << define_length(:short)
  res << define_length(:medium)
  res << define_length(:long)
  res << define_length(:very_long)
  res
end

def define_length(length)

Returns:
  • (Integer) - The corresponding length value

Parameters:
  • length (Symbol) -- The length symbol (:short, :medium, :long, or :very_long)
def define_length(length)
  case length
  when :short
    @lengths[:short] || 60
  when :medium
    @lengths[:medium] || 200
  when :long
    @lengths[:long] || 300
  when :very_long
    @lengths[:very_long] || 500
  else
    raise ArgumentError, "Invalid length: #{length}. Use :short, :medium, or :long."
  end
end

def generate_additional_clauses

Simplified generate_additional_clauses
def generate_additional_clauses
  Array.new(rand(1..2)) { random_clause }
end

def generate_combined_sentence(length = nil)

Returns:
  • (String) - A randomly generated sentence

Parameters:
  • length (Symbol) -- The desired length of the sentence, :short, :medium, :long, or :very_long
def generate_combined_sentence(length = nil)
  length ||= define_length(@sentence_length)
  sentence = generate_sentence
  return sentence.to_sent(random_terminator).fix_caps(terminators).expand_debug if sentence.length > length
  while sentence.length < length
    # Generate a random number of sentences to combine
    new_sentence = generate_sentence(length / 2)
    # Combine the sentences with random conjunctions
    sentence = "#{sentence.strip.no_term(terminators)}, #{random_coordinating_conjunction} #{new_sentence.no_term(terminators)}"
  end
  sentence.to_sent(random_terminator).fix_caps(terminators).expand_debug
end

def generate_main_clause

Returns:
  • (String) - A randomly generated main clause
def generate_main_clause
  beginning = case rand(10)
              when 0..1
                random_phrase
              when 2..3
                "#{random_number_with_plural} #{random_adverb} #{random_plural_verb}"
              when 4..5
                random_name
              when 6..7
                noun = random_noun
                "#{random_adverb}, #{random_article_for_word(noun)} #{noun} #{random_verb}"
              else
                noun = random_noun
                adjective = random_adjective
                "#{random_article_for_word(adjective)} #{adjective} #{noun} #{random_adverb} #{random_verb}"
              end
  tail = roll(50) ? " #{random_prepositional_phrase}" : ''
  separator = random_separator
  tail += roll(10) ? "#{separator} #{random_clause}" : ''
  "#{beginning.strip.sub(/[#{Regexp.escape(separator)}]*$/, separator)}#{tail}"
end

def generate_sentence(length = nil)

Returns:
  • (String) - A randomly generated sentence

Parameters:
  • length (Integer) -- The desired length of the sentence
def generate_sentence(length = nil)
  length ||= define_length(@sentence_length)
  sentence_components = []
  # Randomly decide if we include a plural noun with a number
  # sentence_components << random_number_with_plural if roll(10) # 10% chance to include a plural noun
  # Construct main clause
  sentence_components << generate_main_clause
  # Include any additional clauses
  # sentence_components.concat(generate_additional_clauses)
  while sentence_components.join(' ').strip.length < length
    # Randomly include a subordinate conjunction
    additional_clauses = generate_additional_clauses
    sentence_components.concat(additional_clauses)
    sentence_components.map!(&:strip)
    # break if sentence_components.join(' ').length >= length
    # conjunction = if roll(50) || (RandomWords.testing && !RandomWords.tested.include?('subordinate_conjunction'))
    #                 RandomWords.tested << 'subordinate_conjunction' if RandomWords.testing
    #                 random_subordinate_conjunction.strip
    #               else
    #                 RandomWords.tested << 'coordinating_conjunction' if RandomWords.testing
    #                 random_coordinating_conjunction.strip
    #               end
    # # sentence_components.unshift(conjunction.capitalize) # Place conjunction at the start
    # sentence_components << conjunction unless conjunction.empty?
  end
  # Join all parts into a single sentence
  output = sentence_components.shift
  sentence_components.each do |part|
    output << " #{roll(50) ? random_coordinating_conjunction : random_subordinate_conjunction} #{part}"
  end
  output.strip.compress
end

def generate_word

Returns:
  • (String) - A randomly generated word
def generate_word
  send(SENTENCE_PARTS.sample)
end

def handle_overflow(config)

Other tags:
    See: #nouns_of_length -
    See: #words_of_length -
    See: #characters -
    See: OverflowConfig -

Returns:
  • (String) - The modified result after handling overflow

Parameters:
  • config (OverflowConfig) -- The configuration for handling overflow
def handle_overflow(config)
  space = config.whitespace ? ' ' : ''
  needed = config.max - config.result.compress.length
  needed -= space.length if needed > 0 && config.result.compress.length.positive?
  config.min = config.max if config.min > config.max
  if needed > 1
    options = words_of_length(needed)
    return "#{config.result}#{space}#{options.sample}".compress unless options.empty?
  end
  if config.whole_words
    return characters(config.min, config.max, whole_words: config.whole_words, whitespace: config.whitespace,
                                              dead_switch: config.dead_switch + 1)
  end
  truncated = config.new_result.compress[0...config.max]
  truncated.compress.length == config.max ? truncated.compress : nil
end

def html(settings = {})

Returns:
  • (String) - A randomly generated HTML string

Parameters:
  • settings (Hash) -- Settings for generating HTML
def html(settings = {})
  RandomWords::LoremMarkdown.new(settings).output
end

def initialize(source = :english, options = {})

Parameters:
  • options (Hash) -- Options for the generator (e.g., length, paragraph_length)
  • source (Symbol) -- The source of the words (e.g., :english)
def initialize(source = :english, options = {})
  @debug = options[:debug] || false
  @tested = []
  @config = RandomWords::Config.new(source)
  @source = source
  @nouns = @config.dictionary[:nouns]
  @plural_nouns = @config.dictionary[:plural_nouns]
  @verbs = @config.dictionary[:verbs]
  @plural_verbs = @config.dictionary[:plural_verbs]
  @passive_verbs = @config.dictionary[:passive_verbs]
  @adverbs = @config.dictionary[:adverbs]
  @adjectives = @config.dictionary[:adjectives]
  @articles = @config.dictionary[:articles]
  @plural_articles = @config.dictionary[:plural_articles]
  @prepositions = @config.dictionary[:prepositions]
  @clauses = @config.dictionary[:clauses]
  @coordinating_conjunctions = @config.dictionary[:coordinating_conjunctions]
  @subordinate_conjunctions = @config.dictionary[:subordinate_conjunctions]
  @numbers = @config.dictionary[:numbers]
  @sources = @config.sources
  @terminators = @config.dictionary[:terminators]
  @names = [@config.dictionary[:first_names], @config.dictionary[:last_names], @config.dictionary[:full_names]]
  @phrases = @config.dictionary[:phrases]
  @all_words = @config.dictionary[:all_words]
  @options = {
    sentence_length: :medium,
    paragraph_length: 5,
    use_extended_punctuation: false
  }
  @options.merge!(options) if options.is_a?(Hash)
  @sentence_length = @options[:sentence_length]
  @paragraph_length = @options[:paragraph_length]
  @use_extended_punctuation = @options[:use_extended_punctuation]
  @terminators.concat(@config.dictionary[:extended_punctuation]) if @use_extended_punctuation
  lengths
end

def lengths

short: 20, medium: 60, long: 100, very_long: 300
The default lengths are set to the following values:
This method returns the lengths of sentences
Refactored lengths and lengths= methods
def lengths
  @lengths ||= { short: 20, medium: 60, long: 100, very_long: 300 }
end

def lengths=(new_lengths)

Returns:
  • (Hash) - The updated lengths hash

Parameters:
  • new_lengths (Hash) -- A hash containing the new lengths for the sentences
def lengths=(new_lengths)
  @lengths = lengths.merge(new_lengths)
end

def markdown(settings = {})

Returns:
  • (String) - A randomly generated markdown string

Parameters:
  • settings (Hash) -- Settings for generating markdown
def markdown(settings = {})
  input = RandomWords::LoremMarkdown.new(settings).output
  RandomWords::HTML2Markdown.new(input).markdown
end

def name

Returns:
  • (String) - A randomly generated name
def name
  "#{debug('NAM')}#{random_name}"
end

def nouns_of_length(length)

Returns:
  • (Array) - An array of nouns with the specified length

Parameters:
  • length (Integer) -- The desired length of the nouns
def nouns_of_length(length)
  nouns.select { |word| word.length == length }
end

def paragraph(length = @paragraph_length)

Other tags:
    See: #generate_combined_sentence -

Returns:
  • (String) - A randomly generated paragraph

Parameters:
  • length (Integer) -- The desired number of sentences in the paragraph
def paragraph(length = @paragraph_length)
  sentences = []
  length.times do
    sentences << generate_combined_sentence
  end
  sentences.join(' ').strip.compress
end

def paragraph_length=(length)

Parameters:
  • length (Integer) -- The number of sentences in the paragraph
def paragraph_length=(length)
  raise ArgumentError, 'Paragraph length must be a positive integer' unless length.is_a?(Integer) && length.positive?
  @paragraph_length = length
end

def random_adjective

Returns:
  • (String) - A randomly selected adjective
def random_adjective
  "#{debug('ADJ')}#{adjectives.sample}"
end

def random_adverb

Returns:
  • (String) - A randomly selected adverb
def random_adverb
  "#{debug('ADV')}#{adverbs.sample}"
end

def random_article

Returns:
  • (String) - A randomly selected article
def random_article
  "#{debug('ART')}#{articles.rotate[0]}"
end

def random_article_for_word(word)

Returns:
  • (String) - A randomly selected article for the given noun

Parameters:
  • word (String) -- The noun for which to generate an article
def random_article_for_word(word)
  article = plural_nouns.include?(word) ? random_plural_article : random_article
  # puts [word, article].inspect
  article = 'an' if RandomWords.testing && !RandomWords.tested.include?('random_article_for_word')
  RandomWords.tested << 'random_article_for_word' if RandomWords.testing
  if word.start_with?(/[aeiou]/i) && article =~ /^an?$/i
    article = 'an'
  elsif /^an$/i.match?(article)
    article = 'a'
  end
  article
end

def random_clause

Returns:
  • (String) - A randomly selected clause
def random_clause
  "#{debug('CLA')}#{clauses.sample}"
end

def random_conjunction

Returns:
  • (String) - A randomly selected conjunction
def random_conjunction
  "#{debug('COC')}#{coordinating_conjunctions.sample}"
end

def random_coordinating_conjunction

Returns:
  • (String) - A randomly selected coordinating conjunction
def random_coordinating_conjunction
  "#{debug('COC')}#{coordinating_conjunctions.rotate[0]}"
end

def random_name

def random_name
  return @names[2].sample if (@names[0].empty? || @names[1].empty?) && !@names[2].empty?
  return @names[2].sample if !@names[2].empty? && roll(60)
  first_name = @names[0].sample
  middle_initial = roll(20) ? " #{('A'..'Z').to_a.sample}" : ''
  last_name = @names[1].sample
  "#{first_name}#{middle_initial} #{last_name}"
end

def random_noun

Returns:
  • (String) - A randomly selected noun
def random_noun
  "#{debug('NOU')}#{nouns.sample}"
end

def random_number_with_plural

Returns:
  • (String) - A string containing a number and a plural noun
def random_number_with_plural
  num = rand(1000)
  number = if roll(50)
             num.to_word(@numbers)
           else
             num.to_commas
           end
  if num == 1 || (RandomWords.testing && !RandomWords.tested.include?('random_noun'))
    RandomWords.tested << 'random_noun' if RandomWords.testing
    "#{debug('NUM')}#{number} #{random_noun}"
  else
    RandomWords.tested << 'random_plural_noun' if RandomWords.testing
    "#{debug('NUM')}#{number} #{random_plural_noun}"
  end
end

def random_passive_verb

Returns:
  • (String) - A randomly selected passive verb
def random_passive_verb
  "#{debug('PAV')}#{passive_verbs.sample}"
end

def random_phrase

Returns:
  • (String) - A randomly selected phrase
def random_phrase
  "#{debug('PHR')}#{phrases.sample}"
end

def random_plural_article

Returns:
  • (String) - A randomly selected plural article
def random_plural_article
  "#{debug('PLA')}#{plural_articles.rotate[0]}"
end

def random_plural_noun

Returns:
  • (String) - A randomly selected plural noun
def random_plural_noun
  "#{debug('PLN')}#{plural_nouns.sample}"
end

def random_plural_verb

Returns:
  • (String) - A randomly selected plural verb
def random_plural_verb
  "#{debug('PLV')}#{plural_verbs.sample}"
end

def random_preposition

Returns:
  • (String) - A randomly selected preposition
def random_preposition
  "#{debug('PRE')}#{prepositions.rotate[0]}"
end

def random_prepositional_phrase

Returns:
  • (String) - A randomly generated prepositional phrase
def random_prepositional_phrase
  preposition = random_preposition
  phrase = if roll(20) || (@testing && !@tested.include?('random_plural_article'))
             @tested << 'random_plural_article' if @testing
             "#{random_plural_article} #{random_number_with_plural}"
           else
             @tested << 'random_article_for_word' if @testing
             noun = random_noun
             "#{random_article_for_word(noun)} #{noun}"
           end
  "#{debug('PRP')}#{preposition} #{phrase}"
end

def random_separator

Returns:
  • (String) - A randomly selected separator
def random_separator
  "#{debug('SEP')}#{random_separators.sample}"
end

def random_separators

Generate a random set of separators
def random_separators
  [',', ',', ',', ';', ':', ' —']
end

def random_subordinate_conjunction

Returns:
  • (String) - A randomly selected subordinate conjunction
def random_subordinate_conjunction
  "#{debug('SUC')}#{subordinate_conjunctions.rotate[0]}"
end

def random_terminator

Returns:
  • (Array) - A randomly selected terminator pair
def random_terminator
  terminators.sample
end

def random_verb

Returns:
  • (String) - A randomly selected verb
def random_verb
  "#{debug('VER')}#{verbs.sample}"
end

def roll(percent)

Returns:
  • (Boolean) - True if the action occurs, false otherwise

Parameters:
  • percent (Integer) -- 1-100 percent chance of the action occurring (1-100)
def roll(percent)
  rand(1..100) <= percent
end

def sentence(length = nil)

Returns:
  • (String) - A randomly generated sentence

Parameters:
  • length (Integer) -- The desired length of the sentence in characters
def sentence(length = nil)
  generate_combined_sentence(length)
end

def sentence_length=(length)

Parameters:
  • length (Symbol) -- :short, :medium, :long, or :very_long
def sentence_length=(length)
  to_set = case length.to_s
           when /^s/
             :short
           when /^m/
             :medium
           when /^l/
             :long
           when /^v/
             :very_long
           else
             raise ArgumentError, "Invalid length: #{length}. Use :short, :medium, :long, or :very_long."
           end
  @sentence_length = to_set
end

def sentences(number)

Returns:
  • (Array) - An array of generated sentences

Parameters:
  • number (Integer) -- The number of sentences to generate
def sentences(number)
  Array.new(number) { generate_combined_sentence }
end

def source=(new_source)

Define a new source dictionary and re-initialize
def source=(new_source)
  initialize(new_source)
end

def test_random

@!visibility private
These methods are used to test the random generation of words and sentences
Test random generators
def test_random
  RandomWords.testing = true
  @debug = true
  @use_extended_punctuation = true
  res = []
  res << random_noun
  res << random_verb
  res << random_adjective
  res << random_adverb
  res << random_article
  res << random_article_for_word('apple')
  res << random_article_for_word('apples')
  res << random_article_for_word('banana')
  res << random_article_for_word('bananas')
  res << random_plural_article
  res << random_clause
  res << random_separator
  res << random_subordinate_conjunction
  res << random_coordinating_conjunction
  res << random_number_with_plural
  res << random_phrase
  res << random_conjunction
  res << random_name
  res << random_passive_verb
  res << random_plural_noun
  res << random_plural_verb
  res << random_preposition
  res << random_prepositional_phrase
  res << random_terminator.join(' ')
  res << generate_additional_clauses.join(' ')
  res << words_of_length(5).join(' ')
  res << nouns_of_length(5).join(' ')
  res
end

def use_extended_punctuation=(use_extended_punctuation)

def use_extended_punctuation=(use_extended_punctuation)
  raise ArgumentError, 'use_extended_punctuation must be a boolean' unless [true, false].include?(use_extended_punctuation)
  @use_extended_punctuation = use_extended_punctuation
  @terminators.concat(@config.dictionary[:extended_punctuation]) if use_extended_punctuation
end

def word

Returns:
  • (String) - A randomly generated word
def word
  generate_word
end

def words(number)

Parameters:
  • number (Integer) -- The number of words to generate
def words(number)
  result = SENTENCE_PARTS.cycle.take(number).map { |part| send(part.to_sym) }.take(number)
  result.map do |word|
    word.split(/ /).last
  end.join(' ').compress
end

def words_of_length(length)

Other tags:
    See: #nouns_of_length -

Returns:
  • (Array) - An array of words with the specified length

Parameters:
  • length (Integer) -- The desired length of the words
def words_of_length(length)
  all_words.select { |word| word.length == length }
end