class Plasper::Plasper

Constants

SENTENCE_DELIMITER

Attributes

weights[R]

Public Class Methods

new() click to toggle source

Prepares selectors and weights storage

# File lib/Plasper/plasper.rb, line 11
def initialize
  @weights = { count: {}, first: {}, next: {}, last: {} }
end

Public Instance Methods

<<(input) click to toggle source

Analyze input and add appropriate part

Determines if input is word, sentence or passage and adds it

@param [String] input

# File lib/Plasper/plasper.rb, line 20
def <<(input)
  if input.index(/\s+/).nil?
    word      = normalize_word input
    self.word = word unless word == ''
  elsif input.scan(SENTENCE_DELIMITER).length < 2
    self.sentence = input.gsub(SENTENCE_DELIMITER, '')
  else
    self.passage = input
  end
end
add_weight(type, group, item, weight = 1) click to toggle source

Add weight

Used for adding weights for counters, first, next and last letter. Valid types are :count, :first, :next and :last (@see initialize) Group is either symbol (e.g. :letters, :words, :sentences, :letter), or string representing letter Item is integer (letter, word and sentence count) or string representing letter Weight is used for weighted-select in generation methods

@param [Symbol] type @param [Symbol|String] group @param [String|Integer] item @param [Integer] weight

# File lib/Plasper/plasper.rb, line 110
def add_weight(type, group, item, weight = 1)
  @weights[type][group] ||= Hash.new(0)

  @weights[type][group][item] += Integer weight
end
passage() click to toggle source

Generate passage

@return [String]

# File lib/Plasper/plasper.rb, line 94
def passage
  sentence_count.times.map { sentence }.join('. ') + '.'
end
passage=(passage) click to toggle source

Analyze passage

Splits passage with sentence-ending punctuation, adds sentence count weight and analyzes each sentence

@param [String] passage

# File lib/Plasper/plasper.rb, line 85
def passage=(passage)
  sentences = passage.split(SENTENCE_DELIMITER).select { |sentence| sentence.chomp != '' }
  sentences.each { |sentence| self.sentence = sentence }
  add_weight :count, :sentence, sentences.count
end
sentence() click to toggle source

Generate sentence

@return [String]

# File lib/Plasper/plasper.rb, line 74
def sentence
  string    = word_count.times.map { word }.join(' ')
  string[0] = Unicode.upcase(string[0]) unless string.to_s == ''
  string
end
sentence=(sentence) click to toggle source

Analyze sentence

Splits sentence with whitespace delimiter, adds weight for word count and analyzes each word

@param [String] sentence

# File lib/Plasper/plasper.rb, line 62
def sentence=(sentence)
  words = sentence.split(/\s+/)
  add_weight :count, :word, words.length unless words.length < 1
  words.each do |word|
    normalized_word = normalize_word word
    self.word       = normalized_word unless normalized_word == ''
  end
end
word() click to toggle source

Generate word

@return [String]

# File lib/Plasper/plasper.rb, line 46
def word
  letter_count = weighted(:count, :letter).to_i
  if letter_count == 1
    last_letter! nil
  elsif letter_count > 0
    result = first_letter
    (letter_count - 2).times { result += next_letter!(result[-1]) }
    result + last_letter!(result[-1])
  end
end
word=(word) click to toggle source

Analyze word

Adds weights for first, next and last letters and letter count

@param [String] word

# File lib/Plasper/plasper.rb, line 36
def word=(word)
  add_weight :count, :letter, word.length
  add_weight :first, :letter, word[0]
  (word.length - 1).times { |l| add_weight :next, word[l], word[l.succ] }
  add_weight :last, word[-2], word[-1]
end

Private Instance Methods

first_letter() click to toggle source

Generate first letter

@return [String]

# File lib/Plasper/plasper.rb, line 139
def first_letter
  weighted :first, :letter
end
last_letter(penultimate_letter) click to toggle source

Generate last letter after penultimate letter

@param [String] penultimate_letter @return [String]

# File lib/Plasper/plasper.rb, line 166
def last_letter(penultimate_letter)
  weighted :last, penultimate_letter
end
last_letter!(penultimate_letter) click to toggle source

Generate last letter with fallback to next_letter!

If there are no weights for last letter after given one, try to fall back to next_letter

@param [String] penultimate_letter @return [String]

# File lib/Plasper/plasper.rb, line 176
def last_letter!(penultimate_letter)
  last_letter(penultimate_letter) || next_letter!(penultimate_letter)
end
next_letter(current_letter) click to toggle source

Generate next letter for current one

@param [String] current_letter @return [String]

# File lib/Plasper/plasper.rb, line 147
def next_letter(current_letter)
  weighted :next, current_letter
end
next_letter!(current_letter) click to toggle source

Generate next letter with fallback

If there are no weights with next letters for current_letter, try to generate another first letter instead and use it

@param [String] current_letter @return [String]

# File lib/Plasper/plasper.rb, line 158
def next_letter!(current_letter)
  next_letter(current_letter) || first_letter.to_s
end
normalize_word(word) click to toggle source
# File lib/Plasper/plasper.rb, line 118
def normalize_word(word)
  Unicode.downcase word.gsub(/[^[:word:]'-]/u, '')
end
sentence_count() click to toggle source

Weighted-randomly select sentence count

Used when generating passage

@return [Integer]

# File lib/Plasper/plasper.rb, line 194
def sentence_count
  weighted(:count, :sentence).to_i
end
weighted(type, group) click to toggle source

Generate weighted-random value

Type is :count, :first, :next or :last Group is symbol (for member count or first letter) or string representing letter

@param [Symbol] type @param [Symbol|String] group

# File lib/Plasper/plasper.rb, line 129
def weighted(type, group)
  if @weights[type].has_key?(group)
    selector = WeightedSelect::Selector.new @weights[type][group]
    selector.select
  end
end
word_count() click to toggle source

Weighted-randomly select word count

Used when generating sentence

@return [Integer]

# File lib/Plasper/plasper.rb, line 185
def word_count
  weighted(:count, :word).to_i
end