 
 module.exports = (robot) ->
 
+  # Configure redis the same way that redis-brain does.
   info = Url.parse process.env.REDISTOGO_URL or
     process.env.REDISCLOUD_URL or
     process.env.BOXEN_REDIS_URL or

  client = Redis.createClient(info.port, info.hostname)
  storage = new RedisMarkovStorage(client)

  ply = process.env.HUBOT_MARKOV_PLY or 1
  max = process.env.HUBOT_MARKOV_MAX or 50


# Author:
#   smashwilson

Url = require 'url'
Redis = require 'redis'

# A markov model backed by a configurably storage engine that can both learn and
# generate random text.
class MarkovModel

  # Chain termination marker; chosen because _words will never contain whitespace.
  sentinel = ' '

  # Build a new model with the provided storage backend and order. A markov model's
  # order is the number of prior states that will be examined to determine the
  # probabilities of the next state.
  constructor: (@storage, @ply) ->

  # Split a line of text into whitespace-separated, nonempty words.
  _words: (phrase) ->
    (word for word in phrase.split /\s+/ when word.length > 0)

  # Generate a uniformly distributed random number between 0 and max, inclusive.
  _random: (max) ->
    Math.floor(Math.random() * (max + 1))

  # Given an object with possible choices as keys and relative frequencies as values,
  # choose a key with probability proportional to its frequency.
  _chooseWeighted: (choices) ->
    return sentinel unless choices

    # Sum the frequencies of the available choices and choose a value within that
    # range.
    total = 0
    total += parseInt(freq) for key, freq of choices
    chosen = @._random(total)

    # Accumulate frequencies as you iterate through the choices. Select the key that
    # contains the "chunk" including the chosen value.
    acc = 0
    for key, freq of choices
      acc += parseInt(freq)
      return key if chosen <= acc

    # If we get here, "chosen" was greater than total.
    throw "Bad choice: #{chosen} from #{total}"

  # Generate each state transition of order @ply among the words of "phrase". For
  # example, with @ply 2 and a phrase "a b c d", this would generate:
  #
  # { from: [null, null] to: 'a' }
  # { from: [null, 'a'] to: 'b' }
  # { from: ['a', 'b'], to: 'c' }
  # { from: ['b', 'c'], to: 'd' }
  # { from: ['c', 'd'], to: ' ' }
  _transitions: (phrase) ->
    words = @._words(phrase)
    words.unshift null for i in [1..@ply]
