jQuery(function ($) {
    var csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content');

    $.fn.extend({
        /**
         * Triggers a custom event on an element and returns the event result
         * this is used to get around not being able to ensure callbacks are placed
         * at the end of the chain.
         *
         * TODO: deprecate with jQuery 1.4.2 release, in favor of subscribing to our
         *       own events and placing ourselves at the end of the chain.
         */
        triggerAndReturn: function (name, data) {
            var event = new $.Event(name);
            this.trigger(event, data);

            return event.result !== false;
        },

        /**
         * Handles execution of remote calls firing overridable events along the way
         */
        callRemote: function () {
            var el      = this,
                method  = el.attr('method') || el.attr('data-method') || 'GET',
                url     = el.attr('action') || el.attr('href'),
                dataType  = el.attr('data-type')  || 'script';

            if (url === undefined) {
              throw "No URL specified for remote call (action or href must be present).";
            } else {
                if (el.triggerAndReturn('ajax:before')) {
                    var data = el.is('form') ? el.serializeArray() : [];
                    $.ajax({
                        url: url,
                        data: data,
                        dataType: dataType,
                        type: method.toUpperCase(),
                        beforeSend: function (xhr) {
                            el.trigger('ajax:loading', xhr);
                        },
                        success: function (data, status, xhr) {
                            el.trigger('ajax:success', [data, status, xhr]);
                        },
                        complete: function (xhr) {
                            el.trigger('ajax:complete', xhr);
                        },
                        error: function (xhr, status, error) {
                            el.trigger('ajax:failure', [xhr, status, error]);
                        }
                    });
                }

                el.trigger('ajax:after');
            }
        }
    });

    /**
     *  confirmation handler
     */
    $('a[data-confirm],input[data-confirm]').click(function () {
        var el = $(this);
        if (el.triggerAndReturn('confirm')) {
            if (!confirm(el.attr('data-confirm'))) {
                return false;
            }
        }
    });


    /**
     * remote handlers
     */
    $('form[data-remote]').live('submit', function (e) {
        $(this).callRemote();
        e.preventDefault();
    });

    $('a[data-remote],input[data-remote]').live('click', function (e) {
        $(this).callRemote();
        e.preventDefault();
    });

    $('a[data-method]:not([data-remote])').live('click', function (e){
        var link = $(this),
            href = link.attr('href'),
            method = link.attr('data-method'),
            form = $('<form method="post" action="'+href+'"></form>'),
            metadata_input = '<input name="_method" value="'+method+'" type="hidden" />';

        if (csrf_param != null && csrf_token != null) {
          metadata_input += '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />';
        }

        form.hide()
            .append(metadata_input)
            .appendTo('body');

        e.preventDefault();
        form.submit();
    });

    /**
     * disable-with handlers
     */
    var disable_with_input_selector = 'input[data-disable-with]';
    var disable_with_form_selector = 'form[data-remote]:has(' + disable_with_input_selector + ')';

    $(disable_with_form_selector).live('ajax:before', function () {
        $(this).find(disable_with_input_selector).each(function () {
            var input = $(this);
            input.data('enable-with', input.val())
                 .attr('value', input.attr('data-disable-with'))
                 .attr('disabled', 'disabled');
        });
    });

    $(disable_with_form_selector).live('ajax:complete', function () {
        $(this).find(disable_with_input_selector).each(function () {
            var input = $(this);
            input.removeAttr('disabled')
                 .val(input.data('enable-with'));
        });
    });
});
;
;
/**
Returns a copy of the array without null and undefined values.

<code><pre>
   [null, undefined, 3, 3, undefined, 5].compact()
=> [3, 3, 5]
</pre></code>

@name compact
@methodOf Array#
@type Array
@returns A new array that contains only the non-null values.
*/var __slice = Array.prototype.slice;
Array.prototype.compact = function() {
  return this.select(function(element) {
    return element != null;
  });
};
/**
Creates and returns a copy of the array. The copy contains
the same objects.

<code><pre>
   a = ["a", "b", "c"]
   b = a.copy()

   # their elements are equal
   a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
=> true

   # but they aren't the same object in memory
   a === b
=> false
</pre></code>

@name copy
@methodOf Array#
@type Array
@returns A new array that is a copy of the array
*/
Array.prototype.copy = function() {
  return this.concat();
};
/**
Empties the array of its contents. It is modified in place.

<code><pre>
   fullArray = [1, 2, 3]
   fullArray.clear()
   fullArray
=> []
</pre></code>

@name clear
@methodOf Array#
@type Array
@returns this, now emptied.
*/
Array.prototype.clear = function() {
  this.length = 0;
  return this;
};
/**
Flatten out an array of arrays into a single array of elements.

<code><pre>
   [[1, 2], [3, 4], 5].flatten()
=> [1, 2, 3, 4, 5]

   # won't flatten twice nested arrays. call
   # flatten twice if that is what you want
   [[1, 2], [3, [4, 5]], 6].flatten()
=> [1, 2, 3, [4, 5], 6]
</pre></code>

@name flatten
@methodOf Array#
@type Array
@returns A new array with all the sub-arrays flattened to the top.
*/
Array.prototype.flatten = function() {
  return this.inject([], function(a, b) {
    return a.concat(b);
  });
};
/**
Invoke the named method on each element in the array
and return a new array containing the results of the invocation.

<code><pre>
   [1.1, 2.2, 3.3, 4.4].invoke("floor")
=> [1, 2, 3, 4]

   ['hello', 'world', 'cool!'].invoke('substring', 0, 3)
=> ['hel', 'wor', 'coo']
</pre></code>

@param {String} method The name of the method to invoke.
@param [arg...] Optional arguments to pass to the method being invoked.

@name invoke
@methodOf Array#
@type Array
@returns A new array containing the results of invoking the
named method on each element.
*/
Array.prototype.invoke = function() {
  var args, method;
  method = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  return this.map(function(element) {
    return element[method].apply(element, args);
  });
};
/**
Randomly select an element from the array.

@name rand
@methodOf Array#
@type Object
@returns A random element from an array
*/
Array.prototype.rand = function() {
  return this[rand(this.length)];
};
/**
Remove the first occurrence of the given object from the array if it is
present. The array is modified in place.

<code><pre>
   a = [1, 1, "a", "b"]
   a.remove(1)
=> 1

   a
=> [1, "a", "b"]
</pre></code>

@name remove
@methodOf Array#
@param {Object} object The object to remove from the array if present.
@returns The removed object if present otherwise undefined.
*/
Array.prototype.remove = function(object) {
  var index;
  index = this.indexOf(object);
  if (index >= 0) {
    return this.splice(index, 1)[0];
  } else {
    return;
  }
};
/**
Returns true if the element is present in the array.

<code><pre>
   ["a", "b", "c"].include("c")
=> true

   [40, "a"].include(700)
=> false
</pre></code>

@name include
@methodOf Array#
@param {Object} element The element to check if present.
@returns true if the element is in the array, false otherwise.
@type Boolean
*/
Array.prototype.include = function(element) {
  return this.indexOf(element) !== -1;
};
/**
Call the given iterator once for each element in the array,
passing in the element as the first argument, the index of
the element as the second argument, and <code>this</code> array as the
third argument.

<code><pre>
   word = ""
   indices = []
   ["r", "a", "d"].each (letter, index) ->
     word += letter
     indices.push(index)

=> ["r", "a", "d"]

   word
=> "rad"

   indices
=> [0, 1, 2]
</pre></code>

@name each
@methodOf Array#
@param {Function} iterator Function to be called once for
each element in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@type Array
@returns this to enable method chaining.
*/
Array.prototype.each = function(iterator, context) {
  var element, i, _len;
  if (this.forEach) {
    this.forEach(iterator, context);
  } else {
    for (i = 0, _len = this.length; i < _len; i++) {
      element = this[i];
      iterator.call(context, element, i, this);
    }
  }
  return this;
};
/**
Call the given iterator once for each element in the array,
passing in the element as the first argument, the index of
the element as the second argument, and `this` array as the
third argument.

<code><pre>
   [1, 2, 3].map (number) ->
     number * number

=> [1, 4, 9]
</pre></code>

@name map
@methodOf Array#
@param {Function} iterator Function to be called once for
each element in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.
@type Array
@returns An array of the results of the iterator function
being called on the original array elements.
*/
Array.prototype.map || (Array.prototype.map = function(iterator, context) {
  var element, i, results, _len;
  results = [];
  for (i = 0, _len = this.length; i < _len; i++) {
    element = this[i];
    results.push(iterator.call(context, element, i, this));
  }
  return results;
});
/**
Call the given iterator once for each pair of objects in the array.

<code><pre>
  [1, 2, 3, 4].eachPair (a, b) ->
    # 1, 2
    # 1, 3
    # 1, 4
    # 2, 3
    # 2, 4
    # 3, 4
</pre></code>

@name eachPair
@methodOf Array#
@param {Function} iterator Function to be called once for
each pair of elements in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.
*/
Array.prototype.eachPair = function(iterator, context) {
  var a, b, i, j, length, _results;
  length = this.length;
  i = 0;
  _results = [];
  while (i < length) {
    a = this[i];
    j = i + 1;
    i += 1;
    _results.push((function() {
      var _results2;
      _results2 = [];
      while (j < length) {
        b = this[j];
        j += 1;
        _results2.push(iterator.call(context, a, b));
      }
      return _results2;
    }).call(this));
  }
  return _results;
};
/**
Call the given iterator once for each element in the array,
passing in the element as the first argument and the given object
as the second argument. Additional arguments are passed similar to
<code>each</code>.

@see Array#each

@name eachWithObject
@methodOf Array#

@param {Object} object The object to pass to the iterator on each
visit.
@param {Function} iterator Function to be called once for
each element in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@returns this
@type Array
*/
Array.prototype.eachWithObject = function(object, iterator, context) {
  this.each(function(element, i, self) {
    return iterator.call(context, element, object, i, self);
  });
  return object;
};
/**
Call the given iterator once for each group of elements in the array,
passing in the elements in groups of n. Additional argumens are
passed as in each.

<code><pre>
   results = []
   [1, 2, 3, 4].eachSlice 2, (slice) ->
     results.push(slice)
=> [1, 2, 3, 4]

   results
=> [[1, 2], [3, 4]]
</pre></code>

@see Array#each

@name eachSlice
@methodOf Array#

@param {Number} n The number of elements in each group.
@param {Function} iterator Function to be called once for
each group of elements in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@returns this
@type Array
*/
Array.prototype.eachSlice = function(n, iterator, context) {
  var i, len;
  if (n > 0) {
    len = (this.length / n).floor();
    i = -1;
    while (++i < len) {
      iterator.call(context, this.slice(i * n, (i + 1) * n), i * n, this);
    }
  }
  return this;
};
/**
Returns a new array with the elements all shuffled up.

@name shuffle
@methodOf Array#

@returns A new array that is randomly shuffled.
@type Array
*/
Array.prototype.shuffle = function() {
  var shuffledArray;
  shuffledArray = [];
  this.each(function(element) {
    return shuffledArray.splice(rand(shuffledArray.length + 1), 0, element);
  });
  return shuffledArray;
};
/**
Returns the first element of the array, undefined if the array is empty.

<code><pre>
   ["first", "second", "third"].first()
=> "first"
</pre></code>

@name first
@methodOf Array#

@returns The first element, or undefined if the array is empty.
@type Object
*/
Array.prototype.first = function() {
  return this[0];
};
/**
Returns the last element of the array, undefined if the array is empty.

<code><pre>
   ["first", "second", "third"].last()
=> "third"
</pre></code>

@name last
@methodOf Array#

@returns The last element, or undefined if the array is empty.
@type Object
*/
Array.prototype.last = function() {
  return this[this.length - 1];
};
/**
Returns an object containing the extremes of this array.

<code><pre>
   [-1, 3, 0].extremes()
=> {min: -1, max: 3}
</pre></code>

@name extremes
@methodOf Array#

@param {Function} [fn] An optional funtion used to evaluate
each element to calculate its value for determining extremes.
@returns {min: minElement, max: maxElement}
@type Object
*/
Array.prototype.extremes = function(fn) {
  var max, maxResult, min, minResult;
  fn || (fn = function(n) {
    return n;
  });
  min = max = void 0;
  minResult = maxResult = void 0;
  this.each(function(object) {
    var result;
    result = fn(object);
    if (min != null) {
      if (result < minResult) {
        min = object;
        minResult = result;
      }
    } else {
      min = object;
      minResult = result;
    }
    if (max != null) {
      if (result > maxResult) {
        max = object;
        return maxResult = result;
      }
    } else {
      max = object;
      return maxResult = result;
    }
  });
  return {
    min: min,
    max: max
  };
};
/**
Pretend the array is a circle and grab a new array containing length elements.
If length is not given return the element at start, again assuming the array
is a circle.

<code><pre>
   [1, 2, 3].wrap(-1)
=> 3

   [1, 2, 3].wrap(6)
=> 1

   ["l", "o", "o", "p"].wrap(0, 16)
=> ["l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p"]
</pre></code>

@name wrap
@methodOf Array#

@param {Number} start The index to start wrapping at, or the index of the
sole element to return if no length is given.
@param {Number} [length] Optional length determines how long result
array should be.
@returns The element at start mod array.length, or an array of length elements,
starting from start and wrapping.
@type Object or Array
*/
Array.prototype.wrap = function(start, length) {
  var end, i, result;
  if (length != null) {
    end = start + length;
    i = start;
    result = [];
    while (i++ < end) {
      result.push(this[i.mod(this.length)]);
    }
    return result;
  } else {
    return this[start.mod(this.length)];
  }
};
/**
Partitions the elements into two groups: those for which the iterator returns
true, and those for which it returns false.

@name partition
@methodOf Array#

@param {Function} iterator
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@type Array
@returns An array in the form of [trueCollection, falseCollection]
*/
Array.prototype.partition = function(iterator, context) {
  var falseCollection, trueCollection;
  trueCollection = [];
  falseCollection = [];
  this.each(function(element) {
    if (iterator.call(context, element)) {
      return trueCollection.push(element);
    } else {
      return falseCollection.push(element);
    }
  });
  return [trueCollection, falseCollection];
};
/**
Return the group of elements for which the return value of the iterator is true.

@name select
@methodOf Array#

@param {Function} iterator The iterator receives each element in turn as
the first agument.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@type Array
@returns An array containing the elements for which the iterator returned true.
*/
Array.prototype.select = function(iterator, context) {
  return this.partition(iterator, context)[0];
};
/**
Return the group of elements that are not in the passed in set.

@name without
@methodOf Array#

@param {Array} values List of elements to exclude.

@type Array
@returns An array containing the elements that are not passed in.
*/
Array.prototype.without = function(values) {
  return this.reject(function(element) {
    return values.include(element);
  });
};
/**
Return the group of elements for which the return value of the iterator is false.

@name reject
@methodOf Array#

@param {Function} iterator The iterator receives each element in turn as
the first agument.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.

@type Array
@returns An array containing the elements for which the iterator returned false.
*/
Array.prototype.reject = function(iterator, context) {
  return this.partition(iterator, context)[1];
};
/**
Combines all elements of the array by applying a binary operation.
for each element in the arra the iterator is passed an accumulator
value (memo) and the element.

@name inject
@methodOf Array#

@type Object
@returns The result of a
*/
Array.prototype.inject = function(initial, iterator) {
  this.each(function(element) {
    return initial = iterator(initial, element);
  });
  return initial;
};
/**
Add all the elements in the array.

@name sum
@methodOf Array#

@type Number
@returns The sum of the elements in the array.
*/
Array.prototype.sum = function() {
  return this.inject(0, function(sum, n) {
    return sum + n;
  });
};
/**
Multiply all the elements in the array.

@name product
@methodOf Array#

@type Number
@returns The product of the elements in the array.
*/
Array.prototype.product = function() {
  return this.inject(1, function(product, n) {
    return product * n;
  });
};
Array.prototype.zip = function() {
  var args;
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  return this.map(function(element, index) {
    var output;
    output = args.map(function(arr) {
      return arr[index];
    });
    output.unshift(element);
    return output;
  });
};;
/**
Bindable module
@name Bindable
@module
@constructor
*/var Bindable;
var __slice = Array.prototype.slice;
Bindable = function() {
  var eventCallbacks;
  eventCallbacks = {};
  return {
    /**
    The bind method adds a function as an event listener.

    <code><pre>
    # this will call coolEventHandler after
    # yourObject.trigger "someCustomEvent" is called.
    yourObject.bind "someCustomEvent", coolEventHandler

    #or
    yourObject.bind "anotherCustomEvent", ->
      doSomething()
    </pre></code>

    @name bind
    @methodOf Bindable#

    @param {String} event The event to listen to.
    @param {Function} callback The function to be called when the specified event
    is triggered.
    */
    bind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];
      return eventCallbacks[event].push(callback);
    },
    /**
    The unbind method removes a specific event listener, or all event listeners if
    no specific listener is given.

    <code><pre>
    #  removes the handler coolEventHandler from the event
    # "someCustomEvent" while leaving the other events intact.
    yourObject.unbind "someCustomEvent", coolEventHandler

    # removes all handlers attached to "anotherCustomEvent"
    yourObject.unbind "anotherCustomEvent"
    </pre></code>

    @name unbind
    @methodOf Bindable#

    @param {String} event The event to remove the listener from.
    @param {Function} [callback] The listener to remove.
    */
    unbind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];
      if (callback) {
        return eventCallbacks[event].remove(callback);
      } else {
        return eventCallbacks[event] = [];
      }
    },
    /**
    The trigger method calls all listeners attached to the specified event.

    <code><pre>
    # calls each event handler bound to "someCustomEvent"
    yourObject.trigger "someCustomEvent"
    </pre></code>

    @name trigger
    @methodOf Bindable#

    @param {String} event The event to trigger.
    @param {Array} [parameters] Additional parameters to pass to the event listener.
    */
    trigger: function() {
      var callbacks, event, parameters, self;
      event = arguments[0], parameters = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
      callbacks = eventCallbacks[event];
      if (callbacks && callbacks.length) {
        self = this;
        return callbacks.each(function(callback) {
          return callback.apply(self, parameters);
        });
      }
    }
  };
};
(typeof exports !== "undefined" && exports !== null ? exports : this)["Bindable"] = Bindable;;
var CommandStack;
CommandStack = function() {
  var index, stack;
  stack = [];
  index = 0;
  return {
    execute: function(command) {
      stack[index] = command;
      command.execute();
      return index += 1;
    },
    undo: function() {
      var command;
      if (this.canUndo()) {
        index -= 1;
        command = stack[index];
        command.undo();
        return command;
      }
    },
    redo: function() {
      var command;
      if (this.canRedo()) {
        command = stack[index];
        command.execute();
        index += 1;
        return command;
      }
    },
    canUndo: function() {
      return index > 0;
    },
    canRedo: function() {
      return stack[index] != null;
    }
  };
};;
/**
The Core class is used to add extended functionality to objects without
extending the object class directly. Inherit from Core to gain its utility
methods.

@name Core
@constructor

@param {Object} I Instance variables
*/var Core;
var __slice = Array.prototype.slice;
Core = function(I) {
  var self;
  I || (I = {});
  return self = {
    /**
      External access to instance variables. Use of this property should be avoided
      in general, but can come in handy from time to time.

    <code><pre>
     I = {
       r: 255
       g: 0
       b: 100
     }

     myObject = Core(I)

     # a bad idea most of the time, but it's
     # pretty convenient to have available.
     myObject.I.r
    => 255

     myObject.I.g
    => 0

     myObject.I.b
    => 100
    </pre></code>

      @name I
      @fieldOf Core#
      */
    I: I,
    /**
      Generates a public jQuery style getter / setter method for each
      String argument.

      <code><pre>
      myObject = Core
        r: 255
        g: 0
        b: 100

      myObject.attrAccessor "r", "g", "b"

      myObject.r(254)
      myObject.r()

     => 254
      </pre></code>

      @name attrAccessor
      @methodOf Core#
      */
    attrAccessor: function() {
      var attrNames;
      attrNames = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      return attrNames.each(function(attrName) {
        return self[attrName] = function(newValue) {
          if (newValue != null) {
            I[attrName] = newValue;
            return self;
          } else {
            return I[attrName];
          }
        };
      });
    },
    /**
    Generates a public jQuery style getter method for each String argument.

    <code><pre>
    myObject = Core
      r: 255
      g: 0
      b: 100

    myObject.attrReader "r", "g", "b"

    myObject.r()
     => 255

    myObject.g()
     => 0

    myObject.b()
     => 100
    </pre></code>

    @name attrReader
    @methodOf Core#
    */
    attrReader: function() {
      var attrNames;
      attrNames = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      return attrNames.each(function(attrName) {
        return self[attrName] = function() {
          return I[attrName];
        };
      });
    },
    /**
    Extends this object with methods from the passed in object. `before` and
    `after` are special option names that glue functionality before or after
    existing methods.

    @name extend
    @methodOf Core#
    */
    extend: function(options) {
      var afterMethods, beforeMethods, fn, name;
      afterMethods = options.after;
      beforeMethods = options.before;
      delete options.after;
      delete options.before;
      Object.extend(self, options);
      if (beforeMethods) {
        for (name in beforeMethods) {
          fn = beforeMethods[name];
          self[name] = self[name].withBefore(fn);
        }
      }
      if (afterMethods) {
        for (name in afterMethods) {
          fn = afterMethods[name];
          self[name] = self[name].withAfter(fn);
        }
      }
      return self;
    },
    /**
    Includes a module in this object.

    <code><pre>
    myObject = Core()
    myObject.include(Bindable)

    # now you can bind handlers to functions and
    # y you've hardly written any code
    myObject.bind "someEvent", ->
      alert("wow. that was easy.")
    </pre></code>

    @name include
    @methodOf Core#

    @param {Module} Module the module to include. A module is a constructor
    that takes two parameters, I and self, and returns an object containing the
    public methods to extend the including object with.
    */
    include: function(Module) {
      return self.extend(Module(I, self));
    }
  };
};;
Function.prototype.withBefore = function(interception) {
  var method;
  method = this;
  return function() {
    interception.apply(this, arguments);
    return method.apply(this, arguments);
  };
};
Function.prototype.withAfter = function(interception) {
  var method;
  method = this;
  return function() {
    var result;
    result = method.apply(this, arguments);
    interception.apply(this, arguments);
    return result;
  };
};;
/**
  @name Logging

<code><pre>
  log "Testing123"
  info "Hey, this is happening"
  warn "Be careful, this might be a problem"
  error "Kaboom!"
</pre></code>

  Gives you some convenience methods for outputting data
  while developing.
*/["log", "info", "warn", "error"].each(function(name) {
  if (typeof console !== "undefined") {
    return (typeof exports !== "undefined" && exports !== null ? exports : this)[name] = function(message) {
      if (console[name]) {
        return console[name](message);
      }
    };
  } else {
    return (typeof exports !== "undefined" && exports !== null ? exports : this)[name] = function() {};
  }
});;
/**
* Matrix.js v1.3.0pre
*
* Copyright (c) 2010 STRd6
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Loosely based on flash:
* http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/geom/Matrix.html
*/(function() {
  /**
  <pre>
     _        _
    | a  c tx  |
    | b  d ty  |
    |_0  0  1 _|
  </pre>
  Creates a matrix for 2d affine transformations.

  concat, inverse, rotate, scale and translate return new matrices with the
  transformations applied. The matrix is not modified in place.

  Returns the identity matrix when called with no arguments.

  @name Matrix
  @param {Number} [a]
  @param {Number} [b]
  @param {Number} [c]
  @param {Number} [d]
  @param {Number} [tx]
  @param {Number} [ty]
  @constructor
  */  var Matrix;
  Matrix = function(a, b, c, d, tx, ty) {
    return {
      __proto__: Matrix.prototype,
      /**
      @name a
      @fieldOf Matrix#
      */
      a: a != null ? a : 1,
      /**
      @name b
      @fieldOf Matrix#
      */
      b: b || 0,
      /**
      @name c
      @fieldOf Matrix#
      */
      c: c || 0,
      /**
      @name d
      @fieldOf Matrix#
      */
      d: d != null ? d : 1,
      /**
      @name tx
      @fieldOf Matrix#
      */
      tx: tx || 0,
      /**
      @name ty
      @fieldOf Matrix#
      */
      ty: ty || 0
    };
  };
  Matrix.prototype = {
    /**
      Returns the result of this matrix multiplied by another matrix
      combining the geometric effects of the two. In mathematical terms,
      concatenating two matrixes is the same as combining them using matrix multiplication.
      If this matrix is A and the matrix passed in is B, the resulting matrix is A x B
      http://mathworld.wolfram.com/MatrixMultiplication.html
      @name concat
      @methodOf Matrix#

      @param {Matrix} matrix The matrix to multiply this matrix by.
      @returns The result of the matrix multiplication, a new matrix.
      @type Matrix
      */
    concat: function(matrix) {
      return Matrix(this.a * matrix.a + this.c * matrix.b, this.b * matrix.a + this.d * matrix.b, this.a * matrix.c + this.c * matrix.d, this.b * matrix.c + this.d * matrix.d, this.a * matrix.tx + this.c * matrix.ty + this.tx, this.b * matrix.tx + this.d * matrix.ty + this.ty);
    },
    /**
    Given a point in the pretransform coordinate space, returns the coordinates of
    that point after the transformation occurs. Unlike the standard transformation
    applied using the transformPoint() method, the deltaTransformPoint() method
    does not consider the translation parameters tx and ty.
    @name deltaTransformPoint
    @methodOf Matrix#
    @see #transformPoint

    @return A new point transformed by this matrix ignoring tx and ty.
    @type Point
    */
    deltaTransformPoint: function(point) {
      return Point(this.a * point.x + this.c * point.y, this.b * point.x + this.d * point.y);
    },
    /**
    Returns the inverse of the matrix.
    http://mathworld.wolfram.com/MatrixInverse.html
    @name inverse
    @methodOf Matrix#

    @returns A new matrix that is the inverse of this matrix.
    @type Matrix
    */
    inverse: function() {
      var determinant;
      determinant = this.a * this.d - this.b * this.c;
      return Matrix(this.d / determinant, -this.b / determinant, -this.c / determinant, this.a / determinant, (this.c * this.ty - this.d * this.tx) / determinant, (this.b * this.tx - this.a * this.ty) / determinant);
    },
    /**
    Returns a new matrix that corresponds this matrix multiplied by a
    a rotation matrix.
    @name rotate
    @methodOf Matrix#
    @see Matrix.rotation

    @param {Number} theta Amount to rotate in radians.
    @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
    @returns A new matrix, rotated by the specified amount.
    @type Matrix
    */
    rotate: function(theta, aboutPoint) {
      return this.concat(Matrix.rotation(theta, aboutPoint));
    },
    /**
    Returns a new matrix that corresponds this matrix multiplied by a
    a scaling matrix.
    @name scale
    @methodOf Matrix#
    @see Matrix.scale

    @param {Number} sx
    @param {Number} [sy]
    @param {Point} [aboutPoint] The point that remains fixed during the scaling
    @type Matrix
    */
    scale: function(sx, sy, aboutPoint) {
      return this.concat(Matrix.scale(sx, sy, aboutPoint));
    },
    /**
    Returns the result of applying the geometric transformation represented by the
    Matrix object to the specified point.
    @name transformPoint
    @methodOf Matrix#
    @see #deltaTransformPoint

    @returns A new point with the transformation applied.
    @type Point
    */
    transformPoint: function(point) {
      return Point(this.a * point.x + this.c * point.y + this.tx, this.b * point.x + this.d * point.y + this.ty);
    },
    /**
    Translates the matrix along the x and y axes, as specified by the tx and ty parameters.
    @name translate
    @methodOf Matrix#
    @see Matrix.translation

    @param {Number} tx The translation along the x axis.
    @param {Number} ty The translation along the y axis.
    @returns A new matrix with the translation applied.
    @type Matrix
    */
    translate: function(tx, ty) {
      return this.concat(Matrix.translation(tx, ty));
    }
    /**
    Creates a matrix transformation that corresponds to the given rotation,
    around (0,0) or the specified point.
    @see Matrix#rotate

    @param {Number} theta Rotation in radians.
    @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
    @returns
    @type Matrix
    */
  };
  Matrix.rotate = Matrix.rotation = function(theta, aboutPoint) {
    var rotationMatrix;
    rotationMatrix = Matrix(Math.cos(theta), Math.sin(theta), -Math.sin(theta), Math.cos(theta));
    if (aboutPoint != null) {
      rotationMatrix = Matrix.translation(aboutPoint.x, aboutPoint.y).concat(rotationMatrix).concat(Matrix.translation(-aboutPoint.x, -aboutPoint.y));
    }
    return rotationMatrix;
  };
  /**
  Returns a matrix that corresponds to scaling by factors of sx, sy along
  the x and y axis respectively.
  If only one parameter is given the matrix is scaled uniformly along both axis.
  If the optional aboutPoint parameter is given the scaling takes place
  about the given point.
  @see Matrix#scale

  @param {Number} sx The amount to scale by along the x axis or uniformly if no sy is given.
  @param {Number} [sy] The amount to scale by along the y axis.
  @param {Point} [aboutPoint] The point about which the scaling occurs. Defaults to (0,0).
  @returns A matrix transformation representing scaling by sx and sy.
  @type Matrix
  */
  Matrix.scale = function(sx, sy, aboutPoint) {
    var scaleMatrix;
    sy = sy || sx;
    scaleMatrix = Matrix(sx, 0, 0, sy);
    if (aboutPoint) {
      scaleMatrix = Matrix.translation(aboutPoint.x, aboutPoint.y).concat(scaleMatrix).concat(Matrix.translation(-aboutPoint.x, -aboutPoint.y));
    }
    return scaleMatrix;
  };
  /**
  Returns a matrix that corresponds to a translation of tx, ty.
  @see Matrix#translate

  @param {Number} tx The amount to translate in the x direction.
  @param {Number} ty The amount to translate in the y direction.
  @return A matrix transformation representing a translation by tx and ty.
  @type Matrix
  */
  Matrix.translate = Matrix.translation = function(tx, ty) {
    return Matrix(1, 0, 0, 1, tx, ty);
  };
  /**
  A constant representing the identity matrix.
  @name IDENTITY
  @fieldOf Matrix
  */
  Matrix.IDENTITY = Matrix();
  /**
  A constant representing the horizontal flip transformation matrix.
  @name HORIZONTAL_FLIP
  @fieldOf Matrix
  */
  Matrix.HORIZONTAL_FLIP = Matrix(-1, 0, 0, 1);
  /**
  A constant representing the vertical flip transformation matrix.
  @name VERTICAL_FLIP
  @fieldOf Matrix
  */
  Matrix.VERTICAL_FLIP = Matrix(1, 0, 0, -1);
  if (Object.freeze) {
    Object.freeze(Matrix.IDENTITY);
    Object.freeze(Matrix.HORIZONTAL_FLIP);
    Object.freeze(Matrix.VERTICAL_FLIP);
  }
  return (typeof exports !== "undefined" && exports !== null ? exports : this)["Matrix"] = Matrix;
})();;
/**
Returns the absolute value of this number.

<code><pre>
   (-4).abs()
=> 4
</pre></code>

@name abs
@methodOf Number#

@type Number
@returns The absolute value of the number.
*/Number.prototype.abs = function() {
  return Math.abs(this);
};
/**
Returns the mathematical ceiling of this number.

<code><pre>
   4.9.ceil()
=> 5

   4.2.ceil()
=> 5

   (-1.2).ceil()
=> -1
</pre></code>

@name ceil
@methodOf Number#

@type Number
@returns The number truncated to the nearest integer of greater than or equal value.
*/
Number.prototype.ceil = function() {
  return Math.ceil(this);
};
/**
Returns the mathematical floor of this number.

<code><pre>
   4.9.floor()
=> 4

   4.2.floor()
=> 4

   (-1.2).floor()
=> -2
</pre></code>

@name floor
@methodOf Number#

@type Number
@returns The number truncated to the nearest integer of less than or equal value.
*/
Number.prototype.floor = function() {
  return Math.floor(this);
};
/**
Returns this number rounded to the nearest integer.

<code><pre>
   4.5.round()
=> 5

   4.4.round()
=> 4
</pre></code>

@name round
@methodOf Number#

@type Number
@returns The number rounded to the nearest integer.
*/
Number.prototype.round = function() {
  return Math.round(this);
};
/**
Returns a number whose value is limited to the given range.

<code><pre>
   # limit the output of this computation to between 0 and 255
   (2 * 255).clamp(0, 255)
=> 255
</pre></code>

@name clamp
@methodOf Number#

@param {Number} min The lower boundary of the output range
@param {Number} max The upper boundary of the output range

@type Number
@returns A number in the range [min, max]
*/
Number.prototype.clamp = function(min, max) {
  return Math.min(Math.max(this, min), max);
};
/**
A mod method useful for array wrapping. The range of the function is
constrained to remain in bounds of array indices.

<code><pre>
   (-1).mod(5)
=> 4
</pre></code>

@name mod
@methodOf Number#

@param {Number} base
@type Number
@returns An integer between 0 and (base - 1) if base is positive.
*/
Number.prototype.mod = function(base) {
  var result;
  result = this % base;
  if (result < 0 && base > 0) {
    result += base;
  }
  return result;
};
/**
Get the sign of this number as an integer (1, -1, or 0).

<code><pre>
   (-5).sign()
=> -1

   0.sign()
=> 0

   5.sign()
=> 1
</pre></code>

@name sign
@methodOf Number#

@type Number
@returns The sign of this number, 0 if the number is 0.
*/
Number.prototype.sign = function() {
  if (this > 0) {
    return 1;
  } else if (this < 0) {
    return -1;
  } else {
    return 0;
  }
};
/**
Returns true if this number is even (evenly divisible by 2).

<code><pre>
   2.even()
=> true

   3.even()
=> false

   0.even()
=> true
</pre></code>

@name even
@methodOf Number#

@type Boolean
@returns true if this number is an even integer, false otherwise.
*/
Number.prototype.even = function() {
  return this % 2 === 0;
};
/**
Returns true if this number is odd (has remainder of 1 when divided by 2).

<code><pre>
   2.odd()
=> false

   3.odd()
=> true

   0.odd()
=> false
</pre></code>

@name odd
@methodOf Number#

@type Boolean
@returns true if this number is an odd integer, false otherwise.
*/
Number.prototype.odd = function() {
  if (this > 0) {
    return this % 2 === 1;
  } else {
    return this % 2 === -1;
  }
};
/**
Calls iterator the specified number of times, passing in the number of the
current iteration as a parameter: 0 on first call, 1 on the second call, etc.

<code><pre>
   output = []

   5.times (n) ->
     output.push(n)

   output
=> [0, 1, 2, 3, 4]
</pre></code>

@name times
@methodOf Number#

@param {Function} iterator The iterator takes a single parameter, the number
of the current iteration.
@param {Object} [context] The optional context parameter specifies an object
to treat as <code>this</code> in the iterator block.

@type Number
@returns The number of times the iterator was called.
*/
Number.prototype.times = function(iterator, context) {
  var i;
  i = -1;
  while (++i < this) {
    iterator.call(context, i);
  }
  return i;
};
/**
Returns the the nearest grid resolution less than or equal to the number.

<code><pre>
    7.snap(8)
=> 0

    4.snap(8)
=> 0

   12.snap(8)
=> 8
</pre></code>

@name snap
@methodOf Number#

@param {Number} resolution The grid resolution to snap to.
@type Number
@returns The nearest multiple of resolution lower than the number.
*/
Number.prototype.snap = function(resolution) {
  var n;
  n = this / resolution;
  1 / 1;
  return n.floor() * resolution;
};
/**
In number theory, integer factorization or prime factorization is the
breaking down of a composite number into smaller non-trivial divisors,
which when multiplied together equal the original integer.

Floors the number for purposes of factorization.

<code><pre>
   60.primeFactors()
=> [2, 2, 3, 5]

   37.primeFactors()
=> [37]
</pre></code>

@name primeFactors
@methodOf Number#

@type Array
@returns An array containing the factorization of this number.
*/
Number.prototype.primeFactors = function() {
  var factors, i, iSquared, n;
  factors = [];
  n = Math.floor(this);
  if (n === 0) {
    return;
  }
  if (n < 0) {
    factors.push(-1);
    n /= -1;
  }
  i = 2;
  iSquared = i * i;
  while (iSquared < n) {
    while ((n % i) === 0) {
      factors.push(i);
      n /= i;
    }
    i += 1;
    iSquared = i * i;
  }
  if (n !== 1) {
    factors.push(n);
  }
  return factors;
};
/**
Returns the two character hexidecimal
representation of numbers 0 through 255.

<code><pre>
   255.toColorPart()
=> "ff"

   0.toColorPart()
=> "00"

   200.toColorPart()
=> "c8"
</pre></code>

@name toColorPart
@methodOf Number#

@type String
@returns Hexidecimal representation of the number
*/
Number.prototype.toColorPart = function() {
  var s;
  s = parseInt(this.clamp(0, 255), 10).toString(16);
  if (s.length === 1) {
    s = '0' + s;
  }
  return s;
};
/**
Returns a number that is maxDelta closer to target.

<code><pre>
   255.approach(0, 5)
=> 250

   5.approach(0, 10)
=> 0
</pre></code>

@name approach
@methodOf Number#

@type Number
@returns A number maxDelta toward target
*/
Number.prototype.approach = function(target, maxDelta) {
  return (target - this).clamp(-maxDelta, maxDelta) + this;
};
/**
Returns a number that is closer to the target by the ratio.

<code><pre>
   255.approachByRatio(0, 0.1)
=> 229.5
</pre></code>

@name approachByRatio
@methodOf Number#

@type Number
@returns A number toward target by the ratio
*/
Number.prototype.approachByRatio = function(target, ratio) {
  return this.approach(target, this * ratio);
};
/**
Returns a number that is closer to the target angle by the delta.

<code><pre>
   Math.PI.approachRotation(0, Math.PI/4)
=> 2.356194490192345 # this is (3/4) * Math.PI, which is (1/4) * Math.PI closer to 0 from Math.PI
</pre></code>

@name approachRotation
@methodOf Number#

@type Number
@returns A number toward the target angle by maxDelta
*/
Number.prototype.approachRotation = function(target, maxDelta) {
  while (target > this + Math.PI) {
    target -= Math.TAU;
  }
  while (target < this - Math.PI) {
    target += Math.TAU;
  }
  return (target - this).clamp(-maxDelta, maxDelta) + this;
};
/**
Constrains a rotation to between -PI and PI.

<code><pre>
   (9/4 * Math.PI).constrainRotation()
=> 0.7853981633974483 # this is (1/4) * Math.PI
</pre></code>

@name constrainRotation
@methodOf Number#

@type Number
@returns This number constrained between -PI and PI.
*/
Number.prototype.constrainRotation = function() {
  var target;
  target = this;
  while (target > Math.PI) {
    target -= Math.TAU;
  }
  while (target < -Math.PI) {
    target += Math.TAU;
  }
  return target;
};
/**
The mathematical d operator. Useful for simulating dice rolls.

@name d
@methodOf Number#

@type Number
@returns The sum of rolling <code>this</code> many <code>sides</code>-sided dice
*/
Number.prototype.d = function(sides) {
  var sum;
  sum = 0;
  this.times(function() {
    return sum += rand(sides) + 1;
  });
  return sum;
};
/**
The mathematical circle constant of 1 turn.

@name TAU
@fieldOf Math
*/
Math.TAU = 2 * Math.PI;;
/**
Checks whether an object is an array.

<code><pre>
   Object.isArray([1, 2, 4])
=> true

   Object.isArray({key: "value"})
=> false
</pre></code>

@name isArray
@methodOf Object

@param {Object} object The object to check for array-ness.
@type Boolean
@returns A boolean expressing whether the object is an instance of Array

*/var __slice = Array.prototype.slice;
Object.isArray = function(object) {
  return Object.prototype.toString.call(object) === '[object Array]';
};
/**
Merges properties from objects into target without overiding.
First come, first served.

<code><pre>
   I = {
     a: 1
     b: 2
     c: 3
   }

   Object.reverseMerge I, {
     c: 6
     d: 4
   }

   I

=> {a: 1, b:2, c:3, d: 4}
</pre></code>

@name reverseMerge
@methodOf Object

@param {Object} target The object to merge the properties into.
@type Object
@returns target
*/
Object.reverseMerge = function() {
  var name, object, objects, target, _i, _len;
  target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  for (_i = 0, _len = objects.length; _i < _len; _i++) {
    object = objects[_i];
    for (name in object) {
      if (!target.hasOwnProperty(name)) {
        target[name] = object[name];
      }
    }
  }
  return target;
};
/**
Merges properties from sources into target with overiding.
Last in covers earlier properties.

<code><pre>
   I = {
     a: 1
     b: 2
     c: 3
   }

   Object.extend I, {
     c: 6
     d: 4
   }

   I

=> {a: 1, b:2, c:6, d: 4}
</pre></code>

@name extend
@methodOf Object

@param {Object} target The object to merge the properties into.
@type Object
@returns target
*/
Object.extend = function() {
  var name, source, sources, target, _i, _len;
  target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  for (_i = 0, _len = sources.length; _i < _len; _i++) {
    source = sources[_i];
    for (name in source) {
      target[name] = source[name];
    }
  }
  return target;
};;
(function() {
  /**
  Create a new point with given x and y coordinates. If no arguments are given
  defaults to (0, 0).
  @name Point
  @param {Number} [x]
  @param {Number} [y]
  @constructor ASFsdfASD
  */  var Point;
  Point = function(x, y) {
    return {
      __proto__: Point.prototype,
      /**
      The x coordinate of this point.
      @name x
      @fieldOf Point#
      */
      x: x || 0,
      /**
      The y coordinate of this point.
      @name y
      @fieldOf Point#
      */
      y: y || 0
    };
  };
  Point.prototype = {
    /**
      Creates a copy of this point.

      @name copy
      @methodOf Point#
      @type Point
      @returns A new point with the same x and y value as this point.

      <code><pre>
        point = Point(1, 1)
        pointCopy = point.copy()

        point.equal(pointCopy)
        => true

        point == pointCopy
        => false
      </pre></code>
      */
    copy: function() {
      return Point(this.x, this.y);
    },
    /**
    Adds a point to this one and returns the new point. You may
    also use a two argument call like <code>point.add(x, y)</code>
    to add x and y values without a second point object.
    @name add
    @methodOf Point#

    @param {Point} other The point to add this point to.
    @returns A new point, the sum of both.
    @type Point
    */
    add: function(first, second) {
      return this.copy().add$(first, second);
    },
    add$: function(first, second) {
      if (second != null) {
        this.x += first;
        this.y += second;
      } else {
        this.x += first.x;
        this.y += first.y;
      }
      return this;
    },
    /**
    Subtracts a point to this one and returns the new point.
    @name subtract
    @methodOf Point#

    @param {Point} other The point to subtract from this point.
    @returns A new point, this - other.
    @type Point
    */
    subtract: function(first, second) {
      return this.copy().subtract$(first, second);
    },
    subtract$: function(first, second) {
      if (second != null) {
        this.x -= first;
        this.y -= second;
      } else {
        this.x -= first.x;
        this.y -= first.y;
      }
      return this;
    },
    /**
    Scale this Point (Vector) by a constant amount.
    @name scale
    @methodOf Point#

    @param {Number} scalar The amount to scale this point by.
    @returns A new point, this * scalar.
    @type Point
    */
    scale: function(scalar) {
      return this.copy().scale$(scalar);
    },
    scale$: function(scalar) {
      this.x *= scalar;
      this.y *= scalar;
      return this;
    },
    /**
    The norm of a vector is the unit vector pointing in the same direction. This method
    treats the point as though it is a vector from the origin to (x, y).
    @name norm
    @methodOf Point#

    @returns The unit vector pointing in the same direction as this vector.
    @type Point
    */
    norm: function(length) {
      if (length == null) {
        length = 1.0;
      }
      return this.copy().norm$(length);
    },
    norm$: function(length) {
      var m;
      if (length == null) {
        length = 1.0;
      }
      if (m = this.length()) {
        return this.scale$(length / m);
      } else {
        return this;
      }
    },
    /**
    Floor the x and y values, returning a new point.

    @name floor
    @methodOf Point#
    @returns A new point, with x and y values each floored to the largest previous integer.
    @type Point
    */
    floor: function() {
      return this.copy().floor$();
    },
    floor$: function() {
      this.x = this.x.floor();
      this.y = this.y.floor();
      return this;
    },
    /**
    Determine whether this point is equal to another point.
    @name equal
    @methodOf Point#

    @param {Point} other The point to check for equality.
    @returns true if the other point has the same x, y coordinates, false otherwise.
    @type Boolean
    */
    equal: function(other) {
      return this.x === other.x && this.y === other.y;
    },
    /**
    Computed the length of this point as though it were a vector from (0,0) to (x,y)
    @name length
    @methodOf Point#

    @returns The length of the vector from the origin to this point.
    @type Number
    */
    length: function() {
      return Math.sqrt(this.dot(this));
    },
    /**
    Calculate the magnitude of this Point (Vector).
    @name magnitude
    @methodOf Point#

    @returns The magnitude of this point as if it were a vector from (0, 0) -> (x, y).
    @type Number
    */
    magnitude: function() {
      return this.length();
    },
    /**
    Returns the direction in radians of this point from the origin.
    @name direction
    @methodOf Point#

    @type Number
    */
    direction: function() {
      return Math.atan2(this.y, this.x);
    },
    /**
    Calculate the dot product of this point and another point (Vector).
    @name dot
    @methodOf Point#

    @param {Point} other The point to dot with this point.
    @returns The dot product of this point dot other as a scalar value.
    @type Number
    */
    dot: function(other) {
      return this.x * other.x + this.y * other.y;
    },
    /**
    Calculate the cross product of this point and another point (Vector).
    Usually cross products are thought of as only applying to three dimensional vectors,
    but z can be treated as zero. The result of this method is interpreted as the magnitude
    of the vector result of the cross product between [x1, y1, 0] x [x2, y2, 0]
    perpendicular to the xy plane.
    @name cross
    @methodOf Point#

    @param {Point} other The point to cross with this point.
    @returns The cross product of this point with the other point as scalar value.
    @type Number
    */
    cross: function(other) {
      return this.x * other.y - other.x * this.y;
    },
    /**
    Computed the Euclidean between this point and another point.
    @name distance
    @methodOf Point#

    @param {Point} other The point to compute the distance to.
    @returns The distance between this point and another point.
    @type Number
    */
    distance: function(other) {
      return Point.distance(this, other);
    }
    /**
    @name distance
    @methodOf Point
    @param {Point} p1
    @param {Point} p2
    @type Number
    @returns The Euclidean distance between two points.
    */
  };
  Point.distance = function(p1, p2) {
    return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  };
  /**
  Construct a point on the unit circle for the given angle.

  @name fromAngle
  @methodOf Point

  @param {Number} angle The angle in radians
  @type Point
  @returns The point on the unit circle.
  */
  Point.fromAngle = function(angle) {
    return Point(Math.cos(angle), Math.sin(angle));
  };
  /**
  If you have two dudes, one standing at point p1, and the other
  standing at point p2, then this method will return the direction
  that the dude standing at p1 will need to face to look at p2.

  @name direction
  @methodOf Point

  @param {Point} p1 The starting point.
  @param {Point} p2 The ending point.
  @type Number
  @returns The direction from p1 to p2 in radians.
  */
  Point.direction = function(p1, p2) {
    return Math.atan2(p2.y - p1.y, p2.x - p1.x);
  };
  /**
  @name ZERO
  @fieldOf Point

  @type Point
  */
  Point.ZERO = Point();
  if (Object.freeze) {
    Object.freeze(Point.ZERO);
  }
  return (typeof exports !== "undefined" && exports !== null ? exports : this)["Point"] = Point;
})();;
(function() {
  /**
  @name Random
  @namespace Some useful methods for generating random things.
  */  (typeof exports !== "undefined" && exports !== null ? exports : this)["Random"] = {
    /**
      Returns a random angle, uniformly distributed, between 0 and 2pi.

      @name angle
      @methodOf Random
      @type Number
      */
    angle: function() {
      return rand() * Math.TAU;
    },
    color: function() {
      return Color.random();
    },
    often: function() {
      return rand(3);
    },
    sometimes: function() {
      return !rand(3);
    }
    /**
    Returns random integers from [0, n) if n is given.
    Otherwise returns random float between 0 and 1.

    @name rand
    @methodOf window

    @param {Number} n
    @type Number
    */
  };
  return (typeof exports !== "undefined" && exports !== null ? exports : this)["rand"] = function(n) {
    if (n) {
      return Math.floor(n * Math.random());
    } else {
      return Math.random();
    }
  };
})();;
/**
Returns true if this string only contains whitespace characters.

@name blank
@methodOf String#

@returns Whether or not this string is blank.
@type Boolean
*/String.prototype.blank = function() {
  return /^\s*$/.test(this);
};
/**
Returns a new string that is a camelCase version.

@name camelize
@methodOf String#
*/
String.prototype.camelize = function() {
  return this.trim().replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) {
    if (chr) {
      return chr.toUpperCase();
    } else {
      return '';
    }
  });
};
/**
Returns a new string with the first letter capitalized and the rest lower cased.

@name capitalize
@methodOf String#
*/
String.prototype.capitalize = function() {
  return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
};
/**
Return the class or constant named in this string.

@name constantize
@methodOf String#

@returns The class or constant named in this string.
@type Object
*/
String.prototype.constantize = function() {
  if (this.match(/[A-Z][A-Za-z0-9]*/)) {
    eval("var that = " + this);
    return that;
  } else {
    throw "String#constantize: '" + this + "' is not a valid constant name.";
  }
};
/**
Returns a new string that is a more human readable version.

@name humanize
@methodOf String#
*/
String.prototype.humanize = function() {
  return this.replace(/_id$/, "").replace(/_/g, " ").capitalize();
};
/**
Returns true.

@name isString
@methodOf String#
@type Boolean
@returns true
*/
String.prototype.isString = function() {
  return true;
};
/**
Parse this string as though it is JSON and return the object it represents. If it
is not valid JSON returns the string itself.

@name parse
@methodOf String#

@returns Returns an object from the JSON this string contains. If it
is not valid JSON returns the string itself.
@type Object
*/
String.prototype.parse = function() {
  try {
    return JSON.parse(this.toString());
  } catch (e) {
    return this.toString();
  }
};
/**
Returns a new string in Title Case.
@name titleize
@methodOf String#
*/
String.prototype.titleize = function() {
  return this.split(/[- ]/).map(function(word) {
    return word.capitalize();
  }).join(' ');
};
/**
Underscore a word, changing camelCased with under_scored.
@name underscore
@methodOf String#
*/
String.prototype.underscore = function() {
  return this.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/-/g, '_').toLowerCase();
};
/**
Assumes the string is something like a file name and returns the
contents of the string without the extension.

"neat.png".witouthExtension() => "neat"

@name withoutExtension
@methodOf String#
*/
String.prototype.withoutExtension = function() {
  return this.replace(/\.[^\.]*$/, '');
};;
/**
Non-standard



@name toSource
@methodOf Boolean#
*/
/**
Returns a string representing the specified Boolean object.

<code><em>bool</em>.toString()</code>

@name toString
@methodOf Boolean#
*/
/**
Returns the primitive value of a Boolean object.

<code><em>bool</em>.valueOf()</code>

@name valueOf
@methodOf Boolean#
*/
/**
Returns a string representing the Number object in exponential notation

<code><i>number</i>.toExponential( [<em>fractionDigits</em>] )</code>
@param  fractionDigits
An integer specifying the number of digits after the decimal point. Defaults
to as many digits as necessary to specify the number.
@name toExponential
@methodOf Number#
*/
/**
Formats a number using fixed-point notation

<code><i>number</i>.toFixed( [<em>digits</em>] )</code>
@param  digits   The number of digits to appear after the decimal point; this
may be a value between 0 and 20, inclusive, and implementations may optionally
support a larger range of values. If this argument is omitted, it is treated as
0.
@name toFixed
@methodOf Number#
*/
/**
number.toLocaleString();



@name toLocaleString
@methodOf Number#
*/
/**
Returns a string representing the Number object to the specified precision.

<code><em>number</em>.toPrecision( [ <em>precision</em> ] )</code>
@param precision An integer specifying the number of significant digits.
@name toPrecision
@methodOf Number#
*/
/**
Non-standard



@name toSource
@methodOf Number#
*/
/**
Returns a string representing the specified Number object

<code><i>number</i>.toString( [<em>radix</em>] )</code>
@param  radix
An integer between 2 and 36 specifying the base to use for representing
numeric values.
@name toString
@methodOf Number#
*/
/**
Returns the primitive value of a Number object.



@name valueOf
@methodOf Number#
*/
/**
Returns the specified character from a string.

<code><em>string</em>.charAt(<em>index</em>)</code>
@param index  An integer between 0 and 1 less than the length of the string.
@name charAt
@methodOf String#
*/
/**
Returns the numeric Unicode value of the character at the given index (except
for unicode codepoints > 0x10000).


@param index  An integer greater than 0 and less than the length of the string;
if it is not a number, it defaults to 0.
@name charCodeAt
@methodOf String#
*/
/**
Combines the text of two or more strings and returns a new string.

<code><em>string</em>.concat(<em>string2</em>, <em>string3</em>[, ..., <em>stringN</em>])</code>
@param string2...stringN  Strings to concatenate to this string.
@name concat
@methodOf String#
*/
/**
Returns the index within the calling String object of the first occurrence of
the specified value, starting the search at fromIndex,
returns -1 if the value is not found.

<code><em>string</em>.indexOf(<em>searchValue</em>[, <em>fromIndex</em>]</code>
@param searchValue  A string representing the value to search for.
@param fromIndex  The location within the calling string to start the search
from. It can be any integer between 0 and the length of the string. The default
value is 0.
@name indexOf
@methodOf String#
*/
/**
Returns the index within the calling String object of the last occurrence of the
specified value, or -1 if not found. The calling string is searched backward,
starting at fromIndex.

<code><em>string</em>.lastIndexOf(<em>searchValue</em>[, <em>fromIndex</em>])</code>
@param searchValue  A string representing the value to search for.
@param fromIndex  The location within the calling string to start the search
from, indexed from left to right. It can be any integer between 0 and the length
of the string. The default value is the length of the string.
@name lastIndexOf
@methodOf String#
*/
/**
Returns a number indicating whether a reference string comes before or after or
is the same as the given string in sort order.

<code> localeCompare(compareString) </code>

@name localeCompare
@methodOf String#
*/
/**
Used to retrieve the matches when matching a string against a regular
expression.

<code><em>string</em>.match(<em>regexp</em>)</code>
@param regexp A regular expression object. If a non-RegExp object obj is passed,
it is implicitly converted to a RegExp by using new RegExp(obj).
@name match
@methodOf String#
*/
/**
Non-standard



@name quote
@methodOf String#
*/
/**
Returns a new string with some or all matches of a pattern replaced by a
replacement.  The pattern can be a string or a RegExp, and the replacement can
be a string or a function to be called for each match.

<code><em>str</em>.replace(<em>regexp|substr</em>, <em>newSubStr|function[</em>, </code><code><em>flags]</em>);</code>
@param regexp  A RegExp object. The match is replaced by the return value of
parameter #2.
@param substr  A String that is to be replaced by newSubStr.
@param newSubStr  The String that replaces the substring received from parameter
#1. A number of special replacement patterns are supported; see the "Specifying
a string as a parameter" section below.
@param function  A function to be invoked to create the new substring (to put in
place of the substring received from parameter #1). The arguments supplied to
this function are described in the "Specifying a function as a parameter"
section below.
@param flags gimy

Non-standardThe use of the flags parameter in the String.replace method is
non-standard. For cross-browser compatibility, use a RegExp object with
corresponding flags.A string containing any combination of the RegExp flags: g
global match i ignore case m match over multiple lines y Non-standard
sticky global matchignore casematch over multiple linesNon-standard     sticky
@name replace
@methodOf String#
*/
/**
Executes the search for a match between a regular expression and this String
object.

<code><em>string</em>.search(<em>regexp</em>)</code>
@param regexp  A  regular expression object. If a non-RegExp object obj is
passed, it is implicitly converted to a RegExp by using new RegExp(obj).
@name search
@methodOf String#
*/
/**
Extracts a section of a string and returns a new string.

<code><em>string</em>.slice(<em>beginslice</em>[, <em>endSlice</em>])</code>
@param beginSlice  The zero-based index at which to begin extraction.
@param endSlice  The zero-based index at which to end extraction. If omitted,
slice extracts to the end of the string.
@name slice
@methodOf String#
*/
/**
Splits a String object into an array of strings by separating the string into
substrings.

<code><em>string</em>.split([<em>separator</em>][, <em>limit</em>])</code>
@param separator  Specifies the character to use for separating the string. The
separator is treated as a string or a regular expression. If separator is
omitted, the array returned contains one element consisting of the entire
string.
@param limit  Integer specifying a limit on the number of splits to be found.
@name split
@methodOf String#
*/
/**
Returns the characters in a string beginning at the specified location through
the specified number of characters.

<code><em>string</em>.substr(<em>start</em>[, <em>length</em>])</code>
@param start  Location at which to begin extracting characters.
@param length  The number of characters to extract.
@name substr
@methodOf String#
*/
/**
Returns a subset of a string between one index and another, or through the end
of the string.

<code><em>string</em>.substring(<em>indexA</em>[, <em>indexB</em>])</code>
@param indexA  An integer between 0 and one less than the length of the string.
@param indexB  (optional) An integer between 0 and the length of the string.
@name substring
@methodOf String#
*/
/**
Returns the calling string value converted to lower case, according to any
locale-specific case mappings.

<code> toLocaleLowerCase() </code>

@name toLocaleLowerCase
@methodOf String#
*/
/**
Returns the calling string value converted to upper case, according to any
locale-specific case mappings.

<code> toLocaleUpperCase() </code>

@name toLocaleUpperCase
@methodOf String#
*/
/**
Returns the calling string value converted to lowercase.

<code><em>string</em>.toLowerCase()</code>

@name toLowerCase
@methodOf String#
*/
/**
Non-standard



@name toSource
@methodOf String#
*/
/**
Returns a string representing the specified object.

<code><em>string</em>.toString()</code>

@name toString
@methodOf String#
*/
/**
Returns the calling string value converted to uppercase.

<code><em>string</em>.toUpperCase()</code>

@name toUpperCase
@methodOf String#
*/
/**
Removes whitespace from both ends of the string.

<code><em>string</em>.trim()</code>

@name trim
@methodOf String#
*/
/**
Non-standard



@name trimLeft
@methodOf String#
*/
/**
Non-standard



@name trimRight
@methodOf String#
*/
/**
Returns the primitive value of a String object.

<code><em>string</em>.valueOf()</code>

@name valueOf
@methodOf String#
*/
/**
Non-standard



@name anchor
@methodOf String#
*/
/**
Non-standard



@name big
@methodOf String#
*/
/**
Non-standard

<code>BLINK</code>

@name blink
@methodOf String#
*/
/**
Non-standard



@name bold
@methodOf String#
*/
/**
Non-standard



@name fixed
@methodOf String#
*/
/**
Non-standard

<code>&lt;FONT COLOR="<i>color</i>"&gt;</code>

@name fontcolor
@methodOf String#
*/
/**
Non-standard

<code>&lt;FONT SIZE="<i>size</i>"&gt;</code>

@name fontsize
@methodOf String#
*/
/**
Non-standard



@name italics
@methodOf String#
*/
/**
Non-standard



@name link
@methodOf String#
*/
/**
Non-standard



@name small
@methodOf String#
*/
/**
Non-standard



@name strike
@methodOf String#
*/
/**
Non-standard



@name sub
@methodOf String#
*/
/**
Non-standard



@name sup
@methodOf String#
*/
/**
Removes the last element from an array and returns that element.

<code>
<i>array</i>.pop()
</code>

@name pop
@methodOf Array#
*/
/**
Mutates an array by appending the given elements and returning the new length of
the array.

<code><em>array</em>.push(<em>element1</em>, ..., <em>elementN</em>)</code>
@param element1, ..., elementN The elements to add to the end of the array.
@name push
@methodOf Array#
*/
/**
Reverses an array in place.  The first array element becomes the last and the
last becomes the first.

<code><em>array</em>.reverse()</code>

@name reverse
@methodOf Array#
*/
/**
Removes the first element from an array and returns that element. This method
changes the length of the array.

<code><em>array</em>.shift()</code>

@name shift
@methodOf Array#
*/
/**
Sorts the elements of an array in place.

<code><em>array</em>.sort([<em>compareFunction</em>])</code>
@param compareFunction  Specifies a function that defines the sort order. If
omitted, the array is sorted lexicographically (in dictionary order) according
to the string conversion of each element.
@name sort
@methodOf Array#
*/
/**
Changes the content of an array, adding new elements while removing old
elements.

<code><em>array</em>.splice(<em>index</em>, <em>howMany</em>[, <em>element1</em>[, ...[, <em>elementN</em>]]])</code>
@param index  Index at which to start changing the array. If negative, will
begin that many elements from the end.
@param howMany  An integer indicating the number of old array elements to
remove. If howMany is 0, no elements are removed. In this case, you should
specify at least one new element. If no howMany parameter is specified (second
syntax above, which is a SpiderMonkey extension), all elements after index are
removed.
@param element1, ..., elementN  The elements to add to the array. If you don't
specify any elements, splice simply removes elements from the array.
@name splice
@methodOf Array#
*/
/**
Adds one or more elements to the beginning of an array and returns the new
length of the array.

<code><em>arrayName</em>.unshift(<em>element1</em>, ..., <em>elementN</em>) </code>
@param element1, ..., elementN The elements to add to the front of the array.
@name unshift
@methodOf Array#
*/
/**
Returns a new array comprised of this array joined with other array(s) and/or
value(s).

<code><em>array</em>.concat(<em>value1</em>, <em>value2</em>, ..., <em>valueN</em>)</code>
@param valueN  Arrays and/or values to concatenate to the resulting array.
@name concat
@methodOf Array#
*/
/**
Joins all elements of an array into a string.

<code><em>array</em>.join(<em>separator</em>)</code>
@param separator  Specifies a string to separate each element of the array. The
separator is converted to a string if necessary. If omitted, the array elements
are separated with a comma.
@name join
@methodOf Array#
*/
/**
Returns a one-level deep copy of a portion of an array.

<code><em>array</em>.slice(<em>begin</em>[, <em>end</em>])</code>
@param begin  Zero-based index at which to begin extraction.As a negative index,
start indicates an offset from the end of the sequence. slice(-2) extracts the
second-to-last element and the last element in the sequence.
@param end  Zero-based index at which to end extraction. slice extracts up to
but not including end.slice(1,4) extracts the second element through the fourth
element (elements indexed 1, 2, and 3).As a negative index, end indicates an
offset from the end of the sequence. slice(2,-1) extracts the third element
through the second-to-last element in the sequence.If end is omitted, slice
extracts to the end of the sequence.
@name slice
@methodOf Array#
*/
/**
Non-standard



@name toSource
@methodOf Array#
*/
/**
Returns a string representing the specified array and its elements.

<code><em>array</em>.toString()</code>

@name toString
@methodOf Array#
*/
/**
Returns the first index at which a given element can be found in the array, or
-1 if it is not present.

<code><em>array</em>.indexOf(<em>searchElement</em>[, <em>fromIndex</em>])</code>
@param searchElement fromIndex  Element to locate in the array.The index at
which to begin the search. Defaults to 0, i.e. the whole array will be searched.
If the index is greater than or equal to the length of the array, -1 is
returned, i.e. the array will not be searched. If negative, it is taken as the
offset from the end of the array. Note that even when the index is negative, the
array is still searched from front to back. If the calculated index is less than
0, the whole array will be searched.
@name indexOf
@methodOf Array#
*/
/**
Returns the last index at which a given element can be found in the array, or -1
if it is not present. The array is searched backwards, starting at fromIndex.

<code><em>array</em>.lastIndexOf(<em>searchElement</em>[, <em>fromIndex</em>])</code>
@param searchElement fromIndex  Element to locate in the array.The index at
which to start searching backwards. Defaults to the array's length, i.e. the
whole array will be searched. If the index is greater than or equal to the
length of the array, the whole array will be searched. If negative, it is taken
as the offset from the end of the array. Note that even when the index is
negative, the array is still searched from back to front. If the calculated
index is less than 0, -1 is returned, i.e. the array will not be searched.
@name lastIndexOf
@methodOf Array#
*/
/**
Creates a new array with all elements that pass the test implemented by the
provided function.

<code><em>array</em>.filter(<em>callback</em>[, <em>thisObject</em>])</code>
@param callback thisObject  Function to test each element of the array.Object to
use as this when executing callback.
@name filter
@methodOf Array#
*/
/**
Executes a provided function once per array element.

<code><em>array</em>.forEach(<em>callback</em>[, <em>thisObject</em>])</code>
@param callback thisObject  Function to execute for each element.Object to use
as this when executing callback.
@name forEach
@methodOf Array#
*/
/**
Tests whether all elements in the array pass the test implemented by the
provided function.

<code><em>array</em>.every(<em>callback</em>[, <em>thisObject</em>])</code>
@param callbackthisObject Function to test for each element.Object to use as
this when executing callback.
@name every
@methodOf Array#
*/
/**
Creates a new array with the results of calling a provided function on every
element in this array.

<code><em>array</em>.map(<em>callback</em>[, <em>thisObject</em>])</code>
@param callbackthisObject Function that produces an element of the new Array
from an element of the current one.Object to use as this when executing
callback.
@name map
@methodOf Array#
*/
/**
Tests whether some element in the array passes the test implemented by the
provided function.

<code><em>array</em>.some(<em>callback</em>[, <em>thisObject</em>])</code>
@param callback thisObject  Function to test for each element.Object to use as
this when executing callback.
@name some
@methodOf Array#
*/
/**
Apply a function against an accumulator and each value of the array (from
left-to-right) as to reduce it to a single value.

<code><em>array</em>.reduce(<em>callback</em>[, <em>initialValue</em>])</code>
@param callbackinitialValue Function to execute on each value in the
array.Object to use as the first argument to the first call of the callback.
@name reduce
@methodOf Array#
*/
/**
Apply a function simultaneously against two values of the array (from
right-to-left) as to reduce it to a single value.

<code><em>array</em>.reduceRight(<em>callback</em>[, <em>initialValue</em>])</code>
@param callback initialValue  Function to execute on each value in the
array.Object to use as the first argument to the first call of the callback.
@name reduceRight
@methodOf Array#
*/
/**
Returns a boolean indicating whether the object has the specified property.

<code><em>obj</em>.hasOwnProperty(<em>prop</em>)</code>
@param prop The name of the property to test.
@name hasOwnProperty
@methodOf Object#
*/
/**
Calls a function with a given this value and arguments provided as an array.

<code><em>fun</em>.apply(<em>thisArg</em>[, <em>argsArray</em>])</code>
@param thisArg  Determines the value of this inside fun. If thisArg is null or
undefined, this will be the global object. Otherwise, this will be equal to
Object(thisArg) (which is thisArg if thisArg is already an object, or a String,
Boolean, or Number if thisArg is a primitive value of the corresponding type).
Therefore, it is always true that typeof this == "object" when the function
executes.
@param argsArray  An argument array for the object, specifying the arguments
with which fun should be called, or null or undefined if no arguments should be
provided to the function.
@name apply
@methodOf Function#
*/
/**
Creates a new function that, when called, itself calls this function in the
context of the provided this value, with a given sequence of arguments preceding
any provided when the new function was called.

<code><em>fun</em>.bind(<em>thisArg</em>[, <em>arg1</em>[, <em>arg2</em>[, ...]]])</code>
@param thisValuearg1, arg2, ... The value to be passed as the this parameter to
the target function when the bound function is called.  The value is ignored if
the bound function is constructed using the new operator.Arguments to prepend to
arguments provided to the bound function when invoking the target function.
@name bind
@methodOf Function#
*/
/**
Calls a function with a given this value and arguments provided individually.

<code><em>fun</em>.call(<em>thisArg</em>[, <em>arg1</em>[, <em>arg2</em>[, ...]]])</code>
@param thisArg  Determines the value of this inside fun. If thisArg is null or
undefined, this will be the global object. Otherwise, this will be equal to
Object(thisArg) (which is thisArg if thisArg is already an object, or a String,
Boolean, or Number if thisArg is a primitive value of the corresponding type).
Therefore, it is always true that typeof this == "object" when the function
executes.
@param arg1, arg2, ...  Arguments for the object.
@name call
@methodOf Function#
*/
/**
Non-standard



@name toSource
@methodOf Function#
*/
/**
Returns a string representing the source code of the function.

<code><em>function</em>.toString(<em>indentation</em>)</code>
@param indentation Non-standard     The amount of spaces to indent the string
representation of the source code. If indentation is less than or equal to -1,
most unnecessary spaces are removed.
@name toString
@methodOf Function#
*/
/**
Executes a search for a match in a specified string. Returns a result array, or
null.


@param regexp  The name of the regular expression. It can be a variable name or
a literal.
@param str  The string against which to match the regular expression.
@name exec
@methodOf RegExp#
*/
/**
Executes the search for a match between a regular expression and a specified
string. Returns true or false.

<code> <em>regexp</em>.test([<em>str</em>]) </code>
@param regexp  The name of the regular expression. It can be a variable name or
a literal.
@param str  The string against which to match the regular expression.
@name test
@methodOf RegExp#
*/
/**
Non-standard



@name toSource
@methodOf RegExp#
*/
/**
Returns a string representing the specified object.

<code><i>regexp</i>.toString()</code>

@name toString
@methodOf RegExp#
*/
/**
Returns a reference to the Date function that created the instance's prototype.
Note that the value of this property is a reference to the function itself, not
a string containing the function's name.



@name constructor
@methodOf Date#
*/
/**
Returns the day of the month for the specified date according to local time.

<code>
getDate()
</code>

@name getDate
@methodOf Date#
*/
/**
Returns the day of the week for the specified date according to local time.

<code>
getDay()
</code>

@name getDay
@methodOf Date#
*/
/**
Returns the year of the specified date according to local time.

<code>
getFullYear()
</code>

@name getFullYear
@methodOf Date#
*/
/**
Returns the hour for the specified date according to local time.

<code>
getHours()
</code>

@name getHours
@methodOf Date#
*/
/**
Returns the milliseconds in the specified date according to local time.

<code>
getMilliseconds()
</code>

@name getMilliseconds
@methodOf Date#
*/
/**
Returns the minutes in the specified date according to local time.

<code>
getMinutes()
</code>

@name getMinutes
@methodOf Date#
*/
/**
Returns the month in the specified date according to local time.

<code>
getMonth()
</code>

@name getMonth
@methodOf Date#
*/
/**
Returns the seconds in the specified date according to local time.

<code>
getSeconds()
</code>

@name getSeconds
@methodOf Date#
*/
/**
Returns the numeric value corresponding to the time for the specified date
according to universal time.

<code> getTime() </code>

@name getTime
@methodOf Date#
*/
/**
Returns the time-zone offset from UTC, in minutes, for the current locale.

<code> getTimezoneOffset() </code>

@name getTimezoneOffset
@methodOf Date#
*/
/**
Returns the day (date) of the month in the specified date according to universal
time.

<code>
getUTCDate()
</code>

@name getUTCDate
@methodOf Date#
*/
/**
Returns the day of the week in the specified date according to universal time.

<code>
getUTCDay()
</code>

@name getUTCDay
@methodOf Date#
*/
/**
Returns the year in the specified date according to universal time.

<code>
getUTCFullYear()
</code>

@name getUTCFullYear
@methodOf Date#
*/
/**
Returns the hours in the specified date according to universal time.

<code>
getUTCHours
</code>

@name getUTCHours
@methodOf Date#
*/
/**
Returns the milliseconds in the specified date according to universal time.

<code>
getUTCMilliseconds()
</code>

@name getUTCMilliseconds
@methodOf Date#
*/
/**
Returns the minutes in the specified date according to universal time.

<code>
getUTCMinutes()
</code>

@name getUTCMinutes
@methodOf Date#
*/
/**
Returns the month of the specified date according to universal time.

<code>
getUTCMonth()
</code>

@name getUTCMonth
@methodOf Date#
*/
/**
Returns the seconds in the specified date according to universal time.

<code>
getUTCSeconds()
</code>

@name getUTCSeconds
@methodOf Date#
*/
/**
Deprecated



@name getYear
@methodOf Date#
*/
/**
Sets the day of the month for a specified date according to local time.

<code> setDate(<em>dayValue</em>) </code>
@param dayValue  An integer from 1 to 31, representing the day of the month.
@name setDate
@methodOf Date#
*/
/**
Sets the full year for a specified date according to local time.

<code>
setFullYear(<i>yearValue</i>[, <i>monthValue</i>[, <em>dayValue</em>]])
</code>
@param  yearValue   An integer specifying the numeric value of the year, for
example, 1995.
@param  monthValue   An integer between 0 and 11 representing the months January
through December.
@param  dayValue   An integer between 1 and 31 representing the day of the
month. If you specify the dayValue parameter, you must also specify the
monthValue.
@name setFullYear
@methodOf Date#
*/
/**
Sets the hours for a specified date according to local time.

<code>
setHours(<i>hoursValue</i>[, <i>minutesValue</i>[, <i>secondsValue</i>[, <em>msValue</em>]]])
</code>
@param  hoursValue   An integer between 0 and 23, representing the hour.
@param  minutesValue   An integer between 0 and 59, representing the minutes.
@param  secondsValue   An integer between 0 and 59, representing the seconds. If
you specify the secondsValue parameter, you must also specify the minutesValue.
@param  msValue   A number between 0 and 999, representing the milliseconds. If
you specify the msValue parameter, you must also specify the minutesValue and
secondsValue.
@name setHours
@methodOf Date#
*/
/**
Sets the milliseconds for a specified date according to local time.

<code>
setMilliseconds(<i>millisecondsValue</i>)
</code>
@param  millisecondsValue   A number between 0 and 999, representing the
milliseconds.
@name setMilliseconds
@methodOf Date#
*/
/**
Sets the minutes for a specified date according to local time.

<code>
setMinutes(<i>minutesValue</i>[, <i>secondsValue</i>[, <em>msValue</em>]])
</code>
@param  minutesValue   An integer between 0 and 59, representing the minutes.
@param  secondsValue   An integer between 0 and 59, representing the seconds. If
you specify the secondsValue parameter, you must also specify the minutesValue.
@param  msValue   A number between 0 and 999, representing the milliseconds. If
you specify the msValue parameter, you must also specify the minutesValue and
secondsValue.
@name setMinutes
@methodOf Date#
*/
/**
Set the month for a specified date according to local time.

<code>
setMonth(<i>monthValue</i>[, <em>dayValue</em>])
</code>
@param  monthValue   An integer between 0 and 11 (representing the months
January through December).
@param  dayValue   An integer from 1 to 31, representing the day of the month.
@name setMonth
@methodOf Date#
*/
/**
Sets the seconds for a specified date according to local time.

<code>
setSeconds(<i>secondsValue</i>[, <em>msValue</em>])
</code>
@param  secondsValue   An integer between 0 and 59.
@param  msValue   A number between 0 and 999, representing the milliseconds.
@name setSeconds
@methodOf Date#
*/
/**
Sets the Date object to the time represented by a number of milliseconds since
January 1, 1970, 00:00:00 UTC.

<code>
setTime(<i>timeValue</i>)
</code>
@param  timeValue   An integer representing the number of milliseconds since 1
January 1970, 00:00:00 UTC.
@name setTime
@methodOf Date#
*/
/**
Sets the day of the month for a specified date according to universal time.

<code>
setUTCDate(<i>dayValue</i>)
</code>
@param  dayValue   An integer from 1 to 31, representing the day of the month.
@name setUTCDate
@methodOf Date#
*/
/**
Sets the full year for a specified date according to universal time.

<code>
setUTCFullYear(<i>yearValue</i>[, <i>monthValue</i>[, <em>dayValue</em>]])
</code>
@param  yearValue   An integer specifying the numeric value of the year, for
example, 1995.
@param  monthValue   An integer between 0 and 11 representing the months January
through December.
@param  dayValue   An integer between 1 and 31 representing the day of the
month. If you specify the dayValue parameter, you must also specify the
monthValue.
@name setUTCFullYear
@methodOf Date#
*/
/**
Sets the hour for a specified date according to universal time.

<code>
setUTCHours(<i>hoursValue</i>[, <i>minutesValue</i>[, <i>secondsValue</i>[, <em>msValue</em>]]])
</code>
@param  hoursValue   An integer between 0 and 23, representing the hour.
@param  minutesValue   An integer between 0 and 59, representing the minutes.
@param  secondsValue   An integer between 0 and 59, representing the seconds. If
you specify the secondsValue parameter, you must also specify the minutesValue.
@param  msValue   A number between 0 and 999, representing the milliseconds. If
you specify the msValue parameter, you must also specify the minutesValue and
secondsValue.
@name setUTCHours
@methodOf Date#
*/
/**
Sets the milliseconds for a specified date according to universal time.

<code>
setUTCMilliseconds(<i>millisecondsValue</i>)
</code>
@param  millisecondsValue   A number between 0 and 999, representing the
milliseconds.
@name setUTCMilliseconds
@methodOf Date#
*/
/**
Sets the minutes for a specified date according to universal time.

<code>
setUTCMinutes(<i>minutesValue</i>[, <i>secondsValue</i>[, <em>msValue</em>]])
</code>
@param  minutesValue   An integer between 0 and 59, representing the minutes.
@param  secondsValue   An integer between 0 and 59, representing the seconds. If
you specify the secondsValue parameter, you must also specify the minutesValue.
@param  msValue   A number between 0 and 999, representing the milliseconds. If
you specify the msValue parameter, you must also specify the minutesValue and
secondsValue.
@name setUTCMinutes
@methodOf Date#
*/
/**
Sets the month for a specified date according to universal time.

<code>
setUTCMonth(<i>monthValue</i>[, <em>dayValue</em>])
</code>
@param  monthValue   An integer between 0 and 11, representing the months
January through December.
@param  dayValue   An integer from 1 to 31, representing the day of the month.
@name setUTCMonth
@methodOf Date#
*/
/**
Sets the seconds for a specified date according to universal time.

<code>
setUTCSeconds(<i>secondsValue</i>[, <em>msValue</em>])
</code>
@param  secondsValue   An integer between 0 and 59.
@param  msValue   A number between 0 and 999, representing the milliseconds.
@name setUTCSeconds
@methodOf Date#
*/
/**
Deprecated



@name setYear
@methodOf Date#
*/
/**
Returns the date portion of a Date object in human readable form in American
English.

<code><em>date</em>.toDateString()</code>

@name toDateString
@methodOf Date#
*/
/**
Returns a JSON representation of the Date object.

<code><em>date</em>.prototype.toJSON()</code>

@name toJSON
@methodOf Date#
*/
/**
Deprecated



@name toGMTString
@methodOf Date#
*/
/**
Converts a date to a string, returning the "date" portion using the operating
system's locale's conventions.

<code>
toLocaleDateString()
</code>

@name toLocaleDateString
@methodOf Date#
*/
/**
Non-standard



@name toLocaleFormat
@methodOf Date#
*/
/**
Converts a date to a string, using the operating system's locale's conventions.

<code>
toLocaleString()
</code>

@name toLocaleString
@methodOf Date#
*/
/**
Converts a date to a string, returning the "time" portion using the current
locale's conventions.

<code> toLocaleTimeString() </code>

@name toLocaleTimeString
@methodOf Date#
*/
/**
Non-standard



@name toSource
@methodOf Date#
*/
/**
Returns a string representing the specified Date object.

<code> toString() </code>

@name toString
@methodOf Date#
*/
/**
Returns the time portion of a Date object in human readable form in American
English.

<code><em>date</em>.toTimeString()</code>

@name toTimeString
@methodOf Date#
*/
/**
Converts a date to a string, using the universal time convention.

<code> toUTCString() </code>

@name toUTCString
@methodOf Date#
*/
/**
Returns the primitive value of a Date object.

<code>
valueOf()
</code>

@name valueOf
@methodOf Date#
*/;
/*!
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com

Copyright (c) 2010 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
*/

/**
Generate a random uuid.

USAGE: Math.uuid(length, radix)

EXAMPLES:
  // No arguments  - returns RFC4122, version 4 ID
  Math.uuid()
  "92329D39-6F5C-4520-ABFC-AAB64544E172"

  // One argument - returns ID of the specified length
  Math.uuid(15)     // 15 character ID (default base=62)
  "VcydxgltxrVZSTV"

  // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
  Math.uuid(8, 2)  // 8 character ID (base=2)
  "01001010"
  Math.uuid(8, 10) // 8 character ID (base=10)
  "47473046"
  Math.uuid(8, 16) // 8 character ID (base=16)
  "098F4D35"

@name uuid
@methodOf Math
@param length The desired number of characters
@param radix  The number of allowable values for each character.
 */
(function() {
  // Private array of chars to use
  var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');

  Math.uuid = function (len, radix) {
    var chars = CHARS, uuid = [];
    radix = radix || chars.length;

    if (len) {
      // Compact form
      for (var i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
    } else {
      // rfc4122, version 4 form
      var r;

      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';

      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (var i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random()*16;
          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
        }
      }
    }

    return uuid.join('');
  };

  // A more performant, but slightly bulkier, RFC4122v4 solution.  We boost performance
  // by minimizing calls to random()
  Math.uuidFast = function() {
    var chars = CHARS, uuid = new Array(36), rnd=0, r;
    for (var i = 0; i < 36; i++) {
      if (i==8 || i==13 ||  i==18 || i==23) {
        uuid[i] = '-';
      } else if (i==14) {
        uuid[i] = '4';
      } else {
        if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
        r = rnd & 0xf;
        rnd = rnd >> 4;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
    return uuid.join('');
  };

  // A more compact, but less performant, RFC4122v4 solution:
  Math.uuidCompact = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    }).toUpperCase();
  };
})();;
;
(function() {
  var clickTrackers, tag, type, _fn;
  var __slice = Array.prototype.slice;
  window.namespace = function(target, name, block) {
    var item, top, _i, _len, _ref, _ref2;
    if (arguments.length < 3) {
      _ref = [(typeof exports !== 'undefined' ? exports : window)].concat(__slice.call(arguments)), target = _ref[0], name = _ref[1], block = _ref[2];
    }
    top = target;
    _ref2 = name.split('.');
    for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
      item = _ref2[_i];
      target = target[item] || (target[item] = {});
    }
    return block(target, top);
  };
  Object.isObject = function(object) {
    return Object.prototype.toString.call(object) === '[object Object]';
  };
  Function.prototype.debounce = function(wait) {
    var func, timeout;
    timeout = null;
    func = this;
    return function() {
      var args, context, later;
      context = this;
      args = arguments;
      later = function() {
        timeout = null;
        return func.apply(context, args);
      };
      clearTimeout(timeout);
      return timeout = setTimeout(later, wait);
    };
  };
  window.trackEvent = function(category, action, label) {
    return _gaq.push(['_trackEvent', category, action, label]);
  };
  clickTrackers = {
    a: "click",
    button: "click"
  };
  _fn = function(tag, type) {
    return $(tag).live(type, function() {
      var category, label;
      category = $(this).parents('[eventCategory]:first').attr('eventCategory') || "Page";
      label = $(this).attr('eventLabel') || $(this).text() || $(this).attr('title');
      return trackEvent(category, type, $.trim(label));
    });
  };
  for (tag in clickTrackers) {
    type = clickTrackers[tag];
    _fn(tag, type);
  }
  window.notify = function(message, delay) {
    return $.pnotify({
      pnotify_animate_speed: 'fast',
      pnotify_text: message,
      pnotify_delay: delay,
      pnotify_history: false
    });
  };
  $(".clickable").live('click', function(event) {
    if (!$(event.target).is("a")) {
      return document.location = $(this).find("a").eq(0).attr("href");
    }
  });
  window.getVal = function(key) {
    if (localStorage) {
      try {
        return JSON.parse(localStorage[key]);
      } catch (error) {
        return;
      }
    }
  };
  window.setVal = function(key, value) {
    if (localStorage) {
      return localStorage[key] = value;
    }
  };
  window.trackPageview = function(pageName) {
    return _gaq.push(["_trackPageview", pageName]);
  };
  window.getCsrfData = function() {
    var data;
    data = {};
    data[$("meta[name=csrf-param]").attr("content")] = $("meta[name=csrf-token]").attr("content");
    return data;
  };
  $(".tag .remove").live("click", function() {
    var $this, spriteId;
    $this = $(this);
    spriteId = $this.parent().attr("data-sprite_id");
    tag = $this.prev().text();
    $this.parent().fadeOut();
    return $.post("/sprites/" + spriteId + "/remove_tag", {
      tag: tag
    });
  });
  $(function() {
    var makeTag;
    $.modal.defaults.overlayClose = true;
    makeTag = function(tag, spriteId) {
      var link, tagElem;
      tagElem = $("<div class='tag' />");
      tagElem.attr("data-sprite_id", spriteId);
      link = $("<a href='/sprites/?tagged=" + (escape(tag)) + "' />").text(tag);
      tagElem.append(link);
      if (loggedIn) {
        tagElem.append($("<div class='remove' />").text("X"));
      }
      return tagElem;
    };
    $(".tags form").ajaxForm({
      beforeSubmit: function(array, $form) {
        var input, spriteId;
        input = $form.find("input[name=tag]");
        spriteId = $form.attr("data-sprite_id");
        tag = input.val();
        $form.before(makeTag(tag, spriteId));
        return input.val("");
      }
    });
    $("#flashes .close").live("mousedown", function() {
      return $(this).parent().slideUp();
    });
    $("#flashes .notice").each(function() {
      return notify($(this).html());
    });
    $('.tipsy').tipsy({
      delayIn: 200,
      delayOut: 500,
      fade: 50,
      gravity: 'w',
      opacity: 1
    });
    $(".window").draggable({
      handle: "h3",
      iframeFix: true
    }).find("h3").disableSelection();
    return $('.window .ui-icon-close').live("click", function() {
      return $(this).parent().hide().children("iframe").remove();
    });
  });
}).call(this);
// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
//   and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
  $.extend($.fn, {

    contextMenu: function(o, callback) {
      // Defaults
      if( o.menu == undefined ) return false;
      if( o.inSpeed == undefined ) o.inSpeed = 150;
      if( o.outSpeed == undefined ) o.outSpeed = 75;
      // 0 needs to be -1 for expected results (no fade)
      if( o.inSpeed == 0 ) o.inSpeed = -1;
      if( o.outSpeed == 0 ) o.outSpeed = -1;

      // Get this context menu
      var menu = $('#' + o.menu);

      // Loop each context menu
      $(this).each( function() {
        var el = $(this);
        var offset = $(el).offset();

        var hideMenu = function() {
          $(document).unbind('click', hideMenu);
          $(menu).fadeOut(o.outSpeed);
          return false;
        };

        // Simulate a true right click
        $(this).mousedown( function(e) {
          var evt = e;
          evt.stopPropagation();

          var mouseup = function(e) {
            e.stopPropagation();
            var srcElement = $(this);
            $(this).unbind('mouseup', mouseup);

            if( evt.button == 2 ) {
              // Hide context menus that may be showing
              $(".context_menu").hide();


              if( $(el).hasClass('disabled') ) return false;

              // Detect mouse position
              var d = {}, x, y;
              if( self.innerHeight ) {
                d.pageYOffset = self.pageYOffset;
                d.pageXOffset = self.pageXOffset;
                d.innerHeight = self.innerHeight;
                d.innerWidth = self.innerWidth;
              } else if( document.documentElement &&
                document.documentElement.clientHeight ) {
                d.pageYOffset = document.documentElement.scrollTop;
                d.pageXOffset = document.documentElement.scrollLeft;
                d.innerHeight = document.documentElement.clientHeight;
                d.innerWidth = document.documentElement.clientWidth;
              } else if( document.body ) {
                d.pageYOffset = document.body.scrollTop;
                d.pageXOffset = document.body.scrollLeft;
                d.innerHeight = document.body.clientHeight;
                d.innerWidth = document.body.clientWidth;
              }
              (e.pageX) ? x = e.pageX : x = e.clientX + d.scrollLeft;
              (e.pageY) ? y = e.pageY : y = e.clientY + d.scrollTop;

              // Show the menu
              $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
              // Hover events
              $(menu).find('A').mouseover( function() {
                $(menu).find('LI.hover').removeClass('hover');
                $(this).parent().addClass('hover');
              }).mouseout( function() {
                $(menu).find('LI.hover').removeClass('hover');
              });

              // When items are selected
              $('#' + o.menu).find('A').unbind('click');
              $('#' + o.menu).find('LI:not(.disabled) A').click( function() {
                $(".context_menu").hide();
                // Callback
                if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
                return false;
              });

              // Hide bindings
              setTimeout( function() { // Delay for Mozilla
                $(document).click( hideMenu );
              }, 0);
            }
          };

          $(this).mouseup( mouseup );
        });

        // Disable text selection
        if( $.browser.mozilla ) {
          $('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
        } else if( $.browser.msie ) {
          $('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
        } else {
          $('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
        }
        // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
        $(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });

      });
      return $(this);
    }

  });
})(jQuery);
/*
 * SimpleModal 1.3.5 - jQuery Plugin
 * http://www.ericmmartin.com/projects/simplemodal/
 * Copyright (c) 2010 Eric Martin (http://twitter.com/EricMMartin)
 * Dual licensed under the MIT and GPL licenses
 * Revision: $Id: jquery.simplemodal.js 245 2010-03-25 20:41:15Z emartin24 $
 */

;(function($){var ie6=$.browser.msie&&parseInt($.browser.version)==6&&typeof window['XMLHttpRequest']!="object",ieQuirks=null,w=[];$.modal=function(data,options){return $.modal.impl.init(data,options);};$.modal.close=function(){$.modal.impl.close();};$.fn.modal=function(options){return $.modal.impl.init(this,options);};$.modal.defaults={appendTo:'body',focus:true,opacity:25,overlayId:'simplemodal-overlay',overlayCss:{},containerId:'simplemodal-container',containerCss:{},dataId:'simplemodal-data',dataCss:{},minHeight:null,minWidth:null,maxHeight:null,maxWidth:null,autoResize:false,autoPosition:true,zIndex:1000,close:true,closeHTML:'<a class="modalCloseImg" title="Close"></a>',closeClass:'simplemodal-close',escClose:true,overlayClose:false,position:null,persist:false,modal:true,onOpen:null,onShow:null,onClose:null};$.modal.impl={o:null,d:{},init:function(data,options){var s=this;if(s.d.data){return false;}ieQuirks=$.browser.msie&&!$.boxModel;s.o=$.extend({},$.modal.defaults,options);s.zIndex=s.o.zIndex;s.occb=false;if(typeof data=='object'){data=data instanceof jQuery?data:$(data);s.d.placeholder=false;if(data.parent().parent().size()>0){data.before($('<span></span>').attr('id','simplemodal-placeholder').css({display:'none'}));s.d.placeholder=true;s.display=data.css('display');if(!s.o.persist){s.d.orig=data.clone(true);}}}else if(typeof data=='string'||typeof data=='number'){data=$('<div></div>').html(data);}else{alert('SimpleModal Error: Unsupported data type: '+typeof data);return s;}s.create(data);data=null;s.open();if($.isFunction(s.o.onShow)){s.o.onShow.apply(s,[s.d]);}return s;},create:function(data){var s=this;w=s.getDimensions();if(s.o.modal&&ie6){s.d.iframe=$('<iframe src="javascript:false;"></iframe>').css($.extend(s.o.iframeCss,{display:'none',opacity:0,position:'fixed',height:w[0],width:w[1],zIndex:s.o.zIndex,top:0,left:0})).appendTo(s.o.appendTo);}s.d.overlay=$('<div></div>').attr('id',s.o.overlayId).addClass('simplemodal-overlay').css($.extend(s.o.overlayCss,{display:'none',opacity:s.o.opacity/100,height:s.o.modal?w[0]:0,width:s.o.modal?w[1]:0,position:'fixed',left:0,top:0,zIndex:s.o.zIndex+1})).appendTo(s.o.appendTo);s.d.container=$('<div></div>').attr('id',s.o.containerId).addClass('simplemodal-container').css($.extend(s.o.containerCss,{display:'none',position:'fixed',zIndex:s.o.zIndex+2})).append(s.o.close&&s.o.closeHTML?$(s.o.closeHTML).addClass(s.o.closeClass):'').appendTo(s.o.appendTo);s.d.wrap=$('<div></div>').attr('tabIndex',-1).addClass('simplemodal-wrap').css({height:'100%',outline:0,width:'100%'}).appendTo(s.d.container);s.d.data=data.attr('id',data.attr('id')||s.o.dataId).addClass('simplemodal-data').css($.extend(s.o.dataCss,{display:'none'})).appendTo('body');data=null;s.setContainerDimensions();s.d.data.appendTo(s.d.wrap);if(ie6||ieQuirks){s.fixIE();}},bindEvents:function(){var s=this;$('.'+s.o.closeClass).bind('click.simplemodal',function(e){e.preventDefault();s.close();});if(s.o.modal&&s.o.close&&s.o.overlayClose){s.d.overlay.bind('click.simplemodal',function(e){e.preventDefault();s.close();});}$(document).bind('keydown.simplemodal',function(e){if(s.o.modal&&s.o.focus&&e.keyCode==9){s.watchTab(e);}else if((s.o.close&&s.o.escClose)&&e.keyCode==27){e.preventDefault();s.close();}});$(window).bind('resize.simplemodal',function(){w=s.getDimensions();s.setContainerDimensions(true);if(ie6||ieQuirks){s.fixIE();}else if(s.o.modal){s.d.iframe&&s.d.iframe.css({height:w[0],width:w[1]});s.d.overlay.css({height:w[0],width:w[1]});}});},unbindEvents:function(){$('.'+this.o.closeClass).unbind('click.simplemodal');$(document).unbind('keydown.simplemodal');$(window).unbind('resize.simplemodal');this.d.overlay.unbind('click.simplemodal');},fixIE:function(){var s=this,p=s.o.position;$.each([s.d.iframe||null,!s.o.modal?null:s.d.overlay,s.d.container],function(i,el){if(el){var bch='document.body.clientHeight',bcw='document.body.clientWidth',bsh='document.body.scrollHeight',bsl='document.body.scrollLeft',bst='document.body.scrollTop',bsw='document.body.scrollWidth',ch='document.documentElement.clientHeight',cw='document.documentElement.clientWidth',sl='document.documentElement.scrollLeft',st='document.documentElement.scrollTop',s=el[0].style;s.position='absolute';if(i<2){s.removeExpression('height');s.removeExpression('width');s.setExpression('height',''+bsh+' > '+bch+' ? '+bsh+' : '+bch+' + "px"');s.setExpression('width',''+bsw+' > '+bcw+' ? '+bsw+' : '+bcw+' + "px"');}else{var te,le;if(p&&p.constructor==Array){var top=p[0]?typeof p[0]=='number'?p[0].toString():p[0].replace(/px/,''):el.css('top').replace(/px/,'');te=top.indexOf('%')==-1?top+' + (t = '+st+' ? '+st+' : '+bst+') + "px"':parseInt(top.replace(/%/,''))+' * (('+ch+' || '+bch+') / 100) + (t = '+st+' ? '+st+' : '+bst+') + "px"';if(p[1]){var left=typeof p[1]=='number'?p[1].toString():p[1].replace(/px/,'');le=left.indexOf('%')==-1?left+' + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"':parseInt(left.replace(/%/,''))+' * (('+cw+' || '+bcw+') / 100) + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"';}}else{te='('+ch+' || '+bch+') / 2 - (this.offsetHeight / 2) + (t = '+st+' ? '+st+' : '+bst+') + "px"';le='('+cw+' || '+bcw+') / 2 - (this.offsetWidth / 2) + (t = '+sl+' ? '+sl+' : '+bsl+') + "px"';}s.removeExpression('top');s.removeExpression('left');s.setExpression('top',te);s.setExpression('left',le);}}});},focus:function(pos){var s=this,p=pos||'first';var input=$(':input:enabled:visible:'+p,s.d.wrap);input.length>0?input.focus():s.d.wrap.focus();},getDimensions:function(){var el=$(window);var h=$.browser.opera&&$.browser.version>'9.5'&&$.fn.jquery<='1.2.6'?document.documentElement['clientHeight']:$.browser.opera&&$.browser.version<'9.5'&&$.fn.jquery>'1.2.6'?window.innerHeight:el.height();return[h,el.width()];},getVal:function(v){return v=='auto'?0:v.indexOf('%')>0?v:parseInt(v.replace(/px/,''));},setContainerDimensions:function(resize){var s=this;if(!resize||(resize&&s.o.autoResize)){var ch=$.browser.opera?s.d.container.height():s.getVal(s.d.container.css('height')),cw=$.browser.opera?s.d.container.width():s.getVal(s.d.container.css('width')),dh=s.d.data.outerHeight(true),dw=s.d.data.outerWidth(true);var mh=s.o.maxHeight&&s.o.maxHeight<w[0]?s.o.maxHeight:w[0],mw=s.o.maxWidth&&s.o.maxWidth<w[1]?s.o.maxWidth:w[1];if(!ch){if(!dh){ch=s.o.minHeight;}else{if(dh>mh){ch=mh;}else if(dh<s.o.minHeight){ch=s.o.minHeight;}else{ch=dh;}}}else{ch=ch>mh?mh:ch;}if(!cw){if(!dw){cw=s.o.minWidth;}else{if(dw>mw){cw=mw;}else if(dw<s.o.minWidth){cw=s.o.minWidth;}else{cw=dw;}}}else{cw=cw>mw?mw:cw;}s.d.container.css({height:ch,width:cw});if(dh>ch||dw>cw){s.d.wrap.css({overflow:'auto'});}}if(s.o.autoPosition){s.setPosition();}},setPosition:function(){var s=this,top,left,hc=(w[0]/2)-(s.d.container.outerHeight(true)/2),vc=(w[1]/2)-(s.d.container.outerWidth(true)/2);if(s.o.position&&Object.prototype.toString.call(s.o.position)==="[object Array]"){top=s.o.position[0]||hc;left=s.o.position[1]||vc;}else{top=hc;left=vc;}s.d.container.css({left:left,top:top});},watchTab:function(e){var s=this;if($(e.target).parents('.simplemodal-container').length>0){s.inputs=$(':input:enabled:visible:first, :input:enabled:visible:last',s.d.data[0]);if((!e.shiftKey&&e.target==s.inputs[s.inputs.length-1])||(e.shiftKey&&e.target==s.inputs[0])||s.inputs.length==0){e.preventDefault();var pos=e.shiftKey?'last':'first';setTimeout(function(){s.focus(pos);},10);}}else{e.preventDefault();setTimeout(function(){s.focus();},10);}},open:function(){var s=this;s.d.iframe&&s.d.iframe.show();if($.isFunction(s.o.onOpen)){s.o.onOpen.apply(s,[s.d]);}else{s.d.overlay.show();s.d.container.show();s.d.data.show();}s.focus();s.bindEvents();},close:function(){var s=this;if(!s.d.data){return false;}s.unbindEvents();if($.isFunction(s.o.onClose)&&!s.occb){s.occb=true;s.o.onClose.apply(s,[s.d]);}else{if(s.d.placeholder){var ph=$('#simplemodal-placeholder');if(s.o.persist){ph.replaceWith(s.d.data.removeClass('simplemodal-data').css('display',s.display));}else{s.d.data.hide().remove();ph.replaceWith(s.d.orig);}}else{s.d.data.hide().remove();}s.d.container.hide().remove();s.d.overlay.hide().remove();s.d.iframe&&s.d.iframe.hide().remove();s.d={};}}};})(jQuery);
/*!
 * jQuery Form Plugin
 * version: 2.43 (12-MAR-2010)
 * @requires jQuery v1.3.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

;(function($) {

/*
	Usage Note:
	-----------
	Do not use both ajaxSubmit and ajaxForm on the same form.  These
	functions are intended to be exclusive.  Use ajaxSubmit if you want
	to bind your own submit handler to the form.  For example,

	$(document).ready(function() {
		$('#myForm').bind('submit', function() {
			$(this).ajaxSubmit({
				target: '#output'
			});
			return false; // <-- important!
		});
	});

	Use ajaxForm when you want the plugin to manage all the event binding
	for you.  For example,

	$(document).ready(function() {
		$('#myForm').ajaxForm({
			target: '#output'
		});
	});

	When using ajaxForm, the ajaxSubmit function will be invoked for you
	at the appropriate time.
*/

/**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
$.fn.ajaxSubmit = function(options) {
	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
	if (!this.length) {
		log('ajaxSubmit: skipping submit process - no element selected');
		return this;
	}

	if (typeof options == 'function')
		options = { success: options };

	var url = $.trim(this.attr('action'));
	if (url) {
		// clean url (don't include hash vaue)
		url = (url.match(/^([^#]+)/)||[])[1];
   	}
   	url = url || window.location.href || '';

	options = $.extend({
		url:  url,
		type: this.attr('method') || 'GET',
		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
	}, options || {});

	// hook for manipulating the form data before it is extracted;
	// convenient for use with rich editors like tinyMCE or FCKEditor
	var veto = {};
	this.trigger('form-pre-serialize', [this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
		return this;
	}

	// provide opportunity to alter form data before it is serialized
	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSerialize callback');
		return this;
	}

	var a = this.formToArray(options.semantic);
	if (options.data) {
		options.extraData = options.data;
		for (var n in options.data) {
		  if(options.data[n] instanceof Array) {
			for (var k in options.data[n])
			  a.push( { name: n, value: options.data[n][k] } );
		  }
		  else
			 a.push( { name: n, value: options.data[n] } );
		}
	}

	// give pre-submit callback an opportunity to abort the submit
	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSubmit callback');
		return this;
	}

	// fire vetoable 'validate' event
	this.trigger('form-submit-validate', [a, this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
		return this;
	}

	var q = $.param(a);

	if (options.type.toUpperCase() == 'GET') {
		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
		options.data = null;  // data is null for 'get'
	}
	else
		options.data = q; // data is the query string for 'post'

	var $form = this, callbacks = [];
	if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
	if (options.clearForm) callbacks.push(function() { $form.clearForm(); });

	// perform a load on the target only if dataType is not provided
	if (!options.dataType && options.target) {
		var oldSuccess = options.success || function(){};
		callbacks.push(function(data) {
			var fn = options.replaceTarget ? 'replaceWith' : 'html';
			$(options.target)[fn](data).each(oldSuccess, arguments);
		});
	}
	else if (options.success)
		callbacks.push(options.success);

	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
		for (var i=0, max=callbacks.length; i < max; i++)
			callbacks[i].apply(options, [data, status, xhr || $form, $form]);
	};

	// are there files to upload?
	var files = $('input:file', this).fieldValue();
	var found = false;
	for (var j=0; j < files.length; j++)
		if (files[j])
			found = true;

	var multipart = false;
//	var mp = 'multipart/form-data';
//	multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);

	// options.iframe allows user to force iframe mode
	// 06-NOV-09: now defaulting to iframe mode if file input is detected
   if ((files.length && options.iframe !== false) || options.iframe || found || multipart) {
	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
	   if (options.closeKeepAlive)
		   $.get(options.closeKeepAlive, fileUpload);
	   else
		   fileUpload();
	   }
   else
	   $.ajax(options);

	// fire 'notify' event
	this.trigger('form-submit-notify', [this, options]);
	return this;


	// private function for handling file uploads (hat tip to YAHOO!)
	function fileUpload() {
		var form = $form[0];

		if ($(':input[name=submit]', form).length) {
			alert('Error: Form elements must not be named "submit".');
			return;
		}

		var opts = $.extend({}, $.ajaxSettings, options);
		var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);

		var id = 'jqFormIO' + (new Date().getTime());
		var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ opts.iframeSrc +'" onload="(jQuery(this).data(\'form-plugin-onload\'))()" />');
		var io = $io[0];

		$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

		var xhr = { // mock object
			aborted: 0,
			responseText: null,
			responseXML: null,
			status: 0,
			statusText: 'n/a',
			getAllResponseHeaders: function() {},
			getResponseHeader: function() {},
			setRequestHeader: function() {},
			abort: function() {
				this.aborted = 1;
				$io.attr('src', opts.iframeSrc); // abort op in progress
			}
		};

		var g = opts.global;
		// trigger ajax global events so that activity/block indicators work like normal
		if (g && ! $.active++) $.event.trigger("ajaxStart");
		if (g) $.event.trigger("ajaxSend", [xhr, opts]);

		if (s.beforeSend && s.beforeSend(xhr, s) === false) {
			s.global && $.active--;
			return;
		}
		if (xhr.aborted)
			return;

		var cbInvoked = false;
		var timedOut = 0;

		// add submitting element to data if we know it
		var sub = form.clk;
		if (sub) {
			var n = sub.name;
			if (n && !sub.disabled) {
				opts.extraData = opts.extraData || {};
				opts.extraData[n] = sub.value;
				if (sub.type == "image") {
					opts.extraData[n+'.x'] = form.clk_x;
					opts.extraData[n+'.y'] = form.clk_y;
				}
			}
		}

		// take a breath so that pending repaints get some cpu time before the upload starts
		function doSubmit() {
			// make sure form attrs are set
			var t = $form.attr('target'), a = $form.attr('action');

			// update form attrs in IE friendly way
			form.setAttribute('target',id);
			if (form.getAttribute('method') != 'POST')
				form.setAttribute('method', 'POST');
			if (form.getAttribute('action') != opts.url)
				form.setAttribute('action', opts.url);

			// ie borks in some cases when setting encoding
			if (! opts.skipEncodingOverride) {
				$form.attr({
					encoding: 'multipart/form-data',
					enctype:  'multipart/form-data'
				});
			}

			// support timout
			if (opts.timeout)
				setTimeout(function() { timedOut = true; cb(); }, opts.timeout);

			// add "extra" data to form if provided in options
			var extraInputs = [];
			try {
				if (opts.extraData)
					for (var n in opts.extraData)
						extraInputs.push(
							$('<input type="hidden" name="'+n+'" value="'+opts.extraData[n]+'" />')
								.appendTo(form)[0]);

				// add iframe to doc and submit the form
				$io.appendTo('body');
				$io.data('form-plugin-onload', cb);
				form.submit();
			}
			finally {
				// reset attrs and remove "extra" input elements
				form.setAttribute('action',a);
				t ? form.setAttribute('target', t) : $form.removeAttr('target');
				$(extraInputs).remove();
			}
		};

		if (opts.forceSync)
			doSubmit();
		else
			setTimeout(doSubmit, 10); // this lets dom updates render
	
		var domCheckCount = 100;

		function cb() {
			if (cbInvoked) 
				return;

			var ok = true;
			try {
				if (timedOut) throw 'timeout';
				// extract the server response from the iframe
				var data, doc;

				doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
				
				var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
				log('isXml='+isXml);
				if (!isXml && (doc.body == null || doc.body.innerHTML == '')) {
				 	if (--domCheckCount) {
						// in some browsers (Opera) the iframe DOM is not always traversable when
						// the onload callback fires, so we loop a bit to accommodate
				 		log('requeing onLoad callback, DOM not available');
						setTimeout(cb, 250);
						return;
					}
					log('Could not access iframe DOM after 100 tries.');
					return;
				}

				log('response detected');
				cbInvoked = true;
				xhr.responseText = doc.body ? doc.body.innerHTML : null;
				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
				xhr.getResponseHeader = function(header){
					var headers = {'content-type': opts.dataType};
					return headers[header];
				};

				if (opts.dataType == 'json' || opts.dataType == 'script') {
					// see if user embedded response in textarea
					var ta = doc.getElementsByTagName('textarea')[0];
					if (ta)
						xhr.responseText = ta.value;
					else {
						// account for browsers injecting pre around json response
						var pre = doc.getElementsByTagName('pre')[0];
						if (pre)
							xhr.responseText = pre.innerHTML;
					}			  
				}
				else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
					xhr.responseXML = toXml(xhr.responseText);
				}
				data = $.httpData(xhr, opts.dataType);
			}
			catch(e){
				log('error caught:',e);
				ok = false;
				xhr.error = e;
				$.handleError(opts, xhr, 'error', e);
			}

			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
			if (ok) {
				opts.success(data, 'success');
				if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
			}
			if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
			if (g && ! --$.active) $.event.trigger("ajaxStop");
			if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');

			// clean up
			setTimeout(function() {
				$io.removeData('form-plugin-onload');
				$io.remove();
				xhr.responseXML = null;
			}, 100);
		};

		function toXml(s, doc) {
			if (window.ActiveXObject) {
				doc = new ActiveXObject('Microsoft.XMLDOM');
				doc.async = 'false';
				doc.loadXML(s);
			}
			else
				doc = (new DOMParser()).parseFromString(s, 'text/xml');
			return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
		};
	};
};

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *	is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *	used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
$.fn.ajaxForm = function(options) {
	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
		e.preventDefault();
		$(this).ajaxSubmit(options);
	}).bind('click.form-plugin', function(e) {
		var target = e.target;
		var $el = $(target);
		if (!($el.is(":submit,input:image"))) {
			// is this a child element of the submit el?  (ex: a span within a button)
			var t = $el.closest(':submit');
			if (t.length == 0)
				return;
			target = t[0];
		}
		var form = this;
		form.clk = target;
		if (target.type == 'image') {
			if (e.offsetX != undefined) {
				form.clk_x = e.offsetX;
				form.clk_y = e.offsetY;
			} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
				var offset = $el.offset();
				form.clk_x = e.pageX - offset.left;
				form.clk_y = e.pageY - offset.top;
			} else {
				form.clk_x = e.pageX - target.offsetLeft;
				form.clk_y = e.pageY - target.offsetTop;
			}
		}
		// clear form vars
		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
	});
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
	return this.unbind('submit.form-plugin click.form-plugin');
};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
$.fn.formToArray = function(semantic) {
	var a = [];
	if (this.length == 0) return a;

	var form = this[0];
	var els = semantic ? form.getElementsByTagName('*') : form.elements;
	if (!els) return a;
	for(var i=0, max=els.length; i < max; i++) {
		var el = els[i];
		var n = el.name;
		if (!n) continue;

		if (semantic && form.clk && el.type == "image") {
			// handle image inputs on the fly when semantic == true
			if(!el.disabled && form.clk == el) {
				a.push({name: n, value: $(el).val()});
				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
			}
			continue;
		}

		var v = $.fieldValue(el, true);
		if (v && v.constructor == Array) {
			for(var j=0, jmax=v.length; j < jmax; j++)
				a.push({name: n, value: v[j]});
		}
		else if (v !== null && typeof v != 'undefined')
			a.push({name: n, value: v});
	}

	if (!semantic && form.clk) {
		// input type=='image' are not found in elements array! handle it here
		var $input = $(form.clk), input = $input[0], n = input.name;
		if (n && !input.disabled && input.type == 'image') {
			a.push({name: n, value: $input.val()});
			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
		}
	}
	return a;
};

/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
$.fn.formSerialize = function(semantic) {
	//hand off to jQuery.param for proper encoding
	return $.param(this.formToArray(semantic));
};

/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
$.fn.fieldSerialize = function(successful) {
	var a = [];
	this.each(function() {
		var n = this.name;
		if (!n) return;
		var v = $.fieldValue(this, successful);
		if (v && v.constructor == Array) {
			for (var i=0,max=v.length; i < max; i++)
				a.push({name: n, value: v[i]});
		}
		else if (v !== null && typeof v != 'undefined')
			a.push({name: this.name, value: v});
	});
	//hand off to jQuery.param for proper encoding
	return $.param(a);
};

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *	  <input name="A" type="text" />
 *	  <input name="A" type="text" />
 *	  <input name="B" type="checkbox" value="B1" />
 *	  <input name="B" type="checkbox" value="B2"/>
 *	  <input name="C" type="radio" value="C1" />
 *	  <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *	   array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
	for (var val=[], i=0, max=this.length; i < max; i++) {
		var el = this[i];
		var v = $.fieldValue(el, successful);
		if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
			continue;
		v.constructor == Array ? $.merge(val, v) : val.push(v);
	}
	return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
	if (typeof successful == 'undefined') successful = true;

	if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
		(t == 'checkbox' || t == 'radio') && !el.checked ||
		(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
		tag == 'select' && el.selectedIndex == -1))
			return null;

	if (tag == 'select') {
		var index = el.selectedIndex;
		if (index < 0) return null;
		var a = [], ops = el.options;
		var one = (t == 'select-one');
		var max = (one ? index+1 : ops.length);
		for(var i=(one ? index : 0); i < max; i++) {
			var op = ops[i];
			if (op.selected) {
				var v = op.value;
				if (!v) // extra pain for IE...
					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
				if (one) return v;
				a.push(v);
			}
		}
		return a;
	}
	return el.value;
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
	return this.each(function() {
		$('input,select,textarea', this).clearFields();
	});
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
	return this.each(function() {
		var t = this.type, tag = this.tagName.toLowerCase();
		if (t == 'text' || t == 'password' || tag == 'textarea')
			this.value = '';
		else if (t == 'checkbox' || t == 'radio')
			this.checked = false;
		else if (tag == 'select')
			this.selectedIndex = -1;
	});
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
	return this.each(function() {
		// guard against an input with the name of 'reset'
		// note that IE reports the reset function as an 'object'
		if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
			this.reset();
	});
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
	if (b == undefined) b = true;
	return this.each(function() {
		this.disabled = !b;
	});
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
	if (select == undefined) select = true;
	return this.each(function() {
		var t = this.type;
		if (t == 'checkbox' || t == 'radio')
			this.checked = select;
		else if (this.tagName.toLowerCase() == 'option') {
			var $sel = $(this).parent('select');
			if (select && $sel[0] && $sel[0].type == 'select-one') {
				// deselect all other options
				$sel.find('option').selected(false);
			}
			this.selected = select;
		}
	});
};

// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
	if ($.fn.ajaxSubmit.debug) {
		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
		if (window.console && window.console.log)
			window.console.log(msg);
		else if (window.opera && window.opera.postError)
			window.opera.postError(msg);
	}
};

})(jQuery);
/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */

;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
(function() {
  /**
  jQuery Hotkeys Plugin
  Copyright 2010, John Resig
  Dual licensed under the MIT or GPL Version 2 licenses.
  
  Based upon the plugin by Tzury Bar Yochay:
  http://github.com/tzuryby/hotkeys
  
  Original idea by:
  Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
  */  (function(jQuery) {
    var isFunctionKey, isTextAcceptingInput, keyHandler;
    isTextAcceptingInput = function(element) {
      return /textarea|select/i.test(element.nodeName) || element.type === "text" || element.type === "password";
    };
    isFunctionKey = function(event) {
      var _ref;
      return (event.type !== "keypress") && ((112 <= (_ref = event.which) && _ref <= 123));
    };
    jQuery.hotkeys = {
      version: "0.8",
      specialKeys: {
        8: "backspace",
        9: "tab",
        13: "return",
        16: "shift",
        17: "ctrl",
        18: "alt",
        19: "pause",
        20: "capslock",
        27: "esc",
        32: "space",
        33: "pageup",
        34: "pagedown",
        35: "end",
        36: "home",
        37: "left",
        38: "up",
        39: "right",
        40: "down",
        45: "insert",
        46: "del",
        96: "0",
        97: "1",
        98: "2",
        99: "3",
        100: "4",
        101: "5",
        102: "6",
        103: "7",
        104: "8",
        105: "9",
        106: "*",
        107: "+",
        109: "-",
        110: ".",
        111: "/",
        112: "f1",
        113: "f2",
        114: "f3",
        115: "f4",
        116: "f5",
        117: "f6",
        118: "f7",
        119: "f8",
        120: "f9",
        121: "f10",
        122: "f11",
        123: "f12",
        144: "numlock",
        145: "scroll",
        186: ";",
        187: "=",
        188: ",",
        189: "-",
        190: ".",
        191: "/",
        219: "[",
        220: "\\",
        221: "]",
        222: "'",
        224: "meta"
      },
      shiftNums: {
        "`": "~",
        "1": "!",
        "2": "@",
        "3": "#",
        "4": "$",
        "5": "%",
        "6": "^",
        "7": "&",
        "8": "*",
        "9": "(",
        "0": ")",
        "-": "_",
        "=": "+",
        ";": ":",
        "'": "\"",
        ",": "<",
        ".": ">",
        "/": "?",
        "\\": "|"
      }
    };
    keyHandler = function(handleObj) {
      var keys, origHandler;
      if (typeof handleObj.data !== "string") {
        return;
      }
      origHandler = handleObj.handler;
      keys = handleObj.data.toLowerCase().split(" ");
      return handleObj.handler = function(event) {
        var character, key, modif, possible, special, target, _i, _len;
        special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which];
        character = String.fromCharCode(event.which).toLowerCase();
        modif = "";
        possible = {};
        target = event.target;
        if (event.altKey && special !== "alt") {
          modif += "alt+";
        }
        if (event.ctrlKey && special !== "ctrl") {
          modif += "ctrl+";
        }
        if (event.metaKey && !event.ctrlKey && special !== "meta") {
          modif += "meta+";
        }
        if (this !== target) {
          if (isTextAcceptingInput(target) && !modif && !isFunctionKey(event)) {
            return;
          }
        }
        if (event.shiftKey && special !== "shift") {
          modif += "shift+";
        }
        if (special) {
          possible[modif + special] = true;
        } else {
          possible[modif + character] = true;
          possible[modif + jQuery.hotkeys.shiftNums[character]] = true;
          if (modif === "shift+") {
            possible[jQuery.hotkeys.shiftNums[character]] = true;
          }
        }
        for (_i = 0, _len = keys.length; _i < _len; _i++) {
          key = keys[_i];
          if (possible[key]) {
            return origHandler.apply(this, arguments);
          }
        }
      };
    };
    return jQuery.each(["keydown", "keyup", "keypress"], function() {
      return jQuery.event.special[this] = {
        add: keyHandler
      };
    });
  })(jQuery);
}).call(this);
/*
 * jQuery Templates Plugin 1.0.0pre
 * http://github.com/jquery/jquery-tmpl
 * Requires jQuery 1.4.2
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function (a) { var r = a.fn.domManip, d = "_tmplitem", q = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, b = {}, f = {}, e, p = { key: 0, data: {} }, i = 0, c = 0, l = []; function g(e, d, g, h) { var c = { data: h || (d ? d.data : {}), _wrap: d ? d._wrap : null, tmpl: null, parent: d || null, nodes: [], calls: u, nest: w, wrap: x, html: v, update: t }; e && a.extend(c, e, { nodes: [], parent: d }); if (g) { c.tmpl = g; c._ctnt = c._ctnt || c.tmpl(a, c); c.key = ++i; (l.length ? f : b)[i] = c } return c } a.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function (f, d) { a.fn[f] = function (n) { var g = [], i = a(n), k, h, m, l, j = this.length === 1 && this[0].parentNode; e = b || {}; if (j && j.nodeType === 11 && j.childNodes.length === 1 && i.length === 1) { i[d](this[0]); g = this } else { for (h = 0, m = i.length; h < m; h++) { c = h; k = (h > 0 ? this.clone(true) : this).get(); a(i[h])[d](k); g = g.concat(k) } c = 0; g = this.pushStack(g, f, i.selector) } l = e; e = null; a.tmpl.complete(l); return g } }); a.fn.extend({ tmpl: function (d, c, b) { return a.tmpl(this[0], d, c, b) }, tmplItem: function () { return a.tmplItem(this[0]) }, template: function (b) { return a.template(b, this[0]) }, domManip: function (d, m, k) { if (d[0] && a.isArray(d[0])) { var g = a.makeArray(arguments), h = d[0], j = h.length, i = 0, f; while (i < j && !(f = a.data(h[i++], "tmplItem"))); if (f && c) g[2] = function (b) { a.tmpl.afterManip(this, b, k) }; r.apply(this, g) } else r.apply(this, arguments); c = 0; !e && a.tmpl.complete(b); return this } }); a.extend({ tmpl: function (d, h, e, c) { var i, k = !c; if (k) { c = p; d = a.template[d] || a.template(null, d); f = {} } else if (!d) { d = c.tmpl; b[c.key] = c; c.nodes = []; c.wrapped && n(c, c.wrapped); return a(j(c, null, c.tmpl(a, c))) } if (!d) return []; if (typeof h === "function") h = h.call(c || {}); e && e.wrapped && n(e, e.wrapped); i = a.isArray(h) ? a.map(h, function (a) { return a ? g(e, c, d, a) : null }) : [g(e, c, d, h)]; return k ? a(j(c, null, i)) : i }, tmplItem: function (b) { var c; if (b instanceof a) b = b[0]; while (b && b.nodeType === 1 && !(c = a.data(b, "tmplItem")) && (b = b.parentNode)); return c || p }, template: function (c, b) { if (b) { if (typeof b === "string") b = o(b); else if (b instanceof a) b = b[0] || {}; if (b.nodeType) b = a.data(b, "tmpl") || a.data(b, "tmpl", o(b.innerHTML)); return typeof c === "string" ? (a.template[c] = b) : b } return c ? typeof c !== "string" ? a.template(null, c) : a.template[c] || a.template(null, q.test(c) ? c : a(c)) : null }, encode: function (a) { return ("" + a).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;") } }); a.extend(a.tmpl, { tag: { tmpl: { _default: { $2: "null" }, open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" }, wrap: { _default: { $2: "null" }, open: "$item.calls(_,$1,$2);_=[];", close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" }, each: { _default: { $2: "$index, $value" }, open: "if($notnull_1){$.each($1a,function($2){with(this){", close: "}});}" }, "if": { open: "if(($notnull_1) && $1a){", close: "}" }, "else": { _default: { $1: "true" }, open: "}else if(($notnull_1) && $1a){" }, html: { open: "if($notnull_1){_.push($1a);}" }, "=": { _default: { $1: "$data" }, open: "if($notnull_1){_.push($.encode($1a));}" }, "!": { open: ""} }, complete: function () { b = {} }, afterManip: function (f, b, d) { var e = b.nodeType === 11 ? a.makeArray(b.childNodes) : b.nodeType === 1 ? [b] : []; d.call(f, b); m(e); c++ } }); function j(e, g, f) { var b, c = f ? a.map(f, function (a) { return typeof a === "string" ? e.key ? a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + d + '="' + e.key + '" $2') : a : j(a, e, a._ctnt) }) : e; if (g) return c; c = c.join(""); c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function (f, c, e, d) { b = a(e).get(); m(b); if (c) b = k(c).concat(b); if (d) b = b.concat(k(d)) }); return b ? b : k(c) } function k(c) { var b = document.createElement("div"); b.innerHTML = c; return a.makeArray(b.childNodes) } function o(b) { return new Function("jQuery", "$item", "var $=jQuery,call,_=[],$data=$item.data;with($data){_.push('" + a.trim(b).replace(/([\\'])/g, "\\$1").replace(/[\r\t\n]/g, " ").replace(/\$\{([^\}]*)\}/g, "{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, function (m, l, k, d, b, c, e) { var j = a.tmpl.tag[k], i, f, g; if (!j) throw "Template command not found: " + k; i = j._default || []; if (c && !/\w$/.test(b)) { b += c; c = "" } if (b) { b = h(b); e = e ? "," + h(e) + ")" : c ? ")" : ""; f = c ? b.indexOf(".") > -1 ? b + h(c) : "(" + b + ").call($item" + e : b; g = c ? f : "(typeof(" + b + ")==='function'?(" + b + ").call($item):(" + b + "))" } else g = f = i.$1 || "null"; d = h(d); return "');" + j[l ? "close" : "open"].split("$notnull_1").join(b ? "typeof(" + b + ")!=='undefined' && (" + b + ")!=null" : "true").split("$1a").join(g).split("$1").join(f).split("$2").join(d ? d.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g, function (d, c, b, a) { a = a ? "," + a + ")" : b ? ")" : ""; return a ? "(" + c + ").call($item" + a : d }) : i.$2 || "") + "_.push('" }) + "');}return _;") } function n(c, b) { c._wrap = j(c, true, a.isArray(b) ? b : [q.test(b) ? b : a(b).html()]).join("") } function h(a) { return a ? a.replace(/\\'/g, "'").replace(/\\\\/g, "\\") : null } function s(b) { var a = document.createElement("div"); a.appendChild(b.cloneNode(true)); return a.innerHTML } function m(o) { var n = "_" + c, k, j, l = {}, e, p, h; for (e = 0, p = o.length; e < p; e++) { if ((k = o[e]).nodeType !== 1) continue; j = k.getElementsByTagName("*"); for (h = j.length - 1; h >= 0; h--) m(j[h]); m(k) } function m(j) { var p, h = j, k, e, m; if (m = j.getAttribute(d)) { while (h.parentNode && (h = h.parentNode).nodeType === 1 && !(p = h.getAttribute(d))); if (p !== m) { h = h.parentNode ? h.nodeType === 11 ? 0 : h.getAttribute(d) || 0 : 0; if (!(e = b[m])) { e = f[m]; e = g(e, b[h] || f[h]); e.key = ++i; b[i] = e } c && o(m) } j.removeAttribute(d) } else if (c && (e = a.data(j, "tmplItem"))) { o(e.key); b[e.key] = e; h = a.data(j.parentNode, "tmplItem"); h = h ? h.key : 0 } if (e) { k = e; while (k && k.key != h) { k.nodes.push(j); k = k.parent } delete e._ctnt; delete e._wrap; a.data(j, "tmplItem", e) } function o(a) { a = a + n; e = l[a] = l[a] || g(e, b[e.parent.key + n] || e.parent) } } } function u(a, d, c, b) { if (!a) return l.pop(); l.push({ _: a, tmpl: d, item: this, data: c, options: b }) } function w(d, c, b) { return a.tmpl(a.template(d), c, b, this) } function x(b, d) { var c = b.options || {}; c.wrapped = d; return a.tmpl(a.template(b.tmpl), b.data, c, b.item) } function v(d, c) { var b = this._wrap; return a.map(a(a.isArray(b) ? b.join("") : b).filter(d || "*"), function (a) { return c ? a.innerText || a.textContent : a.outerHTML || s(a) }) } function t() { var b = this.nodes; a.tmpl(null, null, null, this).insertBefore(b[0]); a(b).remove() } })(jQuery);
(function() {
  (function($) {
    return $.fn.liveEdit = function(selector, options) {
      this.on('dblclick', selector, function() {
        var $this, textInput;
        $this = $(this);
        if ($this.is("input")) {
          return;
        }
        textInput = $("<input/>", {
          "class": $this.attr("class"),
          "data-origType": this.tagName,
          id: $this.attr("id") || null,
          type: "text",
          value: $.trim($this.text())
        });
        $this.replaceWith(textInput);
        return textInput.focus().select();
      });
      this.on('blur keydown', selector, function(event) {
        var $this, newElement, text;
        if (event.type === "keydown") {
          if (!(event.which === 13 || event.which === 9)) {
            return;
          }
        }
        $this = $(this);
        if ($this.attr("data-removed")) {
          return;
        }
        if (!$this.is("input")) {
          return;
        }
        $this.attr("data-removed", true);
        text = $this.val();
        newElement = $("<" + $this.attr("data-origType") + " />", {
          "class": $this.attr("class"),
          id: $this.attr("id") || null,
          text: text
        });
        $this.replaceWith(newElement);
        if (options.change) {
          return options.change(newElement, text);
        }
      });
      return this;
    };
  })(jQuery);
}).call(this);
(function() {
  (function($) {
    var defaults;
    $.event.fix = (function(originalFix) {
      return function(event) {
        event = originalFix.apply(this, arguments);
        if (event.type.indexOf('drag') === 0 || event.type.indexOf('drop') === 0) {
          event.dataTransfer = event.originalEvent.dataTransfer;
        }
        return event;
      };
    })($.event.fix);
    defaults = {
      callback: $.noop,
      matchType: /image.*/
    };
    return $.fn.dropImageReader = function(options) {
      var stopFn;
      if (typeof options === "function") {
        options = {
          callback: options
        };
      }
      options = $.extend({}, defaults, options);
      stopFn = function(event) {
        event.stopPropagation();
        return event.preventDefault();
      };
      return this.each(function() {
        var $this, element;
        element = this;
        $this = $(this);
        $this.bind('dragenter dragover dragleave', stopFn);
        return $this.bind('drop', function(event) {
          stopFn(event);
          return Array.prototype.forEach.call(event.dataTransfer.files, function(file) {
            var reader;
            if (!file.type.match(options.matchType)) {
              return;
            }
            reader = new FileReader();
            reader.onload = function(evt) {
              return options.callback.call(element, file, evt);
            };
            return reader.readAsDataURL(file);
          });
        });
      });
    };
  })(jQuery);
}).call(this);
(function() {
  (function($) {
    var defaults;
    $.event.fix = (function(originalFix) {
      return function(event) {
        event = originalFix.apply(this, arguments);
        if (event.type.indexOf('copy') === 0 || event.type.indexOf('paste') === 0) {
          event.clipboardData = event.originalEvent.clipboardData;
        }
        return event;
      };
    })($.event.fix);
    defaults = {
      callback: $.noop,
      matchType: /image.*/
    };
    return $.fn.pasteImageReader = function(options) {
      if (typeof options === "function") {
        options = {
          callback: options
        };
      }
      options = $.extend({}, defaults, options);
      return this.each(function() {
        var $this, element;
        element = this;
        $this = $(this);
        return $this.bind('paste', function(event) {
          var clipboardData, found;
          found = false;
          clipboardData = event.clipboardData;
          return Array.prototype.forEach.call(clipboardData.types, function(type, i) {
            var file, reader;
            if (found) {
              return;
            }
            if (!type.match(options.matchType)) {
              return;
            }
            file = clipboardData.items[i].getAsFile();
            reader = new FileReader();
            reader.onload = function(evt) {
              return options.callback.call(element, file, evt);
            };
            reader.readAsDataURL(file);
            return found = true;
          });
        });
      });
    };
  })(jQuery);
}).call(this);
/*
 * jQuery Pines Notify (pnotify) Plugin 1.0.1
 *
 * Copyright (c) 2009 Hunter Perrin
 *
 * Licensed (along with all of Pines) under the GNU Affero GPL:
 *	  http://www.gnu.org/licenses/agpl.html
 */

(function(e){var q,m,k,n;e.extend({pnotify_remove_all:function(){var g=k.data("pnotify");g&&g.length&&e.each(g,function(){this.pnotify_remove&&this.pnotify_remove()})},pnotify_position_all:function(){m&&clearTimeout(m);m=null;var g=k.data("pnotify");if(g&&g.length){e.each(g,function(){var c=this.opts.pnotify_stack;if(c){if(!c.nextpos1)c.nextpos1=c.firstpos1;if(!c.nextpos2)c.nextpos2=c.firstpos2;if(!c.addpos2)c.addpos2=0;if(this.css("display")!="none"){var a,j,i={},b;switch(c.dir1){case "down":b="top";
break;case "up":b="bottom";break;case "left":b="right";break;case "right":b="left";break}a=parseInt(this.css(b));if(isNaN(a))a=0;if(typeof c.firstpos1=="undefined"){c.firstpos1=a;c.nextpos1=c.firstpos1}var h;switch(c.dir2){case "down":h="top";break;case "up":h="bottom";break;case "left":h="right";break;case "right":h="left";break}j=parseInt(this.css(h));if(isNaN(j))j=0;if(typeof c.firstpos2=="undefined"){c.firstpos2=j;c.nextpos2=c.firstpos2}if(c.dir1=="down"&&c.nextpos1+this.height()>n.height()||
c.dir1=="up"&&c.nextpos1+this.height()>n.height()||c.dir1=="left"&&c.nextpos1+this.width()>n.width()||c.dir1=="right"&&c.nextpos1+this.width()>n.width()){c.nextpos1=c.firstpos1;c.nextpos2+=c.addpos2+10;c.addpos2=0}if(c.animation&&c.nextpos2<j)switch(c.dir2){case "down":i.top=c.nextpos2+"px";break;case "up":i.bottom=c.nextpos2+"px";break;case "left":i.right=c.nextpos2+"px";break;case "right":i.left=c.nextpos2+"px";break}else this.css(h,c.nextpos2+"px");switch(c.dir2){case "down":case "up":if(this.outerHeight(true)>
c.addpos2)c.addpos2=this.height();break;case "left":case "right":if(this.outerWidth(true)>c.addpos2)c.addpos2=this.width();break}if(c.nextpos1)if(c.animation&&(a>c.nextpos1||i.top||i.bottom||i.right||i.left))switch(c.dir1){case "down":i.top=c.nextpos1+"px";break;case "up":i.bottom=c.nextpos1+"px";break;case "left":i.right=c.nextpos1+"px";break;case "right":i.left=c.nextpos1+"px";break}else this.css(b,c.nextpos1+"px");if(i.top||i.bottom||i.right||i.left)this.animate(i,{duration:500,queue:false});switch(c.dir1){case "down":case "up":c.nextpos1+=
this.height()+10;break;case "left":case "right":c.nextpos1+=this.width()+10;break}}}});e.each(g,function(){var c=this.opts.pnotify_stack;if(c){c.nextpos1=c.firstpos1;c.nextpos2=c.firstpos2;c.addpos2=0;c.animation=true}})}},pnotify:function(g){k||(k=e("body"));n||(n=e(window));var c,a;if(typeof g!="object"){a=e.extend({},e.pnotify.defaults);a.pnotify_text=g}else a=e.extend({},e.pnotify.defaults,g);if(a.pnotify_before_init)if(a.pnotify_before_init(a)===false)return null;var j,i=function(d,f){b.css("display",
"none");var o=document.elementFromPoint(d.clientX,d.clientY);b.css("display","block");var r=e(o),s=r.css("cursor");b.css("cursor",s!="auto"?s:"default");if(!j||j.get(0)!=o){if(j){p.call(j.get(0),"mouseleave",d.originalEvent);p.call(j.get(0),"mouseout",d.originalEvent)}p.call(o,"mouseenter",d.originalEvent);p.call(o,"mouseover",d.originalEvent)}p.call(o,f,d.originalEvent);j=r},b=e("<div />",{"class":"ui-pnotify "+a.pnotify_addclass,css:{display:"none"},mouseenter:function(d){a.pnotify_nonblock&&d.stopPropagation();
if(a.pnotify_mouse_reset&&c=="out"){b.stop(true);c="in";b.css("height","auto").animate({width:a.pnotify_width,opacity:a.pnotify_nonblock?a.pnotify_nonblock_opacity:a.pnotify_opacity},"fast")}a.pnotify_nonblock&&b.animate({opacity:a.pnotify_nonblock_opacity},"fast");a.pnotify_hide&&a.pnotify_mouse_reset&&b.pnotify_cancel_remove();a.pnotify_closer&&!a.pnotify_nonblock&&b.closer.show()},mouseleave:function(d){a.pnotify_nonblock&&d.stopPropagation();j=null;b.css("cursor","auto");a.pnotify_nonblock&&c!=
"out"&&b.animate({opacity:a.pnotify_opacity},"fast");a.pnotify_hide&&a.pnotify_mouse_reset&&b.pnotify_queue_remove();b.closer.hide();e.pnotify_position_all()},mouseover:function(d){a.pnotify_nonblock&&d.stopPropagation()},mouseout:function(d){a.pnotify_nonblock&&d.stopPropagation()},mousemove:function(d){if(a.pnotify_nonblock){d.stopPropagation();i(d,"onmousemove")}},mousedown:function(d){if(a.pnotify_nonblock){d.stopPropagation();d.preventDefault();i(d,"onmousedown")}},mouseup:function(d){if(a.pnotify_nonblock){d.stopPropagation();
d.preventDefault();i(d,"onmouseup")}},click:function(d){if(a.pnotify_nonblock){d.stopPropagation();i(d,"onclick")}},dblclick:function(d){if(a.pnotify_nonblock){d.stopPropagation();i(d,"ondblclick")}}});b.opts=a;if(a.pnotify_shadow&&!e.browser.msie)b.shadow_container=e("<div />",{"class":"ui-widget-shadow ui-corner-all ui-pnotify-shadow"}).prependTo(b);b.container=e("<div />",{"class":"ui-widget ui-widget-content ui-corner-all ui-pnotify-container "+(a.pnotify_type=="error"?"ui-state-error":"ui-state-highlight")}).appendTo(b);
b.pnotify_version="1.0.1";b.pnotify=function(d){var f=a;if(typeof d=="string")a.pnotify_text=d;else a=e.extend({},a,d);b.opts=a;if(a.pnotify_shadow!=f.pnotify_shadow)if(a.pnotify_shadow&&!e.browser.msie)b.shadow_container=e("<div />",{"class":"ui-widget-shadow ui-pnotify-shadow"}).prependTo(b);else b.children(".ui-pnotify-shadow").remove();if(a.pnotify_addclass===false)b.removeClass(f.pnotify_addclass);else a.pnotify_addclass!==f.pnotify_addclass&&b.removeClass(f.pnotify_addclass).addClass(a.pnotify_addclass);
if(a.pnotify_title===false)b.title_container.hide("fast");else a.pnotify_title!==f.pnotify_title&&b.title_container.html(a.pnotify_title).show(200);if(a.pnotify_text===false)b.text_container.hide("fast");else if(a.pnotify_text!==f.pnotify_text){if(a.pnotify_insert_brs)a.pnotify_text=a.pnotify_text.replace(/\n/g,"<br />");b.text_container.html(a.pnotify_text).show(200)}b.pnotify_history=a.pnotify_history;a.pnotify_type!=f.pnotify_type&&b.container.toggleClass("ui-state-error ui-state-highlight");if(a.pnotify_notice_icon!=
f.pnotify_notice_icon&&a.pnotify_type=="notice"||a.pnotify_error_icon!=f.pnotify_error_icon&&a.pnotify_type=="error"||a.pnotify_type!=f.pnotify_type){b.container.find("div.ui-pnotify-icon").remove();if(a.pnotify_error_icon&&a.pnotify_type=="error"||a.pnotify_notice_icon)e("<div />",{"class":"ui-pnotify-icon"}).append(e("<span />",{"class":a.pnotify_type=="error"?a.pnotify_error_icon:a.pnotify_notice_icon})).prependTo(b.container)}a.pnotify_width!==f.pnotify_width&&b.animate({width:a.pnotify_width});
a.pnotify_min_height!==f.pnotify_min_height&&b.container.animate({minHeight:a.pnotify_min_height});a.pnotify_opacity!==f.pnotify_opacity&&b.fadeTo(a.pnotify_animate_speed,a.pnotify_opacity);if(a.pnotify_hide)f.pnotify_hide||b.pnotify_queue_remove();else b.pnotify_cancel_remove();b.pnotify_queue_position();return b};b.pnotify_queue_position=function(){m&&clearTimeout(m);m=setTimeout(e.pnotify_position_all,10)};b.pnotify_display=function(){b.parent().length||b.appendTo(k);if(a.pnotify_before_open)if(a.pnotify_before_open(b)===
false)return;b.pnotify_queue_position();if(a.pnotify_animation=="fade"||a.pnotify_animation.effect_in=="fade")b.show().fadeTo(0,0).hide();else a.pnotify_opacity!=1&&b.show().fadeTo(0,a.pnotify_opacity).hide();b.animate_in(function(){a.pnotify_after_open&&a.pnotify_after_open(b);b.pnotify_queue_position();a.pnotify_hide&&b.pnotify_queue_remove()})};b.pnotify_remove=function(){if(b.timer){window.clearTimeout(b.timer);b.timer=null}if(a.pnotify_before_close)if(a.pnotify_before_close(b)===false)return;
b.animate_out(function(){if(a.pnotify_after_close)if(a.pnotify_after_close(b)===false)return;b.pnotify_queue_position();a.pnotify_remove&&b.detach()})};b.animate_in=function(d){c="in";var f;f=typeof a.pnotify_animation.effect_in!="undefined"?a.pnotify_animation.effect_in:a.pnotify_animation;if(f=="none"){b.show();d()}else if(f=="show")b.show(a.pnotify_animate_speed,d);else if(f=="fade")b.show().fadeTo(a.pnotify_animate_speed,a.pnotify_opacity,d);else if(f=="slide")b.slideDown(a.pnotify_animate_speed,
d);else if(typeof f=="function")f("in",d,b);else b.effect&&b.effect(f,{},a.pnotify_animate_speed,d)};b.animate_out=function(d){c="out";var f;f=typeof a.pnotify_animation.effect_out!="undefined"?a.pnotify_animation.effect_out:a.pnotify_animation;if(f=="none"){b.hide();d()}else if(f=="show")b.hide(a.pnotify_animate_speed,d);else if(f=="fade")b.fadeOut(a.pnotify_animate_speed,d);else if(f=="slide")b.slideUp(a.pnotify_animate_speed,d);else if(typeof f=="function")f("out",d,b);else b.effect&&b.effect(f,
{},a.pnotify_animate_speed,d)};b.pnotify_cancel_remove=function(){b.timer&&window.clearTimeout(b.timer)};b.pnotify_queue_remove=function(){b.pnotify_cancel_remove();b.timer=window.setTimeout(function(){b.pnotify_remove()},isNaN(a.pnotify_delay)?0:a.pnotify_delay)};b.closer=e("<div />",{"class":"ui-pnotify-closer",css:{cursor:"pointer",display:"none"},click:function(){b.pnotify_remove();b.closer.hide()}}).append(e("<span />",{"class":"ui-icon ui-icon-circle-close"})).appendTo(b.container);if(a.pnotify_error_icon&&
a.pnotify_type=="error"||a.pnotify_notice_icon)e("<div />",{"class":"ui-pnotify-icon"}).append(e("<span />",{"class":a.pnotify_type=="error"?a.pnotify_error_icon:a.pnotify_notice_icon})).appendTo(b.container);b.title_container=e("<div />",{"class":"ui-pnotify-title",html:a.pnotify_title}).appendTo(b.container);a.pnotify_title===false&&b.title_container.hide();if(a.pnotify_insert_brs&&typeof a.pnotify_text=="string")a.pnotify_text=a.pnotify_text.replace(/\n/g,"<br />");b.text_container=e("<div />",
{"class":"ui-pnotify-text",html:a.pnotify_text}).appendTo(b.container);a.pnotify_text===false&&b.text_container.hide();typeof a.pnotify_width=="string"&&b.css("width",a.pnotify_width);typeof a.pnotify_min_height=="string"&&b.container.css("min-height",a.pnotify_min_height);b.pnotify_history=a.pnotify_history;var h=k.data("pnotify");if(h==null||typeof h!="object")h=[];h=a.pnotify_stack.push=="top"?e.merge([b],h):e.merge(h,[b]);k.data("pnotify",h);a.pnotify_after_init&&a.pnotify_after_init(b);if(a.pnotify_history){var l=
k.data("pnotify_history");if(typeof l=="undefined"){l=e("<div />",{"class":"ui-pnotify-history-container ui-state-default ui-corner-bottom",mouseleave:function(){l.animate({top:"-"+q+"px"},{duration:100,queue:false})}}).append(e("<div />",{"class":"ui-pnotify-history-header",text:"Redisplay"})).append(e("<button />",{"class":"ui-pnotify-history-all ui-state-default ui-corner-all",text:"All",mouseenter:function(){e(this).addClass("ui-state-hover")},mouseleave:function(){e(this).removeClass("ui-state-hover")},
click:function(){e.each(h,function(){this.pnotify_history&&this.pnotify_display&&this.pnotify_display()});return false}})).append(e("<button />",{"class":"ui-pnotify-history-last ui-state-default ui-corner-all",text:"Last",mouseenter:function(){e(this).addClass("ui-state-hover")},mouseleave:function(){e(this).removeClass("ui-state-hover")},click:function(){for(var d=1;!h[h.length-d]||!h[h.length-d].pnotify_history||h[h.length-d].is(":visible");){if(h.length-d===0)return false;d++}d=h[h.length-d];
d.pnotify_display&&d.pnotify_display();return false}})).appendTo(k);q=e("<span />",{"class":"ui-pnotify-history-pulldown ui-icon ui-icon-grip-dotted-horizontal",mouseenter:function(){l.animate({top:"0"},{duration:100,queue:false})}}).appendTo(l).offset().top+2;l.css({top:"-"+q+"px"});k.data("pnotify_history",l)}}a.pnotify_stack.animation=false;b.pnotify_display();return b}});var t=/^on/,u=/^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/,v=/^(focus|blur|select|change|reset)$|^key(press|down|up)$/,
w=/^(scroll|resize|(un)?load|abort|error)$/,p=function(g,c){var a;g=g.toLowerCase();if(document.createEvent&&this.dispatchEvent){g=g.replace(t,"");if(g.match(u)){e(this).offset();a=document.createEvent("MouseEvents");a.initMouseEvent(g,c.bubbles,c.cancelable,c.view,c.detail,c.screenX,c.screenY,c.clientX,c.clientY,c.ctrlKey,c.altKey,c.shiftKey,c.metaKey,c.button,c.relatedTarget)}else if(g.match(v)){a=document.createEvent("UIEvents");a.initUIEvent(g,c.bubbles,c.cancelable,c.view,c.detail)}else if(g.match(w)){a=
document.createEvent("HTMLEvents");a.initEvent(g,c.bubbles,c.cancelable)}a&&this.dispatchEvent(a)}else{g.match(t)||(g="on"+g);a=document.createEventObject(c);this.fireEvent(g,a)}};e.pnotify.defaults={pnotify_title:false,pnotify_text:false,pnotify_addclass:"",pnotify_nonblock:false,pnotify_nonblock_opacity:0.2,pnotify_history:true,pnotify_width:"300px",pnotify_min_height:"16px",pnotify_type:"notice",pnotify_notice_icon:"ui-icon ui-icon-info",pnotify_error_icon:"ui-icon ui-icon-alert",pnotify_animation:"fade",
pnotify_animate_speed:"slow",pnotify_opacity:1,pnotify_shadow:false,pnotify_closer:true,pnotify_hide:true,pnotify_delay:8E3,pnotify_mouse_reset:true,pnotify_remove:true,pnotify_insert_brs:true,pnotify_stack:{dir1:"down",dir2:"left",push:"bottom"}}})(jQuery);
(function() {
  (function($) {
    var events, hiddenFields, shouldHide;
    events = ["create", "step", "update", "destroy"];
    hiddenFields = events.eachWithObject([], function(event, array) {
      return array.push(event, event + "Coffee");
    });
    shouldHide = function(key, value) {
      return hiddenFields.include(key) || $.isFunction(value);
    };
    return $.fn.propertyEditor = function(properties) {
      var addBlurEvents, addNestedRow, addRow, element, fireChangedEvent, object, rowCheck;
      properties || (properties = {});
      object = properties;
      element = this.eq(0);
      element.addClass("properties");
      element.getProps = function() {
        return object;
      };
      element.setProps = function(properties) {
        var key, propertiesArray, value;
        properties || (properties = {});
        object = properties;
        element.html('');
        if (properties) {
          propertiesArray = [];
          for (key in properties) {
            value = properties[key];
            propertiesArray.push([key, value]);
          }
          propertiesArray.sort().each(function(pair) {
            key = pair[0], value = pair[1];
            if (shouldHide(key, value)) {} else if (key.match(/color/i)) {
              return addRow(key, value).find('td:last input').colorPicker({
                leadingHash: true
              });
            } else if (Object.isObject(value)) {
              return addNestedRow(key, value);
            } else if (value != null ? typeof value.match === "function" ? value.match(/^data:image\//) : void 0 : void 0) {
              return addRow(key, value).find('td:last input').modalPixelEditor(properties);
            } else {
              return addRow(key, value);
            }
          });
        }
        addRow('', '');
        return element;
      };
      rowCheck = function() {
        var input;
        if ((input = element.find("tr").last().find("input").first()).length) {
          if (input.val()) {
            return addRow('', '');
          }
        } else {
          return addRow('', '');
        }
      };
      fireChangedEvent = function() {
        try {
          return element.trigger("change", [object]);
        } catch (error) {
          return typeof console !== "undefined" && console !== null ? typeof console.error === "function" ? console.error(error) : void 0 : void 0;
        }
      };
      addBlurEvents = function(keyInput, valueInput) {
        keyInput.blur(function() {
          var currentName, previousName;
          currentName = keyInput.val();
          previousName = keyInput.data("previousName");
          if (currentName !== previousName) {
            keyInput.data("previousName", currentName);
            delete object[previousName];
            if (currentName.blank()) {
              return;
            }
            object[currentName] = valueInput.val();
            fireChangedEvent();
            return rowCheck();
          }
        });
        return valueInput.blur(function() {
          var currentValue, key, previousValue;
          currentValue = valueInput.val().parse();
          previousValue = valueInput.data("previousValue");
          if (currentValue !== previousValue) {
            if (!(key = keyInput.val())) {
              return;
            }
            valueInput.data("previousValue", currentValue);
            object[key] = currentValue;
            fireChangedEvent();
            return rowCheck();
          }
        });
      };
      addRow = function(key, value, options) {
        var keyInput, row, valueInput, valueInputType;
        if (options == null) {
          options = {};
        }
        row = $("<tr>");
        keyInput = $("<input>", {
          "class": "key",
          data: {
            previousName: key
          },
          type: "text",
          placeholder: "key",
          value: key
        }).appendTo($("<td>").appendTo(row));
        if (!(typeof value === "string" || typeof value === "number")) {
          value = JSON.stringify(value);
        }
        valueInputType = options.valueInputType || "input";
        valueInput = $("<" + valueInputType + ">", {
          "class": "value",
          data: {
            previousValue: value
          },
          type: "text",
          placeholder: "value",
          value: value
        }).appendTo($("<td>").appendTo(row));
        addBlurEvents(keyInput, valueInput);
        return row.appendTo(element);
      };
      addNestedRow = function(key, value) {
        var cell, nestedEditor, row;
        row = $("<tr>");
        cell = $("<td colspan='2'>").appendTo(row);
        $("<label>", {
          text: key
        }).appendTo(cell);
        nestedEditor = $("<table>", {
          "class": "nested"
        }).appendTo(cell).propertyEditor(value);
        nestedEditor.bind("change", function(event, changedNestedObject) {
          event.stopPropagation();
          return fireChangedEvent();
        });
        return row.appendTo(element);
      };
      return element.setProps(properties);
    };
  })(jQuery);
}).call(this);
(function() {
  var __slice = Array.prototype.slice;
  (function($) {
    return $.fn.powerCanvas = function(options) {
      var $canvas, canvas, context;
      options || (options = {});
      canvas = this.get(0);
      context = void 0;
      /**
      * PowerCanvas provides a convenient wrapper for working with Context2d.
      * @name PowerCanvas
      * @constructor
      */
      $canvas = $(canvas).extend({
        /**
         * Passes this canvas to the block with the given matrix transformation
         * applied. All drawing methods called within the block will draw
         * into the canvas with the transformation applied. The transformation
         * is removed at the end of the block, even if the block throws an error.
         *
         * @name withTransform
         * @methodOf PowerCanvas#
         *
         * @param {Matrix} matrix
         * @param {Function} block
         * @returns this
        */
        withTransform: function(matrix, block) {
          context.save();
          context.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
          try {
            block(this);
          } finally {
            context.restore();
          }
          return this;
        },
        clear: function() {
          context.clearRect(0, 0, canvas.width, canvas.height);
          return this;
        },
        clearRect: function(x, y, width, height) {
          context.clearRect(x, y, width, height);
          return this;
        },
        context: function() {
          return context;
        },
        element: function() {
          return canvas;
        },
        globalAlpha: function(newVal) {
          if (newVal != null) {
            context.globalAlpha = newVal;
            return this;
          } else {
            return context.globalAlpha;
          }
        },
        compositeOperation: function(newVal) {
          if (newVal != null) {
            context.globalCompositeOperation = newVal;
            return this;
          } else {
            return context.globalCompositeOperation;
          }
        },
        createLinearGradient: function(x0, y0, x1, y1) {
          return context.createLinearGradient(x0, y0, x1, y1);
        },
        createRadialGradient: function(x0, y0, r0, x1, y1, r1) {
          return context.createRadialGradient(x0, y0, r0, x1, y1, r1);
        },
        buildRadialGradient: function(c1, c2, stops) {
          var color, gradient, position;
          gradient = context.createRadialGradient(c1.x, c1.y, c1.radius, c2.x, c2.y, c2.radius);
          for (position in stops) {
            color = stops[position];
            gradient.addColorStop(position, color);
          }
          return gradient;
        },
        createPattern: function(image, repitition) {
          return context.createPattern(image, repitition);
        },
        drawImage: function(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) {
          context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
          return this;
        },
        drawLine: function(x1, y1, x2, y2, width) {
          if (arguments.length === 3) {
            width = x2;
            x2 = y1.x;
            y2 = y1.y;
            y1 = x1.y;
            x1 = x1.x;
          }
          width || (width = 3);
          context.lineWidth = width;
          context.beginPath();
          context.moveTo(x1, y1);
          context.lineTo(x2, y2);
          context.closePath();
          context.stroke();
          return this;
        },
        fill: function(color) {
          $canvas.fillColor(color);
          context.fillRect(0, 0, canvas.width, canvas.height);
          return this;
        },
        /**
         * Fills a circle at the specified position with the specified
         * radius and color.
         *
         * @name fillCircle
         * @methodOf PowerCanvas#
         *
         * @param {Number} x
         * @param {Number} y
         * @param {Number} radius
         * @param {Number} color
         * @see PowerCanvas#fillColor
         * @returns this
        */
        fillCircle: function(x, y, radius, color) {
          $canvas.fillColor(color);
          context.beginPath();
          context.arc(x, y, radius, 0, Math.TAU, true);
          context.closePath();
          context.fill();
          return this;
        },
        /**
         * Fills a rectangle with the current fillColor
         * at the specified position with the specified
         * width and height
        
         * @name fillRect
         * @methodOf PowerCanvas#
         *
         * @param {Number} x
         * @param {Number} y
         * @param {Number} width
         * @param {Number} height
         * @see PowerCanvas#fillColor
         * @returns this
        */
        fillRect: function(x, y, width, height) {
          context.fillRect(x, y, width, height);
          return this;
        },
        fillShape: function() {
          var points;
          points = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          context.beginPath();
          points.each(function(point, i) {
            if (i === 0) {
              return context.moveTo(point.x, point.y);
            } else {
              return context.lineTo(point.x, point.y);
            }
          });
          context.lineTo(points[0].x, points[0].y);
          return context.fill();
        },
        /**
        * Adapted from http://js-bits.blogspot.com/2010/07/canvas-rounded-corner-rectangles.html
        */
        fillRoundRect: function(x, y, width, height, radius, strokeWidth) {
          radius || (radius = 5);
          context.beginPath();
          context.moveTo(x + radius, y);
          context.lineTo(x + width - radius, y);
          context.quadraticCurveTo(x + width, y, x + width, y + radius);
          context.lineTo(x + width, y + height - radius);
          context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
          context.lineTo(x + radius, y + height);
          context.quadraticCurveTo(x, y + height, x, y + height - radius);
          context.lineTo(x, y + radius);
          context.quadraticCurveTo(x, y, x + radius, y);
          context.closePath();
          if (strokeWidth) {
            context.lineWidth = strokeWidth;
            context.stroke();
          }
          context.fill();
          return this;
        },
        fillText: function(text, x, y) {
          context.fillText(text, x, y);
          return this;
        },
        centerText: function(text, y) {
          var textWidth;
          textWidth = $canvas.measureText(text);
          return $canvas.fillText(text, (canvas.width - textWidth) / 2, y);
        },
        fillWrappedText: function(text, x, y, width) {
          var lineHeight, tokens, tokens2;
          tokens = text.split(" ");
          tokens2 = text.split(" ");
          lineHeight = 16;
          if ($canvas.measureText(text) > width) {
            if (tokens.length % 2 === 0) {
              tokens2 = tokens.splice(tokens.length / 2, tokens.length / 2, "");
            } else {
              tokens2 = tokens.splice(tokens.length / 2 + 1, (tokens.length / 2) + 1, "");
            }
            context.fillText(tokens.join(" "), x, y);
            return context.fillText(tokens2.join(" "), x, y + lineHeight);
          } else {
            return context.fillText(tokens.join(" "), x, y + lineHeight);
          }
        },
        fillColor: function(color) {
          if (color) {
            if (color.channels) {
              context.fillStyle = color.toString();
            } else {
              context.fillStyle = color;
            }
            return this;
          } else {
            return context.fillStyle;
          }
        },
        font: function(font) {
          if (font != null) {
            context.font = font;
            return this;
          } else {
            return context.font;
          }
        },
        measureText: function(text) {
          return context.measureText(text).width;
        },
        putImageData: function(imageData, x, y) {
          context.putImageData(imageData, x, y);
          return this;
        },
        strokeColor: function(color) {
          if (color) {
            if (color.channels) {
              context.strokeStyle = color.toString();
            } else {
              context.strokeStyle = color;
            }
            return this;
          } else {
            return context.strokeStyle;
          }
        },
        strokeCircle: function(x, y, radius, color) {
          $canvas.strokeColor(color);
          context.beginPath();
          context.arc(x, y, radius, 0, Math.TAU, true);
          context.closePath();
          context.stroke();
          return this;
        },
        strokeRect: function(x, y, width, height) {
          context.strokeRect(x, y, width, height);
          return this;
        },
        textAlign: function(textAlign) {
          context.textAlign = textAlign;
          return this;
        },
        height: function() {
          return canvas.height;
        },
        width: function() {
          return canvas.width;
        }
      });
      if (canvas != null ? canvas.getContext : void 0) {
        context = canvas.getContext('2d');
        if (options.init) {
          options.init($canvas);
        }
        return $canvas;
      }
    };
  })(jQuery);
}).call(this);
(function() {
  jQuery.fn.serializeObject = function() {
    var arrayData, objectData;
    arrayData = this.serializeArray();
    objectData = {};
    $.each(arrayData, function() {
      var name, object, paths, value;
      name = this.name;
      if (this.value != null) {
        value = this.value;
      } else {
        value = '';
      }
      paths = name.split("[").map(function(e, i) {
        if (i === 0) {
          return e;
        } else {
          return e.substr(0, e.length - 1);
        }
      });
      object = objectData;
      return paths.each(function(key, i) {
        if (key === paths.last()) {
          return object[key] = value;
        } else {
          return object = (object[key] || (object[key] = {}));
        }
      });
    });
    return objectData;
  };
}).call(this);
(function() {
  /*
   tagbox
   adapted from superbly tagfield v0.1
   http://www.superbly.ch
  */  (function($) {
    $.fn.tagbox = function(options) {
      var addItem, inputContainer, inserted, keys, removeItem, tagField, tagInput, tagList, updateTags, _ref;
      inserted = [];
      tagField = this.addClass('tag_container');
      tagList = $("<ul class='tag_list' />");
      inputContainer = $("<li class='input_container' />");
      tagInput = $("<input class='tag_input'>");
      tagField.append(tagList);
      tagList.append(inputContainer);
      inputContainer.append(tagInput);
      updateTags = function() {
        tagInput.focus();
        return tagField.attr('data-tags', inserted.join(','));
      };
      addItem = function(value) {
        if (!inserted.include(value)) {
          inserted.push(value);
          tagInput.parent().before("<li class='tag_item'><span>" + value + "</span><a> x</a></li>");
          tagInput.val("");
          $(tagList.find('.tag_item:last a')).click(function(e) {
            value = $(this).prev().text();
            return removeItem(value);
          });
          return updateTags();
        }
      };
      removeItem = function(value) {
        if (inserted.include(value)) {
          inserted.remove(value);
          tagList.find('.tag_item span').filter(function() {
            return $(this).text() === value;
          }).parent().remove();
          return updateTags();
        }
      };
      if (options != null ? (_ref = options.presets) != null ? _ref.length : void 0 : void 0) {
        options.presets.each(function(item) {
          return addItem(item);
        });
      }
      keys = {
        enter: 13,
        tab: 9,
        backspace: 8
      };
      tagInput.keydown(function(e) {
        var key, value;
        value = $(this).val() || "";
        key = e.which;
        if (key === keys.enter || key === keys.tab) {
          if (!value.blank()) {
            addItem(value.trim());
          }
          if (key === keys.enter) {
            return e.preventDefault();
          }
        } else if (key === keys.backspace) {
          if (value.blank()) {
            return removeItem(inserted.last());
          }
        }
      });
      return $('.tag_container').click(function(e) {
        return tagInput.focus();
      });
    };
    return this;
  })(jQuery);
}).call(this);
(function() {
  (function($) {
    return $.fn.takeClass = function(name) {
      this.addClass(name).siblings().removeClass(name);
      return this;
    };
  })(jQuery);
}).call(this);
// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// released under the MIT license

(function($) {
    function Tipsy(element, options) {
        this.$element = $(element);
        this.options = options;
        this.enabled = true;
        this.fixTitle();
    }

    Tipsy.prototype = {
        show: function() {
            var title = this.getTitle();
            if (title && this.enabled) {
                var $tip = this.tip();

                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);

                var pos = $.extend({}, this.$element.offset(), {
                    width: this.$element[0].offsetWidth,
                    height: this.$element[0].offsetHeight
                });

                var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
                var gravity = (typeof this.options.gravity == 'function')
                                ? this.options.gravity.call(this.$element[0])
                                : this.options.gravity;

                var tp;
                switch (gravity.charAt(0)) {
                    case 'n':
                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 's':
                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 'e':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
                        break;
                    case 'w':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
                        break;
                }

                if (gravity.length == 2) {
                    if (gravity.charAt(1) == 'w') {
                        tp.left = pos.left + pos.width / 2 - 15;
                    } else {
                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
                    }
                }

                $tip.css(tp).addClass('tipsy-' + gravity);

                if (this.options.fade) {
                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
                } else {
                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
                }
            }
        },

        hide: function() {
            if (this.options.fade) {
                this.tip().stop().fadeOut(function() { $(this).remove(); });
            } else {
                this.tip().remove();
            }
        },

        fixTitle: function() {
            var $e = this.$element;
            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
            }
        },

        getTitle: function() {
            var title, $e = this.$element, o = this.options;
            this.fixTitle();
            var title, o = this.options;
            if (typeof o.title == 'string') {
                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
            } else if (typeof o.title == 'function') {
                title = o.title.call($e[0]);
            }
            title = ('' + title).replace(/(^\s*|\s*$)/, "");
            return title || o.fallback;
        },

        tip: function() {
            if (!this.$tip) {
                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
            }
            return this.$tip;
        },

        validate: function() {
            if (!this.$element[0].parentNode) {
                this.hide();
                this.$element = null;
                this.options = null;
            }
        },

        enable: function() { this.enabled = true; },
        disable: function() { this.enabled = false; },
        toggleEnabled: function() { this.enabled = !this.enabled; }
    };

    $.fn.tipsy = function(options) {

        if (options === true) {
            return this.data('tipsy');
        } else if (typeof options == 'string') {
            var tipsy = this.data('tipsy');
            if (tipsy) tipsy[options]();
            return this;
        }

        options = $.extend({}, $.fn.tipsy.defaults, options);

        function get(ele) {
            var tipsy = $.data(ele, 'tipsy');
            if (!tipsy) {
                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
                $.data(ele, 'tipsy', tipsy);
            }
            return tipsy;
        }

        function enter() {
            var tipsy = get(this);
            tipsy.hoverState = 'in';
            if (options.delayIn == 0) {
                tipsy.show();
            } else {
                tipsy.fixTitle();
                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
            }
        };

        function leave() {
            var tipsy = get(this);
            tipsy.hoverState = 'out';
            if (options.delayOut == 0) {
                tipsy.hide();
            } else {
                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
            }
        };

        if (!options.live) this.each(function() { get(this); });

        if (options.trigger != 'manual') {
            var binder   = options.live ? 'live' : 'bind',
                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
            this[binder](eventIn, enter)[binder](eventOut, leave);
        }

        return this;

    };

    $.fn.tipsy.defaults = {
        delayIn: 0,
        delayOut: 0,
        fade: false,
        fallback: '',
        gravity: 'n',
        html: false,
        live: false,
        offset: 0,
        opacity: 0.8,
        title: 'title',
        trigger: 'hover'
    };

    // Overwrite this method to provide options on a per-element basis.
    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
    // (remember - do not modify 'options' in place!)
    $.fn.tipsy.elementOptions = function(ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };

    $.fn.tipsy.autoNS = function() {
        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
    };

    $.fn.tipsy.autoWE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
    };

})(jQuery);
(function() {
  (function($) {
    return $.fn.vectorPicker = function() {
      var RADIUS, SIZE, input, mouseHeld, setVector, showDialog;
      input = this.eq(0);
      SIZE = 126;
      RADIUS = 5;
      mouseHeld = false;
      setVector = function(x, y) {
        var xTranslate, yTranslate, _ref;
        _ref = [x, y].map(function(value) {
          return ((value - SIZE / 2) / 5).round();
        }), xTranslate = _ref[0], yTranslate = _ref[1];
        input.val(JSON.stringify({
          x: xTranslate,
          y: yTranslate
        }));
        return $('.unit_circle').css({
          backgroundPosition: "" + (x - RADIUS) + "px " + (y - RADIUS) + "px"
        });
      };
      showDialog = function() {
        var dialog, height, offset;
        dialog = $('<div />', {
          "class": "vector_picker"
        });
        $('<div class="unit_circle" />').bind({
          mousedown: function(e) {
            setVector(e.offsetX, e.offsetY);
            return mouseHeld = true;
          },
          mousemove: function(e) {
            if (mouseHeld) {
              return setVector(e.offsetX, e.offsetY);
            }
          },
          mouseup: function() {
            $(input).focus();
            return mouseHeld = false;
          }
        }).appendTo(dialog);
        offset = input.offset();
        height = input.get(0).offsetHeight;
        dialog.css({
          left: offset.left,
          top: offset.top + height
        });
        return $('body').append(dialog);
      };
      return input.bind({
        blur: function() {
          if (!mouseHeld) {
            return $('.vector_picker').remove();
          }
        },
        focus: function() {
          var obj;
          if (!$('.vector_picker').length) {
            showDialog();
          }
          try {
            obj = JSON.parse(input.val());
          } catch (e) {
            obj = null;
          }
          return $('.unit_circle').css({
            backgroundPosition: obj ? "" + (5 * obj.x + (SIZE / 2) - RADIUS) + "px " + (5 * obj.y + (SIZE / 2) - RADIUS) + "px" : void 0
          });
        }
      });
    };
  })(jQuery);
}).call(this);
/*
 * timeago: a jQuery plugin, version: 0.9.3 (2011-01-21)
 * @requires jQuery v1.2.3 or later
 *
 * Timeago is a jQuery plugin that makes it easy to support automatically
 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
 *
 * For usage and examples, visit:
 * http://timeago.yarp.com/
 *
 * Licensed under the MIT:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2008-2011, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
 */

(function($) {
  $.timeago = function(timestamp) {
    if (timestamp instanceof Date) {
      return inWords(timestamp);
    } else if (typeof timestamp === "string") {
      return inWords($.timeago.parse(timestamp));
    } else {
      return inWords($.timeago.datetime(timestamp));
    }
  };
  var $t = $.timeago;

  $.extend($.timeago, {
    settings: {
      refreshMillis: 60000,
      allowFuture: false,
      strings: {
        prefixAgo: null,
        prefixFromNow: null,
        suffixAgo: "ago",
        suffixFromNow: "from now",
        seconds: "less than a minute",
        minute: "about a minute",
        minutes: "%d minutes",
        hour: "about an hour",
        hours: "about %d hours",
        day: "a day",
        days: "%d days",
        month: "about a month",
        months: "%d months",
        year: "about a year",
        years: "%d years",
        numbers: []
      }
    },
    inWords: function(distanceMillis) {
      var $l = this.settings.strings;
      var prefix = $l.prefixAgo;
      var suffix = $l.suffixAgo;
      if (this.settings.allowFuture) {
        if (distanceMillis < 0) {
          prefix = $l.prefixFromNow;
          suffix = $l.suffixFromNow;
        }
        distanceMillis = Math.abs(distanceMillis);
      }

      var seconds = distanceMillis / 1000;
      var minutes = seconds / 60;
      var hours = minutes / 60;
      var days = hours / 24;
      var years = days / 365;

      function substitute(stringOrFunction, number) {
        var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
        var value = ($l.numbers && $l.numbers[number]) || number;
        return string.replace(/%d/i, value);
      }

      var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
        seconds < 90 && substitute($l.minute, 1) ||
        minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
        minutes < 90 && substitute($l.hour, 1) ||
        hours < 24 && substitute($l.hours, Math.round(hours)) ||
        hours < 48 && substitute($l.day, 1) ||
        days < 30 && substitute($l.days, Math.floor(days)) ||
        days < 60 && substitute($l.month, 1) ||
        days < 365 && substitute($l.months, Math.floor(days / 30)) ||
        years < 2 && substitute($l.year, 1) ||
        substitute($l.years, Math.floor(years));

      return $.trim([prefix, words, suffix].join(" "));
    },
    parse: function(iso8601) {
      var s = $.trim(iso8601);
      s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
      s = s.replace(/-/,"/").replace(/-/,"/");
      s = s.replace(/T/," ").replace(/Z/," UTC");
      s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
      return new Date(s);
    },
    datetime: function(elem) {
      // jQuery's `is()` doesn't play well with HTML5 in IE
      var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
      var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
      return $t.parse(iso8601);
    }
  });

  $.fn.timeago = function() {
    var self = this;
    self.each(refresh);

    var $s = $t.settings;
    if ($s.refreshMillis > 0) {
      setInterval(function() { self.each(refresh); }, $s.refreshMillis);
    }
    return self;
  };

  function refresh() {
    var data = prepareData(this);
    if (!isNaN(data.datetime)) {
      $(this).text(inWords(data.datetime));
    }
    return this;
  }

  function prepareData(element) {
    element = $(element);
    if (!element.data("timeago")) {
      element.data("timeago", { datetime: $t.datetime(element) });
      var text = $.trim(element.text());
      if (text.length > 0) {
        element.attr("title", text);
      }
    }
    return element.data("timeago");
  }

  function inWords(date) {
    return $t.inWords(distance(date));
  }

  function distance(date) {
    return (new Date().getTime() - date.getTime());
  }

  // fix for IE6 suckage
  document.createElement("abbr");
  document.createElement("time");
}(jQuery));
//     Underscore.js 1.1.7
//     (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
//     Underscore is freely distributable under the MIT license.
//     Portions of Underscore are inspired or borrowed from Prototype,
//     Oliver Steele's Functional, and John Resig's Micro-Templating.
//     For all details and documentation:
//     http://documentcloud.github.com/underscore

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var root = this;

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Establish the object that gets returned to break out of a loop iteration.
  var breaker = {};

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var slice            = ArrayProto.slice,
      unshift          = ArrayProto.unshift,
      toString         = ObjProto.toString,
      hasOwnProperty   = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) { return new wrapper(obj); };

  // Export the Underscore object for **CommonJS**, with backwards-compatibility
  // for the old `require()` API. If we're not in CommonJS, add `_` to the
  // global object.
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = _;
    _._ = _;
  } else {
    // Exported as a string, for Closure Compiler "advanced" mode.
    root['_'] = _;
  }

  // Current version.
  _.VERSION = '1.1.7';

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles objects with the built-in `forEach`, arrays, and raw objects.
  // Delegates to **ECMAScript 5**'s native `forEach` if available.
  var each = _.each = _.forEach = function(obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
      for (var i = 0, l = obj.length; i < l; i++) {
        if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {
      for (var key in obj) {
        if (hasOwnProperty.call(obj, key)) {
          if (iterator.call(context, obj[key], key, obj) === breaker) return;
        }
      }
    }
  };

  // Return the results of applying the iterator to each element.
  // Delegates to **ECMAScript 5**'s native `map` if available.
  _.map = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    each(obj, function(value, index, list) {
      results[results.length] = iterator.call(context, value, index, list);
    });
    return results;
  };

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    var initial = memo !== void 0;
    if (obj == null) obj = [];
    if (nativeReduce && obj.reduce === nativeReduce) {
      if (context) iterator = _.bind(iterator, context);
      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    }
    each(obj, function(value, index, list) {
      if (!initial) {
        memo = value;
        initial = true;
      } else {
        memo = iterator.call(context, memo, value, index, list);
      }
    });
    if (!initial) throw new TypeError("Reduce of empty array with no initial value");
    return memo;
  };

  // The right-associative version of reduce, also known as `foldr`.
  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
    if (obj == null) obj = [];
    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
      if (context) iterator = _.bind(iterator, context);
      return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
    }
    var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
    return _.reduce(reversed, iterator, memo, context);
  };

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, iterator, context) {
    var result;
    any(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) {
        result = value;
        return true;
      }
    });
    return result;
  };

  // Return all the elements that pass a truth test.
  // Delegates to **ECMAScript 5**'s native `filter` if available.
  // Aliased as `select`.
  _.filter = _.select = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    each(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    each(obj, function(value, index, list) {
      if (!iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Determine whether all of the elements match a truth test.
  // Delegates to **ECMAScript 5**'s native `every` if available.
  // Aliased as `all`.
  _.every = _.all = function(obj, iterator, context) {
    var result = true;
    if (obj == null) return result;
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    each(obj, function(value, index, list) {
      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
    });
    return result;
  };

  // Determine if at least one element in the object matches a truth test.
  // Delegates to **ECMAScript 5**'s native `some` if available.
  // Aliased as `any`.
  var any = _.some = _.any = function(obj, iterator, context) {
    iterator = iterator || _.identity;
    var result = false;
    if (obj == null) return result;
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    each(obj, function(value, index, list) {
      if (result |= iterator.call(context, value, index, list)) return breaker;
    });
    return !!result;
  };

  // Determine if a given value is included in the array or object using `===`.
  // Aliased as `contains`.
  _.include = _.contains = function(obj, target) {
    var found = false;
    if (obj == null) return found;
    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    any(obj, function(value) {
      if (found = value === target) return true;
    });
    return found;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    return _.map(obj, function(value) {
      return (method.call ? method || value : value[method]).apply(value, args);
    });
  };

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, function(value){ return value[key]; });
  };

  // Return the maximum element or (element-based computation).
  _.max = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
    var result = {computed : -Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed >= result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
    var result = {computed : Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed < result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Sort the object's values by a criterion produced by an iterator.
  _.sortBy = function(obj, iterator, context) {
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value : value,
        criteria : iterator.call(context, value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }), 'value');
  };

  // Groups the object's values by a criterion produced by an iterator
  _.groupBy = function(obj, iterator) {
    var result = {};
    each(obj, function(value, index) {
      var key = iterator(value, index);
      (result[key] || (result[key] = [])).push(value);
    });
    return result;
  };

  // Use a comparator function to figure out at what index an object should
  // be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iterator) {
    iterator || (iterator = _.identity);
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >> 1;
      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    }
    return low;
  };

  // Safely convert anything iterable into a real, live array.
  _.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return slice.call(iterable);
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    return _.toArray(obj).length;
  };

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head`. The **guard** check allows it to work
  // with `_.map`.
  _.first = _.head = function(array, n, guard) {
    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
  };

  // Returns everything but the first entry of the array. Aliased as `tail`.
  // Especially useful on the arguments object. Passing an **index** will return
  // the rest of the values in the array from that index onward. The **guard**
  // check allows it to work with `_.map`.
  _.rest = _.tail = function(array, index, guard) {
    return slice.call(array, (index == null) || guard ? 1 : index);
  };

  // Get the last element of an array.
  _.last = function(array) {
    return array[array.length - 1];
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, function(value){ return !!value; });
  };

  // Return a completely flattened version of an array.
  _.flatten = function(array) {
    return _.reduce(array, function(memo, value) {
      if (_.isArray(value)) return memo.concat(_.flatten(value));
      memo[memo.length] = value;
      return memo;
    }, []);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted) {
    return _.reduce(array, function(memo, el, i) {
      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
      return memo;
    }, []);
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = function() {
    return _.uniq(_.flatten(arguments));
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays. (Aliased as "intersect" for back-compat.)
  _.intersection = _.intersect = function(array) {
    var rest = slice.call(arguments, 1);
    return _.filter(_.uniq(array), function(item) {
      return _.every(rest, function(other) {
        return _.indexOf(other, item) >= 0;
      });
    });
  };

  // Take the difference between one array and another.
  // Only the elements present in just the first array will remain.
  _.difference = function(array, other) {
    return _.filter(array, function(value){ return !_.include(other, value); });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function() {
    var args = slice.call(arguments);
    var length = _.max(_.pluck(args, 'length'));
    var results = new Array(length);
    for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
    return results;
  };

  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
  // we need this function. Return the position of the first occurrence of an
  // item in an array, or -1 if the item is not included in the array.
  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = function(array, item, isSorted) {
    if (array == null) return -1;
    var i, l;
    if (isSorted) {
      i = _.sortedIndex(array, item);
      return array[i] === item ? i : -1;
    }
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
    for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
    return -1;
  };


  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
  _.lastIndexOf = function(array, item) {
    if (array == null) return -1;
    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
    var i = array.length;
    while (i--) if (array[i] === item) return i;
    return -1;
  };

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (arguments.length <= 1) {
      stop = start || 0;
      start = 0;
    }
    step = arguments[2] || 1;

    var len = Math.max(Math.ceil((stop - start) / step), 0);
    var idx = 0;
    var range = new Array(len);

    while(idx < len) {
      range[idx++] = start;
      start += step;
    }

    return range;
  };

  // Function (ahem) Functions
  // ------------------

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Binding with arguments is also known as `curry`.
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
  // We check for `func.bind` first, to fail fast when `func` is undefined.
  _.bind = function(func, obj) {
    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    var args = slice.call(arguments, 2);
    return function() {
      return func.apply(obj, args.concat(slice.call(arguments)));
    };
  };

  // Bind all of an object's methods to that object. Useful for ensuring that
  // all callbacks defined on an object belong to it.
  _.bindAll = function(obj) {
    var funcs = slice.call(arguments, 1);
    if (funcs.length == 0) funcs = _.functions(obj);
    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    return obj;
  };

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memo = {};
    hasher || (hasher = _.identity);
    return function() {
      var key = hasher.apply(this, arguments);
      return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    };
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){ return func.apply(func, args); }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  };

  // Internal function used to implement `_.throttle` and `_.debounce`.
  var limit = function(func, wait, debounce) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var throttler = function() {
        timeout = null;
        func.apply(context, args);
      };
      if (debounce) clearTimeout(timeout);
      if (debounce || !timeout) timeout = setTimeout(throttler, wait);
    };
  };

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time.
  _.throttle = function(func, wait) {
    return limit(func, wait, false);
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds.
  _.debounce = function(func, wait) {
    return limit(func, wait, true);
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = function(func) {
    var ran = false, memo;
    return function() {
      if (ran) return memo;
      ran = true;
      return memo = func.apply(this, arguments);
    };
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return function() {
      var args = [func].concat(slice.call(arguments));
      return wrapper.apply(this, args);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var funcs = slice.call(arguments);
    return function() {
      var args = slice.call(arguments);
      for (var i = funcs.length - 1; i >= 0; i--) {
        args = [funcs[i].apply(this, args)];
      }
      return args[0];
    };
  };

  // Returns a function that will only be executed after being called N times.
  _.after = function(times, func) {
    return function() {
      if (--times < 1) { return func.apply(this, arguments); }
    };
  };


  // Object Functions
  // ----------------

  // Retrieve the names of an object's properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`
  _.keys = nativeKeys || function(obj) {
    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    var keys = [];
    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    return _.map(obj, _.identity);
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (source[prop] !== void 0) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Fill in a given object with default properties.
  _.defaults = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (obj[prop] == null) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    // Check object identity.
    if (a === b) return true;
    // Different types?
    var atype = typeof(a), btype = typeof(b);
    if (atype != btype) return false;
    // Basic equality test (watch out for coercions).
    if (a == b) return true;
    // One is falsy and the other truthy.
    if ((!a && b) || (a && !b)) return false;
    // Unwrap any wrapped objects.
    if (a._chain) a = a._wrapped;
    if (b._chain) b = b._wrapped;
    // One of them implements an isEqual()?
    if (a.isEqual) return a.isEqual(b);
    if (b.isEqual) return b.isEqual(a);
    // Check dates' integer values.
    if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
    // Both are NaN?
    if (_.isNaN(a) && _.isNaN(b)) return false;
    // Compare regular expressions.
    if (_.isRegExp(a) && _.isRegExp(b))
      return a.source     === b.source &&
             a.global     === b.global &&
             a.ignoreCase === b.ignoreCase &&
             a.multiline  === b.multiline;
    // If a is not an object by this point, we can't handle it.
    if (atype !== 'object') return false;
    // Check for different array lengths before comparing contents.
    if (a.length && (a.length !== b.length)) return false;
    // Nothing else worked, deep compare the contents.
    var aKeys = _.keys(a), bKeys = _.keys(b);
    // Different object sizes?
    if (aKeys.length != bKeys.length) return false;
    // Recursive comparison of contents.
    for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
    return true;
  };

  // Is a given array or object empty?
  _.isEmpty = function(obj) {
    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
    return true;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType == 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    return obj === Object(obj);
  };

  // Is a given variable an arguments object?
  _.isArguments = function(obj) {
    return !!(obj && hasOwnProperty.call(obj, 'callee'));
  };

  // Is a given value a function?
  _.isFunction = function(obj) {
    return !!(obj && obj.constructor && obj.call && obj.apply);
  };

  // Is a given value a string?
  _.isString = function(obj) {
    return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
  };

  // Is a given value a number?
  _.isNumber = function(obj) {
    return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
  };

  // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
  // that does not equal itself.
  _.isNaN = function(obj) {
    return obj !== obj;
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false;
  };

  // Is a given value a date?
  _.isDate = function(obj) {
    return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
  };

  // Is the given value a regular expression?
  _.isRegExp = function(obj) {
    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iterators.
  _.identity = function(value) {
    return value;
  };

  // Run a function **n** times.
  _.times = function (n, iterator, context) {
    for (var i = 0; i < n; i++) iterator.call(context, i);
  };

  // Add your own custom functions to the Underscore object, ensuring that
  // they're correctly added to the OOP wrapper as well.
  _.mixin = function(obj) {
    each(_.functions(obj), function(name){
      addToWrapper(name, _[name] = obj[name]);
    });
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = idCounter++;
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  _.template = function(str, data) {
    var c  = _.templateSettings;
    var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
      'with(obj||{}){__p.push(\'' +
      str.replace(/\\/g, '\\\\')
         .replace(/'/g, "\\'")
         .replace(c.interpolate, function(match, code) {
           return "'," + code.replace(/\\'/g, "'") + ",'";
         })
         .replace(c.evaluate || null, function(match, code) {
           return "');" + code.replace(/\\'/g, "'")
                              .replace(/[\r\n\t]/g, ' ') + "__p.push('";
         })
         .replace(/\r/g, '\\r')
         .replace(/\n/g, '\\n')
         .replace(/\t/g, '\\t')
         + "');}return __p.join('');";
    var func = new Function('obj', tmpl);
    return data ? func(data) : func;
  };

  // The OOP Wrapper
  // ---------------

  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.
  var wrapper = function(obj) { this._wrapped = obj; };

  // Expose `wrapper.prototype` as `_.prototype`
  _.prototype = wrapper.prototype;

  // Helper function to continue chaining intermediate results.
  var result = function(obj, chain) {
    return chain ? _(obj).chain() : obj;
  };

  // A method to easily add functions to the OOP wrapper.
  var addToWrapper = function(name, func) {
    wrapper.prototype[name] = function() {
      var args = slice.call(arguments);
      unshift.call(args, this._wrapped);
      return result(func.apply(_, args), this._chain);
    };
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      method.apply(this._wrapped, arguments);
      return result(this._wrapped, this._chain);
    };
  });

  // Add all accessor Array functions to the wrapper.
  each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      return result(method.apply(this._wrapped, arguments), this._chain);
    };
  });

  // Start chaining a wrapped Underscore object.
  wrapper.prototype.chain = function() {
    this._chain = true;
    return this;
  };

  // Extracts the result from a wrapped and chained object.
  wrapper.prototype.value = function() {
    return this._wrapped;
  };

})();
//     Backbone.js 0.5.3
//     (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
//     Backbone may be freely distributed under the MIT license.
//     For all details and documentation:
//     http://documentcloud.github.com/backbone

(function(){

  // Initial Setup
  // -------------

  // Save a reference to the global object.
  var root = this;

  // Save the previous value of the `Backbone` variable.
  var previousBackbone = root.Backbone;

  // The top-level namespace. All public Backbone classes and modules will
  // be attached to this. Exported for both CommonJS and the browser.
  var Backbone;
  if (typeof exports !== 'undefined') {
    Backbone = exports;
  } else {
    Backbone = root.Backbone = {};
  }

  // Current version of the library. Keep in sync with `package.json`.
  Backbone.VERSION = '0.5.3';

  // Require Underscore, if we're on the server, and it's not already present.
  var _ = root._;
  if (!_ && (typeof require !== 'undefined')) _ = require('underscore')._;

  // For Backbone's purposes, jQuery or Zepto owns the `$` variable.
  var $ = root.jQuery || root.Zepto;

  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
  // to its previous owner. Returns a reference to this Backbone object.
  Backbone.noConflict = function() {
    root.Backbone = previousBackbone;
    return this;
  };

  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option will
  // fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and set a
  // `X-Http-Method-Override` header.
  Backbone.emulateHTTP = false;

  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
  // `application/json` requests ... will encode the body as
  // `application/x-www-form-urlencoded` instead and will send the model in a
  // form param named `model`.
  Backbone.emulateJSON = false;

  // Backbone.Events
  // -----------------

  // A module that can be mixed in to *any object* in order to provide it with
  // custom events. You may `bind` or `unbind` a callback function to an event;
  // `trigger`-ing an event fires all callbacks in succession.
  //
  //     var object = {};
  //     _.extend(object, Backbone.Events);
  //     object.bind('expand', function(){ alert('expanded'); });
  //     object.trigger('expand');
  //
  Backbone.Events = {

    // Bind an event, specified by a string name, `ev`, to a `callback` function.
    // Passing `"all"` will bind the callback to all events fired.
    bind : function(ev, callback, context) {
      var calls = this._callbacks || (this._callbacks = {});
      var list  = calls[ev] || (calls[ev] = []);
      list.push([callback, context]);
      return this;
    },

    // Remove one or many callbacks. If `callback` is null, removes all
    // callbacks for the event. If `ev` is null, removes all bound callbacks
    // for all events.
    unbind : function(ev, callback) {
      var calls;
      if (!ev) {
        this._callbacks = {};
      } else if (calls = this._callbacks) {
        if (!callback) {
          calls[ev] = [];
        } else {
          var list = calls[ev];
          if (!list) return this;
          for (var i = 0, l = list.length; i < l; i++) {
            if (list[i] && callback === list[i][0]) {
              list[i] = null;
              break;
            }
          }
        }
      }
      return this;
    },

    // Trigger an event, firing all bound callbacks. Callbacks are passed the
    // same arguments as `trigger` is, apart from the event name.
    // Listening for `"all"` passes the true event name as the first argument.
    trigger : function(eventName) {
      var list, calls, ev, callback, args;
      var both = 2;
      if (!(calls = this._callbacks)) return this;
      while (both--) {
        ev = both ? eventName : 'all';
        if (list = calls[ev]) {
          for (var i = 0, l = list.length; i < l; i++) {
            if (!(callback = list[i])) {
              list.splice(i, 1); i--; l--;
            } else {
              args = both ? Array.prototype.slice.call(arguments, 1) : arguments;
              callback[0].apply(callback[1] || this, args);
            }
          }
        }
      }
      return this;
    }

  };

  // Backbone.Model
  // --------------

  // Create a new model, with defined attributes. A client id (`cid`)
  // is automatically generated and assigned for you.
  Backbone.Model = function(attributes, options) {
    var defaults;
    attributes || (attributes = {});
    if (defaults = this.defaults) {
      if (_.isFunction(defaults)) defaults = defaults.call(this);
      attributes = _.extend({}, defaults, attributes);
    }
    this.attributes = {};
    this._escapedAttributes = {};
    this.cid = _.uniqueId('c');
    this.set(attributes, {silent : true});
    this._changed = false;
    this._previousAttributes = _.clone(this.attributes);
    if (options && options.collection) this.collection = options.collection;
    this.initialize(attributes, options);
  };

  // Attach all inheritable methods to the Model prototype.
  _.extend(Backbone.Model.prototype, Backbone.Events, {

    // A snapshot of the model's previous attributes, taken immediately
    // after the last `"change"` event was fired.
    _previousAttributes : null,

    // Has the item been changed since the last `"change"` event?
    _changed : false,

    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
    // CouchDB users may want to set this to `"_id"`.
    idAttribute : 'id',

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize : function(){},

    // Return a copy of the model's `attributes` object.
    toJSON : function() {
      return _.clone(this.attributes);
    },

    // Get the value of an attribute.
    get : function(attr) {
      return this.attributes[attr];
    },

    // Get the HTML-escaped value of an attribute.
    escape : function(attr) {
      var html;
      if (html = this._escapedAttributes[attr]) return html;
      var val = this.attributes[attr];
      return this._escapedAttributes[attr] = escapeHTML(val == null ? '' : '' + val);
    },

    // Returns `true` if the attribute contains a value that is not null
    // or undefined.
    has : function(attr) {
      return this.attributes[attr] != null;
    },

    // Set a hash of model attributes on the object, firing `"change"` unless you
    // choose to silence it.
    set : function(attrs, options) {

      // Extract attributes and options.
      options || (options = {});
      if (!attrs) return this;
      if (attrs.attributes) attrs = attrs.attributes;
      var now = this.attributes, escaped = this._escapedAttributes;

      // Run validation.
      if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false;

      // Check for changes of `id`.
      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];

      // We're about to start triggering change events.
      var alreadyChanging = this._changing;
      this._changing = true;

      // Update attributes.
      for (var attr in attrs) {
        var val = attrs[attr];
        if (!_.isEqual(now[attr], val)) {
          now[attr] = val;
          delete escaped[attr];
          this._changed = true;
          if (!options.silent) this.trigger('change:' + attr, this, val, options);
        }
      }

      // Fire the `"change"` event, if the model has been changed.
      if (!alreadyChanging && !options.silent && this._changed) this.change(options);
      this._changing = false;
      return this;
    },

    // Remove an attribute from the model, firing `"change"` unless you choose
    // to silence it. `unset` is a noop if the attribute doesn't exist.
    unset : function(attr, options) {
      if (!(attr in this.attributes)) return this;
      options || (options = {});
      var value = this.attributes[attr];

      // Run validation.
      var validObj = {};
      validObj[attr] = void 0;
      if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;

      // Remove the attribute.
      delete this.attributes[attr];
      delete this._escapedAttributes[attr];
      if (attr == this.idAttribute) delete this.id;
      this._changed = true;
      if (!options.silent) {
        this.trigger('change:' + attr, this, void 0, options);
        this.change(options);
      }
      return this;
    },

    // Clear all attributes on the model, firing `"change"` unless you choose
    // to silence it.
    clear : function(options) {
      options || (options = {});
      var attr;
      var old = this.attributes;

      // Run validation.
      var validObj = {};
      for (attr in old) validObj[attr] = void 0;
      if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;

      this.attributes = {};
      this._escapedAttributes = {};
      this._changed = true;
      if (!options.silent) {
        for (attr in old) {
          this.trigger('change:' + attr, this, void 0, options);
        }
        this.change(options);
      }
      return this;
    },

    // Fetch the model from the server. If the server's representation of the
    // model differs from its current attributes, they will be overriden,
    // triggering a `"change"` event.
    fetch : function(options) {
      options || (options = {});
      var model = this;
      var success = options.success;
      options.success = function(resp, status, xhr) {
        if (!model.set(model.parse(resp, xhr), options)) return false;
        if (success) success(model, resp);
      };
      options.error = wrapError(options.error, model, options);
      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    },

    // Set a hash of model attributes, and sync the model to the server.
    // If the server returns an attributes hash that differs, the model's
    // state will be `set` again.
    save : function(attrs, options) {
      options || (options = {});
      if (attrs && !this.set(attrs, options)) return false;
      var model = this;
      var success = options.success;
      options.success = function(resp, status, xhr) {
        if (!model.set(model.parse(resp, xhr), options)) return false;
        if (success) success(model, resp, xhr);
      };
      options.error = wrapError(options.error, model, options);
      var method = this.isNew() ? 'create' : 'update';
      return (this.sync || Backbone.sync).call(this, method, this, options);
    },

    // Destroy this model on the server if it was already persisted. Upon success, the model is removed
    // from its collection, if it has one.
    destroy : function(options) {
      options || (options = {});
      if (this.isNew()) return this.trigger('destroy', this, this.collection, options);
      var model = this;
      var success = options.success;
      options.success = function(resp) {
        model.trigger('destroy', model, model.collection, options);
        if (success) success(model, resp);
      };
      options.error = wrapError(options.error, model, options);
      return (this.sync || Backbone.sync).call(this, 'delete', this, options);
    },

    // Default URL for the model's representation on the server -- if you're
    // using Backbone's restful methods, override this to change the endpoint
    // that will be called.
    url : function() {
      var base = getUrl(this.collection) || this.urlRoot || urlError();
      if (this.isNew()) return base;
      return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
    },

    // **parse** converts a response into the hash of attributes to be `set` on
    // the model. The default implementation is just to pass the response along.
    parse : function(resp, xhr) {
      return resp;
    },

    // Create a new model with identical attributes to this one.
    clone : function() {
      return new this.constructor(this);
    },

    // A model is new if it has never been saved to the server, and lacks an id.
    isNew : function() {
      return this.id == null;
    },

    // Call this method to manually fire a `change` event for this model.
    // Calling this will cause all objects observing the model to update.
    change : function(options) {
      this.trigger('change', this, options);
      this._previousAttributes = _.clone(this.attributes);
      this._changed = false;
    },

    // Determine if the model has changed since the last `"change"` event.
    // If you specify an attribute name, determine if that attribute has changed.
    hasChanged : function(attr) {
      if (attr) return this._previousAttributes[attr] != this.attributes[attr];
      return this._changed;
    },

    // Return an object containing all the attributes that have changed, or false
    // if there are no changed attributes. Useful for determining what parts of a
    // view need to be updated and/or what attributes need to be persisted to
    // the server.
    changedAttributes : function(now) {
      now || (now = this.attributes);
      var old = this._previousAttributes;
      var changed = false;
      for (var attr in now) {
        if (!_.isEqual(old[attr], now[attr])) {
          changed = changed || {};
          changed[attr] = now[attr];
        }
      }
      return changed;
    },

    // Get the previous value of an attribute, recorded at the time the last
    // `"change"` event was fired.
    previous : function(attr) {
      if (!attr || !this._previousAttributes) return null;
      return this._previousAttributes[attr];
    },

    // Get all of the attributes of the model at the time of the previous
    // `"change"` event.
    previousAttributes : function() {
      return _.clone(this._previousAttributes);
    },

    // Run validation against a set of incoming attributes, returning `true`
    // if all is well. If a specific `error` callback has been passed,
    // call that instead of firing the general `"error"` event.
    _performValidation : function(attrs, options) {
      var error = this.validate(attrs);
      if (error) {
        if (options.error) {
          options.error(this, error, options);
        } else {
          this.trigger('error', this, error, options);
        }
        return false;
      }
      return true;
    }

  });

  // Backbone.Collection
  // -------------------

  // Provides a standard collection class for our sets of models, ordered
  // or unordered. If a `comparator` is specified, the Collection will maintain
  // its models in sort order, as they're added and removed.
  Backbone.Collection = function(models, options) {
    options || (options = {});
    if (options.comparator) this.comparator = options.comparator;
    _.bindAll(this, '_onModelEvent', '_removeReference');
    this._reset();
    if (models) this.reset(models, {silent: true});
    this.initialize.apply(this, arguments);
  };

  // Define the Collection's inheritable methods.
  _.extend(Backbone.Collection.prototype, Backbone.Events, {

    // The default model for a collection is just a **Backbone.Model**.
    // This should be overridden in most cases.
    model : Backbone.Model,

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize : function(){},

    // The JSON representation of a Collection is an array of the
    // models' attributes.
    toJSON : function() {
      return this.map(function(model){ return model.toJSON(); });
    },

    // Add a model, or list of models to the set. Pass **silent** to avoid
    // firing the `added` event for every new model.
    add : function(models, options) {
      if (_.isArray(models)) {
        for (var i = 0, l = models.length; i < l; i++) {
          this._add(models[i], options);
        }
      } else {
        this._add(models, options);
      }
      return this;
    },

    // Remove a model, or a list of models from the set. Pass silent to avoid
    // firing the `removed` event for every model removed.
    remove : function(models, options) {
      if (_.isArray(models)) {
        for (var i = 0, l = models.length; i < l; i++) {
          this._remove(models[i], options);
        }
      } else {
        this._remove(models, options);
      }
      return this;
    },

    // Get a model from the set by id.
    get : function(id) {
      if (id == null) return null;
      return this._byId[id.id != null ? id.id : id];
    },

    // Get a model from the set by client id.
    getByCid : function(cid) {
      return cid && this._byCid[cid.cid || cid];
    },

    // Get the model at the given index.
    at: function(index) {
      return this.models[index];
    },

    // Force the collection to re-sort itself. You don't need to call this under normal
    // circumstances, as the set will maintain sort order as each item is added.
    sort : function(options) {
      options || (options = {});
      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
      this.models = this.sortBy(this.comparator);
      if (!options.silent) this.trigger('reset', this, options);
      return this;
    },

    // Pluck an attribute from each model in the collection.
    pluck : function(attr) {
      return _.map(this.models, function(model){ return model.get(attr); });
    },

    // When you have more items than you want to add or remove individually,
    // you can reset the entire set with a new list of models, without firing
    // any `added` or `removed` events. Fires `reset` when finished.
    reset : function(models, options) {
      models  || (models = []);
      options || (options = {});
      this.each(this._removeReference);
      this._reset();
      this.add(models, {silent: true});
      if (!options.silent) this.trigger('reset', this, options);
      return this;
    },

    // Fetch the default set of models for this collection, resetting the
    // collection when they arrive. If `add: true` is passed, appends the
    // models to the collection instead of resetting.
    fetch : function(options) {
      options || (options = {});
      var collection = this;
      var success = options.success;
      options.success = function(resp, status, xhr) {
        collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
        if (success) success(collection, resp);
      };
      options.error = wrapError(options.error, collection, options);
      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    },

    // Create a new instance of a model in this collection. After the model
    // has been created on the server, it will be added to the collection.
    // Returns the model, or 'false' if validation on a new model fails.
    create : function(model, options) {
      var coll = this;
      options || (options = {});
      model = this._prepareModel(model, options);
      if (!model) return false;
      var success = options.success;
      options.success = function(nextModel, resp, xhr) {
        coll.add(nextModel, options);
        if (success) success(nextModel, resp, xhr);
      };
      model.save(null, options);
      return model;
    },

    // **parse** converts a response into a list of models to be added to the
    // collection. The default implementation is just to pass it through.
    parse : function(resp, xhr) {
      return resp;
    },

    // Proxy to _'s chain. Can't be proxied the same way the rest of the
    // underscore methods are proxied because it relies on the underscore
    // constructor.
    chain: function () {
      return _(this.models).chain();
    },

    // Reset all internal state. Called when the collection is reset.
    _reset : function(options) {
      this.length = 0;
      this.models = [];
      this._byId  = {};
      this._byCid = {};
    },

    // Prepare a model to be added to this collection
    _prepareModel: function(model, options) {
      if (!(model instanceof Backbone.Model)) {
        var attrs = model;
        model = new this.model(attrs, {collection: this});
        if (model.validate && !model._performValidation(attrs, options)) model = false;
      } else if (!model.collection) {
        model.collection = this;
      }
      return model;
    },

    // Internal implementation of adding a single model to the set, updating
    // hash indexes for `id` and `cid` lookups.
    // Returns the model, or 'false' if validation on a new model fails.
    _add : function(model, options) {
      options || (options = {});
      model = this._prepareModel(model, options);
      if (!model) return false;
      var already = this.getByCid(model);
      if (already) throw new Error(["Can't add the same model to a set twice", already.id]);
      this._byId[model.id] = model;
      this._byCid[model.cid] = model;
      var index = options.at != null ? options.at :
                  this.comparator ? this.sortedIndex(model, this.comparator) :
                  this.length;
      this.models.splice(index, 0, model);
      model.bind('all', this._onModelEvent);
      this.length++;
      if (!options.silent) model.trigger('add', model, this, options);
      return model;
    },

    // Internal implementation of removing a single model from the set, updating
    // hash indexes for `id` and `cid` lookups.
    _remove : function(model, options) {
      options || (options = {});
      model = this.getByCid(model) || this.get(model);
      if (!model) return null;
      delete this._byId[model.id];
      delete this._byCid[model.cid];
      this.models.splice(this.indexOf(model), 1);
      this.length--;
      if (!options.silent) model.trigger('remove', model, this, options);
      this._removeReference(model);
      return model;
    },

    // Internal method to remove a model's ties to a collection.
    _removeReference : function(model) {
      if (this == model.collection) {
        delete model.collection;
      }
      model.unbind('all', this._onModelEvent);
    },

    // Internal method called every time a model in the set fires an event.
    // Sets need to update their indexes when models change ids. All other
    // events simply proxy through. "add" and "remove" events that originate
    // in other collections are ignored.
    _onModelEvent : function(ev, model, collection, options) {
      if ((ev == 'add' || ev == 'remove') && collection != this) return;
      if (ev == 'destroy') {
        this._remove(model, options);
      }
      if (model && ev === 'change:' + model.idAttribute) {
        delete this._byId[model.previous(model.idAttribute)];
        this._byId[model.id] = model;
      }
      this.trigger.apply(this, arguments);
    }

  });

  // Underscore methods that we want to implement on the Collection.
  var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', 'detect',
    'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
    'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size',
    'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty', 'groupBy'];

  // Mix in each Underscore method as a proxy to `Collection#models`.
  _.each(methods, function(method) {
    Backbone.Collection.prototype[method] = function() {
      return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
    };
  });

  // Backbone.Router
  // -------------------

  // Routers map faux-URLs to actions, and fire events when routes are
  // matched. Creating a new one sets its `routes` hash, if not set statically.
  Backbone.Router = function(options) {
    options || (options = {});
    if (options.routes) this.routes = options.routes;
    this._bindRoutes();
    this.initialize.apply(this, arguments);
  };

  // Cached regular expressions for matching named param parts and splatted
  // parts of route strings.
  var namedParam    = /:([\w\d]+)/g;
  var splatParam    = /\*([\w\d]+)/g;
  var escapeRegExp  = /[-[\]{}()+?.,\\^$|#\s]/g;

  // Set up all inheritable **Backbone.Router** properties and methods.
  _.extend(Backbone.Router.prototype, Backbone.Events, {

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize : function(){},

    // Manually bind a single named route to a callback. For example:
    //
    //     this.route('search/:query/p:num', 'search', function(query, num) {
    //       ...
    //     });
    //
    route : function(route, name, callback) {
      Backbone.history || (Backbone.history = new Backbone.History);
      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
      Backbone.history.route(route, _.bind(function(fragment) {
        var args = this._extractParameters(route, fragment);
        callback.apply(this, args);
        this.trigger.apply(this, ['route:' + name].concat(args));
      }, this));
    },

    // Simple proxy to `Backbone.history` to save a fragment into the history.
    navigate : function(fragment, triggerRoute) {
      Backbone.history.navigate(fragment, triggerRoute);
    },

    // Bind all defined routes to `Backbone.history`. We have to reverse the
    // order of the routes here to support behavior where the most general
    // routes can be defined at the bottom of the route map.
    _bindRoutes : function() {
      if (!this.routes) return;
      var routes = [];
      for (var route in this.routes) {
        routes.unshift([route, this.routes[route]]);
      }
      for (var i = 0, l = routes.length; i < l; i++) {
        this.route(routes[i][0], routes[i][1], this[routes[i][1]]);
      }
    },

    // Convert a route string into a regular expression, suitable for matching
    // against the current location hash.
    _routeToRegExp : function(route) {
      route = route.replace(escapeRegExp, "\\$&")
                   .replace(namedParam, "([^\/]*)")
                   .replace(splatParam, "(.*?)");
      return new RegExp('^' + route + '$');
    },

    // Given a route, and a URL fragment that it matches, return the array of
    // extracted parameters.
    _extractParameters : function(route, fragment) {
      return route.exec(fragment).slice(1);
    }

  });

  // Backbone.History
  // ----------------

  // Handles cross-browser history management, based on URL fragments. If the
  // browser does not support `onhashchange`, falls back to polling.
  Backbone.History = function() {
    this.handlers = [];
    _.bindAll(this, 'checkUrl');
  };

  // Cached regex for cleaning hashes.
  var hashStrip = /^#*/;

  // Cached regex for detecting MSIE.
  var isExplorer = /msie [\w.]+/;

  // Has the history handling already been started?
  var historyStarted = false;

  // Set up all inheritable **Backbone.History** properties and methods.
  _.extend(Backbone.History.prototype, {

    // The default interval to poll for hash changes, if necessary, is
    // twenty times a second.
    interval: 50,

    // Get the cross-browser normalized URL fragment, either from the URL,
    // the hash, or the override.
    getFragment : function(fragment, forcePushState) {
      if (fragment == null) {
        if (this._hasPushState || forcePushState) {
          fragment = window.location.pathname;
          var search = window.location.search;
          if (search) fragment += search;
          if (fragment.indexOf(this.options.root) == 0) fragment = fragment.substr(this.options.root.length);
        } else {
          fragment = window.location.hash;
        }
      }
      return decodeURIComponent(fragment.replace(hashStrip, ''));
    },

    // Start the hash change handling, returning `true` if the current URL matches
    // an existing route, and `false` otherwise.
    start : function(options) {

      // Figure out the initial configuration. Do we need an iframe?
      // Is pushState desired ... is it available?
      if (historyStarted) throw new Error("Backbone.history has already been started");
      this.options          = _.extend({}, {root: '/'}, this.options, options);
      this._wantsPushState  = !!this.options.pushState;
      this._hasPushState    = !!(this.options.pushState && window.history && window.history.pushState);
      var fragment          = this.getFragment();
      var docMode           = document.documentMode;
      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
      if (oldIE) {
        this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
        this.navigate(fragment);
      }

      // Depending on whether we're using pushState or hashes, and whether
      // 'onhashchange' is supported, determine how we check the URL state.
      if (this._hasPushState) {
        $(window).bind('popstate', this.checkUrl);
      } else if ('onhashchange' in window && !oldIE) {
        $(window).bind('hashchange', this.checkUrl);
      } else {
        setInterval(this.checkUrl, this.interval);
      }

      // Determine if we need to change the base url, for a pushState link
      // opened by a non-pushState browser.
      this.fragment = fragment;
      historyStarted = true;
      var loc = window.location;
      var atRoot  = loc.pathname == this.options.root;
      if (this._wantsPushState && !this._hasPushState && !atRoot) {
        this.fragment = this.getFragment(null, true);
        window.location.replace(this.options.root + '#' + this.fragment);
        // Return immediately as browser will do redirect to new url
        return true;
      } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
        this.fragment = loc.hash.replace(hashStrip, '');
        window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
      }

      if (!this.options.silent) {
        return this.loadUrl();
      }
    },

    // Add a route to be tested when the fragment changes. Routes added later may
    // override previous routes.
    route : function(route, callback) {
      this.handlers.unshift({route : route, callback : callback});
    },

    // Checks the current URL to see if it has changed, and if it has,
    // calls `loadUrl`, normalizing across the hidden iframe.
    checkUrl : function(e) {
      var current = this.getFragment();
      if (current == this.fragment && this.iframe) current = this.getFragment(this.iframe.location.hash);
      if (current == this.fragment || current == decodeURIComponent(this.fragment)) return false;
      if (this.iframe) this.navigate(current);
      this.loadUrl() || this.loadUrl(window.location.hash);
    },

    // Attempt to load the current URL fragment. If a route succeeds with a
    // match, returns `true`. If no defined routes matches the fragment,
    // returns `false`.
    loadUrl : function(fragmentOverride) {
      var fragment = this.fragment = this.getFragment(fragmentOverride);
      var matched = _.any(this.handlers, function(handler) {
        if (handler.route.test(fragment)) {
          handler.callback(fragment);
          return true;
        }
      });
      return matched;
    },

    // Save a fragment into the hash history. You are responsible for properly
    // URL-encoding the fragment in advance. This does not trigger
    // a `hashchange` event.
    navigate : function(fragment, triggerRoute) {
      var frag = (fragment || '').replace(hashStrip, '');
      if (this.fragment == frag || this.fragment == decodeURIComponent(frag)) return;
      if (this._hasPushState) {
        var loc = window.location;
        if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag;
        this.fragment = frag;
        window.history.pushState({}, document.title, loc.protocol + '//' + loc.host + frag);
      } else {
        window.location.hash = this.fragment = frag;
        if (this.iframe && (frag != this.getFragment(this.iframe.location.hash))) {
          this.iframe.document.open().close();
          this.iframe.location.hash = frag;
        }
      }
      if (triggerRoute) this.loadUrl(fragment);
    }

  });

  // Backbone.View
  // -------------

  // Creating a Backbone.View creates its initial element outside of the DOM,
  // if an existing element is not provided...
  Backbone.View = function(options) {
    this.cid = _.uniqueId('view');
    this._configure(options || {});
    this._ensureElement();
    this.delegateEvents();
    this.initialize.apply(this, arguments);
  };

  // Element lookup, scoped to DOM elements within the current view.
  // This should be prefered to global lookups, if you're dealing with
  // a specific view.
  var selectorDelegate = function(selector) {
    return $(selector, this.el);
  };

  // Cached regex to split keys for `delegate`.
  var eventSplitter = /^(\S+)\s*(.*)$/;

  // List of view options to be merged as properties.
  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'];

  // Set up all inheritable **Backbone.View** properties and methods.
  _.extend(Backbone.View.prototype, Backbone.Events, {

    // The default `tagName` of a View's element is `"div"`.
    tagName : 'div',

    // Attach the `selectorDelegate` function as the `$` property.
    $       : selectorDelegate,

    // Initialize is an empty function by default. Override it with your own
    // initialization logic.
    initialize : function(){},

    // **render** is the core function that your view should override, in order
    // to populate its element (`this.el`), with the appropriate HTML. The
    // convention is for **render** to always return `this`.
    render : function() {
      return this;
    },

    // Remove this view from the DOM. Note that the view isn't present in the
    // DOM by default, so calling this method may be a no-op.
    remove : function() {
      $(this.el).remove();
      return this;
    },

    // For small amounts of DOM Elements, where a full-blown template isn't
    // needed, use **make** to manufacture elements, one at a time.
    //
    //     var el = this.make('li', {'class': 'row'}, this.model.escape('title'));
    //
    make : function(tagName, attributes, content) {
      var el = document.createElement(tagName);
      if (attributes) $(el).attr(attributes);
      if (content) $(el).html(content);
      return el;
    },

    // Set callbacks, where `this.callbacks` is a hash of
    //
    // *{"event selector": "callback"}*
    //
    //     {
    //       'mousedown .title':  'edit',
    //       'click .button':     'save'
    //     }
    //
    // pairs. Callbacks will be bound to the view, with `this` set properly.
    // Uses event delegation for efficiency.
    // Omitting the selector binds the event to `this.el`.
    // This only works for delegate-able events: not `focus`, `blur`, and
    // not `change`, `submit`, and `reset` in Internet Explorer.
    delegateEvents : function(events) {
      if (!(events || (events = this.events))) return;
      if (_.isFunction(events)) events = events.call(this);
      $(this.el).unbind('.delegateEvents' + this.cid);
      for (var key in events) {
        var method = this[events[key]];
        if (!method) throw new Error('Event "' + events[key] + '" does not exist');
        var match = key.match(eventSplitter);
        var eventName = match[1], selector = match[2];
        method = _.bind(method, this);
        eventName += '.delegateEvents' + this.cid;
        if (selector === '') {
          $(this.el).bind(eventName, method);
        } else {
          $(this.el).delegate(selector, eventName, method);
        }
      }
    },

    // Performs the initial configuration of a View with a set of options.
    // Keys with special meaning *(model, collection, id, className)*, are
    // attached directly to the view.
    _configure : function(options) {
      if (this.options) options = _.extend({}, this.options, options);
      for (var i = 0, l = viewOptions.length; i < l; i++) {
        var attr = viewOptions[i];
        if (options[attr]) this[attr] = options[attr];
      }
      this.options = options;
    },

    // Ensure that the View has a DOM element to render into.
    // If `this.el` is a string, pass it through `$()`, take the first
    // matching element, and re-assign it to `el`. Otherwise, create
    // an element from the `id`, `className` and `tagName` proeprties.
    _ensureElement : function() {
      if (!this.el) {
        var attrs = this.attributes || {};
        if (this.id) attrs.id = this.id;
        if (this.className) attrs['class'] = this.className;
        this.el = this.make(this.tagName, attrs);
      } else if (_.isString(this.el)) {
        this.el = $(this.el).get(0);
      }
    }

  });

  // The self-propagating extend function that Backbone classes use.
  var extend = function (protoProps, classProps) {
    var child = inherits(this, protoProps, classProps);
    child.extend = this.extend;
    return child;
  };

  // Set up inheritance for the model, collection, and view.
  Backbone.Model.extend = Backbone.Collection.extend =
    Backbone.Router.extend = Backbone.View.extend = extend;

  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
  var methodMap = {
    'create': 'POST',
    'update': 'PUT',
    'delete': 'DELETE',
    'read'  : 'GET'
  };

  // Backbone.sync
  // -------------

  // Override this function to change the manner in which Backbone persists
  // models to the server. You will be passed the type of request, and the
  // model in question. By default, uses makes a RESTful Ajax request
  // to the model's `url()`. Some possible customizations could be:
  //
  // * Use `setTimeout` to batch rapid-fire updates into a single request.
  // * Send up the models as XML instead of JSON.
  // * Persist models via WebSockets instead of Ajax.
  //
  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
  // as `POST`, with a `_method` parameter containing the true HTTP method,
  // as well as all requests with the body as `application/x-www-form-urlencoded` instead of
  // `application/json` with the model in a param named `model`.
  // Useful when interfacing with server-side languages like **PHP** that make
  // it difficult to read the body of `PUT` requests.
  Backbone.sync = function(method, model, options) {
    var type = methodMap[method];

    // Default JSON-request options.
    var params = _.extend({
      type:         type,
      dataType:     'json'
    }, options);

    // Ensure that we have a URL.
    if (!params.url) {
      params.url = getUrl(model) || urlError();
    }

    // Ensure that we have the appropriate request data.
    if (!params.data && model && (method == 'create' || method == 'update')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(model.toJSON());
    }

    // For older servers, emulate JSON by encoding the request into an HTML-form.
    if (Backbone.emulateJSON) {
      params.contentType = 'application/x-www-form-urlencoded';
      params.data        = params.data ? {model : params.data} : {};
    }

    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
    // And an `X-HTTP-Method-Override` header.
    if (Backbone.emulateHTTP) {
      if (type === 'PUT' || type === 'DELETE') {
        if (Backbone.emulateJSON) params.data._method = type;
        params.type = 'POST';
        params.beforeSend = function(xhr) {
          xhr.setRequestHeader('X-HTTP-Method-Override', type);
        };
      }
    }

    // Don't process data on a non-GET request.
    if (params.type !== 'GET' && !Backbone.emulateJSON) {
      params.processData = false;
    }

    // Make the request.
    return $.ajax(params);
  };

  // Helpers
  // -------

  // Shared empty constructor function to aid in prototype-chain creation.
  var ctor = function(){};

  // Helper function to correctly set up the prototype chain, for subclasses.
  // Similar to `goog.inherits`, but uses a hash of prototype properties and
  // class properties to be extended.
  var inherits = function(parent, protoProps, staticProps) {
    var child;

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call `super()`.
    if (protoProps && protoProps.hasOwnProperty('constructor')) {
      child = protoProps.constructor;
    } else {
      child = function(){ return parent.apply(this, arguments); };
    }

    // Inherit class (static) properties from parent.
    _.extend(child, parent);

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function.
    ctor.prototype = parent.prototype;
    child.prototype = new ctor();

    // Add prototype properties (instance properties) to the subclass,
    // if supplied.
    if (protoProps) _.extend(child.prototype, protoProps);

    // Add static properties to the constructor function, if supplied.
    if (staticProps) _.extend(child, staticProps);

    // Correctly set child's `prototype.constructor`.
    child.prototype.constructor = child;

    // Set a convenience property in case the parent's prototype is needed later.
    child.__super__ = parent.prototype;

    return child;
  };

  // Helper function to get a URL from a Model or Collection as a property
  // or as a function.
  var getUrl = function(object) {
    if (!(object && object.url)) return null;
    return _.isFunction(object.url) ? object.url() : object.url;
  };

  // Throw an error when a URL is needed, and none is supplied.
  var urlError = function() {
    throw new Error('A "url" property or function must be specified');
  };

  // Wrap an optional error callback with a fallback error event.
  var wrapError = function(onError, model, options) {
    return function(resp) {
      if (onError) {
        onError(model, resp, options);
      } else {
        model.trigger('error', model, resp, options);
      }
    };
  };

  // Helper function to escape a string for HTML rendering.
  var escapeHTML = function(string) {
    return string.replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
  };

}).call(this);
;(function() {
    
    //Support paths for nested attributes e.g. 'user.name'
    function getNested(obj, path) {
        var fields = path.split(".");
        var result = obj;
        for (var i = 0, n = fields.length; i < n; i++) {
            result = result[fields[i]];
        }
        return result;
    }
    
    function getNestedSchema(obj, path) {
        path = path.replace(/\./g, '.subSchema.');
        return getNested(obj, path);
    }
    
    var helpers = {};
    var validators = {};
    
    /**
     * This function is used to transform the key from a schema into the title used in a label.
     * (If a specific title is provided it will be used instead).
     * 
     * By default this converts a camelCase string into words, i.e. Camel Case
     * If you have a different naming convention for schema keys, replace this function.
     * 
     * @param {String}  Key
     * @return {String} Title
     */
    helpers.keyToTitle = function(str) {
        //Add spaces
        str = str.replace(/([A-Z])/g, ' $1');

        //Uppercase first character
        str = str.replace(/^./, function(str) { return str.toUpperCase(); });

        return str;
    };

    /**
     * Helper to create a template with the {{mustache}} style tags. Template settings are reset
     * to user's settings when done to avoid conflicts.
     * @param {String}      Template string
     * @return {Template}   Compiled template
     */
    helpers.createTemplate = function(str) {
        //Store user's template options 
        var _interpolateBackup = _.templateSettings.interpolate;

        //Set custom template settings
        _.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

        var template = _.template(str);

        //Reset to users' template settings
        _.templateSettings.interpolate = _interpolateBackup;

        return template;
    };
    
    
    /**
     * Return the editor constructor for a given schema 'type'.
     * Accepts strings for the default editors, or the reference to the constructor function
     * for custom editors
     * 
     * @param {String|Function} The schema type e.g. 'Text', 'Select', or the editor constructor e.g. editors.Date
     * @param {Object}          Options to pass to editor, including required 'key', 'schema'
     * @return {Mixed}          An instance of the mapped editor
     */
    helpers.createEditor = function(schemaType, options) {
        var constructorFn;

        if (_.isString(schemaType))
            constructorFn = editors[schemaType];
        else
            constructorFn = schemaType;

        return new constructorFn(options);
    };
    
    /**
     * Triggers an event that can be cancelled. Requires the user to invoke a callback. If false
     * is passed to the callback, the action does not run.
     * 
     * @param {Mixed}       Instance of Backbone model, view, collection to trigger event on
     * @param {String}      Event name
     * @param {Array}       Arguments to pass to the event handlers
     * @param {Function}    Callback to run after the event handler has run.
     *                      If any of them passed false or error, this callback won't run
     */ 
    helpers.triggerCancellableEvent = function(subject, event, args, callback) {
        var eventHandlers = subject._callbacks[event] || [];
        
        if (!eventHandlers.length) return callback();
        
        var fn = eventHandlers[0][0],
            context = eventHandlers[0][1] || this;
        
        //Add the callback that will be used when done
        args.push(callback);
        
        fn.apply(context, args);
    }

    helpers.getValidator = function(validator) {
        var isRegExp = _(validator).isRegExp();
        if (isRegExp || validator['RegExp']) {
            if (!isRegExp) {
                validator = new RegExp(validator['RegExp']);
            }
            return function (value) {
                if (!validator.test(value)) {
                    return 'Value '+value+' does not pass validation against regular expression '+validator;
                }
            };
        } else if (_(validator).isString()) {
            if (validators[validator]) {
                return validators[validator];
            } else {
                throw 'Validator "'+validator+'" not found';
            }
        } else if (_(validator).isFunction()) {
            return validator;
        } else {
            throw 'Could not process validator' + validator;
        }
    };

    validators.required = function (value) {
        var exists = (value === 0 || !!value);
        if (!exists) {
            return 'This field is required';
        }
    };
    

    var Form = Backbone.View.extend({
        
        //Field views
        fields: null,

        tagName: 'fieldset',
        
        className: 'bbf-form',

        /**
         * @param {Object}  Options
         *      Required:
         *          schema  {Array}
         *      Optional:
         *          model   {Backbone.Model} : Use instead of data, and use commit().
         *          data    {Array} : Pass this when not using a model. Use getValue() to get out value
         *          fields  {Array} : Keys of fields to include in the form, in display order (default: all fields)
         */
        initialize: function(options) {
            this.schema = options.schema || (options.model ? options.model.schema : {}),
            this.model = options.model;
            this.data = options.data;
            this.fieldsToRender = options.fields || _.keys(this.schema);
            this.fieldsets = options.fieldsets;
            this.idPrefix = options.idPrefix || '';

            //Stores all Field views
            this.fields = {};
        },

        /**
         * Renders the form and all fields
         */
        render: function() {
            var fieldsToRender = this.fieldsToRender,
                fieldsets = this.fieldsets,
                el = $(this.el),
                self = this;

            if (fieldsets) {
                _.each(fieldsets, function (fs) {
                    if (_(fs).isArray()) {
                        fs = {'fields': fs};
                    }

                    var fieldset = $('<fieldset><ul>');

                    if (fs.legend) {
                        fieldset.append($('<legend>').html(fs.legend));
                    }
                    self.renderFields(fs.fields, fieldset.find('ul'));
                    el.append(fieldset);
                });
            } else {
                var target = $('<ul>');
                el.append(target)
                this.renderFields(fieldsToRender, target);
            }

            return this;
        },

        /**
         * Render a list of fields. Returns the rendered Field object.
         */
        renderFields: function (fieldsToRender, el) {
            var schema = this.schema,
                model = this.model,
                data = this.data,
                fields = this.fields,
                el = el || $(this.el),
                self = this;
            
            //Create form fields
            _.each(fieldsToRender, function(key) {
                var itemSchema = getNestedSchema(schema, key);

                if (!itemSchema) throw "Field '"+key+"' not found in schema";

                var options = {
                    key: key,
                    schema: itemSchema,
                    idPrefix: self.idPrefix
                };

                if (model) {
                    options.model = model;
                } else if (data) {
                    options.value = data[key];
                } else {
                    options.value = null;
                }

                var field = new Field(options);

                //Render the fields with editors, apart from Hidden fields
                if (itemSchema.type == 'Hidden') {
                    field.editor = helpers.createEditor('Hidden', options);
                } else {
                    el.append(field.render().el);
                }

                fields[key] = field;
            });
        },

        /**
         * Validate the data
         *
         * @return {Object} Validation errors
         */
        validate: function() {
            var fields = this.fields,
                model = this.model,
                errors = {};

            _.each(fields, function(field) {
                var error = field.validate();
                if (error) {
                    errors[field.key] = error;
                }
            });

            if (model && model.validate) {
                var modelErrors = model.validate(this.getValue());
                if (modelErrors) errors._nonFieldErrors = modelErrors;
            }

            return _.isEmpty(errors) ? null : errors;
        },

        /**
         * Update the model with all latest values.
         *
         * @return {Object}  Validation errors
         */
        commit: function() {
            var fields = this.fields;

            var errors = this.validate();

            if (errors) {
                return errors;
            }

            _.each(fields, function(field) {
                var error = field.commit();
                if (error) errors[field.key] = error;
            });

            return _.isEmpty(errors) ? null : errors;
        },

        /**
         * Get all the field values as an object.
         * Use this method when passing data instead of objects
         * 
         * @param {String}  To get a specific field value pass the key name
         */
        getValue: function(key) {
            if (key) {
                //Return given key only
                return this.fields[key].getValue();
            } else {
                //Return entire form data
                var schema = this.schema,
                    fields = this.fields
                    obj = {};

                _.each(fields, function(field) {
                    obj[field.key] = field.getValue();
                });

                return obj;
            }
        },
        
        /**
         * Update field values, referenced by key
         * @param {Object}  New values to set
         */
        setValue: function(data) {
            for (var key in data) {
                this.fields[key].setValue(data[key]);
            }
        },

        /**
         * Override default remove function in order to remove embedded views
         */
        remove: function() {
            var fields = this.fields;
            
            for (var key in fields) {
                fields[key].remove();
            }

            Backbone.View.prototype.remove.call(this);
        }

    });


    var Field = Backbone.View.extend({

        tagName: 'li',

        className: 'bbf-field',

        events: {
            'click label': 'logValue'
        },

        /**
         * @param {Object}  Options
         *      Required:
         *          key     {String} : The model attribute key
         *      Optional:
         *          schema  {Object} : Schema for the field
         *          value       {Mixed} : Pass value when not using a model. Use getValue() to get out value
         *          model       {Backbone.Model} : Use instead of value, and use commit().
         *          idPrefix    {String} : Prefix to add to the editor DOM element's ID
         */
        initialize: function(options) {
            this.key = options.key;
            this.schema = options.schema || {};
            this.value = options.value;
            this.model = options.model;
            this.idPrefix = options.idPrefix || '';

            //Set schema defaults
            var schema = this.schema;
            if (!schema.type) schema.type = 'Text';
            if (!schema.title) schema.title = helpers.keyToTitle(this.key);
        },

        render: function() {
            var schema = this.schema,
                el = $(this.el);

            el.addClass('bbf-field' + schema.type);

            //Standard options that will go to all editors
            var options = {
                key: this.key,
                schema: schema,
                idPrefix: this.idPrefix,
                id: this.idPrefix + this.key
            };

            //Decide on data delivery type to pass to editors
            if (this.model)
                options.model = this.model;
            else
                options.value = this.value;

            //Decide on the editor to use
            var editor = helpers.createEditor(schema.type, options);

            el.html(Field.template({
                key: this.key,
                title: schema.title,
                id: editor.id,
                type: schema.type
            }));

            //Add the editor
            $('.bbf-editor', el).html(editor.render().el);

            this.editor = editor;

            return this;
        },

        /**
         * Validate the value from the editor
         */
        validate: function() {
            return this.editor.validate();
        },

        /**
         * Update the model with the new value from the editor
         */
        commit: function() {
            return this.editor.commit();
        },

        /**
         * Get the value from the editor
         * @return {Mixed}
         */
        getValue: function() {
            return this.editor.getValue();
        },
        
        /**
         * Set/change the value of the editor
         */
        setValue: function(value) {
            this.editor.setValue(value);
        },

        logValue: function() {
            console.log(this.getValue());
        },

        remove: function() {
            this.editor.remove();

            Backbone.View.prototype.remove.call(this);
        }

    },  {
        
        //Static
        template: helpers.createTemplate('\
             <label for="{{id}}">{{title}}</label>\
             <div class="bbf-editor bbf-editor{{type}}"></div>\
        ')
        
    });




    //========================================================================
    //EDITORS
    //========================================================================

    var editors = {};

    /**
     * Base editor (interface). To be extended, not used directly

     * @param {Object}  Options
     *      Optional:
     *         model   {Backbone.Model} : Use instead of value, and use commit().
     *         key     {String} : The model attribute key. Required when using 'model'
     *         value   {String} : When not using a model. If neither provided, defaultValue will be used.
     *         schema  {Object} : May be required by some editors
     */
    editors.Base = Backbone.View.extend({

        defaultValue: null,

        initialize: function(options) {
            var options = options || {};

            if (options.model) {
                if (!options.key) throw "Missing option: 'key'";

                this.model = options.model;
                this.key = options.key;

                this.value = this.model.get(this.key);
            }
            else if (options.value)
                this.value = options.value;
            
            if (this.value === undefined) this.value = this.defaultValue;

            this.schema = options.schema || {};
            this.validators = options.validators || this.schema.validators;
        },

        getValue: function() {
            throw 'Not implemented. Extend and override this method.';
        },
        
        setValue: function() {
            throw 'Not implemented. Extend and override this method.';
        },

        /**
         * Check the validity of a particular field
         */
        validate: function () {
            var el = $(this.el),
                error = null,
                value = this.getValue();

            if (this.validators) {
                _(this.validators).each(function(validator) {
                    if (!error) {
                        error = helpers.getValidator(validator)(value);
                    }
                });
            }

            if (!error && this.model && this.model.validate) {
                var change = {};
                change[this.key] = value;
                error = this.model.validate(change);
            }

            if (error) {
                el.addClass('bbf-error');
            } else {
                el.removeClass('bbf-error');
            }

            return error;
        },

        /**
         * Update the model with the new value from the editor
         *
         * @return {Error|null} Validation error or null
         */
        commit: function() {
            var error = null;
            var change = {};
            change[this.key] = this.getValue();
            this.model.set(change, {
                error: function(model, e) {
                    error = e;
                }
            });

            return error;
        }

    });

    editors.Text = editors.Base.extend({

        tagName: 'input',

        defaultValue: '',
        
        initialize: function(options) {            
            editors.Base.prototype.initialize.call(this, options);
            
            //Allow customising text type (email, phone etc.) for HTML5 browsers
            var type = 'text';
            
            if (this.schema && this.schema.dataType) type = this.schema.dataType;

            $(this.el).attr('type', type);
        },

        /**
         * Adds the editor to the DOM
         */
        render: function() {
            this.setValue(this.value);

            return this;
        },

        /**
         * Returns the current editor value
         * @return {String}
         */
        getValue: function() {
            return $(this.el).val();
        },
        
        /**
         * Sets the value of the form element
         * @param {String}
         */
        setValue: function(value) {
            $(this.el).val(value);
        }

    });


    /**
     * Normal text input that only allows a number. Letters etc. are not entered
     */
    editors.Number = editors.Text.extend({

        defaultValue: 0,

        events: {
            'keypress': 'onKeyPress'
        },

        /**
         * Check value is numeric
         */
        onKeyPress: function(event) {        
            var newVal = $(this.el).val() + String.fromCharCode(event.keyCode);

            var numeric = /^[0-9]*\.?[0-9]*?$/.test(newVal);

            if (!numeric) event.preventDefault();
        },

        getValue: function() {        
            var value = $(this.el).val();
            
            return value === "" ? null : parseFloat(value, 10);
        },
        
        setValue: function(value) {
            value = value === null ? null : parseFloat(value, 10);
            
            editors.Text.prototype.setValue.call(this, value);
        }

    });


    editors.Password = editors.Text.extend({

        initialize: function(options) {
            editors.Text.prototype.initialize.call(this, options);

            $(this.el).attr('type', 'password');
        }

    });


    editors.TextArea = editors.Text.extend({

       tagName: 'textarea'

    });
    
    
    editors.Checkbox = editors.Base.extend({
        
        defaultValue: false,
        
        tagName: 'input',
        
        initialize: function(options) {
            editors.Base.prototype.initialize.call(this, options);
            
            $(this.el).attr('type', 'checkbox');
        },

        /**
         * Adds the editor to the DOM
         */
        render: function() {
            this.setValue(this.value);

            return this;
        },
        
        getValue: function() {
            return $(this.el).attr('checked') ? true : false;
        },
        
        setValue: function(value) {
            $(this.el).attr('checked', value);
        }
        
    });
    
    
    editors.Hidden = editors.Base.extend({
        
        defaultValue: '',

        initialize: function(options) {
            editors.Text.prototype.initialize.call(this, options);

            $(this.el).attr('type', 'hidden');
        },
        
        getValue: function() {
            return this.value;
        },
        
        setValue: function(value) {
            this.value = value;
        }

    });


    /**
     * Renders a <select> with given options
     *
     * Requires an 'options' value on the schema.
     *  Can be an array of options, a function that calls back with the array of options, a string of HTML
     *  or a Backbone collection. If a collection, the models must implement a toString() method
     */
    editors.Select = editors.Base.extend({

        tagName: 'select',

        initialize: function(options) {
            editors.Base.prototype.initialize.call(this, options);

            if (!this.schema || !this.schema.options)
                throw "Missing required 'schema.options'";
        },

        render: function() {
            var options = this.schema.options,
                self = this;

            //If a collection was passed, check if it needs fetching
            if (options instanceof Backbone.Collection) {
                var collection = options;

                //Don't do the fetch if it's already populated
                if (collection.length > 0) {
                    self.renderOptions(options);
                } else {
                    collection.fetch({
                        success: function(collection) {
                            self.renderOptions(options);
                        }
                    });
                }
            }

            //If a function was passed, run it to get the options
            else if (_.isFunction(options)) {
                options(function(result) {
                    self.renderOptions(result);
                });
            }

            //Otherwise, ready to go straight to renderOptions
            else {
                self.renderOptions(options);
            }

            return this;
        },

        /**
         * Adds the <option> html to the DOM
         * @param {Mixed}   Options as a simple array e.g. ['option1', 'option2']
         *                      or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
         *                      or as a string of <option> HTML to insert into the <select>
         */
        renderOptions: function(options) {
            var $select = $(this.el),
                html;

            //Accept string of HTML
            if (_.isString(options)) {
                html = options;
            }

            //Or array
            else if (_.isArray(options)) {
                html = this._arrayToHtml(options);
            }

            //Or Backbone collection
            else if (options instanceof Backbone.Collection) {
                html = this._collectionToHtml(options)
            }

            //Insert options
            $select.html(html);

            //Select correct option
            this.setValue(this.value);
        },

        getValue: function() {
            return $(this.el).val();
        },
        
        setValue: function(value) {
            $(this.el).val(value);
        },

        /**
         * Transforms a collection into HTML ready to use in the renderOptions method
         * @param {Backbone.Collection} 
         * @return {String}
         */
        _collectionToHtml: function(collection) {
            //Convert collection to array first
            var array = [];
            collection.each(function(model) {
                array.push({ val: model.id, label: model.toString() });
            });

            //Now convert to HTML
            var html = this._arrayToHtml(array);

            return html;
        },

        /**
         * Create the <option> HTML
         * @param {Array}   Options as a simple array e.g. ['option1', 'option2']
         *                      or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
         * @return {String} HTML
         */
        _arrayToHtml: function(array) {
            var html = [];

            //Generate HTML
            _.each(array, function(option) {
                if (_.isObject(option)) {
                    var val = option.val ? option.val : '';
                    html.push('<option value="'+val+'">'+option.label+'</option>');
                }
                else {
                    html.push('<option>'+option+'</option>');
                }
            });

            return html.join('');
        }

    });




    /**
     * Renders a <ul> with given options represented as <li> objects containing radio buttons
     *
     * Requires an 'options' value on the schema.
     *  Can be an array of options, a function that calls back with the array of options, a string of HTML
     *  or a Backbone collection. If a collection, the models must implement a toString() method
     */
    editors.Radio = editors.Select.extend({

        tagName: 'ul',
        className: 'bbf-radio',

        getValue: function() {
            return this.$('input[type=radio]:checked').val();
        },

        setValue: function(value) {
            return this.$('input[type=radio][value='+value+']').attr({checked: 'checked'});
        },

        /**
         * Create the radio list HTML
         * @param {Array}   Options as a simple array e.g. ['option1', 'option2']
         *                      or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
         * @return {String} HTML
         */
        _arrayToHtml: function (array) {
            var html = [];
            var self = this;

            _.each(array, function(option, index) {
                var itemHtml = '<li>';
                if (_.isObject(option)) {
                    var val = option.val ? option.val : '';
                    itemHtml += ('<input type="radio" name="'+self.id+'" value="'+val+'" id="'+self.id+'-'+index+'" />')
                    itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>')
                }
                else {
                    itemHtml += ('<input type="radio" name="'+self.id+'" value="'+option+'" id="'+self.id+'-'+index+'" />')
                    itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>')
                }
                itemHtml += '</li>';
                html.push(itemHtml);
            });

            return html.join('');
        }

    });




    /**
     * Creates a child form. For editing Javascript objects
     * 
     * Special options:
     *   schema.subSchema:    Subschema for object.
     *   idPrefix, 
     */
    editors.Object = editors.Base.extend({

        className: 'bbf-object',

        defaultValue: {},

        initialize: function(options) {
            editors.Base.prototype.initialize.call(this, options);

            if (!this.schema.subSchema)
                throw "Missing required 'schema.subSchema' option for Object editor";

            this.idPrefix = options.idPrefix || '';
        },

        render: function() {
            var el = $(this.el),
                data = this.value || {},
                key = this.key,
                schema = this.schema,
                objSchema = schema.subSchema;

            this.form = new Form({
                schema: objSchema,
                data: data,
                idPrefix: this.idPrefix + this.key + '_'
            });

            //Render form
            el.html(this.form.render().el);

            return this;
        },

        getValue: function() {
            return this.form.getValue();
        },
        
        setValue: function(value) {
            this.value = value;
            
            this.render();
        },

        remove: function() {
            this.form.remove();

            Backbone.View.prototype.remove.call(this);
        }

    });


    /**
     * Creates a child form. For editing nested Backbone models
     * 
     * Special options:
     *   schema.model:   Embedded model constructor
     */
    editors.NestedModel = editors.Object.extend({

        initialize: function(options) {
            editors.Base.prototype.initialize.call(this, options);

            if (!options.schema.model)
                throw 'Missing required "schema.model" option for NestedModel editor';

            this.idPrefix = options.idPrefix || '';
        },

        render: function() {
            var el = $(this.el),
                data = this.value || {},
                key = this.key,
                nestedModel = this.schema.model,
                nestedModelSchema = (nestedModel).prototype.schema;

            this.form = new Form({
                schema: nestedModelSchema,
                model: new nestedModel(data),
                idPrefix: this.idPrefix + this.key + '_'
            });

            //Render form
            el.html(this.form.render().el);

            return this;
        },

        /**
         * Update the embedded model, checking for nested validation errors and pass them up
         * Then update the main model if all OK
         *
         * @return {Error|null} Validation error or null
         */
        commit: function() {
            var error = this.form.commit();
            if (error) {
                $(this.el).addClass('error');
                return error;
            }

            return editors.Object.prototype.commit.call(this);
        }

    });
    
    
    //Exports
    Form.helpers = helpers;
    Form.Field = Field;
    Form.editors = editors;
    Form.validators = validators;
    Backbone.Form = Form;

})();
;(function() {
    
    var Form = Backbone.Form,
        Base = Form.editors.Base,
        createTemplate = Form.helpers.createTemplate,
        triggerCancellableEvent = Form.helpers.triggerCancellableEvent,
        exports = {};
    
    /**
     * Additional editors that depend on jQuery UI
     */
    exports.Date = Base.extend({

        className: 'bbf-date',
        
        initialize: function(options) {
            Base.prototype.initialize.call(this, options);
            
            if (!this.value) {
                var date = new Date();
                date.setSeconds(0);
                date.setMilliseconds(0);
                
                this.value = date;
            }
        },

        render: function() {
            var el = $(this.el);

            el.html('<input>');

            var input = $('input', el);

            input.datepicker({
                dateFormat: 'dd/mm/yy',
                showButtonPanel: true
            });

            //Make sure setValue of this object is called, not of any objects extending it (e.g. DateTime)
            exports.Date.prototype.setValue.call(this, this.value);

            return this;
        },

        /**
        * @return {Date}   Selected date
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            return date;
        },
        
        setValue: function(value) {
            $('input', this.el).datepicker('setDate', value);
        }

    });



    exports.DateTime = exports.Date.extend({

        className: 'bbf-datetime',

        template: createTemplate('<select>{{hours}}</select> : <select>{{mins}}</select>'),

        render: function() {
            function pad(n) {
                return n < 10 ? '0' + n : n
            }

            //Render the date element first
            exports.Date.prototype.render.call(this);

            //Setup hour options
            var hours = _.range(0, 24),
                hoursOptions = [];

            _.each(hours, function(hour) {
                hoursOptions.push('<option value="'+hour+'">' + pad(hour) + '</option>');
            });

            //Setup minute options
            var minsInterval = this.schema.minsInterval || 15,
                mins = _.range(0, 60, minsInterval),
                minsOptions = [];

            _.each(mins, function(min) {
                minsOptions.push('<option value="'+min+'">' + pad(min) + '</option>');
            });

            //Render time selects
            $(this.el).append(this.template({
                hours: hoursOptions.join(),
                mins: minsOptions.join()
            }));

            //Store references to selects
            this.$hours = $('select:eq(0)', this.el);
            this.$mins = $('select:eq(1)', this.el);
            
            //Set time
            this.setValue(this.value);

            return this;
        },

        /**
        * @return {Date}   Selected datetime
        */
        getValue: function() {
            var input = $('input', this.el),
                date = input.datepicker('getDate');

            date.setHours(this.$hours.val());
            date.setMinutes(this.$mins.val());
            date.setMilliseconds(0);

            return date;
        },
        
        setValue: function(date) {
            exports.Date.prototype.setValue.call(this, date);
            
            this.$hours.val(date.getHours());
            this.$mins.val(date.getMinutes());
        }

    });


    exports.List = Base.extend({

        className: 'bbf-list',

        //Note: The extra div around the <ul> is used to limit the drag area
        template: createTemplate('\
            <ul></ul>\
            <div><button class="bbf-list-add">Add</div>\
        '),

        itemTemplate: createTemplate('\
            <li rel="{{id}}">\
                <span class="bbf-list-text">{{text}}</span>\
                <div class="bbf-list-actions">\
                    <button class="bbf-list-edit">Edit</button>\
                    <button class="bbf-list-del">Delete</button>\
                </div>\
            </li>\
        '),
        
        editorTemplate: createTemplate('\
            <div class="bbf-field">\
                <div class="bbf-list-editor"></div>\
            </div>\
        '),

        events: {
            'click .bbf-list-add':   'addNewItem',
            'click .bbf-list-edit':  'editItem',
            'click .bbf-list-del':   'deleteItem'
        },

        initialize: function(options) {
            Base.prototype.initialize.call(this, options);

            if (!this.schema) throw "Missing required option 'schema'";
            
            this.schema.listType = this.schema.listType || 'Text';
            
            if (this.schema.listType == 'NestedModel' && !this.schema.model)
                throw "Missing required option 'schema.model'";
        },

        render: function() {
            var el = $(this.el);
            
            //Main element
            el.html(this.template());
            
            //Create list
            var self = this,
                el = $(this.el),
                data = this.value || [],
                schema = this.schema,
                itemToString = this.itemToString,
                itemTemplate = this.itemTemplate,
                listEl = $('ul', el);
            
            _.each(data, function(itemData) {     
                var text = itemToString.call(self, itemData);

                //Create DOM element
                var li = $(itemTemplate({
                    id: itemData.id || '',
                    text: text
                }));

                //Attach data
                $.data(li[0], 'data', itemData);

                listEl.append(li);
            });

            //Make sortable
            if (schema.sortable !== false) {
                listEl.sortable({
                    axis: 'y',
                    cursor: 'move',
                    containment: 'parent'
                });
                
                el.addClass('bbf-list-sortable');
            }

            //jQuery UI buttonize
            $('button.bbf-list-add', el).button({
                text: false,
                icons: { primary: 'ui-icon-plus' }
            });
            $('button.bbf-list-edit', el).button({
                text: false,
                icons: { primary: 'ui-icon-pencil' }
            });
            $('button.bbf-list-del', el).button({
                text: false,
                icons: { primary: 'ui-icon-trash' }
            });

            return this;
        },

        /**
         * Formats an item for display in the list
         * For example objects, dates etc. can have a custom
         * itemToString method which says how it should be formatted.
         */
        itemToString: function(data) {
            if (!data) return data;
            
            var schema = this.schema;
            
            //If there's a specified toString use that
            if (schema.itemToString)
                return schema.itemToString(data);
            
            //Otherwise check if it's NestedModel with it's own toString() method
            if (this.schema.listType == 'NestedModel') {
                var model = new (this.schema.model)(data);
                
                return model.toString();
            }
            
            //Last resort, just return the data as is
            return data;
        },

        /**
         * Add a new item to the list if it is completed in the editor
         */
        addNewItem: function(event) {
            event.preventDefault();
                     
            var self = this;

            this.openEditor(null, function(value) {
                //Fire 'addItem' cancellable event
                triggerCancellableEvent(self, 'addItem', [value], function() {
                    var text = self.itemToString(value);

                    //Create DOM element
                    var li = $(self.itemTemplate({
                        id: value.id || '',
                        text: text
                    }));

                    //Store data
                    $.data(li[0], 'data', value);

                    $('ul', self.el).append(li);

                    //jQuery UI buttonize
                    $('button.bbf-list-edit', this.el).button({
                        text: false,
                        icons: { primary: 'ui-icon-pencil' }
                    });
                    $('button.bbf-list-del', this.el).button({
                        text: false,
                        icons: { primary: 'ui-icon-trash' }
                    });
                });
            });
        },

        /**
         * Edit an existing item in the list
         */
        editItem: function(event) {
            event.preventDefault();
                   
            var self = this,
                li = $(event.target).closest('li'),
                originalValue = $.data(li[0], 'data');

            this.openEditor(originalValue, function(newValue) {
                //Fire 'editItem' cancellable event
                triggerCancellableEvent(self, 'editItem', [newValue], function() {
                    //Update display
                    $('.bbf-list-text', li).html(self.itemToString(newValue));

                    //Store data
                    $.data(li[0], 'data', newValue);
                });
            });
        },

        deleteItem: function(event) {
            event.preventDefault();
        
            var self = this,
                li = $(event.target).closest('li'),
                data = $.data(li[0], 'data');

            var confirmDelete = (this.schema.confirmDelete) ? this.schema.confirmDelete : false,
                confirmMsg = this.schema.confirmDeleteMsg || 'Are you sure?';
                        
            function remove() {
                triggerCancellableEvent(self, 'removeItem', [data], function() {
                    li.remove();
                });
            }
            
            if (this.schema.confirmDelete) {
                if (confirm(confirmMsg)) remove();
            } else {
                remove();
            }
        },

        /**
         * Opens the sub editor dialog
         * @param {Mixed}       Data (if editing existing list item, null otherwise)
         * @param {Function}    Save callback. receives: value
         */
        openEditor: function(data, callback) {
            var self = this,
                schema = this.schema,
                listType = schema.listType || 'Text';

            var editor = Form.helpers.createEditor(listType, {
                key: '',
                schema: schema,
                value: data
            }).render();
            
            var container = $(this.editorTemplate());
            $('.bbf-list-editor', container).html(editor.el);

            var close = function() {
                container.dialog('close');

                editor.remove();
                container.remove();
            };

            $(container).dialog({
                resizable:  false,
                modal:      true,
                width:      500,
                title:      data ? 'Edit item' : 'New item',
                buttons: {
                    'OK': function() {
                        callback(editor.getValue());
                        close();
                    }, 
                    'Cancel': close
                }
            });
        },

        getValue: function() {
            var data = [];

            $('li', this.el).each(function(index, li) {
                data.push($.data(li, 'data'));
            });

            return data;
        },
        
        setValue: function(value) {
            this.value = value;
            this.render();
        }

    });


    //Exports
    _.extend(Form.editors, exports);
    
})();
(function() {
  window.ColorUtil = {
    additive: function(c1, c2) {
      var A, B, G, R, a, ax, b, bx, g, gx, r, rx, _ref, _ref2;
      _ref = c1.channels(), R = _ref[0], G = _ref[1], B = _ref[2], A = _ref[3];
      _ref2 = c2.channels(), r = _ref2[0], g = _ref2[1], b = _ref2[2], a = _ref2[3];
      if (a === 0) {
        return c1;
      }
      if (A === 0) {
        return c2;
      }
      ax = 1 - (1 - a) * (1 - A);
      rx = (r * a / ax + R * A * (1 - a) / ax).round().clamp(0, 255);
      gx = (g * a / ax + G * A * (1 - a) / ax).round().clamp(0, 255);
      bx = (b * a / ax + B * A * (1 - a) / ax).round().clamp(0, 255);
      return Color(rx, gx, bx, ax);
    },
    replace: function(c1, c2) {
      return c2;
    }
  };
}).call(this);
(function() {
  var _base;
  window.Pixie || (window.Pixie = {});
  Pixie.Editor || (Pixie.Editor = {});
  (_base = Pixie.Editor).Pixel || (_base.Pixel = {});
  Pixie.Editor.Pixel.config = {
    DEBUG: false,
    IMAGE_DIR: "/assets/pixie/"
  };
}).call(this);
(function() {
  var _base;
  window.Pixie || (window.Pixie = {});
  Pixie.Editor || (Pixie.Editor = {});
  (_base = Pixie.Editor).Pixel || (_base.Pixel = {});
  Pixie.Editor.Pixel.actions = (function($) {
    var actions;
    return actions = {
      undo: {
        hotkeys: ['ctrl+z', 'meta+z'],
        perform: function(canvas) {
          return canvas.undo();
        },
        undoable: false
      },
      redo: {
        hotkeys: ["ctrl+y", "meta+z"],
        perform: function(canvas) {
          return canvas.redo();
        },
        undoable: false
      },
      clear: {
        perform: function(canvas) {
          return canvas.clear();
        }
      },
      preview: {
        menu: false,
        perform: function(canvas) {
          return canvas.preview();
        },
        undoable: false
      },
      left: {
        hotkeys: ["left"],
        menu: false,
        perform: function(canvas) {
        var deferredColors = [];

        canvas.height().times(function(y) {
          deferredColors[y] = canvas.getPixel(0, y).color();
        });

        canvas.eachPixel(function(pixel, x, y) {
          var rightPixel = canvas.getPixel(x + 1, y);

          if(rightPixel) {
            pixel.color(rightPixel.color(), 'replace');
          } else {
            pixel.color(Color(), 'replace')
          }
        });

        $.each(deferredColors, function(y, color) {
          canvas.getPixel(canvas.width() - 1, y).color(color);
        });
      }
      },
      right: {
        hotkeys: ["right"],
        menu: false,
        perform: function(canvas) {
        var width = canvas.width();
        var height = canvas.height();

        var deferredColors = [];

        height.times(function(y) {
          deferredColors[y] = canvas.getPixel(width - 1, y).color();
        });

        for(var x = width-1; x >= 0; x--) {
          for(var y = 0; y < height; y++) {
            var currentPixel = canvas.getPixel(x, y);
            var leftPixel = canvas.getPixel(x - 1, y);

            if(leftPixel) {
              currentPixel.color(leftPixel.color(), 'replace');
            } else {
              currentPixel.color(Color(), 'replace');
            }
          }
        }

        $.each(deferredColors, function(y, color) {
          canvas.getPixel(0, y).color(color);
        });
      }
      },
      up: {
        hotkeys: ["up"],
        menu: false,
        perform: function(canvas) {
        var deferredColors = [];

        canvas.width().times(function(x) {
          deferredColors[x] = canvas.getPixel(x, 0).color();
        });

        canvas.eachPixel(function(pixel, x, y) {
          var lowerPixel = canvas.getPixel(x, y + 1);

          if(lowerPixel) {
            pixel.color(lowerPixel.color(), 'replace');
          } else {
            pixel.color(Color(), 'replace');
          }
        });

        $.each(deferredColors, function(x, color) {
          canvas.getPixel(x, canvas.height() - 1).color(color);
        });
      }
      },
      down: {
        hotkeys: ["down"],
        menu: false,
        perform: function(canvas) {
        var width = canvas.width();
        var height = canvas.height();

        var deferredColors = [];

        canvas.width().times(function(x) {
          deferredColors[x] = canvas.getPixel(x, height - 1).color();
        });

        for(var x = 0; x < width; x++) {
          for(var y = height-1; y >= 0; y--) {
            var currentPixel = canvas.getPixel(x, y);
            var upperPixel = canvas.getPixel(x, y-1);

            if(upperPixel) {
              currentPixel.color(upperPixel.color(), 'replace');
            } else {
              currentPixel.color(Color(), 'replace');
            }
          }
        }

        $.each(deferredColors, function(x, color) {
          canvas.getPixel(x, 0).color(color);
        });
      }
      },
      download: {
        hotkeys: ["ctrl+s"],
        perform: function(canvas) {
          var w;
          w = window.open();
          return w.document.location = canvas.toDataURL();
        },
        undoable: false
      }
    };
  })(jQuery);
}).call(this);
/* CodeMirror main module
 *
 * Implements the CodeMirror constructor and prototype, which take care
 * of initializing the editor frame, and providing the outside interface.
 */

// The CodeMirrorConfig object is used to specify a default
// configuration. If you specify such an object before loading this
// file, the values you put into it will override the defaults given
// below. You can also assign to it after loading.
var CodeMirrorConfig = window.CodeMirrorConfig || {};

var CodeMirror = (function(){
  function setDefaults(object, defaults) {
    for (var option in defaults) {
      if (!object.hasOwnProperty(option))
        object[option] = defaults[option];
    }
  }
  function forEach(array, action) {
    for (var i = 0; i < array.length; i++)
      action(array[i]);
  }

  // These default options can be overridden by passing a set of
  // options to a specific CodeMirror constructor. See manual.html for
  // their meaning.
  setDefaults(CodeMirrorConfig, {
    stylesheet: [],
    path: "",
    parserfile: [],
    basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"],
    iframeClass: null,
    passDelay: 200,
    passTime: 50,
    lineNumberDelay: 200,
    lineNumberTime: 50,
    continuousScanning: false,
    saveFunction: null,
    onChange: null,
    undoDepth: 50,
    undoDelay: 800,
    disableSpellcheck: true,
    textWrapping: true,
    readOnly: false,
    width: "",
    height: "300px",
    minHeight: 100,
    autoMatchParens: false,
    parserConfig: null,
    tabMode: "indent", // or "spaces", "default", "shift"
    reindentOnLoad: false,
    activeTokens: null,
    cursorActivity: null,
    lineNumbers: false,
    indentUnit: 2,
    domain: null
  });

  function addLineNumberDiv(container) {
    var nums = document.createElement("DIV"),
        scroller = document.createElement("DIV");
    nums.style.position = "absolute";
    nums.style.height = "100%";
    if (nums.style.setExpression) {
      try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");}
      catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
    }
    nums.style.top = "0px";
    nums.style.left = "0px";
    nums.style.overflow = "hidden";
    container.appendChild(nums);
    scroller.className = "CodeMirror-line-numbers";
    nums.appendChild(scroller);
    scroller.innerHTML = "<div>1</div>";
    return nums;
  }

  function frameHTML(options) {
    if (typeof options.parserfile == "string")
      options.parserfile = [options.parserfile];
    if (typeof options.stylesheet == "string")
      options.stylesheet = [options.stylesheet];

    var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head>"];
    // Hack to work around a bunch of IE8-specific problems.
    html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>");
    forEach(options.stylesheet, function(file) {
      html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + "\"/>");
    });
    forEach(options.basefiles.concat(options.parserfile), function(file) {
      if (!/^https?:/.test(file)) file = options.path + file;
      html.push("<script type=\"text/javascript\" src=\"" + file + "\"><" + "/script>");
    });
    html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
              (options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
    return html.join("");
  }

  var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);

  function CodeMirror(place, options) {
    // Use passed options, if any, to override defaults.
    this.options = options = options || {};
    setDefaults(options, CodeMirrorConfig);

    // Backward compatibility for deprecated options.
    if (options.dumbTabs) options.tabMode = "spaces";
    else if (options.normalTab) options.tabMode = "default";

    var frame = this.frame = document.createElement("IFRAME");
    if (options.iframeClass) frame.className = options.iframeClass;
    frame.frameBorder = 0;
    frame.style.border = "0";
    frame.style.width = '100%';
    frame.style.height = '100%';
    // display: block occasionally suppresses some Firefox bugs, so we
    // always add it, redundant as it sounds.
    frame.style.display = "block";

    var div = this.wrapping = document.createElement("DIV");
    div.style.position = "relative";
    div.className = "CodeMirror-wrapping";
    div.style.width = options.width;
    div.style.height = (options.height == "dynamic") ? options.minHeight + "px" : options.height;
    // This is used by Editor.reroutePasteEvent
    var teHack = this.textareaHack = document.createElement("TEXTAREA");
    div.appendChild(teHack);
    teHack.style.position = "absolute";
    teHack.style.left = "-10000px";
    teHack.style.width = "10px";

    // Link back to this object, so that the editor can fetch options
    // and add a reference to itself.
    frame.CodeMirror = this;
    if (options.domain && internetExplorer) {
      this.html = frameHTML(options);
      frame.src = "javascript:(function(){document.open();" +
        (options.domain ? "document.domain=\"" + options.domain + "\";" : "") +
        "document.write(window.frameElement.CodeMirror.html);document.close();})()";
    }
    else {
      frame.src = "javascript:false";
    }

    if (place.appendChild) place.appendChild(div);
    else place(div);
    div.appendChild(frame);
    if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div);

    this.win = frame.contentWindow;
    if (!options.domain || !internetExplorer) {
      this.win.document.open();
      this.win.document.write(frameHTML(options));
      this.win.document.close();
    }
  }

  CodeMirror.prototype = {
    init: function() {
      if (this.options.initCallback) this.options.initCallback(this);
      if (this.options.lineNumbers) this.activateLineNumbers();
      if (this.options.reindentOnLoad) this.reindent();
      if (this.options.height == "dynamic") this.setDynamicHeight();
    },

    getCode: function() {return this.editor.getCode();},
    setCode: function(code) {this.editor.importCode(code);},
    selection: function() {this.focusIfIE(); return this.editor.selectedText();},
    reindent: function() {this.editor.reindent();},
    reindentSelection: function() {this.focusIfIE(); this.editor.reindentSelection(null);},

    focusIfIE: function() {
      // in IE, a lot of selection-related functionality only works when the frame is focused
      if (this.win.select.ie_selection) this.focus();
    },
    focus: function() {
      this.win.focus();
      if (this.editor.selectionSnapshot) // IE hack
        this.win.select.setBookmark(this.win.document.body, this.editor.selectionSnapshot);
    },
    replaceSelection: function(text) {
      this.focus();
      this.editor.replaceSelection(text);
      return true;
    },
    replaceChars: function(text, start, end) {
      this.editor.replaceChars(text, start, end);
    },
    getSearchCursor: function(string, fromCursor, caseFold) {
      return this.editor.getSearchCursor(string, fromCursor, caseFold);
    },

    undo: function() {this.editor.history.undo();},
    redo: function() {this.editor.history.redo();},
    historySize: function() {return this.editor.history.historySize();},
    clearHistory: function() {this.editor.history.clear();},

    grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);},
    ungrabKeys: function() {this.editor.ungrabKeys();},

    setParser: function(name, parserConfig) {this.editor.setParser(name, parserConfig);},
    setSpellcheck: function(on) {this.win.document.body.spellcheck = on;},
    setStylesheet: function(names) {
      if (typeof names === "string") names = [names];
      var activeStylesheets = {};
      var matchedNames = {};
      var links = this.win.document.getElementsByTagName("link");
      // Create hashes of active stylesheets and matched names.
      // This is O(n^2) but n is expected to be very small.
      for (var x = 0, link; link = links[x]; x++) {
        if (link.rel.indexOf("stylesheet") !== -1) {
          for (var y = 0; y < names.length; y++) {
            var name = names[y];
            if (link.href.substring(link.href.length - name.length) === name) {
              activeStylesheets[link.href] = true;
              matchedNames[name] = true;
            }
          }
        }
      }
      // Activate the selected stylesheets and disable the rest.
      for (var x = 0, link; link = links[x]; x++) {
        if (link.rel.indexOf("stylesheet") !== -1) {
          link.disabled = !(link.href in activeStylesheets);
        }
      }
      // Create any new stylesheets.
      for (var y = 0; y < names.length; y++) {
        var name = names[y];
        if (!(name in matchedNames)) {
          var link = this.win.document.createElement("link");
          link.rel = "stylesheet";
          link.type = "text/css";
          link.href = name;
          this.win.document.getElementsByTagName('head')[0].appendChild(link);
        }
      }
    },
    setTextWrapping: function(on) {
      if (on == this.options.textWrapping) return;
      this.win.document.body.style.whiteSpace = on ? "" : "nowrap";
      this.options.textWrapping = on;
      if (this.lineNumbers) {
        this.setLineNumbers(false);
        this.setLineNumbers(true);
      }
    },
    setIndentUnit: function(unit) {this.win.indentUnit = unit;},
    setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;},
    setTabMode: function(mode) {this.options.tabMode = mode;},
    setLineNumbers: function(on) {
      if (on && !this.lineNumbers) {
        this.lineNumbers = addLineNumberDiv(this.wrapping);
        this.activateLineNumbers();
      }
      else if (!on && this.lineNumbers) {
        this.wrapping.removeChild(this.lineNumbers);
        this.wrapping.style.marginLeft = "";
        this.lineNumbers = null;
      }
    },

    cursorPosition: function(start) {this.focusIfIE(); return this.editor.cursorPosition(start);},
    firstLine: function() {return this.editor.firstLine();},
    lastLine: function() {return this.editor.lastLine();},
    nextLine: function(line) {return this.editor.nextLine(line);},
    prevLine: function(line) {return this.editor.prevLine(line);},
    lineContent: function(line) {return this.editor.lineContent(line);},
    setLineContent: function(line, content) {this.editor.setLineContent(line, content);},
    removeLine: function(line){this.editor.removeLine(line);},
    insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);},
    selectLines: function(startLine, startOffset, endLine, endOffset) {
      this.win.focus();
      this.editor.selectLines(startLine, startOffset, endLine, endOffset);
    },
    nthLine: function(n) {
      var line = this.firstLine();
      for (; n > 1 && line !== false; n--)
        line = this.nextLine(line);
      return line;
    },
    lineNumber: function(line) {
      var num = 0;
      while (line !== false) {
        num++;
        line = this.prevLine(line);
      }
      return num;
    },
    jumpToLine: function(line) {
      if (typeof line == "number") line = this.nthLine(line);
      this.selectLines(line, 0);
      this.win.focus();
    },
    currentLine: function() { // Deprecated, but still there for backward compatibility
      return this.lineNumber(this.cursorLine());
    },
    cursorLine: function() {
      return this.cursorPosition().line;
    },
    cursorCoords: function(start) {return this.editor.cursorCoords(start);},

    activateLineNumbers: function() {
      var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body,
          nums = this.lineNumbers, scroller = nums.firstChild, self = this;
      var barWidth = null;

      function sizeBar() {
        if (frame.offsetWidth == 0) return;
        for (var root = frame; root.parentNode; root = root.parentNode);
        if (!nums.parentNode || root != document || !win.Editor) {
          // Clear event handlers (their nodes might already be collected, so try/catch)
          try{clear();}catch(e){}
          clearInterval(sizeInterval);
          return;
        }

        if (nums.offsetWidth != barWidth) {
          barWidth = nums.offsetWidth;
          frame.parentNode.style.paddingLeft = barWidth + "px";
        }
      }
      function doScroll() {
        nums.scrollTop = body.scrollTop || doc.documentElement.scrollTop || 0;
      }
      // Cleanup function, registered by nonWrapping and wrapping.
      var clear = function(){};
      sizeBar();
      var sizeInterval = setInterval(sizeBar, 500);

      function ensureEnoughLineNumbers(fill) {
        var lineHeight = scroller.firstChild.offsetHeight;
        if (lineHeight == 0) return;
        var targetHeight = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)),
            lastNumber = Math.ceil(targetHeight / lineHeight);
        for (var i = scroller.childNodes.length; i <= lastNumber; i++) {
          var div = document.createElement("DIV");
          div.appendChild(document.createTextNode(fill ? String(i + 1) : "\u00a0"));
          scroller.appendChild(div);
        }
      }

      function nonWrapping() {
        function update() {
          ensureEnoughLineNumbers(true);
          doScroll();
        }
        self.updateNumbers = update;
        var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
            onResize = win.addEventHandler(win, "resize", update, true);
        clear = function(){
          onScroll(); onResize();
          if (self.updateNumbers == update) self.updateNumbers = null;
        };
        update();
      }

      function wrapping() {
        var node, lineNum, next, pos, changes = [], styleNums = self.options.styleNumbers;

        function setNum(n, node) {
          // Does not typically happen (but can, if you mess with the
          // document during the numbering)
          if (!lineNum) lineNum = scroller.appendChild(document.createElement("DIV"));
          if (styleNums) styleNums(lineNum, node, n);
          // Changes are accumulated, so that the document layout
          // doesn't have to be recomputed during the pass
          changes.push(lineNum); changes.push(n);
          pos = lineNum.offsetHeight + lineNum.offsetTop;
          lineNum = lineNum.nextSibling;
        }
        function commitChanges() {
          for (var i = 0; i < changes.length; i += 2)
            changes[i].innerHTML = changes[i + 1];
          changes = [];
        }
        function work() {
          if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return;

          var endTime = new Date().getTime() + self.options.lineNumberTime;
          while (node) {
            setNum(next++, node.previousSibling);
            for (; node && !win.isBR(node); node = node.nextSibling) {
              var bott = node.offsetTop + node.offsetHeight;
              while (scroller.offsetHeight && bott - 3 > pos) setNum("&nbsp;");
            }
            if (node) node = node.nextSibling;
            if (new Date().getTime() > endTime) {
              commitChanges();
              pending = setTimeout(work, self.options.lineNumberDelay);
              return;
            }
          }
          commitChanges();
          doScroll();
        }
        function start() {
          doScroll();
          ensureEnoughLineNumbers(false);
          node = body.firstChild;
          lineNum = scroller.firstChild;
          pos = 0;
          next = 1;
          work();
        }

        start();
        var pending = null;
        function update() {
          if (pending) clearTimeout(pending);
          if (self.editor.allClean()) start();
          else pending = setTimeout(update, 200);
        }
        self.updateNumbers = update;
        var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
            onResize = win.addEventHandler(win, "resize", update, true);
        clear = function(){
          if (pending) clearTimeout(pending);
          if (self.updateNumbers == update) self.updateNumbers = null;
          onScroll();
          onResize();
        };
      }
      (this.options.textWrapping || this.options.styleNumbers ? wrapping : nonWrapping)();
    },

    setDynamicHeight: function() {
      var self = this, activity = self.options.cursorActivity, win = self.win, body = win.document.body,
          lineHeight = null, timeout = null, vmargin = 2 * self.frame.offsetTop;
      body.style.overflowY = "hidden";
      win.document.documentElement.style.overflowY = "hidden";
      this.frame.scrolling = "no";

      function updateHeight() {
        for (var span = body.firstChild, sawBR = false; span; span = span.nextSibling)
          if (win.isSpan(span) && span.offsetHeight) {
            lineHeight = span.offsetHeight;
            if (!sawBR) vmargin = 2 * (self.frame.offsetTop + span.offsetTop + body.offsetTop + (internetExplorer ? 10 : 0));
            break;
          }
        if (lineHeight)
          self.wrapping.style.height = Math.max(vmargin + lineHeight * (body.getElementsByTagName("BR").length + 1),
                                                self.options.minHeight) + "px";
      }
      setTimeout(updateHeight, 100);
      self.options.cursorActivity = function(x) {
        if (activity) activity(x);
        clearTimeout(timeout);
        timeout = setTimeout(updateHeight, 200);
      };
    }
  };

  CodeMirror.InvalidLineHandle = {toString: function(){return "CodeMirror.InvalidLineHandle";}};

  CodeMirror.replace = function(element) {
    if (typeof element == "string")
      element = document.getElementById(element);
    return function(newElement) {
      element.parentNode.replaceChild(newElement, element);
    };
  };

  CodeMirror.fromTextArea = function(area, options) {
    if (typeof area == "string")
      area = document.getElementById(area);

    options = options || {};
    if (area.style.width && options.width == null)
      options.width = area.style.width;
    if (area.style.height && options.height == null)
      options.height = area.style.height;
    if (options.content == null) options.content = area.value;

    if (area.form) {
      function updateField() {
        area.value = mirror.getCode();
      }
      if (typeof area.form.addEventListener == "function")
        area.form.addEventListener("submit", updateField, false);
      else
        area.form.attachEvent("onsubmit", updateField);
      var realSubmit = area.form.submit;
      function wrapSubmit() {
        updateField();
        // Can't use realSubmit.apply because IE6 is too stupid
        area.form.submit = realSubmit;
        area.form.submit();
        area.form.submit = wrapSubmit;
      }
      area.form.submit = wrapSubmit;
    }

    function insert(frame) {
      if (area.nextSibling)
        area.parentNode.insertBefore(frame, area.nextSibling);
      else
        area.parentNode.appendChild(frame);
    }

    area.style.display = "none";
    var mirror = new CodeMirror(insert, options);
    return mirror;
  };

  CodeMirror.isProbablySupported = function() {
    // This is rather awful, but can be useful.
    var match;
    if (window.opera)
      return Number(window.opera.version()) >= 9.52;
    else if (/Apple Computers, Inc/.test(navigator.vendor) && (match = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)?)\./)))
      return Number(match[1]) >= 3;
    else if (document.selection && window.ActiveXObject && (match = navigator.userAgent.match(/MSIE (\d+(?:\.\d*)?)\b/)))
      return Number(match[1]) >= 6;
    else if (match = navigator.userAgent.match(/gecko\/(\d{8})/i))
      return Number(match[1]) >= 20050901;
    else if (match = navigator.userAgent.match(/AppleWebKit\/(\d+)/))
      return Number(match[1]) >= 525;
    else
      return null;
  };

  return CodeMirror;
})();
/* Demonstration of embedding CodeMirror in a bigger application. The
 * interface defined here is a mess of prompts and confirms, and
 * should probably not be used in a real project.
 */


function MirrorFrame(place, options) {
  this.home = document.createElement("DIV");
  if (place.appendChild)
    place.appendChild(this.home);
  else
    place(this.home);

  var self = this;
  function makeButton(name, action) {
    var button = document.createElement("INPUT");
    button.type = "button";
    button.value = name;
    self.home.appendChild(button);
    button.onclick = function(){self[action].call(self);};
  }

  makeButton("Search", "search");
  makeButton("Replace", "replace");
  makeButton("Current line", "line");
  makeButton("Jump to line", "jump");
  makeButton("Insert constructor", "macro");
  makeButton("Indent all", "reindent");

  this.mirror = new CodeMirror(this.home, options);
}

MirrorFrame.prototype = {
  search: function() {
    var text = prompt("Enter search term:", "");
    if (!text) return;

    var first = true;
    do {
      var cursor = this.mirror.getSearchCursor(text, first);
      first = false;
      while (cursor.findNext()) {
        cursor.select();
        if (!confirm("Search again?"))
          return;
      }
    } while (confirm("End of document reached. Start over?"));
  },

  replace: function() {
    // This is a replace-all, but it is possible to implement a
    // prompting replace.
    var from = prompt("Enter search string:", ""), to;
    if (from) to = prompt("What should it be replaced with?", "");
    if (to == null) return;

    var cursor = this.mirror.getSearchCursor(from, false);
    while (cursor.findNext())
      cursor.replace(to);
  },

  jump: function() {
    var line = prompt("Jump to line:", "");
    if (line && !isNaN(Number(line)))
      this.mirror.jumpToLine(Number(line));
  },

  line: function() {
    alert("The cursor is currently at line " + this.mirror.currentLine());
    this.mirror.focus();
  },

  macro: function() {
    var name = prompt("Name your constructor:", "");
    if (name)
      this.mirror.replaceSelection("function " + name + "() {\n  \n}\n\n" + name + ".prototype = {\n  \n};\n");
  },

  reindent: function() {
    this.mirror.reindent();
  }
};
(function($) {
  $.template("pixie/console", "<div class=\'console\'>\n  <div class=\'actions\'><\/div>\n  <textarea><\/textarea>\n  <pre class=\'output\'><\/pre>\n<\/div>\n");
})(jQuery);
(function() {
  window.Pixie || (window.Pixie = {});
  (function($) {
    var DEFAULTS;
    DEFAULTS = {
      evalContext: eval,
      maxHistoryLength: 20
    };
    return Pixie.Console = function(options) {
      var actionBar, actions, config, editor, evalContext, history, historyPosition, input, keyBindings, lang, maxHistoryLength, next, output, prev, print, record, run, self;
      self = $.tmpl("pixie/console");
      config = Object.extend({}, DEFAULTS, options);
      evalContext = config.evalContext, maxHistoryLength = config.maxHistoryLength;
      history = [];
      historyPosition = -1;
      prev = function() {
        historyPosition += 1;
        return self.val(history.wrap(historyPosition));
      };
      next = function() {
        historyPosition -= 1;
        return self.val(history.wrap(historyPosition));
      };
      record = function(command) {
        history.unshift(command);
        if (history.length > maxHistoryLength) {
          history.length = maxHistoryLength;
        }
        return historyPosition = -1;
      };
      print = function(message) {
        if ((message != null ? message.toString : void 0) != null) {
          message = message.toString();
        }
        return output.text(message);
      };
      run = function() {
        var command, compiledCommand, result;
        if (!(command = editor.getCode())) {
          return;
        }
        try {
          compiledCommand = CoffeeScript.compile(command, {
            bare: true
          });
          result = evalContext(compiledCommand);
          self.val("");
          record(command);
        } catch (error) {
          result = error.message;
        }
        print(result);
        return result;
      };
      actions = {
        prev: {
          perform: prev
        },
        next: {
          perform: next
        },
        run: {
          perform: run
        }
      };
      input = self.find("textarea");
      lang = "coffeescript";
      editor = null;
      keyBindings = {
        "shift+return": run,
        "pageup": prev,
        "pagedown": next
      };
      setTimeout(function() {
        var binding, handler, _results;
        editor = new CodeMirror.fromTextArea(input.get(0), {
          autoMatchParens: true,
          lineNumbers: true,
          parserfile: ["tokenize_" + lang + ".js", "parse_" + lang + ".js"],
          path: "/assets/codemirror/",
          stylesheet: ["/assets/codemirror/main.css"],
          tabMode: "shift",
          textWrapping: false
        });
        $(editor.win.document).find('html').addClass("light");
        _results = [];
        for (binding in keyBindings) {
          handler = keyBindings[binding];
          _results.push((function(handler) {
            return $(editor.win.document).bind("keydown", binding, function(e) {
              e.preventDefault();
              return handler();
            });
          })(handler));
        }
        return _results;
      }, 10);
      output = self.find(".output");
      actionBar = self.find(".actions");
      Object.extend(self, {
        val: function(newVal) {
          if (newVal != null) {
            return editor.setCode(newVal);
          } else {
            return editor.getCode();
          }
        },
        addAction: function(action) {
          var actionElement, name, perform, titleText;
          name = action.name;
          titleText = name.capitalize();
          perform = function() {
            return action.perform(self);
          };
          actionElement = $("<button />", {
            text: titleText,
            title: titleText
          }).bind("mousedown touchstart", function(e) {
            if (!$(this).attr('disabled')) {
              return perform();
            }
          });
          return actionElement.appendTo(actionBar);
        }
      });
      $.each(actions, function(key, action) {
        action.name = key;
        return self.addAction(action);
      });
      return self;
    };
  })(jQuery);
}).call(this);
(function($) {
  $.template("pixie/window", "<div class=\'window\'>\n  <span class=\'ui-icon ui-icon-close\'><\/span>\n  <h3 class=\'ui-widget-header\'>${ title }<\/h3>\n  <div class=\'content\'><\/div>\n<\/div>\n");
})(jQuery);
(function() {
  window.Pixie || (window.Pixie = {});
  Pixie.Window = function(I) {
    var self;
    if (I == null) {
      I = {};
    }
    self = $.tmpl("pixie/window", I);
    self.draggable({
      handle: "h3",
      iframeFix: true
    }).find("h3").disableSelection();
    return self;
  };
}).call(this);
(function() {
  Pixie.Editor.Pixel.Console = function(I, self) {
    var console, consoleWindow, recipeIndex, recipes;
    consoleWindow = Pixie.Window({
      title: "Console"
    }).hide().appendTo("body").css({
      position: "absolute",
      top: "125px",
      left: "250px"
    });
    console = Pixie.Console({
      evalContext: self.eval
    });
    consoleWindow.find(".content").append(console);
    recipeIndex = 0;
    recipes = ["# this makes a gradient\nself.eachPixel (pixel, x, y) ->\n  r = x * 8\n  g = y * 8\n  b = 128\n  pixel.color(Color(r, g, b))", "# Flip image horizontally\nself.eachPixel (pixel, x, y) ->\n  return if x >= I.width / 2\n  currentColor = pixels[y][x].color()\n  oppositePosition = I.width - 1 - x\n\n  flipColor = pixels[y][oppositePosition].color()\n  pixel.color(flipColor)\n  pixels[y][oppositePosition].color(currentColor)"];
    console.addAction({
      name: "Recipes",
      perform: function() {
        console.val(recipes.wrap(recipeIndex));
        return recipeIndex += 1;
      }
    });
    self.addAction({
      name: "console",
      perform: function() {
        return consoleWindow.toggle();
      }
    });
    return {};
  };
}).call(this);
(function() {
  Pixie.Editor.Pixel.Layer = function(I) {
    var context, layer, layerElement, layerHeight, layerWidth;
    layer = $("<canvas />", {
      "class": "layer"
    });
    layerWidth = function() {
      return I.width * I.pixelWidth;
    };
    layerHeight = function() {
      return I.height * I.pixelHeight;
    };
    layerElement = layer.get(0);
    layerElement.width = layerWidth();
    layerElement.height = layerHeight();
    context = layerElement.getContext("2d");
    return $.extend(layer, {
      context: context,
      resize: function() {
        layerElement.width = layerWidth();
        return layerElement.height = layerHeight();
      }
    });
  };
}).call(this);
(function() {
  Pixie.Editor.Pixel.palette = ["#000000", "#FFFFFF", "#666666", "#DCDCDC", "#EB070E", "#F69508", "#FFDE49", "#388326", "#0246E3", "#563495", "#58C4F5", "#E5AC99", "#5B4635", "#FFFEE9"];
}).call(this);
(function() {
  var Pixel;
  Pixel = function(I) {
    var changed, color, oldColor, self, x, y;
    if (I == null) {
      I = {};
    }
    x = I.x, y = I.y, color = I.color, oldColor = I.oldColor, changed = I.changed;
    color || (color = Color(0, 0, 0, 0));
    oldColor || (oldColor = Color(0, 0, 0, 0));
    return self = {
      color: function(newColor, blendMode) {
        if (blendMode == null) {
          blendMode = "additive";
        }
        if (arguments.length >= 1) {
          oldColor = color;
          newColor = Color(newColor);
          color = ColorUtil[blendMode](oldColor, newColor);
          if (typeof changed === "function") {
            changed(self);
          }
          return self;
        } else {
          return color;
        }
      },
      oldColor: function() {
        return oldColor;
      },
      x: x,
      y: y,
      toString: function() {
        return "[Pixel: " + [x, y].join(",") + "]";
      }
    };
  };
  Pixie.Editor.Pixel.Pixel = Pixel;
}).call(this);
(function() {
  var _base;
  window.Pixie || (window.Pixie = {});
  Pixie.Editor || (Pixie.Editor = {});
  (_base = Pixie.Editor).Pixel || (_base.Pixel = {});
  Pixie.Editor.Pixel.tools = (function($) {
    var DEBUG, IMAGE_DIR, colorNeighbors, erase, floodFill, line, pencilTool, tools, _ref;
    _ref = Pixie.Editor.Pixel.config, IMAGE_DIR = _ref.IMAGE_DIR, DEBUG = _ref.DEBUG;
    colorNeighbors = function(color) {
      this.color(color);
      return $.each(this.canvas.getNeighbors(this.x, this.y), function(i, neighbor) {
        return neighbor != null ? neighbor.color(color) : void 0;
      });
    };
    erase = function(pixel, opacity) {
      var inverseOpacity, pixelColor;
      inverseOpacity = 1 - opacity;
      pixelColor = pixel.color();
      return pixel.color(Color(pixelColor.toString(), pixelColor.a * inverseOpacity), "replace");
    };
    floodFill = function(e, newColor, pixel) {
      var canvas, neighbors, originalColor, q;
      originalColor = this.color();
      if (newColor.equal(originalColor)) {
        return;
      }
      q = [];
      pixel.color(newColor);
      q.push(pixel);
      canvas = this.canvas;
      while (q.length) {
        pixel = q.pop();
        neighbors = canvas.getNeighbors(pixel.x, pixel.y);
        $.each(neighbors, function(index, neighbor) {
          if (neighbor != null ? neighbor.color().equal(originalColor) : void 0) {
            neighbor.color(newColor);
            return q.push(neighbor);
          }
        });
      }
    };
    line = function(canvas, color, p0, p1) {
      var dx, dy, e2, err, sx, sy, x0, x1, y0, y1, _results;
      x0 = p0.x, y0 = p0.y;
      x1 = p1.x, y1 = p1.y;
      dx = (x1 - x0).abs();
      dy = (y1 - y0).abs();
      sx = (x1 - x0).sign();
      sy = (y1 - y0).sign();
      err = dx - dy;
      canvas.getPixel(x0, y0).color(color);
      _results = [];
      while (!(x0 === x1 && y0 === y1)) {
        e2 = 2 * err;
        if (e2 > -dy) {
          err -= dy;
          x0 += sx;
        }
        if (e2 < dx) {
          err += dx;
          y0 += sy;
        }
        _results.push(canvas.getPixel(x0, y0).color(color));
      }
      return _results;
    };
    pencilTool = (function() {
      var lastPosition;
      lastPosition = Point(0, 0);
      return {
        cursor: "url(" + IMAGE_DIR + "pencil.png) 4 14, default",
        hotkeys: ['p', '1'],
        mousedown: function(e, color) {
          var currentPosition;
          currentPosition = Point(this.x, this.y);
          if (e.shiftKey) {
            line(this.canvas, color, lastPosition, currentPosition);
          } else {
            this.color(color);
          }
          return lastPosition = currentPosition;
        },
        mouseenter: function(e, color) {
          var currentPosition;
          currentPosition = Point(this.x, this.y);
          line(this.canvas, color, lastPosition, currentPosition);
          return lastPosition = currentPosition;
        }
      };
    })();
    return tools = {
      pencil: pencilTool,
      mirror_pencil: {
        cursor: "url(" + IMAGE_DIR + "mirror_pencil.png) 8 14, default",
        hotkeys: ['m'],
        mousedown: function(e, color) {
          var mirrorCoordinate;
          mirrorCoordinate = this.canvas.width() - this.x - 1;
          this.color(color);
          return this.canvas.getPixel(mirrorCoordinate, this.y).color(color);
        },
        mouseenter: function(e, color) {
          var mirrorCoordinate;
          mirrorCoordinate = this.canvas.width() - this.x - 1;
          this.color(color);
          return this.canvas.getPixel(mirrorCoordinate, this.y).color(color);
        }
      },
      brush: {
        cursor: "url(" + IMAGE_DIR + "brush.png) 4 14, default",
        hotkeys: ['b', '2'],
        mousedown: function(e, color) {
          return colorNeighbors.call(this, color);
        },
        mouseenter: function(e, color) {
          return colorNeighbors.call(this, color);
        }
      },
      dropper: {
        cursor: "url(" + IMAGE_DIR + "dropper.png) 13 13, default",
        hotkeys: ['i', '3'],
        mousedown: function(e) {
          this.canvas.color(this.color());
          if (!e.shiftKey) {
            return this.canvas.setTool(tools.pencil);
          }
        }
      },
      eraser: {
        cursor: "url(" + IMAGE_DIR + "eraser.png) 4 11, default",
        hotkeys: ['e', '4'],
        mousedown: function(e, color, pixel) {
          return erase(pixel, color.a);
        },
        mouseenter: function(e, color, pixel) {
          return erase(pixel, color.a);
        }
      },
      fill: {
        cursor: "url(" + IMAGE_DIR + "fill.png) 12 13, default",
        hotkeys: ['f', '5'],
        mousedown: floodFill,
        mouseenter: floodFill
      }
    };
  })(jQuery);
}).call(this);
(function() {
  window.UndoStack = function() {
    var empty, redos, undos;
    undos = [];
    redos = [];
    empty = true;
    return {
      last: function() {
        return undos[undos.length - 1];
      },
      popUndo: function() {
        var undo;
        undo = undos.pop();
        if (undo) {
          redos.push(undo);
        }
        return undo;
      },
      popRedo: function() {
        var redo;
        redo = redos.pop();
        if (redo) {
          undos.push(redo);
        }
        return redo;
      },
      next: function() {
        var last;
        last = this.last();
        if (!last || !empty) {
          undos.push({});
          empty = true;
          return redos = [];
        }
      },
      add: function(object, data) {
        var last;
        last = this.last();
        if (!last) {
          this.next();
          last = this.last();
        }
        if (last[object]) {
          last[object].newColor = data.newColor;
        } else {
          last[object] = data;
          empty = false;
        }
        return this;
      },
      replayData: function() {
        var replayData;
        replayData = [];
        $.each(undos, function(i, items) {
          replayData[i] = [];
          return $.each(items, function(key, data) {
            var pixel;
            pixel = data.pixel;
            return replayData[i].push({
              x: pixel.x,
              y: pixel.y,
              color: data.newColor.toString()
            });
          });
        });
        return replayData;
      }
    };
  };
}).call(this);
(function() {
  (function($) {
    return Pixie.Editor.Pixel.Undo = function(I, self) {
      var lastClean, noUndo, undoStack;
      undoStack = UndoStack();
      noUndo = 0;
      lastClean = void 0;
      $.extend(self, {
        addUndoData: function(pixel, oldColor, newColor) {
          if (!noUndo) {
            return undoStack.add(pixel, {
              pixel: pixel,
              oldColor: oldColor,
              newColor: newColor
            });
          }
        },
        dirty: function(newDirty) {
          if (newDirty != null) {
            if (newDirty === false) {
              lastClean = undoStack.last();
            }
            return this;
          } else {
            return lastClean !== undoStack.last();
          }
        },
        getReplayData: function() {
          return undoStack.replayData();
        },
        nextUndo: function() {
          return undoStack.next();
        },
        redo: function() {
          var data;
          data = undoStack.popRedo();
          if (data) {
            self.trigger("dirty");
            return self.withoutUndo(function() {
              return $.each(data, function() {
                return this.pixel.color(this.newColor, "replace");
              });
            });
          }
        },
        undo: function() {
          var data;
          data = undoStack.popUndo();
          if (data) {
            self.trigger("dirty");
            return self.withoutUndo(function() {
              return $.each(data, function() {
                return this.pixel.color(this.oldColor, "replace");
              });
            });
          }
        },
        withoutUndo: function(fn) {
          noUndo += 1;
          fn();
          return noUndo -= 1;
        }
      });
      return self.bind("initialized", function() {
        return self.dirty(false);
      });
    };
  })(jQuery);
}).call(this);
(function($) {
  $.template("editors/pixel", "<div class=\'editor pixie\'>\n  <div class=\'content\'>\n    <div class=\'actions\'><\/div>\n    <div class=\'viewport\'>\n      <div class=\'canvas\'><\/div>\n    <\/div>\n    <div class=\'toolbar module left\'><\/div>\n    <div class=\'module right\'>\n      <div class=\'color_picker_holder\'><\/div>\n      <div class=\'toolbar\'>\n        <div class=\'swatches\'><\/div>\n      <\/div>\n      <div class=\'preview\'><\/div>\n      <div class=\'opacity\'><\/div>\n    <\/div>\n  <\/div>\n<\/div>\n");
})(jQuery);
(function() {
  var elements;
  window.Pixie || (window.Pixie = {});
  /**
  Simple jQuery constructor wrappers for common elements.
  */
  elements = ["Button", "Canvas", "Div", "Img", "Input"];
  Pixie.UI = {};
  elements.each(function(type) {
    var tag;
    tag = type.toLowerCase();
    return Pixie.UI[type] = function(options) {
      return jQuery("<" + tag + "/>", options);
    };
  });
  Pixie.UI.Image = Pixie.UI.Img;
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  (function($) {
    var Button, ColorPicker, DEBUG, Div, IMAGE_DIR, Image, Input, Layer, Pixel, actions, palette, primaryButton, tools, track, _ref, _ref2, _ref3;
    track = function(action, label) {
      return typeof trackEvent === "function" ? trackEvent("Pixel Editor", action, label) : void 0;
    };
    _ref = Pixie.Editor.Pixel, actions = _ref.actions, _ref2 = _ref.config, IMAGE_DIR = _ref2.IMAGE_DIR, DEBUG = _ref2.DEBUG, palette = _ref.palette, tools = _ref.tools, Layer = _ref.Layer, Pixel = _ref.Pixel;
    _ref3 = Pixie.UI, Button = _ref3.Button, Div = _ref3.Div, Image = _ref3.Image, Input = _ref3.Input;
    primaryButton = function(event) {
      return !(event.button != null) || event.button === 0;
    };
    ColorPicker = function() {
      return Input({
        "class": 'color'
      }).colorPicker({
        leadingHash: false
      });
    };
    return Pixie.Editor.Pixel.create = function(I) {
      var actionbar, active, canvas, colorPickerHolder, colorbar, content, currentTool, guideLayer, handleEvent, initialStateData, initializer, lastPixel, layer, layers, mode, noUndo, opacitySlider, opacityVal, pixelChanged, pixels, preview, primaryColorPicker, replaying, secondaryColorPicker, self, swatches, tilePreview, toolbar, viewport;
      if (I == null) {
        I = {};
      }
      I.width = parseInt(I.width || 8, 10);
      I.height = parseInt(I.height || 8, 10);
      initializer = I.initializer;
      I.pixelWidth = parseInt(I.pixelWidth || I.pixelSize || 16, 10);
      I.pixelHeight = parseInt(I.pixelHeight || I.pixelSize || 16, 10);
      self = $.tmpl("editors/pixel");
      content = self.find(".content");
      viewport = self.find(".viewport");
      canvas = self.find(".canvas").css({
        width: I.width * I.pixelWidth + 2,
        height: I.height * I.pixelHeight + 2
      });
      actionbar = self.find(".actions");
      toolbar = self.find(".toolbar.left");
      swatches = self.find(".swatches");
      colorbar = self.find(".module.right .toolbar");
      colorPickerHolder = self.find(".color_picker_holder");
      colorbar.append(colorPickerHolder, swatches);
      opacityVal = Div({
        "class": "val",
        text: 100
      });
      opacitySlider = self.find(".opacity").slider({
        orientation: 'vertical',
        value: 100,
        min: 5,
        max: 100,
        step: 5,
        slide: function(event, ui) {
          return opacityVal.text(ui.value);
        }
      }).append(opacityVal);
      opacityVal.text(opacitySlider.slider('value'));
      preview = self.find(".preview").css({
        width: I.width,
        height: I.height
      });
      currentTool = void 0;
      active = false;
      mode = void 0;
      primaryColorPicker = ColorPicker().addClass('primary').appendTo(colorPickerHolder);
      secondaryColorPicker = ColorPicker().addClass('secondary').appendTo(colorPickerHolder);
      noUndo = false;
      replaying = false;
      tilePreview = true;
      initialStateData = void 0;
      pixelChanged = function(pixel) {
        var color, layerCanvas, oldColor, x, xPos, y, yPos;
        x = pixel.x, y = pixel.y;
        color = pixel.color();
        oldColor = pixel.oldColor();
        xPos = x * I.pixelWidth;
        yPos = y * I.pixelHeight;
        layerCanvas = layer.context;
        layerCanvas.clearRect(xPos, yPos, I.pixelWidth, I.pixelHeight);
        layerCanvas.fillStyle = color.toString();
        layerCanvas.fillRect(xPos, yPos, I.pixelWidth, I.pixelHeight);
        return self.addUndoData(pixel, oldColor, color);
      };
      self.bind('contextmenu', function() {
        return false;
      }).bind('mouseup', function(e) {
        active = false;
        mode = void 0;
        return self.preview();
      });
      preview.mousedown(function() {
        tilePreview = !tilePreview;
        self.preview();
        return track('mousedown', 'preview');
      });
      swatches.bind('mousedown touchstart', function(e) {
        var color, target;
        target = $(e.target);
        if (target.is('.swatch')) {
          color = Color(target.css('backgroundColor'));
          self.color(color, !primaryButton(e));
          return track(e.type, color.toString());
        }
      });
      pixels = [];
      lastPixel = void 0;
      handleEvent = function(event, element) {
        var col, color, eventType, local, offset, opacity, pixel, row;
        opacity = opacityVal.text() / 100;
        offset = element.offset();
        local = {
          y: event.pageY - offset.top,
          x: event.pageX - offset.left
        };
        row = Math.floor(local.y / I.pixelHeight);
        col = Math.floor(local.x / I.pixelWidth);
        pixel = self.getPixel(col, row);
        eventType = void 0;
        if ((event.type === "mousedown") || (event.type === "touchstart")) {
          eventType = "mousedown";
        } else if (pixel && pixel !== lastPixel && (event.type === "mousemove" || event.type === "touchmove")) {
          eventType = "mouseenter";
        }
        if (pixel && active && currentTool && currentTool[eventType]) {
          color = self.color().toString();
          currentTool[eventType].call({
            canvas: self,
            x: pixel.x,
            y: pixel.y,
            color: pixel.color
          }, event, Color(color, opacity), pixel);
        }
        return lastPixel = pixel;
      };
      layer = Layer(I);
      guideLayer = Layer(I).bind("mousedown touchstart", function(e) {
        self.trigger("dirty");
        self.nextUndo();
        active = true;
        if (primaryButton(e)) {
          mode = "P";
        } else {
          mode = "S";
        }
        return e.preventDefault();
      }).bind("mousedown mousemove", function(event) {
        return handleEvent(event, $(this));
      }).bind("touchstart touchmove", function(e) {
        return Array.prototype.each.call(event.touches, __bind(function(touch) {
          touch.type = e.type;
          return handleEvent(touch, $(this));
        }, this));
      });
      layers = [layer, guideLayer];
      I.height.times(function(row) {
        pixels[row] = [];
        return I.width.times(function(col) {
          var pixel;
          pixel = Pixel({
            changed: pixelChanged,
            x: col,
            y: row
          });
          return pixels[row][col] = pixel;
        });
      });
      canvas.append(layer, guideLayer);
      $.extend(self, {
        addAction: function(action) {
          var actionButton, doIt, iconImg, name, titleText, undoable;
          name = action.name;
          titleText = name.capitalize();
          undoable = action.undoable;
          doIt = function() {
            if (undoable) {
              self.trigger("dirty");
              self.nextUndo();
            }
            return action.perform(self);
          };
          if (action.hotkeys) {
            titleText += " (" + action.hotkeys + ") ";
            $.each(action.hotkeys, function(i, hotkey) {
              return $(document).bind('keydown', hotkey, function(e) {
                if (currentComponent === self) {
                  e.preventDefault();
                  doIt();
                  track('hotkey', action.name);
                  return false;
                }
              });
            });
          }
          if (action.menu !== false) {
            iconImg = Image({
              src: action.icon || IMAGE_DIR + name + '.png'
            });
            actionButton = Button({
              "class": 'tool',
              text: name.capitalize(),
              title: titleText
            }).prepend(iconImg).bind("mousedown touchstart", function(e) {
              if (!$(this).attr('disabled')) {
                doIt();
              }
              track(e.type, action.name);
              return false;
            });
            return actionButton.appendTo(actionbar);
          }
        },
        addSwatch: function(color) {
          return swatches.append(Div({
            "class": 'swatch',
            style: "background-color: " + (color.toString())
          }));
        },
        addTool: function(tool) {
          var alt, img, name, setMe, toolDiv;
          name = tool.name;
          alt = name.capitalize();
          tool.icon || (tool.icon = IMAGE_DIR + name + '.png');
          setMe = function() {
            return self.setTool(tool);
          };
          if (tool.hotkeys) {
            alt += " (" + tool.hotkeys + ")";
            $.each(tool.hotkeys, function(i, hotkey) {
              return $(document).bind('keydown', hotkey, function(e) {
                if (currentComponent === self) {
                  e.preventDefault();
                  setMe();
                  track("hotkey", tool.name);
                  return false;
                }
              });
            });
          }
          img = Image({
            src: tool.icon,
            alt: alt,
            title: alt
          });
          tool.elementSet = toolDiv = Div({
            "class": "tool"
          }).append(img).bind("mousedown touchstart", function(e) {
            setMe();
            track(e.type, tool.name);
            return false;
          });
          return toolbar.append(toolDiv);
        },
        color: function(color, alternate) {
          if (arguments.length === 0 || color === false) {
            if (mode === "S") {
              return Color(secondaryColorPicker.css('backgroundColor'));
            } else {
              return Color(primaryColorPicker.css('backgroundColor'));
            }
          } else if (color === true) {
            if (mode === "S") {
              return Color(primaryColorPicker.css('backgroundColor'));
            } else {
              return Color(secondaryColorPicker.css('backgroundColor'));
            }
          }
          if ((mode === "S") ^ alternate) {
            secondaryColorPicker.val(color.toHex().substr(1));
            secondaryColorPicker[0].onblur();
          } else {
            primaryColorPicker.val(color.toHex().substr(1));
            primaryColorPicker[0].onblur();
          }
          return self;
        },
        clear: function() {
          return self.eachPixel(function(pixel) {
            return pixel.color(Color(0, 0, 0, 0).toString(), "replace");
          });
        },
        displayInitialState: function(stateData) {
          return self.withoutUndo(function() {
            self.clear();
            stateData || (stateData = initialStateData);
            if (stateData) {
              return $.each(stateData, function(f, data) {
                return self.eachPixel(function(pixel, x, y) {
                  var pos;
                  pos = x + y * I.width;
                  return pixel.color(Color(data[pos]), "replace");
                });
              });
            }
          });
        },
        eachPixel: function(fn) {
          I.height.times(function(row) {
            return I.width.times(function(col) {
              var pixel;
              pixel = pixels[row][col];
              return fn.call(pixel, pixel, col, row);
            });
          });
          return self;
        },
        eval: function(code) {
          return eval(code);
        },
        fromDataURL: function(dataURL) {
          var context, maxDimension;
          context = document.createElement('canvas').getContext('2d');
          maxDimension = 256;
          return Image({
            load: function() {
              var getColor, imageData;
              if (this.width * this.height < maxDimension * maxDimension) {
                self.resize(this.width, this.height);
                context.drawImage(this, 0, 0);
                imageData = context.getImageData(0, 0, this.width, this.height);
                getColor = function(x, y) {
                  var index;
                  index = (x + y * imageData.width) * 4;
                  return Color(imageData.data[index + 0], imageData.data[index + 1], imageData.data[index + 2], imageData.data[index + 3] / 255);
                };
                self.clear();
                self.eachPixel(function(pixel, x, y) {
                  return pixel.color(getColor(x, y));
                });
              } else {
                alert("This image is too big for our editor to handle, try " + maxDimension + "x" + maxDimension + " and smaller");
              }
            },
            src: dataURL
          });
        },
        getNeighbors: function(x, y) {
          return [this.getPixel(x + 1, y), this.getPixel(x, y + 1), this.getPixel(x - 1, y), this.getPixel(x, y - 1)];
        },
        getPixel: function(x, y) {
          if (((0 <= y && y < I.height)) && ((0 <= x && x < I.width))) {
            return pixels[y][x];
          }
        },
        preview: function() {
          var tileCount;
          tileCount = tilePreview ? 4 : 1;
          return preview.css({
            backgroundImage: this.toCSSImageURL(),
            width: tileCount * I.width,
            height: tileCount * I.height
          });
        },
        replay: function(steps, parentData) {
          var delay, i, runStep;
          if (!replaying) {
            replaying = true;
            if (!steps) {
              steps = self.getReplayData();
              self.displayInitialState();
            } else {
              if (parentData) {
                self.displayInitialState(parentData);
              } else {
                self.clear();
              }
            }
            i = 0;
            delay = (5000 / steps.length).clamp(1, 200);
            runStep = function() {
              var step;
              step = steps[i];
              if (step) {
                self.withoutUndo(function() {
                  return $.each(step, function(j, p) {
                    return self.getPixel(p.x, p.y).color(p.color, "replace");
                  });
                });
                i++;
                return setTimeout(runStep, delay);
              } else {
                return replaying = false;
              }
            };
            return setTimeout(runStep, delay);
          }
        },
        resize: function(newWidth, newHeight) {
          I.width = newWidth;
          I.height = newHeight;
          pixels = pixels.slice(0, newHeight);
          while (pixels.length < newHeight) {
            pixels.push([]);
          }
          pixels.each(function(row, y) {
            var _results;
            while (row.length > newWidth) {
              row.pop();
            }
            _results = [];
            while (row.length < newWidth) {
              _results.push(row.push(Pixel({
                x: row.length,
                y: y,
                changed: pixelChanged
              })));
            }
            return _results;
          });
          layers.each(function(layer) {
            return layer.resize();
          });
          return canvas.css({
            width: I.width * I.pixelWidth + 2,
            height: I.height * I.pixelHeight + 2
          });
        },
        setInitialState: function(frameData) {
          initialStateData = frameData;
          return this.displayInitialState();
        },
        setTool: function(tool) {
          currentTool = tool;
          canvas.css('cursor', tool.cursor || "pointer");
          return tool.elementSet.takeClass("active");
        },
        toBase64: function() {
          var data;
          data = this.toDataURL();
          return data.substr(data.indexOf(',') + 1);
        },
        toCSSImageURL: function() {
          return "url(" + (this.toDataURL()) + ")";
        },
        toDataURL: function() {
          var context, tempCanvas;
          tempCanvas = $("<canvas width=" + I.width + " height=" + I.height + "></canvas>").get(0);
          context = tempCanvas.getContext('2d');
          this.eachPixel(function(pixel, x, y) {
            var color;
            color = pixel.color();
            context.fillStyle = color.toString();
            return context.fillRect(x, y, 1, 1);
          });
          return tempCanvas.toDataURL("image/png");
        },
        width: function() {
          return I.width;
        },
        height: function() {
          return I.height;
        }
      });
      $.each(tools, function(key, tool) {
        tool.name = key;
        return self.addTool(tool);
      });
      $.each(actions, function(key, action) {
        action.name = key;
        return self.addAction(action);
      });
      $.each(palette, function(i, color) {
        return self.addSwatch(Color(color));
      });
      self.setTool(tools.pencil);
      self.bind('mouseenter', function() {
        return window.currentComponent = self;
      });
      self.bind('touchstart touchmove touchend', function() {
        return event.preventDefault();
      });
      Pixie.Editor.Pixel.Console(I, self);
      Pixie.Editor.Pixel.Undo(I, self);
      window.currentComponent = self;
      if (initializer) {
        initializer(self);
      }
      self.trigger("initialized");
      return self;
    };
  })(jQuery);
}).call(this);
(function($) {
  $.template("editors/tile/editor", "<div class=\'editor tile_editor\'>\n  <div class=\'content\'>\n    <section>\n      <div class=\'screen\'>\n        <div class=\'layers\'>\n          <div class=\'cursor\'><\/div>\n          <div class=\'selection\'><\/div>\n        <\/div>\n      <\/div>\n    <\/section>\n    <div class=\'actions top\'>\n      <button class=\'save\'>Save<\/button>\n    <\/div>\n    <div class=\'module right\'>\n      <div class=\'component\'>\n        <h3>Layers<\/h3>\n        <button class=\'new\'>New Layer<\/button>\n        <div class=\'layer_select\'><\/div>\n      <\/div>\n      <div class=\'component\' style=\'display: none\'>\n        <h3>Properties<\/h3>\n        <table class=\'prop_editor\'><\/table>\n        <button class=\'prop_save\'>Save Properties<\/button>\n      <\/div>\n      <div class=\'component\'>\n        <h3>Saved Selections<\/h3>\n        <div class=\'saved_selections\'><\/div>\n      <\/div>\n      <div class=\'component tile_select\'>\n        <h3>\n          Entities\n        <\/h3>\n        <div class=\'tile_actions\'>\n          <button class=\'new_tile\'>\n            New\n          <\/button>\n          <button class=\'delete_tile\'>\n            Delete\n          <\/button>\n        <\/div>\n        <div class=\'tiles\'><\/div>\n      <\/div>\n    <\/div>\n    <div class=\'tools module left\'>\n      <div class=\'tool primary secondary\' data-tool=\'stamp\'><\/div>\n      <div class=\'tool\' data-tool=\'eraser\'><\/div>\n      <div class=\'tool\' data-tool=\'fill\'><\/div>\n      <div class=\'tool\' data-tool=\'selection\'><\/div>\n    <\/div>\n  <\/div>\n<\/div>\n");
})(jQuery);
(function($) {
  $.template("editors/tile/layer_select", "<div class=\'choice\'>\n  <div class=\'name\'>${name}<\/div>\n  <div class=\'show on\'><\/div>\n<\/div>\n");
})(jQuery);
(function($) {
  $.template("editors/tile/saved_selection", "<div class=\'selection\'>\n  <div class=\'name\'>${text}<\/div>\n  <div class=\'preview\'><\/div>\n<\/div>\n");
})(jQuery);
(function() {
  var _base;
  (_base = Pixie.Editor).Tile || (_base.Tile = {});
  Pixie.Editor.Tile.create = function(options) {
    var addNewLayer, addScreenLayer, clearSelection, clickMode, createNewTile, createPixelEditor, createdTileCount, currentLayer, currentTool, debugMode, deleteTile, dirty, eachEntity, editEntity, entered, filledToken, firstGID, floodFill, generateUuid, getNeighborPositions, grid, harvestSelection, hotkeys, inBounds, isInSelection, layerSelect, loadData, loadEntity, loadExternalEntities, modeDown, nextTile, pixelEditTile, positionElementIndices, prevTile, propEditor, propElement, removeEntity, removeTile, replaceTile, saveData, savedSelectionCount, select, selectNextVisibleLayer, selectTile, selectTool, selectionCache, selectionCopy, selectionCut, selectionDelete, selectionEach, selectionStart, showPropertiesEditor, stamp, tileAt, tileEditor, tileHeight, tileLookup, tilePosition, tileTray, tileWidth, tilesTall, tilesWide, _ref;
    options = $.extend({
      layers: ["Background", "Entities"],
      eachEntity: function() {},
      editEntity: function() {},
      loadEntity: function() {},
      removeEntity: function() {},
      tilesWide: 20,
      tilesTall: 15,
      tileWidth: 32,
      tileHeight: 32
    }, options);
    tileEditor = $.tmpl("editors/tile/editor");
    debugMode = false;
    dirty = false;
    firstGID = 1;
    eachEntity = options.eachEntity, editEntity = options.editEntity, loadEntity = options.loadEntity, removeEntity = options.removeEntity;
    tilesWide = parseInt(options.tilesWide, 10);
    tilesTall = parseInt(options.tilesTall, 10);
    tileWidth = parseInt(options.tileWidth, 10);
    tileHeight = parseInt(options.tileHeight, 10);
    currentLayer = 0;
    modeDown = null;
    tileTray = ".module .tiles";
    layerSelect = ".module .layer_select";
    positionElementIndices = [];
    grid = GridGen({
      width: tileWidth,
      height: tileHeight
    });
    if ((typeof Pixie !== "undefined" && Pixie !== null ? (_ref = Pixie.Editor) != null ? _ref.Pixel : void 0 : void 0) != null) {
      createPixelEditor = function(options) {
        var pixelEditor, url;
        url = options.url;
        tileEditor = options.tileEditor;
        pixelEditor = Pixie.Editor.Pixel.create({
          width: options.width,
          height: options.height,
          initializer: function(canvas) {
            if (url) {
              canvas.fromDataURL(url);
            }
            canvas.addAction({
              name: "Save Tile",
              icon: "/assets/icons/database_save.png",
              perform: function(canvas) {
                pixelEditor.trigger('save', canvas.toDataURL());
                pixelEditor.remove();
                return tileEditor.show();
              },
              undoable: false
            });
            return canvas.addAction({
              name: "Back to Tilemap",
              icon: "/assets/icons/arrow_left.png",
              perform: function(canvas) {
                pixelEditor.remove();
                return tileEditor.show();
              },
              undoable: false
            });
          }
        });
        tileEditor.hide().after(pixelEditor);
        window.currentComponent = pixelEditor;
        return pixelEditor;
      };
    }
    pixelEditTile = function(selectedTile) {
      var imgSource, pixelEditor;
      if (createPixelEditor) {
        imgSource = selectedTile.attr('src');
        pixelEditor = createPixelEditor({
          width: selectedTile.get(0).width,
          height: selectedTile.get(0).height,
          tileEditor: tileEditor,
          url: imgSource.replace('http://images.pixie.strd6.com', '/s3')
        });
        return pixelEditor.bind('save', function(event, data) {
          var img;
          img = $("<img/>", {
            src: data
          });
          return tileEditor.find('.component .tiles').append(img);
        });
      }
    };
    generateUuid = function() {
      return Math.uuid(32, 16);
    };
    createdTileCount = 0;
    createNewTile = function() {
      var pixelEditor;
      if (createPixelEditor) {
        pixelEditor = createPixelEditor({
          width: tileWidth,
          height: tileHeight,
          tileEditor: tileEditor
        });
        return pixelEditor.bind('save', function(event, data) {
          var entity, img, name, src, uuid;
          uuid = generateUuid();
          name = "New Tile " + (createdTileCount += 1);
          src = data;
          img = $("<img/>", {
            alt: name,
            "data-uuid": uuid,
            src: src,
            title: name
          });
          entity = {
            name: name,
            tileSrc: src
          };
          loadEntity(uuid, {
            src: src,
            entity: entity
          });
          return tileEditor.find('.component .tiles').append(img);
        });
      }
    };
    deleteTile = function(tile) {
      var uuid;
      uuid = tile.remove().data('uuid');
      removeEntity(uuid);
      return tileEditor.find(".screen img[data-uuid=" + uuid + "]").remove();
    };
    tilePosition = function(element, event) {
      var localX, localY, offset;
      offset = element.offset();
      localY = (event.pageY - offset.top).snap(tileHeight).clamp(0, (tilesTall - 1) * tileHeight);
      localX = (event.pageX - offset.left).snap(tileWidth).clamp(0, (tilesWide - 1) * tileWidth);
      return {
        x: localX,
        y: localY
      };
    };
    addScreenLayer = function() {
      $("<div />", {
        "class": "layer",
        width: tilesWide * tileWidth,
        height: tilesTall * tileHeight
      }).appendTo(tileEditor.find("section .layers"));
      tileEditor.find(".screen").find(".cursor, .selection").appendTo(tileEditor.find("section .layers"));
      return positionElementIndices.push({});
    };
    addNewLayer = function(layerName) {
      layerName || (layerName = "Layer " + (tileEditor.find(".layer_select .choice").length + 1));
      $.tmpl("editors/tile/layer_select", {
        name: layerName
      }).appendTo(tileEditor.find(layerSelect)).find('.name').mousedown();
      return addScreenLayer();
    };
    selectNextVisibleLayer = function() {
      var shownLayers;
      shownLayers = tileEditor.find(".layer_select .choice .show.on");
      if (shownLayers.length) {
        return shownLayers.eq(0).parent().find(".name").mousedown();
      }
    };
    prevTile = function(mode) {
      var cur, tileCount;
      tileCount = $(".tiles img").length;
      cur = tileEditor.find(".tiles ." + mode).removeClass(mode).index();
      return tileEditor.find(".tiles img").eq((cur - 1).mod(tileCount)).addClass(mode);
    };
    nextTile = function(mode) {
      var cur, tileCount;
      tileCount = tileEditor.find(".tiles img").length;
      cur = tileEditor.find(".tiles ." + mode).removeClass(mode).index();
      return tileEditor.find(".tiles img").eq((cur + 1).mod(tileCount)).addClass(mode);
    };
    inBounds = function(x, y) {
      return ((0 <= x && x < tileWidth * tilesWide)) && ((0 <= y && y < tileHeight * tilesTall));
    };
    replaceTile = function(x, y, tile) {
      var posString, targetLayer;
      if (!inBounds(x, y)) {
        return;
      }
      if (!dirty) {
        dirty = true;
        tileEditor.trigger("dirty");
      }
      posString = x + "x" + y;
      tile = tile.clone().removeClass("primary secondary").css({
        position: "absolute",
        top: y,
        left: x
      }).attr("data-pos", posString);
      targetLayer = tileEditor.find(".screen .layer").eq(currentLayer);
      removeTile(x, y);
      targetLayer.append(tile);
      positionElementIndices[currentLayer][posString] = tile.get();
      return tile;
    };
    removeTile = function(x, y) {
      var posString;
      if (!dirty) {
        dirty = true;
        tileEditor.trigger("dirty");
      }
      tileAt(x, y).remove();
      posString = x + "x" + y;
      return positionElementIndices[currentLayer][posString] = void 0;
    };
    tileAt = function(x, y) {
      var posString;
      posString = x + "x" + y;
      return $(positionElementIndices[currentLayer][posString]);
    };
    getNeighborPositions = function(position) {
      var neighbors;
      return neighbors = [[position[0] - tileWidth, position[1]], [position[0] + tileWidth, position[1]], [position[0], position[1] - tileHeight], [position[0], position[1] + tileHeight]].select(function(neighborPos) {
        return inBounds(neighborPos[0], neighborPos[1]);
      });
    };
    filledToken = 0;
    floodFill = function(x, y, mode) {
      var inSelection, neighbors, position, queue, selection, sourceTiles, targetTile, targetUuid, tile;
      if ((tile = tileEditor.find(".tiles").find("." + mode)).length) {
        sourceTiles = [[tile]];
      } else if (selection = tileEditor.find(".saved_selections").find("." + mode).data("selectionData")) {
        sourceTiles = selection;
      }
      filledToken += 1;
      inSelection = isInSelection(x, y);
      targetTile = tileAt(x, y);
      targetUuid = targetTile.data("uuid");
      tile = sourceTiles[0][0];
      queue = [];
      replaceTile(x, y, tile).data("fill", filledToken);
      queue.push([x, y]);
      while (position = queue.pop()) {
        neighbors = getNeighborPositions(position);
        neighbors.each(function(neighbor, index) {
          var currentUuid;
          if (inSelection === isInSelection(neighbor[0], neighbor[1])) {
            tile = sourceTiles.wrap((neighbor[1] - y) / tileHeight).wrap((neighbor[0] - x) / tileWidth);
            if (neighbor) {
              targetTile = tileAt(neighbor[0], neighbor[1]);
              currentUuid = targetTile.data("uuid");
              if (currentUuid === targetUuid && targetTile.data("fill") !== filledToken) {
                replaceTile(neighbor[0], neighbor[1], tile).data("fill", filledToken);
                return queue.push(neighbor);
              }
            }
          }
        });
      }
    };
    selectionCache = null;
    isInSelection = function(x, y) {
      if (selectionCache) {
        return (selectionCache.top <= y && y < selectionCache.top + selectionCache.height) && (selectionCache.left <= x && x < selectionCache.left + selectionCache.width);
      } else {
        return false;
      }
    };
    clearSelection = function() {
      tileEditor.find(".screen .selection").removeClass("active");
      return selectionCache = null;
    };
    selectionEach = function(callback) {
      var $selection, pos, selectionHeight, selectionWidth, x, y;
      $selection = tileEditor.find(".screen .selection");
      if ($selection.hasClass("active")) {
        pos = $selection.position();
        selectionWidth = $selection.outerWidth();
        selectionHeight = $selection.outerHeight();
        y = pos.top;
        while (y < pos.top + selectionHeight) {
          x = pos.left;
          while (x < pos.left + selectionWidth) {
            callback(x, y);
            x += tileWidth;
          }
          y += tileHeight;
        }
        return clearSelection();
      }
    };
    selectionDelete = function() {
      return selectionEach(removeTile);
    };
    savedSelectionCount = 0;
    harvestSelection = function(remove) {
      var preview, row, rowY, savedSelection, selectionData;
      rowY = void 0;
      row = void 0;
      savedSelection = $.tmpl("editors/tile/saved_selection", {
        text: "Selection" + (++savedSelectionCount)
      }).appendTo(tileEditor.find(".saved_selections"));
      preview = savedSelection.find(".preview");
      selectionData = [];
      selectionEach(function(x, y) {
        var tile;
        if (y !== rowY) {
          rowY = y;
          row = [];
          selectionData.push(row);
        }
        tile = tileAt(x, y).clone();
        row.push(tile);
        tile.css({
          position: "absolute",
          top: (selectionData.length - 1) * tileHeight,
          left: (row.length - 1) * tileWidth
        });
        preview.append(tile);
        if (remove) {
          return removeTile(x, y);
        }
      });
      savedSelection.data("selectionData", selectionData);
      return selectTile(savedSelection, "primary");
    };
    selectionCopy = function() {
      return harvestSelection();
    };
    selectionCut = function() {
      return harvestSelection(true);
    };
    selectionStart = null;
    select = function(x, y) {
      var $selection, deltaX, deltaY, pos, selectionHeight, selectionLeft, selectionTop, selectionWidth;
      if (selectionStart) {
        $selection = tileEditor.find(".screen .selection");
        pos = $selection.position();
        deltaX = x - selectionStart.x;
        deltaY = y - selectionStart.y;
        selectionWidth = deltaX.abs() + tileWidth;
        selectionHeight = deltaY.abs() + tileHeight;
        selectionLeft = deltaX < 0 ? x : selectionStart.x;
        selectionTop = deltaY < 0 ? y : selectionStart.y;
        selectionCache = {
          height: selectionHeight,
          left: selectionLeft,
          top: selectionTop,
          width: selectionWidth
        };
        return $selection.css(selectionCache);
      } else {
        selectionCache = {
          height: tileHeight,
          left: x,
          top: y,
          width: tileWidth
        };
        tileEditor.find(".screen .selection").addClass('active').css(selectionCache);
        return selectionStart = {
          x: x,
          y: y
        };
      }
    };
    stamp = function(x, y, mode) {
      var selection, tile;
      if ((tile = tileEditor.find(".tiles").find("." + mode)).length) {
        return replaceTile(x, y, tile);
      } else if (selection = tileEditor.find(".saved_selections").find("." + mode).data("selectionData")) {
        return selection.each(function(row, tileY) {
          return row.each(function(tile, tileX) {
            var targetX, targetY;
            if (tile) {
              targetX = x + tileX * tileWidth;
              targetY = y + tileY * tileHeight;
              return replaceTile(targetX, targetY, tile);
            }
          });
        });
      }
    };
    currentTool = function(mode) {
      return tileEditor.find(".tools .tool." + mode).data("tool");
    };
    entered = function(x, y) {
      var mode;
      if (mode = modeDown) {
        switch (currentTool(mode)) {
          case "stamp":
            return stamp(x, y, mode);
          case "eraser":
            return removeTile(x, y);
          case "fill":
            return floodFill(x, y, mode);
          case "selection":
            return select(x, y);
        }
      }
    };
    clickMode = function(event) {
      if (event.which === 1) {
        return "primary";
      } else if (event.which === 3) {
        return "secondary";
      }
    };
    selectTool = function(name, mode) {
      var tool;
      tool = tileEditor.find(".tools .tool[data-tool=" + name + "]");
      return tool.takeClass(mode);
    };
    selectTile = function(tile, mode) {
      tileEditor.find(".saved_selections .selection").removeClass(mode);
      tileEditor.find(".tiles img").removeClass(mode);
      return tile.addClass(mode);
    };
    propElement = null;
    showPropertiesEditor = function(element) {
      propElement = element;
      propEditor.setProps(propElement.data("properties"));
      return propEditor.parent().show();
    };
    tileEditor.bind("contextmenu", function(event) {
      if (!debugMode) {
        return event.preventDefault();
      }
    });
    tileEditor.on("mousedown", ".tools .tool", function(event) {
      var mode;
      event.preventDefault();
      if (mode = clickMode(event)) {
        return $(this).takeClass(mode);
      }
    });
    tileEditor.on("mousedown", ".tiles img, .saved_selections .selection", function(event) {
      var mode;
      event.preventDefault();
      if (mode = clickMode(event)) {
        return selectTile($(this), mode);
      }
    });
    tileEditor.on("mouseup", ".tiles img, .saved_selections .selection", function(event) {
      if (event.which === 2) {
        return $(this).remove();
      }
    });
    tileEditor.on("dblclick", ".tiles img", function(event) {
      return editEntity($(this).data('uuid'));
    });
    tileEditor.find("button.new_tile").click(function() {
      return createNewTile();
    });
    tileEditor.find("button.delete_tile").click(function() {
      return deleteTile(tileEditor.find('.tiles img.primary'));
    });
    tileEditor.find(".prop_save").click(function(event) {
      if (propElement) {
        propElement.data("properties", propEditor.getProps());
        return propEditor.parent().hide();
      }
    });
    tileEditor.find(".layer_select").parent().find('.new').click(function() {
      return addNewLayer();
    });
    tileEditor.on("mousedown", ".layer_select .choice .name", function(event) {
      var $layer;
      $layer = $(this).parent();
      $layer.takeClass("active");
      return currentLayer = $layer.index();
    });
    tileEditor.find(".layer_select").delegate(".show", 'mousedown', function(event) {
      var $choice, $this;
      $this = $(this);
      $choice = $this.parent();
      if ($this.toggleClass("on").hasClass("on")) {
        tileEditor.find(".screen .layers .layer").eq($choice.index()).fadeIn();
        return $choice.find(".name").mousedown();
      } else {
        tileEditor.find(".screen .layers .layer").eq($choice.index()).fadeOut();
        return selectNextVisibleLayer();
      }
    });
    tileEditor.find(".screen .layers").bind("mousemove", function(event) {
      var oldPos, pos;
      pos = tilePosition($(this), event);
      oldPos = tileEditor.find(".screen .cursor").position();
      if (!(oldPos.left === pos.x && oldPos.top === pos.y)) {
        entered(pos.x, pos.y);
        return tileEditor.find(".screen .cursor").css({
          left: pos.x,
          top: pos.y
        });
      }
    });
    tileEditor.find(".screen .layers").bind("mousedown", function(event) {
      var pos;
      if (modeDown = clickMode(event)) {
        pos = tilePosition($(this), event);
        return entered(pos.x, pos.y);
      }
    });
    $(document).bind("mouseup", function(event) {
      selectionStart = null;
      return modeDown = null;
    });
    tileEditor.mousedown(function() {
      return window.currentComponent = tileEditor;
    });
    hotkeys = {
      a: function(event) {
        return prevTile("primary");
      },
      z: function(event) {
        return nextTile("primary");
      },
      s: function(event) {
        return prevTile("secondary");
      },
      x: function(event) {
        return nextTile("secondary");
      },
      p: function() {
        return showPropertiesEditor(tileEditor.find('.tiles img.primary'));
      },
      i: function() {
        var left, tile, top, _ref2;
        _ref2 = tileEditor.find(".screen .cursor").position(), left = _ref2.left, top = _ref2.top;
        if ((tile = tileAt(left, top)).length) {
          return showPropertiesEditor(tile);
        }
      },
      backspace: selectionDelete,
      del: selectionDelete,
      esc: clearSelection,
      "ctrl+c": selectionCopy,
      "ctrl+x": selectionCut
    };
    $.each(hotkeys, function(key, fn) {
      return $(document).bind("keydown", key, function(event) {
        if (window.currentComponent === tileEditor) {
          event.preventDefault();
          return fn(event);
        }
      });
    });
    tileEditor.find(tileTray).sortable();
    tileEditor.dropImageReader(function(file, event) {
      var entity, img, name, src, uuid;
      if (event.target.readyState === FileReader.DONE) {
        uuid = generateUuid();
        src = event.target.result;
        name = file.name.replace(/\.[^\.]*$/, '');
        img = $("<img/>", {
          alt: name,
          src: src,
          title: name,
          "data-uuid": uuid
        });
        entity = {
          name: name,
          tileSrc: src
        };
        loadEntity(uuid, {
          src: src,
          entity: entity
        });
        return $(this).find(".tiles").append(img);
      }
    });
    $('.filename, .layer_select .name, .saved_selections .name', tileEditor).liveEdit();
    propEditor = $(".prop_editor", tileEditor).propertyEditor();
    tileEditor.find("button.save").click(function() {
      return typeof options.save === "function" ? options.save(saveData()) : void 0;
    });
    saveData = function() {
      var entityCache, layers;
      entityCache = {};
      tileEditor.find(".module .tiles img").each(function() {
        var $this, entity, mapTileData, props, src, uuid;
        $this = $(this);
        uuid = $this.data("uuid");
        src = $this.attr("src");
        entity = {
          tileSrc: src
        };
        mapTileData = {
          entity: entity,
          src: src
        };
        loadEntity(uuid, mapTileData);
        if (props = $this.data("properties")) {
          mapTileData.properties = props;
        }
        return entityCache[uuid] = mapTileData;
      });
      layers = [];
      tileEditor.find(".layer_select .choice").each(function(i) {
        var $this, entities, entityLayer, layer, name, screenLayer, tileLookup, tiles;
        $this = $(this);
        name = $this.text().trim();
        entityLayer = name.match(/entities/i);
        screenLayer = tileEditor.find(".screen .layers .layer").eq(i);
        if (entityLayer) {
          entities = screenLayer.find("img").map(function() {
            var $element, left, top, uuid, _ref2;
            $element = $(this);
            uuid = $element.data("uuid");
            _ref2 = $element.position(), top = _ref2.top, left = _ref2.left;
            return {
              x: left,
              y: top,
              uuid: uuid,
              properties: $(this).data("properties")
            };
          }).get();
          layer = {
            name: name,
            entities: entities
          };
        } else {
          tileLookup = {};
          screenLayer.find("img").each(function() {
            var pos, uuid;
            uuid = this.getAttribute("data-uuid");
            pos = this.getAttribute("data-pos");
            return tileLookup[pos] = uuid;
          });
          tiles = [];
          tilesTall.times(function(y) {
            var row;
            row = [];
            tiles.push(row);
            return tilesWide.times(function(x) {
              var posString;
              posString = x * tileWidth + "x" + y * tileHeight;
              return row.push(tileLookup[posString]);
            });
          });
          layer = {
            name: name,
            tiles: tiles
          };
        }
        return layers.push(layer);
      });
      return {
        title: tileEditor.find(".filename").text(),
        orientation: "orthogonal",
        width: tilesWide,
        height: tilesTall,
        tileWidth: tileWidth,
        tileHeight: tileHeight,
        entityCache: entityCache,
        layers: layers
      };
    };
    loadData = function(data, tileLookup) {
      tileWidth = data.tileWidth, tileHeight = data.tileHeight;
      tilesWide = data.width;
      tilesTall = data.height;
      positionElementIndices = [];
      tileEditor.find("section .layers .layer").remove();
      tileEditor.find(layerSelect).html('');
      data.layers.each(function(layer, i) {
        var entities, entity, tile, tiles, _i, _len, _results;
        currentLayer = i;
        addScreenLayer();
        $.tmpl("editors/tile/layer_select", {
          name: layer.name
        }).appendTo(tileEditor.find(layerSelect));
        if (tiles = layer.tiles) {
          tiles.each(function(row, y) {
            return row.each(function(uuid, x) {
              if (uuid) {
                return replaceTile(x * tileWidth, y * tileHeight, tileLookup[uuid]);
              }
            });
          });
        }
        if (entities = layer.entities) {
          _results = [];
          for (_i = 0, _len = entities.length; _i < _len; _i++) {
            entity = entities[_i];
            tile = replaceTile(entity.x, entity.y, tileLookup[entity.uuid]);
            _results.push(entity.properties ? tile.data("properties", entity.properties) : void 0);
          }
          return _results;
        }
      });
      return tileEditor.find(layerSelect).find(".name").last().trigger("mousedown");
    };
    loadExternalEntities = function(data) {
      var entityCache, index, tileData, tileLookup, uuid;
      if (entityCache = data != null ? data.entityCache : void 0) {
        for (uuid in entityCache) {
          tileData = entityCache[uuid];
          loadEntity(uuid, tileData);
        }
      }
      tileEditor.find(tileTray).html('');
      tileLookup = {};
      index = 0;
      eachEntity(function(uuid, entity) {
        var active, src;
        active = index === 0 ? "primary" : index === 1 ? "secondary" : void 0;
        src = entity.tileSrc;
        tileLookup[uuid] = $("<img />", {
          "class": active,
          "data-uuid": uuid,
          src: src
        }).appendTo(tileEditor.find(tileTray));
        if (typeof cachedEntity !== "undefined" && cachedEntity !== null ? cachedEntity.properties : void 0) {
          tileLookup[uuid].data("properties", cachedEntity.properties);
        }
        return index += 1;
      });
      return tileLookup;
    };
    tileLookup = loadExternalEntities(options.data);
    if (options.data) {
      loadData(options.data, tileLookup);
    } else {
      if (options.layers.each) {
        options.layers.each(function(layerName) {
          return addNewLayer(layerName);
        });
      } else if (options.layers.times) {
        options.layers.times(function() {
          return addNewLayer();
        });
      }
    }
    tileEditor.find(".screen .cursor").css({
      width: tileWidth - 1,
      height: tileHeight - 1
    });
    tileEditor.find(".screen .layers").css({
      backgroundImage: grid.backgroundImage(),
      width: tilesWide * tileWidth,
      height: tilesTall * tileHeight
    });
    tileEditor.bind("clean", function() {
      return dirty = false;
    });
    dirty = false;
    return $.extend(tileEditor, {
      addAction: function(action) {
        var actionButton;
        actionButton = $("<button/>", {
          text: action.name,
          click: action.perform
        });
        return tileEditor.find(".actions").append(actionButton);
      },
      mapData: saveData
    });
  };
}).call(this);
(function($) {
  $.template("pagination", "<div class=\'spinner_container\'>\n  <img class=\'spinner\' src=\'/assets/ajax-loader.gif\' />\n  Loading...\n<\/div>\n{{if total > 1}}\n{{if prev}}\n<a class=\'prev\' href=\'#\'>« Previous<\/a>\n{{else}}\n<span class=\'disabled previous_page\'>« Previous<\/span>\n{{/if}}\n{{each(index, value) range}}\n{{if page == value}}\n<em class=\'current\'>${page}<\/em>\n{{else}}\n{{if value == \'...\'}}\n<span class=\'gap\'>...<\/span>\n{{else}}\n<a class=\'page\' data-page=\'${value}\' href=\'#\'>${value}<\/a>\n{{/if}}\n{{/if}}\n{{/each}}\n{{if next}}\n<a class=\'next\' href=\'#\'>Next »<\/a>\n{{else}}\n<span class=\'disabled next_page\'>Next »<\/span>\n{{/if}}\n{{/if}}\n");
})(jQuery);
(function() {
  /**
  A base view for our frontbone framework.
  */
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie", function(Pixie) {
    return Pixie.View = (function() {
      __extends(View, Backbone.View);
      function View() {
        View.__super__.constructor.apply(this, arguments);
      }
      View.prototype.initialize = function() {
        this.el = $(this.el);
        if (this.template != null) {
          this.el.html($.tmpl(this.template));
        }
        this.settings = this.options.settings;
        return this.editor = this.options.editor;
      };
      View.prototype.include = function(module) {
        return Object.extend(this, module(this, this));
      };
      return View;
    })();
  });
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Views", function(Views) {
    return Views.Paginated = (function() {
      __extends(Paginated, Pixie.View);
      function Paginated() {
        this.render = __bind(this.render, this);
        this.next = __bind(this.next, this);
        this.previous = __bind(this.previous, this);
        this.toPage = __bind(this.toPage, this);
        Paginated.__super__.constructor.apply(this, arguments);
      }
      Paginated.prototype.className = 'pagination';
      Paginated.prototype.tagName = 'nav';
      Paginated.prototype.initialize = function() {
        Paginated.__super__.initialize.apply(this, arguments);
        this.collection.bind('fetching', __bind(function() {
          return this.$('.spinner_container').fadeIn(150);
        }, this));
        return this.collection.bind('afterReset', __bind(function() {
          this.$('.spinner_container').fadeOut(150);
          this.render();
          if (this.collection.pageInfo().next) {
            return this.el.css('visibility: visible');
          } else {
            return this.el.css('visibility: hidden');
          }
        }, this));
      };
      Paginated.prototype.events = {
        'click a.prev': 'previous',
        'click a.next': 'next',
        'click a.page': 'toPage'
      };
      Paginated.prototype.toPage = function(e) {
        e.preventDefault();
        return this.collection.toPage($(e.target).data('page'));
      };
      Paginated.prototype.previous = function(e) {
        e.preventDefault();
        return this.collection.previousPage();
      };
      Paginated.prototype.next = function(e) {
        e.preventDefault();
        return this.collection.nextPage();
      };
      Paginated.prototype.render = function() {
        var pages;
        this.el.empty();
        pages = $.tmpl('pagination', this.collection.pageInfo());
        this.el.html(pages);
        return this;
      };
      return Paginated;
    })();
  });
}).call(this);
(function($) {
  $.template("comments/comment", "{{if commentable_id > 0}}\n<div class=\'comment\' data-commentable_id=\'${commentable_id}\'>\n  <div class=\'attribution\'>\n    <div class=\'name\'>\n      <a href=\'/people/${commenter_id}\'>\n        ${commenter_name}\n        <img alt=\'Thumb\' src=\'${avatar_src}\' />\n      <\/a>\n    <\/div>\n    <time class=\'timeago\' datetime=\'${time}\'>${time}<\/time>\n  <\/div>\n  <div class=\'commentable\'>\n    <a href=\'/${commentable_type}/${commentable_id}\'>\n      <img alt=\'${commentable_name}\' src=\'${commentable_img_src}\' />\n    <\/a>\n  <\/div>\n  {{html body}}\n<\/div>\n{{/if}}\n");
})(jQuery);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Views.Comments", function(Comments) {
    return Comments.Comment = (function() {
      __extends(Comment, Backbone.View);
      function Comment() {
        this.render = __bind(this.render, this);
        Comment.__super__.constructor.apply(this, arguments);
      }
      Comment.prototype.className = 'comment';
      Comment.prototype.render = function() {
        var data;
        data = _.extend(this.model.toJSON(), {
          current_user_id: this.model.collection.current_user_id,
          owner_id: this.model.collection.owner_id
        });
        $(this.el).html($.tmpl('comments/comment', data));
        return this;
      };
      return Comment;
    })();
  });
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Models", function(Models) {
    var calculateRange;
    calculateRange = function(page, total) {
      var innerWindow, left, middle, outerWindow, right, window_from, window_to, _i, _j, _k, _l, _m, _ref, _ref2, _ref3, _ref4, _results, _results2, _results3, _results4, _results5;
      outerWindow = Models.PaginatedCollection.OUTER_WINDOW;
      innerWindow = Models.PaginatedCollection.INNER_WINDOW;
      window_from = page - innerWindow;
      window_to = page + innerWindow;
      if (window_to > total) {
        window_from -= window_to - total;
        window_to = total;
      }
      if (window_from < 1) {
        window_to += 1 - window_from;
        window_from = 1;
        if (window_to > total) {
          window_to = total;
        }
      }
      middle = (function() {
        _results = [];
        for (var _i = window_from; window_from <= window_to ? _i <= window_to : _i >= window_to; window_from <= window_to ? _i++ : _i--){ _results.push(_i); }
        return _results;
      }).apply(this);
      if (outerWindow + 3 < middle.first()) {
        left = (function() {
          _results2 = [];
          for (var _j = 1, _ref = outerWindow + 1; 1 <= _ref ? _j <= _ref : _j >= _ref; 1 <= _ref ? _j++ : _j--){ _results2.push(_j); }
          return _results2;
        }).apply(this);
        left.push("...");
      } else {
        left = (function() {
          _results3 = [];
          for (var _k = 1, _ref2 = middle.first(); 1 <= _ref2 ? _k < _ref2 : _k > _ref2; 1 <= _ref2 ? _k++ : _k--){ _results3.push(_k); }
          return _results3;
        }).apply(this);
      }
      if (total - outerWindow - 2 > middle.last()) {
        right = (function() {
          _results4 = [];
          for (var _l = _ref3 = total - outerWindow; _ref3 <= total ? _l <= total : _l >= total; _ref3 <= total ? _l++ : _l--){ _results4.push(_l); }
          return _results4;
        }).apply(this);
        right.unshift("...");
      } else {
        if (middle.last() + 1 > total) {
          right = [];
        } else {
          right = (function() {
            _results5 = [];
            for (var _m = _ref4 = middle.last() + 1; _ref4 <= total ? _m <= total : _m >= total; _ref4 <= total ? _m++ : _m--){ _results5.push(_m); }
            return _results5;
          }).apply(this);
        }
      }
      return left.concat(middle).concat(right);
    };
    Models.PaginatedCollection = (function() {
      __extends(PaginatedCollection, Backbone.Collection);
      function PaginatedCollection() {
        this.search = __bind(this.search, this);
        this.resetSearch = __bind(this.resetSearch, this);
        this.previousPage = __bind(this.previousPage, this);
        this.nextPage = __bind(this.nextPage, this);
        this.toPage = __bind(this.toPage, this);
        this.pageInfo = __bind(this.pageInfo, this);
        this.parse = __bind(this.parse, this);
        PaginatedCollection.__super__.constructor.apply(this, arguments);
      }
      PaginatedCollection.prototype.initialize = function() {
        this.page = 1;
        return this.params || (this.params = {});
      };
      PaginatedCollection.prototype.fetch = function(options) {
        var success;
        if (options == null) {
          options = {};
        }
        this.trigger("fetching");
        this.params.page = this.page;
        options.data = this.params;
        success = options.success;
        options.success = __bind(function(resp) {
          this.trigger("fetched");
          if (success) {
            return success(self, resp);
          }
        }, this);
        return PaginatedCollection.__super__.fetch.call(this, options);
      };
      PaginatedCollection.prototype.parse = function(resp) {
        this.page = resp.page, this.per_page = resp.per_page, this.total = resp.total, this.current_user_id = resp.current_user_id;
        return resp.models;
      };
      PaginatedCollection.prototype.pageInfo = function() {
        var info;
        info = {
          current_user_id: this.current_user_id,
          total: this.total,
          page: this.page,
          perPage: this.per_page,
          prev: false,
          next: false
        };
        if (this.page > 1) {
          info.prev = this.page - 1;
        }
        if (this.page < info.total) {
          info.next = this.page + 1;
        }
        info.range = calculateRange(this.page, this.total);
        return info;
      };
      PaginatedCollection.prototype.toPage = function(pageNumber) {
        if ((1 <= pageNumber && pageNumber <= this.total)) {
          this.page = pageNumber;
          return this.fetch();
        }
      };
      PaginatedCollection.prototype.nextPage = function() {
        if (this.page !== this.total) {
          this.page += 1;
          return this.fetch();
        }
      };
      PaginatedCollection.prototype.previousPage = function() {
        if (this.page !== 1) {
          this.page -= 1;
          return this.fetch();
        }
      };
      PaginatedCollection.prototype.resetSearch = function() {
        this.page = 1;
        delete this.params.search;
        delete this.params.tagged;
        return this.fetch();
      };
      PaginatedCollection.prototype.search = function(query) {
        this.page = 1;
        this.params.search = query.trim();
        return this.fetch();
      };
      return PaginatedCollection;
    })();
    Models.PaginatedCollection.INNER_WINDOW = 4;
    return Models.PaginatedCollection.OUTER_WINDOW = 1;
  });
}).call(this);
(function() {
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  namespace("Pixie.Models", function(Models) {
    Models.Comment = (function() {
      __extends(Comment, Backbone.Model);
      function Comment() {
        Comment.__super__.constructor.apply(this, arguments);
      }
      return Comment;
    })();
    return Models.CommentsCollection = (function() {
      __extends(CommentsCollection, Models.PaginatedCollection);
      function CommentsCollection() {
        this.parse = __bind(this.parse, this);
        CommentsCollection.__super__.constructor.apply(this, arguments);
      }
      CommentsCollection.prototype.model = Models.Comment;
      CommentsCollection.prototype.parse = function(data) {
        this.params.id = data.owner_id || false;
        return CommentsCollection.__super__.parse.call(this, data);
      };
      CommentsCollection.prototype.url = function() {
        return '/comments';
      };
      return CommentsCollection;
    })();
  });
}).call(this);
(function($) {
  $.template("comments/header", "<div class=\'header\'>\n  <h2>Messages<\/h2>\n<\/div>\n");
})(jQuery);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Views.Comments", function(Comments) {
    return Comments.Gallery = (function() {
      __extends(Gallery, Backbone.View);
      function Gallery() {
        this.addComment = __bind(this.addComment, this);
        Gallery.__super__.constructor.apply(this, arguments);
      }
      Gallery.prototype.el = '.comments';
      Gallery.prototype.initialize = function() {
        var pages;
        this.collection = new Pixie.Models.CommentsCollection;
        pages = new Pixie.Views.Paginated({
          collection: this.collection
        });
        $(this.el).find('.header').remove();
        $(this.el).append($.tmpl('comments/header', this.collection.pageInfo()));
        return this.collection.bind('reset', __bind(function(collection) {
          $(this.el).find('.header').append(pages.render().el);
          $(this.el).find('.comment').remove();
          collection.each(this.addComment);
          $('.timeago').timeago();
          return collection.trigger('afterReset');
        }, this));
      };
      Gallery.prototype.addComment = function(message) {
        var commentView;
        commentView = new Pixie.Views.Comments.Comment({
          model: message
        });
        return $(this.el).append(commentView.render().el);
      };
      return Gallery;
    })();
  });
}).call(this);
(function($) {
  $.template("projects/project", "{{if owner_id != user_id}}\n<div class=\'membership\' title=\'Owned by ${owner_name}\'>\n  <img src=\'/assets/icons/group.png\' />\n<\/div>\n{{/if}}\n{{if current_user_id == user_id}}\n<ul class=\'hover_actions right\'>\n  <a href=\'/projects/${id}\' title=\'Details\'>\n    <div class=\'static-table\'><\/div>\n    Details\n  <\/a>\n  <a href=\'/projects/${id}/fullscreen\' title=\'Run\'>\n    <div class=\'static-application_go\'><\/div>\n    Run\n  <\/a>\n  <a href=\'/projects/${id}/edit\' title=\'Edit Info\'>\n    <div class=\'static-pencil\'><\/div>\n    Edit Info\n  <\/a>\n  <a class=\'delete\' data-id=\'${id}\' title=\'Delete\'>\n    <div class=\'static-cross\'><\/div>\n    Delete\n  <\/a>\n<\/ul>\n{{/if}}\n<div class=\'thumb fancy\'>\n  <img alt=\'${title}\' class=\'show\' height=\'96\' src=\'${img}\' title=\'${title}\' width=\'96\' />\n<\/div>\n<h3 class=\'title\'>\n  <a href=\'/projects/${id}/ide\'>${title}<\/a>\n<\/h3>\n<p class=\'description\'>${description}<\/p>\n");
})(jQuery);
(function() {
  var _base;
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Views || (Pixie.Views = {});
  (_base = Pixie.Views).Projects || (_base.Projects = {});
  Pixie.Views.Projects.Project = (function() {
    __extends(Project, Backbone.View);
    function Project() {
      this.render = __bind(this.render, this);
      Project.__super__.constructor.apply(this, arguments);
    }
    Project.prototype.className = 'project clickable';
    Project.prototype.render = function() {
      var data;
      data = _.extend(this.model.toJSON(), {
        current_user_id: this.model.collection.current_user_id,
        owner_id: this.model.collection.params.id
      });
      $(this.el).html($.tmpl('projects/project', data));
      return this;
    };
    return Project;
  })();
}).call(this);
(function() {
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Models || (Pixie.Models = {});
  Pixie.Models.Project = (function() {
    __extends(Project, Backbone.Model);
    function Project() {
      Project.__super__.constructor.apply(this, arguments);
    }
    return Project;
  })();
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Models || (Pixie.Models = {});
  Pixie.Models.ProjectsCollection = (function() {
    __extends(ProjectsCollection, Pixie.Models.PaginatedCollection);
    function ProjectsCollection() {
      this.parse = __bind(this.parse, this);
      this.pageInfo = __bind(this.pageInfo, this);
      this.filterPages = __bind(this.filterPages, this);
      ProjectsCollection.__super__.constructor.apply(this, arguments);
    }
    ProjectsCollection.prototype.filterPages = function(filter) {
      if (filter === 'all') {
        filter = 'none';
      }
      if (filter === 'my projects') {
        filter = 'own';
      }
      this.page = 1;
      this.params.page = this.page;
      this.params.filter = filter;
      return this.fetch();
    };
    ProjectsCollection.prototype.model = Pixie.Models.Project;
    ProjectsCollection.prototype.pageInfo = function() {
      var info;
      info = ProjectsCollection.__super__.pageInfo.call(this);
      _.extend(info, {
        owner_id: this.params.id
      });
      return info;
    };
    ProjectsCollection.prototype.parse = function(data) {
      this.params.id = data.owner_id || false;
      return ProjectsCollection.__super__.parse.call(this, data);
    };
    ProjectsCollection.prototype.url = function() {
      return '/projects';
    };
    return ProjectsCollection;
  })();
}).call(this);
(function($) {
  $.template("projects/header", "<div class=\'header\'>\n  <h2>\n    {{if current_user_id && current_user_id == owner_id}} My {{/if}}\n    Projects\n  <\/h2>\n  {{if current_user_id && current_user_id == owner_id}}\n  <a class=\'button complement\' href=\'/projects/new\'>New Project<\/a>\n  {{/if}}\n  <a class=\'button complement\' href=\'/projects?filter=tutorials\'>Tutorials<\/a>\n<\/div>\n");
})(jQuery);
(function() {
  var _base;
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Views || (Pixie.Views = {});
  (_base = Pixie.Views).Projects || (_base.Projects = {});
  Pixie.Views.Projects.Gallery = (function() {
    __extends(Gallery, Backbone.View);
    function Gallery() {
      this.updatePagination = __bind(this.updatePagination, this);
      this.addProject = __bind(this.addProject, this);
      Gallery.__super__.constructor.apply(this, arguments);
    }
    Gallery.prototype.el = ".projects";
    Gallery.prototype.initialize = function() {
      var pages;
      this.collection = new Pixie.Models.ProjectsCollection;
      pages = new Pixie.Views.Paginated({
        collection: this.collection
      });
      return this.collection.bind('reset', __bind(function(collection) {
        $(this.el).find('.header').remove();
        $(this.el).append($.tmpl("projects/header", this.collection.pageInfo()));
        $(this.el).find('.project').remove();
        collection.each(this.addProject);
        $(this.el).find('.project:first').before(pages.render().el);
        return collection.trigger('afterReset');
      }, this));
    };
    Gallery.prototype.addProject = function(project) {
      var view;
      view = new Pixie.Views.Projects.Project({
        model: project,
        collection: this.collection
      });
      return $(this.el).append(view.render().el);
    };
    Gallery.prototype.updatePagination = function() {
      return $(this.el).find('.pagination').html($.tmpl('pagination', this.collection.pageInfo()));
    };
    return Gallery;
  })();
}).call(this);
(function($) {
  $.template("search", "<input class=\'search_field\' placeholder=\'Search...\' type=\'text\'><button class=\'search\' disabled=\'disabled\'>Search<\/button><button class=\'clear\'>Clear Search<\/button><\/input>\n");
})(jQuery);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Views", function(Views) {
    return Views.Searchable = (function() {
      __extends(Searchable, Pixie.View);
      function Searchable() {
        this.render = __bind(this.render, this);
        this.searchOnEnter = __bind(this.searchOnEnter, this);
        this.search = __bind(this.search, this);
        this.resetSearch = __bind(this.resetSearch, this);
        Searchable.__super__.constructor.apply(this, arguments);
      }
      Searchable.prototype.className = 'search';
      Searchable.prototype.initialize = function() {
        return Searchable.__super__.initialize.apply(this, arguments);
      };
      Searchable.prototype.events = {
        'click button.search': 'search',
        'keyup .search_field': 'searchOnEnter',
        'click button.clear': 'resetSearch',
        'blur .search_field': 'searchOnEnter'
      };
      Searchable.prototype.resetSearch = function(e) {
        this.$('.search_field').val("");
        this.$('button.search').attr('disabled', 'disabled');
        return this.collection.resetSearch();
      };
      Searchable.prototype.search = function(e) {
        var query;
        query = this.$('.search_field').val();
        if (query.length) {
          return this.collection.search(query);
        }
      };
      Searchable.prototype.searchOnEnter = function(e) {
        var query;
        query = $(e.target).val();
        if (query.length) {
          this.$('button.search').removeAttr('disabled');
          if (e.keyCode === 13) {
            return this.collection.search(query);
          }
        } else {
          return this.$('button.search').attr('disabled', 'disabled');
        }
      };
      Searchable.prototype.render = function() {
        this.el.html($.tmpl('search'));
        return this;
      };
      return Searchable;
    })();
  });
}).call(this);
(function($) {
  $.template("tags/tag", "<div class=\'tag\'>\n  <a href=\'#\'>${name}<\/a>\n<\/div>\n");
})(jQuery);
(function() {
  var _base;
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Views || (Pixie.Views = {});
  (_base = Pixie.Views).Tags || (_base.Tags = {});
  Pixie.Views.Tags.Tags = (function() {
    __extends(Tags, Backbone.View);
    function Tags() {
      this.render = __bind(this.render, this);
      this.searchTags = __bind(this.searchTags, this);
      Tags.__super__.constructor.apply(this, arguments);
    }
    Tags.prototype.el = '.tags';
    Tags.prototype.events = {
      'click .tag': 'searchTags'
    };
    Tags.prototype.initialize = function() {
      return this.collection.bind('afterReset', __bind(function() {
        return this.render();
      }, this));
    };
    Tags.prototype.searchTags = function(e) {
      var tag;
      tag = $(e.target).text().toLowerCase();
      return this.collection.filterTagged(tag);
    };
    Tags.prototype.render = function() {
      var model, name, tag, tags, _i, _j, _k, _len, _len2, _len3, _ref, _ref2;
      tags = [];
      $(this.el).empty();
      _ref = this.collection.models;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        model = _ref[_i];
        _ref2 = model.attributes.tags;
        for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
          tag = _ref2[_j];
          if (!tags.include(tag.name)) {
            tags.push(tag.name);
          }
        }
      }
      for (_k = 0, _len3 = tags.length; _k < _len3; _k++) {
        name = tags[_k];
        $(this.el).append($.tmpl('tags/tag', {
          name: name
        }));
      }
      return this;
    };
    return Tags;
  })();
}).call(this);
(function($) {
  $.template("sprites/sprite", "<a href=\'/sprites/${id}\'>\n  <img alt=\'${title}\' data-name=\'${title}\' draggable=\'true\' src=\'${url}\' title=\'${title}\' />\n<\/a>\n");
})(jQuery);
(function() {
  var _base;
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Views || (Pixie.Views = {});
  (_base = Pixie.Views).Sprites || (_base.Sprites = {});
  Pixie.Views.Sprites.Sprite = (function() {
    __extends(Sprite, Backbone.View);
    function Sprite() {
      this.render = __bind(this.render, this);
      Sprite.__super__.constructor.apply(this, arguments);
    }
    Sprite.prototype.className = 'sprite_container';
    Sprite.prototype.render = function() {
      $(this.el).html($.tmpl('sprites/sprite', this.model.toJSON()));
      return this;
    };
    return Sprite;
  })();
}).call(this);
(function() {
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  window.Pixie || (window.Pixie = {});
  Pixie.Models || (Pixie.Models = {});
  Pixie.Models.Sprite = (function() {
    __extends(Sprite, Backbone.Model);
    function Sprite() {
      Sprite.__super__.constructor.apply(this, arguments);
    }
    return Sprite;
  })();
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Models", function(Models) {
    return Models.SpritesCollection = (function() {
      __extends(SpritesCollection, Models.PaginatedCollection);
      function SpritesCollection() {
        this.filterTagged = __bind(this.filterTagged, this);
        this.parse = __bind(this.parse, this);
        this.pageInfo = __bind(this.pageInfo, this);
        SpritesCollection.__super__.constructor.apply(this, arguments);
      }
      SpritesCollection.prototype.model = Models.Sprite;
      SpritesCollection.prototype.pageInfo = function() {
        var info;
        info = SpritesCollection.__super__.pageInfo.call(this);
        _.extend(info, {
          owner_id: this.params.id
        });
        return info;
      };
      SpritesCollection.prototype.parse = function(data) {
        this.params.id = data.owner_id || false;
        return SpritesCollection.__super__.parse.call(this, data);
      };
      SpritesCollection.prototype.filterTagged = function(tag) {
        this.page = 1;
        this.params.tagged = tag;
        return this.fetch();
      };
      SpritesCollection.prototype.url = function() {
        return '/sprites';
      };
      return SpritesCollection;
    })();
  });
}).call(this);
(function($) {
  $.template("sprites/header", "<div class=\'header\'>\n  <h2>\n    {{if current_user_id && current_user_id == owner_id}} My {{/if}}\n    Sprites\n  <\/h2>\n  {{if current_user_id && current_user_id == owner_id}}\n  <a class=\'button complement\' href=\'/pixel-editor\'>New Sprite<\/a>\n  {{/if}}\n<\/div>\n");
})(jQuery);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  };
  namespace("Pixie.Views.Sprites", function(Sprites) {
    var Models, Views;
    Models = Pixie.Models, Views = Pixie.Views;
    return Sprites.Gallery = (function() {
      __extends(Gallery, Pixie.View);
      function Gallery() {
        this.addSprite = __bind(this.addSprite, this);
        Gallery.__super__.constructor.apply(this, arguments);
      }
      Gallery.prototype.el = '.sprites';
      Gallery.prototype.initialize = function() {
        var pages, searchable;
        Gallery.__super__.initialize.apply(this, arguments);
        this.collection = new Models.SpritesCollection;
        pages = new Views.Paginated({
          collection: this.collection
        });
        new Views.Tags.Tags({
          collection: this.collection
        });
        searchable = new Views.Searchable({
          collection: this.collection
        });
        this.el.append($.tmpl('sprites/header', this.collection.pageInfo()));
        this.el.append(pages.render().el);
        if (!this.options.profile) {
          $('.header h2').remove();
          this.el.append(searchable.render().el);
        }
        return this.collection.bind('reset', __bind(function(collection) {
          if (this.options.profile) {
            this.$('.header').replaceWith($.tmpl('sprites/header', this.collection.pageInfo()));
          }
          this.$('.sprite_container').remove();
          collection.each(this.addSprite);
          return collection.trigger('afterReset');
        }, this));
      };
      Gallery.prototype.addSprite = function(sprite) {
        var spriteView;
        spriteView = new Sprites.Sprite({
          model: sprite
        });
        return this.el.append(spriteView.render().el);
      };
      return Gallery;
    })();
  });
}).call(this);
(function() {
  // Lookup arrays for base64 conversions
  var enc64List, dec64List;
  // Load the lookup arrays once
  (function() {
      enc64List = new Array();
      dec64List = new Array();
      var i;
      for (i = 0; i < 26; i++) {
          enc64List[enc64List.length] = String.fromCharCode(65 + i);
      }
      for (i = 0; i < 26; i++) {
          enc64List[enc64List.length] = String.fromCharCode(97 + i);
      }
      for (i = 0; i < 10; i++) {
          enc64List[enc64List.length] = String.fromCharCode(48 + i);
      }
      enc64List[enc64List.length] = "+";
      enc64List[enc64List.length] = "/";
      for (i = 0; i < 128; i++) {
          dec64List[dec64List.length] = -1;
      }
      for (i = 0; i < 64; i++) {
          dec64List[enc64List[i].charCodeAt(0)] = i;
      }
  })();

  window.Base64 = {
    encode: function(str) {
        var c, d, e, end = 0;
        var u, v, w, x;
        var ptr = -1;
        var input = str.split("");
        var output = "";
        while(end == 0) {
            c = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
                ((end = 1) ? 0 : 0);
            d = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
                ((end += 1) ? 0 : 0);
            e = (typeof input[++ptr] != "undefined") ? input[ptr].charCodeAt(0) :
                ((end += 1) ? 0 : 0);
            u = enc64List[c >> 2];
            v = enc64List[(0x00000003 & c) << 4 | d >> 4];
            w = enc64List[(0x0000000F & d) << 2 | e >> 6];
            x = enc64List[e & 0x0000003F];

            // handle padding to even out unevenly divisible string lengths
            if (end >= 1) {x = "=";}
            if (end == 2) {w = "=";}

            if (end < 3) {output += u + v + w + x;}
        }
        return output;
    },

    decode: function(str) {
        var c=0, d=0, e=0, f=0, i=0, n=0;
        var input = str.split("");
        var output = "";
        var ptr = 0;
        do {
            f = input[ptr++].charCodeAt(0);
            i = dec64List[f];
            if ( f >= 0 && f < 128 && i != -1 ) {
                if ( n % 4 == 0 ) {
                    c = i << 2;
                } else if ( n % 4 == 1 ) {
                    c = c | ( i >> 4 );
                    d = ( i & 0x0000000F ) << 4;
                } else if ( n % 4 == 2 ) {
                    d = d | ( i >> 2 );
                    e = ( i & 0x00000003 ) << 6;
                } else {
                    e = e | i;
                }
                n++;
                if ( n % 4 == 0 ) {
                    output += String.fromCharCode(c) +
                              String.fromCharCode(d) +
                              String.fromCharCode(e);
                }
            }
        }
        while (typeof input[ptr] != "undefined");
        output += (n % 4 == 3) ? String.fromCharCode(c) + String.fromCharCode(d) :
                  ((n % 4 == 2) ? String.fromCharCode(c) : "");
        return output;
    }
  };
}());
(function() {
  window.CommandStack = function() {
    var index, stack;
    stack = [];
    index = 0;
    return {
      execute: function(command) {
        stack[index] = command;
        command.execute();
        return stack.length = index += 1;
      },
      undo: function() {
        var command;
        if (this.canUndo()) {
          index -= 1;
          command = stack[index];
          command.undo();
          return command;
        }
      },
      redo: function() {
        var command;
        if (this.canRedo()) {
          command = stack[index];
          command.execute();
          index += 1;
          return command;
        }
      },
      current: function() {
        return stack[index - 1];
      },
      canUndo: function() {
        return index > 0;
      },
      canRedo: function() {
        return stack[index] != null;
      }
    };
  };
}).call(this);
(function() {
  window.onerror = function(message, url, lineNumber) {
    return $.post("/js_errors", {
      format: 'json',
      js_error: {
        url: url,
        message: message,
        line_number: lineNumber,
        user_agent: navigator.userAgent
      }
    });
  };
}).call(this);
(function() {
  window.GridGen = function(options) {
    var canvas, canvasHeight, canvasWidth, color, context, guide, height, width;
    options = $.extend({}, {
      color: "rgba(0, 0, 0, 0.3)",
      height: 32,
      width: 32,
      guide: 5
    }, options);
    width = options.width, height = options.height, guide = options.guide, color = options.color;
    canvasWidth = width * guide;
    canvasHeight = height * guide;
    canvas = $("<canvas width='" + canvasWidth + "' height='" + canvasHeight + "'></canvas>").get(0);
    context = canvas.getContext("2d");
    context.fillStyle = color;
    guide.times(function(i) {
      context.fillRect(i * width, 0, 1, canvasHeight);
      return context.fillRect(0, i * height, canvasWidth, 1);
    });
    context.fillRect(0, 0, 1, canvasHeight);
    context.fillRect(0, 0, canvasWidth, 1);
    return {
      backgroundImage: function() {
        return "url(" + (this.toDataURL()) + ")";
      },
      toDataURL: function() {
        return canvas.toDataURL("image/png");
      }
    };
  };
}).call(this);
/*!
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com

Copyright (c) 2010 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
*/

/**
Generate a random uuid.

USAGE: Math.uuid(length, radix)

EXAMPLES:
  // No arguments  - returns RFC4122, version 4 ID
  Math.uuid()
  "92329D39-6F5C-4520-ABFC-AAB64544E172"

  // One argument - returns ID of the specified length
  Math.uuid(15)     // 15 character ID (default base=62)
  "VcydxgltxrVZSTV"

  // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
  Math.uuid(8, 2)  // 8 character ID (base=2)
  "01001010"
  Math.uuid(8, 10) // 8 character ID (base=10)
  "47473046"
  Math.uuid(8, 16) // 8 character ID (base=16)
  "098F4D35"

@name uuid
@methodOf Math
@param length The desired number of characters
@param radix  The number of allowable values for each character.
 */

(function() {
  // Private array of chars to use
  var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');

  Math.uuid = function (len, radix) {
    var chars = CHARS, uuid = [];
    radix = radix || chars.length;

    if (len) {
      // Compact form
      for (var i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
    } else {
      // rfc4122, version 4 form
      var r;

      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';

      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (var i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random()*16;
          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
        }
      }
    }

    return uuid.join('');
  };

  // A more performant, but slightly bulkier, RFC4122v4 solution.  We boost performance
  // by minimizing calls to random()
  Math.uuidFast = function() {
    var chars = CHARS, uuid = new Array(36), rnd=0, r;
    for (var i = 0; i < 36; i++) {
      if (i==8 || i==13 ||  i==18 || i==23) {
        uuid[i] = '-';
      } else if (i==14) {
        uuid[i] = '4';
      } else {
        if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
        r = rnd & 0xf;
        rnd = rnd >> 4;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
    return uuid.join('');
  };

  // A more compact, but less performant, RFC4122v4 solution:
  Math.uuidCompact = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    }).toUpperCase();
  };
})();
(function($) {
  $.template("color_picker", "<div class=\'color_picker\'>\n  <div class=\'white_overlay\'><\/div>\n  <div class=\'black_overlay\'><\/div>\n  <div class=\'color_overlay\'>\n    <div class=\'white_overlay\'><\/div>\n    <div class=\'black_overlay\'><\/div>\n    <div class=\'cursor_overlay\'><\/div>\n  <\/div>\n  <div class=\'slider\'>\n    <div class=\'hue_gradient\'><\/div>\n  <\/div>\n  <div class=\'hue_selector\'><\/div>\n<\/div>\n");
})(jQuery);
(function() {
  /*
   jQuery Plugin port of
   JavaScript Color Picker
  
   @author    Honza Odvarko, http:#odvarko.cz
   @copyright Honza Odvarko
   @license   http://www.gnu.org/copyleft/gpl.html  GNU General Public License
   @version   1.0.9
   @link      http://jscolor.com
  
   @ported_by Daniel Moore http://strd6.com
   @ported_by Matt Diebolt http://pixieengine.com
  */  (function($) {
    return $.fn.colorPicker = function(options) {
      var blur, color, colorOverlaySize, colorPicker, createDialog, cursorOverlay, cursorSize, dir, focus, generateHueGradient, getElementPos, getMousePos, gradient, gradientStep, hideDialog, instance, instanceId, leadingHash, overlay, showDialog, slider, sliderPointerHeight, updateInput, updateOverlayPosition, updateSliderPosition;
      options || (options = {});
      leadingHash = options.leadingHash != null ? options.leadingHash : true;
      dir = options.dir || '/assets/jscolor/';
      colorOverlaySize = 256;
      cursorSize = 15;
      sliderPointerHeight = 11;
      gradientStep = 2;
      instanceId = 0;
      instance = null;
      colorPicker = $.tmpl("color_picker");
      slider = colorPicker.find('.hue_selector');
      overlay = colorPicker.find('.color_overlay');
      gradient = colorPicker.find('.slider');
      cursorOverlay = colorPicker.find('.cursor_overlay');
      color = function(hex) {
        var HSV_RGB, RGB_HSV;
        this.hue = 0;
        this.saturation = 1;
        this.value = 0;
        this.red = 0;
        this.green = 0;
        this.blue = 0;
        this.setRGB = function(r, g, b) {
          var hsv;
          if (r != null) {
            this.red = r;
          }
          if (g != null) {
            this.green = g;
          }
          if (b != null) {
            this.blue = b;
          }
          hsv = RGB_HSV(this.red, this.green, this.blue);
          this.hue = hsv[0];
          this.saturation = hsv[1];
          return this.value = hsv[2];
        };
        this.setHSV = function(h, s, v) {
          var rgb;
          if (h != null) {
            this.hue = h;
          }
          if (s != null) {
            this.saturation = s;
          }
          if (v != null) {
            this.value = v;
          }
          rgb = HSV_RGB(this.hue, this.saturation, this.value);
          this.red = rgb[0];
          this.green = rgb[1];
          return this.blue = rgb[2];
        };
        RGB_HSV = function(r, g, b) {
          var h, m, n, v;
          n = Math.min(r, g, b);
          v = Math.max(r, g, b);
          m = v - n;
          if (m === 0) {
            return [0, 0, v];
          }
          if (r === n) {
            h = 3 + (b - g) / m;
          } else if (g === n) {
            h = 5 + (r - b) / m;
          } else {
            h = 1 + (g - r) / m;
          }
          h = h % 6;
          return [h, m / v, v];
        };
        HSV_RGB = function(h, s, v) {
          var f, i, m, n;
          if (h == null) {
            return [v, v, v];
          }
          i = Math.floor(h);
          f = i % 2 ? h - i : 1 - (h - i);
          m = v * (1 - s);
          n = v * (1 - s * f);
          switch (i) {
            case 0:
            case 6:
              return [v, n, m];
            case 1:
              return [n, v, m];
            case 2:
              return [m, v, n];
            case 3:
              return [m, n, v];
            case 4:
              return [n, m, v];
            case 5:
              return [v, m, n];
          }
        };
        this.setString = function(hex) {
          var m;
          m = hex.match(/^\s*#?([0-9A-F]{3}([0-9A-F]{3})?)\s*$/i);
          if (m) {
            if (m[1].length === 6) {
              return this.setRGB(parseInt(m[1].substr(0, 2), 16) / 255, parseInt(m[1].substr(2, 2), 16) / 255, parseInt(m[1].substr(4, 2), 16) / 255);
            } else {
              return this.setRGB(parseInt(m[1].charAt(0) + m[1].charAt(0), 16) / 255, parseInt(m[1].charAt(1) + m[1].charAt(1), 16) / 255, parseInt(m[1].charAt(2) + m[1].charAt(2), 16) / 255);
            }
          } else {
            this.setRGB(0, 0, 0);
            return false;
          }
        };
        this.toString = function() {
          var b, color, g, r, _ref;
          _ref = (function() {
            var _i, _len, _ref, _results;
            _ref = [this.red, this.green, this.blue];
            _results = [];
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
              color = _ref[_i];
              _results.push((color * 255).round().toString(16));
            }
            return _results;
          }).call(this), r = _ref[0], g = _ref[1], b = _ref[2];
          return ((r.length === 1 ? '0' + r : r) + (g.length === 1 ? '0' + g : g) + (b.length === 1 ? '0' + b : b)).toUpperCase();
        };
        if (hex) {
          return this.setString(hex);
        }
      };
      createDialog = function() {
        var g, i, setHue, setSV;
        colorPicker.get(0).onmousedown = function(e) {
          instance.preserve = true;
          return cursorOverlay.css({
            cursor: 'none'
          });
        };
        colorPicker.get(0).onmousemove = function(e) {
          if (instance.overlayActive) {
            setSV(e);
          }
          if (instance.sliderActive) {
            return setHue(e);
          }
        };
        colorPicker.get(0).onselectstart = function(e) {
          return e.preventDefault();
        };
        colorPicker.get(0).onmouseup = colorPicker.onmouseout = function(e) {
          var _base;
          cursorOverlay.css({
            cursor: "url(/assets/jscolor/cross.png) 3 4, default"
          });
          if (instance.overlayActive || instance.sliderActive) {
            instance.overlayActive = instance.sliderActive = false;
            if (typeof (_base = instance.input).onchange === "function") {
              _base.onchange();
            }
          }
          return instance.input.focus();
        };
        setSV = function(e) {
          var p, relX, relY;
          p = getMousePos(e);
          relX = (p.x - instance.cursor.x).clamp(0, colorOverlaySize);
          relY = (p.y - instance.cursor.y).clamp(0, colorOverlaySize);
          instance.color.saturation = relX / colorOverlaySize;
          instance.color.value = 1 - (relY / colorOverlaySize);
          instance.color.setHSV();
          updateOverlayPosition(relX, relY);
          return updateInput(instance.input, instance.color);
        };
        overlay.get(0).onmousedown = function(e) {
          instance.overlayActive = true;
          return setSV(e);
        };
        for (i = 0; 0 <= colorOverlaySize ? i < colorOverlaySize : i > colorOverlaySize; i += gradientStep) {
          g = $('<div class="hue_gradient" />');
          g.css({
            backgroundColor: "hsl(" + i + ", 1, 0.5)",
            height: "" + gradientStep + "px"
          });
          $(gradient).append(g);
        }
        setHue = function(e) {
          var p, relY;
          p = getMousePos(e);
          relY = (p.y - instance.sliderPosition).clamp(0, colorOverlaySize);
          instance.color.hue = ((relY / colorOverlaySize) * 6).clamp(0, 5.99);
          instance.color.setHSV();
          updateSliderPosition(relY);
          return updateInput(instance.input, instance.color);
        };
        slider.get(0).onmousedown = function(e) {
          instance.sliderActive = true;
          setHue(e);
          return slider.css({
            cursor: 'none'
          });
        };
        return slider.get(0).onmouseup = function() {
          return slider.css({
            cursor: 'pointer'
          });
        };
      };
      showDialog = function(input) {
        var colorPickerWidth, dp, inputHeight, inputWidth, ip;
        inputHeight = input.offsetHeight;
        inputWidth = input.offsetWidth;
        colorPickerWidth = 292;
        ip = getElementPos(input);
        dp = {
          x: ip.x + inputWidth - colorPickerWidth,
          y: ip.y + inputHeight
        };
        instanceId++;
        instance = {
          input: input,
          color: new color(input.value),
          preserve: false,
          overlayActive: false,
          sliderActive: false,
          cursor: {
            x: dp.x,
            y: dp.y
          },
          sliderPosition: dp.y
        };
        updateOverlayPosition();
        updateSliderPosition();
        generateHueGradient();
        $(colorPicker).css({
          left: "" + dp.x + "px",
          top: "" + dp.y + "px"
        });
        return $('body').append(colorPicker);
      };
      hideDialog = function() {
        $('body').find(colorPicker).remove();
        return instance = null;
      };
      updateSliderPosition = function(y) {
        var hue;
        hue = instance.color.hue;
        y || (y = ((hue / 6) * colorOverlaySize).round());
        slider.css({
          backgroundPosition: "0 " + ((y - (sliderPointerHeight / 2) + 1).floor()) + "px"
        });
        return overlay.css({
          backgroundColor: "hsl(" + (hue * 60) + ", 100%, 50%)"
        });
      };
      updateOverlayPosition = function(x, y) {
        var hue, saturation, value, _ref;
        _ref = [instance.color.hue, instance.color.saturation, instance.color.value], hue = _ref[0], saturation = _ref[1], value = _ref[2];
        x || (x = (saturation * colorOverlaySize).round());
        y || (y = ((1 - value) * colorOverlaySize).round());
        return cursorOverlay.css({
          backgroundPosition: "" + ((x - cursorSize / 2).floor()) + "px " + ((y - cursorSize / 2).floor()) + "px"
        });
      };
      generateHueGradient = function() {
        var b, c, g, gr_length, hue, r, s, saturation, value, _ref;
        _ref = [instance.color.hue, instance.color.saturation, instance.color.value], hue = _ref[0], saturation = _ref[1], value = _ref[2];
        r = g = b = s = c = [value, 0, 0];
        gr_length = $(gradient).children().length;
        return $(gradient).children().each(function(i, element) {
          hue = ((i / gr_length) * 360).round();
          return $(element).css({
            backgroundColor: "hsl(" + hue + ", 100%, 50%)"
          });
        });
      };
      updateInput = function(el, color) {
        $(el).val((leadingHash ? '#' : '') + color);
        return $(el).css({
          backgroundColor: '#' + color,
          color: color.value < 0.6 ? '#FFF' : '#000',
          textShadow: color.value < 0.6 ? 'rgba(255, 255, 255, 0.2) 1px 1px' : 'rgba(0, 0, 0, 0.2) 1px 1px'
        });
      };
      getElementPos = function(e) {
        return {
          x: $(e).offset().left,
          y: $(e).offset().top
        };
      };
      getMousePos = function(e) {
        return {
          x: e.pageX,
          y: e.pageY
        };
      };
      focus = function() {
        if (instance != null ? instance.preserve : void 0) {
          return instance.preserve = false;
        } else {
          return showDialog(this);
        }
      };
      blur = function() {
        var id, self;
        if (instance != null ? instance.preserve : void 0) {
          return;
        }
        self = this;
        id = instanceId;
        return setTimeout(function() {
          if (instance != null ? instance.preserve : void 0) {
            return;
          }
          if (instance && instanceId === id) {
            hideDialog();
          }
          return updateInput(self, new color($(self).val()));
        }, 0);
      };
      createDialog();
      return this.each(function() {
        var self;
        self = this;
        $(this).css({
          backgroundColor: this.value
        });
        this.originalStyle = {
          color: this.style.color,
          backgroundColor: this.style.backgroundColor
        };
        $(this).attr('autocomplete', 'off');
        this.onfocus = focus;
        this.onblur = blur;
        return updateInput(this, new color(this.value));
      });
    };
  })(jQuery);
}).call(this);
(function() {
  var __slice = Array.prototype.slice;
  (function() {
    var Color, channelize, hslParser, hslToRgb, lookup, names, normalizeKey, parseHSL, parseHex, parseRGB, rgbParser;
    rgbParser = /^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),?\s*(\d?\.?\d*)?\)$/;
    hslParser = /^hsla?\((\d{1,3}),\s*(\d?\.?\d*),\s*(\d?\.?\d*),?\s*(\d?\.?\d*)?\)$/;
    parseRGB = function(colorString) {
      var channel, channels, parsedColor;
      if (!(channels = rgbParser.exec(colorString))) {
        return;
      }
      parsedColor = (function() {
        var _i, _len, _ref, _results;
        _ref = channels.slice(1, 5);
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          channel = _ref[_i];
          _results.push(parseFloat(channel));
        }
        return _results;
      })();
      if (isNaN(parsedColor[3])) {
        parsedColor[3] = 1;
      }
      return parsedColor;
    };
    parseHex = function(hexString) {
      var alpha, i, rgb;
      hexString = hexString.replace(/#/, '');
      switch (hexString.length) {
        case 3:
        case 4:
          if (hexString.length === 4) {
            alpha = (parseInt(hexString.substr(3, 1), 16) * 0x11) / 255;
          } else {
            alpha = 1;
          }
          rgb = (function() {
            var _results;
            _results = [];
            for (i = 0; i <= 2; i++) {
              _results.push(parseInt(hexString.substr(i, 1), 16) * 0x11);
            }
            return _results;
          })();
          rgb.push(alpha);
          return rgb;
        case 6:
        case 8:
          if (hexString.length === 8) {
            alpha = parseInt(hexString.substr(6, 2), 16) / 255;
          } else {
            alpha = 1;
          }
          rgb = (function() {
            var _results;
            _results = [];
            for (i = 0; i <= 2; i++) {
              _results.push(parseInt(hexString.substr(2 * i, 2), 16));
            }
            return _results;
          })();
          rgb.push(alpha);
          return rgb;
      }
    };
    parseHSL = function(colorString) {
      var channel, channels, parsedColor;
      if (!(channels = hslParser.exec(colorString))) {
        return;
      }
      parsedColor = (function() {
        var _i, _len, _ref, _results;
        _ref = channels.slice(1, 5);
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          channel = _ref[_i];
          _results.push(parseFloat(channel));
        }
        return _results;
      })();
      if (isNaN(parsedColor[3])) {
        parsedColor[3] = 1;
      }
      return hslToRgb(parsedColor);
    };
    hslToRgb = function(hsl) {
      var a, b, channel, g, h, hueToRgb, l, p, q, r, rgbMap, s;
      h = hsl[0], s = hsl[1], l = hsl[2], a = hsl[3];
      h = h % 360;
      if (a == null) {
        a = 1;
      }
      r = g = b = null;
      hueToRgb = function(p, q, hue) {
        hue = hue.mod(360);
        if (hue < 60) {
          return p + (q - p) * (hue / 60);
        }
        if (hue < 180) {
          return q;
        }
        if (hue < 240) {
          return p + (q - p) * ((240 - hue) / 60);
        }
        return p;
      };
      if (s === 0) {
        r = g = b = l;
      } else {
        q = (l < 0.5 ? l * (1 + s) : l + s - l * s);
        p = 2 * l - q;
        r = hueToRgb(p, q, h + 120);
        g = hueToRgb(p, q, h);
        b = hueToRgb(p, q, h - 120);
      }
      rgbMap = (function() {
        var _i, _len, _ref, _results;
        _ref = [r, g, b];
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          channel = _ref[_i];
          _results.push((channel * 255).round());
        }
        return _results;
      })();
      return rgbMap.concat(a);
    };
    normalizeKey = function(key) {
      return key.toString().toLowerCase().split(' ').join('');
    };
    channelize = function(color, alpha) {
      var channel, result;
      if (color.channels != null) {
        return color.channels();
      }
      if (Object.isArray(color)) {
        if (alpha != null) {
          alpha = parseFloat(alpha);
        } else if (color[3] != null) {
          alpha = parseFloat(color[3]);
        } else {
          alpha = 1;
        }
        result = ((function() {
          var _i, _len, _ref, _results;
          _ref = color.slice(0, 3);
          _results = [];
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            channel = _ref[_i];
            _results.push(parseFloat(channel));
          }
          return _results;
        })()).concat(alpha);
      } else {
        result = lookup[normalizeKey(color)] || parseHex(color) || parseRGB(color) || parseHSL(color);
        if (alpha != null) {
          result[3] = parseFloat(alpha);
        }
      }
      return result;
    };
    /**
    Create a new color. The constructor is very flexible. It accepts individual r, g, b, a values,
    arrays of r, g, b values, hex strings, rgb strings, hsl strings, other Color objects,
    and even the named colors from the xkcd survey: http://blog.xkcd.com/2010/05/03/color-survey-results/.
    If no arguments are given, defaults to transparent.
    
    <code><pre>
    individualRgb = Color(23, 56, 49, 0.4)
    
    individualRgb.toString()
    # => 'rgba(23, 56, 49, 0.4)'
    
    arrayRgb = Color([59, 100, 230])
    
    arrayRgb.toString()
    # => 'rgba(59, 100, 230, 1)'
    
    hex = Color('#ff0000')
    
    hex.toString()
    # => 'rgba(255, 0, 0, 1)'
    
    rgb = Color('rgb(0, 255, 0)')
    
    rgb.toString()
    # => 'rgba(0, 255, 0, 1)'
    
    hsl = Color('hsl(180, 1, 0.5)')
    
    hsl.toString()
    # => 'rgba(0, 255, 255, 1)'
    
    anotherColor = Color('blue')
    
    Color(anotherColor)
    # => a new color with the same r, g, b, and alpha values as `anotherColor`
    
    # You have access to all sorts of weird colors.
    # We give you all the named colors the browser recognizes
    # and the ones from this survey
    # http://blog.xkcd.com/2010/05/03/color-survey-results/
    namedBrown = Color('Fuzzy Wuzzy Brown')
    
    namedBrown.toHex()
    # => '#c45655'
    
    # Default behavior
    transparent = Color()
    
    transparent.toString()
    # => 'rgba(0, 0, 0, 0)'
    </pre></code>
    
    @name Color
    @param {Array|Number|String|Color} args... An Array, r, g, b values,
    a sequence of numbers defining r, g, b values, a hex or hsl string, another Color object, or a named color
    @constructor
    */
    Color = function() {
      var args, parsedColor;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      parsedColor = (function() {
        switch (args.length) {
          case 0:
            return [0, 0, 0, 0];
          case 1:
            return channelize(args.first());
          case 2:
            return channelize(args.first(), args.last());
          default:
            return channelize(args);
        }
      })();
      if (!parsedColor) {
        throw "" + (args.join(',')) + " is an unknown color";
      }
      return {
        __proto__: Color.prototype,
        r: parsedColor[0].round(),
        g: parsedColor[1].round(),
        b: parsedColor[2].round(),
        a: parsedColor[3]
      };
    };
    Color.prototype = {
      /**
        Returns the rgba color channels in an array.
      
        <code><pre>
        transparent =  Color()
      
        transparent.channels()
        # => [0, 0, 0, 0]
      
        red = Color("#FF0000")
      
        red.channels()
        # => [255, 0, 0, 1]
      
        rgb = Color(200, 34, 2)
      
        rgb.channels()
        # => [200, 34, 2, 1]
        </pre></code>
      
        @name channels
        @methodOf Color#
      
        @returns {Array} Array of r, g, b, and alpha values of the color
        */
      channels: function() {
        return [this.r, this.g, this.b, this.a];
      },
      /**
      A copy of the calling color that is its complementary color on the color wheel.
      
      <code><pre>
      red = Color(255, 0, 0)
      
      cyan = red.complement()
      
      cyan.toString()
      # => 'rgba(0, 255, 255, 1)'
      </pre></code>
      
      @name complement
      @methodOf Color#
      
      @returns {Color} new color that is a copy of the calling color with its hue shifted by 180 degrees on the color wheel
      */
      complement: function() {
        return this.copy().complement$();
      },
      /**
      Modifies the calling color to make it the complement of its previous value.
      
      <code><pre>
      red = Color(255, 0, 0)
      
      # modifies red in place to make it into cyan
      red.complement$()
      
      red.toString()
      # => 'rgba(0, 255, 255, 1)'
      </pre></code>
      
      @name complement$
      @methodOf Color#
      
      @returns {Color} the color hue shifted by 180 degrees on the color wheel. Modifies the existing color.
      */
      complement$: function() {
        return this.shiftHue$(180);
      },
      /**
      A copy of the calling color.
      
      <code><pre>
      color = Color(0, 100, 200)
      
      copy = color.copy()
      
      color == copy
      # => false
      
      color.equal(copy)
      # => true
      </pre></code>
      
      @name copy
      @methodOf Color#
      
      @returns {Color} A new color. A copy of the calling color
      */
      copy: function() {
        return Color(this.r, this.g, this.b, this.a);
      },
      /**
      Returns a copy of the calling color darkened by `amount` (Lightness of the color ranges from 0 to 1).
      
      <code><pre>
      green = Color(0, 255, 0)
      
      darkGreen = green.darken(0.3)
      
      darkGreen.toString()
      # => 'rgba(0, 102, 0, 1)'
      </pre></code>
      
      @name darken
      @methodOf Color#
      @param {Number} amount Amount to darken color by (between 0 - 1)
      
      @returns {Color} A new color. The lightness value is reduced by `amount` from the original.
      */
      darken: function(amount) {
        return this.copy().darken$(amount);
      },
      /**
      Modifies the color so that it is darkened by `amount` (Lightness of the color ranges from 0 to 1).
      
      <code><pre>
      green = Color(0, 255, 0)
      
      # Modifies green to be darkGreen
      green.darken$(0.3)
      
      green.toString()
      # => 'rgba(0, 102, 0, 1)'
      </pre></code>
      
      @name darken$
      @methodOf Color#
      @param {Number} amount Amount to darken color by (between 0 - 1)
      
      @returns {Color} the color with the lightness value reduced by `amount`
      */
      darken$: function(amount) {
        var hsl, _ref;
        hsl = this.toHsl();
        hsl[2] -= amount;
        _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        return this;
      },
      /**
      A copy of the calling color with its saturation reduced by `amount`.
      
      <code><pre>
      blue = Color(0, 0, 255)
      
      desaturatedBlue = blue.desaturate(0.3)
      
      desaturatedBlue.toString()
      # => 'rgba(38, 38, 217, 1)'
      </pre></code>
      
      @name desaturate
      @methodOf Color#
      @param {Number} amount Amount to reduce color saturation by (between 0 - 1)
      
      @returns {Color} A copy of the color with the saturation value reduced by `amount`
      */
      desaturate: function(amount) {
        return this.copy().desaturate$(amount);
      },
      /**
      The modified color with its saturation reduced by `amount`.
      
      <code><pre>
      blue = Color(0, 0, 255)
      
      # modifies blue to be desaturatedBlue
      blue.desaturate$(0.3)
      
      blue.toString()
      # => 'rgba(38, 38, 217, 1)'
      </pre></code>
      
      @name desaturate$
      @methodOf Color#
      @param {Number} amount Amount to reduce color saturation by (between 0 - 1)
      
      @returns {Color} the color with the saturation value reduced by `amount`
      */
      desaturate$: function(amount) {
        var hsl, _ref;
        hsl = this.toHsl();
        hsl[1] -= amount;
        _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        return this;
      },
      /**
      Determine whether two colors are equal. Compares their r, g, b, and alpha values.
      
      <code><pre>
      hex = Color('#ffff00')
      rgb = Color(255, 255, 0)
      
      hex == rgb
      # => false
      
      hex.equal(rgb)
      # => true
      </pre></code>
      
      @name equal
      @methodOf Color#
      @param {Color} other the color to compare to the calling color
      
      @returns {Boolean} true if the r, g, b, a values of the colors agree, false otherwise
      */
      equal: function(other) {
        return other.r === this.r && other.g === this.g && other.b === this.b && other.a === this.a;
      },
      /**
      A copy of the calling color converted to grayscale.
      
      <code><pre>
      color = Color(255, 255, 0)
      
      gray = color.grayscale()
      
      gray.toString()
      # => 'rgba(128, 128, 128, 1)'
      </pre></code>
      
      @name grayscale
      @methodOf Color#
      
      @returns {Color} A copy of the calling color converted to grayscale.
      */
      grayscale: function() {
        return this.copy().grayscale$();
      },
      /**
      The calling color converted to grayscale.
      
      <code><pre>
      color = Color(255, 255, 0)
      
      # modifies color into gray
      color.grayscale$()
      
      color.toString()
      # => 'rgba(128, 128, 128, 1)'
      </pre></code>
      
      @name grayscale$
      @methodOf Color#
      
      @returns {Color} The calling color converted to grayscale.
      */
      grayscale$: function() {
        var g, hsl;
        hsl = this.toHsl();
        g = (hsl[2] * 255).round();
        this.r = this.g = this.b = g;
        return this;
      },
      /**
      A getter / setter for the hue value of the color. Passing no argument returns the
      current hue value. Passing a value will set the hue to that value and return the color.
      
      <code><pre>
      magenta = Color(255, 0, 255)
      
      yellow = magenta.hue(60)
      
      yellow.toString()
      # => 'rgba(255, 255, 0, 1)'
      </pre></code>
      
      @name hue
      @methodOf Color#
      @param {Number} [newVal] the new hue value
      
      @returns {Color|Number} returns the color object if you pass a new hue value and returns the hue otherwise
      */
      hue: function(newVal) {
        var hsl, _ref;
        hsl = this.toHsl();
        if (newVal != null) {
          hsl[0] = newVal;
          _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
          return this;
        } else {
          return hsl[0];
        }
      },
      /**
      A getter / setter for the lightness value of the color. Passing no argument returns the
      current lightness value. Passing a value will set the lightness to that value and return the color.
      
      <code><pre>
      magenta = Color(255, 0, 255)
      
      magenta.lightness()
      # => 0.9
      
      darkerMagenta = magenta.lightness(0.75)
      
      darkerMagenta.lightness()
      # => 0.75
      </pre></code>
      
      @name lightness
      @methodOf Color#
      @param {Number} [newVal] the new lightness value
      
      @returns {Color|Number} returns the color object if you pass a new lightness value and returns the lightness otherwise
      */
      lightness: function(newVal) {
        var hsl, _ref;
        hsl = this.toHsl();
        if (newVal != null) {
          hsl[2] = newVal;
          _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
          return this;
        } else {
          return hsl[2];
        }
      },
      /**
      A copy of the calling color with its hue shifted by `degrees`. This differs from the hue setter in that it adds to the existing hue value and will wrap around 0 and 360.
      
      <code><pre>
      magenta = Color(255, 0, 255)
      
      magenta.hue()
      # => 300
      
      yellow = magenta.shiftHue(120)
      
      # since magenta's hue is 300 we have wrapped
      # around 360 to end up at 60
      yellow.hue()
      # => 60
      
      yellow.toString()
      # => 'rgba(255, 255, 0, 1)'
      </pre></code>
      
      @name shiftHue
      @methodOf Color#
      @param {Number} degrees number of degrees to shift the hue on the color wheel.
      
      @returns {Color} A copy of the color with its hue shifted by `degrees`
      */
      shiftHue: function(degrees) {
        return this.copy().shiftHue$(degrees);
      },
      /**
      The calling color with its hue shifted by `degrees`. This differs from the hue setter in that it adds to the existing hue value and will wrap around 0 and 360.
      
      <code><pre>
      magenta = Color(255, 0, 255)
      
      magenta.hue()
      # => 300
      
      magenta.shiftHue$(120)
      
      # since magenta's hue is 300 we have wrapped
      # around 360 to end up at 60. Also we have
      # modified magenta in place to become yellow
      magenta.hue()
      # => 60
      
      magenta.toString()
      # => 'rgba(255, 255, 0, 1)'
      </pre></code>
      
      @name shiftHue$
      @methodOf Color#
      @param {Number} degrees number of degrees to shift the hue on the color wheel.
      
      @returns {Color} The color with its hue shifted by `degrees`
      */
      shiftHue$: function(degrees) {
        var hsl, _ref;
        hsl = this.toHsl();
        hsl[0] = (hsl[0] + degrees.round()).mod(360);
        _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        return this;
      },
      /**
      Returns a copy of the calling color lightened by `amount` (Lightness of the color ranges from 0 to 1).
      
      <code><pre>
      green = Color(0, 255, 0)
      
      lightGreen = green.lighten(0.2)
      
      lightGreen.toString()
      # => 'rgba(102, 255, 102, 1)'
      </pre></code>
      
      @name lighten
      @methodOf Color#
      @param {Number} amount Amount to lighten color by (between 0 to 1)
      
      @returns {Color} A new color. The lightness value is increased by `amount` from the original.
      */
      lighten: function(amount) {
        return this.copy().lighten$(amount);
      },
      /**
      The calling color lightened by `amount` (Lightness of the color ranges from 0 to 1).
      
      <code><pre>
      green = Color(0, 255, 0)
      
      green.lighten(0.2)
      
      # we have modified green in place
      # to become lightGreen
      green.toString()
      # => 'rgba(102, 255, 102, 1)'
      </pre></code>
      
      @name lighten$
      @methodOf Color#
      @param {Number} amount Amount to lighten color by (between 0 - 1)
      
      @returns {Color} The calling color with its lightness value increased by `amount`.
      */
      lighten$: function(amount) {
        var hsl, _ref;
        hsl = this.toHsl();
        hsl[2] += amount;
        _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        return this;
      },
      /**
      A copy of the calling color mixed with `other` using `amount` as the
      mixing ratio. If amount is not passed, then the colors are mixed evenly.
      
      <code><pre>
      red = Color(255, 0, 0)
      yellow = Color(255, 255, 0)
      
      # With no amount argument the colors are mixed evenly
      orange = red.mixWith(yellow)
      
      orange.toString()
      # => 'rgba(255, 128, 0, 1)'
      
      # With an amount of 0.3 we are mixing the color 30% red and 70% yellow
      somethingCloseToOrange = red.mixWith(yellow, 0.3)
      
      somethingCloseToOrange.toString()
      # => rgba(255, 179, 0, 1)
      </pre></code>
      
      @name mixWith
      @methodOf Color#
      @param {Color} other the other color to mix
      @param {Number} [amount] the mixing ratio of the calling color to `other`
      
      @returns {Color} A new color that is a mix of the calling color and `other`
      */
      mixWith: function(other, amount) {
        return this.copy().mixWith$(other, amount);
      },
      /**
      A copy of the calling color mixed with `other` using `amount` as the
      mixing ratio. If amount is not passed, then the colors are mixed evenly.
      
      <code><pre>
      red = Color(255, 0, 0)
      yellow = Color(255, 255, 0)
      anotherRed = Color(255, 0, 0)
      
      # With no amount argument the colors are mixed evenly
      red.mixWith$(yellow)
      
      # We have modified red in place to be orange
      red.toString()
      # => 'rgba(255, 128, 0, 1)'
      
      # With an amount of 0.3 we are mixing the color 30% red and 70% yellow
      anotherRed.mixWith$(yellow, 0.3)
      
      # We have modified `anotherRed` in place to be somethingCloseToOrange
      anotherRed.toString()
      # => rgba(255, 179, 0, 1)
      </pre></code>
      
      @name mixWith$
      @methodOf Color#
      @param {Color} other the other color to mix
      @param {Number} [amount] the mixing ratio of the calling color to `other`
      
      @returns {Color} The modified calling color after mixing it with `other`
      */
      mixWith$: function(other, amount) {
        var _ref, _ref2;
        amount || (amount = 0.5);
        _ref = [this.r, this.g, this.b, this.a].zip([other.r, other.g, other.b, other.a]).map(function(array) {
          return (array[0] * amount) + (array[1] * (1 - amount));
        }), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        _ref2 = [this.r, this.g, this.b].map(function(color) {
          return color.round();
        }), this.r = _ref2[0], this.g = _ref2[1], this.b = _ref2[2];
        return this;
      },
      /**
      A copy of the calling color with its saturation increased by `amount`.
      
      <code><pre>
      color = Color(50, 50, 200)
      
      color.saturation()
      # => 0.6
      
      saturatedColor = color.saturate(0.2)
      
      saturatedColor.saturation()
      # => 0.8
      
      saturatedColor.toString()
      # => rgba(25, 25, 225, 1)
      </pre></code>
      
      @name saturate
      @methodOf Color#
      @param {Number} amount the amount to increase saturation by
      
      @returns {Color} A copy of the calling color with its saturation increased by `amount`
      */
      saturate: function(amount) {
        return this.copy().saturate$(amount);
      },
      /**
      The calling color with its saturation increased by `amount`.
      
      <code><pre>
      color = Color(50, 50, 200)
      
      color.saturation()
      # => 0.6
      
      color.saturate$(0.2)
      
      # We have modified color in place and increased its saturation to 0.8
      color.saturation()
      # => 0.8
      
      color.toString()
      # => rgba(25, 25, 225, 1)
      </pre></code>
      
      @name saturate$
      @methodOf Color#
      @param {Number} amount the amount to increase saturation by
      
      @returns {Color} The calling color with its saturation increased by `amount`
      */
      saturate$: function(amount) {
        var hsl, _ref;
        hsl = this.toHsl();
        hsl[1] += amount;
        _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
        return this;
      },
      /**
      A getter / setter for the saturation value of the color. Passing no argument returns the
      current saturation value. Passing a value will set the saturation to that value and return the color.
      
      <code><pre>
      hslColor = Color('hsl(60, 0.5, 0.5)')
      
      hslColor.saturation()
      # => 0.5
      </pre></code>
      
      @name saturation
      @methodOf Color#
      @param {Number} [newVal] the new saturation value
      
      @returns {Color|Number} returns the color object if you pass a new saturation value and returns the saturation otherwise
      */
      saturation: function(newVal) {
        var hsl, _ref;
        hsl = this.toHsl();
        if (newVal != null) {
          hsl[1] = newVal;
          _ref = hslToRgb(hsl), this.r = _ref[0], this.g = _ref[1], this.b = _ref[2], this.a = _ref[3];
          return this;
        } else {
          return hsl[1];
        }
      },
      /**
      returns the Hex representation of the color. Exclude the leading `#` by passing false.
      
      <code><pre>
      color = Color('hsl(60, 1, 0.5)')
      
      # passing nothing will leave the `#` intact
      color.toHex()
      # => '#ffff00'
      
      # passing false will remove the `#`
      color.toHex(false)
      # => 'ffff00'
      </pre></code>
      
      @name toHex
      @methodOf Color#
      @param {Boolean} [leadingHash] if passed as false excludes the leading `#` from the string
      
      @returns {String} returns the Hex representation of the color
      */
      toHex: function(leadingHash) {
        var hexFromNumber, padString;
        padString = function(hexString) {
          var pad;
          if (hexString.length === 1) {
            pad = "0";
          } else {
            pad = "";
          }
          return pad + hexString;
        };
        hexFromNumber = function(number) {
          return padString(number.toString(16));
        };
        if (leadingHash === false) {
          return "" + (hexFromNumber(this.r)) + (hexFromNumber(this.g)) + (hexFromNumber(this.b));
        } else {
          return "#" + (hexFromNumber(this.r)) + (hexFromNumber(this.g)) + (hexFromNumber(this.b));
        }
      },
      /**
      returns an array of the hue, saturation, lightness, and alpha values of the color.
      
      <code><pre>
      magenta = Color(255, 0, 255)
      
      magenta.toHsl()
      # => [300, 1, 0.5, 1]
      </pre></code>
      
      @name toHsl
      @methodOf Color#
      
      @returns {Array} An array of the hue, saturation, lightness, and alpha values of the color.
      */
      toHsl: function() {
        var b, channel, chroma, g, hue, lightness, max, min, r, saturation, _ref, _ref2;
        _ref = (function() {
          var _i, _len, _ref, _results;
          _ref = [this.r, this.g, this.b];
          _results = [];
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            channel = _ref[_i];
            _results.push(channel / 255);
          }
          return _results;
        }).call(this), r = _ref[0], g = _ref[1], b = _ref[2];
        _ref2 = [r, g, b].extremes(), min = _ref2.min, max = _ref2.max;
        hue = saturation = lightness = (max + min) / 2;
        chroma = max - min;
        if (chroma.abs() < 0.00001) {
          hue = saturation = 0;
        } else {
          saturation = lightness > 0.5 ? chroma / (1 - lightness) : chroma / lightness;
          saturation /= 2;
          switch (max) {
            case r:
              hue = ((g - b) / chroma) + 0;
              break;
            case g:
              hue = ((b - r) / chroma) + 2;
              break;
            case b:
              hue = ((r - g) / chroma) + 4;
          }
          hue = (hue * 60).mod(360);
        }
        return [hue, saturation, lightness, this.a];
      },
      /**
      returns string rgba representation of the color.
      
      <code><pre>
      red = Color('#ff0000')
      
      red.toString()
      # => 'rgba(255, 0, 0, 1)'
      </pre></code>
      
      @name toString
      @methodOf Color#
      
      @returns {String} The rgba string representation of the color
      */
      toString: function() {
        return "rgba(" + this.r + ", " + this.g + ", " + this.b + ", " + this.a + ")";
      },
      /**
      A copy of the calling color with its alpha reduced by `amount`.
      
      <code><pre>
      color = Color(0, 0, 0, 1)
      
      color.a
      # => 1
      
      transparentColor = color.transparentize(0.5)
      
      transparentColor.a
      # => 0.5
      </pre></code>
      
      @name transparentize
      @methodOf Color#
      
      @returns {Color} A copy of the calling color with its alpha reduced by `amount`
      */
      transparentize: function(amount) {
        return this.copy().transparentize$(amount);
      },
      /**
      The calling color with its alpha reduced by `amount`.
      
      <code><pre>
      color = Color(0, 0, 0, 1)
      
      color.a
      # => 1
      
      # We modify color in place
      color.transparentize$(0.5)
      
      color.a
      # => 0.5
      </pre></code>
      
      @name transparentize$
      @methodOf Color#
      
      @returns {Color} The calling color with its alpha reduced by `amount`
      */
      transparentize$: function(amount) {
        this.a = (this.a - amount).clamp(0, 1);
        return this;
      },
      /**
      A copy of the calling color with its alpha increased by `amount`.
      
      <code><pre>
      color = Color(0, 0, 0, 0)
      
      color.a
      # => 1
      
      opaqueColor = color.opacify(0.25)
      
      opaqueColor.a
      # => 0.25
      </pre></code>
      
      @name opacify
      @methodOf Color#
      
      @returns {Color} A copy of the calling color with its alpha increased by `amount`
      */
      opacify: function(amount) {
        return this.copy().opacify$(amount);
      },
      /**
      The calling color with its alpha increased by `amount`.
      
      <code><pre>
      color = Color(0, 0, 0, 0)
      
      color.a
      # => 1
      
      # We modify color in place
      color.opacify$(0.25)
      
      color.a
      # => 0.25
      </pre></code>
      
      @name opacify$
      @methodOf Color#
      
      @returns {Color} The calling color with its alpha increased by `amount`
      */
      opacify$: function(amount) {
        this.a += amount;
        return this;
      }
    };
    lookup = {};
    names = [["000000", "Black"], ["000080", "Navy Blue"], ["0000C8", "Dark Blue"], ["0000FF", "Blue"], ["000741", "Stratos"], ["001B1C", "Swamp"], ["002387", "Resolution Blue"], ["002900", "Deep Fir"], ["002E20", "Burnham"], ["002FA7", "International Klein Blue"], ["003153", "Prussian Blue"], ["003366", "Midnight Blue"], ["003399", "Smalt"], ["003532", "Deep Teal"], ["003E40", "Cyprus"], ["004620", "Kaitoke Green"], ["0047AB", "Cobalt"], ["004816", "Crusoe"], ["004950", "Sherpa Blue"], ["0056A7", "Endeavour"], ["00581A", "Camarone"], ["0066CC", "Science Blue"], ["0066FF", "Blue Ribbon"], ["00755E", "Tropical Rain Forest"], ["0076A3", "Allports"], ["007BA7", "Deep Cerulean"], ["007EC7", "Lochmara"], ["007FFF", "Azure Radiance"], ["008080", "Teal"], ["0095B6", "Bondi Blue"], ["009DC4", "Pacific Blue"], ["00A693", "Persian Green"], ["00A86B", "Jade"], ["00CC99", "Caribbean Green"], ["00CCCC", "Robin's Egg Blue"], ["00FF00", "Green"], ["00FF7F", "Spring Green"], ["00FFFF", "Cyan / Aqua"], ["010D1A", "Blue Charcoal"], ["011635", "Midnight"], ["011D13", "Holly"], ["012731", "Daintree"], ["01361C", "Cardin Green"], ["01371A", "County Green"], ["013E62", "Astronaut Blue"], ["013F6A", "Regal Blue"], ["014B43", "Aqua Deep"], ["015E85", "Orient"], ["016162", "Blue Stone"], ["016D39", "Fun Green"], ["01796F", "Pine Green"], ["017987", "Blue Lagoon"], ["01826B", "Deep Sea"], ["01A368", "Green Haze"], ["022D15", "English Holly"], ["02402C", "Sherwood Green"], ["02478E", "Congress Blue"], ["024E46", "Evening Sea"], ["026395", "Bahama Blue"], ["02866F", "Observatory"], ["02A4D3", "Cerulean"], ["03163C", "Tangaroa"], ["032B52", "Green Vogue"], ["036A6E", "Mosque"], ["041004", "Midnight Moss"], ["041322", "Black Pearl"], ["042E4C", "Blue Whale"], ["044022", "Zuccini"], ["044259", "Teal Blue"], ["051040", "Deep Cove"], ["051657", "Gulf Blue"], ["055989", "Venice Blue"], ["056F57", "Watercourse"], ["062A78", "Catalina Blue"], ["063537", "Tiber"], ["069B81", "Gossamer"], ["06A189", "Niagara"], ["073A50", "Tarawera"], ["080110", "Jaguar"], ["081910", "Black Bean"], ["082567", "Deep Sapphire"], ["088370", "Elf Green"], ["08E8DE", "Bright Turquoise"], ["092256", "Downriver"], ["09230F", "Palm Green"], ["09255D", "Madison"], ["093624", "Bottle Green"], ["095859", "Deep Sea Green"], ["097F4B", "Salem"], ["0A001C", "Black Russian"], ["0A480D", "Dark Fern"], ["0A6906", "Japanese Laurel"], ["0A6F75", "Atoll"], ["0B0B0B", "Cod Gray"], ["0B0F08", "Marshland"], ["0B1107", "Gordons Green"], ["0B1304", "Black Forest"], ["0B6207", "San Felix"], ["0BDA51", "Malachite"], ["0C0B1D", "Ebony"], ["0C0D0F", "Woodsmoke"], ["0C1911", "Racing Green"], ["0C7A79", "Surfie Green"], ["0C8990", "Blue Chill"], ["0D0332", "Black Rock"], ["0D1117", "Bunker"], ["0D1C19", "Aztec"], ["0D2E1C", "Bush"], ["0E0E18", "Cinder"], ["0E2A30", "Firefly"], ["0F2D9E", "Torea Bay"], ["10121D", "Vulcan"], ["101405", "Green Waterloo"], ["105852", "Eden"], ["110C6C", "Arapawa"], ["120A8F", "Ultramarine"], ["123447", "Elephant"], ["126B40", "Jewel"], ["130000", "Diesel"], ["130A06", "Asphalt"], ["13264D", "Blue Zodiac"], ["134F19", "Parsley"], ["140600", "Nero"], ["1450AA", "Tory Blue"], ["151F4C", "Bunting"], ["1560BD", "Denim"], ["15736B", "Genoa"], ["161928", "Mirage"], ["161D10", "Hunter Green"], ["162A40", "Big Stone"], ["163222", "Celtic"], ["16322C", "Timber Green"], ["163531", "Gable Green"], ["171F04", "Pine Tree"], ["175579", "Chathams Blue"], ["182D09", "Deep Forest Green"], ["18587A", "Blumine"], ["19330E", "Palm Leaf"], ["193751", "Nile Blue"], ["1959A8", "Fun Blue"], ["1A1A68", "Lucky Point"], ["1AB385", "Mountain Meadow"], ["1B0245", "Tolopea"], ["1B1035", "Haiti"], ["1B127B", "Deep Koamaru"], ["1B1404", "Acadia"], ["1B2F11", "Seaweed"], ["1B3162", "Biscay"], ["1B659D", "Matisse"], ["1C1208", "Crowshead"], ["1C1E13", "Rangoon Green"], ["1C39BB", "Persian Blue"], ["1C402E", "Everglade"], ["1C7C7D", "Elm"], ["1D6142", "Green Pea"], ["1E0F04", "Creole"], ["1E1609", "Karaka"], ["1E1708", "El Paso"], ["1E385B", "Cello"], ["1E433C", "Te Papa Green"], ["1E90FF", "Dodger Blue"], ["1E9AB0", "Eastern Blue"], ["1F120F", "Night Rider"], ["1FC2C2", "Java"], ["20208D", "Jacksons Purple"], ["202E54", "Cloud Burst"], ["204852", "Blue Dianne"], ["211A0E", "Eternity"], ["220878", "Deep Blue"], ["228B22", "Forest Green"], ["233418", "Mallard"], ["240A40", "Violet"], ["240C02", "Kilamanjaro"], ["242A1D", "Log Cabin"], ["242E16", "Black Olive"], ["24500F", "Green House"], ["251607", "Graphite"], ["251706", "Cannon Black"], ["251F4F", "Port Gore"], ["25272C", "Shark"], ["25311C", "Green Kelp"], ["2596D1", "Curious Blue"], ["260368", "Paua"], ["26056A", "Paris M"], ["261105", "Wood Bark"], ["261414", "Gondola"], ["262335", "Steel Gray"], ["26283B", "Ebony Clay"], ["273A81", "Bay of Many"], ["27504B", "Plantation"], ["278A5B", "Eucalyptus"], ["281E15", "Oil"], ["283A77", "Astronaut"], ["286ACD", "Mariner"], ["290C5E", "Violent Violet"], ["292130", "Bastille"], ["292319", "Zeus"], ["292937", "Charade"], ["297B9A", "Jelly Bean"], ["29AB87", "Jungle Green"], ["2A0359", "Cherry Pie"], ["2A140E", "Coffee Bean"], ["2A2630", "Baltic Sea"], ["2A380B", "Turtle Green"], ["2A52BE", "Cerulean Blue"], ["2B0202", "Sepia Black"], ["2B194F", "Valhalla"], ["2B3228", "Heavy Metal"], ["2C0E8C", "Blue Gem"], ["2C1632", "Revolver"], ["2C2133", "Bleached Cedar"], ["2C8C84", "Lochinvar"], ["2D2510", "Mikado"], ["2D383A", "Outer Space"], ["2D569B", "St Tropaz"], ["2E0329", "Jacaranda"], ["2E1905", "Jacko Bean"], ["2E3222", "Rangitoto"], ["2E3F62", "Rhino"], ["2E8B57", "Sea Green"], ["2EBFD4", "Scooter"], ["2F270E", "Onion"], ["2F3CB3", "Governor Bay"], ["2F519E", "Sapphire"], ["2F5A57", "Spectra"], ["2F6168", "Casal"], ["300529", "Melanzane"], ["301F1E", "Cocoa Brown"], ["302A0F", "Woodrush"], ["304B6A", "San Juan"], ["30D5C8", "Turquoise"], ["311C17", "Eclipse"], ["314459", "Pickled Bluewood"], ["315BA1", "Azure"], ["31728D", "Calypso"], ["317D82", "Paradiso"], ["32127A", "Persian Indigo"], ["32293A", "Blackcurrant"], ["323232", "Mine Shaft"], ["325D52", "Stromboli"], ["327C14", "Bilbao"], ["327DA0", "Astral"], ["33036B", "Christalle"], ["33292F", "Thunder"], ["33CC99", "Shamrock"], ["341515", "Tamarind"], ["350036", "Mardi Gras"], ["350E42", "Valentino"], ["350E57", "Jagger"], ["353542", "Tuna"], ["354E8C", "Chambray"], ["363050", "Martinique"], ["363534", "Tuatara"], ["363C0D", "Waiouru"], ["36747D", "Ming"], ["368716", "La Palma"], ["370202", "Chocolate"], ["371D09", "Clinker"], ["37290E", "Brown Tumbleweed"], ["373021", "Birch"], ["377475", "Oracle"], ["380474", "Blue Diamond"], ["381A51", "Grape"], ["383533", "Dune"], ["384555", "Oxford Blue"], ["384910", "Clover"], ["394851", "Limed Spruce"], ["396413", "Dell"], ["3A0020", "Toledo"], ["3A2010", "Sambuca"], ["3A2A6A", "Jacarta"], ["3A686C", "William"], ["3A6A47", "Killarney"], ["3AB09E", "Keppel"], ["3B000B", "Temptress"], ["3B0910", "Aubergine"], ["3B1F1F", "Jon"], ["3B2820", "Treehouse"], ["3B7A57", "Amazon"], ["3B91B4", "Boston Blue"], ["3C0878", "Windsor"], ["3C1206", "Rebel"], ["3C1F76", "Meteorite"], ["3C2005", "Dark Ebony"], ["3C3910", "Camouflage"], ["3C4151", "Bright Gray"], ["3C4443", "Cape Cod"], ["3C493A", "Lunar Green"], ["3D0C02", "Bean  "], ["3D2B1F", "Bistre"], ["3D7D52", "Goblin"], ["3E0480", "Kingfisher Daisy"], ["3E1C14", "Cedar"], ["3E2B23", "English Walnut"], ["3E2C1C", "Black Marlin"], ["3E3A44", "Ship Gray"], ["3EABBF", "Pelorous"], ["3F2109", "Bronze"], ["3F2500", "Cola"], ["3F3002", "Madras"], ["3F307F", "Minsk"], ["3F4C3A", "Cabbage Pont"], ["3F583B", "Tom Thumb"], ["3F5D53", "Mineral Green"], ["3FC1AA", "Puerto Rico"], ["3FFF00", "Harlequin"], ["401801", "Brown Pod"], ["40291D", "Cork"], ["403B38", "Masala"], ["403D19", "Thatch Green"], ["405169", "Fiord"], ["40826D", "Viridian"], ["40A860", "Chateau Green"], ["410056", "Ripe Plum"], ["411F10", "Paco"], ["412010", "Deep Oak"], ["413C37", "Merlin"], ["414257", "Gun Powder"], ["414C7D", "East Bay"], ["4169E1", "Royal Blue"], ["41AA78", "Ocean Green"], ["420303", "Burnt Maroon"], ["423921", "Lisbon Brown"], ["427977", "Faded Jade"], ["431560", "Scarlet Gum"], ["433120", "Iroko"], ["433E37", "Armadillo"], ["434C59", "River Bed"], ["436A0D", "Green Leaf"], ["44012D", "Barossa"], ["441D00", "Morocco Brown"], ["444954", "Mako"], ["454936", "Kelp"], ["456CAC", "San Marino"], ["45B1E8", "Picton Blue"], ["460B41", "Loulou"], ["462425", "Crater Brown"], ["465945", "Gray Asparagus"], ["4682B4", "Steel Blue"], ["480404", "Rustic Red"], ["480607", "Bulgarian Rose"], ["480656", "Clairvoyant"], ["481C1C", "Cocoa Bean"], ["483131", "Woody Brown"], ["483C32", "Taupe"], ["49170C", "Van Cleef"], ["492615", "Brown Derby"], ["49371B", "Metallic Bronze"], ["495400", "Verdun Green"], ["496679", "Blue Bayoux"], ["497183", "Bismark"], ["4A2A04", "Bracken"], ["4A3004", "Deep Bronze"], ["4A3C30", "Mondo"], ["4A4244", "Tundora"], ["4A444B", "Gravel"], ["4A4E5A", "Trout"], ["4B0082", "Pigment Indigo"], ["4B5D52", "Nandor"], ["4C3024", "Saddle"], ["4C4F56", "Abbey"], ["4D0135", "Blackberry"], ["4D0A18", "Cab Sav"], ["4D1E01", "Indian Tan"], ["4D282D", "Cowboy"], ["4D282E", "Livid Brown"], ["4D3833", "Rock"], ["4D3D14", "Punga"], ["4D400F", "Bronzetone"], ["4D5328", "Woodland"], ["4E0606", "Mahogany"], ["4E2A5A", "Bossanova"], ["4E3B41", "Matterhorn"], ["4E420C", "Bronze Olive"], ["4E4562", "Mulled Wine"], ["4E6649", "Axolotl"], ["4E7F9E", "Wedgewood"], ["4EABD1", "Shakespeare"], ["4F1C70", "Honey Flower"], ["4F2398", "Daisy Bush"], ["4F69C6", "Indigo"], ["4F7942", "Fern Green"], ["4F9D5D", "Fruit Salad"], ["4FA83D", "Apple"], ["504351", "Mortar"], ["507096", "Kashmir Blue"], ["507672", "Cutty Sark"], ["50C878", "Emerald"], ["514649", "Emperor"], ["516E3D", "Chalet Green"], ["517C66", "Como"], ["51808F", "Smalt Blue"], ["52001F", "Castro"], ["520C17", "Maroon Oak"], ["523C94", "Gigas"], ["533455", "Voodoo"], ["534491", "Victoria"], ["53824B", "Hippie Green"], ["541012", "Heath"], ["544333", "Judge Gray"], ["54534D", "Fuscous Gray"], ["549019", "Vida Loca"], ["55280C", "Cioccolato"], ["555B10", "Saratoga"], ["556D56", "Finlandia"], ["5590D9", "Havelock Blue"], ["56B4BE", "Fountain Blue"], ["578363", "Spring Leaves"], ["583401", "Saddle Brown"], ["585562", "Scarpa Flow"], ["587156", "Cactus"], ["589AAF", "Hippie Blue"], ["591D35", "Wine Berry"], ["592804", "Brown Bramble"], ["593737", "Congo Brown"], ["594433", "Millbrook"], ["5A6E9C", "Waikawa Gray"], ["5A87A0", "Horizon"], ["5B3013", "Jambalaya"], ["5C0120", "Bordeaux"], ["5C0536", "Mulberry Wood"], ["5C2E01", "Carnaby Tan"], ["5C5D75", "Comet"], ["5D1E0F", "Redwood"], ["5D4C51", "Don Juan"], ["5D5C58", "Chicago"], ["5D5E37", "Verdigris"], ["5D7747", "Dingley"], ["5DA19F", "Breaker Bay"], ["5E483E", "Kabul"], ["5E5D3B", "Hemlock"], ["5F3D26", "Irish Coffee"], ["5F5F6E", "Mid Gray"], ["5F6672", "Shuttle Gray"], ["5FA777", "Aqua Forest"], ["5FB3AC", "Tradewind"], ["604913", "Horses Neck"], ["605B73", "Smoky"], ["606E68", "Corduroy"], ["6093D1", "Danube"], ["612718", "Espresso"], ["614051", "Eggplant"], ["615D30", "Costa Del Sol"], ["61845F", "Glade Green"], ["622F30", "Buccaneer"], ["623F2D", "Quincy"], ["624E9A", "Butterfly Bush"], ["625119", "West Coast"], ["626649", "Finch"], ["639A8F", "Patina"], ["63B76C", "Fern"], ["6456B7", "Blue Violet"], ["646077", "Dolphin"], ["646463", "Storm Dust"], ["646A54", "Siam"], ["646E75", "Nevada"], ["6495ED", "Cornflower Blue"], ["64CCDB", "Viking"], ["65000B", "Rosewood"], ["651A14", "Cherrywood"], ["652DC1", "Purple Heart"], ["657220", "Fern Frond"], ["65745D", "Willow Grove"], ["65869F", "Hoki"], ["660045", "Pompadour"], ["660099", "Purple"], ["66023C", "Tyrian Purple"], ["661010", "Dark Tan"], ["66B58F", "Silver Tree"], ["66FF00", "Bright Green"], ["66FF66", "Screamin' Green"], ["67032D", "Black Rose"], ["675FA6", "Scampi"], ["676662", "Ironside Gray"], ["678975", "Viridian Green"], ["67A712", "Christi"], ["683600", "Nutmeg Wood Finish"], ["685558", "Zambezi"], ["685E6E", "Salt Box"], ["692545", "Tawny Port"], ["692D54", "Finn"], ["695F62", "Scorpion"], ["697E9A", "Lynch"], ["6A442E", "Spice"], ["6A5D1B", "Himalaya"], ["6A6051", "Soya Bean"], ["6B2A14", "Hairy Heath"], ["6B3FA0", "Royal Purple"], ["6B4E31", "Shingle Fawn"], ["6B5755", "Dorado"], ["6B8BA2", "Bermuda Gray"], ["6B8E23", "Olive Drab"], ["6C3082", "Eminence"], ["6CDAE7", "Turquoise Blue"], ["6D0101", "Lonestar"], ["6D5E54", "Pine Cone"], ["6D6C6C", "Dove Gray"], ["6D9292", "Juniper"], ["6D92A1", "Gothic"], ["6E0902", "Red Oxide"], ["6E1D14", "Moccaccino"], ["6E4826", "Pickled Bean"], ["6E4B26", "Dallas"], ["6E6D57", "Kokoda"], ["6E7783", "Pale Sky"], ["6F440C", "Cafe Royale"], ["6F6A61", "Flint"], ["6F8E63", "Highland"], ["6F9D02", "Limeade"], ["6FD0C5", "Downy"], ["701C1C", "Persian Plum"], ["704214", "Sepia"], ["704A07", "Antique Bronze"], ["704F50", "Ferra"], ["706555", "Coffee"], ["708090", "Slate Gray"], ["711A00", "Cedar Wood Finish"], ["71291D", "Metallic Copper"], ["714693", "Affair"], ["714AB2", "Studio"], ["715D47", "Tobacco Brown"], ["716338", "Yellow Metal"], ["716B56", "Peat"], ["716E10", "Olivetone"], ["717486", "Storm Gray"], ["718080", "Sirocco"], ["71D9E2", "Aquamarine Blue"], ["72010F", "Venetian Red"], ["724A2F", "Old Copper"], ["726D4E", "Go Ben"], ["727B89", "Raven"], ["731E8F", "Seance"], ["734A12", "Raw Umber"], ["736C9F", "Kimberly"], ["736D58", "Crocodile"], ["737829", "Crete"], ["738678", "Xanadu"], ["74640D", "Spicy Mustard"], ["747D63", "Limed Ash"], ["747D83", "Rolling Stone"], ["748881", "Blue Smoke"], ["749378", "Laurel"], ["74C365", "Mantis"], ["755A57", "Russett"], ["7563A8", "Deluge"], ["76395D", "Cosmic"], ["7666C6", "Blue Marguerite"], ["76BD17", "Lima"], ["76D7EA", "Sky Blue"], ["770F05", "Dark Burgundy"], ["771F1F", "Crown of Thorns"], ["773F1A", "Walnut"], ["776F61", "Pablo"], ["778120", "Pacifika"], ["779E86", "Oxley"], ["77DD77", "Pastel Green"], ["780109", "Japanese Maple"], ["782D19", "Mocha"], ["782F16", "Peanut"], ["78866B", "Camouflage Green"], ["788A25", "Wasabi"], ["788BBA", "Ship Cove"], ["78A39C", "Sea Nymph"], ["795D4C", "Roman Coffee"], ["796878", "Old Lavender"], ["796989", "Rum"], ["796A78", "Fedora"], ["796D62", "Sandstone"], ["79DEEC", "Spray"], ["7A013A", "Siren"], ["7A58C1", "Fuchsia Blue"], ["7A7A7A", "Boulder"], ["7A89B8", "Wild Blue Yonder"], ["7AC488", "De York"], ["7B3801", "Red Beech"], ["7B3F00", "Cinnamon"], ["7B6608", "Yukon Gold"], ["7B7874", "Tapa"], ["7B7C94", "Waterloo "], ["7B8265", "Flax Smoke"], ["7B9F80", "Amulet"], ["7BA05B", "Asparagus"], ["7C1C05", "Kenyan Copper"], ["7C7631", "Pesto"], ["7C778A", "Topaz"], ["7C7B7A", "Concord"], ["7C7B82", "Jumbo"], ["7C881A", "Trendy Green"], ["7CA1A6", "Gumbo"], ["7CB0A1", "Acapulco"], ["7CB7BB", "Neptune"], ["7D2C14", "Pueblo"], ["7DA98D", "Bay Leaf"], ["7DC8F7", "Malibu"], ["7DD8C6", "Bermuda"], ["7E3A15", "Copper Canyon"], ["7F1734", "Claret"], ["7F3A02", "Peru Tan"], ["7F626D", "Falcon"], ["7F7589", "Mobster"], ["7F76D3", "Moody Blue"], ["7FFF00", "Chartreuse"], ["7FFFD4", "Aquamarine"], ["800000", "Maroon"], ["800B47", "Rose Bud Cherry"], ["801818", "Falu Red"], ["80341F", "Red Robin"], ["803790", "Vivid Violet"], ["80461B", "Russet"], ["807E79", "Friar Gray"], ["808000", "Olive"], ["808080", "Gray"], ["80B3AE", "Gulf Stream"], ["80B3C4", "Glacier"], ["80CCEA", "Seagull"], ["81422C", "Nutmeg"], ["816E71", "Spicy Pink"], ["817377", "Empress"], ["819885", "Spanish Green"], ["826F65", "Sand Dune"], ["828685", "Gunsmoke"], ["828F72", "Battleship Gray"], ["831923", "Merlot"], ["837050", "Shadow"], ["83AA5D", "Chelsea Cucumber"], ["83D0C6", "Monte Carlo"], ["843179", "Plum"], ["84A0A0", "Granny Smith"], ["8581D9", "Chetwode Blue"], ["858470", "Bandicoot"], ["859FAF", "Bali Hai"], ["85C4CC", "Half Baked"], ["860111", "Red Devil"], ["863C3C", "Lotus"], ["86483C", "Ironstone"], ["864D1E", "Bull Shot"], ["86560A", "Rusty Nail"], ["868974", "Bitter"], ["86949F", "Regent Gray"], ["871550", "Disco"], ["87756E", "Americano"], ["877C7B", "Hurricane"], ["878D91", "Oslo Gray"], ["87AB39", "Sushi"], ["885342", "Spicy Mix"], ["886221", "Kumera"], ["888387", "Suva Gray"], ["888D65", "Avocado"], ["893456", "Camelot"], ["893843", "Solid Pink"], ["894367", "Cannon Pink"], ["897D6D", "Makara"], ["8A3324", "Burnt Umber"], ["8A73D6", "True V"], ["8A8360", "Clay Creek"], ["8A8389", "Monsoon"], ["8A8F8A", "Stack"], ["8AB9F1", "Jordy Blue"], ["8B00FF", "Electric Violet"], ["8B0723", "Monarch"], ["8B6B0B", "Corn Harvest"], ["8B8470", "Olive Haze"], ["8B847E", "Schooner"], ["8B8680", "Natural Gray"], ["8B9C90", "Mantle"], ["8B9FEE", "Portage"], ["8BA690", "Envy"], ["8BA9A5", "Cascade"], ["8BE6D8", "Riptide"], ["8C055E", "Cardinal Pink"], ["8C472F", "Mule Fawn"], ["8C5738", "Potters Clay"], ["8C6495", "Trendy Pink"], ["8D0226", "Paprika"], ["8D3D38", "Sanguine Brown"], ["8D3F3F", "Tosca"], ["8D7662", "Cement"], ["8D8974", "Granite Green"], ["8D90A1", "Manatee"], ["8DA8CC", "Polo Blue"], ["8E0000", "Red Berry"], ["8E4D1E", "Rope"], ["8E6F70", "Opium"], ["8E775E", "Domino"], ["8E8190", "Mamba"], ["8EABC1", "Nepal"], ["8F021C", "Pohutukawa"], ["8F3E33", "El Salva"], ["8F4B0E", "Korma"], ["8F8176", "Squirrel"], ["8FD6B4", "Vista Blue"], ["900020", "Burgundy"], ["901E1E", "Old Brick"], ["907874", "Hemp"], ["907B71", "Almond Frost"], ["908D39", "Sycamore"], ["92000A", "Sangria"], ["924321", "Cumin"], ["926F5B", "Beaver"], ["928573", "Stonewall"], ["928590", "Venus"], ["9370DB", "Medium Purple"], ["93CCEA", "Cornflower"], ["93DFB8", "Algae Green"], ["944747", "Copper Rust"], ["948771", "Arrowtown"], ["950015", "Scarlett"], ["956387", "Strikemaster"], ["959396", "Mountain Mist"], ["960018", "Carmine"], ["964B00", "Brown"], ["967059", "Leather"], ["9678B6", "Purple Mountain's Majesty"], ["967BB6", "Lavender Purple"], ["96A8A1", "Pewter"], ["96BBAB", "Summer Green"], ["97605D", "Au Chico"], ["9771B5", "Wisteria"], ["97CD2D", "Atlantis"], ["983D61", "Vin Rouge"], ["9874D3", "Lilac Bush"], ["98777B", "Bazaar"], ["98811B", "Hacienda"], ["988D77", "Pale Oyster"], ["98FF98", "Mint Green"], ["990066", "Fresh Eggplant"], ["991199", "Violet Eggplant"], ["991613", "Tamarillo"], ["991B07", "Totem Pole"], ["996666", "Copper Rose"], ["9966CC", "Amethyst"], ["997A8D", "Mountbatten Pink"], ["9999CC", "Blue Bell"], ["9A3820", "Prairie Sand"], ["9A6E61", "Toast"], ["9A9577", "Gurkha"], ["9AB973", "Olivine"], ["9AC2B8", "Shadow Green"], ["9B4703", "Oregon"], ["9B9E8F", "Lemon Grass"], ["9C3336", "Stiletto"], ["9D5616", "Hawaiian Tan"], ["9DACB7", "Gull Gray"], ["9DC209", "Pistachio"], ["9DE093", "Granny Smith Apple"], ["9DE5FF", "Anakiwa"], ["9E5302", "Chelsea Gem"], ["9E5B40", "Sepia Skin"], ["9EA587", "Sage"], ["9EA91F", "Citron"], ["9EB1CD", "Rock Blue"], ["9EDEE0", "Morning Glory"], ["9F381D", "Cognac"], ["9F821C", "Reef Gold"], ["9F9F9C", "Star Dust"], ["9FA0B1", "Santas Gray"], ["9FD7D3", "Sinbad"], ["9FDD8C", "Feijoa"], ["A02712", "Tabasco"], ["A1750D", "Buttered Rum"], ["A1ADB5", "Hit Gray"], ["A1C50A", "Citrus"], ["A1DAD7", "Aqua Island"], ["A1E9DE", "Water Leaf"], ["A2006D", "Flirt"], ["A23B6C", "Rouge"], ["A26645", "Cape Palliser"], ["A2AAB3", "Gray Chateau"], ["A2AEAB", "Edward"], ["A3807B", "Pharlap"], ["A397B4", "Amethyst Smoke"], ["A3E3ED", "Blizzard Blue"], ["A4A49D", "Delta"], ["A4A6D3", "Wistful"], ["A4AF6E", "Green Smoke"], ["A50B5E", "Jazzberry Jam"], ["A59B91", "Zorba"], ["A5CB0C", "Bahia"], ["A62F20", "Roof Terracotta"], ["A65529", "Paarl"], ["A68B5B", "Barley Corn"], ["A69279", "Donkey Brown"], ["A6A29A", "Dawn"], ["A72525", "Mexican Red"], ["A7882C", "Luxor Gold"], ["A85307", "Rich Gold"], ["A86515", "Reno Sand"], ["A86B6B", "Coral Tree"], ["A8989B", "Dusty Gray"], ["A899E6", "Dull Lavender"], ["A8A589", "Tallow"], ["A8AE9C", "Bud"], ["A8AF8E", "Locust"], ["A8BD9F", "Norway"], ["A8E3BD", "Chinook"], ["A9A491", "Gray Olive"], ["A9ACB6", "Aluminium"], ["A9B2C3", "Cadet Blue"], ["A9B497", "Schist"], ["A9BDBF", "Tower Gray"], ["A9BEF2", "Perano"], ["A9C6C2", "Opal"], ["AA375A", "Night Shadz"], ["AA4203", "Fire"], ["AA8B5B", "Muesli"], ["AA8D6F", "Sandal"], ["AAA5A9", "Shady Lady"], ["AAA9CD", "Logan"], ["AAABB7", "Spun Pearl"], ["AAD6E6", "Regent St Blue"], ["AAF0D1", "Magic Mint"], ["AB0563", "Lipstick"], ["AB3472", "Royal Heath"], ["AB917A", "Sandrift"], ["ABA0D9", "Cold Purple"], ["ABA196", "Bronco"], ["AC8A56", "Limed Oak"], ["AC91CE", "East Side"], ["AC9E22", "Lemon Ginger"], ["ACA494", "Napa"], ["ACA586", "Hillary"], ["ACA59F", "Cloudy"], ["ACACAC", "Silver Chalice"], ["ACB78E", "Swamp Green"], ["ACCBB1", "Spring Rain"], ["ACDD4D", "Conifer"], ["ACE1AF", "Celadon"], ["AD781B", "Mandalay"], ["ADBED1", "Casper"], ["ADDFAD", "Moss Green"], ["ADE6C4", "Padua"], ["ADFF2F", "Green Yellow"], ["AE4560", "Hippie Pink"], ["AE6020", "Desert"], ["AE809E", "Bouquet"], ["AF4035", "Medium Carmine"], ["AF4D43", "Apple Blossom"], ["AF593E", "Brown Rust"], ["AF8751", "Driftwood"], ["AF8F2C", "Alpine"], ["AF9F1C", "Lucky"], ["AFA09E", "Martini"], ["AFB1B8", "Bombay"], ["AFBDD9", "Pigeon Post"], ["B04C6A", "Cadillac"], ["B05D54", "Matrix"], ["B05E81", "Tapestry"], ["B06608", "Mai Tai"], ["B09A95", "Del Rio"], ["B0E0E6", "Powder Blue"], ["B0E313", "Inch Worm"], ["B10000", "Bright Red"], ["B14A0B", "Vesuvius"], ["B1610B", "Pumpkin Skin"], ["B16D52", "Santa Fe"], ["B19461", "Teak"], ["B1E2C1", "Fringy Flower"], ["B1F4E7", "Ice Cold"], ["B20931", "Shiraz"], ["B2A1EA", "Biloba Flower"], ["B32D29", "Tall Poppy"], ["B35213", "Fiery Orange"], ["B38007", "Hot Toddy"], ["B3AF95", "Taupe Gray"], ["B3C110", "La Rioja"], ["B43332", "Well Read"], ["B44668", "Blush"], ["B4CFD3", "Jungle Mist"], ["B57281", "Turkish Rose"], ["B57EDC", "Lavender"], ["B5A27F", "Mongoose"], ["B5B35C", "Olive Green"], ["B5D2CE", "Jet Stream"], ["B5ECDF", "Cruise"], ["B6316C", "Hibiscus"], ["B69D98", "Thatch"], ["B6B095", "Heathered Gray"], ["B6BAA4", "Eagle"], ["B6D1EA", "Spindle"], ["B6D3BF", "Gum Leaf"], ["B7410E", "Rust"], ["B78E5C", "Muddy Waters"], ["B7A214", "Sahara"], ["B7A458", "Husk"], ["B7B1B1", "Nobel"], ["B7C3D0", "Heather"], ["B7F0BE", "Madang"], ["B81104", "Milano Red"], ["B87333", "Copper"], ["B8B56A", "Gimblet"], ["B8C1B1", "Green Spring"], ["B8C25D", "Celery"], ["B8E0F9", "Sail"], ["B94E48", "Chestnut"], ["B95140", "Crail"], ["B98D28", "Marigold"], ["B9C46A", "Wild Willow"], ["B9C8AC", "Rainee"], ["BA0101", "Guardsman Red"], ["BA450C", "Rock Spray"], ["BA6F1E", "Bourbon"], ["BA7F03", "Pirate Gold"], ["BAB1A2", "Nomad"], ["BAC7C9", "Submarine"], ["BAEEF9", "Charlotte"], ["BB3385", "Medium Red Violet"], ["BB8983", "Brandy Rose"], ["BBD009", "Rio Grande"], ["BBD7C1", "Surf"], ["BCC9C2", "Powder Ash"], ["BD5E2E", "Tuscany"], ["BD978E", "Quicksand"], ["BDB1A8", "Silk"], ["BDB2A1", "Malta"], ["BDB3C7", "Chatelle"], ["BDBBD7", "Lavender Gray"], ["BDBDC6", "French Gray"], ["BDC8B3", "Clay Ash"], ["BDC9CE", "Loblolly"], ["BDEDFD", "French Pass"], ["BEA6C3", "London Hue"], ["BEB5B7", "Pink Swan"], ["BEDE0D", "Fuego"], ["BF5500", "Rose of Sharon"], ["BFB8B0", "Tide"], ["BFBED8", "Blue Haze"], ["BFC1C2", "Silver Sand"], ["BFC921", "Key Lime Pie"], ["BFDBE2", "Ziggurat"], ["BFFF00", "Lime"], ["C02B18", "Thunderbird"], ["C04737", "Mojo"], ["C08081", "Old Rose"], ["C0C0C0", "Silver"], ["C0D3B9", "Pale Leaf"], ["C0D8B6", "Pixie Green"], ["C1440E", "Tia Maria"], ["C154C1", "Fuchsia Pink"], ["C1A004", "Buddha Gold"], ["C1B7A4", "Bison Hide"], ["C1BAB0", "Tea"], ["C1BECD", "Gray Suit"], ["C1D7B0", "Sprout"], ["C1F07C", "Sulu"], ["C26B03", "Indochine"], ["C2955D", "Twine"], ["C2BDB6", "Cotton Seed"], ["C2CAC4", "Pumice"], ["C2E8E5", "Jagged Ice"], ["C32148", "Maroon Flush"], ["C3B091", "Indian Khaki"], ["C3BFC1", "Pale Slate"], ["C3C3BD", "Gray Nickel"], ["C3CDE6", "Periwinkle Gray"], ["C3D1D1", "Tiara"], ["C3DDF9", "Tropical Blue"], ["C41E3A", "Cardinal"], ["C45655", "Fuzzy Wuzzy Brown"], ["C45719", "Orange Roughy"], ["C4C4BC", "Mist Gray"], ["C4D0B0", "Coriander"], ["C4F4EB", "Mint Tulip"], ["C54B8C", "Mulberry"], ["C59922", "Nugget"], ["C5994B", "Tussock"], ["C5DBCA", "Sea Mist"], ["C5E17A", "Yellow Green"], ["C62D42", "Brick Red"], ["C6726B", "Contessa"], ["C69191", "Oriental Pink"], ["C6A84B", "Roti"], ["C6C3B5", "Ash"], ["C6C8BD", "Kangaroo"], ["C6E610", "Las Palmas"], ["C7031E", "Monza"], ["C71585", "Red Violet"], ["C7BCA2", "Coral Reef"], ["C7C1FF", "Melrose"], ["C7C4BF", "Cloud"], ["C7C9D5", "Ghost"], ["C7CD90", "Pine Glade"], ["C7DDE5", "Botticelli"], ["C88A65", "Antique Brass"], ["C8A2C8", "Lilac"], ["C8A528", "Hokey Pokey"], ["C8AABF", "Lily"], ["C8B568", "Laser"], ["C8E3D7", "Edgewater"], ["C96323", "Piper"], ["C99415", "Pizza"], ["C9A0DC", "Light Wisteria"], ["C9B29B", "Rodeo Dust"], ["C9B35B", "Sundance"], ["C9B93B", "Earls Green"], ["C9C0BB", "Silver Rust"], ["C9D9D2", "Conch"], ["C9FFA2", "Reef"], ["C9FFE5", "Aero Blue"], ["CA3435", "Flush Mahogany"], ["CABB48", "Turmeric"], ["CADCD4", "Paris White"], ["CAE00D", "Bitter Lemon"], ["CAE6DA", "Skeptic"], ["CB8FA9", "Viola"], ["CBCAB6", "Foggy Gray"], ["CBD3B0", "Green Mist"], ["CBDBD6", "Nebula"], ["CC3333", "Persian Red"], ["CC5500", "Burnt Orange"], ["CC7722", "Ochre"], ["CC8899", "Puce"], ["CCCAA8", "Thistle Green"], ["CCCCFF", "Periwinkle"], ["CCFF00", "Electric Lime"], ["CD5700", "Tenn"], ["CD5C5C", "Chestnut Rose"], ["CD8429", "Brandy Punch"], ["CDF4FF", "Onahau"], ["CEB98F", "Sorrell Brown"], ["CEBABA", "Cold Turkey"], ["CEC291", "Yuma"], ["CEC7A7", "Chino"], ["CFA39D", "Eunry"], ["CFB53B", "Old Gold"], ["CFDCCF", "Tasman"], ["CFE5D2", "Surf Crest"], ["CFF9F3", "Humming Bird"], ["CFFAF4", "Scandal"], ["D05F04", "Red Stage"], ["D06DA1", "Hopbush"], ["D07D12", "Meteor"], ["D0BEF8", "Perfume"], ["D0C0E5", "Prelude"], ["D0F0C0", "Tea Green"], ["D18F1B", "Geebung"], ["D1BEA8", "Vanilla"], ["D1C6B4", "Soft Amber"], ["D1D2CA", "Celeste"], ["D1D2DD", "Mischka"], ["D1E231", "Pear"], ["D2691E", "Hot Cinnamon"], ["D27D46", "Raw Sienna"], ["D29EAA", "Careys Pink"], ["D2B48C", "Tan"], ["D2DA97", "Deco"], ["D2F6DE", "Blue Romance"], ["D2F8B0", "Gossip"], ["D3CBBA", "Sisal"], ["D3CDC5", "Swirl"], ["D47494", "Charm"], ["D4B6AF", "Clam Shell"], ["D4BF8D", "Straw"], ["D4C4A8", "Akaroa"], ["D4CD16", "Bird Flower"], ["D4D7D9", "Iron"], ["D4DFE2", "Geyser"], ["D4E2FC", "Hawkes Blue"], ["D54600", "Grenadier"], ["D591A4", "Can Can"], ["D59A6F", "Whiskey"], ["D5D195", "Winter Hazel"], ["D5F6E3", "Granny Apple"], ["D69188", "My Pink"], ["D6C562", "Tacha"], ["D6CEF6", "Moon Raker"], ["D6D6D1", "Quill Gray"], ["D6FFDB", "Snowy Mint"], ["D7837F", "New York Pink"], ["D7C498", "Pavlova"], ["D7D0FF", "Fog"], ["D84437", "Valencia"], ["D87C63", "Japonica"], ["D8BFD8", "Thistle"], ["D8C2D5", "Maverick"], ["D8FCFA", "Foam"], ["D94972", "Cabaret"], ["D99376", "Burning Sand"], ["D9B99B", "Cameo"], ["D9D6CF", "Timberwolf"], ["D9DCC1", "Tana"], ["D9E4F5", "Link Water"], ["D9F7FF", "Mabel"], ["DA3287", "Cerise"], ["DA5B38", "Flame Pea"], ["DA6304", "Bamboo"], ["DA6A41", "Red Damask"], ["DA70D6", "Orchid"], ["DA8A67", "Copperfield"], ["DAA520", "Golden Grass"], ["DAECD6", "Zanah"], ["DAF4F0", "Iceberg"], ["DAFAFF", "Oyster Bay"], ["DB5079", "Cranberry"], ["DB9690", "Petite Orchid"], ["DB995E", "Di Serria"], ["DBDBDB", "Alto"], ["DBFFF8", "Frosted Mint"], ["DC143C", "Crimson"], ["DC4333", "Punch"], ["DCB20C", "Galliano"], ["DCB4BC", "Blossom"], ["DCD747", "Wattle"], ["DCD9D2", "Westar"], ["DCDDCC", "Moon Mist"], ["DCEDB4", "Caper"], ["DCF0EA", "Swans Down"], ["DDD6D5", "Swiss Coffee"], ["DDF9F1", "White Ice"], ["DE3163", "Cerise Red"], ["DE6360", "Roman"], ["DEA681", "Tumbleweed"], ["DEBA13", "Gold Tips"], ["DEC196", "Brandy"], ["DECBC6", "Wafer"], ["DED4A4", "Sapling"], ["DED717", "Barberry"], ["DEE5C0", "Beryl Green"], ["DEF5FF", "Pattens Blue"], ["DF73FF", "Heliotrope"], ["DFBE6F", "Apache"], ["DFCD6F", "Chenin"], ["DFCFDB", "Lola"], ["DFECDA", "Willow Brook"], ["DFFF00", "Chartreuse Yellow"], ["E0B0FF", "Mauve"], ["E0B646", "Anzac"], ["E0B974", "Harvest Gold"], ["E0C095", "Calico"], ["E0FFFF", "Baby Blue"], ["E16865", "Sunglo"], ["E1BC64", "Equator"], ["E1C0C8", "Pink Flare"], ["E1E6D6", "Periglacial Blue"], ["E1EAD4", "Kidnapper"], ["E1F6E8", "Tara"], ["E25465", "Mandy"], ["E2725B", "Terracotta"], ["E28913", "Golden Bell"], ["E292C0", "Shocking"], ["E29418", "Dixie"], ["E29CD2", "Light Orchid"], ["E2D8ED", "Snuff"], ["E2EBED", "Mystic"], ["E2F3EC", "Apple Green"], ["E30B5C", "Razzmatazz"], ["E32636", "Alizarin Crimson"], ["E34234", "Cinnabar"], ["E3BEBE", "Cavern Pink"], ["E3F5E1", "Peppermint"], ["E3F988", "Mindaro"], ["E47698", "Deep Blush"], ["E49B0F", "Gamboge"], ["E4C2D5", "Melanie"], ["E4CFDE", "Twilight"], ["E4D1C0", "Bone"], ["E4D422", "Sunflower"], ["E4D5B7", "Grain Brown"], ["E4D69B", "Zombie"], ["E4F6E7", "Frostee"], ["E4FFD1", "Snow Flurry"], ["E52B50", "Amaranth"], ["E5841B", "Zest"], ["E5CCC9", "Dust Storm"], ["E5D7BD", "Stark White"], ["E5D8AF", "Hampton"], ["E5E0E1", "Bon Jour"], ["E5E5E5", "Mercury"], ["E5F9F6", "Polar"], ["E64E03", "Trinidad"], ["E6BE8A", "Gold Sand"], ["E6BEA5", "Cashmere"], ["E6D7B9", "Double Spanish White"], ["E6E4D4", "Satin Linen"], ["E6F2EA", "Harp"], ["E6F8F3", "Off Green"], ["E6FFE9", "Hint of Green"], ["E6FFFF", "Tranquil"], ["E77200", "Mango Tango"], ["E7730A", "Christine"], ["E79F8C", "Tonys Pink"], ["E79FC4", "Kobi"], ["E7BCB4", "Rose Fog"], ["E7BF05", "Corn"], ["E7CD8C", "Putty"], ["E7ECE6", "Gray Nurse"], ["E7F8FF", "Lily White"], ["E7FEFF", "Bubbles"], ["E89928", "Fire Bush"], ["E8B9B3", "Shilo"], ["E8E0D5", "Pearl Bush"], ["E8EBE0", "Green White"], ["E8F1D4", "Chrome White"], ["E8F2EB", "Gin"], ["E8F5F2", "Aqua Squeeze"], ["E96E00", "Clementine"], ["E97451", "Burnt Sienna"], ["E97C07", "Tahiti Gold"], ["E9CECD", "Oyster Pink"], ["E9D75A", "Confetti"], ["E9E3E3", "Ebb"], ["E9F8ED", "Ottoman"], ["E9FFFD", "Clear Day"], ["EA88A8", "Carissma"], ["EAAE69", "Porsche"], ["EAB33B", "Tulip Tree"], ["EAC674", "Rob Roy"], ["EADAB8", "Raffia"], ["EAE8D4", "White Rock"], ["EAF6EE", "Panache"], ["EAF6FF", "Solitude"], ["EAF9F5", "Aqua Spring"], ["EAFFFE", "Dew"], ["EB9373", "Apricot"], ["EBC2AF", "Zinnwaldite"], ["ECA927", "Fuel Yellow"], ["ECC54E", "Ronchi"], ["ECC7EE", "French Lilac"], ["ECCDB9", "Just Right"], ["ECE090", "Wild Rice"], ["ECEBBD", "Fall Green"], ["ECEBCE", "Aths Special"], ["ECF245", "Starship"], ["ED0A3F", "Red Ribbon"], ["ED7A1C", "Tango"], ["ED9121", "Carrot Orange"], ["ED989E", "Sea Pink"], ["EDB381", "Tacao"], ["EDC9AF", "Desert Sand"], ["EDCDAB", "Pancho"], ["EDDCB1", "Chamois"], ["EDEA99", "Primrose"], ["EDF5DD", "Frost"], ["EDF5F5", "Aqua Haze"], ["EDF6FF", "Zumthor"], ["EDF9F1", "Narvik"], ["EDFC84", "Honeysuckle"], ["EE82EE", "Lavender Magenta"], ["EEC1BE", "Beauty Bush"], ["EED794", "Chalky"], ["EED9C4", "Almond"], ["EEDC82", "Flax"], ["EEDEDA", "Bizarre"], ["EEE3AD", "Double Colonial White"], ["EEEEE8", "Cararra"], ["EEEF78", "Manz"], ["EEF0C8", "Tahuna Sands"], ["EEF0F3", "Athens Gray"], ["EEF3C3", "Tusk"], ["EEF4DE", "Loafer"], ["EEF6F7", "Catskill White"], ["EEFDFF", "Twilight Blue"], ["EEFF9A", "Jonquil"], ["EEFFE2", "Rice Flower"], ["EF863F", "Jaffa"], ["EFEFEF", "Gallery"], ["EFF2F3", "Porcelain"], ["F091A9", "Mauvelous"], ["F0D52D", "Golden Dream"], ["F0DB7D", "Golden Sand"], ["F0DC82", "Buff"], ["F0E2EC", "Prim"], ["F0E68C", "Khaki"], ["F0EEFD", "Selago"], ["F0EEFF", "Titan White"], ["F0F8FF", "Alice Blue"], ["F0FCEA", "Feta"], ["F18200", "Gold Drop"], ["F19BAB", "Wewak"], ["F1E788", "Sahara Sand"], ["F1E9D2", "Parchment"], ["F1E9FF", "Blue Chalk"], ["F1EEC1", "Mint Julep"], ["F1F1F1", "Seashell"], ["F1F7F2", "Saltpan"], ["F1FFAD", "Tidal"], ["F1FFC8", "Chiffon"], ["F2552A", "Flamingo"], ["F28500", "Tangerine"], ["F2C3B2", "Mandys Pink"], ["F2F2F2", "Concrete"], ["F2FAFA", "Black Squeeze"], ["F34723", "Pomegranate"], ["F3AD16", "Buttercup"], ["F3D69D", "New Orleans"], ["F3D9DF", "Vanilla Ice"], ["F3E7BB", "Sidecar"], ["F3E9E5", "Dawn Pink"], ["F3EDCF", "Wheatfield"], ["F3FB62", "Canary"], ["F3FBD4", "Orinoco"], ["F3FFD8", "Carla"], ["F400A1", "Hollywood Cerise"], ["F4A460", "Sandy brown"], ["F4C430", "Saffron"], ["F4D81C", "Ripe Lemon"], ["F4EBD3", "Janna"], ["F4F2EE", "Pampas"], ["F4F4F4", "Wild Sand"], ["F4F8FF", "Zircon"], ["F57584", "Froly"], ["F5C85C", "Cream Can"], ["F5C999", "Manhattan"], ["F5D5A0", "Maize"], ["F5DEB3", "Wheat"], ["F5E7A2", "Sandwisp"], ["F5E7E2", "Pot Pourri"], ["F5E9D3", "Albescent White"], ["F5EDEF", "Soft Peach"], ["F5F3E5", "Ecru White"], ["F5F5DC", "Beige"], ["F5FB3D", "Golden Fizz"], ["F5FFBE", "Australian Mint"], ["F64A8A", "French Rose"], ["F653A6", "Brilliant Rose"], ["F6A4C9", "Illusion"], ["F6F0E6", "Merino"], ["F6F7F7", "Black Haze"], ["F6FFDC", "Spring Sun"], ["F7468A", "Violet Red"], ["F77703", "Chilean Fire"], ["F77FBE", "Persian Pink"], ["F7B668", "Rajah"], ["F7C8DA", "Azalea"], ["F7DBE6", "We Peep"], ["F7F2E1", "Quarter Spanish White"], ["F7F5FA", "Whisper"], ["F7FAF7", "Snow Drift"], ["F8B853", "Casablanca"], ["F8C3DF", "Chantilly"], ["F8D9E9", "Cherub"], ["F8DB9D", "Marzipan"], ["F8DD5C", "Energy Yellow"], ["F8E4BF", "Givry"], ["F8F0E8", "White Linen"], ["F8F4FF", "Magnolia"], ["F8F6F1", "Spring Wood"], ["F8F7DC", "Coconut Cream"], ["F8F7FC", "White Lilac"], ["F8F8F7", "Desert Storm"], ["F8F99C", "Texas"], ["F8FACD", "Corn Field"], ["F8FDD3", "Mimosa"], ["F95A61", "Carnation"], ["F9BF58", "Saffron Mango"], ["F9E0ED", "Carousel Pink"], ["F9E4BC", "Dairy Cream"], ["F9E663", "Portica"], ["F9E6F4", "Underage Pink"], ["F9EAF3", "Amour"], ["F9F8E4", "Rum Swizzle"], ["F9FF8B", "Dolly"], ["F9FFF6", "Sugar Cane"], ["FA7814", "Ecstasy"], ["FA9D5A", "Tan Hide"], ["FAD3A2", "Corvette"], ["FADFAD", "Peach Yellow"], ["FAE600", "Turbo"], ["FAEAB9", "Astra"], ["FAECCC", "Champagne"], ["FAF0E6", "Linen"], ["FAF3F0", "Fantasy"], ["FAF7D6", "Citrine White"], ["FAFAFA", "Alabaster"], ["FAFDE4", "Hint of Yellow"], ["FAFFA4", "Milan"], ["FB607F", "Brink Pink"], ["FB8989", "Geraldine"], ["FBA0E3", "Lavender Rose"], ["FBA129", "Sea Buckthorn"], ["FBAC13", "Sun"], ["FBAED2", "Lavender Pink"], ["FBB2A3", "Rose Bud"], ["FBBEDA", "Cupid"], ["FBCCE7", "Classic Rose"], ["FBCEB1", "Apricot Peach"], ["FBE7B2", "Banana Mania"], ["FBE870", "Marigold Yellow"], ["FBE96C", "Festival"], ["FBEA8C", "Sweet Corn"], ["FBEC5D", "Candy Corn"], ["FBF9F9", "Hint of Red"], ["FBFFBA", "Shalimar"], ["FC0FC0", "Shocking Pink"], ["FC80A5", "Tickle Me Pink"], ["FC9C1D", "Tree Poppy"], ["FCC01E", "Lightning Yellow"], ["FCD667", "Goldenrod"], ["FCD917", "Candlelight"], ["FCDA98", "Cherokee"], ["FCF4D0", "Double Pearl Lusta"], ["FCF4DC", "Pearl Lusta"], ["FCF8F7", "Vista White"], ["FCFBF3", "Bianca"], ["FCFEDA", "Moon Glow"], ["FCFFE7", "China Ivory"], ["FCFFF9", "Ceramic"], ["FD0E35", "Torch Red"], ["FD5B78", "Wild Watermelon"], ["FD7B33", "Crusta"], ["FD7C07", "Sorbus"], ["FD9FA2", "Sweet Pink"], ["FDD5B1", "Light Apricot"], ["FDD7E4", "Pig Pink"], ["FDE1DC", "Cinderella"], ["FDE295", "Golden Glow"], ["FDE910", "Lemon"], ["FDF5E6", "Old Lace"], ["FDF6D3", "Half Colonial White"], ["FDF7AD", "Drover"], ["FDFEB8", "Pale Prim"], ["FDFFD5", "Cumulus"], ["FE28A2", "Persian Rose"], ["FE4C40", "Sunset Orange"], ["FE6F5E", "Bittersweet"], ["FE9D04", "California"], ["FEA904", "Yellow Sea"], ["FEBAAD", "Melon"], ["FED33C", "Bright Sun"], ["FED85D", "Dandelion"], ["FEDB8D", "Salomie"], ["FEE5AC", "Cape Honey"], ["FEEBF3", "Remy"], ["FEEFCE", "Oasis"], ["FEF0EC", "Bridesmaid"], ["FEF2C7", "Beeswax"], ["FEF3D8", "Bleach White"], ["FEF4CC", "Pipi"], ["FEF4DB", "Half Spanish White"], ["FEF4F8", "Wisp Pink"], ["FEF5F1", "Provincial Pink"], ["FEF7DE", "Half Dutch White"], ["FEF8E2", "Solitaire"], ["FEF8FF", "White Pointer"], ["FEF9E3", "Off Yellow"], ["FEFCED", "Orange White"], ["FF0000", "Red"], ["FF007F", "Rose"], ["FF00CC", "Purple Pizzazz"], ["FF00FF", "Magenta / Fuchsia"], ["FF2400", "Scarlet"], ["FF3399", "Wild Strawberry"], ["FF33CC", "Razzle Dazzle Rose"], ["FF355E", "Radical Red"], ["FF3F34", "Red Orange"], ["FF4040", "Coral Red"], ["FF4D00", "Vermilion"], ["FF4F00", "International Orange"], ["FF6037", "Outrageous Orange"], ["FF6600", "Blaze Orange"], ["FF66FF", "Pink Flamingo"], ["FF681F", "Orange"], ["FF69B4", "Hot Pink"], ["FF6B53", "Persimmon"], ["FF6FFF", "Blush Pink"], ["FF7034", "Burning Orange"], ["FF7518", "Pumpkin"], ["FF7D07", "Flamenco"], ["FF7F00", "Flush Orange"], ["FF7F50", "Coral"], ["FF8C69", "Salmon"], ["FF9000", "Pizazz"], ["FF910F", "West Side"], ["FF91A4", "Pink Salmon"], ["FF9933", "Neon Carrot"], ["FF9966", "Atomic Tangerine"], ["FF9980", "Vivid Tangerine"], ["FF9E2C", "Sunshade"], ["FFA000", "Orange Peel"], ["FFA194", "Mona Lisa"], ["FFA500", "Web Orange"], ["FFA6C9", "Carnation Pink"], ["FFAB81", "Hit Pink"], ["FFAE42", "Yellow Orange"], ["FFB0AC", "Cornflower Lilac"], ["FFB1B3", "Sundown"], ["FFB31F", "My Sin"], ["FFB555", "Texas Rose"], ["FFB7D5", "Cotton Candy"], ["FFB97B", "Macaroni and Cheese"], ["FFBA00", "Selective Yellow"], ["FFBD5F", "Koromiko"], ["FFBF00", "Amber"], ["FFC0A8", "Wax Flower"], ["FFC0CB", "Pink"], ["FFC3C0", "Your Pink"], ["FFC901", "Supernova"], ["FFCBA4", "Flesh"], ["FFCC33", "Sunglow"], ["FFCC5C", "Golden Tainoi"], ["FFCC99", "Peach Orange"], ["FFCD8C", "Chardonnay"], ["FFD1DC", "Pastel Pink"], ["FFD2B7", "Romantic"], ["FFD38C", "Grandis"], ["FFD700", "Gold"], ["FFD800", "School bus Yellow"], ["FFD8D9", "Cosmos"], ["FFDB58", "Mustard"], ["FFDCD6", "Peach Schnapps"], ["FFDDAF", "Caramel"], ["FFDDCD", "Tuft Bush"], ["FFDDCF", "Watusi"], ["FFDDF4", "Pink Lace"], ["FFDEAD", "Navajo White"], ["FFDEB3", "Frangipani"], ["FFE1DF", "Pippin"], ["FFE1F2", "Pale Rose"], ["FFE2C5", "Negroni"], ["FFE5A0", "Cream Brulee"], ["FFE5B4", "Peach"], ["FFE6C7", "Tequila"], ["FFE772", "Kournikova"], ["FFEAC8", "Sandy Beach"], ["FFEAD4", "Karry"], ["FFEC13", "Broom"], ["FFEDBC", "Colonial White"], ["FFEED8", "Derby"], ["FFEFA1", "Vis Vis"], ["FFEFC1", "Egg White"], ["FFEFD5", "Papaya Whip"], ["FFEFEC", "Fair Pink"], ["FFF0DB", "Peach Cream"], ["FFF0F5", "Lavender blush"], ["FFF14F", "Gorse"], ["FFF1B5", "Buttermilk"], ["FFF1D8", "Pink Lady"], ["FFF1EE", "Forget Me Not"], ["FFF1F9", "Tutu"], ["FFF39D", "Picasso"], ["FFF3F1", "Chardon"], ["FFF46E", "Paris Daisy"], ["FFF4CE", "Barley White"], ["FFF4DD", "Egg Sour"], ["FFF4E0", "Sazerac"], ["FFF4E8", "Serenade"], ["FFF4F3", "Chablis"], ["FFF5EE", "Seashell Peach"], ["FFF5F3", "Sauvignon"], ["FFF6D4", "Milk Punch"], ["FFF6DF", "Varden"], ["FFF6F5", "Rose White"], ["FFF8D1", "Baja White"], ["FFF9E2", "Gin Fizz"], ["FFF9E6", "Early Dawn"], ["FFFACD", "Lemon Chiffon"], ["FFFAF4", "Bridal Heath"], ["FFFBDC", "Scotch Mist"], ["FFFBF9", "Soapstone"], ["FFFC99", "Witch Haze"], ["FFFCEA", "Buttery White"], ["FFFCEE", "Island Spice"], ["FFFDD0", "Cream"], ["FFFDE6", "Chilean Heath"], ["FFFDE8", "Travertine"], ["FFFDF3", "Orchid White"], ["FFFDF4", "Quarter Pearl Lusta"], ["FFFEE1", "Half and Half"], ["FFFEEC", "Apricot White"], ["FFFEF0", "Rice Cake"], ["FFFEF6", "Black White"], ["FFFEFD", "Romance"], ["FFFF00", "Yellow"], ["FFFF66", "Laser Lemon"], ["FFFF99", "Pale Canary"], ["FFFFB4", "Portafino"], ["FFFFF0", "Ivory"], ["FFFFFF", "White"], ["acc2d9", "cloudy blue"], ["56ae57", "dark pastel green"], ["b2996e", "dust"], ["a8ff04", "electric lime"], ["69d84f", "fresh green"], ["894585", "light eggplant"], ["70b23f", "nasty green"], ["d4ffff", "really light blue"], ["65ab7c", "tea"], ["952e8f", "warm purple"], ["fcfc81", "yellowish tan"], ["a5a391", "cement"], ["388004", "dark grass green"], ["4c9085", "dusty teal"], ["5e9b8a", "grey teal"], ["efb435", "macaroni and cheese"], ["d99b82", "pinkish tan"], ["0a5f38", "spruce"], ["0c06f7", "strong blue"], ["61de2a", "toxic green"], ["3778bf", "windows blue"], ["2242c7", "blue blue"], ["533cc6", "blue with a hint of purple"], ["9bb53c", "booger"], ["05ffa6", "bright sea green"], ["1f6357", "dark green blue"], ["017374", "deep turquoise"], ["0cb577", "green teal"], ["ff0789", "strong pink"], ["afa88b", "bland"], ["08787f", "deep aqua"], ["dd85d7", "lavender pink"], ["a6c875", "light moss green"], ["a7ffb5", "light seafoam green"], ["c2b709", "olive yellow"], ["e78ea5", "pig pink"], ["966ebd", "deep lilac"], ["ccad60", "desert"], ["ac86a8", "dusty lavender"], ["947e94", "purpley grey"], ["983fb2", "purply"], ["ff63e9", "candy pink"], ["b2fba5", "light pastel green"], ["63b365", "boring green"], ["8ee53f", "kiwi green"], ["b7e1a1", "light grey green"], ["ff6f52", "orange pink"], ["bdf8a3", "tea green"], ["d3b683", "very light brown"], ["fffcc4", "egg shell"], ["430541", "eggplant purple"], ["ffb2d0", "powder pink"], ["997570", "reddish grey"], ["ad900d", "baby shit brown"], ["c48efd", "liliac"], ["507b9c", "stormy blue"], ["7d7103", "ugly brown"], ["fffd78", "custard"], ["da467d", "darkish pink"], ["410200", "deep brown"], ["c9d179", "greenish beige"], ["fffa86", "manilla"], ["5684ae", "off blue"], ["6b7c85", "battleship grey"], ["6f6c0a", "browny green"], ["7e4071", "bruise"], ["009337", "kelley green"], ["d0e429", "sickly yellow"], ["fff917", "sunny yellow"], ["1d5dec", "azul"], ["054907", "darkgreen"], ["b5ce08", "green/yellow"], ["8fb67b", "lichen"], ["c8ffb0", "light light green"], ["fdde6c", "pale gold"], ["ffdf22", "sun yellow"], ["a9be70", "tan green"], ["6832e3", "burple"], ["fdb147", "butterscotch"], ["c7ac7d", "toupe"], ["fff39a", "dark cream"], ["850e04", "indian red"], ["efc0fe", "light lavendar"], ["40fd14", "poison green"], ["b6c406", "baby puke green"], ["9dff00", "bright yellow green"], ["3c4142", "charcoal grey"], ["f2ab15", "squash"], ["ac4f06", "cinnamon"], ["c4fe82", "light pea green"], ["2cfa1f", "radioactive green"], ["9a6200", "raw sienna"], ["ca9bf7", "baby purple"], ["875f42", "cocoa"], ["3a2efe", "light royal blue"], ["fd8d49", "orangeish"], ["8b3103", "rust brown"], ["cba560", "sand brown"], ["698339", "swamp"], ["0cdc73", "tealish green"], ["b75203", "burnt siena"], ["7f8f4e", "camo"], ["26538d", "dusk blue"], ["63a950", "fern"], ["c87f89", "old rose"], ["b1fc99", "pale light green"], ["ff9a8a", "peachy pink"], ["f6688e", "rosy pink"], ["76fda8", "light bluish green"], ["53fe5c", "light bright green"], ["4efd54", "light neon green"], ["a0febf", "light seafoam"], ["7bf2da", "tiffany blue"], ["bcf5a6", "washed out green"], ["ca6b02", "browny orange"], ["107ab0", "nice blue"], ["2138ab", "sapphire"], ["719f91", "greyish teal"], ["fdb915", "orangey yellow"], ["fefcaf", "parchment"], ["fcf679", "straw"], ["1d0200", "very dark brown"], ["cb6843", "terracota"], ["31668a", "ugly blue"], ["247afd", "clear blue"], ["ffffb6", "creme"], ["90fda9", "foam green"], ["86a17d", "grey/green"], ["fddc5c", "light gold"], ["78d1b6", "seafoam blue"], ["13bbaf", "topaz"], ["fb5ffc", "violet pink"], ["20f986", "wintergreen"], ["ffe36e", "yellow tan"], ["9d0759", "dark fuchsia"], ["3a18b1", "indigo blue"], ["c2ff89", "light yellowish green"], ["d767ad", "pale magenta"], ["720058", "rich purple"], ["ffda03", "sunflower yellow"], ["01c08d", "green/blue"], ["ac7434", "leather"], ["014600", "racing green"], ["9900fa", "vivid purple"], ["02066f", "dark royal blue"], ["8e7618", "hazel"], ["d1768f", "muted pink"], ["96b403", "booger green"], ["fdff63", "canary"], ["95a3a6", "cool grey"], ["7f684e", "dark taupe"], ["751973", "darkish purple"], ["089404", "true green"], ["ff6163", "coral pink"], ["598556", "dark sage"], ["214761", "dark slate blue"], ["3c73a8", "flat blue"], ["ba9e88", "mushroom"], ["021bf9", "rich blue"], ["734a65", "dirty purple"], ["23c48b", "greenblue"], ["8fae22", "icky green"], ["e6f2a2", "light khaki"], ["4b57db", "warm blue"], ["d90166", "dark hot pink"], ["015482", "deep sea blue"], ["9d0216", "carmine"], ["728f02", "dark yellow green"], ["ffe5ad", "pale peach"], ["4e0550", "plum purple"], ["f9bc08", "golden rod"], ["ff073a", "neon red"], ["c77986", "old pink"], ["d6fffe", "very pale blue"], ["fe4b03", "blood orange"], ["fd5956", "grapefruit"], ["fce166", "sand yellow"], ["b2713d", "clay brown"], ["1f3b4d", "dark blue grey"], ["699d4c", "flat green"], ["56fca2", "light green blue"], ["fb5581", "warm pink"], ["3e82fc", "dodger blue"], ["a0bf16", "gross green"], ["d6fffa", "ice"], ["4f738e", "metallic blue"], ["ffb19a", "pale salmon"], ["5c8b15", "sap green"], ["54ac68", "algae"], ["89a0b0", "bluey grey"], ["7ea07a", "greeny grey"], ["1bfc06", "highlighter green"], ["cafffb", "light light blue"], ["b6ffbb", "light mint"], ["a75e09", "raw umber"], ["152eff", "vivid blue"], ["8d5eb7", "deep lavender"], ["5f9e8f", "dull teal"], ["63f7b4", "light greenish blue"], ["606602", "mud green"], ["fc86aa", "pinky"], ["8c0034", "red wine"], ["758000", "shit green"], ["ab7e4c", "tan brown"], ["030764", "darkblue"], ["fe86a4", "rosa"], ["d5174e", "lipstick"], ["fed0fc", "pale mauve"], ["680018", "claret"], ["fedf08", "dandelion"], ["fe420f", "orangered"], ["6f7c00", "poop green"], ["ca0147", "ruby"], ["1b2431", "dark"], ["00fbb0", "greenish turquoise"], ["db5856", "pastel red"], ["ddd618", "piss yellow"], ["41fdfe", "bright cyan"], ["cf524e", "dark coral"], ["21c36f", "algae green"], ["a90308", "darkish red"], ["6e1005", "reddy brown"], ["fe828c", "blush pink"], ["4b6113", "camouflage green"], ["4da409", "lawn green"], ["beae8a", "putty"], ["0339f8", "vibrant blue"], ["a88f59", "dark sand"], ["5d21d0", "purple/blue"], ["feb209", "saffron"], ["4e518b", "twilight"], ["964e02", "warm brown"], ["85a3b2", "bluegrey"], ["ff69af", "bubble gum pink"], ["c3fbf4", "duck egg blue"], ["2afeb7", "greenish cyan"], ["005f6a", "petrol"], ["0c1793", "royal"], ["ffff81", "butter"], ["f0833a", "dusty orange"], ["f1f33f", "off yellow"], ["b1d27b", "pale olive green"], ["fc824a", "orangish"], ["71aa34", "leaf"], ["b7c9e2", "light blue grey"], ["4b0101", "dried blood"], ["a552e6", "lightish purple"], ["af2f0d", "rusty red"], ["8b88f8", "lavender blue"], ["9af764", "light grass green"], ["a6fbb2", "light mint green"], ["ffc512", "sunflower"], ["750851", "velvet"], ["c14a09", "brick orange"], ["fe2f4a", "lightish red"], ["0203e2", "pure blue"], ["0a437a", "twilight blue"], ["a50055", "violet red"], ["ae8b0c", "yellowy brown"], ["fd798f", "carnation"], ["bfac05", "muddy yellow"], ["3eaf76", "dark seafoam green"], ["c74767", "deep rose"], ["b9484e", "dusty red"], ["647d8e", "grey/blue"], ["bffe28", "lemon lime"], ["d725de", "purple/pink"], ["b29705", "brown yellow"], ["673a3f", "purple brown"], ["a87dc2", "wisteria"], ["fafe4b", "banana yellow"], ["c0022f", "lipstick red"], ["0e87cc", "water blue"], ["8d8468", "brown grey"], ["ad03de", "vibrant purple"], ["8cff9e", "baby green"], ["94ac02", "barf green"], ["c4fff7", "eggshell blue"], ["fdee73", "sandy yellow"], ["33b864", "cool green"], ["fff9d0", "pale"], ["758da3", "blue/grey"], ["f504c9", "hot magenta"], ["77a1b5", "greyblue"], ["8756e4", "purpley"], ["889717", "baby shit green"], ["c27e79", "brownish pink"], ["017371", "dark aquamarine"], ["9f8303", "diarrhea"], ["f7d560", "light mustard"], ["bdf6fe", "pale sky blue"], ["75b84f", "turtle green"], ["9cbb04", "bright olive"], ["29465b", "dark grey blue"], ["696006", "greeny brown"], ["adf802", "lemon green"], ["c1c6fc", "light periwinkle"], ["35ad6b", "seaweed green"], ["fffd37", "sunshine yellow"], ["a442a0", "ugly purple"], ["f36196", "medium pink"], ["947706", "puke brown"], ["fff4f2", "very light pink"], ["1e9167", "viridian"], ["b5c306", "bile"], ["feff7f", "faded yellow"], ["cffdbc", "very pale green"], ["0add08", "vibrant green"], ["87fd05", "bright lime"], ["1ef876", "spearmint"], ["7bfdc7", "light aquamarine"], ["bcecac", "light sage"], ["bbf90f", "yellowgreen"], ["ab9004", "baby poo"], ["1fb57a", "dark seafoam"], ["00555a", "deep teal"], ["a484ac", "heather"], ["c45508", "rust orange"], ["3f829d", "dirty blue"], ["548d44", "fern green"], ["c95efb", "bright lilac"], ["3ae57f", "weird green"], ["016795", "peacock blue"], ["87a922", "avocado green"], ["f0944d", "faded orange"], ["5d1451", "grape purple"], ["25ff29", "hot green"], ["d0fe1d", "lime yellow"], ["ffa62b", "mango"], ["01b44c", "shamrock"], ["ff6cb5", "bubblegum"], ["6b4247", "purplish brown"], ["c7c10c", "vomit yellow"], ["b7fffa", "pale cyan"], ["aeff6e", "key lime"], ["ec2d01", "tomato red"], ["76ff7b", "lightgreen"], ["730039", "merlot"], ["040348", "night blue"], ["df4ec8", "purpleish pink"], ["6ecb3c", "apple"], ["8f9805", "baby poop green"], ["5edc1f", "green apple"], ["d94ff5", "heliotrope"], ["c8fd3d", "yellow/green"], ["070d0d", "almost black"], ["4984b8", "cool blue"], ["51b73b", "leafy green"], ["ac7e04", "mustard brown"], ["4e5481", "dusk"], ["876e4b", "dull brown"], ["58bc08", "frog green"], ["2fef10", "vivid green"], ["2dfe54", "bright light green"], ["0aff02", "fluro green"], ["9cef43", "kiwi"], ["18d17b", "seaweed"], ["35530a", "navy green"], ["1805db", "ultramarine blue"], ["6258c4", "iris"], ["ff964f", "pastel orange"], ["ffab0f", "yellowish orange"], ["8f8ce7", "perrywinkle"], ["24bca8", "tealish"], ["3f012c", "dark plum"], ["cbf85f", "pear"], ["ff724c", "pinkish orange"], ["280137", "midnight purple"], ["b36ff6", "light urple"], ["48c072", "dark mint"], ["bccb7a", "greenish tan"], ["a8415b", "light burgundy"], ["06b1c4", "turquoise blue"], ["cd7584", "ugly pink"], ["f1da7a", "sandy"], ["ff0490", "electric pink"], ["805b87", "muted purple"], ["50a747", "mid green"], ["a8a495", "greyish"], ["cfff04", "neon yellow"], ["ffff7e", "banana"], ["ff7fa7", "carnation pink"], ["ef4026", "tomato"], ["3c9992", "sea"], ["886806", "muddy brown"], ["04f489", "turquoise green"], ["fef69e", "buff"], ["cfaf7b", "fawn"], ["3b719f", "muted blue"], ["fdc1c5", "pale rose"], ["20c073", "dark mint green"], ["9b5fc0", "amethyst"], ["0f9b8e", "blue/green"], ["742802", "chestnut"], ["9db92c", "sick green"], ["a4bf20", "pea"], ["cd5909", "rusty orange"], ["ada587", "stone"], ["be013c", "rose red"], ["b8ffeb", "pale aqua"], ["dc4d01", "deep orange"], ["a2653e", "earth"], ["638b27", "mossy green"], ["419c03", "grassy green"], ["b1ff65", "pale lime green"], ["9dbcd4", "light grey blue"], ["fdfdfe", "pale grey"], ["77ab56", "asparagus"], ["464196", "blueberry"], ["990147", "purple red"], ["befd73", "pale lime"], ["32bf84", "greenish teal"], ["af6f09", "caramel"], ["a0025c", "deep magenta"], ["ffd8b1", "light peach"], ["7f4e1e", "milk chocolate"], ["bf9b0c", "ocher"], ["6ba353", "off green"], ["f075e6", "purply pink"], ["7bc8f6", "lightblue"], ["475f94", "dusky blue"], ["f5bf03", "golden"], ["fffeb6", "light beige"], ["fffd74", "butter yellow"], ["895b7b", "dusky purple"], ["436bad", "french blue"], ["d0c101", "ugly yellow"], ["c6f808", "greeny yellow"], ["f43605", "orangish red"], ["02c14d", "shamrock green"], ["b25f03", "orangish brown"], ["2a7e19", "tree green"], ["490648", "deep violet"], ["536267", "gunmetal"], ["5a06ef", "blue/purple"], ["cf0234", "cherry"], ["c4a661", "sandy brown"], ["978a84", "warm grey"], ["1f0954", "dark indigo"], ["03012d", "midnight"], ["2bb179", "bluey green"], ["c3909b", "grey pink"], ["a66fb5", "soft purple"], ["770001", "blood"], ["922b05", "brown red"], ["7d7f7c", "medium grey"], ["990f4b", "berry"], ["8f7303", "poo"], ["c83cb9", "purpley pink"], ["fea993", "light salmon"], ["acbb0d", "snot"], ["c071fe", "easter purple"], ["ccfd7f", "light yellow green"], ["00022e", "dark navy blue"], ["828344", "drab"], ["ffc5cb", "light rose"], ["ab1239", "rouge"], ["b0054b", "purplish red"], ["99cc04", "slime green"], ["937c00", "baby poop"], ["019529", "irish green"], ["ef1de7", "pink/purple"], ["000435", "dark navy"], ["42b395", "greeny blue"], ["9d5783", "light plum"], ["c8aca9", "pinkish grey"], ["c87606", "dirty orange"], ["aa2704", "rust red"], ["e4cbff", "pale lilac"], ["fa4224", "orangey red"], ["0804f9", "primary blue"], ["5cb200", "kermit green"], ["76424e", "brownish purple"], ["6c7a0e", "murky green"], ["fbdd7e", "wheat"], ["2a0134", "very dark purple"], ["044a05", "bottle green"], ["fd4659", "watermelon"], ["0d75f8", "deep sky blue"], ["fe0002", "fire engine red"], ["cb9d06", "yellow ochre"], ["fb7d07", "pumpkin orange"], ["b9cc81", "pale olive"], ["edc8ff", "light lilac"], ["61e160", "lightish green"], ["8ab8fe", "carolina blue"], ["920a4e", "mulberry"], ["fe02a2", "shocking pink"], ["9a3001", "auburn"], ["65fe08", "bright lime green"], ["befdb7", "celadon"], ["b17261", "pinkish brown"], ["885f01", "poo brown"], ["02ccfe", "bright sky blue"], ["c1fd95", "celery"], ["836539", "dirt brown"], ["fb2943", "strawberry"], ["84b701", "dark lime"], ["b66325", "copper"], ["7f5112", "medium brown"], ["5fa052", "muted green"], ["6dedfd", "robin's egg"], ["0bf9ea", "bright aqua"], ["c760ff", "bright lavender"], ["ffffcb", "ivory"], ["f6cefc", "very light purple"], ["155084", "light navy"], ["f5054f", "pink red"], ["645403", "olive brown"], ["7a5901", "poop brown"], ["a8b504", "mustard green"], ["3d9973", "ocean green"], ["000133", "very dark blue"], ["76a973", "dusty green"], ["2e5a88", "light navy blue"], ["0bf77d", "minty green"], ["bd6c48", "adobe"], ["ac1db8", "barney"], ["2baf6a", "jade green"], ["26f7fd", "bright light blue"], ["aefd6c", "light lime"], ["9b8f55", "dark khaki"], ["ffad01", "orange yellow"], ["c69c04", "ocre"], ["f4d054", "maize"], ["de9dac", "faded pink"], ["05480d", "british racing green"], ["c9ae74", "sandstone"], ["60460f", "mud brown"], ["98f6b0", "light sea green"], ["8af1fe", "robin egg blue"], ["2ee8bb", "aqua marine"], ["11875d", "dark sea green"], ["fdb0c0", "soft pink"], ["b16002", "orangey brown"], ["f7022a", "cherry red"], ["d5ab09", "burnt yellow"], ["86775f", "brownish grey"], ["c69f59", "camel"], ["7a687f", "purplish grey"], ["042e60", "marine"], ["c88d94", "greyish pink"], ["a5fbd5", "pale turquoise"], ["fffe71", "pastel yellow"], ["6241c7", "bluey purple"], ["fffe40", "canary yellow"], ["d3494e", "faded red"], ["985e2b", "sepia"], ["a6814c", "coffee"], ["ff08e8", "bright magenta"], ["9d7651", "mocha"], ["feffca", "ecru"], ["98568d", "purpleish"], ["9e003a", "cranberry"], ["287c37", "darkish green"], ["b96902", "brown orange"], ["ba6873", "dusky rose"], ["ff7855", "melon"], ["94b21c", "sickly green"], ["c5c9c7", "silver"], ["661aee", "purply blue"], ["6140ef", "purpleish blue"], ["9be5aa", "hospital green"], ["7b5804", "shit brown"], ["276ab3", "mid blue"], ["feb308", "amber"], ["8cfd7e", "easter green"], ["6488ea", "soft blue"], ["056eee", "cerulean blue"], ["b27a01", "golden brown"], ["0ffef9", "bright turquoise"], ["fa2a55", "red pink"], ["820747", "red purple"], ["7a6a4f", "greyish brown"], ["f4320c", "vermillion"], ["a13905", "russet"], ["6f828a", "steel grey"], ["a55af4", "lighter purple"], ["ad0afd", "bright violet"], ["004577", "prussian blue"], ["658d6d", "slate green"], ["ca7b80", "dirty pink"], ["005249", "dark blue green"], ["2b5d34", "pine"], ["bff128", "yellowy green"], ["b59410", "dark gold"], ["2976bb", "bluish"], ["014182", "darkish blue"], ["bb3f3f", "dull red"], ["fc2647", "pinky red"], ["a87900", "bronze"], ["82cbb2", "pale teal"], ["667c3e", "military green"], ["fe46a5", "barbie pink"], ["fe83cc", "bubblegum pink"], ["94a617", "pea soup green"], ["a88905", "dark mustard"], ["7f5f00", "shit"], ["9e43a2", "medium purple"], ["062e03", "very dark green"], ["8a6e45", "dirt"], ["cc7a8b", "dusky pink"], ["9e0168", "red violet"], ["fdff38", "lemon yellow"], ["c0fa8b", "pistachio"], ["eedc5b", "dull yellow"], ["7ebd01", "dark lime green"], ["3b5b92", "denim blue"], ["01889f", "teal blue"], ["3d7afd", "lightish blue"], ["5f34e7", "purpley blue"], ["6d5acf", "light indigo"], ["748500", "swamp green"], ["706c11", "brown green"], ["3c0008", "dark maroon"], ["cb00f5", "hot purple"], ["002d04", "dark forest green"], ["658cbb", "faded blue"], ["749551", "drab green"], ["b9ff66", "light lime green"], ["9dc100", "snot green"], ["faee66", "yellowish"], ["7efbb3", "light blue green"], ["7b002c", "bordeaux"], ["c292a1", "light mauve"], ["017b92", "ocean"], ["fcc006", "marigold"], ["657432", "muddy green"], ["d8863b", "dull orange"], ["738595", "steel"], ["aa23ff", "electric purple"], ["08ff08", "fluorescent green"], ["9b7a01", "yellowish brown"], ["f29e8e", "blush"], ["6fc276", "soft green"], ["ff5b00", "bright orange"], ["fdff52", "lemon"], ["866f85", "purple grey"], ["8ffe09", "acid green"], ["eecffe", "pale lavender"], ["510ac9", "violet blue"], ["4f9153", "light forest green"], ["9f2305", "burnt red"], ["728639", "khaki green"], ["de0c62", "cerise"], ["916e99", "faded purple"], ["ffb16d", "apricot"], ["3c4d03", "dark olive green"], ["7f7053", "grey brown"], ["77926f", "green grey"], ["010fcc", "true blue"], ["ceaefa", "pale violet"], ["8f99fb", "periwinkle blue"], ["c6fcff", "light sky blue"], ["5539cc", "blurple"], ["544e03", "green brown"], ["017a79", "bluegreen"], ["01f9c6", "bright teal"], ["c9b003", "brownish yellow"], ["929901", "pea soup"], ["0b5509", "forest"], ["a00498", "barney purple"], ["2000b1", "ultramarine"], ["94568c", "purplish"], ["c2be0e", "puke yellow"], ["748b97", "bluish grey"], ["665fd1", "dark periwinkle"], ["9c6da5", "dark lilac"], ["c44240", "reddish"], ["a24857", "light maroon"], ["825f87", "dusty purple"], ["c9643b", "terra cotta"], ["90b134", "avocado"], ["01386a", "marine blue"], ["25a36f", "teal green"], ["59656d", "slate grey"], ["75fd63", "lighter green"], ["21fc0d", "electric green"], ["5a86ad", "dusty blue"], ["fec615", "golden yellow"], ["fffd01", "bright yellow"], ["dfc5fe", "light lavender"], ["b26400", "umber"], ["7f5e00", "poop"], ["de7e5d", "dark peach"], ["048243", "jungle green"], ["ffffd4", "eggshell"], ["3b638c", "denim"], ["b79400", "yellow brown"], ["84597e", "dull purple"], ["411900", "chocolate brown"], ["7b0323", "wine red"], ["04d9ff", "neon blue"], ["667e2c", "dirty green"], ["fbeeac", "light tan"], ["d7fffe", "ice blue"], ["4e7496", "cadet blue"], ["874c62", "dark mauve"], ["d5ffff", "very light blue"], ["826d8c", "grey purple"], ["ffbacd", "pastel pink"], ["d1ffbd", "very light green"], ["448ee4", "dark sky blue"], ["05472a", "evergreen"], ["d5869d", "dull pink"], ["3d0734", "aubergine"], ["4a0100", "mahogany"], ["f8481c", "reddish orange"], ["02590f", "deep green"], ["89a203", "vomit green"], ["e03fd8", "purple pink"], ["d58a94", "dusty pink"], ["7bb274", "faded green"], ["526525", "camo green"], ["c94cbe", "pinky purple"], ["db4bda", "pink purple"], ["9e3623", "brownish red"], ["b5485d", "dark rose"], ["735c12", "mud"], ["9c6d57", "brownish"], ["028f1e", "emerald green"], ["b1916e", "pale brown"], ["49759c", "dull blue"], ["a0450e", "burnt umber"], ["39ad48", "medium green"], ["b66a50", "clay"], ["8cffdb", "light aqua"], ["a4be5c", "light olive green"], ["cb7723", "brownish orange"], ["05696b", "dark aqua"], ["ce5dae", "purplish pink"], ["c85a53", "dark salmon"], ["96ae8d", "greenish grey"], ["1fa774", "jade"], ["7a9703", "ugly green"], ["ac9362", "dark beige"], ["01a049", "emerald"], ["d9544d", "pale red"], ["fa5ff7", "light magenta"], ["82cafc", "sky"], ["acfffc", "light cyan"], ["fcb001", "yellow orange"], ["910951", "reddish purple"], ["fe2c54", "reddish pink"], ["c875c4", "orchid"], ["cdc50a", "dirty yellow"], ["fd411e", "orange red"], ["9a0200", "deep red"], ["be6400", "orange brown"], ["030aa7", "cobalt blue"], ["fe019a", "neon pink"], ["f7879a", "rose pink"], ["887191", "greyish purple"], ["b00149", "raspberry"], ["12e193", "aqua green"], ["fe7b7c", "salmon pink"], ["ff9408", "tangerine"], ["6a6e09", "brownish green"], ["8b2e16", "red brown"], ["696112", "greenish brown"], ["e17701", "pumpkin"], ["0a481e", "pine green"], ["343837", "charcoal"], ["ffb7ce", "baby pink"], ["6a79f7", "cornflower"], ["5d06e9", "blue violet"], ["3d1c02", "chocolate"], ["82a67d", "greyish green"], ["be0119", "scarlet"], ["c9ff27", "green yellow"], ["373e02", "dark olive"], ["a9561e", "sienna"], ["caa0ff", "pastel purple"], ["ca6641", "terracotta"], ["02d8e9", "aqua blue"], ["88b378", "sage green"], ["980002", "blood red"], ["cb0162", "deep pink"], ["5cac2d", "grass"], ["769958", "moss"], ["a2bffe", "pastel blue"], ["10a674", "bluish green"], ["06b48b", "green blue"], ["af884a", "dark tan"], ["0b8b87", "greenish blue"], ["ffa756", "pale orange"], ["a2a415", "vomit"], ["154406", "forrest green"], ["856798", "dark lavender"], ["34013f", "dark violet"], ["632de9", "purple blue"], ["0a888a", "dark cyan"], ["6f7632", "olive drab"], ["d46a7e", "pinkish"], ["1e488f", "cobalt"], ["bc13fe", "neon purple"], ["7ef4cc", "light turquoise"], ["76cd26", "apple green"], ["74a662", "dull green"], ["80013f", "wine"], ["b1d1fc", "powder blue"], ["ffffe4", "off white"], ["0652ff", "electric blue"], ["045c5a", "dark turquoise"], ["5729ce", "blue purple"], ["069af3", "azure"], ["ff000d", "bright red"], ["f10c45", "pinkish red"], ["5170d7", "cornflower blue"], ["acbf69", "light olive"], ["6c3461", "grape"], ["5e819d", "greyish blue"], ["601ef9", "purplish blue"], ["b0dd16", "yellowish green"], ["cdfd02", "greenish yellow"], ["2c6fbb", "medium blue"], ["c0737a", "dusty rose"], ["d6b4fc", "light violet"], ["020035", "midnight blue"], ["703be7", "bluish purple"], ["fd3c06", "red orange"], ["960056", "dark magenta"], ["40a368", "greenish"], ["03719c", "ocean blue"], ["fc5a50", "coral"], ["ffffc2", "cream"], ["7f2b0a", "reddish brown"], ["b04e0f", "burnt sienna"], ["a03623", "brick"], ["87ae73", "sage"], ["789b73", "grey green"], ["ffffff", "white"], ["98eff9", "robin's egg blue"], ["658b38", "moss green"], ["5a7d9a", "steel blue"], ["380835", "eggplant"], ["fffe7a", "light yellow"], ["5ca904", "leaf green"], ["d8dcd6", "light grey"], ["a5a502", "puke"], ["d648d7", "pinkish purple"], ["047495", "sea blue"], ["b790d4", "pale purple"], ["5b7c99", "slate blue"], ["607c8e", "blue grey"], ["0b4008", "hunter green"], ["ed0dd9", "fuchsia"], ["8c000f", "crimson"], ["ffff84", "pale yellow"], ["bf9005", "ochre"], ["d2bd0a", "mustard yellow"], ["ff474c", "light red"], ["0485d1", "cerulean"], ["ffcfdc", "pale pink"], ["040273", "deep blue"], ["a83c09", "rust"], ["90e4c1", "light teal"], ["516572", "slate"], ["fac205", "goldenrod"], ["d5b60a", "dark yellow"], ["363737", "dark grey"], ["4b5d16", "army green"], ["6b8ba4", "grey blue"], ["80f9ad", "seafoam"], ["a57e52", "puce"], ["a9f971", "spring green"], ["c65102", "dark orange"], ["e2ca76", "sand"], ["b0ff9d", "pastel green"], ["9ffeb0", "mint"], ["fdaa48", "light orange"], ["fe01b1", "bright pink"], ["c1f80a", "chartreuse"], ["36013f", "deep purple"], ["341c02", "dark brown"], ["b9a281", "taupe"], ["8eab12", "pea green"], ["9aae07", "puke green"], ["02ab2e", "kelly green"], ["7af9ab", "seafoam green"], ["137e6d", "blue green"], ["aaa662", "khaki"], ["610023", "burgundy"], ["014d4e", "dark teal"], ["8f1402", "brick red"], ["4b006e", "royal purple"], ["580f41", "plum"], ["8fff9f", "mint green"], ["dbb40c", "gold"], ["a2cffe", "baby blue"], ["c0fb2d", "yellow green"], ["be03fd", "bright purple"], ["840000", "dark red"], ["d0fefe", "pale blue"], ["3f9b0b", "grass green"], ["01153e", "navy"], ["04d8b2", "aquamarine"], ["c04e01", "burnt orange"], ["0cff0c", "neon green"], ["0165fc", "bright blue"], ["cf6275", "rose"], ["ffd1df", "light pink"], ["ceb301", "mustard"], ["380282", "indigo"], ["aaff32", "lime"], ["53fca1", "sea green"], ["8e82fe", "periwinkle"], ["cb416b", "dark pink"], ["677a04", "olive green"], ["ffb07c", "peach"], ["c7fdb5", "pale green"], ["ad8150", "light brown"], ["ff028d", "hot pink"], ["000000", "black"], ["cea2fd", "lilac"], ["001146", "navy blue"], ["0504aa", "royal blue"], ["e6daa6", "beige"], ["ff796c", "salmon"], ["6e750e", "olive"], ["650021", "maroon"], ["01ff07", "bright green"], ["35063e", "dark purple"], ["ae7181", "mauve"], ["06470c", "forest green"], ["13eac9", "aqua"], ["00ffff", "cyan"], ["d1b26f", "tan"], ["00035b", "dark blue"], ["c79fef", "lavender"], ["06c2ac", "turquoise"], ["033500", "dark green"], ["9a0eea", "violet"], ["bf77f6", "light purple"], ["89fe05", "lime green"], ["929591", "grey"], ["75bbfd", "sky blue"], ["ffff14", "yellow"], ["c20078", "magenta"], ["96f97b", "light green"], ["f97306", "orange"], ["029386", "teal"], ["95d0fc", "light blue"], ["e50000", "red"], ["653700", "brown"], ["ff81c0", "pink"], ["0343df", "blue"], ["15b01a", "green"], ["7e1e9c", "purple"], ["FF5E99", "paul irish pink"], ["00000000", "transparent"]];
    names.each(function(element) {
      return lookup[normalizeKey(element[1])] = parseHex(element[0]);
    });
    /**
    returns a random color.
    
    <code><pre>
    Color.random().toString()
    # => 'rgba(213, 144, 202, 1)'
    
    Color.random().toString()
    # => 'rgba(1, 211, 24, 1)'
    </pre></code>
    
    @name random
    @methodOf Color
    
    @returns {Color} A random color.
    */
    Color.random = function() {
      return Color(rand(256), rand(256), rand(256));
    };
    /**
    Mix two colors. Behaves just like `#mixWith` except that you are passing two colors.
    
    <code><pre>
    red = Color(255, 0, 0)
    yellow = Color(255, 255, 0)
    
    # With no amount argument the colors are mixed evenly
    orange = Color.mix(red, yellow)
    
    orange.toString()
    # => 'rgba(255, 128, 0, 1)'
    
    # With an amount of 0.3 we are mixing the color 30% red and 70% yellow
    somethingCloseToOrange = Color.mix(red, yellow, 0.3)
    
    somethingCloseToOrange.toString()
    # => rgba(255, 179, 0, 1)
    </pre></code>
    
    @name mix
    @methodOf Color
    @see Color#mixWith
    @param {Color} color1 the first color to mix
    @param {Color} color2 the second color to mix
    @param {Number} amount the ratio to mix the colors
    
    @returns {Color} A new color that is the two colors mixed at the ratio defined by `amount`
    */
    Color.mix = function(color1, color2, amount) {
      var newColors;
      amount || (amount = 0.5);
      newColors = [color1.r, color1.g, color1.b, color1.a].zip([color2.r, color2.g, color2.b, color2.a]).map(function(array) {
        return (array[0] * amount) + (array[1] * (1 - amount));
      });
      return Color(newColors);
    };
    return (typeof exports !== "undefined" && exports !== null ? exports : this)["Color"] = Color;
  })();
}).call(this);
(function() {
  var __slice = Array.prototype.slice;
  (function($) {
    return $.fn.pixieCanvas = function(options) {
      var $canvas, canvas, context, contextAttrAccessor;
      options || (options = {});
      canvas = this.get(0);
      context = void 0;
      /**
      PixieCanvas provides a convenient wrapper for working with Context2d.
      
      Methods try to be as flexible as possible as to what arguments they take.
      
      Non-getter methods return `this` for method chaining.
      
      @name PixieCanvas
      @constructor
      */
      $canvas = $(canvas).extend({
        /**
        Passes this canvas to the block with the given matrix transformation
        applied. All drawing methods called within the block will draw
        into the canvas with the transformation applied. The transformation
        is removed at the end of the block, even if the block throws an error.
        
        @name withTransform
        @methodOf PixieCanvas#
        
        @param {Matrix} matrix
        @param {Function} block
        
        @returns this
        */
        withTransform: function(matrix, block) {
          context.save();
          context.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
          try {
            block(this);
          } finally {
            context.restore();
          }
          return this;
        },
        /**
        Clear the canvas (or a portion of it).
        
        Clear the entire canvas
        
        <code><pre>
        canvas.clear()
        </pre></code>
        
        Clear a portion of the canvas
        
        <code class="run"><pre>
        # Set up: Fill canvas with blue
        canvas.fill("blue")  
        
        # Clear a portion of the canvas
        canvas.clear
          x: 50
          y: 50
          width: 50
          height: 50
        </pre></code>
        
        You can also clear the canvas by passing x, y, width height as
        unnamed parameters:
        
        <code><pre>
        canvas.clear(25, 25, 50, 50)
        </pre></code>
        
        @name clear
        @methodOf PixieCanvas#
        
        @param {Number} [x]
        @param {Number} [y]
        @param {Number} [width]
        @param {Number} [height]
        
        @returns this
        */
        clear: function(x, y, width, height) {
          var _ref;
          if (x == null) {
            x = {};
          }
          if (y == null) {
            _ref = x, x = _ref.x, y = _ref.y, width = _ref.width, height = _ref.height;
          }
          x || (x = 0);
          y || (y = 0);
          if (width == null) {
            width = canvas.width;
          }
          if (height == null) {
            height = canvas.height;
          }
          context.clearRect(x, y, width, height);
          return this;
        },
        /**
        Fills the entire canvas (or a specified section of it) with
        the given color.
        
        <code class="run"><pre>
        # Paint the town (entire canvas) red
        canvas.fill "red"
        
        # Fill a section of the canvas white (#FFF)
        canvas.fill
          x: 50
          y: 50
          width: 50
          height: 50
          color: "#FFF"
        </pre></code>
        
        @name fill
        @methodOf PixieCanvas#
        
        @param {Number} [x=0] Optional x position to fill from.
        @param {Number} [y=0]
        @param {Number} [width=canvas.width]
        @param {Number} [height=canvas.height]
        @param {Bounds} [bounds]
        @param {String|Color} [color]
        
        @returns this
        */
        fill: function(color) {
          var bounds, height, width, x, y, _ref;
          if (color == null) {
            color = {};
          }
          if (!(typeof color.isString === "function" ? color.isString() : void 0)) {
            _ref = color, x = _ref.x, y = _ref.y, width = _ref.width, height = _ref.height, bounds = _ref.bounds, color = _ref.color;
          }
          if (bounds) {
            x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
          }
          x || (x = 0);
          y || (y = 0);
          if (width == null) {
            width = canvas.width;
          }
          if (height == null) {
            height = canvas.height;
          }
          this.fillColor(color);
          context.fillRect(x, y, width, height);
          return this;
        },
        /**
        A direct map to the Context2d draw image. `GameObject`s
        that implement drawable will have this wrapped up nicely,
        so there is a good chance that you will not have to deal with
        it directly.
        
        @name drawImage
        @methodOf PixieCanvas#
        
        @param image
        @param sx
        @param sy
        @param sWidth
        @param sHeight
        @param dx
        @param dy
        @param dWidth
        @param dHeight
        
        @returns this
        */
        drawImage: function(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) {
          context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
          return this;
        },
        /**
        Draws a circle at the specified position with the specified
        radius and color.
        
        <code class="run"><pre>
        # Draw a large orange circle
        canvas.drawCircle
          radius: 30
          position: Point(100, 75)
          color: "orange"
        
        # Draw a blue circle with radius 10 at (25, 50)
        # and a red stroke
        canvas.drawCircle
          x: 25
          y: 50
          raduis: 10
          color: "blue"
          stroke:
            color: "red"
            width: 1
        
        # Create a circle object to set up the next examples
        circle =
          radius: 20
          x: 50
          y: 50
        
        # Draw a given circle in yellow
        canvas.drawCircle
          circle: circle
          color: "yellow"
        
        # Draw the circle in green at a different position
        canvas.drawCircle
          circle: circle
          position: Point(25, 75)
          color: "green"
        
        # Draw an outline circle in purple.
        canvas.drawCircle
          x: 50
          y: 75
          radius: 10
          stroke:
            color: "purple"
            width: 2
        </pre></code>
        
        @name drawCircle
        @methodOf PixieCanvas#
        
        @param {Number} [x]
        @param {Number} [y]
        @param {Point} [position]
        @param {Number} [radius]
        @param {Color|String} [color]
        @param {Circle} [circle]
        
        @returns this
        */
        drawCircle: function(_arg) {
          var circle, color, position, radius, stroke, x, y;
          x = _arg.x, y = _arg.y, radius = _arg.radius, position = _arg.position, color = _arg.color, stroke = _arg.stroke, circle = _arg.circle;
          if (circle) {
            x = circle.x, y = circle.y, radius = circle.radius;
          }
          if (position) {
            x = position.x, y = position.y;
          }
          context.beginPath();
          context.arc(x, y, radius, 0, Math.TAU, true);
          context.closePath();
          if (color) {
            this.fillColor(color);
            context.fill();
          }
          if (stroke) {
            this.strokeColor(stroke.color);
            this.lineWidth(stroke.width);
            context.stroke();
          }
          return this;
        },
        /**
        Draws a rectangle at the specified position with given 
        width and height. Optionally takes a position, bounds
        and color argument.
        
        <code class="run"><pre>
        # Draw a red rectangle using x, y, width and height
        canvas.drawRect
          x: 50
          y: 50
          width: 50
          height: 50
          color: "#F00"
        
        # Draw a blue rectangle using position, width and height
        # and throw in a stroke for good measure
        canvas.drawRect
          position: Point(0, 0)
          width: 50
          height: 50
          color: "blue"
          stroke:
            color: "orange"
            width: 3
        
        # Set up a bounds object for the next examples
        bounds =
          x: 100
          y: 0
          width: 100
          height: 100
        
        # Draw a purple rectangle using bounds
        canvas.drawRect
          bounds: bounds
          color: "green"
        
        # Draw the outline of the same bounds, but at a different position
        canvas.drawRect
          bounds: bounds
          position: Point(0, 50)
          stroke:
            color: "purple"
            width: 2
        </pre></code>
        
        @name drawRect
        @methodOf PixieCanvas#
        
        @param {Number} [x]
        @param {Number} [y]
        @param {Number} [width]
        @param {Number} [height]
        @param {Point} [position]
        @param {Color|String} [color]
        @param {Bounds} [bounds]
        @param {Stroke} [stroke]
        
        @returns this
        */
        drawRect: function(_arg) {
          var bounds, color, height, position, stroke, width, x, y;
          x = _arg.x, y = _arg.y, width = _arg.width, height = _arg.height, position = _arg.position, bounds = _arg.bounds, color = _arg.color, stroke = _arg.stroke;
          if (bounds) {
            x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
          }
          if (position) {
            x = position.x, y = position.y;
          }
          if (color) {
            this.fillColor(color);
            context.fillRect(x, y, width, height);
          }
          if (stroke) {
            this.strokeColor(stroke.color);
            this.lineWidth(stroke.width);
            context.strokeRect(x, y, width, height);
          }
          return this;
        },
        /**
        Draw a line from `start` to `end`.
        
        <code class="run"><pre>
        # Draw a sweet diagonal
        canvas.drawLine
          start: Point(0, 0)
          end: Point(200, 200)
          color: "purple"
        
        # Draw another sweet diagonal
        canvas.drawLine
          start: Point(200, 0)
          end: Point(0, 200)
          color: "red"
          width: 6
        
        # Now draw a sweet horizontal with a direction and a length
        canvas.drawLine
          start: Point(0, 100)
          length: 200
          direction: Point(1, 0)
          color: "orange"
        
        </pre></code>
        
        @name drawLine
        @methodOf PixieCanvas#
        
        @param {Point} start
        @param {Point} [end]
        @param {Number} [width]
        @param {String|Color} [color]
        
        @returns this
        */
        drawLine: function(_arg) {
          var color, direction, end, length, start, width;
          start = _arg.start, end = _arg.end, width = _arg.width, color = _arg.color, direction = _arg.direction, length = _arg.length;
          width || (width = 3);
          if (direction) {
            end = direction.norm(length).add(start);
          }
          this.lineWidth(width);
          this.strokeColor(color);
          context.beginPath();
          context.moveTo(start.x, start.y);
          context.lineTo(end.x, end.y);
          context.closePath();
          context.stroke();
          return this;
        },
        /**
        Draw a polygon.
        
        <code class="run"><pre>
        # Draw a sweet rhombus
        canvas.drawPoly
          points: [
            Point(50, 25)
            Point(75, 50)
            Point(50, 75)
            Point(25, 50)
          ]
          color: "purple"
          stroke:
            color: "red"
            width: 2
        </pre></code>
        
        @name drawPoly
        @methodOf PixieCanvas#
        
        @param {Point[]} [points]
        @param {String|Color} [color]
        @param {stroke} [stroke]
        
        @returns this
        */
        drawPoly: function(_arg) {
          var color, points, stroke;
          points = _arg.points, color = _arg.color, stroke = _arg.stroke;
          context.beginPath();
          points.each(function(point, i) {
            if (i === 0) {
              return context.moveTo(point.x, point.y);
            } else {
              return context.lineTo(point.x, point.y);
            }
          });
          context.lineTo(points[0].x, points[0].y);
          if (color) {
            this.fillColor(color);
            context.fill();
          }
          if (stroke) {
            this.strokeColor(stroke.color);
            this.lineWidth(stroke.width);
            context.stroke();
          }
          return this;
        },
        /**
        Draw a rounded rectangle.
        
        Adapted from http://js-bits.blogspot.com/2010/07/canvas-rounded-corner-rectangles.html
        
        <code class="run"><pre>
        # Draw a purple rounded rectangle with a red outline
        canvas.drawRoundRect
          position: Point(25, 25)
          radius: 10
          width: 150
          height: 100
          color: "purple"
          stroke:
            color: "red"
            width: 2
        </pre></code>
        
        @param {Number} [x]
        @param {Number} [y]
        @param {Number} [width]
        @param {Number} [height]
        @param {Number} [radius] Defaults to 5
        @param {Point} [position]
        @param {Color|String} [color]
        @param {Bounds} [bounds]
        @param {Stroke} [stroke]
        
        @returns this
        */
        drawRoundRect: function(_arg) {
          var bounds, color, height, position, radius, stroke, width, x, y;
          x = _arg.x, y = _arg.y, width = _arg.width, height = _arg.height, radius = _arg.radius, position = _arg.position, bounds = _arg.bounds, color = _arg.color, stroke = _arg.stroke;
          if (radius == null) {
            radius = 5;
          }
          if (bounds) {
            x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
          }
          if (position) {
            x = position.x, y = position.y;
          }
          context.beginPath();
          context.moveTo(x + radius, y);
          context.lineTo(x + width - radius, y);
          context.quadraticCurveTo(x + width, y, x + width, y + radius);
          context.lineTo(x + width, y + height - radius);
          context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
          context.lineTo(x + radius, y + height);
          context.quadraticCurveTo(x, y + height, x, y + height - radius);
          context.lineTo(x, y + radius);
          context.quadraticCurveTo(x, y, x + radius, y);
          context.closePath();
          if (color) {
            this.fillColor(color);
            context.fill();
          }
          if (stroke) {
            this.lineWidth(stroke.width);
            this.strokeColor(stroke.color);
            context.stroke();
          }
          return this;
        },
        /**
        Draws text on the canvas at the given position, in the given color.
        If no color is given then the previous fill color is used.
        
        <code class="run"><pre>
        # A line to indicate the baseline
        canvas.drawLine
          start: Point(25, 50)
          end: Point(125, 50)
          color: "#333"
        
        # Draw some text, note the position of the baseline
        canvas.drawText
          position: Point(25, 50)
          color: "red"
          text: "It's dangerous to go alone"
        
        </pre></code>
        
        @name drawText
        @methodOf PixieCanvas#
        
        @param {Number} [x]
        @param {Number} [y]
        @param {String} text
        @param {Point} [position]
        @param {String|Color} [color]
        */
        drawText: function(_arg) {
          var color, position, text, x, y;
          x = _arg.x, y = _arg.y, text = _arg.text, position = _arg.position, color = _arg.color;
          if (position) {
            x = position.x, y = position.y;
          }
          this.fillColor(color);
          context.fillText(text, x, y);
          return this;
        },
        /**
        Centers the given text on the canvas at the given y position. An x position
        or point position can also be given in which case the text is centered at the
        x, y or position value specified.
        
        <code class="run"><pre>
        # A line to indicate the baseline
        canvas.drawLine
          start: Point(25, 25)
          end: Point(125, 25)
          color: "#333"
        
        # Center text on the screen at y value 25
        canvas.centerText
          y: 25
          color: "red"
          text: "It's dangerous to go alone"
        
        # Center text at point (75, 75)
        canvas.centerText
          position: Point(75, 75)
          color: "green"
          text: "take this"
        
        </pre></code>
        
        @name centerText
        @methodOf PixieCanvas#
        
        @param {String} text
        @param {Number} [y]
        @param {Number} [x]
        @param {Point} [position]
        @param {String|Color} [color]
        */
        centerText: function(_arg) {
          var color, position, text, textWidth, x, y;
          text = _arg.text, x = _arg.x, y = _arg.y, position = _arg.position, color = _arg.color;
          if (position) {
            x = position.x, y = position.y;
          }
          if (x == null) {
            x = canvas.width / 2;
          }
          textWidth = this.measureText(text);
          return this.drawText({
            text: text,
            color: color,
            x: x - textWidth / 2,
            y: y
          });
        },
        fillColor: function(color) {
          if (color) {
            if (color.channels) {
              context.fillStyle = color.toString();
            } else {
              context.fillStyle = color;
            }
            return this;
          } else {
            return context.fillStyle;
          }
        },
        strokeColor: function(color) {
          if (color) {
            if (color.channels) {
              context.strokeStyle = color.toString();
            } else {
              context.strokeStyle = color;
            }
            return this;
          } else {
            return context.strokeStyle;
          }
        },
        measureText: function(text) {
          return context.measureText(text).width;
        },
        putImageData: function(imageData, x, y) {
          context.putImageData(imageData, x, y);
          return this;
        },
        context: function() {
          return context;
        },
        element: function() {
          return canvas;
        }
      });
      contextAttrAccessor = function() {
        var attrs;
        attrs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        return attrs.each(function(attr) {
          return $canvas[attr] = function(newVal) {
            if (newVal != null) {
              context[attr] = newVal;
              return this;
            } else {
              return context[attr];
            }
          };
        });
      };
      contextAttrAccessor("font", "globalAlpha", "globalCompositeOperation", "height", "lineWidth", "textAlign", "width");
      if (canvas != null ? canvas.getContext : void 0) {
        context = canvas.getContext('2d');
        if (options.init) {
          options.init($canvas);
        }
        return $canvas;
      }
    };
  })(jQuery);
}).call(this);
/**
 * CoffeeScript Compiler v1.2.0
 * http://coffeescript.org
 *
 * Copyright 2011, Jeremy Ashkenas
 * Released under the MIT License
 */

(function(root){var CoffeeScript=function(){function require(a){return require[a]}require["./helpers"]=new function(){var a=this;(function(){var b,c;a.starts=function(a,b,c){return b===a.substr(c,b.length)},a.ends=function(a,b,c){var d;d=b.length;return b===a.substr(a.length-d-(c||0),d)},a.compact=function(a){var b,c,d,e;e=[];for(c=0,d=a.length;c<d;c++)b=a[c],b&&e.push(b);return e},a.count=function(a,b){var c,d;c=d=0;if(!b.length)return 1/0;while(d=1+a.indexOf(b,d))c++;return c},a.merge=function(a,c){return b(b({},a),c)},b=a.extend=function(a,b){var c,d;for(c in b)d=b[c],a[c]=d;return a},a.flatten=c=function(a){var b,d,e,f;d=[];for(e=0,f=a.length;e<f;e++)b=a[e],b instanceof Array?d=d.concat(c(b)):d.push(b);return d},a.del=function(a,b){var c;c=a[b],delete a[b];return c},a.last=function(a,b){return a[a.length-(b||0)-1]}}).call(this)},require["./rewriter"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=Array.prototype.indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(b in this&&this[b]===a)return b;return-1},u=Array.prototype.slice;a.Rewriter=function(){function a(){}a.prototype.rewrite=function(a){this.tokens=a,this.removeLeadingNewlines(),this.removeMidExpressionNewlines(),this.closeOpenCalls(),this.closeOpenIndexes(),this.addImplicitIndentation(),this.tagPostfixConditionals(),this.addImplicitBraces(),this.addImplicitParentheses();return this.tokens},a.prototype.scanTokens=function(a){var b,c,d;d=this.tokens,b=0;while(c=d[b])b+=a.call(this,c,b,d);return!0},a.prototype.detectEnd=function(a,b,c){var f,g,h,i,j;h=this.tokens,f=0;while(g=h[a]){if(f===0&&b.call(this,g,a))return c.call(this,g,a);if(!g||f<0)return c.call(this,g,a-1);if(i=g[0],t.call(e,i)>=0)f+=1;else if(j=g[0],t.call(d,j)>=0)f-=1;a+=1}return a-1},a.prototype.removeLeadingNewlines=function(){var a,b,c,d;d=this.tokens;for(a=0,c=d.length;a<c;a++){b=d[a][0];if(b!=="TERMINATOR")break}if(a)return this.tokens.splice(0,a)},a.prototype.removeMidExpressionNewlines=function(){return this.scanTokens(function(a,b,d){var e;if(!(a[0]==="TERMINATOR"&&(e=this.tag(b+1),t.call(c,e)>=0)))return 1;d.splice(b,1);return 0})},a.prototype.closeOpenCalls=function(){var a,b;b=function(a,b){var c;return(c=a[0])===")"||c==="CALL_END"||a[0]==="OUTDENT"&&this.tag(b-1)===")"},a=function(a,b){return this.tokens[a[0]==="OUTDENT"?b-1:b][0]="CALL_END"};return this.scanTokens(function(c,d){c[0]==="CALL_START"&&this.detectEnd(d+1,b,a);return 1})},a.prototype.closeOpenIndexes=function(){var a,b;b=function(a,b){var c;return(c=a[0])==="]"||c==="INDEX_END"},a=function(a,b){return a[0]="INDEX_END"};return this.scanTokens(function(c,d){c[0]==="INDEX_START"&&this.detectEnd(d+1,b,a);return 1})},a.prototype.addImplicitBraces=function(){var a,b,c,f,g,i,j;f=[],g=null,j=null,c=!0,i=0,b=function(a,b){var d,e,f,g,i,k;i=this.tokens.slice(b+1,b+3+1||9e9),d=i[0],g=i[1],f=i[2];if("HERECOMMENT"===(d!=null?d[0]:void 0))return!1;e=a[0],t.call(l,e)>=0&&(c=!1);return(e==="TERMINATOR"||e==="OUTDENT"||t.call(h,e)>=0&&c)&&(!j&&this.tag(b-1)!==","||(g!=null?g[0]:void 0)!==":"&&((d!=null?d[0]:void 0)!=="@"||(f!=null?f[0]:void 0)!==":"))||e===","&&d&&(k=d[0])!=="IDENTIFIER"&&k!=="NUMBER"&&k!=="STRING"&&k!=="@"&&k!=="TERMINATOR"&&k!=="OUTDENT"},a=function(a,b){var c;c=["}","}",a[2]],c.generated=!0;return this.tokens.splice(b,0,c)};return this.scanTokens(function(h,i,k){var m,n,o,p,q,r,s,u;if(s=p=h[0],t.call(e,s)>=0){f.push([p==="INDENT"&&this.tag(i-1)==="{"?"{":p,i]);return 1}if(t.call(d,p)>=0){g=f.pop();return 1}if(p!==":"||(m=this.tag(i-2))!==":"&&((u=f[f.length-1])!=null?u[0]:void 0)==="{")return 1;c=!0,f.push(["{"]),n=m==="@"?i-2:i-1;while(this.tag(n-2)==="HERECOMMENT")n-=2;o=this.tag(n-1),j=!o||t.call(l,o)>=0,r=new String("{"),r.generated=!0,q=["{",r,h[2]],q.generated=!0,k.splice(n,0,q),this.detectEnd(i+2,b,a);return 2})},a.prototype.addImplicitParentheses=function(){var a,b,c,d,e;c=e=d=!1,b=function(a,b){var c,g,i,j;g=a[0];if(!e&&a.fromThen)return!0;if(g==="IF"||g==="ELSE"||g==="CATCH"||g==="->"||g==="=>"||g==="CLASS")e=!0;if(g==="IF"||g==="ELSE"||g==="SWITCH"||g==="TRY"||g==="=")d=!0;if((g==="."||g==="?."||g==="::")&&this.tag(b-1)==="OUTDENT")return!0;return!a.generated&&this.tag(b-1)!==","&&(t.call(h,g)>=0||g==="INDENT"&&!d)&&(g!=="INDENT"||(i=this.tag(b-2))!=="CLASS"&&i!=="EXTENDS"&&(j=this.tag(b-1),t.call(f,j)<0)&&(!(c=this.tokens[b+1])||!c.generated||c[0]!=="{"))},a=function(a,b){return this.tokens.splice(b,0,["CALL_END",")",a[2]])};return this.scanTokens(function(f,h,k){var m,n,o,p,q,r,s,u;q=f[0];if(q==="CLASS"||q==="IF")c=!0;r=k.slice(h-1,h+1+1||9e9),p=r[0],n=r[1],o=r[2],m=!c&&q==="INDENT"&&o&&o.generated&&o[0]==="{"&&p&&(s=p[0],t.call(i,s)>=0),e=!1,d=!1,t.call(l,q)>=0&&(c=!1),p&&!p.spaced&&q==="?"&&(f.call=!0);if(f.fromThen)return 1;if(!(m||(p!=null?p.spaced:void 0)&&(p.call||(u=p[0],t.call(i,u)>=0))&&(t.call(g,q)>=0||!f.spaced&&!f.newLine&&t.call(j,q)>=0)))return 1;k.splice(h,0,["CALL_START","(",f[2]]),this.detectEnd(h+1,b,a),p[0]==="?"&&(p[0]="FUNC_EXIST");return 2})},a.prototype.addImplicitIndentation=function(){var a,b,c,d,e;e=c=d=null,b=function(a,b){var c;return a[1]!==";"&&(c=a[0],t.call(m,c)>=0)&&(a[0]!=="ELSE"||e==="IF"||e==="THEN")},a=function(a,b){return this.tokens.splice(this.tag(b-1)===","?b-1:b,0,d)};return this.scanTokens(function(f,g,h){var i,j,k;i=f[0];if(i==="TERMINATOR"&&this.tag(g+1)==="THEN"){h.splice(g,1);return 0}if(i==="ELSE"&&this.tag(g-1)!=="OUTDENT"){h.splice.apply(h,[g,0].concat(u.call(this.indentation(f))));return 2}if(i==="CATCH"&&((j=this.tag(g+2))==="OUTDENT"||j==="TERMINATOR"||j==="FINALLY")){h.splice.apply(h,[g+2,0].concat(u.call(this.indentation(f))));return 4}if(t.call(n,i)>=0&&this.tag(g+1)!=="INDENT"&&(i!=="ELSE"||this.tag(g+1)!=="IF")){e=i,k=this.indentation(f),c=k[0],d=k[1],e==="THEN"&&(c.fromThen=!0),c.generated=d.generated=!0,h.splice(g+1,0,c),this.detectEnd(g+2,b,a),i==="THEN"&&h.splice(g,1);return 1}return 1})},a.prototype.tagPostfixConditionals=function(){var a,b,c;c=null,b=function(a,b){var c;return(c=a[0])==="TERMINATOR"||c==="INDENT"},a=function(a,b){if(a[0]!=="INDENT"||a.generated&&!a.fromThen)return c[0]="POST_"+c[0]};return this.scanTokens(function(d,e){if(d[0]!=="IF")return 1;c=d,this.detectEnd(e+1,b,a);return 1})},a.prototype.indentation=function(a){return[["INDENT",2,a[2]],["OUTDENT",2,a[2]]]},a.prototype.tag=function(a){var b;return(b=this.tokens[a])!=null?b[0]:void 0};return a}(),b=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],a.INVERSES=k={},e=[],d=[];for(q=0,r=b.length;q<r;q++)s=b[q],o=s[0],p=s[1],e.push(k[p]=o),d.push(k[o]=p);c=["CATCH","WHEN","ELSE","FINALLY"].concat(d),i=["IDENTIFIER","SUPER",")","CALL_END","]","INDEX_END","@","THIS"],g=["IDENTIFIER","NUMBER","STRING","JS","REGEX","NEW","PARAM_START","CLASS","IF","TRY","SWITCH","THIS","BOOL","UNARY","SUPER","@","->","=>","[","(","{","--","++"],j=["+","-"],f=["->","=>","{","[",","],h=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],n=["ELSE","->","=>","TRY","FINALLY","THEN"],m=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],l=["TERMINATOR","INDENT","OUTDENT"]}).call(this)},require["./lexer"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W=Array.prototype.indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(b in this&&this[b]===a)return b;return-1};U=require("./rewriter"),J=U.Rewriter,r=U.INVERSES,V=require("./helpers"),Q=V.count,T=V.starts,P=V.compact,S=V.last,a.Lexer=y=function(){function a(){}a.prototype.tokenize=function(a,b){var c,d;b==null&&(b={}),O.test(a)&&(a="\n"+a),a=a.replace(/\r/g,"").replace(M,""),this.code=a,this.line=b.line||0,this.indent=0,this.indebt=0,this.outdebt=0,this.indents=[],this.ends=[],this.tokens=[],c=0;while(this.chunk=a.slice(c))c+=this.identifierToken()||this.commentToken()||this.whitespaceToken()||this.lineToken()||this.heredocToken()||this.stringToken()||this.numberToken()||this.regexToken()||this.jsToken()||this.literalToken();this.closeIndentation(),(d=this.ends.pop())&&this.error("missing "+d);if(b.rewrite===!1)return this.tokens;return(new J).rewrite(this.tokens)},a.prototype.identifierToken=function(){var a,b,c,d,h,i,j,k,l;if(!(h=p.exec(this.chunk)))return 0;d=h[0],c=h[1],a=h[2];if(c==="own"&&this.tag()==="FOR"){this.token("OWN",c);return c.length}b=a||(i=S(this.tokens))&&((k=i[0])==="."||k==="?."||k==="::"||!i.spaced&&i[0]==="@"),j="IDENTIFIER",!b&&(W.call(u,c)>=0||W.call(g,c)>=0)&&(j=c.toUpperCase(),j==="WHEN"&&(l=this.tag(),W.call(v,l)>=0)?j="LEADING_WHEN":j==="FOR"?this.seenFor=!0:j==="UNLESS"?j="IF":W.call(N,j)>=0?j="UNARY":W.call(H,j)>=0&&(j!=="INSTANCEOF"&&this.seenFor?(j="FOR"+j,this.seenFor=!1):(j="RELATION",this.value()==="!"&&(this.tokens.pop(),c="!"+c)))),W.call(["eval","arguments"].concat(t),c)>=0&&(b?(j="IDENTIFIER",c=new String(c),c.reserved=!0):W.call(I,c)>=0&&this.error('reserved word "'+c+'"')),b||(W.call(e,c)>=0&&(c=f[c]),j=function(){switch(c){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":case"null":case"undefined":return"BOOL";case"break":case"continue":return"STATEMENT";default:return j}}()),this.token(j,c),a&&this.token(":",":");return d.length},a.prototype.numberToken=function(){var a,b,c,d;if(!(c=E.exec(this.chunk)))return 0;d=c[0],b=d.length;if(a=/0b([01]+)/.exec(d))d=parseInt(a[1],2).toString();this.token("NUMBER",d);return b},a.prototype.stringToken=function(){var a,b;switch(this.chunk.charAt(0)){case"'":if(!(a=L.exec(this.chunk)))return 0;this.token("STRING",(b=a[0]).replace(A,"\\\n"));break;case'"':if(!(b=this.balancedString(this.chunk,'"')))return 0;0<b.indexOf("#{",1)?this.interpolateString(b.slice(1,-1)):this.token("STRING",this.escapeLines(b));break;default:return 0}this.line+=Q(b,"\n");return b.length},a.prototype.heredocToken=function(){var a,b,c,d;if(!(c=k.exec(this.chunk)))return 0;b=c[0],d=b.charAt(0),a=this.sanitizeHeredoc(c[2],{quote:d,indent:null}),d==='"'&&0<=a.indexOf("#{")?this.interpolateString(a,{heredoc:!0}):this.token("STRING",this.makeString(a,d,!0)),this.line+=Q(b,"\n");return b.length},a.prototype.commentToken=function(){var a,b,c;if(!(c=this.chunk.match(h)))return 0;a=c[0],b=c[1],b&&(this.token("HERECOMMENT",this.sanitizeHeredoc(b,{herecomment:!0,indent:Array(this.indent+1).join(" ")})),this.token("TERMINATOR","\n")),this.line+=Q(a,"\n");return a.length},a.prototype.jsToken=function(){var a,b;if(this.chunk.charAt(0)!=="`"||!(a=s.exec(this.chunk)))return 0;this.token("JS",(b=a[0]).slice(1,-1));return b.length},a.prototype.regexToken=function(){var a,b,c,d,e,f,g;if(this.chunk.charAt(0)!=="/")return 0;if(c=n.exec(this.chunk)){b=this.heregexToken(c),this.line+=Q(c[0],"\n");return b}d=S(this.tokens);if(d&&(f=d[0],W.call(d.spaced?C:D,f)>=0))return 0;if(!(c=G.exec(this.chunk)))return 0;g=c,c=g[0],e=g[1],a=g[2],e.slice(0,2)==="/*"&&this.error("regular expressions cannot begin with `*`"),e==="//"&&(e="/(?:)/"),this.token("REGEX",""+e+a);return c.length},a.prototype.heregexToken=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n;d=a[0],b=a[1],c=a[2];if(0>b.indexOf("#{")){e=b.replace(o,"").replace(/\//g,"\\/"),e.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(e||"(?:)")+"/"+c);return d.length}this.token("IDENTIFIER","RegExp"),this.tokens.push(["CALL_START","("]),g=[],k=this.interpolateString(b,{regex:!0});for(i=0,j=k.length;i<j;i++){l=k[i],f=l[0],h=l[1];if(f==="TOKENS")g.push.apply(g,h);else{if(!(h=h.replace(o,"")))continue;h=h.replace(/\\/g,"\\\\"),g.push(["STRING",this.makeString(h,'"',!0)])}g.push(["+","+"])}g.pop(),((m=g[0])!=null?m[0]:void 0)!=="STRING"&&this.tokens.push(["STRING",'""'],["+","+"]),(n=this.tokens).push.apply(n,g),c&&this.tokens.push([",",","],["STRING",'"'+c+'"']),this.token(")",")");return d.length},a.prototype.lineToken=function(){var a,b,c,d,e,f;if(!(c=B.exec(this.chunk)))return 0;b=c[0],this.line+=Q(b,"\n"),this.seenFor=!1,e=S(this.tokens,1),f=b.length-1-b.lastIndexOf("\n"),d=this.unfinished();if(f-this.indebt===this.indent){d?this.suppressNewlines():this.newlineToken();return b.length}if(f>this.indent){if(d){this.indebt=f-this.indent,this.suppressNewlines();return b.length}a=f-this.indent+this.outdebt,this.token("INDENT",a),this.indents.push(a),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0}else this.indebt=0,this.outdentToken(this.indent-f,d);this.indent=f;return b.length},a.prototype.outdentToken=function(a,b){var c,d;while(a>0)d=this.indents.length-1,this.indents[d]===void 0?a=0:this.indents[d]===this.outdebt?(a-=this.outdebt,this.outdebt=0):this.indents[d]<this.outdebt?(this.outdebt-=this.indents[d],a-=this.indents[d]):(c=this.indents.pop()-this.outdebt,a-=c,this.outdebt=0,this.pair("OUTDENT"),this.token("OUTDENT",c));c&&(this.outdebt-=a);while(this.value()===";")this.tokens.pop();this.tag()!=="TERMINATOR"&&!b&&this.token("TERMINATOR","\n");return this},a.prototype.whitespaceToken=function(){var a,b,c;if(!(a=O.exec(this.chunk))&&!(b=this.chunk.charAt(0)==="\n"))return 0;c=S(this.tokens),c&&(c[a?"spaced":"newLine"]=!0);return a?a[0].length:0},a.prototype.newlineToken=function(){while(this.value()===";")this.tokens.pop();this.tag()!=="TERMINATOR"&&this.token("TERMINATOR","\n");return this},a.prototype.suppressNewlines=function(){this.value()==="\\"&&this.tokens.pop();return this},a.prototype.literalToken=function(){var a,b,e,f,g,h,k,l;(a=F.exec(this.chunk))?(f=a[0],d.test(f)&&this.tagParameters()):f=this.chunk.charAt(0),e=f,b=S(this.tokens);if(f==="="&&b){!b[1].reserved&&(g=b[1],W.call(t,g)>=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned");if((h=b[1])==="||"||h==="&&"){b[0]="COMPOUND_ASSIGN",b[1]+="=";return f.length}}if(f===";")this.seenFor=!1,e="TERMINATOR";else if(W.call(z,f)>=0)e="MATH";else if(W.call(i,f)>=0)e="COMPARE";else if(W.call(j,f)>=0)e="COMPOUND_ASSIGN";else if(W.call(N,f)>=0)e="UNARY";else if(W.call(K,f)>=0)e="SHIFT";else if(W.call(x,f)>=0||f==="?"&&(b!=null?b.spaced:void 0))e="LOGIC";else if(b&&!b.spaced)if(f==="("&&(k=b[0],W.call(c,k)>=0))b[0]==="?"&&(b[0]="FUNC_EXIST"),e="CALL_START";else if(f==="["&&(l=b[0],W.call(q,l)>=0)){e="INDEX_START";switch(b[0]){case"?":b[0]="INDEX_SOAK"}}switch(f){case"(":case"{":case"[":this.ends.push(r[f]);break;case")":case"}":case"]":this.pair(f)}this.token(e,f);return f.length},a.prototype.sanitizeHeredoc=function(a,b){var c,d,e,f,g;e=b.indent,d=b.herecomment;if(d){l.test(a)&&this.error('block comment cannot contain "*/", starting');if(a.indexOf("\n")<=0)return a}else while(f=m.exec(a)){c=f[1];if(e===null||0<(g=c.length)&&g<e.length)e=c}e&&(a=a.replace(RegExp("\\n"+e,"g"),"\n")),d||(a=a.replace(/^\n/,""));return a},a.prototype.tagParameters=function(){var a,b,c,d;if(this.tag()!==")")return this;b=[],d=this.tokens,a=d.length,d[--a][0]="PARAM_END";while(c=d[--a])switch(c[0]){case")":b.push(c);break;case"(":case"CALL_START":if(b.length)b.pop();else{if(c[0]==="("){c[0]="PARAM_START";return this}return this}}return this},a.prototype.closeIndentation=function(){return this.outdentToken(this.indent)},a.prototype.balancedString=function(a,b){var c,d,e,f,g,h;g=[b];for(c=1,h=a.length;1<=h?c<h:c>h;1<=h?c++:c--){switch(d=a.charAt(c)){case"\\":c++;continue;case b:g.pop();if(!g.length)return a.slice(0,c+1);b=g[g.length-1];continue}b!=="}"||d!=='"'&&d!=="'"?b==="}"&&d==="/"&&(e=n.exec(a.slice(c))||G.exec(a.slice(c)))?c+=e[0].length-1:b==="}"&&d==="{"?g.push(b="}"):b==='"'&&f==="#"&&d==="{"&&g.push(b="}"):g.push(b=d),f=d}return this.error("missing "+g.pop()+", starting")},a.prototype.interpolateString=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t;c==null&&(c={}),e=c.heredoc,m=c.regex,o=[],l=0,f=-1;while(j=b.charAt(f+=1)){if(j==="\\"){f+=1;continue}if(j!=="#"||b.charAt(f+1)!=="{"||!(d=this.balancedString(b.slice(f+1),"}")))continue;l<f&&o.push(["NEOSTRING",b.slice(l,f)]),g=d.slice(1,-1);if(g.length){k=(new a).tokenize(g,{line:this.line,rewrite:!1}),k.pop(),((r=k[0])!=null?r[0]:void 0)==="TERMINATOR"&&k.shift();if(i=k.length)i>1&&(k.unshift(["(","(",this.line]),k.push([")",")",this.line])),o.push(["TOKENS",k])}f+=d.length,l=f+1}f>l&&l<b.length&&o.push(["NEOSTRING",b.slice(l)]);if(m)return o;if(!o.length)return this.token("STRING",'""');o[0][0]!=="NEOSTRING"&&o.unshift(["",""]),(h=o.length>1)&&this.token("(","(");for(f=0,q=o.length;f<q;f++)s=o[f],n=s[0],p=s[1],f&&this.token("+","+"),n==="TOKENS"?(t=this.tokens).push.apply(t,p):this.token("STRING",this.makeString(p,'"',e));h&&this.token(")",")");return o},a.prototype.pair=function(a){var b,c;if(a!==(c=S(this.ends))){"OUTDENT"!==c&&this.error("unmatched "+a),this.indent-=b=S(this.indents),this.outdentToken(b,!0);return this.pair(a)}return this.ends.pop()},a.prototype.token=function(a,b){return this.tokens.push([a,b,this.line])},a.prototype.tag=function(a,b){var c;return(c=S(this.tokens,a))&&(b?c[0]=b:c[0])},a.prototype.value=function(a,b){var c;return(c=S(this.tokens,a))&&(b?c[1]=b:c[1])},a.prototype.unfinished=function(){var a;return w.test(this.chunk)||(a=this.tag())==="\\"||a==="."||a==="?."||a==="UNARY"||a==="MATH"||a==="+"||a==="-"||a==="SHIFT"||a==="RELATION"||a==="COMPARE"||a==="LOGIC"||a==="COMPOUND_ASSIGN"||a==="THROW"||a==="EXTENDS"},a.prototype.escapeLines=function(a,b){return a.replace(A,b?"\\n":"")},a.prototype.makeString=function(a,b,c){if(!a)return b+b;a=a.replace(/\\([\s\S])/g,function(a,c){return c==="\n"||c===b?c:a}),a=a.replace(RegExp(""+b,"g"),"\\$&");return b+this.escapeLines(a,c)+b},a.prototype.error=function(a){throw SyntaxError(""+a+" on line "+(this.line+1))};return a}(),u=["true","false","null","this","new","delete","typeof","in","instanceof","return","throw","break","continue","debugger","if","else","switch","for","while","do","try","catch","finally","class","extends","super"],g=["undefined","then","unless","until","loop","of","by","when"],f={and:"&&",or:"||",is:"==",isnt:"!=",not:"!",yes:"true",no:"false",on:"true",off:"false"},e=function(){var a;a=[];for(R in f)a.push(R);return a}(),g=g.concat(e),I=["case","default","function","var","void","with","const","let","enum","export","import","native","__hasProp","__extends","__slice","__bind","__indexOf"],t=u.concat(I),a.RESERVED=I.concat(u).concat(g),p=/^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/,E=/^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i,k=/^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/,F=/^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/,O=/^[^\n\S]+/,h=/^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/,d=/^[-=]>/,B=/^(?:\n[^\n\S]*)+/,L=/^'[^\\']*(?:\\.[^\\']*)*'/,s=/^`[^\\`]*(?:\\.[^\\`]*)*`/,G=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,n=/^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/,o=/\s+(?:#.*)?/g,A=/\n/g,m=/\n+([^\n\S]*)/g,l=/\*\//,w=/^\s*(?:,|\??\.(?![.\d])|::)/,M=/\s+$/,j=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|="],N=["!","~","NEW","TYPEOF","DELETE","DO"],x=["&&","||","&","|","^"],K=["<<",">>",">>>"],i=["==","!=","<",">","<=",">="],z=["*","/","%"],H=["IN","OF","INSTANCEOF"],b=["TRUE","FALSE","NULL","UNDEFINED"],C=["NUMBER","REGEX","BOOL","++","--","]"],D=C.concat(")","}","THIS","IDENTIFIER","STRING"),c=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER"],q=c.concat("NUMBER","BOOL"),v=["INDENT","OUTDENT","TERMINATOR"]}).call(this)},require["./parser"]=new function(){var a=this,b=function(){var a={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Block:5,TERMINATOR:6,Line:7,Expression:8,Statement:9,Return:10,Comment:11,STATEMENT:12,Value:13,Invocation:14,Code:15,Operation:16,Assign:17,If:18,Try:19,While:20,For:21,Switch:22,Class:23,Throw:24,INDENT:25,OUTDENT:26,Identifier:27,IDENTIFIER:28,AlphaNumeric:29,NUMBER:30,STRING:31,Literal:32,JS:33,REGEX:34,DEBUGGER:35,BOOL:36,Assignable:37,"=":38,AssignObj:39,ObjAssignable:40,":":41,ThisProperty:42,RETURN:43,HERECOMMENT:44,PARAM_START:45,ParamList:46,PARAM_END:47,FuncGlyph:48,"->":49,"=>":50,OptComma:51,",":52,Param:53,ParamVar:54,"...":55,Array:56,Object:57,Splat:58,SimpleAssignable:59,Accessor:60,Parenthetical:61,Range:62,This:63,".":64,"?.":65,"::":66,Index:67,INDEX_START:68,IndexValue:69,INDEX_END:70,INDEX_SOAK:71,Slice:72,"{":73,AssignList:74,"}":75,CLASS:76,EXTENDS:77,OptFuncExist:78,Arguments:79,SUPER:80,FUNC_EXIST:81,CALL_START:82,CALL_END:83,ArgList:84,THIS:85,"@":86,"[":87,"]":88,RangeDots:89,"..":90,Arg:91,SimpleArgs:92,TRY:93,Catch:94,FINALLY:95,CATCH:96,THROW:97,"(":98,")":99,WhileSource:100,WHILE:101,WHEN:102,UNTIL:103,Loop:104,LOOP:105,ForBody:106,FOR:107,ForStart:108,ForSource:109,ForVariables:110,OWN:111,ForValue:112,FORIN:113,FOROF:114,BY:115,SWITCH:116,Whens:117,ELSE:118,When:119,LEADING_WHEN:120,IfBlock:121,IF:122,POST_IF:123,UNARY:124,"-":125,"+":126,"--":127,"++":128,"?":129,MATH:130,SHIFT:131,COMPARE:132,LOGIC:133,RELATION:134,COMPOUND_ASSIGN:135,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"BOOL",38:"=",41:":",43:"RETURN",44:"HERECOMMENT",45:"PARAM_START",47:"PARAM_END",49:"->",50:"=>",52:",",55:"...",64:".",65:"?.",66:"::",68:"INDEX_START",70:"INDEX_END",71:"INDEX_SOAK",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[39,1],[39,3],[39,5],[39,1],[40,1],[40,1],[40,1],[10,2],[10,1],[11,1],[15,5],[15,2],[48,1],[48,1],[51,0],[51,1],[46,0],[46,1],[46,3],[53,1],[53,2],[53,3],[54,1],[54,1],[54,1],[54,1],[58,2],[59,1],[59,2],[59,2],[59,1],[37,1],[37,1],[37,1],[13,1],[13,1],[13,1],[13,1],[13,1],[60,2],[60,2],[60,2],[60,1],[60,1],[67,3],[67,2],[69,1],[69,1],[57,4],[74,0],[74,1],[74,3],[74,4],[74,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[78,0],[78,1],[79,2],[79,4],[63,1],[63,1],[42,2],[56,2],[56,4],[89,1],[89,1],[62,5],[72,3],[72,2],[72,2],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[19,2],[19,3],[19,4],[19,5],[94,3],[24,2],[61,3],[61,5],[100,2],[100,4],[100,2],[100,4],[20,2],[20,2],[20,2],[20,1],[104,2],[104,2],[21,2],[21,2],[21,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[22,5],[22,7],[22,4],[22,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],performAction:function(a,b,c,d,e,f,g){var h=f.length-1;switch(e){case 1:return this.$=new d.Block;case 2:return this.$=f[h];case 3:return this.$=f[h-1];case 4:this.$=d.Block.wrap([f[h]]);break;case 5:this.$=f[h-2].push(f[h]);break;case 6:this.$=f[h-1];break;case 7:this.$=f[h];break;case 8:this.$=f[h];break;case 9:this.$=f[h];break;case 10:this.$=f[h];break;case 11:this.$=new d.Literal(f[h]);break;case 12:this.$=f[h];break;case 13:this.$=f[h];break;case 14:this.$=f[h];break;case 15:this.$=f[h];break;case 16:this.$=f[h];break;case 17:this.$=f[h];break;case 18:this.$=f[h];break;case 19:this.$=f[h];break;case 20:this.$=f[h];break;case 21:this.$=f[h];break;case 22:this.$=f[h];break;case 23:this.$=f[h];break;case 24:this.$=new d.Block;break;case 25:this.$=f[h-1];break;case 26:this.$=new d.Literal(f[h]);break;case 27:this.$=new d.Literal(f[h]);break;case 28:this.$=new d.Literal(f[h]);break;case 29:this.$=f[h];break;case 30:this.$=new d.Literal(f[h]);break;case 31:this.$=new d.Literal(f[h]);break;case 32:this.$=new d.Literal(f[h]);break;case 33:this.$=function(){var a;a=new d.Literal(f[h]),f[h]==="undefined"&&(a.isUndefined=!0);return a}();break;case 34:this.$=new d.Assign(f[h-2],f[h]);break;case 35:this.$=new d.Assign(f[h-3],f[h]);break;case 36:this.$=new d.Assign(f[h-4],f[h-1]);break;case 37:this.$=new d.Value(f[h]);break;case 38:this.$=new d.Assign(new d.Value(f[h-2]),f[h],"object");break;case 39:this.$=new d.Assign(new d.Value(f[h-4]),f[h-1],"object");break;case 40:this.$=f[h];break;case 41:this.$=f[h];break;case 42:this.$=f[h];break;case 43:this.$=f[h];break;case 44:this.$=new d.Return(f[h]);break;case 45:this.$=new d.Return;break;case 46:this.$=new d.Comment(f[h]);break;case 47:this.$=new d.Code(f[h-3],f[h],f[h-1]);break;case 48:this.$=new d.Code([],f[h],f[h-1]);break;case 49:this.$="func";break;case 50:this.$="boundfunc";break;case 51:this.$=f[h];break;case 52:this.$=f[h];break;case 53:this.$=[];break;case 54:this.$=[f[h]];break;case 55:this.$=f[h-2].concat(f[h]);break;case 56:this.$=new d.Param(f[h]);break;case 57:this.$=new d.Param(f[h-1],null,!0);break;case 58:this.$=new d.Param(f[h-2],f[h]);break;case 59:this.$=f[h];break;case 60:this.$=f[h];break;case 61:this.$=f[h];break;case 62:this.$=f[h];break;case 63:this.$=new d.Splat(f[h-1]);break;case 64:this.$=new d.Value(f[h]);break;case 65:this.$=f[h-1].add(f[h]);break;case 66:this.$=new d.Value(f[h-1],[].concat(f[h]));break;case 67:this.$=f[h];break;case 68:this.$=f[h];break;case 69:this.$=new d.Value(f[h]);break;case 70:this.$=new d.Value(f[h]);break;case 71:this.$=f[h];break;case 72:this.$=new d.Value(f[h]);break;case 73:this.$=new d.Value(f[h]);break;case 74:this.$=new d.Value(f[h]);break;case 75:this.$=f[h];break;case 76:this.$=new d.Access(f[h]);break;case 77:this.$=new d.Access(f[h],"soak");break;case 78:this.$=[new d.Access(new d.Literal("prototype")),new d.Access(f[h])];break;case 79:this.$=new d.Access(new d.Literal("prototype"));break;case 80:this.$=f[h];break;case 81:this.$=f[h-1];break;case 82:this.$=d.extend(f[h],{soak:!0});break;case 83:this.$=new d.Index(f[h]);break;case 84:this.$=new d.Slice(f[h]);break;case 85:this.$=new d.Obj(f[h-2],f[h-3].generated);break;case 86:this.$=[];break;case 87:this.$=[f[h]];break;case 88:this.$=f[h-2].concat(f[h]);break;case 89:this.$=f[h-3].concat(f[h]);break;case 90:this.$=f[h-5].concat(f[h-2]);break;case 91:this.$=new d.Class;break;case 92:this.$=new d.Class(null,null,f[h]);break;case 93:this.$=new d.Class(null,f[h]);break;case 94:this.$=new d.Class(null,f[h-1],f[h]);break;case 95:this.$=new d.Class(f[h]);break;case 96:this.$=new d.Class(f[h-1],null,f[h]);break;case 97:this.$=new d.Class(f[h-2],f[h]);break;case 98:this.$=new d.Class(f[h-3],f[h-1],f[h]);break;case 99:this.$=new d.Call(f[h-2],f[h],f[h-1]);break;case 100:this.$=new d.Call(f[h-2],f[h],f[h-1]);break;case 101:this.$=new d.Call("super",[new d.Splat(new d.Literal("arguments"))]);break;case 102:this.$=new d.Call("super",f[h]);break;case 103:this.$=!1;break;case 104:this.$=!0;break;case 105:this.$=[];break;case 106:this.$=f[h-2];break;case 107:this.$=new d.Value(new d.Literal("this"));break;case 108:this.$=new d.Value(new d.Literal("this"));break;case 109:this.$=new d.Value(new d.Literal("this"),[new d.Access(f[h])],"this");break;case 110:this.$=new d.Arr([]);break;case 111:this.$=new d.Arr(f[h-2]);break;case 112:this.$="inclusive";break;case 113:this.$="exclusive";break;case 114:this.$=new d.Range(f[h-3],f[h-1],f[h-2]);break;case 115:this.$=new d.Range(f[h-2],f[h],f[h-1]);break;case 116:this.$=new d.Range(f[h-1],null,f[h]);break;case 117:this.$=new d.Range(null,f[h],f[h-1]);break;case 118:this.$=[f[h]];break;case 119:this.$=f[h-2].concat(f[h]);break;case 120:this.$=f[h-3].concat(f[h]);break;case 121:this.$=f[h-2];break;case 122:this.$=f[h-5].concat(f[h-2]);break;case 123:this.$=f[h];break;case 124:this.$=f[h];break;case 125:this.$=f[h];break;case 126:this.$=[].concat(f[h-2],f[h]);break;case 127:this.$=new d.Try(f[h]);break;case 128:this.$=new d.Try(f[h-1],f[h][0],f[h][1]);break;case 129:this.$=new d.Try(f[h-2],null,null,f[h]);break;case 130:this.$=new d.Try(f[h-3],f[h-2][0],f[h-2][1],f[h]);break;case 131:this.$=[f[h-1],f[h]];break;case 132:this.$=new d.Throw(f[h]);break;case 133:this.$=new d.Parens(f[h-1]);break;case 134:this.$=new d.Parens(f[h-2]);break;case 135:this.$=new d.While(f[h]);break;case 136:this.$=new d.While(f[h-2],{guard:f[h]});break;case 137:this.$=new d.While(f[h],{invert:!0});break;case 138:this.$=new d.While(f[h-2],{invert:!0,guard:f[h]});break;case 139:this.$=f[h-1].addBody(f[h]);break;case 140:this.$=f[h].addBody(d.Block.wrap([f[h-1]]));break;case 141:this.$=f[h].addBody(d.Block.wrap([f[h-1]]));break;case 142:this.$=f[h];break;case 143:this.$=(new d.While(new d.Literal("true"))).addBody(f[h]);break;case 144:this.$=(new d.While(new d.Literal("true"))).addBody(d.Block.wrap([f[h]]));break;case 145:this.$=new d.For(f[h-1],f[h]);break;case 146:this.$=new d.For(f[h-1],f[h]);break;case 147:this.$=new d.For(f[h],f[h-1]);break;case 148:this.$={source:new d.Value(f[h])};break;case 149:this.$=function(){f[h].own=f[h-1].own,f[h].name=f[h-1][0],f[h].index=f[h-1][1];return f[h]}();break;case 150:this.$=f[h];break;case 151:this.$=function(){f[h].own=!0;return f[h]}();break;case 152:this.$=f[h];break;case 153:this.$=new d.Value(f[h]);break;case 154:this.$=new d.Value(f[h]);break;case 155:this.$=[f[h]];break;case 156:this.$=[f[h-2],f[h]];break;case 157:this.$={source:f[h]};break;case 158:this.$={source:f[h],object:!0};break;case 159:this.$={source:f[h-2],guard:f[h]};break;case 160:this.$={source:f[h-2],guard:f[h],object:!0};break;case 161:this.$={source:f[h-2],step:f[h]};break;case 162:this.$={source:f[h-4],guard:f[h-2],step:f[h]};break;case 163:this.$={source:f[h-4],step:f[h-2],guard:f[h]};break;case 164:this.$=new d.Switch(f[h-3],f[h-1]);break;case 165:this.$=new d.Switch(f[h-5],f[h-3],f[h-1]);break;case 166:this.$=new d.Switch(null,f[h-1]);break;case 167:this.$=new d.Switch(null,f[h-3],f[h-1]);break;case 168:this.$=f[h];break;case 169:this.$=f[h-1].concat(f[h]);break;case 170:this.$=[[f[h-1],f[h]]];break;case 171:this.$=[[f[h-2],f[h-1]]];break;case 172:this.$=new d.If(f[h-1],f[h],{type:f[h-2]});break;case 173:this.$=f[h-4].addElse(new d.If(f[h-1],f[h],{type:f[h-2]}));break;case 174:this.$=f[h];break;case 175:this.$=f[h-2].addElse(f[h]);break;case 176:this.$=new d.If(f[h],d.Block.wrap([f[h-2]]),{type:f[h-1],statement:!0});break;case 177:this.$=new d.If(f[h],d.Block.wrap([f[h-2]]),{type:f[h-1],statement:!0});break;case 178:this.$=new d.Op(f[h-1],f[h]);break;case 179:this.$=new d.Op("-",f[h]);break;case 180:this.$=new d.Op("+",f[h]);break;case 181:this.$=new d.Op("--",f[h]);break;case 182:this.$=new d.Op("++",f[h]);break;case 183:this.$=new d.Op("--",f[h-1],null,!0);break;case 184:this.$=new d.Op("++",f[h-1],null,!0);break;case 185:this.$=new d.Existence(f[h-1]);break;case 186:this.$=new d.Op("+",f[h-2],f[h]);break;case 187:this.$=new d.Op("-",f[h-2],f[h]);break;case 188:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 189:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 190:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 191:this.$=new d.Op(f[h-1],f[h-2],f[h]);break;case 192:this.$=function(){return f[h-1].charAt(0)==="!"?(new d.Op(f[h-1].slice(1),f[h-2],f[h])).invert():new d.Op(f[h-1],f[h-2],f[h])}();break;case 193:this.$=new d.Assign(f[h-2],f[h],f[h-1]);break;case 194:this.$=new d.Assign(f[h-4],f[h-1],f[h-3]);break;case 195:this.$=new d.Extends(f[h-2],f[h])}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,72]},{6:[1,73]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:75,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,74],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],47:[2,12],52:[2,12],55:[2,12],60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,12],71:[1,98],75:[2,12],78:90,81:[1,92],82:[2,103],83:[2,12],88:[2,12],90:[2,12],99:[2,12],101:[2,12],102:[2,12],103:[2,12],107:[2,12],115:[2,12],123:[2,12],125:[2,12],126:[2,12],129:[2,12],130:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],47:[2,13],52:[2,13],55:[2,13],60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,13],71:[1,98],75:[2,13],78:99,81:[1,92],82:[2,103],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],47:[2,14],52:[2,14],55:[2,14],70:[2,14],75:[2,14],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],47:[2,15],52:[2,15],55:[2,15],70:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],47:[2,16],52:[2,16],55:[2,16],70:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],47:[2,17],52:[2,17],55:[2,17],70:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],47:[2,18],52:[2,18],55:[2,18],70:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],47:[2,19],52:[2,19],55:[2,19],70:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],47:[2,20],52:[2,20],55:[2,20],70:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],47:[2,21],52:[2,21],55:[2,21],70:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],47:[2,22],52:[2,22],55:[2,22],70:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],47:[2,23],52:[2,23],55:[2,23],70:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],38:[1,101],47:[2,71],52:[2,71],55:[2,71],64:[2,71],65:[2,71],66:[2,71],68:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],47:[2,72],52:[2,72],55:[2,72],64:[2,72],65:[2,72],66:[2,72],68:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],47:[2,73],52:[2,73],55:[2,73],64:[2,73],65:[2,73],66:[2,73],68:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],47:[2,74],52:[2,74],55:[2,74],64:[2,74],65:[2,74],66:[2,74],68:[2,74],70:[2,74],71:[2,74],75:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],47:[2,75],52:[2,75],55:[2,75],64:[2,75],65:[2,75],66:[2,75],68:[2,75],70:[2,75],71:[2,75],75:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],47:[2,101],52:[2,101],55:[2,101],64:[2,101],65:[2,101],66:[2,101],68:[2,101],70:[2,101],71:[2,101],75:[2,101],79:102,81:[2,101],82:[1,103],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{27:107,28:[1,71],42:108,46:104,47:[2,53],52:[2,53],53:105,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:118,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:122,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],38:[2,68],47:[2,68],52:[2,68],55:[2,68],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,68],71:[2,68],75:[2,68],77:[1,126],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],127:[1,123],128:[1,124],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[1,125]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],47:[2,174],52:[2,174],55:[2,174],70:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],118:[1,127],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],47:[2,142],52:[2,142],55:[2,142],70:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{5:130,25:[1,5]},{8:131,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,132],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,91],5:133,6:[2,91],13:119,14:120,25:[1,5],26:[2,91],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,47:[2,91],52:[2,91],55:[2,91],56:47,57:48,59:135,61:25,62:26,63:27,70:[2,91],73:[1,68],75:[2,91],77:[1,134],80:[1,28],83:[2,91],85:[1,56],86:[1,57],87:[1,55],88:[2,91],90:[2,91],98:[1,54],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{8:136,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,45],6:[2,45],8:137,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,45],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,45],100:39,101:[2,45],103:[2,45],104:40,105:[1,65],106:41,107:[2,45],108:67,116:[1,42],121:37,122:[1,62],123:[2,45],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],52:[2,46],75:[2,46],99:[2,46],101:[2,46],103:[2,46],107:[2,46],123:[2,46]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],38:[2,69],47:[2,69],52:[2,69],55:[2,69],64:[2,69],65:[2,69],66:[2,69],68:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],38:[2,70],47:[2,70],52:[2,70],55:[2,70],64:[2,70],65:[2,70],66:[2,70],68:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],47:[2,29],52:[2,29],55:[2,29],64:[2,29],65:[2,29],66:[2,29],68:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],47:[2,30],52:[2,30],55:[2,30],64:[2,30],65:[2,30],66:[2,30],68:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],47:[2,31],52:[2,31],55:[2,31],64:[2,31],65:[2,31],66:[2,31],68:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],47:[2,32],52:[2,32],55:[2,32],64:[2,32],65:[2,32],66:[2,32],68:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],47:[2,33],52:[2,33],55:[2,33],64:[2,33],65:[2,33],66:[2,33],68:[2,33],70:[2,33],71:[2,33],75:[2,33],81:[2,33],82:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],101:[2,33],102:[2,33],103:[2,33],107:[2,33],115:[2,33],123:[2,33],125:[2,33],126:[2,33],129:[2,33],130:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33]},{4:138,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,139],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],47:[2,107],52:[2,107],55:[2,107],64:[2,107],65:[2,107],66:[2,107],68:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],27:146,28:[1,71],47:[2,108],52:[2,108],55:[2,108],64:[2,108],65:[2,108],66:[2,108],68:[2,108],70:[2,108],71:[2,108],75:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108]},{25:[2,49]},{25:[2,50]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],38:[2,64],47:[2,64],52:[2,64],55:[2,64],64:[2,64],65:[2,64],66:[2,64],68:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],38:[2,67],47:[2,67],52:[2,67],55:[2,67],64:[2,67],65:[2,67],66:[2,67],68:[2,67],70:[2,67],71:[2,67],75:[2,67],77:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67],135:[2,67]},{8:147,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,71],56:157,57:158,62:152,73:[1,68],87:[1,55],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,86],11:165,25:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:162,75:[2,86],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],41:[2,27],47:[2,27],52:[2,27],55:[2,27],64:[2,27],65:[2,27],66:[2,27],68:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],41:[2,28],47:[2,28],52:[2,28],55:[2,28],64:[2,28],65:[2,28],66:[2,28],68:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],38:[2,26],41:[2,26],47:[2,26],52:[2,26],55:[2,26],64:[2,26],65:[2,26],66:[2,26],68:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,6],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],47:[2,24],52:[2,24],55:[2,24],70:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,72],26:[1,170]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],47:[2,185],52:[2,185],55:[2,185],70:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],101:[2,185],102:[2,185],103:[2,185],107:[2,185],115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{8:171,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],47:[2,141],52:[2,141],55:[2,141],70:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],47:[2,146],52:[2,146],55:[2,146],70:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{8:179,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],47:[2,140],52:[2,140],55:[2,140],70:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],47:[2,145],52:[2,145],55:[2,145],70:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],101:[2,145],102:[2,145],103:[2,145],107:[2,145],115:[2,145],123:[2,145],125:[2,145],126:[2,145],129:[2,145],130:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145]},{79:180,82:[1,103]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],38:[2,65],47:[2,65],52:[2,65],55:[2,65],64:[2,65],65:[2,65],66:[2,65],68:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{82:[2,104]},{27:181,28:[1,71]},{27:182,28:[1,71]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],27:183,28:[1,71],38:[2,79],47:[2,79],52:[2,79],55:[2,79],64:[2,79],65:[2,79],66:[2,79],68:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],38:[2,80],47:[2,80],52:[2,80],55:[2,80],64:[2,80],65:[2,80],66:[2,80],68:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{8:185,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],55:[1,189],56:47,57:48,59:36,61:25,62:26,63:27,69:184,72:186,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],89:187,90:[1,188],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{67:190,68:[1,97],71:[1,98]},{79:191,82:[1,103]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],38:[2,66],47:[2,66],52:[2,66],55:[2,66],64:[2,66],65:[2,66],66:[2,66],68:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[2,66]},{6:[1,193],8:192,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,194],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],47:[2,102],52:[2,102],55:[2,102],64:[2,102],65:[2,102],66:[2,102],68:[2,102],70:[2,102],71:[2,102],75:[2,102],81:[2,102],82:[2,102],83:[2,102],88:[2,102],90:[2,102],99:[2,102],101:[2,102],102:[2,102],103:[2,102],107:[2,102],115:[2,102],123:[2,102],125:[2,102],126:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{47:[1,198],52:[1,199]},{47:[2,54],52:[2,54]},{38:[1,201],47:[2,56],52:[2,56],55:[1,200]},{38:[2,59],47:[2,59],52:[2,59],55:[2,59]},{38:[2,60],47:[2,60],52:[2,60],55:[2,60]},{38:[2,61],47:[2,61],52:[2,61],55:[2,61]},{38:[2,62],47:[2,62],52:[2,62],55:[2,62]},{27:146,28:[1,71]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],47:[2,48],52:[2,48],55:[2,48],70:[2,48],75:[2,48],83:[2,48],88:[2,48],90:[2,48],99:[2,48],101:[2,48],102:[2,48],103:[2,48],107:[2,48],115:[2,48],123:[2,48],125:[2,48],126:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],133:[2,48],134:[2,48]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],47:[2,178],52:[2,178],55:[2,178],70:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:85,101:[2,178],102:[2,178],103:[2,178],106:86,107:[2,178],108:67,115:[2,178],123:[2,178],125:[2,178],126:[2,178],129:[1,76],130:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178]},{100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],47:[2,179],52:[2,179],55:[2,179],70:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:85,101:[2,179],102:[2,179],103:[2,179],106:86,107:[2,179],108:67,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,76],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],47:[2,180],52:[2,180],55:[2,180],70:[2,180],75:[2,180],83:[2,180],88:[2,180],90:[2,180],99:[2,180],100:85,101:[2,180],102:[2,180],103:[2,180],106:86,107:[2,180],108:67,115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[1,76],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],47:[2,181],52:[2,181],55:[2,181],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,181],71:[2,68],75:[2,181],81:[2,68],82:[2,68],83:[2,181],88:[2,181],90:[2,181],99:[2,181],101:[2,181],102:[2,181],103:[2,181],107:[2,181],115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[2,181],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:90,81:[1,92],82:[2,103]},{60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:99,81:[1,92],82:[2,103]},{64:[2,71],65:[2,71],66:[2,71],68:[2,71],71:[2,71],81:[2,71],82:[2,71]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],47:[2,182],52:[2,182],55:[2,182],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,182],71:[2,68],75:[2,182],81:[2,68],82:[2,68],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],47:[2,183],52:[2,183],55:[2,183],70:[2,183],75:[2,183],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],47:[2,184],52:[2,184],55:[2,184],70:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{8:202,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,203],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,127],6:[2,127],25:[2,127],26:[2,127],47:[2,127],52:[2,127],55:[2,127],70:[2,127],75:[2,127],83:[2,127],88:[2,127],90:[2,127],94:207,95:[1,208],96:[1,209],99:[2,127],101:[2,127],102:[2,127],103:[2,127],107:[2,127],115:[2,127],123:[2,127],125:[2,127],126:[2,127],129:[2,127],130:[2,127],131:[2,127],132:[2,127],133:[2,127],134:[2,127]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],47:[2,139],52:[2,139],55:[2,139],70:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],101:[2,139],102:[2,139],103:[2,139],107:[2,139],115:[2,139],123:[2,139],125:[2,139],126:[2,139],129:[2,139],130:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],47:[2,147],52:[2,147],55:[2,147],70:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{25:[1,210],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{117:211,119:212,120:[1,213]},{1:[2,92],6:[2,92],25:[2,92],26:[2,92],47:[2,92],52:[2,92],55:[2,92],70:[2,92],75:[2,92],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{8:214,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,95],5:215,6:[2,95],25:[1,5],26:[2,95],47:[2,95],52:[2,95],55:[2,95],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,95],71:[2,68],75:[2,95],77:[1,216],81:[2,68],82:[2,68],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],47:[2,132],52:[2,132],55:[2,132],70:[2,132],75:[2,132],83:[2,132],88:[2,132],90:[2,132],99:[2,132],100:85,101:[2,132],102:[2,132],103:[2,132],106:86,107:[2,132],108:67,115:[2,132],123:[2,132],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,44],6:[2,44],26:[2,44],99:[2,44],100:85,101:[2,44],103:[2,44],106:86,107:[2,44],108:67,123:[2,44],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,72],99:[1,217]},{4:218,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,123],25:[2,123],52:[2,123],55:[1,220],88:[2,123],89:219,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],38:[2,110],47:[2,110],52:[2,110],55:[2,110],64:[2,110],65:[2,110],66:[2,110],68:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{6:[2,51],25:[2,51],51:221,52:[1,222],88:[2,51]},{6:[2,118],25:[2,118],26:[2,118],52:[2,118],83:[2,118],88:[2,118]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:223,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,124],25:[2,124],26:[2,124],52:[2,124],83:[2,124],88:[2,124]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],38:[2,109],41:[2,109],47:[2,109],52:[2,109],55:[2,109],64:[2,109],65:[2,109],66:[2,109],68:[2,109],70:[2,109],71:[2,109],75:[2,109],77:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109]},{5:224,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],47:[2,135],52:[2,135],55:[2,135],70:[2,135],75:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],100:85,101:[1,63],102:[1,225],103:[1,64],106:86,107:[1,66],108:67,115:[2,135],123:[2,135],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],47:[2,137],52:[2,137],55:[2,137],70:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:85,101:[1,63],102:[1,226],103:[1,64],106:86,107:[1,66],108:67,115:[2,137],123:[2,137],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],47:[2,143],52:[2,143],55:[2,143],70:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],101:[2,143],102:[2,143],103:[2,143],107:[2,143],115:[2,143],123:[2,143],125:[2,143],126:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],133:[2,143],134:[2,143]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],47:[2,144],52:[2,144],55:[2,144],70:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],100:85,101:[1,63],102:[2,144],103:[1,64],106:86,107:[1,66],108:67,115:[2,144],123:[2,144],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],47:[2,148],52:[2,148],55:[2,148],70:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{113:[2,150],114:[2,150]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],110:227,112:155},{52:[1,228],113:[2,155],114:[2,155]},{52:[2,152],113:[2,152],114:[2,152]},{52:[2,153],113:[2,153],114:[2,153]},{52:[2,154],113:[2,154],114:[2,154]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],47:[2,149],52:[2,149],55:[2,149],70:[2,149],75:[2,149],83:[2,149],88:[2,149],90:[2,149],99:[2,149],101:[2,149],102:[2,149],103:[2,149],107:[2,149],115:[2,149],123:[2,149],125:[2,149],126:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],133:[2,149],134:[2,149]},{8:229,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:230,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],51:231,52:[1,232],75:[2,51]},{6:[2,87],25:[2,87],26:[2,87],52:[2,87],75:[2,87]},{6:[2,37],25:[2,37],26:[2,37],41:[1,233],52:[2,37],75:[2,37]},{6:[2,40],25:[2,40],26:[2,40],52:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],41:[2,41],52:[2,41],75:[2,41]},{6:[2,42],25:[2,42],26:[2,42],41:[2,42],52:[2,42],75:[2,42]},{6:[2,43],25:[2,43],26:[2,43],41:[2,43],52:[2,43],75:[2,43]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],47:[2,25],52:[2,25],55:[2,25],70:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],47:[2,186],52:[2,186],55:[2,186],70:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],100:85,101:[2,186],102:[2,186],103:[2,186],106:86,107:[2,186],108:67,115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[1,76],130:[1,79],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],47:[2,187],52:[2,187],55:[2,187],70:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:85,101:[2,187],102:[2,187],103:[2,187],106:86,107:[2,187],108:67,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,76],130:[1,79],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],47:[2,188],52:[2,188],55:[2,188],70:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:85,101:[2,188],102:[2,188],103:[2,188],106:86,107:[2,188],108:67,115:[2,188],123:[2,188],125:[2,188],126:[2,188],129:[1,76],130:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],47:[2,189],52:[2,189],55:[2,189],70:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:85,101:[2,189],102:[2,189],103:[2,189],106:86,107:[2,189],108:67,115:[2,189],123:[2,189],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[2,189],132:[2,189],133:[2,189],134:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],47:[2,190],52:[2,190],55:[2,190],70:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:85,101:[2,190],102:[2,190],103:[2,190],106:86,107:[2,190],108:67,115:[2,190],123:[2,190],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,190],133:[2,190],134:[1,83]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],47:[2,191],52:[2,191],55:[2,191],70:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:85,101:[2,191],102:[2,191],103:[2,191],106:86,107:[2,191],108:67,115:[2,191],123:[2,191],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[2,191],134:[1,83]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],47:[2,192],52:[2,192],55:[2,192],70:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:85,101:[2,192],102:[2,192],103:[2,192],106:86,107:[2,192],108:67,115:[2,192],123:[2,192],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,192],133:[2,192],134:[2,192]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],47:[2,177],52:[2,177],55:[2,177],70:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:85,101:[1,63],102:[2,177],103:[1,64],106:86,107:[1,66],108:67,115:[2,177],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],47:[2,176],52:[2,176],55:[2,176],70:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],100:85,101:[1,63],102:[2,176],103:[1,64],106:86,107:[1,66],108:67,115:[2,176],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],47:[2,99],52:[2,99],55:[2,99],64:[2,99],65:[2,99],66:[2,99],68:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],38:[2,76],47:[2,76],52:[2,76],55:[2,76],64:[2,76],65:[2,76],66:[2,76],68:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],38:[2,77],47:[2,77],52:[2,77],55:[2,77],64:[2,77],65:[2,77],66:[2,77],68:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],38:[2,78],47:[2,78],52:[2,78],55:[2,78],64:[2,78],65:[2,78],66:[2,78],68:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{70:[1,234]},{55:[1,189],70:[2,83],89:235,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{70:[2,84]},{8:236,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{12:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],36:[2,112],43:[2,112],44:[2,112],45:[2,112],49:[2,112],50:[2,112],70:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{12:[2,113],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],70:[2,113],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],38:[2,82],47:[2,82],52:[2,82],55:[2,82],64:[2,82],65:[2,82],66:[2,82],68:[2,82],70:[2,82],71:[2,82],75:[2,82],77:[2,82],81:[2,82],82:[2,82],83:[2,82],88:[2,82],90:[2,82],99:[2,82],101:[2,82],102:[2,82],103:[2,82],107:[2,82],115:[2,82],123:[2,82],125:[2,82],126:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],47:[2,100],52:[2,100],55:[2,100],64:[2,100],65:[2,100],66:[2,100],68:[2,100],70:[2,100],71:[2,100],75:[2,100],81:[2,100],82:[2,100],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],47:[2,34],52:[2,34],55:[2,34],70:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],100:85,101:[2,34],102:[2,34],103:[2,34],106:86,107:[2,34],108:67,115:[2,34],123:[2,34],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:237,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:238,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],47:[2,105],52:[2,105],55:[2,105],64:[2,105],65:[2,105],66:[2,105],68:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{6:[2,51],25:[2,51],51:239,52:[1,222],83:[2,51]},{6:[2,123],25:[2,123],26:[2,123],52:[2,123],55:[1,240],83:[2,123],88:[2,123],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{48:241,49:[1,58],50:[1,59]},{27:107,28:[1,71],42:108,53:242,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{47:[2,57],52:[2,57]},{8:243,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],47:[2,193],52:[2,193],55:[2,193],70:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],100:85,101:[2,193],102:[2,193],103:[2,193],106:86,107:[2,193],108:67,115:[2,193],123:[2,193],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:244,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],47:[2,195],52:[2,195],55:[2,195],70:[2,195],75:[2,195],83:[2,195],88:[2,195],90:[2,195],99:[2,195],100:85,101:[2,195],102:[2,195],103:[2,195],106:86,107:[2,195],108:67,115:[2,195],123:[2,195],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],47:[2,175],52:[2,175],55:[2,175],70:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],101:[2,175],102:[2,175],103:[2,175],107:[2,175],115:[2,175],123:[2,175],125:[2,175],126:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],133:[2,175],134:[2,175]},{8:245,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],47:[2,128],52:[2,128],55:[2,128],70:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],95:[1,246],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{5:247,25:[1,5]},{27:248,28:[1,71]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,168],118:[2,168],120:[2,168]},{8:254,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],92:253,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,93],5:255,6:[2,93],25:[1,5],26:[2,93],47:[2,93],52:[2,93],55:[2,93],70:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],100:85,101:[1,63],102:[2,93],103:[1,64],106:86,107:[1,66],108:67,115:[2,93],123:[2,93],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],47:[2,96],52:[2,96],55:[2,96],70:[2,96],75:[2,96],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{8:256,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],47:[2,133],52:[2,133],55:[2,133],64:[2,133],65:[2,133],66:[2,133],68:[2,133],70:[2,133],71:[2,133],75:[2,133],81:[2,133],82:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],101:[2,133],102:[2,133],103:[2,133],107:[2,133],115:[2,133],123:[2,133],125:[2,133],126:[2,133],129:[2,133],130:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133]},{6:[1,72],26:[1,257]},{8:258,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,63],12:[2,113],25:[2,63],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],52:[2,63],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,63],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,52],8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,52],26:[2,52],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[2,52],85:[1,56],86:[1,57],87:[1,55],88:[2,52],91:262,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],26:[2,51],51:263,52:[1,222]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],47:[2,172],52:[2,172],55:[2,172],70:[2,172],75:[2,172],83:[2,172],88:[2,172],90:[2,172],99:[2,172],101:[2,172],102:[2,172],103:[2,172],107:[2,172],115:[2,172],118:[2,172],123:[2,172],125:[2,172],126:[2,172],129:[2,172],130:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172]},{8:264,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,151],114:[2,151]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],112:266},{1:[2,157],6:[2,157],25:[2,157],26:[2,157],47:[2,157],52:[2,157],55:[2,157],70:[2,157],75:[2,157],83:[2,157],88:[2,157],90:[2,157],99:[2,157],100:85,101:[2,157],102:[1,267],103:[2,157],106:86,107:[2,157],108:67,115:[1,268],123:[2,157],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],47:[2,158],52:[2,158],55:[2,158],70:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:85,101:[2,158],102:[1,269],103:[2,158],106:86,107:[2,158],108:67,115:[2,158],123:[2,158],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,52],11:165,25:[2,52],26:[2,52],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:273,40:164,42:168,44:[1,46],75:[2,52],86:[1,111]},{8:274,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,275],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],38:[2,81],47:[2,81],52:[2,81],55:[2,81],64:[2,81],65:[2,81],66:[2,81],68:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{8:276,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,116],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,117],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],47:[2,35],52:[2,35],55:[2,35],70:[2,35],75:[2,35],83:[2,35],88:[2,35],90:[2,35],99:[2,35],100:85,101:[2,35],102:[2,35],103:[2,35],106:86,107:[2,35],108:67,115:[2,35],123:[2,35],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,277],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,63],25:[2,63],26:[2,63],52:[2,63],83:[2,63],88:[2,63]},{5:279,25:[1,5]},{47:[2,55],52:[2,55]},{47:[2,58],52:[2,58],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,280],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:281,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:282,25:[1,5]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],47:[2,129],52:[2,129],55:[2,129],70:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],47:[2,166],52:[2,166],55:[2,166],70:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{5:286,25:[1,5]},{26:[2,169],118:[2,169],120:[2,169]},{5:287,25:[1,5],52:[1,288]},{25:[2,125],52:[2,125],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,94],6:[2,94],25:[2,94],26:[2,94],47:[2,94],52:[2,94],55:[2,94],70:[2,94],75:[2,94],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,97],5:289,6:[2,97],25:[1,5],26:[2,97],47:[2,97],52:[2,97],55:[2,97],70:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],100:85,101:[1,63],102:[2,97],103:[1,64],106:86,107:[1,66],108:67,115:[2,97],123:[2,97],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{99:[1,290]},{88:[1,291],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],38:[2,111],47:[2,111],52:[2,111],55:[2,111],64:[2,111],65:[2,111],66:[2,111],68:[2,111],70:[2,111],71:[2,111],75:[2,111],81:[2,111],82:[2,111],83:[2,111],88:[2,111],90:[2,111],99:[2,111],101:[2,111],102:[2,111],103:[2,111],107:[2,111],113:[2,111],114:[2,111],115:[2,111],123:[2,111],125:[2,111],126:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],91:292,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:293,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,119],25:[2,119],26:[2,119],52:[2,119],83:[2,119],88:[2,119]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],47:[2,136],52:[2,136],55:[2,136],70:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:85,101:[1,63],102:[2,136],103:[1,64],106:86,107:[1,66],108:67,115:[2,136],123:[2,136],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],47:[2,138],52:[2,138],55:[2,138],70:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],100:85,101:[1,63],102:[2,138],103:[1,64],106:86,107:[1,66],108:67,115:[2,138],123:[2,138],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{113:[2,156],114:[2,156]},{8:295,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],38:[2,85],47:[2,85],52:[2,85],55:[2,85],64:[2,85],65:[2,85],66:[2,85],68:[2,85],70:[2,85],71:[2,85],75:[2,85],81:[2,85],82:[2,85],83:[2,85],88:[2,85],90:[2,85],99:[2,85],101:[2,85],102:[2,85],103:[2,85],107:[2,85],113:[2,85],114:[2,85],115:[2,85],123:[2,85],125:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85]},{11:165,27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:298,40:164,42:168,44:[1,46],86:[1,111]},{6:[2,86],11:165,25:[2,86],26:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:299,86:[1,111]},{6:[2,88],25:[2,88],26:[2,88],52:[2,88],75:[2,88]},{6:[2,38],25:[2,38],26:[2,38],52:[2,38],75:[2,38],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:300,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,115],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],47:[2,36],52:[2,36],55:[2,36],70:[2,36],75:[2,36],83:[2,36],88:[2,36],90:[2,36],99:[2,36],101:[2,36],102:[2,36],103:[2,36],107:[2,36],115:[2,36],123:[2,36],125:[2,36],126:[2,36],129:[2,36],130:[2,36],131:[2,36],132:[2,36],133:[2,36],134:[2,36]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],47:[2,106],52:[2,106],55:[2,106],64:[2,106],65:[2,106],66:[2,106],68:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],47:[2,47],52:[2,47],55:[2,47],70:[2,47],75:[2,47],83:[2,47],88:[2,47],90:[2,47],99:[2,47],101:[2,47],102:[2,47],103:[2,47],107:[2,47],115:[2,47],123:[2,47],125:[2,47],126:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],133:[2,47],134:[2,47]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],47:[2,194],52:[2,194],55:[2,194],70:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],101:[2,194],102:[2,194],103:[2,194],107:[2,194],115:[2,194],123:[2,194],125:[2,194],126:[2,194],129:[2,194],130:[2,194],131:[2,194],132:[2,194],133:[2,194],134:[2,194]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],47:[2,173],52:[2,173],55:[2,173],70:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[2,173],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],47:[2,130],52:[2,130],55:[2,130],70:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{1:[2,131],6:[2,131],25:[2,131],26:[2,131],47:[2,131],52:[2,131],55:[2,131],70:[2,131],75:[2,131],83:[2,131],88:[2,131],90:[2,131],95:[2,131],99:[2,131],101:[2,131],102:[2,131],103:[2,131],107:[2,131],115:[2,131],123:[2,131],125:[2,131],126:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],133:[2,131],134:[2,131]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],47:[2,164],52:[2,164],55:[2,164],70:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],101:[2,164],102:[2,164],103:[2,164],107:[2,164],115:[2,164],123:[2,164],125:[2,164],126:[2,164],129:[2,164],130:[2,164],131:[2,164],132:[2,164],133:[2,164],134:[2,164]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,170],118:[2,170],120:[2,170]},{8:304,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],47:[2,98],52:[2,98],55:[2,98],70:[2,98],75:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],47:[2,134],52:[2,134],55:[2,134],64:[2,134],65:[2,134],66:[2,134],68:[2,134],70:[2,134],71:[2,134],75:[2,134],81:[2,134],82:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],101:[2,134],102:[2,134],103:[2,134],107:[2,134],115:[2,134],123:[2,134],125:[2,134],126:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],47:[2,114],52:[2,114],55:[2,114],64:[2,114],65:[2,114],66:[2,114],68:[2,114],70:[2,114],71:[2,114],75:[2,114],81:[2,114],82:[2,114],83:[2,114],88:[2,114],90:[2,114],99:[2,114],101:[2,114],102:[2,114],103:[2,114],107:[2,114],115:[2,114],123:[2,114],125:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114]},{6:[2,120],25:[2,120],26:[2,120],52:[2,120],83:[2,120],88:[2,120]},{6:[2,51],25:[2,51],26:[2,51],51:305,52:[1,222]},{6:[2,121],25:[2,121],26:[2,121],52:[2,121],83:[2,121],88:[2,121]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],47:[2,159],52:[2,159],55:[2,159],70:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:85,101:[2,159],102:[2,159],103:[2,159],106:86,107:[2,159],108:67,115:[1,306],123:[2,159],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],47:[2,161],52:[2,161],55:[2,161],70:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:85,101:[2,161],102:[1,307],103:[2,161],106:86,107:[2,161],108:67,115:[2,161],123:[2,161],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],47:[2,160],52:[2,160],55:[2,160],70:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:85,101:[2,160],102:[2,160],103:[2,160],106:86,107:[2,160],108:67,115:[2,160],123:[2,160],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,89],25:[2,89],26:[2,89],52:[2,89],75:[2,89]},{6:[2,51],25:[2,51],26:[2,51],51:308,52:[1,232]},{26:[1,309],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,310]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],47:[2,167],52:[2,167],55:[2,167],70:[2,167],75:[2,167],83:[2,167],88:[2,167],90:[2,167],99:[2,167],101:[2,167],102:[2,167],103:[2,167],107:[2,167],115:[2,167],123:[2,167],125:[2,167],126:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],133:[2,167],134:[2,167]},{26:[2,171],118:[2,171],120:[2,171]},{25:[2,126],52:[2,126],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,39],25:[2,39],26:[2,39],52:[2,39],75:[2,39]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],47:[2,165],52:[2,165],55:[2,165],70:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{6:[2,122],25:[2,122],26:[2,122],52:[2,122],83:[2,122],88:[2,122]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],47:[2,162],52:[2,162],55:[2,162],70:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:85,101:[2,162],102:[2,162],103:[2,162],106:86,107:[2,162],108:67,115:[2,162],123:[2,162],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],47:[2,163],52:[2,163],55:[2,163],70:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],100:85,101:[2,163],102:[2,163],103:[2,163],106:86,107:[2,163],108:67,115:[2,163],123:[2,163],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,90],25:[2,90],26:[2,90],52:[2,90],75:[2,90]}],defaultActions:{58:[2,49],59:[2,50],73:[2,3],92:[2,104],186:[2,84]},parseError:function(a,b){throw new Error(a)},parse:function(a){function o(){var a;a=b.lexer.lex()||1,typeof a!="number"&&(a=b.symbols_[a]||a);return a}function n(a){c.length=c.length-2*a,d.length=d.length-a,e.length=e.length-a}var b=this,c=[0],d=[null],e=[],f=this.table,g="",h=0,i=0,j=0,k=2,l=1;this.lexer.setInput(a),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var m=this.lexer.yylloc;e.push(m),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var p,q,r,s,t,u,v={},w,x,y,z;for(;;){r=c[c.length-1],this.defaultActions[r]?s=this.defaultActions[r]:(p==null&&(p=o()),s=f[r]&&f[r][p]);if(typeof s=="undefined"||!s.length||!s[0]){if(!j){z=[];for(w in f[r])this.terminals_[w]&&w>2&&z.push("'"+this.terminals_[w]+"'");var A="";this.lexer.showPosition?A="Parse error on line "+(h+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+z.join(", "):A="Parse error on line "+(h+1)+": Unexpected "+(p==1?"end of input":"'"+(this.terminals_[p]||p)+"'"),this.parseError(A,{text:this.lexer.match,token:this.terminals_[p]||p,line:this.lexer.yylineno,loc:m,expected:z})}if(j==3){if(p==l)throw new Error(A||"Parsing halted.");i=this.lexer.yyleng,g=this.lexer.yytext,h=this.lexer.yylineno,m=this.lexer.yylloc,p=o()}for(;;){if(k.toString()in f[r])break;if(r==0)throw new Error(A||"Parsing halted.");n(1),r=c[c.length-1]}q=p,p=k,r=c[c.length-1],s=f[r]&&f[r][k],j=3}if(s[0]instanceof Array&&s.length>1)throw new Error("Parse Error: multiple actions possible at state: "+r+", token: "+p);switch(s[0]){case 1:c.push(p),d.push(this.lexer.yytext),e.push(this.lexer.yylloc),c.push(s[1]),p=null,q?(p=q,q=null):(i=this.lexer.yyleng,g=this.lexer.yytext,h=this.lexer.yylineno,m=this.lexer.yylloc,j>0&&j--);break;case 2:x=this.productions_[s[1]][1],v.$=d[d.length-x],v._$={first_line:e[e.length-(x||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(x||1)].first_column,last_column:e[e.length-1].last_column},u=this.performAction.call(v,g,i,h,this.yy,s[1],d,e);if(typeof u!="undefined")return u;x&&(c=c.slice(0,-1*x*2),d=d.slice(0,-1*x),e=e.slice(0,-1*x)),c.push(this.productions_[s[1]][0]),d.push(v.$),e.push(v._$),y=f[c[c.length-2]][c[c.length-1]],c.push(y);break;case 3:return!0}}return!0}};return a}();typeof require!="undefined"&&typeof a!="undefined"&&(a.parser=b,a.parse=function(){return b.parse.apply(b,arguments)},a.main=function(b){if(!b[1])throw new Error("Usage: "+b[0]+" FILE");if(typeof process!="undefined")var c=require("fs").readFileSync(require("path").join(process.cwd(),b[1]),"utf8");else var d=require("file").path(require("file").cwd()),c=d.join(b[1]).read({charset:"utf-8"});return a.parser.parse(c)},typeof module!="undefined"&&require.main===module&&a.main(typeof process!="undefined"?process.argv.slice(1):require("system").args))},require["./scope"]=new function(){var a=this;(function(){var b,c,d,e;e=require("./helpers"),c=e.extend,d=e.last,a.Scope=b=function(){function a(b,c,d){this.parent=b,this.expressions=c,this.method=d,this.variables=[{name:"arguments",type:"arguments"}],this.positions={},this.parent||(a.root=this)}a.root=null,a.prototype.add=function(a,b,c){if(this.shared&&!c)return this.parent.add(a,b,c);return Object.prototype.hasOwnProperty.call(this.positions,a)?this.variables[this.positions[a]].type=b:this.positions[a]=this.variables.push({name:a,type:b})-1},a.prototype.find=function(a,b){if(this.check(a,b))return!0;this.add(a,"var");return!1},a.prototype.parameter=function(a){if(!this.shared||!this.parent.check(a,!0))return this.add(a,"param")},a.prototype.check=function(a,b){var c,d;c=!!this.type(a);if(c||b)return c;return(d=this.parent)!=null?!!d.check(a):!!void 0},a.prototype.temporary=function(a,b){return a.length>1?"_"+a+(b>1?b:""):"_"+(b+parseInt(a,36)).toString(36).replace(/\d/g,"a")},a.prototype.type=function(a){var b,c,d,e;e=this.variables;for(c=0,d=e.length;c<d;c++){b=e[c];if(b.name===a)return b.type}return null},a.prototype.freeVariable=function(a,b){var c,d;b==null&&(b=!0),c=0;while(this.check(d=this.temporary(a,c)))c++;b&&this.add(d,"var",!0);return d},a.prototype.assign=function(a,b){this.add(a,{value:b,assigned:!0},!0);return this.hasAssignments=!0},a.prototype.hasDeclarations=function(){return!!this.declaredVariables().length},a.prototype.declaredVariables=function(){var a,b,c,d,e,f;a=[],b=[],f=this.variables;for(d=0,e=f.length;d<e;d++)c=f[d],c.type==="var"&&(c.name.charAt(0)==="_"?b:a).push(c.name);return a.sort().concat(b.sort())},a.prototype.assignedVariables=function(){var a,b,c,d,e;d=this.variables,e=[];for(b=0,c=d.length;b<c;b++)a=d[b],a.type.assigned&&e.push(""+a.name+" = "+a.type.value);return e};return a}()}).call(this)},require["./nodes"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,ba,bb,bc,bd,be,bf,bg,bh,bi=Object.prototype.hasOwnProperty,bj=function(a,b){function d(){this.constructor=a}for(var c in b)bi.call(b,c)&&(a[c]=b[c]);d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype;return a},bk=Array.prototype.indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(b in this&&this[b]===a)return b;return-1};M=require("./scope").Scope,I=require("./lexer").RESERVED,bh=require("./helpers"),Y=bh.compact,ba=bh.flatten,_=bh.extend,bc=bh.merge,Z=bh.del,be=bh.starts,$=bh.ends,bb=bh.last,a.extend=_,X=function(){return!0},D=function(){return!1},R=function(){return this},C=function(){this.negated=!this.negated;return this},a.Base=e=function(){function a(){}a.prototype.compile=function(a,b){var c;a=_({},a),b&&(a.level=b),c=this.unfoldSoak(a)||this,c.tab=a.indent;return a.level===z||!c.isStatement(a)?c.compileNode(a):c.compileClosure(a)},a.prototype.compileClosure=function(a){if(this.jumps())throw SyntaxError("cannot use a pure statement in an expression.");a.sharedScope=!0;return i.wrap(this).compileNode(a)},a.prototype.cache=function(a,b,c){var e,f;if(!this.isComplex()){e=b?this.compile(a,b):this;return[e,e]}e=new A(c||a.scope.freeVariable("ref")),f=new d(e,this);return b?[f.compile(a,b),e.value]:[f,e]},a.prototype.compileLoopReference=function(a,b){var c,d;c=d=this.compile(a,w),-Infinity<+c&&+c<Infinity||o.test(c)&&a.scope.check(c,!0)||(c=""+(d=a.scope.freeVariable(b))+" = "+c);return[c,d]},a.prototype.makeReturn=function(a){var b;b=this.unwrapAll();return a?new g(new A(""+a+".push"),[b]):new K(b)},a.prototype.contains=function(a){var b;b=!1,this.traverseChildren(!1,function(c){if(a(c)){b=!0;return!1}});return b},a.prototype.containsType=function(a){return this instanceof a||this.contains(function(b){return b instanceof a})},a.prototype.lastNonComment=function(a){var b;b=a.length;while(b--)if(!(a[b]instanceof k))return a[b];return null},a.prototype.toString=function(a,b){var c;a==null&&(a=""),b==null&&(b=this.constructor.name),c="\n"+a+b,this.soak&&(c+="?"),this.eachChild(function(b){return c+=b.toString(a+Q)});return c},a.prototype.eachChild=function(a){var b,c,d,e,f,g,h,i;if(!this.children)return this;h=this.children;for(d=0,f=h.length;d<f;d++){b=h[d];if(this[b]){i=ba([this[b]]);for(e=0,g=i.length;e<g;e++){c=i[e];if(a(c)===!1)return this}}}return this},a.prototype.traverseChildren=function(a,b){return this.eachChild(function(c){if(b(c)===!1)return!1;return c.traverseChildren(a,b)})},a.prototype.invert=function(){return new F("!",this)},a.prototype.unwrapAll=function(){var a;a=this;while(a!==(a=a.unwrap()))continue;return a},a.prototype.children=[],a.prototype.isStatement=D,a.prototype.jumps=D,a.prototype.isComplex=X,a.prototype.isChainable=D,a.prototype.isAssignable=D,a.prototype.unwrap=R,a.prototype.unfoldSoak=D,a.prototype.assigns=D;return a}(),a.Block=f=function(a){function b(a){this.expressions=Y(ba(a||[]))}bj(b,a),b.prototype.children=["expressions"],b.prototype.push=function(a){this.expressions.push(a);return this},b.prototype.pop=function(){return this.expressions.pop()},b.prototype.unshift=function(a){this.expressions.unshift(a);return this},b.prototype.unwrap=function(){return this.expressions.length===1?this.expressions[0]:this},b.prototype.isEmpty=function(){return!this.expressions.length},b.prototype.isStatement=function(a){var b,c,d,e;e=this.expressions;for(c=0,d=e.length;c<d;c++){b=e[c];if(b.isStatement(a))return!0}return!1},b.prototype.jumps=function(a){var b,c,d,e;e=this.expressions;for(c=0,d=e.length;c<d;c++){b=e[c];if(b.jumps(a))return b}},b.prototype.makeReturn=function(a){var b,c;c=this.expressions.length;while(c--){b=this.expressions[c];if(!(b instanceof k)){this.expressions[c]=b.makeReturn(a),b instanceof K&&!b.expression&&this.expressions.splice(c,1);break}}return this},b.prototype.compile=function(a,c){a==null&&(a={});return a.scope?b.__super__.compile.call(this,a,c):this.compileRoot(a)},b.prototype.compileNode=function(a){var c,d,e,f,g,h,i;this.tab=a.indent,f=a.level===z,d=[],i=this.expressions;for(g=0,h=i.length;g<h;g++)e=i[g],e=e.unwrapAll(),e=e.unfoldSoak(a)||e,e instanceof b?d.push(e.compileNode(a)):f?(e.front=!0,c=e.compile(a),d.push(e.isStatement(a)?c:""+this.tab+c+";")):d.push(e.compile(a,w));if(f)return this.spaced?"\n"+d.join("\n\n")+"\n":d.join("\n");c=d.join(", ")||"void 0";return d.length>1&&a.level>=w?"("+c+")":c},b.prototype.compileRoot=function(a){var b,c,d,e,f,g;a.indent=a.bare?"":Q,a.scope=new M(null,this,null),a.level=z,this.spaced=!0,e="",a.bare||(f=function(){var a,b,e;b=this.expressions,e=[];for(d=0,a=b.length;d<a;d++){c=b[d];if(!(c.unwrap()instanceof k))break;e.push(c)}return e}.call(this),g=this.expressions.slice(f.length),this.expressions=f,f.length&&(e=""+this.compileNode(bc(a,{indent:""}))+"\n"),this.expressions=g),b=this.compileWithDeclarations(a);if(a.bare)return b;return""+e+"(function() {\n"+b+"\n}).call(this);\n"},b.prototype.compileWithDeclarations=function(a){var b,c,d,e,f,g,h,i,j,l,m,n,o;c=g="",m=this.expressions;for(f=0,l=m.length;f<l;f++){e=m[f],e=e.unwrap();if(!(e instanceof k||e instanceof A))break}a=bc(a,{level:z}),f&&(h=this.expressions.splice(f,9e9),n=[this.spaced,!1],j=n[0],this.spaced=n[1],o=[this.compileNode(a),j],c=o[0],this.spaced=o[1],this.expressions=h),g=this.compileNode(a),i=a.scope;if(i.expressions===this){d=a.scope.hasDeclarations(),b=i.hasAssignments;if(d||b)f&&(c+="\n"),c+=""+this.tab+"var ",d&&(c+=i.declaredVariables().join(", ")),b&&(d&&(c+=",\n"+(this.tab+Q)),c+=i.assignedVariables().join(",\n"+(this.tab+Q))),c+=";\n"}return c+g},b.wrap=function(a){if(a.length===1&&a[0]instanceof b)return a[0];return new b(a)};return b}(e),a.Literal=A=function(a){function b(a){this.value=a}bj(b,a),b.prototype.makeReturn=function(){return this.isStatement()?this:b.__super__.makeReturn.apply(this,arguments)},b.prototype.isAssignable=function(){return o.test(this.value)},b.prototype.isStatement=function(){var a;return(a=this.value)==="break"||a==="continue"||a==="debugger"},b.prototype.isComplex=D,b.prototype.assigns=function(a){return a===this.value},b.prototype.jumps=function(a){if(this.value==="break"&&!((a!=null?a.loop:void 0)||(a!=null?a.block:void 0)))return this;if(this.value==="continue"&&(a!=null?!a.loop:!void 0))return this},b.prototype.compileNode=function(a){var b,c,d;b=this.isUndefined?a.level>=u?"(void 0)":"void 0":this.value==="this"?((c=a.scope.method)!=null?c.bound:void 0)?a.scope.method.context:this.value:this.value.reserved&&(d=""+this.value)!=="eval"&&d!=="arguments"?'"'+this.value+'"':this.value;return this.isStatement()?""+this.tab+b+";":b},b.prototype.toString=function(){return' "'+this.value+'"'};return b}(e),a.Return=K=function(a){function b(a){a&&!a.unwrap().isUndefined&&(this.expression=a)}bj(b,a),b.prototype.children=["expression"],b.prototype.isStatement=X,b.prototype.makeReturn=R,b.prototype.jumps=R,b.prototype.compile=function(a,c){var d,e;d=(e=this.expression)!=null?e.makeReturn():void 0;return!d||d instanceof b?b.__super__.compile.call(this,a,c):d.compile(a,c)},b.prototype.compileNode=function(a){return this.tab+("return"+[this.expression?" "+this.expression.compile(a,y):void 0]+";")};return b}(e),a.Value=V=function(a){function b(a,c,d){if(!c&&a instanceof b)return a;this.base=a,this.properties=c||[],d&&(this[d]=!0);return this}bj(b,a),b.prototype.children=["base","properties"],b.prototype.add=function(a){this.properties=this.properties.concat(a);return this},b.prototype.hasProperties=function(){return!!this.properties.length},b.prototype.isArray=function(){return!this.properties.length&&this.base instanceof c},b.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},b.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},b.prototype.isSimpleNumber=function(){return this.base instanceof A&&L.test(this.base.value)},b.prototype.isAtomic=function(){var a,b,c,d;d=this.properties.concat(this.base);for(b=0,c=d.length;b<c;b++){a=d[b];if(a.soak||a instanceof g)return!1}return!0},b.prototype.isStatement=function(a){return!this.properties.length&&this.base.isStatement(a)},b.prototype.assigns=function(a){return!this.properties.length&&this.base.assigns(a)},b.prototype.jumps=function(a){return!this.properties.length&&this.base.jumps(a)},b.prototype.isObject=function(a){if(this.properties.length)return!1;return this.base instanceof E&&(!a||this.base.generated)},b.prototype.isSplice=function(){return bb(this.properties)instanceof N},b.prototype.unwrap=function(){return this.properties.length?this:this.base},b.prototype.cacheReference=function(a){var c,e,f,g;f=bb(this.properties);if(this.properties.length<2&&!this.base.isComplex()&&(f!=null?!f.isComplex():!void 0))return[this,this];c=new b(this.base,this.properties.slice(0,-1)),c.isComplex()&&(e=new A(a.scope.freeVariable("base")),c=new b(new H(new d(e,c))));if(!f)return[c,e];f.isComplex()&&(g=new A(a.scope.freeVariable("name")),f=new t(new d(g,f.index)),g=new t(g));return[c.add(f),new b(e||c.base,[g||f])]},b.prototype.compileNode=function(a){var b,c,d,e,f;this.base.front=this.front,d=this.properties,b=this.base.compile(a,d.length?u:null),(this.base instanceof H||d.length)&&L.test(b)&&(b=""+b+".");for(e=0,f=d.length;e<f;e++)c=d[e],b+=c.compile(a);return b},b.prototype.unfoldSoak=function(a){var c,e=this;if(this.unfoldedSoak!=null)return this.unfoldedSoak;c=function(){var c,f,g,h,i,j,k,m;if(g=e.base.unfoldSoak(a)){Array.prototype.push.apply(g.body.properties,e.properties);return g}m=e.properties;for(f=0,k=m.length;f<k;f++){h=m[f];if(!h.soak)continue;h.soak=!1,c=new b(e.base,e.properties.slice(0,f)),j=new b(e.base,e.properties.slice(f)),c.isComplex()&&(i=new A(a.scope.freeVariable("ref")),c=new H(new d(i,c)),j.base=i);return new r(new l(c),j,{soak:!0})}return null}();return this.unfoldedSoak=c||!1};return b}(e),a.Comment=k=function(a){function b(a){this.comment=a}bj(b,a),b.prototype.isStatement=X,b.prototype.makeReturn=R,b.prototype.compileNode=function(a,b){var c;c="/*"+bd(this.comment,this.tab)+("\n"+this.tab+"*/"),(b||a.level)===z&&(c=a.indent+c);return c};return b}(e),a.Call=g=function(a){function c(a,b,c){this.args=b!=null?b:[],this.soak=c,this.isNew=!1,this.isSuper=a==="super",this.variable=this.isSuper?null:a}bj(c,a),c.prototype.children=["variable","args"],c.prototype.newInstance=function(){var a,b;a=((b=this.variable)!=null?b.base:void 0)||this.variable,a instanceof c&&!a.isNew?a.newInstance():this.isNew=!0;return this},c.prototype.superReference=function(a){var c,d,e;d=a.scope.method;if(!d)throw SyntaxError("cannot call super outside of a function.");e=d.name;if(e==null)throw SyntaxError("cannot call super on an anonymous function.");if(d.klass){c=[new b(new A("__super__"))],d.static&&c.push(new b(new A("constructor"))),c.push(new b(new A(e)));return(new V(new A(d.klass),c)).compile(a)}return""+e+".__super__.constructor"},c.prototype.unfoldSoak=function(a){var b,d,e,f,g,h,i,j,k;if(this.soak){if(this.variable){if(d=bf(a,this,"variable"))return d;j=(new V(this.variable)).cacheReference(a),e=j[0],g=j[1]}else e=new A(this.superReference(a)),g=new V(e);g=new c(g,this.args),g.isNew=this.isNew,e=new A("typeof "+e.compile(a)+' === "function"');return new r(e,new V(g),{soak:!0})}b=this,f=[];for(;;){if(b.variable instanceof c){f.push(b),b=b.variable;continue}if(!(b.variable instanceof V))break;f.push(b);if(!((b=b.variable.base)instanceof c))break}k=f.reverse();for(h=0,i=k.length;h<i;h++)b=k[h],d&&(b.variable instanceof c?b.variable=d:b.variable.base=d),d=bf(a,b,"variable");return d},c.prototype.filterImplicitObjects=function(a){var b,c,e,f,g,h,i,j,l,m;c=[];for(h=0,j=a.length;h<j;h++){b=a[h];if(!((typeof b.isObject=="function"?b.isObject():void 0)&&b.base.generated)){c.push(b);continue}e=null,m=b.base.properties;for(i=0,l=m.length;i<l;i++)f=m[i],f instanceof d||f instanceof k?(e||c.push(e=new E(g=[],!0)),g.push(f)):(c.push(f),e=null)}return c},c.prototype.compileNode=function(a){var b,c,d,e;(e=this.variable)!=null&&(e.front=this.front);if(d=O.compileSplattedArray(a,this.args,!0))return this.compileSplat(a,d);c=this.filterImplicitObjects(this.args),c=function(){var d,e,f;f=[];for(d=0,e=c.length;d<e;d++)b=c[d],f.push(b.compile(a,w));return f}().join(", ");return this.isSuper?this.superReference(a)+(".call(this"+(c&&", "+c)+")"):(this.isNew?"new ":"")+this.variable.compile(a,u)+("("+c+")")},c.prototype.compileSuper=function(a,b){return""+this.superReference(b)+".call(this"+(a.length?", ":"")+a+")"},c.prototype.compileSplat=function(a,b){var c,d,e,f,g;if(this.isSuper)return""+this.superReference(a)+".apply(this, "+b+")";if(this.isNew){e=this.tab+Q;return"(function(func, args, ctor) {\n"+e+"ctor.prototype = func.prototype;\n"+e+"var child = new ctor, result = func.apply(child, args);\n"+e+'return typeof result === "object" ? result : child;\n'+this.tab+"})("+this.variable.compile(a,w)+", "+b+", function() {})"}c=new V(this.variable),(f=c.properties.pop())&&c.isComplex()?(g=a.scope.freeVariable("ref"),d="("+g+" = "+c.compile(a,w)+")"+f.compile(a)):(d=c.compile(a,u),L.test(d)&&(d="("+d+")"),f?(g=d,d+=f.compile(a)):g="null");return""+d+".apply("+g+", "+b+")"};return c}(e),a.Extends=m=function(a){function b(a,b){this.child=a,this.parent=b}bj(b,a),b.prototype.children=["child","parent"],b.prototype.compile=function(a){return(new g(new V(new A(bg("extends"))),[this.child,this.parent])).compile(a)};return b}(e),a.Access=b=function(a){function b(a,b){this.name=a,this.name.asKey=!0,this.soak=b==="soak"}bj(b,a),b.prototype.children=["name"],b.prototype.compile=function(a){var b;b=this.name.compile(a);return o.test(b)?"."+b:"["+b+"]"},b.prototype.isComplex=D;return b}(e),a.Index=t=function(a){function b(a){this.index=a}bj(b,a),b.prototype.children=["index"],b.prototype.compile=function(a){return"["+this.index.compile(a,y)+"]"},b.prototype.isComplex=function(){return this.index.isComplex()};return b}(e),a.Range=J=function(a){function b(a,b,c){this.from=a,this.to=b,this.exclusive=c==="exclusive",this.equals=this.exclusive?"":"="}bj(b,a),b.prototype.children=["from","to"],b.prototype.compileVariables=function(a){var b,c,d,e,f;a=bc(a,{top:!0}),c=this.from.cache(a,w),this.fromC=c[0],this.fromVar=c[1],d=this.to.cache(a,w),this.toC=d[0],this.toVar=d[1];if(b=Z(a,"step"))e=b.cache(a,w),this.step=e[0],this.stepVar=e[1];f=[this.fromVar.match(L),this.toVar.match(L)],this.fromNum=f[0],this.toNum=f[1];if(this.stepVar)return this.stepNum=this.stepVar.match(L)},b.prototype.compileNode=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;this.fromVar||this.compileVariables(a);if(!a.index)return this.compileArray(a);g=this.fromNum&&this.toNum,f=Z(a,"index"),k=""+f+" = "+this.fromC,this.toC!==this.toVar&&(k+=", "+this.toC),this.step!==this.stepVar&&(k+=", "+this.step),l=[""+f+" <"+this.equals,""+f+" >"+this.equals],h=l[0],e=l[1],c=this.stepNum?+this.stepNum>0?""+h+" "+this.toVar:""+e+" "+this.toVar:g?(m=[+this.fromNum,+this.toNum],d=m[0],j=m[1],m,d<=j?""+h+" "+j:""+e+" "+j):(b=""+this.fromVar+" <= "+this.toVar,""+b+" ? "+h+" "+this.toVar+" : "+e+" "+this.toVar),i=this.stepVar?""+f+" += "+this.stepVar:g?d<=j?""+f+"++":""+f+"--":""+b+" ? "+f+"++ : "+f+"--";return""+k+"; "+c+"; "+i},b.prototype.compileArray=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p;if(this.fromNum&&this.toNum&&Math.abs(this.fromNum-this.toNum)<=20){j=function(){p=[];for(var a=n=+this.fromNum,b=+this.toNum;n<=b?a<=b:a>=b;n<=b?a++:a--)p.push(a);return p}.apply(this),this.exclusive&&j.pop();return"["+j.join(", ")+"]"}g=this.tab+Q,f=a.scope.freeVariable("i"),k=a.scope.freeVariable("results"),i="\n"+g+k+" = [];",this.fromNum&&this.toNum?(a.index=f,c=this.compileNode(a)):(l=""+f+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),d=""+this.fromVar+" <= "+this.toVar,c="var "+l+"; "+d+" ? "+f+" <"+this.equals+" "+this.toVar+" : "+f+" >"+this.equals+" "+this.toVar+"; "+d+" ? "+f+"++ : "+f+"--"),h="{ "+k+".push("+f+"); }\n"+g+"return "+k+";\n"+a.indent,e=function(a){return a!=null?a.contains(function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey}):void 0};if(e(this.from)||e(this.to))b=", arguments";return"(function() {"+i+"\n"+g+"for ("+c+")"+h+"}).apply(this"+(b!=null?b:"")+")"};return b}(e),a.Slice=N=function(a){function b(a){this.range=a,b.__super__.constructor.call(this)}bj(b,a),b.prototype.children=["range"],b.prototype.compileNode=function(a){var b,c,d,e,f,g;g=this.range,e=g.to,c=g.from,d=c&&c.compile(a,y)||"0",b=e&&e.compile(a,u),e&&(!!this.range.exclusive||+b!==-1)&&(f=", "+(this.range.exclusive?b:L.test(b)?(+b+1).toString():""+b+" + 1 || 9e9"));return".slice("+d+(f||"")+")"};return b}(e),a.Obj=E=function(a){function b(a,b){this.generated=b!=null?b:!1,this.objects=this.properties=a||[]}bj(b,a),b.prototype.children=["properties"],b.prototype.compileNode=function(a){var b,c,e,f,g,h,i,j,l,m,n;l=this.properties;if(!l.length)return this.front?"({})":"{}";if(this.generated)for(m=0,n=l.length;m<n;m++){h=l[m];if(h instanceof V)throw new Error("cannot have an implicit value in an implicit object")}c=a.indent+=Q,g=this.lastNonComment(this.properties),l=function(){var h,i;i=[];for(b=0,h=l.length;b<h;b++)j=l[b],f=b===l.length-1?"":j===g||j instanceof k?"\n":",\n",e=j instanceof k?"":c,j instanceof V&&j["this"]&&(j=new d(j.properties[0].name,j,"object")),j instanceof k||(j instanceof d||(j=new d(j,j,"object")),(j.variable.base||j.variable).asKey=!0),i.push(e+j.compile(a,z)+f);return i}(),l=l.join(""),i="{"+(l&&"\n"+l+"\n"+this.tab)+"}";return this.front?"("+i+")":i},b.prototype.assigns=function(a){var b,c,d,e;e=this.properties;for(c=0,d=e.length;c<d;c++){b=e[c];if(b.assigns(a))return!0}return!1};return b}(e),a.Arr=c=function(a){function b(a){this.objects=a||[]}bj(b,a),b.prototype.children=["objects"],b.prototype.filterImplicitObjects=g.prototype.filterImplicitObjects,b.prototype.compileNode=function(a){var b,c,d;if(!this.objects.length)return"[]";a.indent+=Q,d=this.filterImplicitObjects(this.objects);if(b=O.compileSplattedArray(a,d))return b;b=function(){var b,e,f;f=[];for(b=0,e=d.length;b<e;b++)c=d[b],f.push(c.compile(a,w));return f}().join(", ");return b.indexOf("\n")>=0?"[\n"+a.indent+b+"\n"+this.tab+"]":"["+b+"]"},b.prototype.assigns=function(a){var b,c,d,e;e=this.objects;for(c=0,d=e.length;c<d;c++){b=e[c];if(b.assigns(a))return!0}return!1};return b}(e),a.Class=h=function(a){function c(a,b,c){this.variable=a,this.parent=b,this.body=c!=null?c:new f,this.boundFuncs=[],this.body.classBody=!0}bj(c,a),c.prototype.children=["variable","parent","body"],c.prototype.determineName=function(){var a,c;if(!this.variable)return null;a=(c=bb(this.variable.properties))?c instanceof b&&c.name.value:this.variable.base.value;return a&&(a=o.test(a)&&a)},c.prototype.setContext=function(a){return this.body.traverseChildren(!1,function(b){if(b.classBody)return!1;if(b instanceof A&&b.value==="this")return b.value=a;if(b instanceof j){b.klass=a;if(b.bound)return b.context=a}})},c.prototype.addBoundFunctions=function(a){var c,d,e,f,g,h;if(this.boundFuncs.length){g=this.boundFuncs,h=[];for(e=0,f=g.length;e<f;e++)c=g[e],d=(new V(new A("this"),[new b(c)])).compile(a),h.push(this.ctor.body.unshift(new A(""+d+" = "+bg("bind")+"("+d+", this)")));return h}},c.prototype.addProperties=function(a,c,e){var f,g,h,i,k;k=a.base.properties.slice(0),h=function(){var a;a=[];while(f=k.shift()){if(f instanceof d){g=f.variable.base,delete f.context,i=f.value;if(g.value==="constructor"){if(this.ctor)throw new Error("cannot define more than one constructor in a class");if(i.bound)throw new Error("cannot define a constructor as a bound function");i instanceof j?f=this.ctor=i:(this.externalCtor=e.scope.freeVariable("class"),f=new d(new A(this.externalCtor),i))}else f.variable["this"]?(i.static=!0,i.bound&&(i.context=c)):(f.variable=new V(new A(c),[new b(new A("prototype")),new b(g)]),i instanceof j&&i.bound&&(this.boundFuncs.push(g),i.bound=!1))}a.push(f)}return a}.call(this);return Y(h)},c.prototype.walkBody=function(a,b){var d=this;return this.traverseChildren(!1,function(e){var g,h,i,j,k;if(e instanceof c)return!1;if(e instanceof f){k=g=e.expressions;for(h=0,j=k.length;h<j;h++)i=k[h],i instanceof V&&i.isObject(!0)&&(g[h]=d.addProperties(i,a,b));return e.expressions=g=ba(g)}})},c.prototype.ensureConstructor=function(a){this.ctor||(this.ctor=new j,this.parent&&this.ctor.body.push(new A(""+a+".__super__.constructor.apply(this, arguments)")),this.externalCtor&&this.ctor.body.push(new A(""+this.externalCtor+".apply(this, arguments)")),this.body.expressions.unshift(this.ctor)),this.ctor.ctor=this.ctor.name=a,this.ctor.klass=null;return this.ctor.noReturn=!0},c.prototype.compileNode=function(a){var b,c,e,f,g;c=this.determineName(),g=c||this.name||"_Class",g.reserved&&(g="_"+g),f=new A(g),this.setContext(g),this.walkBody(g,a),this.ensureConstructor(g),this.body.spaced=!0,this.ctor instanceof j||this.body.expressions.unshift(this.ctor),this.body.expressions.push(f),this.addBoundFunctions(a),b=i.wrap(this.body),this.parent&&(this.superClass=new A(a.scope.freeVariable("super",!1)),this.body.expressions.unshift(new m(f,this.superClass)),b.args.push(this.parent),b.variable.params.push(new G(this.superClass))),e=new H(b,!0),this.variable&&(e=new d(this.variable,e));return e.compile(a)};return c}(e),a.Assign=d=function(a){function c(a,b,c,d){this.variable=a,this.value=b,this.context=c,this.param=d&&d.param,this.subpattern=d&&d.subpattern}bj(c,a),c.prototype.children=["variable","value"],c.prototype.isStatement=function(a){return(a!=null?a.level:void 0)===z&&this.context!=null&&bk.call(this.context,"?")>=0},c.prototype.assigns=function(a){return this[this.context==="object"?"value":"variable"].assigns(a)},c.prototype.unfoldSoak=function(a){return bf(a,this,"variable")},c.prototype.compileNode=function(a){var b,c,d,e,f,g,h,i,k;if(b=this.variable instanceof V){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(a);if(this.variable.isSplice())return this.compileSplice(a);if((g=this.context)==="||="||g==="&&="||g==="?=")return this.compileConditional(a)}d=this.variable.compile(a,w);if(!this.context){if(!(f=this.variable.unwrapAll()).isAssignable())throw SyntaxError('"'+this.variable.compile(a)+'" cannot be assigned.');if(typeof f.hasProperties=="function"?!f.hasProperties():!void 0)this.param?a.scope.add(d,"var"):a.scope.find(d)}this.value instanceof j&&(c=B.exec(d))&&(c[1]&&(this.value.klass=c[1]),this.value.name=(h=(i=(k=c[2])!=null?k:c[3])!=null?i:c[4])!=null?h:c[5]),e=this.value.compile(a,w);if(this.context==="object")return""+d+": "+e;e=d+(" "+(this.context||"=")+" ")+e;return a.level<=w?e:"("+e+")"},c.prototype.compilePatternMatch=function(a){var d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,u,v,y,B,C,D,E,F,G,J,K;s=a.level===z,v=this.value,m=this.variable.base.objects;if(!(n=m.length)){f=v.compile(a);return a.level>=x?"("+f+")":f}i=this.variable.isObject();if(s&&n===1&&!((l=m[0])instanceof O)){l instanceof c?(C=l,D=C.variable,h=D.base,l=C.value):l.base instanceof H?(E=(new V(l.unwrapAll())).cacheReference(a),l=E[0],h=E[1]):h=i?l["this"]?l.properties[0].name:l:new A(0),d=o.test(h.unwrap().value||0),v=new V(v),v.properties.push(new(d?b:t)(h));if(F=l.unwrap().value,bk.call(["arguments","eval"].concat(I),F)>=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+v.compile(a));return(new c(l,v,null,{param:this.param})).compile(a,z)}y=v.compile(a,w),e=[],r=!1;if(!o.test(y)||this.variable.assigns(y))e.push(""+(p=a.scope.freeVariable("ref"))+" = "+y),y=p;for(g=0,B=m.length;g<B;g++){l=m[g],h=g,i&&(l instanceof c?(G=l,J=G.variable,h=J.base,l=G.value):l.base instanceof H?(K=(new V(l.unwrapAll())).cacheReference(a),l=K[0],h=K[1]):h=l["this"]?l.properties[0].name:l);if(!r&&l instanceof O)k=l.name.unwrap().value,l=l.unwrap(),u=""+n+" <= "+y+".length ? "+bg("slice")+".call("+y+", "+g,(q=n-g-1)?(j=a.scope.freeVariable("i"),u+=", "+j+" = "+y+".length - "+q+") : ("+j+" = "+g+", [])"):u+=") : []",u=new A(u),r=""+j+"++";else{k=l.unwrap().value;if(l instanceof O){l=l.name.compile(a);throw new SyntaxError("multiple splats are disallowed in an assignment: "+l+"...")}typeof h=="number"?(h=new A(r||h),d=!1):d=i&&o.test(h.unwrap().value||0),u=new V(new A(y),[new(d?b:t)(h)])}if(k!=null&&bk.call(["arguments","eval"].concat(I),k)>=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+u.compile(a));e.push((new c(l,u,null,{param:this.param,subpattern:!0})).compile(a,w))}!s&&!this.subpattern&&e.push(y),f=e.join(", ");return a.level<w?f:"("+f+")"},c.prototype.compileConditional=function(a){var b,d,e;e=this.variable.cacheReference(a),b=e[0],d=e[1],bk.call(this.context,"?")>=0&&(a.isExistentialEquals=!0);return(new F(this.context.slice(0,-1),b,new c(d,this.value,"="))).compile(a)},c.prototype.compileSplice=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;k=this.variable.properties.pop().range,d=k.from,h=k.to,c=k.exclusive,g=this.variable.compile(a),l=(d!=null?d.cache(a,x):void 0)||["0","0"],e=l[0],f=l[1],h?(d!=null?d.isSimpleNumber():void 0)&&h.isSimpleNumber()?(h=+h.compile(a)- +f,c||(h+=1)):(h=h.compile(a,u)+" - "+f,c||(h+=" + 1")):h="9e9",m=this.value.cache(a,w),i=m[0],j=m[1],b="[].splice.apply("+g+", ["+e+", "+h+"].concat("+i+")), "+j;return a.level>z?"("+b+")":b};return c}(e),a.Code=j=function(a){function b(a,b,c){this.params=a||[],this.body=b||new f,this.bound=c==="boundfunc",this.bound&&(this.context="_this")}bj(b,a),b.prototype.children=["params","body"],b.prototype.isStatement=function(){return!!this.ctor},b.prototype.jumps=D,b.prototype.compileNode=function(a){var b,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,v,w,x,y,z,B,C,D,E;a.scope=new M(a.scope,this.body,this),a.scope.shared=Z(a,"sharedScope"),a.indent+=Q,delete a.bare,o=[],e=[],z=this.params;for(q=0,v=z.length;q<v;q++){j=z[q];if(!j.splat)continue;B=this.params;for(s=0,w=B.length;s<w;s++)i=B[s],i.name.value&&a.scope.add(i.name.value,"var",!0);l=new d(new V(new c(function(){var b,c,d,e;d=this.params,e=[];for(b=0,c=d.length;b<c;b++)i=d[b],e.push(i.asReference(a));return e}.call(this))),new V(new A("arguments")));break}C=this.params;for(t=0,x=C.length;t<x;t++)j=C[t],j.isComplex()?(n=k=j.asReference(a),j.value&&(n=new F("?",k,j.value)),e.push(new d(new V(j.name),n,"=",{param:!0}))):(k=j,j.value&&(h=new A(k.name.value+" == null"),n=new d(new V(j.name),j.value,"="),e.push(new r(h,n)))),l||o.push(k);p=this.body.isEmpty(),l&&e.unshift(l),e.length&&(D=this.body.expressions).unshift.apply(D,e);if(!l)for(f=0,y=o.length;f<y;f++)m=o[f],a.scope.parameter(o[f]=m.compile(a));!p&&!this.noReturn&&this.body.makeReturn(),this.bound&&(((E=a.scope.parent.method)!=null?E.bound:void 0)?this.bound=this.context=a.scope.parent.method.context:this.static||a.scope.parent.assign("_this","this")),g=a.indent,b="function",this.ctor&&(b+=" "+this.name),b+="("+o.join(", ")+") {",this.body.isEmpty()||(b+="\n"+this.body.compileWithDeclarations(a)+"\n"+this.tab),b+="}";if(this.ctor)return this.tab+b;return this.front||a.level>=u?"("+b+")":b},b.prototype.traverseChildren=function(a,c){if(a)return b.__super__.traverseChildren.call(this,a,c)};return b}(e),a.Param=G=function(a){function b(a,b,c){this.name=a,this.value=b,this.splat=c}bj(b,a),b.prototype.children=["name","value"],b.prototype.compile=function(a){return this.name.compile(a,w)},b.prototype.asReference=function(a){var b;if(this.reference)return this.reference;b=this.name,b["this"]?(b=b.properties[0].name,b.value.reserved&&(b=new A("_"+b.value))):b.isComplex()&&(b=new A(a.scope.freeVariable("arg"))),b=new V(b),this.splat&&(b=new O(b));return this.reference=b},b.prototype.isComplex=function(){return this.name.isComplex()};return b}(e),a.Splat=O=function(a){function b(a){this.name=a.compile?a:new A(a)}bj(b,a),b.prototype.children=["name"],b.prototype.isAssignable=X,b.prototype.assigns=function(a){return this.name.assigns(a)},b.prototype.compile=function(a){return this.index!=null?this.compileParam(a):this.name.compile(a)},b.prototype.unwrap=function(){return this.name},b.compileSplattedArray=function(a,c,d){var e,f,g,h,i,j,k;i=-1;while((j=c[++i])&&!(j instanceof b))continue;if(i>=c.length)return"";if(c.length===1){g=c[0].compile(a,w);if(d)return g;return""+bg("slice")+".call("+g+")"}e=c.slice(i);for(h=0,k=e.length;h<k;h++)j=e[h],g=j.compile(a,w),e[h]=j instanceof b?""+bg("slice")+".call("+g+")":"["+g+"]";if(i===0)return e[0]+(".concat("+e.slice(1).join(", ")+")");f=function(){var b,d,e,f;e=c.slice(0,i),f=[];for(b=0,d=e.length;b<d;b++)j=e[b],f.push(j.compile(a,w));return f}();return"["+f.join(", ")+"].concat("+e.join(", ")+")"};return b}(e),a.While=W=function(a){function b(a,b){this.condition=(b!=null?b.invert:void 0)?a.invert():a,this.guard=b!=null?b.guard:void 0}bj(b,a),b.prototype.children=["condition","guard","body"],b.prototype.isStatement=X,b.prototype.makeReturn=function(a){if(a)return b.__super__.makeReturn.apply(this,arguments);this.returns=!this.jumps({loop:!0});return this},b.prototype.addBody=function(a){this.body=a;return this},b.prototype.jumps=function(){var a,b,c,d;a=this.body.expressions;if(!a.length)return!1;for(c=0,d=a.length;c<d;c++){b=a[c];if(b.jumps({loop:!0}))return b}return!1},b.prototype.compileNode=function(a){var b,c,d,e;a.indent+=Q,e="",b=this.body,b.isEmpty()?b="":(this.returns&&(b.makeReturn(d=a.scope.freeVariable("results")),e=""+this.tab+d+" = [];\n"),this.guard&&(b.expressions.length>1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),b="\n"+b.compile(a,z)+"\n"+this.tab),c=e+this.tab+("while ("+this.condition.compile(a,y)+") {"+b+"}"),this.returns&&(c+="\n"+this.tab+"return "+d+";");return c};return b}(e),a.Op=F=function(a){function e(a,c,d,e){var f;if(a==="in")return new s(c,d);if(a==="do"){f=new g(c,c.params||[]),f["do"]=!0;return f}if(a==="new"){if(c instanceof g&&!c["do"]&&!c.isNew)return c.newInstance();if(c instanceof j&&c.bound||c["do"])c=new H(c)}this.operator=b[a]||a,this.first=c,this.second=d,this.flip=!!e;return this}var b,c;bj(e,a),b={"==":"===","!=":"!==",of:"in"},c={"!==":"===","===":"!=="},e.prototype.children=["first","second"],e.prototype.isSimpleNumber=D,e.prototype.isUnary=function(){return!this.second},e.prototype.isComplex=function(){var a;return!this.isUnary()||(a=this.operator)!=="+"&&a!=="-"||this.first.isComplex()},e.prototype.isChainable=function(){var a;return(a=this.operator)==="<"||a===">"||a===">="||a==="<="||a==="==="||a==="!=="},e.prototype.invert=function(){var a,b,d,f,g;if(this.isChainable()&&this.first.isChainable()){a=!0,b=this;while(b&&b.operator)a&&(a=b.operator in c),b=b.first;if(!a)return(new H(this)).invert();b=this;while(b&&b.operator)b.invert=!b.invert,b.operator=c[b.operator],b=b.first;return this}if(f=c[this.operator]){this.operator=f,this.first.unwrap()instanceof e&&this.first.invert();return this}return this.second?(new H(this)).invert():this.operator==="!"&&(d=this.first.unwrap())instanceof e&&((g=d.operator)==="!"||g==="in"||g==="instanceof")?d:new e("!",this)},e.prototype.unfoldSoak=function(a){var b;return((b=this.operator)==="++"||b==="--"||b==="delete")&&bf(a,this,"first")},e.prototype.compileNode=function(a){var b,c;c=this.isChainable()&&this.first.isChainable(),c||(this.first.front=this.front);if(this.isUnary())return this.compileUnary(a);if(c)return this.compileChain(a);if(this.operator==="?")return this.compileExistence(a);b=this.first.compile(a,x)+" "+this.operator+" "+this.second.compile(a,x);return a.level<=x?b:"("+b+")"},e.prototype.compileChain=function(a){var b,c,d,e;e=this.first.second.cache(a),this.first.second=e[0],d=e[1],c=this.first.compile(a,x),b=""+c+" "+(this.invert?"&&":"||")+" "+d.compile(a)+" "+this.operator+" "+this.second.compile(a,x);return"("+b+")"},e.prototype.compileExistence=function(a){var b,c;this.first.isComplex()&&a.level>z?(c=new A(a.scope.freeVariable("ref")),b=new H(new d(c,this.first))):(b=this.first,c=b);return(new r(new l(b),c,{type:"if"})).addElse(this.second).compile(a)},e.prototype.compileUnary=function(a){var b,c,d;c=[b=this.operator],d=b==="+"||b==="-",(b==="new"||b==="typeof"||b==="delete"||d&&this.first instanceof e&&this.first.operator===b)&&c.push(" ");if(d&&this.first instanceof e||b==="new"&&this.first.isStatement(a))this.first=new H(this.first);c.push(this.first.compile(a,x)),this.flip&&c.reverse();return c.join("")},e.prototype.toString=function(a){return e.__super__.toString.call(this,a,this.constructor.name+" "+this.operator)};return e}(e),a.In=s=function(a){function b(a,b){this.object=a,this.array=b}bj(b,a),b.prototype.children=["object","array"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e,f;if(this.array instanceof V&&this.array.isArray()){f=this.array.base.objects;for(d=0,e=f.length;d<e;d++){c=f[d];if(!(c instanceof O))continue;b=!0;break}if(!b)return this.compileOrTest(a)}return this.compileLoopTest(a)},b.prototype.compileOrTest=function(a){var b,c,d,e,f,g,h,i,j;if(this.array.base.objects.length===0)return""+!!this.negated;i=this.object.cache(a,x),g=i[0],f=i[1],j=this.negated?[" !== "," && "]:[" === "," || "],b=j[0],c=j[1],h=function(){var c,h,i;h=this.array.base.objects,i=[];for(d=0,c=h.length;d<c;d++)e=h[d],i.push((d?f:g)+b+e.compile(a,u));return i}.call(this),h=h.join(c);return a.level<x?h:"("+h+")"},b.prototype.compileLoopTest=function(a){var b,c,d,e;e=this.object.cache(a,w),d=e[0],c=e[1],b=bg("indexOf")+(".call("+this.array.compile(a,w)+", "+c+") ")+(this.negated?"< 0":">= 0");if(d===c)return b;b=d+", "+b;return a.level<w?b:"("+b+")"},b.prototype.toString=function(a){return b.__super__.toString.call(this,a,this.constructor.name+(this.negated?"!":""))};return b}(e),a.Try=T=function(a){function b(a,b,c,d){this.attempt=a,this.error=b,this.recovery=c,this.ensure=d}bj(b,a),b.prototype.children=["attempt","recovery","ensure"],b.prototype.isStatement=X,b.prototype.jumps=function(a){var b;return this.attempt.jumps(a)||((b=this.recovery)!=null?b.jumps(a):void 0)},b.prototype.makeReturn=function(a){this.attempt&&(this.attempt=this.attempt.makeReturn(a)),this.recovery&&(this.recovery=this.recovery.makeReturn(a));return this},b.prototype.compileNode=function(a){var b,c,d,e;a.indent+=Q,d=this.error?" ("+this.error.compile(a)+") ":" ",e=this.attempt.compile(a,z),b=this.recovery?(a.scope.check(this.error.value)?void 0:a.scope.add(this.error.value,"param")," catch"+d+"{\n"+this.recovery.compile(a,z)+"\n"+this.tab+"}"):!this.ensure&&!this.recovery?" catch (_error) {}":void 0,c=this.ensure?" finally {\n"+this.ensure.compile(a,z)+"\n"+this.tab+"}":"";return""+this.tab+"try {\n"+e+"\n"+this.tab+"}"+(b||"")+c};return b}(e),a.Throw=S=function(a){function b(a){this.expression=a}bj(b,a),b.prototype.children=["expression"],b.prototype.isStatement=X,b.prototype.jumps=D,b.prototype.makeReturn=R,b.prototype.compileNode=function(a){return this.tab+("throw "+this.expression.compile(a)+";")};return b}(e),a.Existence=l=function(a){function b(a){this.expression=a}bj(b,a),b.prototype.children=["expression"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e;this.expression.front=this.front,d=this.expression.compile(a,x),o.test(d)&&!a.scope.check(d)?(e=this.negated?["===","||"]:["!==","&&"],b=e[0],c=e[1],d="typeof "+d+" "+b+' "undefined" '+c+" "+d+" "+b+" null"):d=""+d+" "+(this.negated?"==":"!=")+" null";return a.level<=v?d:"("+d+")"};return b}(e),a.Parens=H=function(a){function b(a){this.body=a}bj(b,a),b.prototype.children=["body"],b.prototype.unwrap=function(){return this.body},b.prototype.isComplex=function(){return this.body.isComplex()},b.prototype.compileNode=function(a){var b,c,d;d=this.body.unwrap();if(d instanceof V&&d.isAtomic()){d.front=this.front;return d.compile(a)}c=d.compile(a,y),b=a.level<x&&(d instanceof F||d instanceof g||d instanceof n&&d.returns);return b?c:"("+c+")"};return b}(e),a.For=n=function(a){function b(a,b){var c;this.source=b.source,this.guard=b.guard,this.step=b.step,this.name=b.name,this.index=b.index,this.body=f.wrap([a]),this.own=!!b.own,this.object=!!b.object,this.object&&(c=[this.index,this.name],this.name=c[0],this.index=c[1]);if(this.index instanceof V)throw SyntaxError("index cannot be a pattern matching expression");this.range=this.source instanceof V&&this.source.base instanceof J&&!this.source.properties.length,this.pattern=this.name instanceof V;if(this.range&&this.index)throw SyntaxError("indexes do not apply to range loops");if(this.range&&this.pattern)throw SyntaxError("cannot pattern match over range loops");this.returns=!1}bj(b,a),b.prototype.children=["body","source","guard","step"],b.prototype.compileNode=function(a){var b,c,e,g,h,i,j,k,l,m,n,p,q,s,t,u,v,y,B,C,D,E,F;b=f.wrap([this.body]),l=(F=bb(b.expressions))!=null?F.jumps():void 0,l&&l instanceof K&&(this.returns=!1),y=this.range?this.source.base:this.source,v=a.scope,n=this.name&&this.name.compile(a,w),j=this.index&&this.index.compile(a,w),n&&!this.pattern&&v.find(n,{immediate:!0}),j&&v.find(j,{immediate:!0}),this.returns&&(u=v.freeVariable("results")),k=(this.range?n:j)||v.freeVariable("i"),this.step&&!this.range&&(C=v.freeVariable("step")),this.pattern&&(n=k),E="",h="",c="",i=this.tab+Q,this.range?e=y.compile(bc(a,{index:k,step:this.step})):(D=this.source.compile(a,w),(n||this.own)&&!o.test(D)&&(c=""+this.tab+(q=v.freeVariable("ref"))+" = "+D+";\n",D=q),n&&!this.pattern&&(p=""+n+" = "+D+"["+k+"]"),this.object||(m=v.freeVariable("len"),g=""+k+" = 0, "+m+" = "+D+".length"+(this.step?", "+C+" = "+this.step.compile(a,x):""),B=this.step?""+k+" += "+C:""+k+"++",e=""+g+"; "+k+" < "+m+"; "+B)),this.returns&&(s=""+this.tab+u+" = [];\n",t="\n"+this.tab+"return "+u+";",b.makeReturn(u)),this.guard&&(b.expressions.length>1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),this.pattern&&b.expressions.unshift(new d(this.name,new A(""+D+"["+k+"]"))),c+=this.pluckDirectCall(a,b),p&&(E="\n"+i+p+";"),this.object&&(e=""+k+" in "+D,this.own&&(h="\n"+i+"if (!"+bg("hasProp")+".call("+D+", "+k+")) continue;")),b=b.compile(bc(a,{indent:i}),z),b&&(b="\n"+b+"\n");return""+c+(s||"")+this.tab+"for ("+e+") {"+h+E+b+this.tab+"}"+(t||"")},b.prototype.pluckDirectCall=function(a,b){var c,e,f,h,i,k,l,m,n,o,p,q,r,s;e="",n=b.expressions;for(i=0,m=n.length;i<m;i++){f=n[i],f=f.unwrapAll();if(!(f instanceof g))continue;l=f.variable.unwrapAll();if(!(l instanceof j||l instanceof V&&((o=l.base)!=null?o.unwrapAll():void 0)instanceof j&&l.properties.length===1&&((p=(q=l.properties[0].name)!=null?q.value:void 0)==="call"||p==="apply")))continue;h=((r=l.base)!=null?r.unwrapAll():void 0)||l,k=new A(a.scope.freeVariable("fn")),c=new V(k),l.base&&(s=[c,l],l.base=s[0],c=s[1]),b.expressions[i]=new g(c,f.args),e+=this.tab+(new d(k,h)).compile(a,z)+";\n"}return e};return b}(W),a.Switch=P=function(a){function b(a,b,c){this.subject=a,this.cases=b,this.otherwise=c}bj(b,a),b.prototype.children=["subject","cases","otherwise"],b.prototype.isStatement=X,b.prototype.jumps=function(a){var b,c,d,e,f,g,h;a==null&&(a={block:!0}),f=this.cases;for(d=0,e=f.length;d<e;d++){g=f[d],c=g[0],b=g[1];if(b.jumps(a))return b}return(h=this.otherwise)!=null?h.jumps(a):void 0},b.prototype.makeReturn=function(a){var b,c,d,e,g;e=this.cases;for(c=0,d=e.length;c<d;c++)b=e[c],b[1].makeReturn(a);a&&(this.otherwise||(this.otherwise=new f([new A("void 0")]))),(g=this.otherwise)!=null&&g.makeReturn(a);return this},b.prototype.compileNode=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q;i=a.indent+Q,j=a.indent=i+Q,d=this.tab+("switch ("+(((n=this.subject)!=null?n.compile(a,y):void 0)||!1)+") {\n"),o=this.cases;for(h=0,l=o.length;h<l;h++){p=o[h],f=p[0],b=p[1],q=ba([f]);for(k=0,m=q.length;k<m;k++)e=q[k],this.subject||(e=e.invert()),d+=i+("case "+e.compile(a,y)+":\n");if(c=b.compile(a,z))d+=c+"\n";if(h===this.cases.length-1&&!this.otherwise)break;g=this.lastNonComment(b.expressions);if(g instanceof K||g instanceof A&&g.jumps()&&g.value!=="debugger")continue;d+=j+"break;\n"}this.otherwise&&this.otherwise.expressions.length&&(d+=i+("default:\n"+this.otherwise.compile(a,z)+"\n"));return d+this.tab+"}"};return b}(e),a.If=r=function(a){function b(a,b,c){this.body=b,c==null&&(c={}),this.condition=c.type==="unless"?a.invert():a,this.elseBody=null,this.isChain=!1,this.soak=c.soak}bj(b,a),b.prototype.children=["condition","body","elseBody"],b.prototype.bodyNode=function(){var a;return(a=this.body)!=null?a.unwrap():void 0},b.prototype.elseBodyNode=function(){var a;return(a=this.elseBody)!=null?a.unwrap():void 0},b.prototype.addElse=function(a){this.isChain?this.elseBodyNode().addElse(a):(this.isChain=a instanceof b,this.elseBody=this.ensureBlock(a));return this},b.prototype.isStatement=function(a){var b;return(a!=null?a.level:void 0)===z||this.bodyNode().isStatement(a)||((b=this.elseBodyNode())!=null?b.isStatement(a):void 0)},b.prototype.jumps=function(a){var b;return this.body.jumps(a)||((b=this.elseBody)!=null?b.jumps(a):void 0)},b.prototype.compileNode=function(a){return this.isStatement(a)?this.compileStatement(a):this.compileExpression(a)},b.prototype.makeReturn=function(a){a&&(this.elseBody||(this.elseBody=new f([new A("void 0")]))),this.body&&(this.body=new f([this.body.makeReturn(a)])),this.elseBody&&(this.elseBody=new f([this.elseBody.makeReturn(a)]));return this},b.prototype.ensureBlock=function(a){return a instanceof f?a:new f([a])},b.prototype.compileStatement=function(a){var c,d,e,f,g,h,i;e=Z(a,"chainChild"),g=Z(a,"isExistentialEquals");if(g)return(new b(this.condition.invert(),this.elseBodyNode(),{type:"if"})).compile(a);f=this.condition.compile(a,y),a.indent+=Q,c=this.ensureBlock(this.body),d=c.compile(a);if(1===((i=c.expressions)!=null?i.length:void 0)&&!this.elseBody&&!e&&d&&f&&-1===d.indexOf("\n")&&80>f.length+d.length)return""+this.tab+"if ("+f+") "+d.replace(/^\s+/,"");d&&(d="\n"+d+"\n"+this.tab),h="if ("+f+") {"+d+"}",e||(h=this.tab+h);if(!this.elseBody)return h;return h+" else "+(this.isChain?(a.indent=this.tab,a.chainChild=!0,this.elseBody.unwrap().compile(a,z)):"{\n"+this.elseBody.compile(a,z)+"\n"+this.tab+"}")},b.prototype.compileExpression=function(a){var b,c,d,e;e=this.condition.compile(a,v),c=this.bodyNode().compile(a,w),b=this.elseBodyNode()?this.elseBodyNode().compile(a,w):"void 0",d=""+e+" ? "+c+" : "+b;return a.level>=v?"("+d+")":d},b.prototype.unfoldSoak=function(){return this.soak&&this};return b}(e),i={wrap:function(a,c,d){var e,h,i,k,l;if(a.jumps())return a;i=new j([],f.wrap([a])),e=[];if((k=a.contains(this.literalArgs))||a.contains(this.literalThis))l=new A(k?"apply":"call"),e=[new A("this")],k&&e.push(new A("arguments")),i=new V(i,[new b(l)]);i.noReturn=d,h=new g(i,e);return c?f.wrap([h]):h},literalArgs:function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey},literalThis:function(a){return a instanceof A&&a.value==="this"&&!a.asKey||a instanceof j&&a.bound}},bf=function(a,b,c){var d;if(!!(d=b[c].unfoldSoak(a))){b[c]=d.body,d.body=new V(b);return d}},U={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+bg("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},hasProp:function(){return"Object.prototype.hasOwnProperty"},slice:function(){return"Array.prototype.slice"}},z=1,y=2,w=3,v=4,x=5,u=6,Q="  ",p="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",o=RegExp("^"+p+"$"),L=/^[+-]?\d+$/,B=RegExp("^(?:("+p+")\\.prototype(?:\\.("+p+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|("+p+")$"),q=/^['"]/,bg=function(a){var b;b="__"+a,M.root.assign(b,U[a]());return b},bd=function(a,b){a=a.replace(/\n/g,"$&"+b);return a.replace(/\s+$/,"")}}).call(this)},require["./coffee-script"]=new function(){var a=this;(function(){var b,c,d,e,f,g,h,i,j,k=Object.prototype.hasOwnProperty;e=require("fs"),h=require("path"),j=require("./lexer"),b=j.Lexer,c=j.RESERVED,g=require("./parser").parser,i=require("vm"),require.extensions?require.extensions[".coffee"]=function(a,b){var c;c=d(e.readFileSync(b,"utf8"),{filename:b});return a._compile(c,b)}:require.registerExtension&&require.registerExtension(".coffee",function(a){return d(a)}),a.VERSION="1.2.0",a.RESERVED=c,a.helpers=require("./helpers"),a.compile=d=function(b,c){var d;c==null&&(c={}),d=a.helpers.merge;try{return g.parse(f.tokenize(b)).compile(d({},c))}catch(e){c.filename&&(e.message="In "+c.filename+", "+e.message);throw e}},a.tokens=function(a,b){return f.tokenize(a,b)},a.nodes=function(a,b){return typeof a=="string"?g.parse(f.tokenize(a,b)):g.parse(a)},a.run=function(a,b){var c;c=require.main,c.filename=process.argv[1]=b.filename?e.realpathSync(b.filename):".",c.moduleCache&&(c.moduleCache={}),c.paths=require("module")._nodeModulePaths(h.dirname(b.filename));return h.extname(c.filename)!==".coffee"||require.extensions?c._compile(d(a,b),c.filename):c._compile(a,c.filename)},a.eval=function(a,b){var c,e,f,g,j,l,m,n,o,p,q,r,s,t;b==null&&(b={});if(!!(a=a.trim())){e=i.Script;if(e){if(b.sandbox!=null){if(b.sandbox instanceof e.createContext().constructor)m=b.sandbox;else{m=e.createContext(),r=b.sandbox;for(g in r){if(!k.call(r,g))continue;n=r[g],m[g]=n}}m.global=m.root=m.GLOBAL=m}else m=global;m.__filename=b.filename||"eval",m.__dirname=h.dirname(m.__filename);if(m===global&&!m.module&&!m.require){c=require("module"),m.module=q=new c(b.modulename||"eval"),m.require=t=function(a){return c._load(a,q,!0)},q.filename=m.__filename,s=Object.getOwnPropertyNames(require);for(o=0,p=s.length;o<p;o++)l=s[o],l!=="paths"&&(t[l]=require[l]);t.paths=q.paths=c._nodeModulePaths(process.cwd()),t.resolve=function(a){return c._resolveFilename(a,q)}}}j={};for(g in b){if(!k.call(b,g))continue;n=b[g],j[g]=n}j.bare=!0,f=d(a,j);return m===global?i.runInThisContext(f):i.runInContext(f,m)}},f=new b,g.lexer={lex:function(){var a,b;b=this.tokens[this.pos++]||[""],a=b[0],this.yytext=b[1],this.yylineno=b[2];return a},setInput:function(a){this.tokens=a;return this.pos=0},upcomingInput:function(){return""}},g.yy=require("./nodes")}).call(this)},require["./browser"]=new function(){var exports=this;(function(){var CoffeeScript,runScripts;CoffeeScript=require("./coffee-script"),CoffeeScript.require=require,CoffeeScript.eval=function(code,options){return eval(CoffeeScript.compile(code,options))},CoffeeScript.run=function(a,b){b==null&&(b={}),b.bare=!0;return Function(CoffeeScript.compile(a,b))()};typeof window!="undefined"&&window!==null&&(CoffeeScript.load=function(a,b){var c;c=new(window.ActiveXObject||XMLHttpRequest)("Microsoft.XMLHTTP"),c.open("GET",a,!0),"overrideMimeType"in c&&c.overrideMimeType("text/plain"),c.onreadystatechange=function(){var d;if(c.readyState===4){if((d=c.status)===0||d===200)CoffeeScript.run(c.responseText);else throw new Error("Could not load "+a);if(b)return b()}};return c.send(null)},runScripts=function(){var a,b,c,d,e,f;f=document.getElementsByTagName("script"),a=function(){var a,b,c;c=[];for(a=0,b=f.length;a<b;a++)e=f[a],e.type==="text/coffeescript"&&c.push(e);return c}(),c=0,d=a.length,(b=function(){var d;d=a[c++];if((d!=null?d.type:void 0)==="text/coffeescript"){if(d.src)return CoffeeScript.load(d.src,b);CoffeeScript.run(d.innerHTML);return b()}})();return null},window.addEventListener?addEventListener("DOMContentLoaded",runScripts,!1):attachEvent("onload",runScripts))}).call(this)};return require["./coffee-script"]}();typeof define=="function"&&define.amd?define(function(){return CoffeeScript}):root.CoffeeScript=CoffeeScript})(this)
;
(function($) {
  $.template("chat/recent", "<li data-id=\'${id}\'>\n  <hr />\n  <span class=\'name\'>${name}<\/span>\n  <span class=\'time\'>${time}<\/span>\n  <span class=\'message\'>{{html message}}<\/span>\n<\/li>\n");
})(jQuery);
(function($) {
  $.template("chat/active_user", "<li data-id=\'${id}\'>\n  <a href=\'${user_path}\' style=\'color: #${color};\' target=\'_blank\'>\n    <img src=\'${avatar}\' />\n    ${display_name}\n  <\/a>\n<\/li>\n");
})(jQuery);
(function() {
  namespace("Pixie.Chat", function(Chat) {
    return Chat.create = function(current_user) {
      var appendChat, chatSound, initialize, refreshData, scrollChat, send, withinScrollBoundary;
      chatSound = $("#chat_sound").get(0);
      if (getVal('chatNotificationEnabled')) {
        $('#notification_toggle').attr('checked', 'checked');
      } else {
        $('#notification_toggle').removeAttr('checked');
      }
      withinScrollBoundary = function() {
        return $('#chats').scrollTop() >= $.scrollTo.max($('#chats').get(0), 'y') * 0.90;
      };
      scrollChat = function() {
        return setTimeout(function() {
          return $('#chats').scrollTo({
            left: '0%',
            top: '100%'
          });
        }, 100);
      };
      appendChat = function(chat, prevChatUser) {
        var chatData;
        chatData = $.tmpl('chat/recent', chat);
        if (chat.name === prevChatUser) {
          $(chatData).find('hr, .name, .time').remove();
        } else if (chat.user_id > 0) {
          $(chatData).find('.name').html('<a target="_blank" href="/people/' + chat.user_id + '">' + chat.name + '</a>');
        }
        if (!chat.id) {
          $(chatData).removeAttr('data-id');
        }
        return $('#chats').append(chatData);
      };
      initialize = function() {
        $.get('/chats/active_users', function(activeUsers) {
          var user, _i, _len, _results;
          _results = [];
          for (_i = 0, _len = activeUsers.length; _i < _len; _i++) {
            user = activeUsers[_i];
            _results.push($.tmpl('chat/active_user', user).appendTo($('#active_users')));
          }
          return _results;
        });
        return $.get('/chats/recent', function(chats) {
          var chat, prevChatUser, _i, _len;
          prevChatUser = null;
          for (_i = 0, _len = chats.length; _i < _len; _i++) {
            chat = chats[_i];
            appendChat(chat, prevChatUser);
            prevChatUser = chat.name;
          }
          return scrollChat();
        });
      };
      refreshData = function() {
        $.get('/chats/active_users', function(activeUsers) {
          var currentlyOnline, id, lastOnline, user, userEl, _i, _j, _len, _len2, _results;
          lastOnline = (function() {
            var _i, _len, _ref, _results;
            _ref = $('#active_users li');
            _results = [];
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
              userEl = _ref[_i];
              _results.push(parseInt($(userEl).attr('data-id')));
            }
            return _results;
          })();
          currentlyOnline = (function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = activeUsers.length; _i < _len; _i++) {
              user = activeUsers[_i];
              _results.push(user.id);
            }
            return _results;
          })();
          for (_i = 0, _len = lastOnline.length; _i < _len; _i++) {
            id = lastOnline[_i];
            if ($.inArray(id, currentlyOnline) < 0) {
              $('#active_users li[data-id=' + id + ']').remove();
            }
          }
          _results = [];
          for (_j = 0, _len2 = activeUsers.length; _j < _len2; _j++) {
            user = activeUsers[_j];
            _results.push($.inArray(user.id, lastOnline) < 0 ? $.tmpl('chat/active_user', user).appendTo($('#active_users')) : void 0);
          }
          return _results;
        });
        return $.get('/chats/recent', function(chats) {
          var chat, newChats, prevChatId, prevChatUser, scroll, _i, _len;
          $('#chats li:not([data-id])').remove();
          prevChatId = null;
          prevChatUser = null;
          newChats = false;
          scroll = withinScrollBoundary();
          for (_i = 0, _len = chats.length; _i < _len; _i++) {
            chat = chats[_i];
            if (prevChatId && chat.id > prevChatId) {
              appendChat(chat, prevChatUser);
              if (chat.name !== current_user.name) {
                newChats = true;
              }
            }
            prevChatId = parseInt($('#chats li[data-id]:last').attr('data-id'));
            prevChatUser = chat.name;
          }
          if (newChats && getVal('chatNotificationEnabled')) {
            chatSound.play();
            $('#chat_zone .header, #open_chat').css('backgroundColor', '#CE5A10');
            newChats = false;
          }
          if (scroll) {
            return scrollChat();
          }
        });
      };
      initialize();
      setInterval(refreshData, 30000);
      send = function(field) {
        var current_time, date, message, newMessage, paddedMinutes, prevChatUser, scroll;
        if (!(message = field.val())) {
          return;
        }
        date = new Date();
        paddedMinutes = date.getMinutes() < 10 ? "0" + (date.getMinutes()) : date.getMinutes();
        current_time = "" + (date.getHours() % 12) + ":" + paddedMinutes + (date.getHours() > 11 ? 'pm' : 'am');
        $.post('/chats', {
          body: message
        });
        prevChatUser = $('#chats li span.name:last').text();
        newMessage = {
          name: current_user.name,
          time: current_time,
          message: message,
          user_id: current_user.id
        };
        scroll = withinScrollBoundary();
        appendChat(newMessage, prevChatUser);
        if (scroll) {
          scrollChat();
        }
        return $('#chat_body').val("");
      };
      $("#chat_zone").dropImageReader(function(file, event) {
        var img, wrapper;
        if (event.target.readyState === FileReader.DONE) {
          wrapper = $("<div />");
          img = $("<img/>", {
            alt: file.name,
            src: event.target.result,
            title: file.name
          });
          img.appendTo(wrapper);
          return $.post('/chats', {
            body: wrapper.html()
          }, function() {
            return refreshData();
          });
        }
      });
      $('#chat_zone #chat_body').keypress(function(e) {
        var textBox;
        textBox = $('#chat_copy_html');
        if (e.keyCode === 13 && !e.shiftKey) {
          e.preventDefault();
          return send(textBox);
        }
      });
      $('#notification_toggle').change(function() {
        return setVal('chatNotificationEnabled', $(this).attr('checked') === 'checked');
      });
      $('#notification_toggle, #notification_label').mousedown(function(e) {
        return e.stopPropagation();
      });
      $('#open_chat, #chat_zone .header').mousedown(function() {
        $('#open_chat').toggleClass('straight');
        return $('#chat_zone').toggleClass('visible');
      });
      $("#chat_zone").bind("show", function() {
        $('#open_chat').addClass('straight');
        return $('#chat_zone').addClass('visible');
      });
      $('#open_chat, #chat_zone').mousedown(function(e) {
        return $('#chat_zone .header, #open_chat').css('backgroundColor', '#1084CE');
      });
      $('#chats li').live({
        mouseenter: function() {
          var chat_id;
          $(this).find('.time').css('display', 'inline-block');
          if (current_user.admin) {
            chat_id = $(this).data('id');
            return $('<a class="delete" href="/chats/' + chat_id + '" title="Delete">Delete</a>').appendTo($(this));
          }
        },
        mouseleave: function() {
          $(this).find('.time').hide();
          return $(this).find('.delete').remove();
        }
      });
      $('#chats .delete').live({
        click: function(e) {
          e.preventDefault();
          if (confirm("Are you sure you want to change history?")) {
            $(this).parent().remove();
            return $.ajax({
              type: "DELETE",
              url: $(this).attr('href'),
              data: {
                id: $(this).parent().data('id')
              }
            });
          }
        }
      });
      return $(document).bind('keydown', 'c', function(e) {
        e.preventDefault();
        return $('#open_chat').mousedown();
      });
    };
  });
}).call(this);
(function() {

}).call(this);

