UNPKG

translator

Version:

[ABANDONED] Translator for node and also for browser

11,980 lines 409 kB
(function() {
	var __r__c__ = this;
	/** Generated by SimQ **/
	/** modules **/
	
	// Generated by CoffeeScript 1.6.3
	(function() {
	  var SUPPORTED, arrayIndexOf, cache, creating, modules, require, resolve, stats;
	
	  if (!this.require) {
	    SUPPORTED = ['js', 'json', 'ts', 'coffee', 'eco'];
	    modules = {};
	    stats = {};
	    cache = {};
	    creating = [];
	    require = function(name, parent) {
	      var fullName, m;
	      if (parent == null) {
	        parent = null;
	      }
	      fullName = resolve(name, parent);
	      if (typeof cache[fullName] === 'undefined') {
	        m = {
	          exports: {},
	          id: fullName,
	          filename: fullName,
	          loaded: false,
	          parent: null,
	          children: null
	        };
	        if (arrayIndexOf(creating, fullName) === -1) {
	          creating.push(fullName);
	          modules[fullName].apply(window, [m.exports, m]);
	          creating.splice(arrayIndexOf(creating, fullName));
	          cache[fullName] = m;
	        }
	        m.loaded = true;
	      } else {
	        m = cache[fullName];
	      }
	      if (typeof stats[fullName] === 'undefined') {
	        stats[fullName] = {
	          atime: null,
	          mtime: null,
	          ctime: null
	        };
	      }
	      stats[fullName].atime = new Date;
	      return m.exports;
	    };
	    resolve = function(name, parent) {
	      var ext, num, original, part, parts, prev, result, _i, _j, _k, _len, _len1, _len2;
	      if (parent == null) {
	        parent = null;
	      }
	      original = name;
	      if (parent !== null && name[0] === '.') {
	        num = parent.lastIndexOf('/');
	        if (num !== -1) {
	          parent = parent.substr(0, num);
	        }
	        name = parent + '/' + name;
	      }
	      parts = name.split('/');
	      result = [];
	      prev = null;
	      for (_i = 0, _len = parts.length; _i < _len; _i++) {
	        part = parts[_i];
	        if (part === '.' || part === '') {
	          continue;
	        } else if (part === '..' && prev) {
	          result.pop();
	        } else {
	          result.push(part);
	        }
	        prev = part;
	      }
	      name = result.join('/');
	      if ((original[0] === '/') || (parent !== null && parent[0] === '/' && original[0] === '.')) {
	        name = '/' + name;
	      }
	      if (typeof modules[name] !== 'undefined') {
	        return name;
	      }
	      for (_j = 0, _len1 = SUPPORTED.length; _j < _len1; _j++) {
	        ext = SUPPORTED[_j];
	        if (typeof modules[name + '.' + ext] !== 'undefined') {
	          return name + '.' + ext;
	        }
	      }
	      for (_k = 0, _len2 = SUPPORTED.length; _k < _len2; _k++) {
	        ext = SUPPORTED[_k];
	        if (typeof modules[name + '/index.' + ext] !== 'undefined') {
	          return name + '/index.' + ext;
	        }
	      }
	      throw new Error("Module " + original + " was not found.");
	    };
	    arrayIndexOf = function(array, search) {
	      var element, i, _i, _len;
	      if (typeof Array.prototype.indexOf !== 'undefined') {
	        return array.indexOf(search);
	      }
	      if (array.length === 0) {
	        return -1;
	      }
	      for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
	        element = array[i];
	        if (element === search) {
	          return i;
	        }
	      }
	      return -1;
	    };
	    this.require = function(name, parent) {
	      if (parent == null) {
	        parent = null;
	      }
	      return require(name, parent);
	    };
	    this.require.simq = true;
	    this.require.version = 1;
	    this.require.resolve = function(name, parent) {
	      if (parent == null) {
	        parent = null;
	      }
	      return resolve(name, parent);
	    };
	    this.require.define = function(bundleOrName, obj) {
	      var m, name, _results;
	      if (obj == null) {
	        obj = null;
	      }
	      if (typeof bundleOrName === 'string') {
	        return modules[bundleOrName] = obj;
	      } else {
	        _results = [];
	        for (name in bundleOrName) {
	          m = bundleOrName[name];
	          _results.push(modules[name] = m);
	        }
	        return _results;
	      }
	    };
	    this.require.release = function() {
	      var name, _results;
	      _results = [];
	      for (name in cache) {
	        _results.push(delete cache[name]);
	      }
	      return _results;
	    };
	    this.require.getStats = function(name, parent) {
	      var fullName;
	      if (parent == null) {
	        parent = null;
	      }
	      fullName = resolve(name, parent);
	      if (fullName === null) {
	        throw new Error('Module ' + name + ' was not found.');
	      }
	      if (typeof stats[fullName] === 'undefined') {
	        stats[fullName] = {
	          atime: null,
	          mtime: null,
	          ctime: null
	        };
	      }
	      return stats[fullName];
	    };
	    this.require.__setStats = function(bundle) {
	      var data, name, _results;
	      _results = [];
	      for (name in bundle) {
	        data = bundle[name];
	        _results.push(stats[name] = {
	          atime: new Date(data.atime),
	          mtime: new Date(data.mtime),
	          ctime: new Date(data.ctime)
	        });
	      }
	      return _results;
	    };
	    this.require.cache = cache;
	  }
	
	  return this.require.define;
	
	}).call(this)({
	 '/lib/Loaders/Loader.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/Loaders/Loader.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/Loaders/Loader.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/Loaders/Loader.js';
		var __dirname = '/lib/Loaders';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/Loaders/Loader.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Loader;
		
		  Loader = (function() {
		    function Loader() {}
		
		    Loader.prototype.load = function() {
		      throw new Error('Translator loader: you have to implement method load.');
		    };
		
		    Loader.prototype.getFileSystemPath = function() {
		      throw new Error('Translator loader: you have to implement method getFileSystemPath.');
		    };
		
		    return Loader;
		
		  })();
		
		  module.exports = Loader;
		
		}).call(this);
		
	
	}, '/lib/Translator.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/Translator.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/Translator.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/Translator.js';
		var __dirname = '/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/Translator.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Args, Cache, JsonLoader, Loader, Storage, Translator, callsite, isBrowser, path, pluralForms;
		
		  Cache = require('cache-storage');
		
		  Storage = require('cache-storage/lib/Storage/Storage');
		
		  Args = require('normalize-arguments');
		
		  path = require('./node/path');
		
		  pluralForms = require('./pluralForms');
		
		  Loader = require('./Loaders/Loader');
		
		  JsonLoader = require('./Loaders/Json');
		
		  isBrowser = typeof window !== 'undefined';
		
		  if (!isBrowser) {
		    callsite = require('callsite');
		  }
		
		  Translator = (function() {
		    Translator.prototype.loader = null;
		
		    Translator.prototype.language = null;
		
		    Translator.prototype.plurals = null;
		
		    Translator.prototype.replacements = null;
		
		    Translator.prototype.filters = null;
		
		    Translator.prototype.data = null;
		
		    Translator.prototype.cache = null;
		
		    function Translator(pathOrLoader) {
		      var config, data, language, stack, _config;
		      this.plurals = {};
		      this.replacements = {};
		      this.filters = [];
		      this.data = {};
		      if (!pathOrLoader) {
		        throw new Error('You have to set path to base directory or to config file or loader.');
		      }
		      if (typeof pathOrLoader === 'string') {
		        if (pathOrLoader.charAt(0) === '.' && isBrowser) {
		          throw new Error('Relative paths to dictionaries is not supported in browser.');
		        }
		        if (pathOrLoader.charAt(0) === '.') {
		          stack = callsite();
		          pathOrLoader = path.join(path.dirname(stack[1].getFileName()), pathOrLoader);
		        }
		        pathOrLoader = path.normalize(pathOrLoader);
		        config = {
		          path: pathOrLoader,
		          loader: 'Json'
		        };
		        if (pathOrLoader.match(/\.json$/) !== null) {
		          _config = require(pathOrLoader);
		          if (typeof _config.path !== 'undefined') {
		            config.path = _config.path;
		          }
		          if (typeof _config.loader !== 'undefined') {
		            config.loader = _config.loader;
		          }
		          if (config.path.charAt(0) === '.') {
		            config.path = path.join(path.dirname(pathOrLoader), config.path);
		          }
		        }
		        pathOrLoader = new (require('./Loaders/' + config.loader))(config.path);
		      }
		      this.setLoader(pathOrLoader);
		      for (language in pluralForms) {
		        data = pluralForms[language];
		        this.addPluralForm(language, data.count, data.form);
		      }
		    }
		
		    Translator.prototype.expand = function(main) {
		      var _this = this;
		      if (main == null) {
		        main = null;
		      }
		      if (main === null) {
		        main = isBrowser ? window : global;
		      }
		      main._ = function() {
		        return _this.translate.apply(_this, arguments);
		      };
		      main._m = function() {
		        return _this.translateMap.apply(_this, arguments);
		      };
		      main._p = function() {
		        return _this.translatePairs.apply(_this, arguments);
		      };
		      return main;
		    };
		
		    Translator.prototype.setLoader = function(loader) {
		      if (!(loader instanceof Loader)) {
		        throw new Error('Loader must be an instance of translator/Loaders/Loader.');
		      }
		      return this.loader = loader;
		    };
		
		    Translator.prototype.invalidate = function() {
		      return this.data = {};
		    };
		
		    Translator.prototype.setCacheStorage = function(cacheStorage) {
		      if (!cacheStorage instanceof Storage) {
		        throw new Error('Cache storage must be an instance of cache-storage/Storage/Storage.');
		      }
		      return this.cache = new Cache(cacheStorage, 'translator');
		    };
		
		    Translator.prototype.addPluralForm = function(language, count, form) {
		      this.plurals[language] = {
		        count: count,
		        form: form
		      };
		      return this;
		    };
		
		    Translator.prototype.addReplacement = function(search, replacement) {
		      this.replacements[search] = replacement;
		      return this;
		    };
		
		    Translator.prototype.removeReplacement = function(search) {
		      if (typeof this.replacements[search] === 'undefined') {
		        throw new Error('Replacement ' + search + ' was not found.');
		      }
		      delete this.replacements[search];
		      return this;
		    };
		
		    Translator.prototype.addFilter = function(fn) {
		      this.filters.push(fn);
		      return this;
		    };
		
		    Translator.prototype.applyFilters = function(translation) {
		      var filter, i, t, _i, _j, _len, _len1, _ref;
		      if (Object.prototype.toString.call(translation) === '[object Array]') {
		        for (i = _i = 0, _len = translation.length; _i < _len; i = ++_i) {
		          t = translation[i];
		          translation[i] = this.applyFilters(t);
		        }
		        return translation;
		      }
		      _ref = this.filters;
		      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
		        filter = _ref[_j];
		        translation = filter(translation);
		      }
		      return translation;
		    };
		
		    Translator.prototype.loadCategory = function(_path, name, language) {
		      var categoryName, conds, data, file;
		      if (language == null) {
		        language = this.language;
		      }
		      categoryName = _path + '/' + name;
		      if (typeof this.data[categoryName] === 'undefined') {
		        if (this.cache === null) {
		          data = this.loader.load(_path, name, language);
		          data = this.normalizeTranslations(data);
		        } else {
		          data = this.cache.load(language + ':' + categoryName);
		          if (data === null) {
		            data = this.loader.load(_path, name, language);
		            data = this.normalizeTranslations(data);
		            conds = {};
		            if (typeof window === 'undefined' || (typeof window !== 'undefined' && window.require.simq === true && typeof window.require.version !== 'undefined' && parseInt(window.require.version.replace(/\./g, '')) >= 510)) {
		              _path = this.loader.getFileSystemPath(_path, name, language);
		              if (_path !== null) {
		                conds.files = [_path];
		              }
		            }
		            this.cache.save(language + ':' + categoryName, data, conds);
		          } else {
		            file = this.loader.load(_path, name, language);
		            data = this.normalizeTranslations(file);
		          }
		        }
		        this.data[categoryName] = data;
		      }
		      return this.data[categoryName];
		    };
		
		    Translator.prototype.normalizeTranslations = function(translations) {
		      var buf, list, match, name, result, sub, t, translation, _i, _j, _len, _len1;
		      result = {};
		      for (name in translations) {
		        translation = translations[name];
		        list = false;
		        if ((match = name.match(/^--\s(.*)/)) !== null) {
		          name = match[1];
		          list = true;
		        }
		        if (typeof translation === 'string') {
		          result[name] = [translation];
		        } else if (Object.prototype.toString.call(translation) === '[object Array]') {
		          result[name] = [];
		          for (_i = 0, _len = translation.length; _i < _len; _i++) {
		            t = translation[_i];
		            if (typeof t === 'object') {
		              buf = [];
		              for (_j = 0, _len1 = t.length; _j < _len1; _j++) {
		                sub = t[_j];
		                if (/^\#.*\#$/.test(sub) === false) {
		                  buf.push(sub);
		                }
		              }
		              result[name].push(buf);
		            } else {
		              if (/^\#.*\#$/.test(t) === false) {
		                if (list === true && typeof t !== 'object') {
		                  t = [t];
		                }
		                result[name].push(t);
		              }
		            }
		          }
		        }
		      }
		      return result;
		    };
		
		    Translator.prototype.hasTranslation = function(message, language) {
		      if (language == null) {
		        language = this.language;
		      }
		      return this.findTranslation(message, language) !== null;
		    };
		
		    Translator.prototype.findTranslation = function(message, language) {
		      var data, info;
		      if (language == null) {
		        language = this.language;
		      }
		      info = this.getMessageInfo(message);
		      data = this.loadCategory(info.path, info.category, language);
		      if (typeof data[info.name] === 'undefined') {
		        return null;
		      } else {
		        return data[info.name];
		      }
		    };
		
		    Translator.prototype.translate = function(message, count, args) {
		      var found, language, match, num, params, translation;
		      if (count == null) {
		        count = null;
		      }
		      if (args == null) {
		        args = {};
		      }
		      params = Args(arguments, [Args.any, Args.number(null), Args.object({})]);
		      message = params[0];
		      count = params[1];
		      args = params[2];
		      language = this.language;
		      found = false;
		      if (typeof message !== 'string') {
		        return message;
		      }
		      if (count !== null) {
		        args.count = count;
		      }
		      if ((match = message.match(/^\:(.*)\:$/)) !== null) {
		        message = match[1];
		        if ((match = message.match(/^[a-z]+\|(.*)$/)) !== null) {
		          message = match[1];
		        }
		      } else {
		        if ((match = message.match(/^([a-z]+)\|(.*)$/)) !== null) {
		          language = match[1];
		          message = match[2];
		        }
		        if (language === null) {
		          throw new Error('You have to set language.');
		        }
		        num = null;
		        if ((match = message.match(/(.+)\[(\d+)\]$/)) !== null) {
		          message = match[1];
		          num = parseInt(match[2]);
		        }
		        message = this.applyReplacements(message, args);
		        translation = this.findTranslation(message, language);
		        found = this.hasTranslation(message, language);
		        if (num !== null) {
		          if (!this.isList(translation)) {
		            throw new Error('Translation ' + message + ' is not a list.');
		          }
		          if (typeof translation[num] === 'undefined') {
		            throw new Error('Item ' + num + ' was not found in ' + message + ' translation.');
		          }
		          translation = translation[num];
		        }
		        if (translation !== null) {
		          message = this.pluralize(message, translation, count, language);
		        }
		      }
		      message = this.prepareTranslation(message, args);
		      if (found) {
		        message = this.applyFilters(message);
		      }
		      return message;
		    };
		
		    Translator.prototype.translatePairs = function(message, key, value, count, args) {
		      var i, k, result, _i, _len;
		      if (count == null) {
		        count = null;
		      }
		      if (args == null) {
		        args = {};
		      }
		      key = "" + message + "." + key;
		      value = "" + message + "." + value;
		      key = this.translate(key, count, args);
		      value = this.translate(value, count, args);
		      if (Object.prototype.toString.call(key) !== '[object Array]' || Object.prototype.toString.call(value) !== '[object Array]') {
		        throw new Error('Translations are not arrays.');
		      }
		      if (key.length !== value.length) {
		        throw new Error('Keys and values translations have not got the same length.');
		      }
		      result = {};
		      for (i = _i = 0, _len = key.length; _i < _len; i = ++_i) {
		        k = key[i];
		        result[k] = value[i];
		      }
		      return result;
		    };
		
		    Translator.prototype.translateMap = function(list, count, args, base) {
		      var i, k, m, params, type, _i, _len;
		      if (count == null) {
		        count = null;
		      }
		      if (args == null) {
		        args = {};
		      }
		      if (base == null) {
		        base = null;
		      }
		      type = Object.prototype.toString.call(list);
		      if (type !== '[object Array]' && type !== '[object Object]') {
		        throw new Error('Translate map is only for arrays and objects.');
		      }
		      params = Args(arguments, [Args.oneOf([Args.array, Args.object]), Args.number(null), Args.object({}), Args.string(null)]);
		      list = params[0];
		      count = params[1];
		      args = params[2];
		      base = params[3];
		      base = base !== null ? base + '.' : '';
		      if (type === '[object Array]') {
		        for (i = _i = 0, _len = list.length; _i < _len; i = ++_i) {
		          m = list[i];
		          list[i] = this.translate(base + m, count, args);
		        }
		      } else {
		        for (k in list) {
		          m = list[k];
		          list[k] = this.translate(base + m, count, args);
		        }
		      }
		      return list;
		    };
		
		    Translator.prototype.isList = function(translation) {
		      return Object.prototype.toString.call(translation[0]) === '[object Array]';
		    };
		
		    Translator.prototype.pluralize = function(message, translation, count, language) {
		      var n, plural, pluralForm, result, t, _i, _j, _len, _len1;
		      if (count == null) {
		        count = null;
		      }
		      if (language == null) {
		        language = this.language;
		      }
		      if (count !== null) {
		        if (typeof translation[0] === 'string') {
		          pluralForm = 'n=' + count + ';plural=+(' + this.plurals[language].form + ');';
		          n = null;
		          plural = null;
		          eval(pluralForm);
		          message = plural !== null && typeof translation[plural] !== 'undefined' ? translation[plural] : translation[0];
		        } else {
		          result = [];
		          for (_i = 0, _len = translation.length; _i < _len; _i++) {
		            t = translation[_i];
		            result.push(this.pluralize(message, t, count, language));
		          }
		          message = result;
		        }
		      } else {
		        if (typeof translation[0] === 'string') {
		          message = translation[0];
		        } else {
		          message = [];
		          for (_j = 0, _len1 = translation.length; _j < _len1; _j++) {
		            t = translation[_j];
		            message.push(t[0]);
		          }
		        }
		      }
		      return message;
		    };
		
		    Translator.prototype.prepareTranslation = function(message, args) {
		      var m, result, _i, _len;
		      if (args == null) {
		        args = {};
		      }
		      if (typeof message === 'string') {
		        message = this.applyReplacements(message, args);
		      } else {
		        result = [];
		        for (_i = 0, _len = message.length; _i < _len; _i++) {
		          m = message[_i];
		          result.push(this.prepareTranslation(m, args));
		        }
		        message = result;
		      }
		      return message;
		    };
		
		    Translator.prototype.applyReplacements = function(message, args) {
		      var name, pattern, replacements, value;
		      if (args == null) {
		        args = {};
		      }
		      replacements = this.replacements;
		      for (name in args) {
		        value = args[name];
		        replacements[name] = value;
		      }
		      for (name in replacements) {
		        value = replacements[name];
		        if (value !== false) {
		          pattern = new RegExp('%' + name + '%', 'g');
		          message = message.replace(pattern, value);
		        }
		      }
		      return message;
		    };
		
		    Translator.prototype.getMessageInfo = function(message) {
		      var category, name, num, result, _path;
		      num = message.lastIndexOf('.');
		      _path = message.substr(0, num);
		      name = message.substr(num + 1);
		      num = _path.lastIndexOf('.');
		      category = _path.substr(num + 1);
		      _path = _path.substr(0, num).replace(/\./g, '/');
		      result = {
		        path: _path,
		        category: category,
		        name: name
		      };
		      return result;
		    };
		
		    return Translator;
		
		  })();
		
		  module.exports = Translator;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Cache.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Cache.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Cache.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Cache.js';
		var __dirname = 'cache-storage/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Cache.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Cache, isFunction;
		
		  isFunction = function(obj) {
		    return Object.prototype.toString.call(obj) === '[object Function]';
		  };
		
		  Cache = (function() {
		    Cache.FILES = 'files';
		
		    Cache.TAGS = 'tags';
		
		    Cache.EXPIRE = 'expire';
		
		    Cache.ITEMS = 'items';
		
		    Cache.PRIORITY = 'priority';
		
		    Cache.ALL = 'all';
		
		    Cache.TIME_FORMAT = 'YYYY-MM-DD HH:mm';
		
		    Cache.fs = null;
		
		    Cache.prototype.storage = null;
		
		    Cache.prototype.async = null;
		
		    Cache.prototype.namespace = null;
		
		    function Cache(storage, namespace) {
		      this.storage = storage;
		      this.namespace = namespace;
		      if (!(this.storage instanceof require('./Storage/Storage'))) {
		        throw new Error('Cache: storage must be instance of cache-storage/Storage/Storage');
		      }
		      this.async = this.storage.async;
		      this.storage.cache = this;
		    }
		
		    Cache.mockFs = function(tree, info) {
		      var FS;
		      if (tree == null) {
		        tree = {};
		      }
		      if (info == null) {
		        info = {};
		      }
		      FS = require('fs-mock');
		      Cache.fs = new FS(tree, info);
		      return Cache.fs;
		    };
		
		    Cache.restoreFs = function() {
		      if (typeof window !== 'undefined') {
		        throw new Error('Testing with fs module is not allowed in browser.');
		      }
		      return Cache.fs = require('fs');
		    };
		
		    Cache.getFs = function() {
		      if (Cache.fs === null) {
		        Cache.restoreFs();
		      }
		      return Cache.fs;
		    };
		
		    Cache.prototype.generateKey = function(key) {
		      var ch, hash, i, max, _i;
		      hash = 0;
		      if (key.length === 0) {
		        return hash;
		      }
		      max = key.length - 1;
		      for (i = _i = 0; 0 <= max ? _i <= max : _i >= max; i = 0 <= max ? ++_i : --_i) {
		        ch = key.charCodeAt(i);
		        hash = ((hash << 5) - hash) + ch;
		        hash |= 0;
		      }
		      return hash;
		    };
		
		    Cache.prototype.load = function(key, fallback, fn) {
		      var data,
		        _this = this;
		      if (fallback == null) {
		        fallback = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (this.async && arguments.length === 2) {
		        fn = fallback;
		        fallback = null;
		      }
		      if (this.async) {
		        return this.storage.read(this.generateKey(key), function(err, data) {
		          if (err) {
		            return fn(err, null);
		          } else if (data === null && fallback !== null) {
		            return _this.save(key, fallback, function(err, data) {
		              return fn(err, data);
		            });
		          } else {
		            return fn(null, data);
		          }
		        });
		      } else {
		        data = this.storage.read(this.generateKey(key));
		        if (data === null && fallback !== null) {
		          return this.save(key, fallback);
		        }
		        return data;
		      }
		    };
		
		    Cache.prototype.save = function(key, data, dependencies, fn) {
		      var _this = this;
		      if (dependencies == null) {
		        dependencies = {};
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(dependencies)) {
		        fn = dependencies;
		        dependencies = {};
		      }
		      key = this.generateKey(key);
		      if (isFunction(data)) {
		        data = data();
		      }
		      if (this.async) {
		        if (data === null) {
		          this.storage.remove(key, function(err) {
		            if (err) {
		              return fn(err, null);
		            } else {
		              return fn(null, data);
		            }
		          });
		        } else {
		          this.storage.parseDependencies(dependencies, function(err, dependencies) {
		            if (err) {
		              return fn(err, null);
		            } else {
		              return _this.storage.write(key, data, dependencies, function(err) {
		                if (err) {
		                  return fn(err, null);
		                } else {
		                  return fn(null, data);
		                }
		              });
		            }
		          });
		        }
		      } else {
		        if (data === null) {
		          this.storage.remove(key);
		        } else {
		          this.storage.write(key, data, this.storage.parseDependencies(dependencies));
		        }
		      }
		      return data;
		    };
		
		    Cache.prototype.remove = function(key, fn) {
		      if (fn == null) {
		        fn = null;
		      }
		      return this.save(key, null, fn);
		    };
		
		    Cache.prototype.clean = function(conditions, fn) {
		      if (fn == null) {
		        fn = null;
		      }
		      this.storage.clean(conditions, fn);
		      return this;
		    };
		
		    return Cache;
		
		  })();
		
		  module.exports = Cache;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Storage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Storage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Storage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Storage.js';
		var __dirname = 'cache-storage/lib/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Storage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Storage;
		
		  Storage = (function() {
		    Storage.prototype.async = false;
		
		    Storage.prototype.cache = null;
		
		    function Storage() {
		      if (!(this instanceof Storage)) {
		        if (typeof this.read === 'undefined' || typeof this.write === 'undefined' || typeof this.remove === 'undefined' || typeof this.removeAll === 'undefined' || typeof this.getMeta === 'undefined') {
		          throw new Error('Cache storage: you have to implement methods read, write, remove, removeAll and getMeta.');
		        }
		      }
		    }
		
		    Storage.prototype.checkFilesSupport = function() {
		      var isWindow, version;
		      isWindow = typeof window === 'undefined' ? false : true;
		      if (isWindow && window.require.simq !== true) {
		        throw new Error('Files meta information can be used in browser only with simq.');
		      }
		      if (isWindow) {
		        version = window.require.version;
		        if (typeof version === 'undefined' || parseInt(version.replace(/\./g, '')) < 510) {
		          throw new Error('File method information is supported only with simq@5.1.0 and later.');
		        }
		      }
		    };
		
		    return Storage;
		
		  })();
		
		  module.exports = Storage;
		
		}).call(this);
		
	
	}, 'normalize-arguments/lib/Args.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'normalize-arguments/lib/Args.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'normalize-arguments/lib/Args.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'normalize-arguments/lib/Args.js';
		var __dirname = 'normalize-arguments/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'normalize-arguments/lib/Args.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var args, count, emptyArgument, expandArguments, exportFunc, fn, isFunction, name, type, types;
		
		  types = {
		    string: '[object String]',
		    number: '[object Number]',
		    'boolean': '[object Boolean]',
		    array: '[object Array]',
		    object: '[object Object]',
		    fn: '[object Function]'
		  };
		
		  exportFunc = {
		    string: function(d) {
		      return {
		        type: 'string',
		        d: d
		      };
		    },
		    number: function(d) {
		      return {
		        type: 'number',
		        d: d
		      };
		    },
		    'boolean': function(d) {
		      return {
		        type: 'boolean',
		        d: d
		      };
		    },
		    array: function(d) {
		      return {
		        type: 'array',
		        d: d
		      };
		    },
		    object: function(d) {
		      return {
		        type: 'object',
		        d: d
		      };
		    },
		    any: function(d) {
		      return {
		        type: 'any',
		        d: d
		      };
		    },
		    fn: function(d) {
		      return {
		        type: 'fn',
		        d: d
		      };
		    },
		    oneOf: function(list, d) {
		      var i, readable, t, type, _i, _len;
		      if (d == null) {
		        d = null;
		      }
		      readable = [];
		      for (i = _i = 0, _len = list.length; _i < _len; i = ++_i) {
		        type = list[i];
		        t = type().type;
		        list[i] = types[t];
		        readable.push(t);
		      }
		      return {
		        type: 'oneOf',
		        d: d,
		        dCalled: arguments.length === 2,
		        types: list,
		        readable: readable
		      };
		    }
		  };
		
		  emptyArgument = {};
		
		  type = Object.prototype.toString;
		
		  isFunction = function(v) {
		    return type.call(v) === '[object Function]';
		  };
		
		  count = function(num) {
		    switch (num) {
		      case 1:
		        return 'st';
		      case 2:
		        return 'nd';
		      case 3:
		        return 'rd';
		      default:
		        return 'th';
		    }
		  };
		
		  expandArguments = function(params, expected) {
		    var actual, e, i, _i, _len;
		    if (params == null) {
		      params = [];
		    }
		    if (expected == null) {
		      expected = [];
		    }
		    for (i = _i = 0, _len = expected.length; _i < _len; i = ++_i) {
		      e = expected[i];
		      if (isFunction(e)) {
		        e = e();
		      }
		      actual = type.call(params[i]);
		      if (params[i] !== null && e.type !== 'any' && ((e.type === 'oneOf' && e.types.indexOf(actual) === -1) || (e.type !== 'oneOf' && types[e.type] !== actual))) {
		        params.splice(i, 0, emptyArgument);
		      }
		    }
		    return params;
		  };
		
		  args = function(params, expected) {
		    var e, expect, fn, i, last, must, num, param, _i, _len;
		    if (params == null) {
		      params = [];
		    }
		    if (expected == null) {
		      expected = [];
		    }
		    if (type.call(params) === '[object Arguments]') {
		      params = Array.prototype.slice.call(params);
		    }
		    params = expandArguments(params, expected);
		    for (i = _i = 0, _len = params.length; _i < _len; i = ++_i) {
		      param = params[i];
		      expect = null;
		      e = expected[i];
		      if (typeof e !== 'undefined') {
		        expect = isFunction(e) ? e().type : e.type;
		      }
		      if (param === emptyArgument) {
		        fn = isFunction(e);
		        if (fn || (!fn && e.type === 'oneOf' && e.dCalled === false)) {
		          if (fn) {
		            must = e().type;
		          } else {
		            if (e.readable.length === 1) {
		              must = e.readable[0];
		            } else {
		              last = e.readable.pop();
		              must = e.readable.join(', ') + ' or ' + last;
		            }
		          }
		          num = i + 1;
		          throw new Error(num + count(num) + ' argument must be ' + must);
		        }
		        params[i] = e.d;
		      }
		    }
		    return params;
		  };
		
		  for (name in exportFunc) {
		    fn = exportFunc[name];
		    args[name] = fn;
		  }
		
		  module.exports = args;
		
		}).call(this);
		
	
	}, '/lib/node/path.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/node/path.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/node/path.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/node/path.js';
		var __dirname = '/lib/node';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/node/path.js'], env: {}};
	
		/** code **/
		// Taken from https://github.com/joyent/node/blob/master/lib/path.js
		
		
		
		// resolves . and .. elements in a path array with directory names there
		// must be no slashes, empty elements, or device names (c:\) in the array
		// (so also no leading and trailing slashes - it does not distinguish
		// relative and absolute paths)
		function normalizeArray(parts, allowAboveRoot) {
			// if the path tries to go above the root, `up` ends up > 0
			var up = 0;
			for (var i = parts.length - 1; i >= 0; i--) {
				var last = parts[i];
				if (last === '.') {
					parts.splice(i, 1);
				} else if (last === '..') {
					parts.splice(i, 1);
					up++;
				} else if (up) {
					parts.splice(i, 1);
					up--;
				}
			}
		
			// if the path is allowed to go above the root, restore leading ..s
			if (allowAboveRoot) {
				for (; up--; up) {
					parts.unshift('..');
				}
			}
		
			return parts;
		}
		
		var splitPathRe =
			/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
		var splitPath = function(filename) {
			return splitPathRe.exec(filename).slice(1);
		};
		
		var isBrowser = typeof window !== 'undefined';
		
		if (!isBrowser) {
			var path = require('path');
		}
		
		exports.isAbsolute = function(_path) {
			if (isBrowser) {
				return _path.charAt(0) === '/';
			} else {
				return path.isAbsolute.call({}, _path);
			}
		};
		
		exports.normalize = function(_path) {
			if (isBrowser) {
				var isAbsolute = exports.isAbsolute(_path),
					trailingSlash = _path[_path.length - 1] === '/',
					segments = _path.split('/'),
					nonEmptySegments = [];
		
				// Normalize the path
				for (var i = 0; i < segments.length; i++) {
					if (segments[i]) {
						nonEmptySegments.push(segments[i]);
					}
				}
				_path = normalizeArray(nonEmptySegments, !isAbsolute).join('/');
		
				if (!_path && !isAbsolute) {
					_path = '.';
				}
				if (_path && trailingSlash) {
					_path += '/';
				}
		
				return (isAbsolute ? '/' : '') + _path;
			} else {
				return path.normalize.call({}, _path);
			}
		};
		
		exports.join = function() {
			if (isBrowser) {
				var _path = '';
				for (var i = 0; i < arguments.length; i++) {
					var segment = arguments[i];
					if (typeof segment != 'string') {
						throw new TypeError('Arguments to path.join must be strings');
					}
					if (segment) {
						if (!_path) {
							_path += segment;
						} else {
							_path += '/' + segment;
						}
					}
				}
				return exports.normalize(_path);
			} else {
				return path.join.apply({}, arguments);
			}
		};
		
		exports.dirname = function(_path) {
			if (isBrowser) {
				var result = splitPath(_path),
					root = result[0],
					dir = result[1];
		
				if (!root && !dir) {
					// No dirname whatsoever
					return '.';
				}
		
				if (dir) {
					// It has a dirname, strip trailing slash
					dir = dir.substr(0, dir.length - 1);
				}
		
				return root + dir;
			} else {
				return path.dirname.call({}, _path);
			}
		};
	
	}, '/lib/pluralForms.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/pluralForms.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/pluralForms.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/pluralForms.json';
		var __dirname = '/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/pluralForms.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"ach": {"count": 2, "form": "(n > 1)"},
			"af": {"count": 2, "form": "(n != 1)"},
			"ak": {"count": 2, "form": "(n > 1)"},
			"am": {"count": 2, "form": "(n > 1)"},
			"an": {"count": 2, "form": "(n != 1)"},
			"ar": {"count": 2, "form": "(n==0 ? 0 : (n==1 ? 1 : (n==2 ? 2 : (n%100>=3 && n%100<=10 ? 3 : (n%100>=11 ? 4 : 5)))))"},
			"arn": {"count": 2, "form": "(n > 1)"},
			"ast": {"count": 2, "form": "(n != 1)"},
			"ay": {"count": 2, "form": "0"},
			"az": {"count": 2, "form": "(n != 1)"},
		
			"be": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"bg": {"count": 2, "form": "(n != 1)"},
			"bn": {"count": 2, "form": "(n != 1)"},
			"bo": {"count": 1, "form": "0"},
			"br": {"count": 2, "form": "(n > 1)"},
			"brx": {"count": 2, "form": "(n != 1)"},
			"bs": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
		
			"ca": {"count": 2, "form": "(n != 1)"},
			"cgg": {"count": 1, "form": "0"},
			"cs": {"count": 3, "form": "(n==1) ? 0 : ((n>=2 && n<=4) ? 1 : 2)"},
			"csb": {"count": 4, "form": "n==1 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)"},
			"cy": {"count": 4, "form": "(n==1) ? 0 : ((n==2) ? 1 : ((n != 8 && n != 11) ? 2 : 3))"},
		
			"da": {"count": 2, "form": "(n != 1)"},
			"de": {"count": 2, "form": "(n != 1)"},
			"doi": {"count": 2, "form": "(n != 1)"},
			"dz": {"count": 1, "form": "0"},
		
			"el": {"count": 2, "form": "(n != 1)"},
			"en": {"count": 2, "form": "(n != 1)"},
			"eo": {"count": 2, "form": "(n != 1)"},
			"es": {"count": 2, "form": "(n != 1)"},
			"es_AR": {"count": 2, "form": "(n != 1)"},
			"et": {"count": 2, "form": "(n != 1)"},
			"eu": {"count": 2, "form": "(n != 1)"},
		
			"fa": {"count": 1, "form": "0"},
			"ff": {"count": 2, "form": "(n != 1)"},
			"fi": {"count": 2, "form": "(n != 1)"},
			"fil": {"count": 2, "form": "(n > 1)"},
			"fo": {"count": 2, "form": "(n != 1)"},
			"fr": {"count": 2, "form": "(n > 1)"},
			"fur": {"count": 2, "form": "(n != 1)"},
			"fy": {"count": 2, "form": "(n != 1)"},
		
			"ga": {"count": 5, "form": "n==1 ? 0 : (n==2 ? 1 : (n<7 ? 2 : (n<11 ? 3 : 4)))"},
			"gd": {"count": 4, "form": "(n==1 || n==11) ? 0 : ((n==2 || n==12) ? 1 : ((n > 2 && n < 20) ? 2 : 3))"},
			"gl": {"count": 2, "form": "(n != 1)"},
			"gu": {"count": 2, "form": "(n != 1)"},
			"gun": {"count": 2, "form": "(n > 1)"},
		
			"ha": {"count": 2, "form": "(n != 1)"},
			"he": {"count": 2, "form": "(n != 1)"},
			"hi": {"count": 2, "form": "(n != 1)"},
			"hne": {"count": 2, "form": "(n != 1)"},
			"hy": {"count": 2, "form": "(n != 1)"},
			"hr": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"hu": {"count": 2, "form": "(n != 1)"},
		
			"ia": {"count": 2, "form": "(n != 1)"},
			"id": {"count": 1, "form": "0"},
			"is": {"count": 2, "form": "(n%10!=1 || n%100==11)"},
			"it": {"count": 2, "form": "(n != 1)"},
		
			"ja": {"count": 1, "form": "0"},
			"jbo": {"count": 1, "form": "0"},
			"jv": {"count": 2, "form": "(n != 0)"},
		
			"ka": {"count": 1, "form": "0"},
			"kk": {"count": 1, "form": "0"},
			"km": {"count": 1, "form": "0"},
			"kn": {"count": 2, "form": "(n != 1)"},
			"ko": {"count": 1, "form": "0"},
			"ku": {"count": 2, "form": "(n != 1)"},
			"kw": {"count": 4, "form": "(n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3"},
			"ky": {"count": 1, "form": "0"},
		
			"lb": {"count": 2, "form": "(n != 1)"},
			"ln": {"count": 2, "form": "(n > 1)"},
			"lo": {"count": 1, "form": "0"},
			"lt": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && (n%100<10 or n%100>=20) ? 1 : 2))"},
			"lv": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n != 0 ? 1 : 2))"},
		
			"mai": {"count": 2, "form": "(n != 1)"},
			"mfe": {"count": 2, "form": "(n > 1)"},
			"mg": {"count": 2, "form": "(n > 1)"},
			"mi": {"count": 2, "form": "(n > 1)"},
			"ml": {"count": 2, "form": "(n != 1)"},
			"mn": {"count": 2, "form": "(n != 1)"},
			"mni": {"count": 2, "form": "(n != 1)"},
			"mnk": {"count": 3, "form": "(n==0 ? 0 : (n==1 ? 1 : 2))"},
			"mr": {"count": 2, "form": "(n != 1)"},
			"ms": {"count": 1, "form": "0"},
			"mt": {"count": 4, "form": "(n==1 ? 0 : (n==0 || ( n%100>1 && n%100<11) ? 1 : ((n%100>10 && n%100<20 ) ? 2 : 3)))"},
			"my": {"count": 1, "form": "0"},
		
			"nah": {"count": 2, "form": "(n != 1)"},
			"nap": {"count": 2, "form": "(n != 1)"},
			"nb": {"count": 2, "form": "(n != 1)"},
			"ne": {"count": 2, "form": "(n != 1)"},
			"nl": {"count": 2, "form": "(n != 1)"},
			"se": {"count": 2, "form": "(n != 1)"},
			"nn": {"count": 2, "form": "(n != 1)"},
			"no": {"count": 2, "form": "(n != 1)"},
			"nso": {"count": 2, "form": "(n != 1)"},
		
			"oc": {"count": 2, "form": "(n > 1)"},
			"or": {"count": 2, "form": "(n != 1)"},
		
			"ps": {"count": 2, "form": "(n != 1)"},
			"pa": {"count": 2, "form": "(n != 1)"},
			"pap": {"count": 2, "form": "(n != 1)"},
			"pl": {"count": 3, "form": "(n==1 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"pms": {"count": 2, "form": "(n != 1)"},
			"pt": {"count": 2, "form": "(n != 1)"},
			"pt_BR": {"count": 2, "form": "(n != 1)"},
		
			"rm": {"count": 2, "form": "(n != 1)"},
			"ro": {"count": 3, "form": "(n==1 ? 0 : ((n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2))"},
			"ru": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"rw": {"count": 2, "form": "(n != 1)"},
		
			"sah": {"count": 1, "form": "0"},
			"sat": {"count": 2, "form": "(n != 1)"},
			"sco": {"count": 2, "form": "(n != 1)"},
			"sd": {"count": 2, "form": "(n != 1)"},
			"si": {"count": 2, "form": "(n != 1)"},
			"sk": {"count": 3, "form": "(n==1) ? 0 : ((n>=2 && n<=4) ? 1 : 2)"},
			"sl": {"count": 4, "form": "(n%100==1 ? 1 : (n%100==2 ? 2 : (n%100==3 || n%100==4 ? 3 : 0)))"},
			"so": {"count": 2, "form": "(n != 1)"},
			"son": {"count": 2, "form": "(n != 1)"},
			"sq": {"count": 2, "form": "(n != 1)"},
			"sr": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"su": {"count": 1, "form": "0"},
			"sw": {"count": 2, "form": "(n != 1)"},
			"sv": {"count": 2, "form": "(n != 1)"},
		
			"ta": {"count": 2, "form": "(n != 1)"},
			"te": {"count": 2, "form": "(n != 1)"},
			"tg": {"count": 2, "form": "(n > 1)"},
			"ti": {"count": 2, "form": "(n > 1)"},
			"th": {"count": 1, "form": "0"},
			"tk": {"count": 2, "form": "(n != 1)"},
			"tr": {"count": 2, "form": "(n > 1)"},
			"tt": {"count": 1, "form": "0"},
		
			"ug": {"count": 1, "form": "0"},
			"uk": {"count": 3, "form": "(n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2))"},
			"ur": {"count": 2, "form": "(n != 1)"},
			"uz": {"count": 2, "form": "(n > 1)"},
		
			"vi": {"count": 1, "form": "0"},
		
			"wa": {"count": 2, "form": "(n > 1)"},
			"wo": {"count": 1, "form": "0"},
		
			"yo": {"count": 2, "form": "(n != 1)"},
		
			"zh": {"count": 1, "form": "0"}
		}
		}).call(this);
		
	
	}, '/lib/Loaders/Json.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/Loaders/Json.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/Loaders/Json.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/Loaders/Json.js';
		var __dirname = '/lib/Loaders';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/Loaders/Json.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Json, Loader, callsite, fs, isBrowser, path,
		    __hasProp = {}.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; };
		
		  Loader = require('./Loader');
		
		  path = require('../node/path');
		
		  isBrowser = typeof window !== 'undefined';
		
		  if (!isBrowser) {
		    callsite = require('callsite');
		    fs = require('fs');
		  }
		
		  Json = (function(_super) {
		    __extends(Json, _super);
		
		    Json.prototype.directory = '/app/lang';
		
		    function Json(directory) {
		      var stack;
		      this.directory = directory != null ? directory : this.directory;
		      if (this.directory.charAt(0) === '.' && isBrowser) {
		        throw new Error('Relative paths to dictionaries is not supported in browser.');
		      }
		      if (this.directory.charAt(0) === '.') {
		        stack = callsite();
		        this.directory = path.dirname(stack[1].getFileName());
		      }
		      if (!isBrowser) {
		        this.directory = path.normalize(this.directory);
		      }
		    }
		
		    Json.prototype.load = function(parent, name, language) {
		      var data, e, _path;
		      _path = this.getFileSystemPath(parent, name, language);
		      try {
		        data = require(_path);
		      } catch (_error) {
		        e = _error;
		        data = {};
		      }
		      return data;
		    };
		
		    Json.prototype.getFileSystemPath = function(parent, name, language) {
		      return this.directory + (parent !== '' ? '/' + parent : '') + ("/" + language + "." + name + ".json");
		    };
		
		    return Json;
		
		  })(Loader);
		
		  module.exports = Json;
		
		}).call(this);
		
	
	}, 'callsite/index.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'callsite/index.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'callsite/index.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'callsite/index.js';
		var __dirname = 'callsite';
		var process = {cwd: function() {return '/';}, argv: ['node', 'callsite/index.js'], env: {}};
	
		/** code **/
		
		module.exports = function(){
		  var orig = Error.prepareStackTrace;
		  Error.prepareStackTrace = function(_, stack){ return stack; };
		  var err = new Error;
		  Error.captureStackTrace(err, arguments.callee);
		  var stack = err.stack;
		  Error.prepareStackTrace = orig;
		  return stack;
		};
		
	
	}, 'fs-finder/lib/Finder.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'fs-finder/lib/Finder.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'fs-finder/lib/Finder.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'fs-finder/lib/Finder.js';
		var __dirname = 'fs-finder/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'fs-finder/lib/Finder.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Base, Finder, Helpers, compare, isFunction, moment, _ref,
		    __hasProp = {}.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; };
		
		  Base = require('./Base');
		
		  Helpers = require('./Helpers');
		
		  moment = require('moment');
		
		  compare = require('operator-compare');
		
		  isFunction = function(obj) {
		    return Object.prototype.toString.call(obj) === '[object Function]';
		  };
		
		  Finder = (function(_super) {
		    __extends(Finder, _super);
		
		    function Finder() {
		      _ref = Finder.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    Finder.TIME_FORMAT = 'YYYY-MM-DD HH:mm';
		
		    Finder["in"] = function(path) {
		      return new Finder(path);
		    };
		
		    Finder.from = function(path) {
		      return (new Finder(path)).recursively();
		    };
		
		    Finder.find = function(path, fn, type) {
		      if (fn == null) {
		        fn = null;
		      }
		      if (type == null) {
		        type = 'all';
		      }
		      path = Helpers.parseDirectory(path);
		      return (new Finder(path.directory)).recursively().find(path.mask, fn, type);
		    };
		
		    Finder.findFiles = function(path, fn) {
		      if (path == null) {
		        path = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(path)) {
		        fn = path;
		        path = null;
		      }
		      return Finder.find(path, fn, 'files');
		    };
		
		    Finder.findDirectories = function(path, fn) {
		      if (path == null) {
		        path = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(path)) {
		        fn = path;
		        path = null;
		      }
		      return Finder.find(path, fn, 'directories');
		    };
		
		    Finder.findFile = function(path, fn) {
		      if (path == null) {
		        path = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(path)) {
		        fn = path;
		        path = null;
		      }
		      return Finder.findFirst().find(path, fn, 'files');
		    };
		
		    Finder.findDirectory = function(path, fn) {
		      if (path == null) {
		        path = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(path)) {
		        fn = path;
		        path = null;
		      }
		      return Finder.findFirst().find(path, fn, 'directories');
		    };
		
		    Finder.prototype.find = function(mask, fn, type) {
		      var _ref1;
		      if (mask == null) {
		        mask = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (type == null) {
		        type = 'all';
		      }
		      if (isFunction(mask)) {
		        type = fn;
		        fn = mask;
		        mask = null;
		      }
		      mask = Helpers.normalizePattern(mask);
		      if (this.up === true || ((_ref1 = typeof this.up) === 'number' || _ref1 === 'string')) {
		        if (fn === null) {
		          return this.getPathsFromParentsSync(mask, type);
		        } else {
		          return this.getPathsFromParentsAsync(fn, mask, type);
		        }
		      } else {
		        if (fn === null) {
		          return this.getPathsSync(type, mask);
		        } else {
		          return this.getPathsAsync(fn, type, mask);
		        }
		      }
		    };
		
		    Finder.prototype.findFiles = function(mask, fn) {
		      if (mask == null) {
		        mask = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(mask)) {
		        fn = mask;
		        mask = null;
		      }
		      return this.find(mask, fn, 'files');
		    };
		
		    Finder.prototype.findDirectories = function(mask, fn) {
		      if (mask == null) {
		        mask = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(mask)) {
		        fn = mask;
		        mask = null;
		      }
		      return this.find(mask, fn, 'directories');
		    };
		
		    Finder.prototype.findFile = function(mask, fn) {
		      if (mask == null) {
		        mask = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(mask)) {
		        fn = mask;
		        mask = null;
		      }
		      return this.findFirst().find(mask, fn, 'files');
		    };
		
		    Finder.prototype.findDirectory = function(mask, fn) {
		      if (mask == null) {
		        mask = null;
		      }
		      if (fn == null) {
		        fn = null;
		      }
		      if (isFunction(mask)) {
		        fn = mask;
		        mask = null;
		      }
		      return this.findFirst().find(mask, fn, 'directories');
		    };
		
		    Finder.prototype.size = function(operation, value) {
		      this.filter(function(stat) {
		        return compare(stat.size, operation, value);
		      });
		      return this;
		    };
		
		    Finder.prototype.date = function(operation, value) {
		      this.filter(function(stat) {
		        var date;
		        switch (Object.prototype.toString.call(value)) {
		          case '[object String]':
		            date = moment(value, Finder.TIME_FORMAT);
		            break;
		          case '[object Object]':
		            date = moment().subtract(value);
		            break;
		          default:
		            throw new Error('Date format is not valid.');
		        }
		        return compare((new Date(stat.mtime)).getTime(), operation, date.valueOf());
		      });
		      return this;
		    };
		
		    return Finder;
		
		  })(Base);
		
		  module.exports = Finder;
		
		}).call(this);
		
	
	}, 'fs-finder/lib/Base.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'fs-finder/lib/Base.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'fs-finder/lib/Base.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'fs-finder/lib/Base.js';
		var __dirname = 'fs-finder/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'fs-finder/lib/Base.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Base, Helpers, Q, async, fs, path;
		
		  Helpers = require('./Helpers');
		
		  path = require('path');
		
		  fs = require('fs');
		
		  Q = require('q');
		
		  async = require('async');
		
		  Base = (function() {
		    Base.prototype.directory = null;
		
		    Base.prototype.recursive = false;
		
		    Base.prototype.excludes = null;
		
		    Base.prototype.filters = null;
		
		    Base.prototype.systemFiles = false;
		
		    Base.prototype.up = false;
		
		    Base.prototype._findFirst = false;
		
		    function Base(directory) {
		      directory = path.resolve(directory);
		      if (!fs.statSync(directory).isDirectory()) {
		        throw new Error("Path " + directory + " is not directory");
		      }
		      this.directory = directory;
		      this.excludes = [];
		      this.filters = [];
		    }
		
		    Base.mock = function(tree, info) {
		      var FS;
		      if (tree == null) {
		        tree = {};
		      }
		      if (info == null) {
		        info = {};
		      }
		      FS = require('fs-mock');
		      fs = new FS(tree, info);
		      return fs;
		    };
		
		    Base.restore = function() {
		      return fs = require('fs');
		    };
		
		    Base.prototype.recursively = function(recursive) {
		      this.recursive = recursive != null ? recursive : true;
		      return this;
		    };
		
		    Base.prototype.exclude = function(excludes, exactly) {
		      var exclude, result, _i, _len;
		      if (exactly == null) {
		        exactly = false;
		      }
		      if (typeof excludes === 'string') {
		        excludes = [excludes];
		      }
		      result = [];
		      for (_i = 0, _len = excludes.length; _i < _len; _i++) {
		        exclude = excludes[_i];
		        if (exactly) {
		          exclude = "<^>" + exclude + "<$>";
		        }
		        result.push(Helpers.normalizePattern(exclude));
		      }
		      this.excludes = this.excludes.concat(result);
		      return this;
		    };
		
		    Base.prototype.showSystemFiles = function(systemFiles) {
		      this.systemFiles = systemFiles != null ? systemFiles : true;
		      return this;
		    };
		
		    Base.prototype.lookUp = function(up) {
		      this.up = up != null ? up : true;
		      return this;
		    };
		
		    Base.prototype.findFirst = function(_findFirst) {
		      this._findFirst = _findFirst != null ? _findFirst : true;
		      return this;
		    };
		
		    Base.prototype.filter = function(fn) {
		      this.filters.push(fn);
		      return this;
		    };
		
		    Base.prototype.getPathsSync = function(type, mask, dir) {
		      var err, paths, read, result, stats, _i, _len, _path;
		      if (type == null) {
		        type = 'all';
		      }
		      if (mask == null) {
		        mask = null;
		      }
		      if (dir == null) {
		        dir = this.directory;
		      }
		      paths = [];
		      try {
		        read = fs.readdirSync(dir);
		      } catch (_error) {
		        err = _error;
		        if (this._findFirst === true) {
		          return null;
		        }
		        return paths;
		      }
		      for (_i = 0, _len = read.length; _i < _len; _i++) {
		        _path = read[_i];
		        _path = path.join(dir, _path);
		        if (!this.checkExcludes(_path) || !this.checkSystemFiles(_path)) {
		          continue;
		        }
		        try {
		          stats = fs.statSync(_path);
		        } catch (_error) {
		          err = _error;
		          continue;
		        }
		        switch (this.checkFile(_path, stats, mask, type)) {
		          case 0:
		            continue;
		          case 1:
		            if (this._findFirst === true) {
		              return _path;
		            }
		            paths.push(_path);
		        }
		        if (stats.isDirectory() && this.recursive === true) {
		          result = this.getPathsSync(type, mask, _path);
		          if (this._findFirst === true && typeof result === 'string') {
		            return result;
		          } else if (this._findFirst === true && result === null) {
		            continue;
		          } else {
		            paths = paths.concat(result);
		          }
		        }
		      }
		      if (this._findFirst === true) {
		        return null;
		      } else {
		        return paths;
		      }
		    };
		
		    Base.prototype.getPathsAsync = function(fn, type, mask, dir) {
		      var paths,
		        _this = this;
		      if (type == null) {
		        type = 'all';
		      }
		      if (mask == null) {
		        mask = null;
		      }
		      if (dir == null) {
		        dir = this.directory;
		      }
		      paths = [];
		      return fs.readdir(dir, function(err, read) {
		        var files, nextPaths, _i, _len, _path;
		        if (err) {
		          return fn(_this._findFirst === true ? null : paths);
		        } else {
		          nextPaths = [];
		          for (_i = 0, _len = read.length; _i < _len; _i++) {
		            _path = read[_i];
		            _path = path.join(dir, _path);
		            if (!_this.checkExcludes(_path) || !_this.checkSystemFiles(_path)) {
		              continue;
		            }
		            nextPaths.push(_path);
		          }
		          files = {};
		          return async.eachSeries(nextPaths, function(item, cb) {
		            return fs.stat(item, function(err, stats) {
		              if (!err) {
		                files[item] = stats;
		              }
		              return cb();
		            });
		          }, function() {
		            var file, stats, subDirectories;
		            subDirectories = [];
		            for (file in files) {
		              stats = files[file];
		              switch (_this.checkFile(file, stats, mask, type)) {
		                case 0:
		                  continue;
		                case 1:
		                  if (_this._findFirst === true) {
		                    fn(file);
		                    return null;
		                  }
		                  paths.push(file);
		              }
		              if (stats.isDirectory() && _this.recursive === true) {
		                subDirectories.push(file);
		              }
		            }
		            if (subDirectories.length === 0) {
		              return fn(_this._findFirst === true ? null : paths);
		            } else {
		              return async.eachSeries(subDirectories, function(item, cb) {
		                return _this.getPathsAsync(function(result) {
		                  if (_this._findFirst === true && typeof result === 'string') {
		                    fn(result);
		                    return cb(new Error('Fake error'));
		                  } else if (_this._findFirst === true && result === null) {
		                    return cb();
		                  } else {
		                    paths = paths.concat(result);
		                    return cb();
		                  }
		                }, type, mask, item);
		              }, function(err) {
		                if (!err) {
		                  return fn(paths);
		                }
		              });
		            }
		          });
		        }
		      });
		    };
		
		    Base.prototype.checkExcludes = function(_path) {
		      var exclude, _i, _len, _ref;
		      _ref = this.excludes;
		      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		        exclude = _ref[_i];
		        if ((new RegExp(exclude)).test(_path)) {
		          return false;
		        }
		      }
		      return true;
		    };
		
		    Base.prototype.checkSystemFiles = function(_path) {
		      if (this.systemFiles === false) {
		        if (path.basename(_path)[0] === '.' || _path.match(/~$/) !== null) {
		          return false;
		        }
		      }
		      return true;
		    };
		
		    Base.prototype.checkFilters = function(_path, stats) {
		      var filter, _i, _len, _ref;
		      _ref = this.filters;
		      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		        filter = _ref[_i];
		        if (!filter(stats, _path)) {
		          return false;
		        }
		      }
		      return true;
		    };
		
		    Base.prototype.checkFile = function(_path, stats, mask, type) {
		      if (type === 'all' || (type === 'files' && stats.isFile()) || (type === 'directories' && stats.isDirectory())) {
		        if (mask === null || (mask !== null && (new RegExp(mask, 'g')).test(_path))) {
		          if (!this.checkFilters(_path, stats)) {
		            return 0;
		          }
		          return 1;
		        }
		      }
		      return 2;
		    };
		
		    Base.prototype.getPathsFromParentsSync = function(mask, type) {
		      var Finder, breakAtEnd, finder, found, i, parentPath, parentPaths, previous, result, _i, _len;
		      if (mask == null) {
		        mask = null;
		      }
		      if (type == null) {
		        type = 'all';
		      }
		      Finder = require('./Finder');
		      parentPaths = Helpers.expandPath(this.directory);
		      result = [];
		      previous = null;
		      breakAtEnd = false;
		      for (i = _i = 0, _len = parentPaths.length; _i < _len; i = ++_i) {
		        parentPath = parentPaths[i];
		        if (this.up === true) {
		
		        } else if (typeof this.up === 'string' && this.up === parentPath) {
		          breakAtEnd = true;
		        } else if (typeof this.up === 'number' && this.up <= i) {
		          break;
		        }
		        finder = new Finder(parentPath);
		        finder.recursive = this.recursive;
		        finder.excludes = this.excludes;
		        finder.filters = this.filters;
		        finder.systemFiles = this.systemFiles;
		        finder._findFirst = this._findFirst === true;
		        if (previous !== null) {
		          finder.exclude(previous, true);
		        }
		        found = finder.getPathsSync(type, mask);
		        if (this._findFirst === true && typeof found === 'string') {
		          return found;
		        } else if (this._findFirst === true && found === null) {
		
		        } else if (found.length > 0) {
		          result = result.concat(found);
		        }
		        if (breakAtEnd) {
		          break;
		        }
		        previous = parentPath;
		      }
		      if (this._findFirst === true) {
		        return null;
		      } else {
		        return result;
		      }
		    };
		
		    Base.prototype.getPathsFromParentsAsync = function(fn, mask, type) {
		      var Finder, breakAtEnd, finder, finders, i, parentPath, parentPaths, previous, result, _i, _len,
		        _this = this;
		      if (mask == null) {
		        mask = null;
		      }
		      if (type == null) {
		        type = 'all';
		      }
		      Finder = require('./Finder');
		      parentPaths = Helpers.expandPath(this.directory);
		      result = [];
		      previous = null;
		      breakAtEnd = false;
		      finders = [];
		      for (i = _i = 0, _len = parentPaths.length; _i < _len; i = ++_i) {
		        parentPath = parentPaths[i];
		        if (this.up === true) {
		
		        } else if (typeof this.up === 'string' && this.up === parentPath) {
		          breakAtEnd = true;
		        } else if (typeof this.up === 'number' && this.up <= i) {
		          break;
		        }
		        finder = new Finder(parentPath);
		        finder.recursive = this.recursive;
		        finder.excludes = this.excludes;
		        finder.filters = this.filters;
		        finder.systemFiles = this.systemFiles;
		        finder._findFirst = this._findFirst === true;
		        if (previous !== null) {
		          finder.exclude(previous, true);
		        }
		        finders.push(finder);
		        if (breakAtEnd) {
		          break;
		        }
		        previous = parentPath;
		      }
		      return async.eachSeries(finders, function(finder, cb) {
		        return finder.getPathsAsync(function(found) {
		          if (_this._findFirst === true && typeof found === 'string') {
		            fn(found);
		            return cb(new Error('Fake error'));
		          } else if (_this._findFirst === true && found === null) {
		            return cb();
		          } else {
		            result = result.concat(found);
		            return cb();
		          }
		        }, type, mask);
		      }, function(err) {
		        if (!err) {
		          return fn(_this._findFirst === true ? null : result);
		        }
		      });
		    };
		
		    return Base;
		
		  })();
		
		  module.exports = Base;
		
		}).call(this);
		
	
	}, 'fs-finder/lib/Helpers.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'fs-finder/lib/Helpers.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'fs-finder/lib/Helpers.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'fs-finder/lib/Helpers.js';
		var __dirname = 'fs-finder/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'fs-finder/lib/Helpers.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Helpers, escape, path;
		
		  escape = require('escape-regexp');
		
		  path = require('path');
		
		  Helpers = (function() {
		    function Helpers() {}
		
		    Helpers.ASTERISK_PATTERN = '<[0-9a-zA-Z/.-_ ]+>';
		
		    Helpers.parseDirectory = function(_path) {
		      var asterisk, mask, regexp, splitter;
		      mask = null;
		      asterisk = _path.indexOf('*');
		      regexp = _path.indexOf('<');
		      if (asterisk !== -1 || regexp !== -1) {
		        if (asterisk === -1 || (asterisk !== -1 && regexp !== -1 && asterisk > regexp)) {
		          splitter = regexp;
		        } else if (regexp === -1 || (regexp !== -1 && asterisk !== -1 && asterisk <= regexp)) {
		          splitter = asterisk;
		        }
		        mask = _path.substr(splitter);
		        _path = _path.substr(0, splitter);
		      }
		      return {
		        directory: _path,
		        mask: mask
		      };
		    };
		
		    Helpers.normalizePattern = function(pattern) {
		      var i, part, parts, partsResult, replacement, _i, _len;
		      if (pattern === null) {
		        return null;
		      }
		      if (pattern === '*') {
		        return null;
		      }
		      pattern = pattern.replace(/\*/g, Helpers.ASTERISK_PATTERN);
		      parts = pattern.match(/<((?!(<|>)).)*>/g);
		      if (parts !== null) {
		        partsResult = {};
		        for (i = _i = 0, _len = parts.length; _i < _len; i = ++_i) {
		          part = parts[i];
		          partsResult['__<<' + i + '>>__'] = part.replace(/^<(.*)>$/, '$1');
		          pattern = pattern.replace(part, '__<<' + i + '>>__');
		        }
		        pattern = escape(pattern);
		        for (replacement in partsResult) {
		          part = partsResult[replacement];
		          pattern = pattern.replace(replacement, part);
		        }
		      } else {
		        pattern = escape(pattern);
		      }
		      return pattern;
		    };
		
		    Helpers.expandPath = function(_path, isFile) {
		      var current, result;
		      if (isFile == null) {
		        isFile = false;
		      }
		      if (isFile) {
		        _path = path.dirname(_path);
		      }
		      current = _path;
		      result = [current];
		      while (current !== '/') {
		        result.push(path.dirname(current));
		        current = path.dirname(current);
		      }
		      return result;
		    };
		
		    return Helpers;
		
		  })();
		
		  module.exports = Helpers;
		
		}).call(this);
		
	
	}, 'escape-regexp/index.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'escape-regexp/index.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'escape-regexp/index.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'escape-regexp/index.js';
		var __dirname = 'escape-regexp';
		var process = {cwd: function() {return '/';}, argv: ['node', 'escape-regexp/index.js'], env: {}};
	
		/** code **/
		
		/**
		 * Escape regexp special characters in `str`.
		 *
		 * @param {String} str
		 * @return {String}
		 * @api public
		 */
		
		module.exports = function(str){
		  return String(str).replace(/([.*+?=^!:${}()|[\]\/\\])/g, '\\$1');
		};
	
	}, 'q/q.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'q/q.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'q/q.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'q/q.js';
		var __dirname = 'q';
		var process = {cwd: function() {return '/';}, argv: ['node', 'q/q.js'], env: {}};
	
		/** code **/
		// vim:ts=4:sts=4:sw=4:
		/*!
		 *
		 * Copyright 2009-2012 Kris Kowal under the terms of the MIT
		 * license found at http://github.com/kriskowal/q/raw/master/LICENSE
		 *
		 * With parts by Tyler Close
		 * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
		 * at http://www.opensource.org/licenses/mit-license.html
		 * Forked at ref_send.js version: 2009-05-11
		 *
		 * With parts by Mark Miller
		 * Copyright (C) 2011 Google Inc.
		 *
		 * Licensed under the Apache License, Version 2.0 (the "License");
		 * you may not use this file except in compliance with the License.
		 * You may obtain a copy of the License at
		 *
		 * http://www.apache.org/licenses/LICENSE-2.0
		 *
		 * Unless required by applicable law or agreed to in writing, software
		 * distributed under the License is distributed on an "AS IS" BASIS,
		 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
		 * See the License for the specific language governing permissions and
		 * limitations under the License.
		 *
		 */
		
		(function (definition) {
		    // Turn off strict mode for this function so we can assign to global.Q
		    /* jshint strict: false */
		
		    // This file will function properly as a <script> tag, or a module
		    // using CommonJS and NodeJS or RequireJS module formats.  In
		    // Common/Node/RequireJS, the module exports the Q API and when
		    // executed as a simple <script>, it creates a Q global instead.
		
		    // Montage Require
		    if (typeof bootstrap === "function") {
		        bootstrap("promise", definition);
		
		    // CommonJS
		    } else if (typeof exports === "object") {
		        module.exports = definition();
		
		    // RequireJS
		    } else if (typeof define === "function" && define.amd) {
		        define(definition);
		
		    // SES (Secure EcmaScript)
		    } else if (typeof ses !== "undefined") {
		        if (!ses.ok()) {
		            return;
		        } else {
		            ses.makeQ = definition;
		        }
		
		    // <script>
		    } else {
		        Q = definition();
		    }
		
		})(function () {
		"use strict";
		
		var hasStacks = false;
		try {
		    throw new Error();
		} catch (e) {
		    hasStacks = !!e.stack;
		}
		
		// All code after this point will be filtered from stack traces reported
		// by Q.
		var qStartingLine = captureLine();
		var qFileName;
		
		// shims
		
		// used for fallback in "allResolved"
		var noop = function () {};
		
		// Use the fastest possible means to execute a task in a future turn
		// of the event loop.
		var nextTick =(function () {
		    // linked list of tasks (single, with head node)
		    var head = {task: void 0, next: null};
		    var tail = head;
		    var flushing = false;
		    var requestTick = void 0;
		    var isNodeJS = false;
		
		    function flush() {
		        /* jshint loopfunc: true */
		
		        while (head.next) {
		            head = head.next;
		            var task = head.task;
		            head.task = void 0;
		            var domain = head.domain;
		
		            if (domain) {
		                head.domain = void 0;
		                domain.enter();
		            }
		
		            try {
		                task();
		
		            } catch (e) {
		                if (isNodeJS) {
		                    // In node, uncaught exceptions are considered fatal errors.
		                    // Re-throw them synchronously to interrupt flushing!
		
		                    // Ensure continuation if the uncaught exception is suppressed
		                    // listening "uncaughtException" events (as domains does).
		                    // Continue in next event to avoid tick recursion.
		                    if (domain) {
		                        domain.exit();
		                    }
		                    setTimeout(flush, 0);
		                    if (domain) {
		                        domain.enter();
		                    }
		
		                    throw e;
		
		                } else {
		                    // In browsers, uncaught exceptions are not fatal.
		                    // Re-throw them asynchronously to avoid slow-downs.
		                    setTimeout(function() {
		                       throw e;
		                    }, 0);
		                }
		            }
		
		            if (domain) {
		                domain.exit();
		            }
		        }
		
		        flushing = false;
		    }
		
		    nextTick = function (task) {
		        tail = tail.next = {
		            task: task,
		            domain: isNodeJS && process.domain,
		            next: null
		        };
		
		        if (!flushing) {
		            flushing = true;
		            requestTick();
		        }
		    };
		
		    if (typeof process !== "undefined" && process.nextTick) {
		        // Node.js before 0.9. Note that some fake-Node environments, like the
		        // Mocha test runner, introduce a `process` global without a `nextTick`.
		        isNodeJS = true;
		
		        requestTick = function () {
		            process.nextTick(flush);
		        };
		
		    } else if (typeof setImmediate === "function") {
		        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
		        if (typeof window !== "undefined") {
		            requestTick = setImmediate.bind(window, flush);
		        } else {
		            requestTick = function () {
		                setImmediate(flush);
		            };
		        }
		
		    } else if (typeof MessageChannel !== "undefined") {
		        // modern browsers
		        // http://www.nonblocking.io/2011/06/windownexttick.html
		        var channel = new MessageChannel();
		        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
		        // working message ports the first time a page loads.
		        channel.port1.onmessage = function () {
		            requestTick = requestPortTick;
		            channel.port1.onmessage = flush;
		            flush();
		        };
		        var requestPortTick = function () {
		            // Opera requires us to provide a message payload, regardless of
		            // whether we use it.
		            channel.port2.postMessage(0);
		        };
		        requestTick = function () {
		            setTimeout(flush, 0);
		            requestPortTick();
		        };
		
		    } else {
		        // old browsers
		        requestTick = function () {
		            setTimeout(flush, 0);
		        };
		    }
		
		    return nextTick;
		})();
		
		// Attempt to make generics safe in the face of downstream
		// modifications.
		// There is no situation where this is necessary.
		// If you need a security guarantee, these primordials need to be
		// deeply frozen anyway, and if you don’t need a security guarantee,
		// this is just plain paranoid.
		// However, this **might** have the nice side-effect of reducing the size of
		// the minified code by reducing x.call() to merely x()
		// See Mark Miller’s explanation of what this does.
		// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
		var call = Function.call;
		function uncurryThis(f) {
		    return function () {
		        return call.apply(f, arguments);
		    };
		}
		// This is equivalent, but slower:
		// uncurryThis = Function_bind.bind(Function_bind.call);
		// http://jsperf.com/uncurrythis
		
		var array_slice = uncurryThis(Array.prototype.slice);
		
		var array_reduce = uncurryThis(
		    Array.prototype.reduce || function (callback, basis) {
		        var index = 0,
		            length = this.length;
		        // concerning the initial value, if one is not provided
		        if (arguments.length === 1) {
		            // seek to the first value in the array, accounting
		            // for the possibility that is is a sparse array
		            do {
		                if (index in this) {
		                    basis = this[index++];
		                    break;
		                }
		                if (++index >= length) {
		                    throw new TypeError();
		                }
		            } while (1);
		        }
		        // reduce
		        for (; index < length; index++) {
		            // account for the possibility that the array is sparse
		            if (index in this) {
		                basis = callback(basis, this[index], index);
		            }
		        }
		        return basis;
		    }
		);
		
		var array_indexOf = uncurryThis(
		    Array.prototype.indexOf || function (value) {
		        // not a very good shim, but good enough for our one use of it
		        for (var i = 0; i < this.length; i++) {
		            if (this[i] === value) {
		                return i;
		            }
		        }
		        return -1;
		    }
		);
		
		var array_map = uncurryThis(
		    Array.prototype.map || function (callback, thisp) {
		        var self = this;
		        var collect = [];
		        array_reduce(self, function (undefined, value, index) {
		            collect.push(callback.call(thisp, value, index, self));
		        }, void 0);
		        return collect;
		    }
		);
		
		var object_create = Object.create || function (prototype) {
		    function Type() { }
		    Type.prototype = prototype;
		    return new Type();
		};
		
		var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
		
		var object_keys = Object.keys || function (object) {
		    var keys = [];
		    for (var key in object) {
		        if (object_hasOwnProperty(object, key)) {
		            keys.push(key);
		        }
		    }
		    return keys;
		};
		
		var object_toString = uncurryThis(Object.prototype.toString);
		
		function isObject(value) {
		    return value === Object(value);
		}
		
		// generator related shims
		
		// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
		function isStopIteration(exception) {
		    return (
		        object_toString(exception) === "[object StopIteration]" ||
		        exception instanceof QReturnValue
		    );
		}
		
		// FIXME: Remove this helper and Q.return once ES6 generators are in
		// SpiderMonkey.
		var QReturnValue;
		if (typeof ReturnValue !== "undefined") {
		    QReturnValue = ReturnValue;
		} else {
		    QReturnValue = function (value) {
		        this.value = value;
		    };
		}
		
		// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
		// engine that has a deployed base of browsers that support generators.
		// However, SM's generators use the Python-inspired semantics of
		// outdated ES6 drafts.  We would like to support ES6, but we'd also
		// like to make it possible to use generators in deployed browsers, so
		// we also support Python-style generators.  At some point we can remove
		// this block.
		var hasES6Generators;
		try {
		    /* jshint evil: true, nonew: false */
		    new Function("(function* (){ yield 1; })");
		    hasES6Generators = true;
		} catch (e) {
		    hasES6Generators = false;
		}
		
		// long stack traces
		
		var STACK_JUMP_SEPARATOR = "From previous event:";
		
		function makeStackTraceLong(error, promise) {
		    // If possible, transform the error stack trace by removing Node and Q
		    // cruft, then concatenating with the stack trace of `promise`. See #57.
		    if (hasStacks &&
		        promise.stack &&
		        typeof error === "object" &&
		        error !== null &&
		        error.stack &&
		        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
		    ) {
		        var stacks = [];
		        for (var p = promise; !!p; p = p.source) {
		            if (p.stack) {
		                stacks.unshift(p.stack);
		            }
		        }
		        stacks.unshift(error.stack);
		
		        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
		        error.stack = filterStackString(concatedStacks);
		    }
		}
		
		function filterStackString(stackString) {
		    var lines = stackString.split("\n");
		    var desiredLines = [];
		    for (var i = 0; i < lines.length; ++i) {
		        var line = lines[i];
		
		        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
		            desiredLines.push(line);
		        }
		    }
		    return desiredLines.join("\n");
		}
		
		function isNodeFrame(stackLine) {
		    return stackLine.indexOf("(module.js:") !== -1 ||
		           stackLine.indexOf("(node.js:") !== -1;
		}
		
		function getFileNameAndLineNumber(stackLine) {
		    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
		    // In IE10 function name can have spaces ("Anonymous function") O_o
		    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
		    if (attempt1) {
		        return [attempt1[1], Number(attempt1[2])];
		    }
		
		    // Anonymous functions: "at filename:lineNumber:columnNumber"
		    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
		    if (attempt2) {
		        return [attempt2[1], Number(attempt2[2])];
		    }
		
		    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
		    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
		    if (attempt3) {
		        return [attempt3[1], Number(attempt3[2])];
		    }
		}
		
		function isInternalFrame(stackLine) {
		    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
		
		    if (!fileNameAndLineNumber) {
		        return false;
		    }
		
		    var fileName = fileNameAndLineNumber[0];
		    var lineNumber = fileNameAndLineNumber[1];
		
		    return fileName === qFileName &&
		        lineNumber >= qStartingLine &&
		        lineNumber <= qEndingLine;
		}
		
		// discover own file name and line number range for filtering stack
		// traces
		function captureLine() {
		    if (!hasStacks) {
		        return;
		    }
		
		    try {
		        throw new Error();
		    } catch (e) {
		        var lines = e.stack.split("\n");
		        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
		        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
		        if (!fileNameAndLineNumber) {
		            return;
		        }
		
		        qFileName = fileNameAndLineNumber[0];
		        return fileNameAndLineNumber[1];
		    }
		}
		
		function deprecate(callback, name, alternative) {
		    return function () {
		        if (typeof console !== "undefined" &&
		            typeof console.warn === "function") {
		            console.warn(name + " is deprecated, use " + alternative +
		                         " instead.", new Error("").stack);
		        }
		        return callback.apply(callback, arguments);
		    };
		}
		
		// end of shims
		// beginning of real work
		
		/**
		 * Constructs a promise for an immediate reference, passes promises through, or
		 * coerces promises from different systems.
		 * @param value immediate reference or promise
		 */
		function Q(value) {
		    // If the object is already a Promise, return it directly.  This enables
		    // the resolve function to both be used to created references from objects,
		    // but to tolerably coerce non-promises to promises.
		    if (isPromise(value)) {
		        return value;
		    }
		
		    // assimilate thenables
		    if (isPromiseAlike(value)) {
		        return coerce(value);
		    } else {
		        return fulfill(value);
		    }
		}
		Q.resolve = Q;
		
		/**
		 * Performs a task in a future turn of the event loop.
		 * @param {Function} task
		 */
		Q.nextTick = nextTick;
		
		/**
		 * Controls whether or not long stack traces will be on
		 */
		Q.longStackSupport = false;
		
		/**
		 * Constructs a {promise, resolve, reject} object.
		 *
		 * `resolve` is a callback to invoke with a more resolved value for the
		 * promise. To fulfill the promise, invoke `resolve` with any value that is
		 * not a thenable. To reject the promise, invoke `resolve` with a rejected
		 * thenable, or invoke `reject` with the reason directly. To resolve the
		 * promise to another thenable, thus putting it in the same state, invoke
		 * `resolve` with that other thenable.
		 */
		Q.defer = defer;
		function defer() {
		    // if "messages" is an "Array", that indicates that the promise has not yet
		    // been resolved.  If it is "undefined", it has been resolved.  Each
		    // element of the messages array is itself an array of complete arguments to
		    // forward to the resolved promise.  We coerce the resolution value to a
		    // promise using the `resolve` function because it handles both fully
		    // non-thenable values and other thenables gracefully.
		    var messages = [], progressListeners = [], resolvedPromise;
		
		    var deferred = object_create(defer.prototype);
		    var promise = object_create(Promise.prototype);
		
		    promise.promiseDispatch = function (resolve, op, operands) {
		        var args = array_slice(arguments);
		        if (messages) {
		            messages.push(args);
		            if (op === "when" && operands[1]) { // progress operand
		                progressListeners.push(operands[1]);
		            }
		        } else {
		            nextTick(function () {
		                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
		            });
		        }
		    };
		
		    // XXX deprecated
		    promise.valueOf = function () {
		        if (messages) {
		            return promise;
		        }
		        var nearerValue = nearer(resolvedPromise);
		        if (isPromise(nearerValue)) {
		            resolvedPromise = nearerValue; // shorten chain
		        }
		        return nearerValue;
		    };
		
		    promise.inspect = function () {
		        if (!resolvedPromise) {
		            return { state: "pending" };
		        }
		        return resolvedPromise.inspect();
		    };
		
		    if (Q.longStackSupport && hasStacks) {
		        try {
		            throw new Error();
		        } catch (e) {
		            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
		            // accessor around; that causes memory leaks as per GH-111. Just
		            // reify the stack trace as a string ASAP.
		            //
		            // At the same time, cut off the first line; it's always just
		            // "[object Promise]\n", as per the `toString`.
		            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
		        }
		    }
		
		    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
		    // consolidating them into `become`, since otherwise we'd create new
		    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
		
		    function become(newPromise) {
		        resolvedPromise = newPromise;
		        promise.source = newPromise;
		
		        array_reduce(messages, function (undefined, message) {
		            nextTick(function () {
		                newPromise.promiseDispatch.apply(newPromise, message);
		            });
		        }, void 0);
		
		        messages = void 0;
		        progressListeners = void 0;
		    }
		
		    deferred.promise = promise;
		    deferred.resolve = function (value) {
		        if (resolvedPromise) {
		            return;
		        }
		
		        become(Q(value));
		    };
		
		    deferred.fulfill = function (value) {
		        if (resolvedPromise) {
		            return;
		        }
		
		        become(fulfill(value));
		    };
		    deferred.reject = function (reason) {
		        if (resolvedPromise) {
		            return;
		        }
		
		        become(reject(reason));
		    };
		    deferred.notify = function (progress) {
		        if (resolvedPromise) {
		            return;
		        }
		
		        array_reduce(progressListeners, function (undefined, progressListener) {
		            nextTick(function () {
		                progressListener(progress);
		            });
		        }, void 0);
		    };
		
		    return deferred;
		}
		
		/**
		 * Creates a Node-style callback that will resolve or reject the deferred
		 * promise.
		 * @returns a nodeback
		 */
		defer.prototype.makeNodeResolver = function () {
		    var self = this;
		    return function (error, value) {
		        if (error) {
		            self.reject(error);
		        } else if (arguments.length > 2) {
		            self.resolve(array_slice(arguments, 1));
		        } else {
		            self.resolve(value);
		        }
		    };
		};
		
		/**
		 * @param resolver {Function} a function that returns nothing and accepts
		 * the resolve, reject, and notify functions for a deferred.
		 * @returns a promise that may be resolved with the given resolve and reject
		 * functions, or rejected by a thrown exception in resolver
		 */
		Q.promise = promise;
		function promise(resolver) {
		    if (typeof resolver !== "function") {
		        throw new TypeError("resolver must be a function.");
		    }
		    var deferred = defer();
		    try {
		        resolver(deferred.resolve, deferred.reject, deferred.notify);
		    } catch (reason) {
		        deferred.reject(reason);
		    }
		    return deferred.promise;
		}
		
		// XXX experimental.  This method is a way to denote that a local value is
		// serializable and should be immediately dispatched to a remote upon request,
		// instead of passing a reference.
		Q.passByCopy = function (object) {
		    //freeze(object);
		    //passByCopies.set(object, true);
		    return object;
		};
		
		Promise.prototype.passByCopy = function () {
		    //freeze(object);
		    //passByCopies.set(object, true);
		    return this;
		};
		
		/**
		 * If two promises eventually fulfill to the same value, promises that value,
		 * but otherwise rejects.
		 * @param x {Any*}
		 * @param y {Any*}
		 * @returns {Any*} a promise for x and y if they are the same, but a rejection
		 * otherwise.
		 *
		 */
		Q.join = function (x, y) {
		    return Q(x).join(y);
		};
		
		Promise.prototype.join = function (that) {
		    return Q([this, that]).spread(function (x, y) {
		        if (x === y) {
		            // TODO: "===" should be Object.is or equiv
		            return x;
		        } else {
		            throw new Error("Can't join: not the same: " + x + " " + y);
		        }
		    });
		};
		
		/**
		 * Returns a promise for the first of an array of promises to become fulfilled.
		 * @param answers {Array[Any*]} promises to race
		 * @returns {Any*} the first promise to be fulfilled
		 */
		Q.race = race;
		function race(answerPs) {
		    return promise(function(resolve, reject) {
		        // Switch to this once we can assume at least ES5
		        // answerPs.forEach(function(answerP) {
		        //     Q(answerP).then(resolve, reject);
		        // });
		        // Use this in the meantime
		        for (var i = 0, len = answerPs.length; i < len; i++) {
		            Q(answerPs[i]).then(resolve, reject);
		        }
		    });
		}
		
		Promise.prototype.race = function () {
		    return this.then(Q.race);
		};
		
		/**
		 * Constructs a Promise with a promise descriptor object and optional fallback
		 * function.  The descriptor contains methods like when(rejected), get(name),
		 * set(name, value), post(name, args), and delete(name), which all
		 * return either a value, a promise for a value, or a rejection.  The fallback
		 * accepts the operation name, a resolver, and any further arguments that would
		 * have been forwarded to the appropriate method above had a method been
		 * provided with the proper name.  The API makes no guarantees about the nature
		 * of the returned object, apart from that it is usable whereever promises are
		 * bought and sold.
		 */
		Q.makePromise = Promise;
		function Promise(descriptor, fallback, inspect) {
		    if (fallback === void 0) {
		        fallback = function (op) {
		            return reject(new Error(
		                "Promise does not support operation: " + op
		            ));
		        };
		    }
		    if (inspect === void 0) {
		        inspect = function () {
		            return {state: "unknown"};
		        };
		    }
		
		    var promise = object_create(Promise.prototype);
		
		    promise.promiseDispatch = function (resolve, op, args) {
		        var result;
		        try {
		            if (descriptor[op]) {
		                result = descriptor[op].apply(promise, args);
		            } else {
		                result = fallback.call(promise, op, args);
		            }
		        } catch (exception) {
		            result = reject(exception);
		        }
		        if (resolve) {
		            resolve(result);
		        }
		    };
		
		    promise.inspect = inspect;
		
		    // XXX deprecated `valueOf` and `exception` support
		    if (inspect) {
		        var inspected = inspect();
		        if (inspected.state === "rejected") {
		            promise.exception = inspected.reason;
		        }
		
		        promise.valueOf = function () {
		            var inspected = inspect();
		            if (inspected.state === "pending" ||
		                inspected.state === "rejected") {
		                return promise;
		            }
		            return inspected.value;
		        };
		    }
		
		    return promise;
		}
		
		Promise.prototype.toString = function () {
		    return "[object Promise]";
		};
		
		Promise.prototype.then = function (fulfilled, rejected, progressed) {
		    var self = this;
		    var deferred = defer();
		    var done = false;   // ensure the untrusted promise makes at most a
		                        // single call to one of the callbacks
		
		    function _fulfilled(value) {
		        try {
		            return typeof fulfilled === "function" ? fulfilled(value) : value;
		        } catch (exception) {
		            return reject(exception);
		        }
		    }
		
		    function _rejected(exception) {
		        if (typeof rejected === "function") {
		            makeStackTraceLong(exception, self);
		            try {
		                return rejected(exception);
		            } catch (newException) {
		                return reject(newException);
		            }
		        }
		        return reject(exception);
		    }
		
		    function _progressed(value) {
		        return typeof progressed === "function" ? progressed(value) : value;
		    }
		
		    nextTick(function () {
		        self.promiseDispatch(function (value) {
		            if (done) {
		                return;
		            }
		            done = true;
		
		            deferred.resolve(_fulfilled(value));
		        }, "when", [function (exception) {
		            if (done) {
		                return;
		            }
		            done = true;
		
		            deferred.resolve(_rejected(exception));
		        }]);
		    });
		
		    // Progress propagator need to be attached in the current tick.
		    self.promiseDispatch(void 0, "when", [void 0, function (value) {
		        var newValue;
		        var threw = false;
		        try {
		            newValue = _progressed(value);
		        } catch (e) {
		            threw = true;
		            if (Q.onerror) {
		                Q.onerror(e);
		            } else {
		                throw e;
		            }
		        }
		
		        if (!threw) {
		            deferred.notify(newValue);
		        }
		    }]);
		
		    return deferred.promise;
		};
		
		/**
		 * Registers an observer on a promise.
		 *
		 * Guarantees:
		 *
		 * 1. that fulfilled and rejected will be called only once.
		 * 2. that either the fulfilled callback or the rejected callback will be
		 *    called, but not both.
		 * 3. that fulfilled and rejected will not be called in this turn.
		 *
		 * @param value      promise or immediate reference to observe
		 * @param fulfilled  function to be called with the fulfilled value
		 * @param rejected   function to be called with the rejection exception
		 * @param progressed function to be called on any progress notifications
		 * @return promise for the return value from the invoked callback
		 */
		Q.when = when;
		function when(value, fulfilled, rejected, progressed) {
		    return Q(value).then(fulfilled, rejected, progressed);
		}
		
		Promise.prototype.thenResolve = function (value) {
		    return this.then(function () { return value; });
		};
		
		Q.thenResolve = function (promise, value) {
		    return Q(promise).thenResolve(value);
		};
		
		Promise.prototype.thenReject = function (reason) {
		    return this.then(function () { throw reason; });
		};
		
		Q.thenReject = function (promise, reason) {
		    return Q(promise).thenReject(reason);
		};
		
		/**
		 * If an object is not a promise, it is as "near" as possible.
		 * If a promise is rejected, it is as "near" as possible too.
		 * If it’s a fulfilled promise, the fulfillment value is nearer.
		 * If it’s a deferred promise and the deferred has been resolved, the
		 * resolution is "nearer".
		 * @param object
		 * @returns most resolved (nearest) form of the object
		 */
		
		// XXX should we re-do this?
		Q.nearer = nearer;
		function nearer(value) {
		    if (isPromise(value)) {
		        var inspected = value.inspect();
		        if (inspected.state === "fulfilled") {
		            return inspected.value;
		        }
		    }
		    return value;
		}
		
		/**
		 * @returns whether the given object is a promise.
		 * Otherwise it is a fulfilled value.
		 */
		Q.isPromise = isPromise;
		function isPromise(object) {
		    return isObject(object) &&
		        typeof object.promiseDispatch === "function" &&
		        typeof object.inspect === "function";
		}
		
		Q.isPromiseAlike = isPromiseAlike;
		function isPromiseAlike(object) {
		    return isObject(object) && typeof object.then === "function";
		}
		
		/**
		 * @returns whether the given object is a pending promise, meaning not
		 * fulfilled or rejected.
		 */
		Q.isPending = isPending;
		function isPending(object) {
		    return isPromise(object) && object.inspect().state === "pending";
		}
		
		Promise.prototype.isPending = function () {
		    return this.inspect().state === "pending";
		};
		
		/**
		 * @returns whether the given object is a value or fulfilled
		 * promise.
		 */
		Q.isFulfilled = isFulfilled;
		function isFulfilled(object) {
		    return !isPromise(object) || object.inspect().state === "fulfilled";
		}
		
		Promise.prototype.isFulfilled = function () {
		    return this.inspect().state === "fulfilled";
		};
		
		/**
		 * @returns whether the given object is a rejected promise.
		 */
		Q.isRejected = isRejected;
		function isRejected(object) {
		    return isPromise(object) && object.inspect().state === "rejected";
		}
		
		Promise.prototype.isRejected = function () {
		    return this.inspect().state === "rejected";
		};
		
		//// BEGIN UNHANDLED REJECTION TRACKING
		
		// This promise library consumes exceptions thrown in handlers so they can be
		// handled by a subsequent promise.  The exceptions get added to this array when
		// they are created, and removed when they are handled.  Note that in ES6 or
		// shimmed environments, this would naturally be a `Set`.
		var unhandledReasons = [];
		var unhandledRejections = [];
		var unhandledReasonsDisplayed = false;
		var trackUnhandledRejections = true;
		function displayUnhandledReasons() {
		    if (
		        !unhandledReasonsDisplayed &&
		        typeof window !== "undefined" &&
		        window.console
		    ) {
		        console.warn("[Q] Unhandled rejection reasons (should be empty):",
		                     unhandledReasons);
		    }
		
		    unhandledReasonsDisplayed = true;
		}
		
		function logUnhandledReasons() {
		    for (var i = 0; i < unhandledReasons.length; i++) {
		        var reason = unhandledReasons[i];
		        console.warn("Unhandled rejection reason:", reason);
		    }
		}
		
		function resetUnhandledRejections() {
		    unhandledReasons.length = 0;
		    unhandledRejections.length = 0;
		    unhandledReasonsDisplayed = false;
		
		    if (!trackUnhandledRejections) {
		        trackUnhandledRejections = true;
		
		        // Show unhandled rejection reasons if Node exits without handling an
		        // outstanding rejection.  (Note that Browserify presently produces a
		        // `process` global without the `EventEmitter` `on` method.)
		        if (typeof process !== "undefined" && process.on) {
		            process.on("exit", logUnhandledReasons);
		        }
		    }
		}
		
		function trackRejection(promise, reason) {
		    if (!trackUnhandledRejections) {
		        return;
		    }
		
		    unhandledRejections.push(promise);
		    if (reason && typeof reason.stack !== "undefined") {
		        unhandledReasons.push(reason.stack);
		    } else {
		        unhandledReasons.push("(no stack) " + reason);
		    }
		    displayUnhandledReasons();
		}
		
		function untrackRejection(promise) {
		    if (!trackUnhandledRejections) {
		        return;
		    }
		
		    var at = array_indexOf(unhandledRejections, promise);
		    if (at !== -1) {
		        unhandledRejections.splice(at, 1);
		        unhandledReasons.splice(at, 1);
		    }
		}
		
		Q.resetUnhandledRejections = resetUnhandledRejections;
		
		Q.getUnhandledReasons = function () {
		    // Make a copy so that consumers can't interfere with our internal state.
		    return unhandledReasons.slice();
		};
		
		Q.stopUnhandledRejectionTracking = function () {
		    resetUnhandledRejections();
		    if (typeof process !== "undefined" && process.on) {
		        process.removeListener("exit", logUnhandledReasons);
		    }
		    trackUnhandledRejections = false;
		};
		
		resetUnhandledRejections();
		
		//// END UNHANDLED REJECTION TRACKING
		
		/**
		 * Constructs a rejected promise.
		 * @param reason value describing the failure
		 */
		Q.reject = reject;
		function reject(reason) {
		    var rejection = Promise({
		        "when": function (rejected) {
		            // note that the error has been handled
		            if (rejected) {
		                untrackRejection(this);
		            }
		            return rejected ? rejected(reason) : this;
		        }
		    }, function fallback() {
		        return this;
		    }, function inspect() {
		        return { state: "rejected", reason: reason };
		    });
		
		    // Note that the reason has not been handled.
		    trackRejection(rejection, reason);
		
		    return rejection;
		}
		
		/**
		 * Constructs a fulfilled promise for an immediate reference.
		 * @param value immediate reference
		 */
		Q.fulfill = fulfill;
		function fulfill(value) {
		    return Promise({
		        "when": function () {
		            return value;
		        },
		        "get": function (name) {
		            return value[name];
		        },
		        "set": function (name, rhs) {
		            value[name] = rhs;
		        },
		        "delete": function (name) {
		            delete value[name];
		        },
		        "post": function (name, args) {
		            // Mark Miller proposes that post with no name should apply a
		            // promised function.
		            if (name === null || name === void 0) {
		                return value.apply(void 0, args);
		            } else {
		                return value[name].apply(value, args);
		            }
		        },
		        "apply": function (thisp, args) {
		            return value.apply(thisp, args);
		        },
		        "keys": function () {
		            return object_keys(value);
		        }
		    }, void 0, function inspect() {
		        return { state: "fulfilled", value: value };
		    });
		}
		
		/**
		 * Converts thenables to Q promises.
		 * @param promise thenable promise
		 * @returns a Q promise
		 */
		function coerce(promise) {
		    var deferred = defer();
		    nextTick(function () {
		        try {
		            promise.then(deferred.resolve, deferred.reject, deferred.notify);
		        } catch (exception) {
		            deferred.reject(exception);
		        }
		    });
		    return deferred.promise;
		}
		
		/**
		 * Annotates an object such that it will never be
		 * transferred away from this process over any promise
		 * communication channel.
		 * @param object
		 * @returns promise a wrapping of that object that
		 * additionally responds to the "isDef" message
		 * without a rejection.
		 */
		Q.master = master;
		function master(object) {
		    return Promise({
		        "isDef": function () {}
		    }, function fallback(op, args) {
		        return dispatch(object, op, args);
		    }, function () {
		        return Q(object).inspect();
		    });
		}
		
		/**
		 * Spreads the values of a promised array of arguments into the
		 * fulfillment callback.
		 * @param fulfilled callback that receives variadic arguments from the
		 * promised array
		 * @param rejected callback that receives the exception if the promise
		 * is rejected.
		 * @returns a promise for the return value or thrown exception of
		 * either callback.
		 */
		Q.spread = spread;
		function spread(value, fulfilled, rejected) {
		    return Q(value).spread(fulfilled, rejected);
		}
		
		Promise.prototype.spread = function (fulfilled, rejected) {
		    return this.all().then(function (array) {
		        return fulfilled.apply(void 0, array);
		    }, rejected);
		};
		
		/**
		 * The async function is a decorator for generator functions, turning
		 * them into asynchronous generators.  Although generators are only part
		 * of the newest ECMAScript 6 drafts, this code does not cause syntax
		 * errors in older engines.  This code should continue to work and will
		 * in fact improve over time as the language improves.
		 *
		 * ES6 generators are currently part of V8 version 3.19 with the
		 * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
		 * for longer, but under an older Python-inspired form.  This function
		 * works on both kinds of generators.
		 *
		 * Decorates a generator function such that:
		 *  - it may yield promises
		 *  - execution will continue when that promise is fulfilled
		 *  - the value of the yield expression will be the fulfilled value
		 *  - it returns a promise for the return value (when the generator
		 *    stops iterating)
		 *  - the decorated function returns a promise for the return value
		 *    of the generator or the first rejected promise among those
		 *    yielded.
		 *  - if an error is thrown in the generator, it propagates through
		 *    every following yield until it is caught, or until it escapes
		 *    the generator function altogether, and is translated into a
		 *    rejection for the promise returned by the decorated generator.
		 */
		Q.async = async;
		function async(makeGenerator) {
		    return function () {
		        // when verb is "send", arg is a value
		        // when verb is "throw", arg is an exception
		        function continuer(verb, arg) {
		            var result;
		            if (hasES6Generators) {
		                try {
		                    result = generator[verb](arg);
		                } catch (exception) {
		                    return reject(exception);
		                }
		                if (result.done) {
		                    return result.value;
		                } else {
		                    return when(result.value, callback, errback);
		                }
		            } else {
		                // FIXME: Remove this case when SM does ES6 generators.
		                try {
		                    result = generator[verb](arg);
		                } catch (exception) {
		                    if (isStopIteration(exception)) {
		                        return exception.value;
		                    } else {
		                        return reject(exception);
		                    }
		                }
		                return when(result, callback, errback);
		            }
		        }
		        var generator = makeGenerator.apply(this, arguments);
		        var callback = continuer.bind(continuer, "next");
		        var errback = continuer.bind(continuer, "throw");
		        return callback();
		    };
		}
		
		/**
		 * The spawn function is a small wrapper around async that immediately
		 * calls the generator and also ends the promise chain, so that any
		 * unhandled errors are thrown instead of forwarded to the error
		 * handler. This is useful because it's extremely common to run
		 * generators at the top-level to work with libraries.
		 */
		Q.spawn = spawn;
		function spawn(makeGenerator) {
		    Q.done(Q.async(makeGenerator)());
		}
		
		// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
		/**
		 * Throws a ReturnValue exception to stop an asynchronous generator.
		 *
		 * This interface is a stop-gap measure to support generator return
		 * values in older Firefox/SpiderMonkey.  In browsers that support ES6
		 * generators like Chromium 29, just use "return" in your generator
		 * functions.
		 *
		 * @param value the return value for the surrounding generator
		 * @throws ReturnValue exception with the value.
		 * @example
		 * // ES6 style
		 * Q.async(function* () {
		 *      var foo = yield getFooPromise();
		 *      var bar = yield getBarPromise();
		 *      return foo + bar;
		 * })
		 * // Older SpiderMonkey style
		 * Q.async(function () {
		 *      var foo = yield getFooPromise();
		 *      var bar = yield getBarPromise();
		 *      Q.return(foo + bar);
		 * })
		 */
		Q["return"] = _return;
		function _return(value) {
		    throw new QReturnValue(value);
		}
		
		/**
		 * The promised function decorator ensures that any promise arguments
		 * are settled and passed as values (`this` is also settled and passed
		 * as a value).  It will also ensure that the result of a function is
		 * always a promise.
		 *
		 * @example
		 * var add = Q.promised(function (a, b) {
		 *     return a + b;
		 * });
		 * add(Q(a), Q(B));
		 *
		 * @param {function} callback The function to decorate
		 * @returns {function} a function that has been decorated.
		 */
		Q.promised = promised;
		function promised(callback) {
		    return function () {
		        return spread([this, all(arguments)], function (self, args) {
		            return callback.apply(self, args);
		        });
		    };
		}
		
		/**
		 * sends a message to a value in a future turn
		 * @param object* the recipient
		 * @param op the name of the message operation, e.g., "when",
		 * @param args further arguments to be forwarded to the operation
		 * @returns result {Promise} a promise for the result of the operation
		 */
		Q.dispatch = dispatch;
		function dispatch(object, op, args) {
		    return Q(object).dispatch(op, args);
		}
		
		Promise.prototype.dispatch = function (op, args) {
		    var self = this;
		    var deferred = defer();
		    nextTick(function () {
		        self.promiseDispatch(deferred.resolve, op, args);
		    });
		    return deferred.promise;
		};
		
		/**
		 * Gets the value of a property in a future turn.
		 * @param object    promise or immediate reference for target object
		 * @param name      name of property to get
		 * @return promise for the property value
		 */
		Q.get = function (object, key) {
		    return Q(object).dispatch("get", [key]);
		};
		
		Promise.prototype.get = function (key) {
		    return this.dispatch("get", [key]);
		};
		
		/**
		 * Sets the value of a property in a future turn.
		 * @param object    promise or immediate reference for object object
		 * @param name      name of property to set
		 * @param value     new value of property
		 * @return promise for the return value
		 */
		Q.set = function (object, key, value) {
		    return Q(object).dispatch("set", [key, value]);
		};
		
		Promise.prototype.set = function (key, value) {
		    return this.dispatch("set", [key, value]);
		};
		
		/**
		 * Deletes a property in a future turn.
		 * @param object    promise or immediate reference for target object
		 * @param name      name of property to delete
		 * @return promise for the return value
		 */
		Q.del = // XXX legacy
		Q["delete"] = function (object, key) {
		    return Q(object).dispatch("delete", [key]);
		};
		
		Promise.prototype.del = // XXX legacy
		Promise.prototype["delete"] = function (key) {
		    return this.dispatch("delete", [key]);
		};
		
		/**
		 * Invokes a method in a future turn.
		 * @param object    promise or immediate reference for target object
		 * @param name      name of method to invoke
		 * @param value     a value to post, typically an array of
		 *                  invocation arguments for promises that
		 *                  are ultimately backed with `resolve` values,
		 *                  as opposed to those backed with URLs
		 *                  wherein the posted value can be any
		 *                  JSON serializable object.
		 * @return promise for the return value
		 */
		// bound locally because it is used by other methods
		Q.mapply = // XXX As proposed by "Redsandro"
		Q.post = function (object, name, args) {
		    return Q(object).dispatch("post", [name, args]);
		};
		
		Promise.prototype.mapply = // XXX As proposed by "Redsandro"
		Promise.prototype.post = function (name, args) {
		    return this.dispatch("post", [name, args]);
		};
		
		/**
		 * Invokes a method in a future turn.
		 * @param object    promise or immediate reference for target object
		 * @param name      name of method to invoke
		 * @param ...args   array of invocation arguments
		 * @return promise for the return value
		 */
		Q.send = // XXX Mark Miller's proposed parlance
		Q.mcall = // XXX As proposed by "Redsandro"
		Q.invoke = function (object, name /*...args*/) {
		    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
		};
		
		Promise.prototype.send = // XXX Mark Miller's proposed parlance
		Promise.prototype.mcall = // XXX As proposed by "Redsandro"
		Promise.prototype.invoke = function (name /*...args*/) {
		    return this.dispatch("post", [name, array_slice(arguments, 1)]);
		};
		
		/**
		 * Applies the promised function in a future turn.
		 * @param object    promise or immediate reference for target function
		 * @param args      array of application arguments
		 */
		Q.fapply = function (object, args) {
		    return Q(object).dispatch("apply", [void 0, args]);
		};
		
		Promise.prototype.fapply = function (args) {
		    return this.dispatch("apply", [void 0, args]);
		};
		
		/**
		 * Calls the promised function in a future turn.
		 * @param object    promise or immediate reference for target function
		 * @param ...args   array of application arguments
		 */
		Q["try"] =
		Q.fcall = function (object /* ...args*/) {
		    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
		};
		
		Promise.prototype.fcall = function (/*...args*/) {
		    return this.dispatch("apply", [void 0, array_slice(arguments)]);
		};
		
		/**
		 * Binds the promised function, transforming return values into a fulfilled
		 * promise and thrown errors into a rejected one.
		 * @param object    promise or immediate reference for target function
		 * @param ...args   array of application arguments
		 */
		Q.fbind = function (object /*...args*/) {
		    var promise = Q(object);
		    var args = array_slice(arguments, 1);
		    return function fbound() {
		        return promise.dispatch("apply", [
		            this,
		            args.concat(array_slice(arguments))
		        ]);
		    };
		};
		Promise.prototype.fbind = function (/*...args*/) {
		    var promise = this;
		    var args = array_slice(arguments);
		    return function fbound() {
		        return promise.dispatch("apply", [
		            this,
		            args.concat(array_slice(arguments))
		        ]);
		    };
		};
		
		/**
		 * Requests the names of the owned properties of a promised
		 * object in a future turn.
		 * @param object    promise or immediate reference for target object
		 * @return promise for the keys of the eventually settled object
		 */
		Q.keys = function (object) {
		    return Q(object).dispatch("keys", []);
		};
		
		Promise.prototype.keys = function () {
		    return this.dispatch("keys", []);
		};
		
		/**
		 * Turns an array of promises into a promise for an array.  If any of
		 * the promises gets rejected, the whole array is rejected immediately.
		 * @param {Array*} an array (or promise for an array) of values (or
		 * promises for values)
		 * @returns a promise for an array of the corresponding values
		 */
		// By Mark Miller
		// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
		Q.all = all;
		function all(promises) {
		    return when(promises, function (promises) {
		        var countDown = 0;
		        var deferred = defer();
		        array_reduce(promises, function (undefined, promise, index) {
		            var snapshot;
		            if (
		                isPromise(promise) &&
		                (snapshot = promise.inspect()).state === "fulfilled"
		            ) {
		                promises[index] = snapshot.value;
		            } else {
		                ++countDown;
		                when(
		                    promise,
		                    function (value) {
		                        promises[index] = value;
		                        if (--countDown === 0) {
		                            deferred.resolve(promises);
		                        }
		                    },
		                    deferred.reject,
		                    function (progress) {
		                        deferred.notify({ index: index, value: progress });
		                    }
		                );
		            }
		        }, void 0);
		        if (countDown === 0) {
		            deferred.resolve(promises);
		        }
		        return deferred.promise;
		    });
		}
		
		Promise.prototype.all = function () {
		    return all(this);
		};
		
		/**
		 * Waits for all promises to be settled, either fulfilled or
		 * rejected.  This is distinct from `all` since that would stop
		 * waiting at the first rejection.  The promise returned by
		 * `allResolved` will never be rejected.
		 * @param promises a promise for an array (or an array) of promises
		 * (or values)
		 * @return a promise for an array of promises
		 */
		Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
		function allResolved(promises) {
		    return when(promises, function (promises) {
		        promises = array_map(promises, Q);
		        return when(all(array_map(promises, function (promise) {
		            return when(promise, noop, noop);
		        })), function () {
		            return promises;
		        });
		    });
		}
		
		Promise.prototype.allResolved = function () {
		    return allResolved(this);
		};
		
		/**
		 * @see Promise#allSettled
		 */
		Q.allSettled = allSettled;
		function allSettled(promises) {
		    return Q(promises).allSettled();
		}
		
		/**
		 * Turns an array of promises into a promise for an array of their states (as
		 * returned by `inspect`) when they have all settled.
		 * @param {Array[Any*]} values an array (or promise for an array) of values (or
		 * promises for values)
		 * @returns {Array[State]} an array of states for the respective values.
		 */
		Promise.prototype.allSettled = function () {
		    return this.then(function (promises) {
		        return all(array_map(promises, function (promise) {
		            promise = Q(promise);
		            function regardless() {
		                return promise.inspect();
		            }
		            return promise.then(regardless, regardless);
		        }));
		    });
		};
		
		/**
		 * Captures the failure of a promise, giving an oportunity to recover
		 * with a callback.  If the given promise is fulfilled, the returned
		 * promise is fulfilled.
		 * @param {Any*} promise for something
		 * @param {Function} callback to fulfill the returned promise if the
		 * given promise is rejected
		 * @returns a promise for the return value of the callback
		 */
		Q.fail = // XXX legacy
		Q["catch"] = function (object, rejected) {
		    return Q(object).then(void 0, rejected);
		};
		
		Promise.prototype.fail = // XXX legacy
		Promise.prototype["catch"] = function (rejected) {
		    return this.then(void 0, rejected);
		};
		
		/**
		 * Attaches a listener that can respond to progress notifications from a
		 * promise's originating deferred. This listener receives the exact arguments
		 * passed to ``deferred.notify``.
		 * @param {Any*} promise for something
		 * @param {Function} callback to receive any progress notifications
		 * @returns the given promise, unchanged
		 */
		Q.progress = progress;
		function progress(object, progressed) {
		    return Q(object).then(void 0, void 0, progressed);
		}
		
		Promise.prototype.progress = function (progressed) {
		    return this.then(void 0, void 0, progressed);
		};
		
		/**
		 * Provides an opportunity to observe the settling of a promise,
		 * regardless of whether the promise is fulfilled or rejected.  Forwards
		 * the resolution to the returned promise when the callback is done.
		 * The callback can return a promise to defer completion.
		 * @param {Any*} promise
		 * @param {Function} callback to observe the resolution of the given
		 * promise, takes no arguments.
		 * @returns a promise for the resolution of the given promise when
		 * ``fin`` is done.
		 */
		Q.fin = // XXX legacy
		Q["finally"] = function (object, callback) {
		    return Q(object)["finally"](callback);
		};
		
		Promise.prototype.fin = // XXX legacy
		Promise.prototype["finally"] = function (callback) {
		    callback = Q(callback);
		    return this.then(function (value) {
		        return callback.fcall().then(function () {
		            return value;
		        });
		    }, function (reason) {
		        // TODO attempt to recycle the rejection with "this".
		        return callback.fcall().then(function () {
		            throw reason;
		        });
		    });
		};
		
		/**
		 * Terminates a chain of promises, forcing rejections to be
		 * thrown as exceptions.
		 * @param {Any*} promise at the end of a chain of promises
		 * @returns nothing
		 */
		Q.done = function (object, fulfilled, rejected, progress) {
		    return Q(object).done(fulfilled, rejected, progress);
		};
		
		Promise.prototype.done = function (fulfilled, rejected, progress) {
		    var onUnhandledError = function (error) {
		        // forward to a future turn so that ``when``
		        // does not catch it and turn it into a rejection.
		        nextTick(function () {
		            makeStackTraceLong(error, promise);
		            if (Q.onerror) {
		                Q.onerror(error);
		            } else {
		                throw error;
		            }
		        });
		    };
		
		    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
		    var promise = fulfilled || rejected || progress ?
		        this.then(fulfilled, rejected, progress) :
		        this;
		
		    if (typeof process === "object" && process && process.domain) {
		        onUnhandledError = process.domain.bind(onUnhandledError);
		    }
		
		    promise.then(void 0, onUnhandledError);
		};
		
		/**
		 * Causes a promise to be rejected if it does not get fulfilled before
		 * some milliseconds time out.
		 * @param {Any*} promise
		 * @param {Number} milliseconds timeout
		 * @param {String} custom error message (optional)
		 * @returns a promise for the resolution of the given promise if it is
		 * fulfilled before the timeout, otherwise rejected.
		 */
		Q.timeout = function (object, ms, message) {
		    return Q(object).timeout(ms, message);
		};
		
		Promise.prototype.timeout = function (ms, message) {
		    var deferred = defer();
		    var timeoutId = setTimeout(function () {
		        deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
		    }, ms);
		
		    this.then(function (value) {
		        clearTimeout(timeoutId);
		        deferred.resolve(value);
		    }, function (exception) {
		        clearTimeout(timeoutId);
		        deferred.reject(exception);
		    }, deferred.notify);
		
		    return deferred.promise;
		};
		
		/**
		 * Returns a promise for the given value (or promised value), some
		 * milliseconds after it resolved. Passes rejections immediately.
		 * @param {Any*} promise
		 * @param {Number} milliseconds
		 * @returns a promise for the resolution of the given promise after milliseconds
		 * time has elapsed since the resolution of the given promise.
		 * If the given promise rejects, that is passed immediately.
		 */
		Q.delay = function (object, timeout) {
		    if (timeout === void 0) {
		        timeout = object;
		        object = void 0;
		    }
		    return Q(object).delay(timeout);
		};
		
		Promise.prototype.delay = function (timeout) {
		    return this.then(function (value) {
		        var deferred = defer();
		        setTimeout(function () {
		            deferred.resolve(value);
		        }, timeout);
		        return deferred.promise;
		    });
		};
		
		/**
		 * Passes a continuation to a Node function, which is called with the given
		 * arguments provided as an array, and returns a promise.
		 *
		 *      Q.nfapply(FS.readFile, [__filename])
		 *      .then(function (content) {
		 *      })
		 *
		 */
		Q.nfapply = function (callback, args) {
		    return Q(callback).nfapply(args);
		};
		
		Promise.prototype.nfapply = function (args) {
		    var deferred = defer();
		    var nodeArgs = array_slice(args);
		    nodeArgs.push(deferred.makeNodeResolver());
		    this.fapply(nodeArgs).fail(deferred.reject);
		    return deferred.promise;
		};
		
		/**
		 * Passes a continuation to a Node function, which is called with the given
		 * arguments provided individually, and returns a promise.
		 * @example
		 * Q.nfcall(FS.readFile, __filename)
		 * .then(function (content) {
		 * })
		 *
		 */
		Q.nfcall = function (callback /*...args*/) {
		    var args = array_slice(arguments, 1);
		    return Q(callback).nfapply(args);
		};
		
		Promise.prototype.nfcall = function (/*...args*/) {
		    var nodeArgs = array_slice(arguments);
		    var deferred = defer();
		    nodeArgs.push(deferred.makeNodeResolver());
		    this.fapply(nodeArgs).fail(deferred.reject);
		    return deferred.promise;
		};
		
		/**
		 * Wraps a NodeJS continuation passing function and returns an equivalent
		 * version that returns a promise.
		 * @example
		 * Q.nfbind(FS.readFile, __filename)("utf-8")
		 * .then(console.log)
		 * .done()
		 */
		Q.nfbind =
		Q.denodeify = function (callback /*...args*/) {
		    var baseArgs = array_slice(arguments, 1);
		    return function () {
		        var nodeArgs = baseArgs.concat(array_slice(arguments));
		        var deferred = defer();
		        nodeArgs.push(deferred.makeNodeResolver());
		        Q(callback).fapply(nodeArgs).fail(deferred.reject);
		        return deferred.promise;
		    };
		};
		
		Promise.prototype.nfbind =
		Promise.prototype.denodeify = function (/*...args*/) {
		    var args = array_slice(arguments);
		    args.unshift(this);
		    return Q.denodeify.apply(void 0, args);
		};
		
		Q.nbind = function (callback, thisp /*...args*/) {
		    var baseArgs = array_slice(arguments, 2);
		    return function () {
		        var nodeArgs = baseArgs.concat(array_slice(arguments));
		        var deferred = defer();
		        nodeArgs.push(deferred.makeNodeResolver());
		        function bound() {
		            return callback.apply(thisp, arguments);
		        }
		        Q(bound).fapply(nodeArgs).fail(deferred.reject);
		        return deferred.promise;
		    };
		};
		
		Promise.prototype.nbind = function (/*thisp, ...args*/) {
		    var args = array_slice(arguments, 0);
		    args.unshift(this);
		    return Q.nbind.apply(void 0, args);
		};
		
		/**
		 * Calls a method of a Node-style object that accepts a Node-style
		 * callback with a given array of arguments, plus a provided callback.
		 * @param object an object that has the named method
		 * @param {String} name name of the method of object
		 * @param {Array} args arguments to pass to the method; the callback
		 * will be provided by Q and appended to these arguments.
		 * @returns a promise for the value or error
		 */
		Q.nmapply = // XXX As proposed by "Redsandro"
		Q.npost = function (object, name, args) {
		    return Q(object).npost(name, args);
		};
		
		Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
		Promise.prototype.npost = function (name, args) {
		    var nodeArgs = array_slice(args || []);
		    var deferred = defer();
		    nodeArgs.push(deferred.makeNodeResolver());
		    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
		    return deferred.promise;
		};
		
		/**
		 * Calls a method of a Node-style object that accepts a Node-style
		 * callback, forwarding the given variadic arguments, plus a provided
		 * callback argument.
		 * @param object an object that has the named method
		 * @param {String} name name of the method of object
		 * @param ...args arguments to pass to the method; the callback will
		 * be provided by Q and appended to these arguments.
		 * @returns a promise for the value or error
		 */
		Q.nsend = // XXX Based on Mark Miller's proposed "send"
		Q.nmcall = // XXX Based on "Redsandro's" proposal
		Q.ninvoke = function (object, name /*...args*/) {
		    var nodeArgs = array_slice(arguments, 2);
		    var deferred = defer();
		    nodeArgs.push(deferred.makeNodeResolver());
		    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
		    return deferred.promise;
		};
		
		Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
		Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
		Promise.prototype.ninvoke = function (name /*...args*/) {
		    var nodeArgs = array_slice(arguments, 1);
		    var deferred = defer();
		    nodeArgs.push(deferred.makeNodeResolver());
		    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
		    return deferred.promise;
		};
		
		/**
		 * If a function would like to support both Node continuation-passing-style and
		 * promise-returning-style, it can end its internal promise chain with
		 * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
		 * elects to use a nodeback, the result will be sent there.  If they do not
		 * pass a nodeback, they will receive the result promise.
		 * @param object a result (or a promise for a result)
		 * @param {Function} nodeback a Node.js-style callback
		 * @returns either the promise or nothing
		 */
		Q.nodeify = nodeify;
		function nodeify(object, nodeback) {
		    return Q(object).nodeify(nodeback);
		}
		
		Promise.prototype.nodeify = function (nodeback) {
		    if (nodeback) {
		        this.then(function (value) {
		            nextTick(function () {
		                nodeback(null, value);
		            });
		        }, function (error) {
		            nextTick(function () {
		                nodeback(error);
		            });
		        });
		    } else {
		        return this;
		    }
		};
		
		// All code before this point will be filtered from stack traces.
		var qEndingLine = captureLine();
		
		return Q;
		
		});
		
	
	}, 'async/lib/async.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'async/lib/async.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'async/lib/async.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'async/lib/async.js';
		var __dirname = 'async/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'async/lib/async.js'], env: {}};
	
		/** code **/
		/*global setImmediate: false, setTimeout: false, console: false */
		(function () {
		
		    var async = {};
		
		    // global on the server, window in the browser
		    var root, previous_async;
		
		    root = this;
		    if (root != null) {
		      previous_async = root.async;
		    }
		
		    async.noConflict = function () {
		        root.async = previous_async;
		        return async;
		    };
		
		    function only_once(fn) {
		        var called = false;
		        return function() {
		            if (called) throw new Error("Callback was already called.");
		            called = true;
		            fn.apply(root, arguments);
		        }
		    }
		
		    //// cross-browser compatiblity functions ////
		
		    var _each = function (arr, iterator) {
		        if (arr.forEach) {
		            return arr.forEach(iterator);
		        }
		        for (var i = 0; i < arr.length; i += 1) {
		            iterator(arr[i], i, arr);
		        }
		    };
		
		    var _map = function (arr, iterator) {
		        if (arr.map) {
		            return arr.map(iterator);
		        }
		        var results = [];
		        _each(arr, function (x, i, a) {
		            results.push(iterator(x, i, a));
		        });
		        return results;
		    };
		
		    var _reduce = function (arr, iterator, memo) {
		        if (arr.reduce) {
		            return arr.reduce(iterator, memo);
		        }
		        _each(arr, function (x, i, a) {
		            memo = iterator(memo, x, i, a);
		        });
		        return memo;
		    };
		
		    var _keys = function (obj) {
		        if (Object.keys) {
		            return Object.keys(obj);
		        }
		        var keys = [];
		        for (var k in obj) {
		            if (obj.hasOwnProperty(k)) {
		                keys.push(k);
		            }
		        }
		        return keys;
		    };
		
		    //// exported async module functions ////
		
		    //// nextTick implementation with browser-compatible fallback ////
		    if (typeof process === 'undefined' || !(process.nextTick)) {
		        if (typeof setImmediate === 'function') {
		            async.nextTick = function (fn) {
		                // not a direct alias for IE10 compatibility
		                setImmediate(fn);
		            };
		            async.setImmediate = async.nextTick;
		        }
		        else {
		            async.nextTick = function (fn) {
		                setTimeout(fn, 0);
		            };
		            async.setImmediate = async.nextTick;
		        }
		    }
		    else {
		        async.nextTick = process.nextTick;
		        if (typeof setImmediate !== 'undefined') {
		            async.setImmediate = function (fn) {
		              // not a direct alias for IE10 compatibility
		              setImmediate(fn);
		            };
		        }
		        else {
		            async.setImmediate = async.nextTick;
		        }
		    }
		
		    async.each = function (arr, iterator, callback) {
		        callback = callback || function () {};
		        if (!arr.length) {
		            return callback();
		        }
		        var completed = 0;
		        _each(arr, function (x) {
		            iterator(x, only_once(function (err) {
		                if (err) {
		                    callback(err);
		                    callback = function () {};
		                }
		                else {
		                    completed += 1;
		                    if (completed >= arr.length) {
		                        callback(null);
		                    }
		                }
		            }));
		        });
		    };
		    async.forEach = async.each;
		
		    async.eachSeries = function (arr, iterator, callback) {
		        callback = callback || function () {};
		        if (!arr.length) {
		            return callback();
		        }
		        var completed = 0;
		        var iterate = function () {
		            iterator(arr[completed], function (err) {
		                if (err) {
		                    callback(err);
		                    callback = function () {};
		                }
		                else {
		                    completed += 1;
		                    if (completed >= arr.length) {
		                        callback(null);
		                    }
		                    else {
		                        iterate();
		                    }
		                }
		            });
		        };
		        iterate();
		    };
		    async.forEachSeries = async.eachSeries;
		
		    async.eachLimit = function (arr, limit, iterator, callback) {
		        var fn = _eachLimit(limit);
		        fn.apply(null, [arr, iterator, callback]);
		    };
		    async.forEachLimit = async.eachLimit;
		
		    var _eachLimit = function (limit) {
		
		        return function (arr, iterator, callback) {
		            callback = callback || function () {};
		            if (!arr.length || limit <= 0) {
		                return callback();
		            }
		            var completed = 0;
		            var started = 0;
		            var running = 0;
		
		            (function replenish () {
		                if (completed >= arr.length) {
		                    return callback();
		                }
		
		                while (running < limit && started < arr.length) {
		                    started += 1;
		                    running += 1;
		                    iterator(arr[started - 1], function (err) {
		                        if (err) {
		                            callback(err);
		                            callback = function () {};
		                        }
		                        else {
		                            completed += 1;
		                            running -= 1;
		                            if (completed >= arr.length) {
		                                callback();
		                            }
		                            else {
		                                replenish();
		                            }
		                        }
		                    });
		                }
		            })();
		        };
		    };
		
		
		    var doParallel = function (fn) {
		        return function () {
		            var args = Array.prototype.slice.call(arguments);
		            return fn.apply(null, [async.each].concat(args));
		        };
		    };
		    var doParallelLimit = function(limit, fn) {
		        return function () {
		            var args = Array.prototype.slice.call(arguments);
		            return fn.apply(null, [_eachLimit(limit)].concat(args));
		        };
		    };
		    var doSeries = function (fn) {
		        return function () {
		            var args = Array.prototype.slice.call(arguments);
		            return fn.apply(null, [async.eachSeries].concat(args));
		        };
		    };
		
		
		    var _asyncMap = function (eachfn, arr, iterator, callback) {
		        var results = [];
		        arr = _map(arr, function (x, i) {
		            return {index: i, value: x};
		        });
		        eachfn(arr, function (x, callback) {
		            iterator(x.value, function (err, v) {
		                results[x.index] = v;
		                callback(err);
		            });
		        }, function (err) {
		            callback(err, results);
		        });
		    };
		    async.map = doParallel(_asyncMap);
		    async.mapSeries = doSeries(_asyncMap);
		    async.mapLimit = function (arr, limit, iterator, callback) {
		        return _mapLimit(limit)(arr, iterator, callback);
		    };
		
		    var _mapLimit = function(limit) {
		        return doParallelLimit(limit, _asyncMap);
		    };
		
		    // reduce only has a series version, as doing reduce in parallel won't
		    // work in many situations.
		    async.reduce = function (arr, memo, iterator, callback) {
		        async.eachSeries(arr, function (x, callback) {
		            iterator(memo, x, function (err, v) {
		                memo = v;
		                callback(err);
		            });
		        }, function (err) {
		            callback(err, memo);
		        });
		    };
		    // inject alias
		    async.inject = async.reduce;
		    // foldl alias
		    async.foldl = async.reduce;
		
		    async.reduceRight = function (arr, memo, iterator, callback) {
		        var reversed = _map(arr, function (x) {
		            return x;
		        }).reverse();
		        async.reduce(reversed, memo, iterator, callback);
		    };
		    // foldr alias
		    async.foldr = async.reduceRight;
		
		    var _filter = function (eachfn, arr, iterator, callback) {
		        var results = [];
		        arr = _map(arr, function (x, i) {
		            return {index: i, value: x};
		        });
		        eachfn(arr, function (x, callback) {
		            iterator(x.value, function (v) {
		                if (v) {
		                    results.push(x);
		                }
		                callback();
		            });
		        }, function (err) {
		            callback(_map(results.sort(function (a, b) {
		                return a.index - b.index;
		            }), function (x) {
		                return x.value;
		            }));
		        });
		    };
		    async.filter = doParallel(_filter);
		    async.filterSeries = doSeries(_filter);
		    // select alias
		    async.select = async.filter;
		    async.selectSeries = async.filterSeries;
		
		    var _reject = function (eachfn, arr, iterator, callback) {
		        var results = [];
		        arr = _map(arr, function (x, i) {
		            return {index: i, value: x};
		        });
		        eachfn(arr, function (x, callback) {
		            iterator(x.value, function (v) {
		                if (!v) {
		                    results.push(x);
		                }
		                callback();
		            });
		        }, function (err) {
		            callback(_map(results.sort(function (a, b) {
		                return a.index - b.index;
		            }), function (x) {
		                return x.value;
		            }));
		        });
		    };
		    async.reject = doParallel(_reject);
		    async.rejectSeries = doSeries(_reject);
		
		    var _detect = function (eachfn, arr, iterator, main_callback) {
		        eachfn(arr, function (x, callback) {
		            iterator(x, function (result) {
		                if (result) {
		                    main_callback(x);
		                    main_callback = function () {};
		                }
		                else {
		                    callback();
		                }
		            });
		        }, function (err) {
		            main_callback();
		        });
		    };
		    async.detect = doParallel(_detect);
		    async.detectSeries = doSeries(_detect);
		
		    async.some = function (arr, iterator, main_callback) {
		        async.each(arr, function (x, callback) {
		            iterator(x, function (v) {
		                if (v) {
		                    main_callback(true);
		                    main_callback = function () {};
		                }
		                callback();
		            });
		        }, function (err) {
		            main_callback(false);
		        });
		    };
		    // any alias
		    async.any = async.some;
		
		    async.every = function (arr, iterator, main_callback) {
		        async.each(arr, function (x, callback) {
		            iterator(x, function (v) {
		                if (!v) {
		                    main_callback(false);
		                    main_callback = function () {};
		                }
		                callback();
		            });
		        }, function (err) {
		            main_callback(true);
		        });
		    };
		    // all alias
		    async.all = async.every;
		
		    async.sortBy = function (arr, iterator, callback) {
		        async.map(arr, function (x, callback) {
		            iterator(x, function (err, criteria) {
		                if (err) {
		                    callback(err);
		                }
		                else {
		                    callback(null, {value: x, criteria: criteria});
		                }
		            });
		        }, function (err, results) {
		            if (err) {
		                return callback(err);
		            }
		            else {
		                var fn = function (left, right) {
		                    var a = left.criteria, b = right.criteria;
		                    return a < b ? -1 : a > b ? 1 : 0;
		                };
		                callback(null, _map(results.sort(fn), function (x) {
		                    return x.value;
		                }));
		            }
		        });
		    };
		
		    async.auto = function (tasks, callback) {
		        callback = callback || function () {};
		        var keys = _keys(tasks);
		        if (!keys.length) {
		            return callback(null);
		        }
		
		        var results = {};
		
		        var listeners = [];
		        var addListener = function (fn) {
		            listeners.unshift(fn);
		        };
		        var removeListener = function (fn) {
		            for (var i = 0; i < listeners.length; i += 1) {
		                if (listeners[i] === fn) {
		                    listeners.splice(i, 1);
		                    return;
		                }
		            }
		        };
		        var taskComplete = function () {
		            _each(listeners.slice(0), function (fn) {
		                fn();
		            });
		        };
		
		        addListener(function () {
		            if (_keys(results).length === keys.length) {
		                callback(null, results);
		                callback = function () {};
		            }
		        });
		
		        _each(keys, function (k) {
		            var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
		            var taskCallback = function (err) {
		                var args = Array.prototype.slice.call(arguments, 1);
		                if (args.length <= 1) {
		                    args = args[0];
		                }
		                if (err) {
		                    var safeResults = {};
		                    _each(_keys(results), function(rkey) {
		                        safeResults[rkey] = results[rkey];
		                    });
		                    safeResults[k] = args;
		                    callback(err, safeResults);
		                    // stop subsequent errors hitting callback multiple times
		                    callback = function () {};
		                }
		                else {
		                    results[k] = args;
		                    async.setImmediate(taskComplete);
		                }
		            };
		            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
		            var ready = function () {
		                return _reduce(requires, function (a, x) {
		                    return (a && results.hasOwnProperty(x));
		                }, true) && !results.hasOwnProperty(k);
		            };
		            if (ready()) {
		                task[task.length - 1](taskCallback, results);
		            }
		            else {
		                var listener = function () {
		                    if (ready()) {
		                        removeListener(listener);
		                        task[task.length - 1](taskCallback, results);
		                    }
		                };
		                addListener(listener);
		            }
		        });
		    };
		
		    async.waterfall = function (tasks, callback) {
		        callback = callback || function () {};
		        if (tasks.constructor !== Array) {
		          var err = new Error('First argument to waterfall must be an array of functions');
		          return callback(err);
		        }
		        if (!tasks.length) {
		            return callback();
		        }
		        var wrapIterator = function (iterator) {
		            return function (err) {
		                if (err) {
		                    callback.apply(null, arguments);
		                    callback = function () {};
		                }
		                else {
		                    var args = Array.prototype.slice.call(arguments, 1);
		                    var next = iterator.next();
		                    if (next) {
		                        args.push(wrapIterator(next));
		                    }
		                    else {
		                        args.push(callback);
		                    }
		                    async.setImmediate(function () {
		                        iterator.apply(null, args);
		                    });
		                }
		            };
		        };
		        wrapIterator(async.iterator(tasks))();
		    };
		
		    var _parallel = function(eachfn, tasks, callback) {
		        callback = callback || function () {};
		        if (tasks.constructor === Array) {
		            eachfn.map(tasks, function (fn, callback) {
		                if (fn) {
		                    fn(function (err) {
		                        var args = Array.prototype.slice.call(arguments, 1);
		                        if (args.length <= 1) {
		                            args = args[0];
		                        }
		                        callback.call(null, err, args);
		                    });
		                }
		            }, callback);
		        }
		        else {
		            var results = {};
		            eachfn.each(_keys(tasks), function (k, callback) {
		                tasks[k](function (err) {
		                    var args = Array.prototype.slice.call(arguments, 1);
		                    if (args.length <= 1) {
		                        args = args[0];
		                    }
		                    results[k] = args;
		                    callback(err);
		                });
		            }, function (err) {
		                callback(err, results);
		            });
		        }
		    };
		
		    async.parallel = function (tasks, callback) {
		        _parallel({ map: async.map, each: async.each }, tasks, callback);
		    };
		
		    async.parallelLimit = function(tasks, limit, callback) {
		        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
		    };
		
		    async.series = function (tasks, callback) {
		        callback = callback || function () {};
		        if (tasks.constructor === Array) {
		            async.mapSeries(tasks, function (fn, callback) {
		                if (fn) {
		                    fn(function (err) {
		                        var args = Array.prototype.slice.call(arguments, 1);
		                        if (args.length <= 1) {
		                            args = args[0];
		                        }
		                        callback.call(null, err, args);
		                    });
		                }
		            }, callback);
		        }
		        else {
		            var results = {};
		            async.eachSeries(_keys(tasks), function (k, callback) {
		                tasks[k](function (err) {
		                    var args = Array.prototype.slice.call(arguments, 1);
		                    if (args.length <= 1) {
		                        args = args[0];
		                    }
		                    results[k] = args;
		                    callback(err);
		                });
		            }, function (err) {
		                callback(err, results);
		            });
		        }
		    };
		
		    async.iterator = function (tasks) {
		        var makeCallback = function (index) {
		            var fn = function () {
		                if (tasks.length) {
		                    tasks[index].apply(null, arguments);
		                }
		                return fn.next();
		            };
		            fn.next = function () {
		                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
		            };
		            return fn;
		        };
		        return makeCallback(0);
		    };
		
		    async.apply = function (fn) {
		        var args = Array.prototype.slice.call(arguments, 1);
		        return function () {
		            return fn.apply(
		                null, args.concat(Array.prototype.slice.call(arguments))
		            );
		        };
		    };
		
		    var _concat = function (eachfn, arr, fn, callback) {
		        var r = [];
		        eachfn(arr, function (x, cb) {
		            fn(x, function (err, y) {
		                r = r.concat(y || []);
		                cb(err);
		            });
		        }, function (err) {
		            callback(err, r);
		        });
		    };
		    async.concat = doParallel(_concat);
		    async.concatSeries = doSeries(_concat);
		
		    async.whilst = function (test, iterator, callback) {
		        if (test()) {
		            iterator(function (err) {
		                if (err) {
		                    return callback(err);
		                }
		                async.whilst(test, iterator, callback);
		            });
		        }
		        else {
		            callback();
		        }
		    };
		
		    async.doWhilst = function (iterator, test, callback) {
		        iterator(function (err) {
		            if (err) {
		                return callback(err);
		            }
		            if (test()) {
		                async.doWhilst(iterator, test, callback);
		            }
		            else {
		                callback();
		            }
		        });
		    };
		
		    async.until = function (test, iterator, callback) {
		        if (!test()) {
		            iterator(function (err) {
		                if (err) {
		                    return callback(err);
		                }
		                async.until(test, iterator, callback);
		            });
		        }
		        else {
		            callback();
		        }
		    };
		
		    async.doUntil = function (iterator, test, callback) {
		        iterator(function (err) {
		            if (err) {
		                return callback(err);
		            }
		            if (!test()) {
		                async.doUntil(iterator, test, callback);
		            }
		            else {
		                callback();
		            }
		        });
		    };
		
		    async.queue = function (worker, concurrency) {
		        if (concurrency === undefined) {
		            concurrency = 1;
		        }
		        function _insert(q, data, pos, callback) {
		          if(data.constructor !== Array) {
		              data = [data];
		          }
		          _each(data, function(task) {
		              var item = {
		                  data: task,
		                  callback: typeof callback === 'function' ? callback : null
		              };
		
		              if (pos) {
		                q.tasks.unshift(item);
		              } else {
		                q.tasks.push(item);
		              }
		
		              if (q.saturated && q.tasks.length === concurrency) {
		                  q.saturated();
		              }
		              async.setImmediate(q.process);
		          });
		        }
		
		        var workers = 0;
		        var q = {
		            tasks: [],
		            concurrency: concurrency,
		            saturated: null,
		            empty: null,
		            drain: null,
		            push: function (data, callback) {
		              _insert(q, data, false, callback);
		            },
		            unshift: function (data, callback) {
		              _insert(q, data, true, callback);
		            },
		            process: function () {
		                if (workers < q.concurrency && q.tasks.length) {
		                    var task = q.tasks.shift();
		                    if (q.empty && q.tasks.length === 0) {
		                        q.empty();
		                    }
		                    workers += 1;
		                    var next = function () {
		                        workers -= 1;
		                        if (task.callback) {
		                            task.callback.apply(task, arguments);
		                        }
		                        if (q.drain && q.tasks.length + workers === 0) {
		                            q.drain();
		                        }
		                        q.process();
		                    };
		                    var cb = only_once(next);
		                    worker(task.data, cb);
		                }
		            },
		            length: function () {
		                return q.tasks.length;
		            },
		            running: function () {
		                return workers;
		            }
		        };
		        return q;
		    };
		
		    async.cargo = function (worker, payload) {
		        var working     = false,
		            tasks       = [];
		
		        var cargo = {
		            tasks: tasks,
		            payload: payload,
		            saturated: null,
		            empty: null,
		            drain: null,
		            push: function (data, callback) {
		                if(data.constructor !== Array) {
		                    data = [data];
		                }
		                _each(data, function(task) {
		                    tasks.push({
		                        data: task,
		                        callback: typeof callback === 'function' ? callback : null
		                    });
		                    if (cargo.saturated && tasks.length === payload) {
		                        cargo.saturated();
		                    }
		                });
		                async.setImmediate(cargo.process);
		            },
		            process: function process() {
		                if (working) return;
		                if (tasks.length === 0) {
		                    if(cargo.drain) cargo.drain();
		                    return;
		                }
		
		                var ts = typeof payload === 'number'
		                            ? tasks.splice(0, payload)
		                            : tasks.splice(0);
		
		                var ds = _map(ts, function (task) {
		                    return task.data;
		                });
		
		                if(cargo.empty) cargo.empty();
		                working = true;
		                worker(ds, function () {
		                    working = false;
		
		                    var args = arguments;
		                    _each(ts, function (data) {
		                        if (data.callback) {
		                            data.callback.apply(null, args);
		                        }
		                    });
		
		                    process();
		                });
		            },
		            length: function () {
		                return tasks.length;
		            },
		            running: function () {
		                return working;
		            }
		        };
		        return cargo;
		    };
		
		    var _console_fn = function (name) {
		        return function (fn) {
		            var args = Array.prototype.slice.call(arguments, 1);
		            fn.apply(null, args.concat([function (err) {
		                var args = Array.prototype.slice.call(arguments, 1);
		                if (typeof console !== 'undefined') {
		                    if (err) {
		                        if (console.error) {
		                            console.error(err);
		                        }
		                    }
		                    else if (console[name]) {
		                        _each(args, function (x) {
		                            console[name](x);
		                        });
		                    }
		                }
		            }]));
		        };
		    };
		    async.log = _console_fn('log');
		    async.dir = _console_fn('dir');
		    /*async.info = _console_fn('info');
		    async.warn = _console_fn('warn');
		    async.error = _console_fn('error');*/
		
		    async.memoize = function (fn, hasher) {
		        var memo = {};
		        var queues = {};
		        hasher = hasher || function (x) {
		            return x;
		        };
		        var memoized = function () {
		            var args = Array.prototype.slice.call(arguments);
		            var callback = args.pop();
		            var key = hasher.apply(null, args);
		            if (key in memo) {
		                callback.apply(null, memo[key]);
		            }
		            else if (key in queues) {
		                queues[key].push(callback);
		            }
		            else {
		                queues[key] = [callback];
		                fn.apply(null, args.concat([function () {
		                    memo[key] = arguments;
		                    var q = queues[key];
		                    delete queues[key];
		                    for (var i = 0, l = q.length; i < l; i++) {
		                      q[i].apply(null, arguments);
		                    }
		                }]));
		            }
		        };
		        memoized.memo = memo;
		        memoized.unmemoized = fn;
		        return memoized;
		    };
		
		    async.unmemoize = function (fn) {
		      return function () {
		        return (fn.unmemoized || fn).apply(null, arguments);
		      };
		    };
		
		    async.times = function (count, iterator, callback) {
		        var counter = [];
		        for (var i = 0; i < count; i++) {
		            counter.push(i);
		        }
		        return async.map(counter, iterator, callback);
		    };
		
		    async.timesSeries = function (count, iterator, callback) {
		        var counter = [];
		        for (var i = 0; i < count; i++) {
		            counter.push(i);
		        }
		        return async.mapSeries(counter, iterator, callback);
		    };
		
		    async.compose = function (/* functions... */) {
		        var fns = Array.prototype.reverse.call(arguments);
		        return function () {
		            var that = this;
		            var args = Array.prototype.slice.call(arguments);
		            var callback = args.pop();
		            async.reduce(fns, args, function (newargs, fn, cb) {
		                fn.apply(that, newargs.concat([function () {
		                    var err = arguments[0];
		                    var nextargs = Array.prototype.slice.call(arguments, 1);
		                    cb(err, nextargs);
		                }]))
		            },
		            function (err, results) {
		                callback.apply(that, [err].concat(results));
		            });
		        };
		    };
		
		    var _applyEach = function (eachfn, fns /*args...*/) {
		        var go = function () {
		            var that = this;
		            var args = Array.prototype.slice.call(arguments);
		            var callback = args.pop();
		            return eachfn(fns, function (fn, cb) {
		                fn.apply(that, args.concat([cb]));
		            },
		            callback);
		        };
		        if (arguments.length > 2) {
		            var args = Array.prototype.slice.call(arguments, 2);
		            return go.apply(this, args);
		        }
		        else {
		            return go;
		        }
		    };
		    async.applyEach = doParallel(_applyEach);
		    async.applyEachSeries = doSeries(_applyEach);
		
		    async.forever = function (fn, callback) {
		        function next(err) {
		            if (err) {
		                if (callback) {
		                    return callback(err);
		                }
		                throw err;
		            }
		            fn(next);
		        }
		        next();
		    };
		
		    // AMD / RequireJS
		    if (typeof define !== 'undefined' && define.amd) {
		        define([], function () {
		            return async;
		        });
		    }
		    // Node.js
		    else if (typeof module !== 'undefined' && module.exports) {
		        module.exports = async;
		    }
		    // included directly via <script> tag
		    else {
		        root.async = async;
		    }
		
		}());
		
	
	}, 'moment/moment.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'moment/moment.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'moment/moment.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'moment/moment.js';
		var __dirname = 'moment';
		var process = {cwd: function() {return '/';}, argv: ['node', 'moment/moment.js'], env: {}};
	
		/** code **/
		//! moment.js
		//! version : 2.5.1
		//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
		//! license : MIT
		//! momentjs.com
		
		(function (undefined) {
		
		    /************************************
		        Constants
		    ************************************/
		
		    var moment,
		        VERSION = "2.5.1",
		        global = this,
		        round = Math.round,
		        i,
		
		        YEAR = 0,
		        MONTH = 1,
		        DATE = 2,
		        HOUR = 3,
		        MINUTE = 4,
		        SECOND = 5,
		        MILLISECOND = 6,
		
		        // internal storage for language config files
		        languages = {},
		
		        // moment internal properties
		        momentProperties = {
		            _isAMomentObject: null,
		            _i : null,
		            _f : null,
		            _l : null,
		            _strict : null,
		            _isUTC : null,
		            _offset : null,  // optional. Combine with _isUTC
		            _pf : null,
		            _lang : null  // optional
		        },
		
		        // check for nodeJS
		        hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
		
		        // ASP.NET json date format regex
		        aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
		        aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
		
		        // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
		        // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
		        isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
		
		        // format tokens
		        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
		        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
		
		        // parsing token regexes
		        parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
		        parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
		        parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
		        parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
		        parseTokenDigits = /\d+/, // nonzero number of digits
		        parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
		        parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
		        parseTokenT = /T/i, // T (ISO separator)
		        parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
		
		        //strict parsing regexes
		        parseTokenOneDigit = /\d/, // 0 - 9
		        parseTokenTwoDigits = /\d\d/, // 00 - 99
		        parseTokenThreeDigits = /\d{3}/, // 000 - 999
		        parseTokenFourDigits = /\d{4}/, // 0000 - 9999
		        parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
		        parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
		
		        // iso 8601 regex
		        // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
		        isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
		
		        isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
		
		        isoDates = [
		            ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
		            ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
		            ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
		            ['GGGG-[W]WW', /\d{4}-W\d{2}/],
		            ['YYYY-DDD', /\d{4}-\d{3}/]
		        ],
		
		        // iso time formats and regexes
		        isoTimes = [
		            ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
		            ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
		            ['HH:mm', /(T| )\d\d:\d\d/],
		            ['HH', /(T| )\d\d/]
		        ],
		
		        // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
		        parseTimezoneChunker = /([\+\-]|\d\d)/gi,
		
		        // getter and setter names
		        proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
		        unitMillisecondFactors = {
		            'Milliseconds' : 1,
		            'Seconds' : 1e3,
		            'Minutes' : 6e4,
		            'Hours' : 36e5,
		            'Days' : 864e5,
		            'Months' : 2592e6,
		            'Years' : 31536e6
		        },
		
		        unitAliases = {
		            ms : 'millisecond',
		            s : 'second',
		            m : 'minute',
		            h : 'hour',
		            d : 'day',
		            D : 'date',
		            w : 'week',
		            W : 'isoWeek',
		            M : 'month',
		            y : 'year',
		            DDD : 'dayOfYear',
		            e : 'weekday',
		            E : 'isoWeekday',
		            gg: 'weekYear',
		            GG: 'isoWeekYear'
		        },
		
		        camelFunctions = {
		            dayofyear : 'dayOfYear',
		            isoweekday : 'isoWeekday',
		            isoweek : 'isoWeek',
		            weekyear : 'weekYear',
		            isoweekyear : 'isoWeekYear'
		        },
		
		        // format function strings
		        formatFunctions = {},
		
		        // tokens to ordinalize and pad
		        ordinalizeTokens = 'DDD w W M D d'.split(' '),
		        paddedTokens = 'M D H h m s w W'.split(' '),
		
		        formatTokenFunctions = {
		            M    : function () {
		                return this.month() + 1;
		            },
		            MMM  : function (format) {
		                return this.lang().monthsShort(this, format);
		            },
		            MMMM : function (format) {
		                return this.lang().months(this, format);
		            },
		            D    : function () {
		                return this.date();
		            },
		            DDD  : function () {
		                return this.dayOfYear();
		            },
		            d    : function () {
		                return this.day();
		            },
		            dd   : function (format) {
		                return this.lang().weekdaysMin(this, format);
		            },
		            ddd  : function (format) {
		                return this.lang().weekdaysShort(this, format);
		            },
		            dddd : function (format) {
		                return this.lang().weekdays(this, format);
		            },
		            w    : function () {
		                return this.week();
		            },
		            W    : function () {
		                return this.isoWeek();
		            },
		            YY   : function () {
		                return leftZeroFill(this.year() % 100, 2);
		            },
		            YYYY : function () {
		                return leftZeroFill(this.year(), 4);
		            },
		            YYYYY : function () {
		                return leftZeroFill(this.year(), 5);
		            },
		            YYYYYY : function () {
		                var y = this.year(), sign = y >= 0 ? '+' : '-';
		                return sign + leftZeroFill(Math.abs(y), 6);
		            },
		            gg   : function () {
		                return leftZeroFill(this.weekYear() % 100, 2);
		            },
		            gggg : function () {
		                return leftZeroFill(this.weekYear(), 4);
		            },
		            ggggg : function () {
		                return leftZeroFill(this.weekYear(), 5);
		            },
		            GG   : function () {
		                return leftZeroFill(this.isoWeekYear() % 100, 2);
		            },
		            GGGG : function () {
		                return leftZeroFill(this.isoWeekYear(), 4);
		            },
		            GGGGG : function () {
		                return leftZeroFill(this.isoWeekYear(), 5);
		            },
		            e : function () {
		                return this.weekday();
		            },
		            E : function () {
		                return this.isoWeekday();
		            },
		            a    : function () {
		                return this.lang().meridiem(this.hours(), this.minutes(), true);
		            },
		            A    : function () {
		                return this.lang().meridiem(this.hours(), this.minutes(), false);
		            },
		            H    : function () {
		                return this.hours();
		            },
		            h    : function () {
		                return this.hours() % 12 || 12;
		            },
		            m    : function () {
		                return this.minutes();
		            },
		            s    : function () {
		                return this.seconds();
		            },
		            S    : function () {
		                return toInt(this.milliseconds() / 100);
		            },
		            SS   : function () {
		                return leftZeroFill(toInt(this.milliseconds() / 10), 2);
		            },
		            SSS  : function () {
		                return leftZeroFill(this.milliseconds(), 3);
		            },
		            SSSS : function () {
		                return leftZeroFill(this.milliseconds(), 3);
		            },
		            Z    : function () {
		                var a = -this.zone(),
		                    b = "+";
		                if (a < 0) {
		                    a = -a;
		                    b = "-";
		                }
		                return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
		            },
		            ZZ   : function () {
		                var a = -this.zone(),
		                    b = "+";
		                if (a < 0) {
		                    a = -a;
		                    b = "-";
		                }
		                return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
		            },
		            z : function () {
		                return this.zoneAbbr();
		            },
		            zz : function () {
		                return this.zoneName();
		            },
		            X    : function () {
		                return this.unix();
		            },
		            Q : function () {
		                return this.quarter();
		            }
		        },
		
		        lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
		
		    function defaultParsingFlags() {
		        // We need to deep clone this object, and es5 standard is not very
		        // helpful.
		        return {
		            empty : false,
		            unusedTokens : [],
		            unusedInput : [],
		            overflow : -2,
		            charsLeftOver : 0,
		            nullInput : false,
		            invalidMonth : null,
		            invalidFormat : false,
		            userInvalidated : false,
		            iso: false
		        };
		    }
		
		    function padToken(func, count) {
		        return function (a) {
		            return leftZeroFill(func.call(this, a), count);
		        };
		    }
		    function ordinalizeToken(func, period) {
		        return function (a) {
		            return this.lang().ordinal(func.call(this, a), period);
		        };
		    }
		
		    while (ordinalizeTokens.length) {
		        i = ordinalizeTokens.pop();
		        formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
		    }
		    while (paddedTokens.length) {
		        i = paddedTokens.pop();
		        formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
		    }
		    formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
		
		
		    /************************************
		        Constructors
		    ************************************/
		
		    function Language() {
		
		    }
		
		    // Moment prototype object
		    function Moment(config) {
		        checkOverflow(config);
		        extend(this, config);
		    }
		
		    // Duration Constructor
		    function Duration(duration) {
		        var normalizedInput = normalizeObjectUnits(duration),
		            years = normalizedInput.year || 0,
		            months = normalizedInput.month || 0,
		            weeks = normalizedInput.week || 0,
		            days = normalizedInput.day || 0,
		            hours = normalizedInput.hour || 0,
		            minutes = normalizedInput.minute || 0,
		            seconds = normalizedInput.second || 0,
		            milliseconds = normalizedInput.millisecond || 0;
		
		        // representation for dateAddRemove
		        this._milliseconds = +milliseconds +
		            seconds * 1e3 + // 1000
		            minutes * 6e4 + // 1000 * 60
		            hours * 36e5; // 1000 * 60 * 60
		        // Because of dateAddRemove treats 24 hours as different from a
		        // day when working around DST, we need to store them separately
		        this._days = +days +
		            weeks * 7;
		        // It is impossible translate months into days without knowing
		        // which months you are are talking about, so we have to store
		        // it separately.
		        this._months = +months +
		            years * 12;
		
		        this._data = {};
		
		        this._bubble();
		    }
		
		    /************************************
		        Helpers
		    ************************************/
		
		
		    function extend(a, b) {
		        for (var i in b) {
		            if (b.hasOwnProperty(i)) {
		                a[i] = b[i];
		            }
		        }
		
		        if (b.hasOwnProperty("toString")) {
		            a.toString = b.toString;
		        }
		
		        if (b.hasOwnProperty("valueOf")) {
		            a.valueOf = b.valueOf;
		        }
		
		        return a;
		    }
		
		    function cloneMoment(m) {
		        var result = {}, i;
		        for (i in m) {
		            if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
		                result[i] = m[i];
		            }
		        }
		
		        return result;
		    }
		
		    function absRound(number) {
		        if (number < 0) {
		            return Math.ceil(number);
		        } else {
		            return Math.floor(number);
		        }
		    }
		
		    // left zero fill a number
		    // see http://jsperf.com/left-zero-filling for performance comparison
		    function leftZeroFill(number, targetLength, forceSign) {
		        var output = '' + Math.abs(number),
		            sign = number >= 0;
		
		        while (output.length < targetLength) {
		            output = '0' + output;
		        }
		        return (sign ? (forceSign ? '+' : '') : '-') + output;
		    }
		
		    // helper function for _.addTime and _.subtractTime
		    function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
		        var milliseconds = duration._milliseconds,
		            days = duration._days,
		            months = duration._months,
		            minutes,
		            hours;
		
		        if (milliseconds) {
		            mom._d.setTime(+mom._d + milliseconds * isAdding);
		        }
		        // store the minutes and hours so we can restore them
		        if (days || months) {
		            minutes = mom.minute();
		            hours = mom.hour();
		        }
		        if (days) {
		            mom.date(mom.date() + days * isAdding);
		        }
		        if (months) {
		            mom.month(mom.month() + months * isAdding);
		        }
		        if (milliseconds && !ignoreUpdateOffset) {
		            moment.updateOffset(mom);
		        }
		        // restore the minutes and hours after possibly changing dst
		        if (days || months) {
		            mom.minute(minutes);
		            mom.hour(hours);
		        }
		    }
		
		    // check if is an array
		    function isArray(input) {
		        return Object.prototype.toString.call(input) === '[object Array]';
		    }
		
		    function isDate(input) {
		        return  Object.prototype.toString.call(input) === '[object Date]' ||
		                input instanceof Date;
		    }
		
		    // compare two arrays, return the number of differences
		    function compareArrays(array1, array2, dontConvert) {
		        var len = Math.min(array1.length, array2.length),
		            lengthDiff = Math.abs(array1.length - array2.length),
		            diffs = 0,
		            i;
		        for (i = 0; i < len; i++) {
		            if ((dontConvert && array1[i] !== array2[i]) ||
		                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
		                diffs++;
		            }
		        }
		        return diffs + lengthDiff;
		    }
		
		    function normalizeUnits(units) {
		        if (units) {
		            var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
		            units = unitAliases[units] || camelFunctions[lowered] || lowered;
		        }
		        return units;
		    }
		
		    function normalizeObjectUnits(inputObject) {
		        var normalizedInput = {},
		            normalizedProp,
		            prop;
		
		        for (prop in inputObject) {
		            if (inputObject.hasOwnProperty(prop)) {
		                normalizedProp = normalizeUnits(prop);
		                if (normalizedProp) {
		                    normalizedInput[normalizedProp] = inputObject[prop];
		                }
		            }
		        }
		
		        return normalizedInput;
		    }
		
		    function makeList(field) {
		        var count, setter;
		
		        if (field.indexOf('week') === 0) {
		            count = 7;
		            setter = 'day';
		        }
		        else if (field.indexOf('month') === 0) {
		            count = 12;
		            setter = 'month';
		        }
		        else {
		            return;
		        }
		
		        moment[field] = function (format, index) {
		            var i, getter,
		                method = moment.fn._lang[field],
		                results = [];
		
		            if (typeof format === 'number') {
		                index = format;
		                format = undefined;
		            }
		
		            getter = function (i) {
		                var m = moment().utc().set(setter, i);
		                return method.call(moment.fn._lang, m, format || '');
		            };
		
		            if (index != null) {
		                return getter(index);
		            }
		            else {
		                for (i = 0; i < count; i++) {
		                    results.push(getter(i));
		                }
		                return results;
		            }
		        };
		    }
		
		    function toInt(argumentForCoercion) {
		        var coercedNumber = +argumentForCoercion,
		            value = 0;
		
		        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
		            if (coercedNumber >= 0) {
		                value = Math.floor(coercedNumber);
		            } else {
		                value = Math.ceil(coercedNumber);
		            }
		        }
		
		        return value;
		    }
		
		    function daysInMonth(year, month) {
		        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
		    }
		
		    function daysInYear(year) {
		        return isLeapYear(year) ? 366 : 365;
		    }
		
		    function isLeapYear(year) {
		        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
		    }
		
		    function checkOverflow(m) {
		        var overflow;
		        if (m._a && m._pf.overflow === -2) {
		            overflow =
		                m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
		                m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
		                m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
		                m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
		                m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
		                m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
		                -1;
		
		            if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
		                overflow = DATE;
		            }
		
		            m._pf.overflow = overflow;
		        }
		    }
		
		    function isValid(m) {
		        if (m._isValid == null) {
		            m._isValid = !isNaN(m._d.getTime()) &&
		                m._pf.overflow < 0 &&
		                !m._pf.empty &&
		                !m._pf.invalidMonth &&
		                !m._pf.nullInput &&
		                !m._pf.invalidFormat &&
		                !m._pf.userInvalidated;
		
		            if (m._strict) {
		                m._isValid = m._isValid &&
		                    m._pf.charsLeftOver === 0 &&
		                    m._pf.unusedTokens.length === 0;
		            }
		        }
		        return m._isValid;
		    }
		
		    function normalizeLanguage(key) {
		        return key ? key.toLowerCase().replace('_', '-') : key;
		    }
		
		    // Return a moment from input, that is local/utc/zone equivalent to model.
		    function makeAs(input, model) {
		        return model._isUTC ? moment(input).zone(model._offset || 0) :
		            moment(input).local();
		    }
		
		    /************************************
		        Languages
		    ************************************/
		
		
		    extend(Language.prototype, {
		
		        set : function (config) {
		            var prop, i;
		            for (i in config) {
		                prop = config[i];
		                if (typeof prop === 'function') {
		                    this[i] = prop;
		                } else {
		                    this['_' + i] = prop;
		                }
		            }
		        },
		
		        _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
		        months : function (m) {
		            return this._months[m.month()];
		        },
		
		        _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
		        monthsShort : function (m) {
		            return this._monthsShort[m.month()];
		        },
		
		        monthsParse : function (monthName) {
		            var i, mom, regex;
		
		            if (!this._monthsParse) {
		                this._monthsParse = [];
		            }
		
		            for (i = 0; i < 12; i++) {
		                // make the regex if we don't have it already
		                if (!this._monthsParse[i]) {
		                    mom = moment.utc([2000, i]);
		                    regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
		                    this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
		                }
		                // test the regex
		                if (this._monthsParse[i].test(monthName)) {
		                    return i;
		                }
		            }
		        },
		
		        _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
		        weekdays : function (m) {
		            return this._weekdays[m.day()];
		        },
		
		        _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
		        weekdaysShort : function (m) {
		            return this._weekdaysShort[m.day()];
		        },
		
		        _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
		        weekdaysMin : function (m) {
		            return this._weekdaysMin[m.day()];
		        },
		
		        weekdaysParse : function (weekdayName) {
		            var i, mom, regex;
		
		            if (!this._weekdaysParse) {
		                this._weekdaysParse = [];
		            }
		
		            for (i = 0; i < 7; i++) {
		                // make the regex if we don't have it already
		                if (!this._weekdaysParse[i]) {
		                    mom = moment([2000, 1]).day(i);
		                    regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
		                    this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
		                }
		                // test the regex
		                if (this._weekdaysParse[i].test(weekdayName)) {
		                    return i;
		                }
		            }
		        },
		
		        _longDateFormat : {
		            LT : "h:mm A",
		            L : "MM/DD/YYYY",
		            LL : "MMMM D YYYY",
		            LLL : "MMMM D YYYY LT",
		            LLLL : "dddd, MMMM D YYYY LT"
		        },
		        longDateFormat : function (key) {
		            var output = this._longDateFormat[key];
		            if (!output && this._longDateFormat[key.toUpperCase()]) {
		                output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
		                    return val.slice(1);
		                });
		                this._longDateFormat[key] = output;
		            }
		            return output;
		        },
		
		        isPM : function (input) {
		            // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
		            // Using charAt should be more compatible.
		            return ((input + '').toLowerCase().charAt(0) === 'p');
		        },
		
		        _meridiemParse : /[ap]\.?m?\.?/i,
		        meridiem : function (hours, minutes, isLower) {
		            if (hours > 11) {
		                return isLower ? 'pm' : 'PM';
		            } else {
		                return isLower ? 'am' : 'AM';
		            }
		        },
		
		        _calendar : {
		            sameDay : '[Today at] LT',
		            nextDay : '[Tomorrow at] LT',
		            nextWeek : 'dddd [at] LT',
		            lastDay : '[Yesterday at] LT',
		            lastWeek : '[Last] dddd [at] LT',
		            sameElse : 'L'
		        },
		        calendar : function (key, mom) {
		            var output = this._calendar[key];
		            return typeof output === 'function' ? output.apply(mom) : output;
		        },
		
		        _relativeTime : {
		            future : "in %s",
		            past : "%s ago",
		            s : "a few seconds",
		            m : "a minute",
		            mm : "%d minutes",
		            h : "an hour",
		            hh : "%d hours",
		            d : "a day",
		            dd : "%d days",
		            M : "a month",
		            MM : "%d months",
		            y : "a year",
		            yy : "%d years"
		        },
		        relativeTime : function (number, withoutSuffix, string, isFuture) {
		            var output = this._relativeTime[string];
		            return (typeof output === 'function') ?
		                output(number, withoutSuffix, string, isFuture) :
		                output.replace(/%d/i, number);
		        },
		        pastFuture : function (diff, output) {
		            var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
		            return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
		        },
		
		        ordinal : function (number) {
		            return this._ordinal.replace("%d", number);
		        },
		        _ordinal : "%d",
		
		        preparse : function (string) {
		            return string;
		        },
		
		        postformat : function (string) {
		            return string;
		        },
		
		        week : function (mom) {
		            return weekOfYear(mom, this._week.dow, this._week.doy).week;
		        },
		
		        _week : {
		            dow : 0, // Sunday is the first day of the week.
		            doy : 6  // The week that contains Jan 1st is the first week of the year.
		        },
		
		        _invalidDate: 'Invalid date',
		        invalidDate: function () {
		            return this._invalidDate;
		        }
		    });
		
		    // Loads a language definition into the `languages` cache.  The function
		    // takes a key and optionally values.  If not in the browser and no values
		    // are provided, it will load the language file module.  As a convenience,
		    // this function also returns the language values.
		    function loadLang(key, values) {
		        values.abbr = key;
		        if (!languages[key]) {
		            languages[key] = new Language();
		        }
		        languages[key].set(values);
		        return languages[key];
		    }
		
		    // Remove a language from the `languages` cache. Mostly useful in tests.
		    function unloadLang(key) {
		        delete languages[key];
		    }
		
		    // Determines which language definition to use and returns it.
		    //
		    // With no parameters, it will return the global language.  If you
		    // pass in a language key, such as 'en', it will return the
		    // definition for 'en', so long as 'en' has already been loaded using
		    // moment.lang.
		    function getLangDefinition(key) {
		        var i = 0, j, lang, next, split,
		            get = function (k) {
		                if (!languages[k] && hasModule) {
		                    try {
		                        require('./lang/' + k);
		                    } catch (e) { }
		                }
		                return languages[k];
		            };
		
		        if (!key) {
		            return moment.fn._lang;
		        }
		
		        if (!isArray(key)) {
		            //short-circuit everything else
		            lang = get(key);
		            if (lang) {
		                return lang;
		            }
		            key = [key];
		        }
		
		        //pick the language from the array
		        //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
		        //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
		        while (i < key.length) {
		            split = normalizeLanguage(key[i]).split('-');
		            j = split.length;
		            next = normalizeLanguage(key[i + 1]);
		            next = next ? next.split('-') : null;
		            while (j > 0) {
		                lang = get(split.slice(0, j).join('-'));
		                if (lang) {
		                    return lang;
		                }
		                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
		                    //the next array item is better than a shallower substring of this one
		                    break;
		                }
		                j--;
		            }
		            i++;
		        }
		        return moment.fn._lang;
		    }
		
		    /************************************
		        Formatting
		    ************************************/
		
		
		    function removeFormattingTokens(input) {
		        if (input.match(/\[[\s\S]/)) {
		            return input.replace(/^\[|\]$/g, "");
		        }
		        return input.replace(/\\/g, "");
		    }
		
		    function makeFormatFunction(format) {
		        var array = format.match(formattingTokens), i, length;
		
		        for (i = 0, length = array.length; i < length; i++) {
		            if (formatTokenFunctions[array[i]]) {
		                array[i] = formatTokenFunctions[array[i]];
		            } else {
		                array[i] = removeFormattingTokens(array[i]);
		            }
		        }
		
		        return function (mom) {
		            var output = "";
		            for (i = 0; i < length; i++) {
		                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
		            }
		            return output;
		        };
		    }
		
		    // format date using native date object
		    function formatMoment(m, format) {
		
		        if (!m.isValid()) {
		            return m.lang().invalidDate();
		        }
		
		        format = expandFormat(format, m.lang());
		
		        if (!formatFunctions[format]) {
		            formatFunctions[format] = makeFormatFunction(format);
		        }
		
		        return formatFunctions[format](m);
		    }
		
		    function expandFormat(format, lang) {
		        var i = 5;
		
		        function replaceLongDateFormatTokens(input) {
		            return lang.longDateFormat(input) || input;
		        }
		
		        localFormattingTokens.lastIndex = 0;
		        while (i >= 0 && localFormattingTokens.test(format)) {
		            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
		            localFormattingTokens.lastIndex = 0;
		            i -= 1;
		        }
		
		        return format;
		    }
		
		
		    /************************************
		        Parsing
		    ************************************/
		
		
		    // get the regex to find the next token
		    function getParseRegexForToken(token, config) {
		        var a, strict = config._strict;
		        switch (token) {
		        case 'DDDD':
		            return parseTokenThreeDigits;
		        case 'YYYY':
		        case 'GGGG':
		        case 'gggg':
		            return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
		        case 'Y':
		        case 'G':
		        case 'g':
		            return parseTokenSignedNumber;
		        case 'YYYYYY':
		        case 'YYYYY':
		        case 'GGGGG':
		        case 'ggggg':
		            return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
		        case 'S':
		            if (strict) { return parseTokenOneDigit; }
		            /* falls through */
		        case 'SS':
		            if (strict) { return parseTokenTwoDigits; }
		            /* falls through */
		        case 'SSS':
		            if (strict) { return parseTokenThreeDigits; }
		            /* falls through */
		        case 'DDD':
		            return parseTokenOneToThreeDigits;
		        case 'MMM':
		        case 'MMMM':
		        case 'dd':
		        case 'ddd':
		        case 'dddd':
		            return parseTokenWord;
		        case 'a':
		        case 'A':
		            return getLangDefinition(config._l)._meridiemParse;
		        case 'X':
		            return parseTokenTimestampMs;
		        case 'Z':
		        case 'ZZ':
		            return parseTokenTimezone;
		        case 'T':
		            return parseTokenT;
		        case 'SSSS':
		            return parseTokenDigits;
		        case 'MM':
		        case 'DD':
		        case 'YY':
		        case 'GG':
		        case 'gg':
		        case 'HH':
		        case 'hh':
		        case 'mm':
		        case 'ss':
		        case 'ww':
		        case 'WW':
		            return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
		        case 'M':
		        case 'D':
		        case 'd':
		        case 'H':
		        case 'h':
		        case 'm':
		        case 's':
		        case 'w':
		        case 'W':
		        case 'e':
		        case 'E':
		            return parseTokenOneOrTwoDigits;
		        default :
		            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
		            return a;
		        }
		    }
		
		    function timezoneMinutesFromString(string) {
		        string = string || "";
		        var possibleTzMatches = (string.match(parseTokenTimezone) || []),
		            tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
		            parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
		            minutes = +(parts[1] * 60) + toInt(parts[2]);
		
		        return parts[0] === '+' ? -minutes : minutes;
		    }
		
		    // function to convert string input to date
		    function addTimeToArrayFromToken(token, input, config) {
		        var a, datePartArray = config._a;
		
		        switch (token) {
		        // MONTH
		        case 'M' : // fall through to MM
		        case 'MM' :
		            if (input != null) {
		                datePartArray[MONTH] = toInt(input) - 1;
		            }
		            break;
		        case 'MMM' : // fall through to MMMM
		        case 'MMMM' :
		            a = getLangDefinition(config._l).monthsParse(input);
		            // if we didn't find a month name, mark the date as invalid.
		            if (a != null) {
		                datePartArray[MONTH] = a;
		            } else {
		                config._pf.invalidMonth = input;
		            }
		            break;
		        // DAY OF MONTH
		        case 'D' : // fall through to DD
		        case 'DD' :
		            if (input != null) {
		                datePartArray[DATE] = toInt(input);
		            }
		            break;
		        // DAY OF YEAR
		        case 'DDD' : // fall through to DDDD
		        case 'DDDD' :
		            if (input != null) {
		                config._dayOfYear = toInt(input);
		            }
		
		            break;
		        // YEAR
		        case 'YY' :
		            datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
		            break;
		        case 'YYYY' :
		        case 'YYYYY' :
		        case 'YYYYYY' :
		            datePartArray[YEAR] = toInt(input);
		            break;
		        // AM / PM
		        case 'a' : // fall through to A
		        case 'A' :
		            config._isPm = getLangDefinition(config._l).isPM(input);
		            break;
		        // 24 HOUR
		        case 'H' : // fall through to hh
		        case 'HH' : // fall through to hh
		        case 'h' : // fall through to hh
		        case 'hh' :
		            datePartArray[HOUR] = toInt(input);
		            break;
		        // MINUTE
		        case 'm' : // fall through to mm
		        case 'mm' :
		            datePartArray[MINUTE] = toInt(input);
		            break;
		        // SECOND
		        case 's' : // fall through to ss
		        case 'ss' :
		            datePartArray[SECOND] = toInt(input);
		            break;
		        // MILLISECOND
		        case 'S' :
		        case 'SS' :
		        case 'SSS' :
		        case 'SSSS' :
		            datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
		            break;
		        // UNIX TIMESTAMP WITH MS
		        case 'X':
		            config._d = new Date(parseFloat(input) * 1000);
		            break;
		        // TIMEZONE
		        case 'Z' : // fall through to ZZ
		        case 'ZZ' :
		            config._useUTC = true;
		            config._tzm = timezoneMinutesFromString(input);
		            break;
		        case 'w':
		        case 'ww':
		        case 'W':
		        case 'WW':
		        case 'd':
		        case 'dd':
		        case 'ddd':
		        case 'dddd':
		        case 'e':
		        case 'E':
		            token = token.substr(0, 1);
		            /* falls through */
		        case 'gg':
		        case 'gggg':
		        case 'GG':
		        case 'GGGG':
		        case 'GGGGG':
		            token = token.substr(0, 2);
		            if (input) {
		                config._w = config._w || {};
		                config._w[token] = input;
		            }
		            break;
		        }
		    }
		
		    // convert an array to a date.
		    // the array should mirror the parameters below
		    // note: all values past the year are optional and will default to the lowest possible value.
		    // [year, month, day , hour, minute, second, millisecond]
		    function dateFromConfig(config) {
		        var i, date, input = [], currentDate,
		            yearToUse, fixYear, w, temp, lang, weekday, week;
		
		        if (config._d) {
		            return;
		        }
		
		        currentDate = currentDateArray(config);
		
		        //compute day of the year from weeks and weekdays
		        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
		            fixYear = function (val) {
		                var int_val = parseInt(val, 10);
		                return val ?
		                  (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
		                  (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
		            };
		
		            w = config._w;
		            if (w.GG != null || w.W != null || w.E != null) {
		                temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
		            }
		            else {
		                lang = getLangDefinition(config._l);
		                weekday = w.d != null ?  parseWeekday(w.d, lang) :
		                  (w.e != null ?  parseInt(w.e, 10) + lang._week.dow : 0);
		
		                week = parseInt(w.w, 10) || 1;
		
		                //if we're parsing 'd', then the low day numbers may be next week
		                if (w.d != null && weekday < lang._week.dow) {
		                    week++;
		                }
		
		                temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
		            }
		
		            config._a[YEAR] = temp.year;
		            config._dayOfYear = temp.dayOfYear;
		        }
		
		        //if the day of the year is set, figure out what it is
		        if (config._dayOfYear) {
		            yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
		
		            if (config._dayOfYear > daysInYear(yearToUse)) {
		                config._pf._overflowDayOfYear = true;
		            }
		
		            date = makeUTCDate(yearToUse, 0, config._dayOfYear);
		            config._a[MONTH] = date.getUTCMonth();
		            config._a[DATE] = date.getUTCDate();
		        }
		
		        // Default to current date.
		        // * if no year, month, day of month are given, default to today
		        // * if day of month is given, default month and year
		        // * if month is given, default only year
		        // * if year is given, don't default anything
		        for (i = 0; i < 3 && config._a[i] == null; ++i) {
		            config._a[i] = input[i] = currentDate[i];
		        }
		
		        // Zero out whatever was not defaulted, including time
		        for (; i < 7; i++) {
		            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
		        }
		
		        // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
		        input[HOUR] += toInt((config._tzm || 0) / 60);
		        input[MINUTE] += toInt((config._tzm || 0) % 60);
		
		        config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
		    }
		
		    function dateFromObject(config) {
		        var normalizedInput;
		
		        if (config._d) {
		            return;
		        }
		
		        normalizedInput = normalizeObjectUnits(config._i);
		        config._a = [
		            normalizedInput.year,
		            normalizedInput.month,
		            normalizedInput.day,
		            normalizedInput.hour,
		            normalizedInput.minute,
		            normalizedInput.second,
		            normalizedInput.millisecond
		        ];
		
		        dateFromConfig(config);
		    }
		
		    function currentDateArray(config) {
		        var now = new Date();
		        if (config._useUTC) {
		            return [
		                now.getUTCFullYear(),
		                now.getUTCMonth(),
		                now.getUTCDate()
		            ];
		        } else {
		            return [now.getFullYear(), now.getMonth(), now.getDate()];
		        }
		    }
		
		    // date from string and format string
		    function makeDateFromStringAndFormat(config) {
		
		        config._a = [];
		        config._pf.empty = true;
		
		        // This array is used to make a Date, either with `new Date` or `Date.UTC`
		        var lang = getLangDefinition(config._l),
		            string = '' + config._i,
		            i, parsedInput, tokens, token, skipped,
		            stringLength = string.length,
		            totalParsedInputLength = 0;
		
		        tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
		
		        for (i = 0; i < tokens.length; i++) {
		            token = tokens[i];
		            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
		            if (parsedInput) {
		                skipped = string.substr(0, string.indexOf(parsedInput));
		                if (skipped.length > 0) {
		                    config._pf.unusedInput.push(skipped);
		                }
		                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
		                totalParsedInputLength += parsedInput.length;
		            }
		            // don't parse if it's not a known token
		            if (formatTokenFunctions[token]) {
		                if (parsedInput) {
		                    config._pf.empty = false;
		                }
		                else {
		                    config._pf.unusedTokens.push(token);
		                }
		                addTimeToArrayFromToken(token, parsedInput, config);
		            }
		            else if (config._strict && !parsedInput) {
		                config._pf.unusedTokens.push(token);
		            }
		        }
		
		        // add remaining unparsed input length to the string
		        config._pf.charsLeftOver = stringLength - totalParsedInputLength;
		        if (string.length > 0) {
		            config._pf.unusedInput.push(string);
		        }
		
		        // handle am pm
		        if (config._isPm && config._a[HOUR] < 12) {
		            config._a[HOUR] += 12;
		        }
		        // if is 12 am, change hours to 0
		        if (config._isPm === false && config._a[HOUR] === 12) {
		            config._a[HOUR] = 0;
		        }
		
		        dateFromConfig(config);
		        checkOverflow(config);
		    }
		
		    function unescapeFormat(s) {
		        return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
		            return p1 || p2 || p3 || p4;
		        });
		    }
		
		    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
		    function regexpEscape(s) {
		        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
		    }
		
		    // date from string and array of format strings
		    function makeDateFromStringAndArray(config) {
		        var tempConfig,
		            bestMoment,
		
		            scoreToBeat,
		            i,
		            currentScore;
		
		        if (config._f.length === 0) {
		            config._pf.invalidFormat = true;
		            config._d = new Date(NaN);
		            return;
		        }
		
		        for (i = 0; i < config._f.length; i++) {
		            currentScore = 0;
		            tempConfig = extend({}, config);
		            tempConfig._pf = defaultParsingFlags();
		            tempConfig._f = config._f[i];
		            makeDateFromStringAndFormat(tempConfig);
		
		            if (!isValid(tempConfig)) {
		                continue;
		            }
		
		            // if there is any input that was not parsed add a penalty for that format
		            currentScore += tempConfig._pf.charsLeftOver;
		
		            //or tokens
		            currentScore += tempConfig._pf.unusedTokens.length * 10;
		
		            tempConfig._pf.score = currentScore;
		
		            if (scoreToBeat == null || currentScore < scoreToBeat) {
		                scoreToBeat = currentScore;
		                bestMoment = tempConfig;
		            }
		        }
		
		        extend(config, bestMoment || tempConfig);
		    }
		
		    // date from iso format
		    function makeDateFromString(config) {
		        var i, l,
		            string = config._i,
		            match = isoRegex.exec(string);
		
		        if (match) {
		            config._pf.iso = true;
		            for (i = 0, l = isoDates.length; i < l; i++) {
		                if (isoDates[i][1].exec(string)) {
		                    // match[5] should be "T" or undefined
		                    config._f = isoDates[i][0] + (match[6] || " ");
		                    break;
		                }
		            }
		            for (i = 0, l = isoTimes.length; i < l; i++) {
		                if (isoTimes[i][1].exec(string)) {
		                    config._f += isoTimes[i][0];
		                    break;
		                }
		            }
		            if (string.match(parseTokenTimezone)) {
		                config._f += "Z";
		            }
		            makeDateFromStringAndFormat(config);
		        }
		        else {
		            config._d = new Date(string);
		        }
		    }
		
		    function makeDateFromInput(config) {
		        var input = config._i,
		            matched = aspNetJsonRegex.exec(input);
		
		        if (input === undefined) {
		            config._d = new Date();
		        } else if (matched) {
		            config._d = new Date(+matched[1]);
		        } else if (typeof input === 'string') {
		            makeDateFromString(config);
		        } else if (isArray(input)) {
		            config._a = input.slice(0);
		            dateFromConfig(config);
		        } else if (isDate(input)) {
		            config._d = new Date(+input);
		        } else if (typeof(input) === 'object') {
		            dateFromObject(config);
		        } else {
		            config._d = new Date(input);
		        }
		    }
		
		    function makeDate(y, m, d, h, M, s, ms) {
		        //can't just apply() to create a date:
		        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
		        var date = new Date(y, m, d, h, M, s, ms);
		
		        //the date constructor doesn't accept years < 1970
		        if (y < 1970) {
		            date.setFullYear(y);
		        }
		        return date;
		    }
		
		    function makeUTCDate(y) {
		        var date = new Date(Date.UTC.apply(null, arguments));
		        if (y < 1970) {
		            date.setUTCFullYear(y);
		        }
		        return date;
		    }
		
		    function parseWeekday(input, language) {
		        if (typeof input === 'string') {
		            if (!isNaN(input)) {
		                input = parseInt(input, 10);
		            }
		            else {
		                input = language.weekdaysParse(input);
		                if (typeof input !== 'number') {
		                    return null;
		                }
		            }
		        }
		        return input;
		    }
		
		    /************************************
		        Relative Time
		    ************************************/
		
		
		    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
		    function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
		        return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
		    }
		
		    function relativeTime(milliseconds, withoutSuffix, lang) {
		        var seconds = round(Math.abs(milliseconds) / 1000),
		            minutes = round(seconds / 60),
		            hours = round(minutes / 60),
		            days = round(hours / 24),
		            years = round(days / 365),
		            args = seconds < 45 && ['s', seconds] ||
		                minutes === 1 && ['m'] ||
		                minutes < 45 && ['mm', minutes] ||
		                hours === 1 && ['h'] ||
		                hours < 22 && ['hh', hours] ||
		                days === 1 && ['d'] ||
		                days <= 25 && ['dd', days] ||
		                days <= 45 && ['M'] ||
		                days < 345 && ['MM', round(days / 30)] ||
		                years === 1 && ['y'] || ['yy', years];
		        args[2] = withoutSuffix;
		        args[3] = milliseconds > 0;
		        args[4] = lang;
		        return substituteTimeAgo.apply({}, args);
		    }
		
		
		    /************************************
		        Week of Year
		    ************************************/
		
		
		    // firstDayOfWeek       0 = sun, 6 = sat
		    //                      the day of the week that starts the week
		    //                      (usually sunday or monday)
		    // firstDayOfWeekOfYear 0 = sun, 6 = sat
		    //                      the first week is the week that contains the first
		    //                      of this day of the week
		    //                      (eg. ISO weeks use thursday (4))
		    function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
		        var end = firstDayOfWeekOfYear - firstDayOfWeek,
		            daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
		            adjustedMoment;
		
		
		        if (daysToDayOfWeek > end) {
		            daysToDayOfWeek -= 7;
		        }
		
		        if (daysToDayOfWeek < end - 7) {
		            daysToDayOfWeek += 7;
		        }
		
		        adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
		        return {
		            week: Math.ceil(adjustedMoment.dayOfYear() / 7),
		            year: adjustedMoment.year()
		        };
		    }
		
		    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
		    function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
		        var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
		
		        weekday = weekday != null ? weekday : firstDayOfWeek;
		        daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
		        dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
		
		        return {
		            year: dayOfYear > 0 ? year : year - 1,
		            dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
		        };
		    }
		
		    /************************************
		        Top Level Functions
		    ************************************/
		
		    function makeMoment(config) {
		        var input = config._i,
		            format = config._f;
		
		        if (input === null) {
		            return moment.invalid({nullInput: true});
		        }
		
		        if (typeof input === 'string') {
		            config._i = input = getLangDefinition().preparse(input);
		        }
		
		        if (moment.isMoment(input)) {
		            config = cloneMoment(input);
		
		            config._d = new Date(+input._d);
		        } else if (format) {
		            if (isArray(format)) {
		                makeDateFromStringAndArray(config);
		            } else {
		                makeDateFromStringAndFormat(config);
		            }
		        } else {
		            makeDateFromInput(config);
		        }
		
		        return new Moment(config);
		    }
		
		    moment = function (input, format, lang, strict) {
		        var c;
		
		        if (typeof(lang) === "boolean") {
		            strict = lang;
		            lang = undefined;
		        }
		        // object construction must be done this way.
		        // https://github.com/moment/moment/issues/1423
		        c = {};
		        c._isAMomentObject = true;
		        c._i = input;
		        c._f = format;
		        c._l = lang;
		        c._strict = strict;
		        c._isUTC = false;
		        c._pf = defaultParsingFlags();
		
		        return makeMoment(c);
		    };
		
		    // creating with utc
		    moment.utc = function (input, format, lang, strict) {
		        var c;
		
		        if (typeof(lang) === "boolean") {
		            strict = lang;
		            lang = undefined;
		        }
		        // object construction must be done this way.
		        // https://github.com/moment/moment/issues/1423
		        c = {};
		        c._isAMomentObject = true;
		        c._useUTC = true;
		        c._isUTC = true;
		        c._l = lang;
		        c._i = input;
		        c._f = format;
		        c._strict = strict;
		        c._pf = defaultParsingFlags();
		
		        return makeMoment(c).utc();
		    };
		
		    // creating with unix timestamp (in seconds)
		    moment.unix = function (input) {
		        return moment(input * 1000);
		    };
		
		    // duration
		    moment.duration = function (input, key) {
		        var duration = input,
		            // matching against regexp is expensive, do it on demand
		            match = null,
		            sign,
		            ret,
		            parseIso;
		
		        if (moment.isDuration(input)) {
		            duration = {
		                ms: input._milliseconds,
		                d: input._days,
		                M: input._months
		            };
		        } else if (typeof input === 'number') {
		            duration = {};
		            if (key) {
		                duration[key] = input;
		            } else {
		                duration.milliseconds = input;
		            }
		        } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
		            sign = (match[1] === "-") ? -1 : 1;
		            duration = {
		                y: 0,
		                d: toInt(match[DATE]) * sign,
		                h: toInt(match[HOUR]) * sign,
		                m: toInt(match[MINUTE]) * sign,
		                s: toInt(match[SECOND]) * sign,
		                ms: toInt(match[MILLISECOND]) * sign
		            };
		        } else if (!!(match = isoDurationRegex.exec(input))) {
		            sign = (match[1] === "-") ? -1 : 1;
		            parseIso = function (inp) {
		                // We'd normally use ~~inp for this, but unfortunately it also
		                // converts floats to ints.
		                // inp may be undefined, so careful calling replace on it.
		                var res = inp && parseFloat(inp.replace(',', '.'));
		                // apply sign while we're at it
		                return (isNaN(res) ? 0 : res) * sign;
		            };
		            duration = {
		                y: parseIso(match[2]),
		                M: parseIso(match[3]),
		                d: parseIso(match[4]),
		                h: parseIso(match[5]),
		                m: parseIso(match[6]),
		                s: parseIso(match[7]),
		                w: parseIso(match[8])
		            };
		        }
		
		        ret = new Duration(duration);
		
		        if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
		            ret._lang = input._lang;
		        }
		
		        return ret;
		    };
		
		    // version number
		    moment.version = VERSION;
		
		    // default format
		    moment.defaultFormat = isoFormat;
		
		    // This function will be called whenever a moment is mutated.
		    // It is intended to keep the offset in sync with the timezone.
		    moment.updateOffset = function () {};
		
		    // This function will load languages and then set the global language.  If
		    // no arguments are passed in, it will simply return the current global
		    // language key.
		    moment.lang = function (key, values) {
		        var r;
		        if (!key) {
		            return moment.fn._lang._abbr;
		        }
		        if (values) {
		            loadLang(normalizeLanguage(key), values);
		        } else if (values === null) {
		            unloadLang(key);
		            key = 'en';
		        } else if (!languages[key]) {
		            getLangDefinition(key);
		        }
		        r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
		        return r._abbr;
		    };
		
		    // returns language data
		    moment.langData = function (key) {
		        if (key && key._lang && key._lang._abbr) {
		            key = key._lang._abbr;
		        }
		        return getLangDefinition(key);
		    };
		
		    // compare moment object
		    moment.isMoment = function (obj) {
		        return obj instanceof Moment ||
		            (obj != null &&  obj.hasOwnProperty('_isAMomentObject'));
		    };
		
		    // for typechecking Duration objects
		    moment.isDuration = function (obj) {
		        return obj instanceof Duration;
		    };
		
		    for (i = lists.length - 1; i >= 0; --i) {
		        makeList(lists[i]);
		    }
		
		    moment.normalizeUnits = function (units) {
		        return normalizeUnits(units);
		    };
		
		    moment.invalid = function (flags) {
		        var m = moment.utc(NaN);
		        if (flags != null) {
		            extend(m._pf, flags);
		        }
		        else {
		            m._pf.userInvalidated = true;
		        }
		
		        return m;
		    };
		
		    moment.parseZone = function (input) {
		        return moment(input).parseZone();
		    };
		
		    /************************************
		        Moment Prototype
		    ************************************/
		
		
		    extend(moment.fn = Moment.prototype, {
		
		        clone : function () {
		            return moment(this);
		        },
		
		        valueOf : function () {
		            return +this._d + ((this._offset || 0) * 60000);
		        },
		
		        unix : function () {
		            return Math.floor(+this / 1000);
		        },
		
		        toString : function () {
		            return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
		        },
		
		        toDate : function () {
		            return this._offset ? new Date(+this) : this._d;
		        },
		
		        toISOString : function () {
		            var m = moment(this).utc();
		            if (0 < m.year() && m.year() <= 9999) {
		                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
		            } else {
		                return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
		            }
		        },
		
		        toArray : function () {
		            var m = this;
		            return [
		                m.year(),
		                m.month(),
		                m.date(),
		                m.hours(),
		                m.minutes(),
		                m.seconds(),
		                m.milliseconds()
		            ];
		        },
		
		        isValid : function () {
		            return isValid(this);
		        },
		
		        isDSTShifted : function () {
		
		            if (this._a) {
		                return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
		            }
		
		            return false;
		        },
		
		        parsingFlags : function () {
		            return extend({}, this._pf);
		        },
		
		        invalidAt: function () {
		            return this._pf.overflow;
		        },
		
		        utc : function () {
		            return this.zone(0);
		        },
		
		        local : function () {
		            this.zone(0);
		            this._isUTC = false;
		            return this;
		        },
		
		        format : function (inputString) {
		            var output = formatMoment(this, inputString || moment.defaultFormat);
		            return this.lang().postformat(output);
		        },
		
		        add : function (input, val) {
		            var dur;
		            // switch args to support add('s', 1) and add(1, 's')
		            if (typeof input === 'string') {
		                dur = moment.duration(+val, input);
		            } else {
		                dur = moment.duration(input, val);
		            }
		            addOrSubtractDurationFromMoment(this, dur, 1);
		            return this;
		        },
		
		        subtract : function (input, val) {
		            var dur;
		            // switch args to support subtract('s', 1) and subtract(1, 's')
		            if (typeof input === 'string') {
		                dur = moment.duration(+val, input);
		            } else {
		                dur = moment.duration(input, val);
		            }
		            addOrSubtractDurationFromMoment(this, dur, -1);
		            return this;
		        },
		
		        diff : function (input, units, asFloat) {
		            var that = makeAs(input, this),
		                zoneDiff = (this.zone() - that.zone()) * 6e4,
		                diff, output;
		
		            units = normalizeUnits(units);
		
		            if (units === 'year' || units === 'month') {
		                // average number of days in the months in the given dates
		                diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
		                // difference in months
		                output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
		                // adjust by taking difference in days, average number of days
		                // and dst in the given months.
		                output += ((this - moment(this).startOf('month')) -
		                        (that - moment(that).startOf('month'))) / diff;
		                // same as above but with zones, to negate all dst
		                output -= ((this.zone() - moment(this).startOf('month').zone()) -
		                        (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
		                if (units === 'year') {
		                    output = output / 12;
		                }
		            } else {
		                diff = (this - that);
		                output = units === 'second' ? diff / 1e3 : // 1000
		                    units === 'minute' ? diff / 6e4 : // 1000 * 60
		                    units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
		                    units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
		                    units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
		                    diff;
		            }
		            return asFloat ? output : absRound(output);
		        },
		
		        from : function (time, withoutSuffix) {
		            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
		        },
		
		        fromNow : function (withoutSuffix) {
		            return this.from(moment(), withoutSuffix);
		        },
		
		        calendar : function () {
		            // We want to compare the start of today, vs this.
		            // Getting start-of-today depends on whether we're zone'd or not.
		            var sod = makeAs(moment(), this).startOf('day'),
		                diff = this.diff(sod, 'days', true),
		                format = diff < -6 ? 'sameElse' :
		                    diff < -1 ? 'lastWeek' :
		                    diff < 0 ? 'lastDay' :
		                    diff < 1 ? 'sameDay' :
		                    diff < 2 ? 'nextDay' :
		                    diff < 7 ? 'nextWeek' : 'sameElse';
		            return this.format(this.lang().calendar(format, this));
		        },
		
		        isLeapYear : function () {
		            return isLeapYear(this.year());
		        },
		
		        isDST : function () {
		            return (this.zone() < this.clone().month(0).zone() ||
		                this.zone() < this.clone().month(5).zone());
		        },
		
		        day : function (input) {
		            var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
		            if (input != null) {
		                input = parseWeekday(input, this.lang());
		                return this.add({ d : input - day });
		            } else {
		                return day;
		            }
		        },
		
		        month : function (input) {
		            var utc = this._isUTC ? 'UTC' : '',
		                dayOfMonth;
		
		            if (input != null) {
		                if (typeof input === 'string') {
		                    input = this.lang().monthsParse(input);
		                    if (typeof input !== 'number') {
		                        return this;
		                    }
		                }
		
		                dayOfMonth = this.date();
		                this.date(1);
		                this._d['set' + utc + 'Month'](input);
		                this.date(Math.min(dayOfMonth, this.daysInMonth()));
		
		                moment.updateOffset(this);
		                return this;
		            } else {
		                return this._d['get' + utc + 'Month']();
		            }
		        },
		
		        startOf: function (units) {
		            units = normalizeUnits(units);
		            // the following switch intentionally omits break keywords
		            // to utilize falling through the cases.
		            switch (units) {
		            case 'year':
		                this.month(0);
		                /* falls through */
		            case 'month':
		                this.date(1);
		                /* falls through */
		            case 'week':
		            case 'isoWeek':
		            case 'day':
		                this.hours(0);
		                /* falls through */
		            case 'hour':
		                this.minutes(0);
		                /* falls through */
		            case 'minute':
		                this.seconds(0);
		                /* falls through */
		            case 'second':
		                this.milliseconds(0);
		                /* falls through */
		            }
		
		            // weeks are a special case
		            if (units === 'week') {
		                this.weekday(0);
		            } else if (units === 'isoWeek') {
		                this.isoWeekday(1);
		            }
		
		            return this;
		        },
		
		        endOf: function (units) {
		            units = normalizeUnits(units);
		            return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
		        },
		
		        isAfter: function (input, units) {
		            units = typeof units !== 'undefined' ? units : 'millisecond';
		            return +this.clone().startOf(units) > +moment(input).startOf(units);
		        },
		
		        isBefore: function (input, units) {
		            units = typeof units !== 'undefined' ? units : 'millisecond';
		            return +this.clone().startOf(units) < +moment(input).startOf(units);
		        },
		
		        isSame: function (input, units) {
		            units = units || 'ms';
		            return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
		        },
		
		        min: function (other) {
		            other = moment.apply(null, arguments);
		            return other < this ? this : other;
		        },
		
		        max: function (other) {
		            other = moment.apply(null, arguments);
		            return other > this ? this : other;
		        },
		
		        zone : function (input) {
		            var offset = this._offset || 0;
		            if (input != null) {
		                if (typeof input === "string") {
		                    input = timezoneMinutesFromString(input);
		                }
		                if (Math.abs(input) < 16) {
		                    input = input * 60;
		                }
		                this._offset = input;
		                this._isUTC = true;
		                if (offset !== input) {
		                    addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
		                }
		            } else {
		                return this._isUTC ? offset : this._d.getTimezoneOffset();
		            }
		            return this;
		        },
		
		        zoneAbbr : function () {
		            return this._isUTC ? "UTC" : "";
		        },
		
		        zoneName : function () {
		            return this._isUTC ? "Coordinated Universal Time" : "";
		        },
		
		        parseZone : function () {
		            if (this._tzm) {
		                this.zone(this._tzm);
		            } else if (typeof this._i === 'string') {
		                this.zone(this._i);
		            }
		            return this;
		        },
		
		        hasAlignedHourOffset : function (input) {
		            if (!input) {
		                input = 0;
		            }
		            else {
		                input = moment(input).zone();
		            }
		
		            return (this.zone() - input) % 60 === 0;
		        },
		
		        daysInMonth : function () {
		            return daysInMonth(this.year(), this.month());
		        },
		
		        dayOfYear : function (input) {
		            var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
		            return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
		        },
		
		        quarter : function () {
		            return Math.ceil((this.month() + 1.0) / 3.0);
		        },
		
		        weekYear : function (input) {
		            var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
		            return input == null ? year : this.add("y", (input - year));
		        },
		
		        isoWeekYear : function (input) {
		            var year = weekOfYear(this, 1, 4).year;
		            return input == null ? year : this.add("y", (input - year));
		        },
		
		        week : function (input) {
		            var week = this.lang().week(this);
		            return input == null ? week : this.add("d", (input - week) * 7);
		        },
		
		        isoWeek : function (input) {
		            var week = weekOfYear(this, 1, 4).week;
		            return input == null ? week : this.add("d", (input - week) * 7);
		        },
		
		        weekday : function (input) {
		            var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
		            return input == null ? weekday : this.add("d", input - weekday);
		        },
		
		        isoWeekday : function (input) {
		            // behaves the same as moment#day except
		            // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
		            // as a setter, sunday should belong to the previous week.
		            return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
		        },
		
		        get : function (units) {
		            units = normalizeUnits(units);
		            return this[units]();
		        },
		
		        set : function (units, value) {
		            units = normalizeUnits(units);
		            if (typeof this[units] === 'function') {
		                this[units](value);
		            }
		            return this;
		        },
		
		        // If passed a language key, it will set the language for this
		        // instance.  Otherwise, it will return the language configuration
		        // variables for this instance.
		        lang : function (key) {
		            if (key === undefined) {
		                return this._lang;
		            } else {
		                this._lang = getLangDefinition(key);
		                return this;
		            }
		        }
		    });
		
		    // helper for adding shortcuts
		    function makeGetterAndSetter(name, key) {
		        moment.fn[name] = moment.fn[name + 's'] = function (input) {
		            var utc = this._isUTC ? 'UTC' : '';
		            if (input != null) {
		                this._d['set' + utc + key](input);
		                moment.updateOffset(this);
		                return this;
		            } else {
		                return this._d['get' + utc + key]();
		            }
		        };
		    }
		
		    // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
		    for (i = 0; i < proxyGettersAndSetters.length; i ++) {
		        makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
		    }
		
		    // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
		    makeGetterAndSetter('year', 'FullYear');
		
		    // add plural methods
		    moment.fn.days = moment.fn.day;
		    moment.fn.months = moment.fn.month;
		    moment.fn.weeks = moment.fn.week;
		    moment.fn.isoWeeks = moment.fn.isoWeek;
		
		    // add aliased format methods
		    moment.fn.toJSON = moment.fn.toISOString;
		
		    /************************************
		        Duration Prototype
		    ************************************/
		
		
		    extend(moment.duration.fn = Duration.prototype, {
		
		        _bubble : function () {
		            var milliseconds = this._milliseconds,
		                days = this._days,
		                months = this._months,
		                data = this._data,
		                seconds, minutes, hours, years;
		
		            // The following code bubbles up values, see the tests for
		            // examples of what that means.
		            data.milliseconds = milliseconds % 1000;
		
		            seconds = absRound(milliseconds / 1000);
		            data.seconds = seconds % 60;
		
		            minutes = absRound(seconds / 60);
		            data.minutes = minutes % 60;
		
		            hours = absRound(minutes / 60);
		            data.hours = hours % 24;
		
		            days += absRound(hours / 24);
		            data.days = days % 30;
		
		            months += absRound(days / 30);
		            data.months = months % 12;
		
		            years = absRound(months / 12);
		            data.years = years;
		        },
		
		        weeks : function () {
		            return absRound(this.days() / 7);
		        },
		
		        valueOf : function () {
		            return this._milliseconds +
		              this._days * 864e5 +
		              (this._months % 12) * 2592e6 +
		              toInt(this._months / 12) * 31536e6;
		        },
		
		        humanize : function (withSuffix) {
		            var difference = +this,
		                output = relativeTime(difference, !withSuffix, this.lang());
		
		            if (withSuffix) {
		                output = this.lang().pastFuture(difference, output);
		            }
		
		            return this.lang().postformat(output);
		        },
		
		        add : function (input, val) {
		            // supports only 2.0-style add(1, 's') or add(moment)
		            var dur = moment.duration(input, val);
		
		            this._milliseconds += dur._milliseconds;
		            this._days += dur._days;
		            this._months += dur._months;
		
		            this._bubble();
		
		            return this;
		        },
		
		        subtract : function (input, val) {
		            var dur = moment.duration(input, val);
		
		            this._milliseconds -= dur._milliseconds;
		            this._days -= dur._days;
		            this._months -= dur._months;
		
		            this._bubble();
		
		            return this;
		        },
		
		        get : function (units) {
		            units = normalizeUnits(units);
		            return this[units.toLowerCase() + 's']();
		        },
		
		        as : function (units) {
		            units = normalizeUnits(units);
		            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
		        },
		
		        lang : moment.fn.lang,
		
		        toIsoString : function () {
		            // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
		            var years = Math.abs(this.years()),
		                months = Math.abs(this.months()),
		                days = Math.abs(this.days()),
		                hours = Math.abs(this.hours()),
		                minutes = Math.abs(this.minutes()),
		                seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
		
		            if (!this.asSeconds()) {
		                // this is the same as C#'s (Noda) and python (isodate)...
		                // but not other JS (goog.date)
		                return 'P0D';
		            }
		
		            return (this.asSeconds() < 0 ? '-' : '') +
		                'P' +
		                (years ? years + 'Y' : '') +
		                (months ? months + 'M' : '') +
		                (days ? days + 'D' : '') +
		                ((hours || minutes || seconds) ? 'T' : '') +
		                (hours ? hours + 'H' : '') +
		                (minutes ? minutes + 'M' : '') +
		                (seconds ? seconds + 'S' : '');
		        }
		    });
		
		    function makeDurationGetter(name) {
		        moment.duration.fn[name] = function () {
		            return this._data[name];
		        };
		    }
		
		    function makeDurationAsGetter(name, factor) {
		        moment.duration.fn['as' + name] = function () {
		            return +this / factor;
		        };
		    }
		
		    for (i in unitMillisecondFactors) {
		        if (unitMillisecondFactors.hasOwnProperty(i)) {
		            makeDurationAsGetter(i, unitMillisecondFactors[i]);
		            makeDurationGetter(i.toLowerCase());
		        }
		    }
		
		    makeDurationAsGetter('Weeks', 6048e5);
		    moment.duration.fn.asMonths = function () {
		        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
		    };
		
		
		    /************************************
		        Default Lang
		    ************************************/
		
		
		    // Set default language, other languages will inherit from English.
		    moment.lang('en', {
		        ordinal : function (number) {
		            var b = number % 10,
		                output = (toInt(number % 100 / 10) === 1) ? 'th' :
		                (b === 1) ? 'st' :
		                (b === 2) ? 'nd' :
		                (b === 3) ? 'rd' : 'th';
		            return number + output;
		        }
		    });
		
		    /* EMBED_LANGUAGES */
		
		    /************************************
		        Exposing Moment
		    ************************************/
		
		    function makeGlobal(deprecate) {
		        var warned = false, local_moment = moment;
		        /*global ender:false */
		        if (typeof ender !== 'undefined') {
		            return;
		        }
		        // here, `this` means `window` in the browser, or `global` on the server
		        // add `moment` as a global object via a string identifier,
		        // for Closure Compiler "advanced" mode
		        if (deprecate) {
		            global.moment = function () {
		                if (!warned && console && console.warn) {
		                    warned = true;
		                    console.warn(
		                            "Accessing Moment through the global scope is " +
		                            "deprecated, and will be removed in an upcoming " +
		                            "release.");
		                }
		                return local_moment.apply(null, arguments);
		            };
		            extend(global.moment, local_moment);
		        } else {
		            global['moment'] = moment;
		        }
		    }
		
		    // CommonJS module is defined
		    if (hasModule) {
		        module.exports = moment;
		        makeGlobal(true);
		    } else if (typeof define === "function" && define.amd) {
		        define("moment", function (require, exports, module) {
		            if (module.config && module.config() && module.config().noGlobal !== true) {
		                // If user provided noGlobal, he is aware of global
		                makeGlobal(module.config().noGlobal === undefined);
		            }
		
		            return moment;
		        });
		    } else {
		        makeGlobal();
		    }
		}).call(this);
		
	
	}, 'operator-compare/lib/Compare.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'operator-compare/lib/Compare.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'operator-compare/lib/Compare.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'operator-compare/lib/Compare.js';
		var __dirname = 'operator-compare/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'operator-compare/lib/Compare.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  module.exports = function(left, operator, right) {
		    switch (operator) {
		      case '>':
		        return left > right;
		      case '>=':
		        return left >= right;
		      case '<':
		        return left < right;
		      case '<=':
		        return left <= right;
		      case '=':
		      case '==':
		        return left === right;
		      case '!':
		      case '!=':
		      case '<>':
		        return left !== right;
		      default:
		        throw new Error('Unknown operator ' + operator + '.', '^.');
		    }
		  };
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Async/Storage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Async/Storage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Async/Storage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Async/Storage.js';
		var __dirname = 'cache-storage/lib/Storage/Async';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Async/Storage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var BaseStorage, Cache, Storage, async, isWindow, moment, path, _ref,
		    __hasProp = {}.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; };
		
		  isWindow = typeof window === 'undefined' ? false : true;
		
		  if (!isWindow) {
		    path = require('path');
		  }
		
		  BaseStorage = require('../Storage');
		
		  moment = require('moment');
		
		  Cache = require('../../Cache');
		
		  async = require('async');
		
		  Storage = (function(_super) {
		    __extends(Storage, _super);
		
		    function Storage() {
		      _ref = Storage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    Storage.prototype.async = true;
		
		    Storage.prototype.read = function(key, fn) {
		      var _this = this;
		      return this.getData(function(err, data) {
		        if (err) {
		          return fn(err, null);
		        } else if (typeof data[key] === 'undefined') {
		          return fn(null, null);
		        } else {
		          return _this.findMeta(key, function(err, meta) {
		            if (err) {
		              return fn(err, null);
		            } else {
		              return _this.verify(meta, function(err, state) {
		                if (err) {
		                  return fn(err, null);
		                } else if (state) {
		                  return fn(null, data[key]);
		                } else {
		                  return _this.remove(key, function(err) {
		                    if (err) {
		                      return fn(err, null);
		                    } else {
		                      return fn(null, null);
		                    }
		                  });
		                }
		              });
		            }
		          });
		        }
		      });
		    };
		
		    Storage.prototype.write = function(key, data, dependencies, fn) {
		      var _this = this;
		      if (dependencies == null) {
		        dependencies = {};
		      }
		      return this.getData(function(err, all) {
		        if (err) {
		          return fn(err);
		        } else {
		          all[key] = data;
		          return _this.getMeta(function(err, meta) {
		            if (err) {
		              return fn(err);
		            } else {
		              meta[key] = dependencies;
		              return _this.writeData(all, meta, fn);
		            }
		          });
		        }
		      });
		    };
		
		    Storage.prototype.remove = function(key, fn) {
		      var _this = this;
		      return this.getData(function(err, data) {
		        if (err) {
		          return fn(err);
		        } else {
		          return _this.getMeta(function(err, meta) {
		            if (err) {
		              return fn(err);
		            } else {
		              if (typeof data[key] !== 'undefined') {
		                delete data[key];
		                delete meta[key];
		              }
		              return _this.writeData(data, meta, fn);
		            }
		          });
		        }
		      });
		    };
		
		    Storage.prototype.removeAll = function(fn) {
		      return this.writeData({}, {}, fn);
		    };
		
		    Storage.prototype.clean = function(conditions, fn) {
		      var keys, removeKeys, type, typeFn,
		        _this = this;
		      typeFn = Object.prototype.toString;
		      type = typeFn.call(conditions);
		      if (conditions === Cache.ALL) {
		        this.removeAll(fn);
		      } else if (type === '[object Object]') {
		        if (typeof conditions[Cache.TAGS] === 'undefined') {
		          conditions[Cache.TAGS] = [];
		        }
		        if (typeFn(conditions[Cache.TAGS]) === '[object String]') {
		          conditions[Cache.TAGS] = [conditions[Cache.TAGS]];
		        }
		        removeKeys = function(keys) {
		          return async.eachSeries(keys, function(key, cb) {
		            return _this.remove(key, function(err) {
		              return cb(err);
		            });
		          }, function(err) {
		            return fn(err);
		          });
		        };
		        keys = [];
		        async.eachSeries(conditions[Cache.TAGS], function(tag, cb) {
		          return _this.findKeysByTag(tag, function(err, _keys) {
		            keys = keys.concat(_keys);
		            return cb(err);
		          });
		        }, function(err) {
		          if (err) {
		            return fn(err);
		          } else if (typeof conditions[Cache.PRIORITY] === 'undefined') {
		            return removeKeys(keys);
		          } else {
		            return _this.findKeysByPriority(conditions[Cache.PRIORITY], function(err, _keys) {
		              if (err) {
		                return fn(err);
		              } else {
		                keys = keys.concat(_keys);
		                return removeKeys(keys);
		              }
		            });
		          }
		        });
		      } else {
		        fn(null);
		      }
		      return this;
		    };
		
		    Storage.prototype.findMeta = function(key, fn) {
		      return this.getMeta(function(err, meta) {
		        if (err) {
		          return fn(err, null);
		        } else if (typeof meta[key] !== 'undefined') {
		          return fn(null, meta[key]);
		        } else {
		          return fn(null, null);
		        }
		      });
		    };
		
		    Storage.prototype.findKeysByTag = function(tag, fn) {
		      return this.getMeta(function(err, metas) {
		        var key, meta, result;
		        if (err) {
		          return fn(err, null);
		        } else {
		          result = [];
		          for (key in metas) {
		            meta = metas[key];
		            if (typeof meta[Cache.TAGS] !== 'undefined' && meta[Cache.TAGS].indexOf(tag) !== -1) {
		              result.push(key);
		            }
		          }
		          return fn(null, result);
		        }
		      });
		    };
		
		    Storage.prototype.findKeysByPriority = function(priority, fn) {
		      return this.getMeta(function(err, metas) {
		        var key, meta, result;
		        if (err) {
		          return fn(err, null);
		        } else {
		          result = [];
		          for (key in metas) {
		            meta = metas[key];
		            if (typeof meta[Cache.PRIORITY] !== 'undefined' && meta[Cache.PRIORITY] <= priority) {
		              result.push(key);
		            }
		          }
		          return fn(null, result);
		        }
		      });
		    };
		
		    Storage.prototype.verify = function(meta, fn) {
		      var typefn,
		        _this = this;
		      typefn = Object.prototype.toString;
		      if (typefn.call(meta) === '[object Object]') {
		        if (typeof meta[Cache.EXPIRE] !== 'undefined') {
		          if (moment().valueOf() >= meta[Cache.EXPIRE]) {
		            fn(null, false);
		            return null;
		          }
		        }
		        if (typeof meta[Cache.ITEMS] === 'undefined') {
		          meta[Cache.ITEMS] = [];
		        }
		        return async.eachSeries(meta[Cache.ITEMS], function(item, cb) {
		          return _this.findMeta(item, function(err, meta) {
		            if (err) {
		              fn(err, null);
		              return cb(new Error('Fake error'));
		            } else if (meta === null) {
		              fn(null, false);
		              return cb(new Error('Fake error'));
		            } else if (meta !== null) {
		              return _this.verify(meta, function(err, state) {
		                if (err) {
		                  fn(err, null);
		                  return cb(new Error('Fake error'));
		                } else if (state === false) {
		                  fn(null, false);
		                  return cb(new Error('Fake error'));
		                } else {
		                  return cb();
		                }
		              });
		            } else {
		              return cb();
		            }
		          });
		        }, function(err) {
		          var file, files, mtime, time, _ref1, _ref2, _ref3;
		          if (!err) {
		            if (typeof meta[Cache.FILES] === 'undefined') {
		              meta[Cache.FILES] = [];
		            }
		            _this.checkFilesSupport();
		            if (isWindow) {
		              _ref1 = meta[Cache.FILES];
		              for (file in _ref1) {
		                time = _ref1[file];
		                mtime = window.require.getStats(file).mtime;
		                if (mtime === null) {
		                  throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
		                }
		                if (window.require.getStats(file).mtime.getTime() !== time) {
		                  fn(null, false);
		                  return null;
		                }
		              }
		              return fn(null, true);
		            } else {
		              files = [];
		              _ref2 = meta[Cache.FILES];
		              for (file in _ref2) {
		                time = _ref2[file];
		                _ref3 = meta[Cache.FILES];
		                for (file in _ref3) {
		                  time = _ref3[file];
		                  files.push({
		                    file: file,
		                    time: time
		                  });
		                }
		              }
		              return async.eachSeries(files, function(item, cb) {
		                return Cache.getFs().stat(item.file, function(err, stats) {
		                  if (err) {
		                    return cb(err);
		                  } else {
		                    if ((new Date(stats.mtime)).getTime() !== item.time) {
		                      fn(null, false);
		                      return cb(new Error('Fake error'));
		                    } else {
		                      return cb();
		                    }
		                  }
		                });
		              }, function(err) {
		                if (err && err.message === 'Fake error') {
		
		                } else if (err) {
		                  return fn(err, null);
		                } else {
		                  return fn(null, true);
		                }
		              });
		            }
		          }
		        });
		      } else {
		        return fn(null, true);
		      }
		    };
		
		    Storage.prototype.parseDependencies = function(dependencies, fn) {
		      var file, files, item, mtime, result, time, typefn, _i, _j, _len, _len1, _ref1, _ref2;
		      typefn = Object.prototype.toString;
		      result = {};
		      if (typefn.call(dependencies) === '[object Object]') {
		        if (typeof dependencies[Cache.EXPIRE] !== 'undefined') {
		          switch (typefn.call(dependencies[Cache.EXPIRE])) {
		            case '[object String]':
		              time = moment(dependencies[Cache.EXPIRE], Cache.TIME_FORMAT);
		              break;
		            case '[object Object]':
		              time = moment().add(dependencies[Cache.EXPIRE]);
		              break;
		            default:
		              throw new Error('Expire format is not valid');
		          }
		          result[Cache.EXPIRE] = time.valueOf();
		        }
		        if (typeof dependencies[Cache.ITEMS] !== 'undefined') {
		          result[Cache.ITEMS] = [];
		          _ref1 = dependencies[Cache.ITEMS];
		          for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
		            item = _ref1[_i];
		            result[Cache.ITEMS].push(this.cache.generateKey(item));
		          }
		        }
		        if (typeof dependencies[Cache.PRIORITY] !== 'undefined') {
		          result[Cache.PRIORITY] = dependencies[Cache.PRIORITY];
		        }
		        if (typeof dependencies[Cache.TAGS] !== 'undefined') {
		          result[Cache.TAGS] = dependencies[Cache.TAGS];
		        }
		        if (typeof dependencies[Cache.FILES] !== 'undefined') {
		          this.checkFilesSupport();
		          files = {};
		          if (isWindow) {
		            _ref2 = dependencies[Cache.FILES];
		            for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
		              file = _ref2[_j];
		              mtime = window.require.getStats(file).mtime;
		              if (mtime === null) {
		                throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
		              }
		              file = window.require.resolve(file);
		              files[file] = mtime.getTime();
		            }
		            result[Cache.FILES] = files;
		            fn(null, result);
		          } else {
		            async.eachSeries(dependencies[Cache.FILES], function(file, cb) {
		              file = path.resolve(file);
		              return Cache.getFs().stat(file, function(err, stats) {
		                if (err) {
		                  return cb(err);
		                } else {
		                  files[file] = (new Date(stats.mtime)).getTime();
		                  return cb();
		                }
		              });
		            }, function(err) {
		              if (err) {
		                return fn(err, null);
		              } else {
		                result[Cache.FILES] = files;
		                return fn(null, result);
		              }
		            });
		          }
		          return result[Cache.FILES] = files;
		        } else {
		          return fn(null, result);
		        }
		      } else {
		        return fn(null, result);
		      }
		    };
		
		    return Storage;
		
		  })(BaseStorage);
		
		  module.exports = Storage;
		
		}).call(this);
		
	
	}, 'redis/index.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/index.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/index.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/index.js';
		var __dirname = 'redis';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/index.js'], env: {}};
	
		/** code **/
		/*global Buffer require exports console setTimeout */
		
		var net = require("net"),
		    util = require("./lib/util"),
		    Queue = require("./lib/queue"),
		    to_array = require("./lib/to_array"),
		    events = require("events"),
		    crypto = require("crypto"),
		    parsers = [], commands,
		    connection_id = 0,
		    default_port = 6379,
		    default_host = "127.0.0.1";
		
		// can set this to true to enable for all connections
		exports.debug_mode = false;
		
		var arraySlice = Array.prototype.slice
		function trace() {
		    if (!exports.debug_mode) return;
		    console.log.apply(null, arraySlice.call(arguments))
		}
		
		// hiredis might not be installed
		try {
		    require("./lib/parser/hiredis");
		    parsers.push(require("./lib/parser/hiredis"));
		} catch (err) {
		    if (exports.debug_mode) {
		        console.warn("hiredis parser not installed.");
		    }
		}
		
		parsers.push(require("./lib/parser/javascript"));
		
		function RedisClient(stream, options) {
		    this.stream = stream;
		    this.options = options = options || {};
		
		    this.connection_id = ++connection_id;
		    this.connected = false;
		    this.ready = false;
		    this.connections = 0;
		    if (this.options.socket_nodelay === undefined) {
		        this.options.socket_nodelay = true;
		    }
		    this.should_buffer = false;
		    this.command_queue_high_water = this.options.command_queue_high_water || 1000;
		    this.command_queue_low_water = this.options.command_queue_low_water || 0;
		    this.max_attempts = null;
		    if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) {
		        this.max_attempts = +options.max_attempts;
		    }
		    this.command_queue = new Queue(); // holds sent commands to de-pipeline them
		    this.offline_queue = new Queue(); // holds commands issued but not able to be sent
		    this.commands_sent = 0;
		    this.connect_timeout = false;
		    if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) {
		        this.connect_timeout = +options.connect_timeout;
		    }
		    this.enable_offline_queue = true;
		    if (typeof this.options.enable_offline_queue === "boolean") {
		        this.enable_offline_queue = this.options.enable_offline_queue;
		    }
		    this.retry_max_delay = null;
		    if (options.retry_max_delay !== undefined && !isNaN(options.retry_max_delay) && options.retry_max_delay > 0) {
		        this.retry_max_delay = options.retry_max_delay;
		    }
		
		    this.initialize_retry_vars();
		    this.pub_sub_mode = false;
		    this.subscription_set = {};
		    this.monitoring = false;
		    this.closing = false;
		    this.server_info = {};
		    this.auth_pass = null;
		    if (options.auth_pass !== undefined) {
		        this.auth_pass = options.auth_pass;
		    }
		    this.parser_module = null;
		    this.selected_db = null;	// save the selected db here, used when reconnecting
		
		    this.old_state = null;
		
		    var self = this;
		
		    this.stream.on("connect", function () {
		        self.on_connect();
		    });
		
		    this.stream.on("data", function (buffer_from_socket) {
		        self.on_data(buffer_from_socket);
		    });
		
		    this.stream.on("error", function (msg) {
		        self.on_error(msg.message);
		    });
		
		    this.stream.on("close", function () {
		        self.connection_gone("close");
		    });
		
		    this.stream.on("end", function () {
		        self.connection_gone("end");
		    });
		
		    this.stream.on("drain", function () {
		        self.should_buffer = false;
		        self.emit("drain");
		    });
		
		    events.EventEmitter.call(this);
		}
		util.inherits(RedisClient, events.EventEmitter);
		exports.RedisClient = RedisClient;
		
		RedisClient.prototype.initialize_retry_vars = function () {
		    this.retry_timer = null;
		    this.retry_totaltime = 0;
		    this.retry_delay = 150;
		    this.retry_backoff = 1.7;
		    this.attempts = 1;
		};
		
		RedisClient.prototype.unref = function () {
		    trace("User requesting to unref the connection");
		    if (this.connected) {
		        trace("unref'ing the socket connection");
		        this.stream.unref();
		    }
		    else {
		        trace("Not connected yet, will unref later");
		        this.once("connect", function () {
		            this.unref();
		        })
		    }
		};
		
		// flush offline_queue and command_queue, erroring any items with a callback first
		RedisClient.prototype.flush_and_error = function (message) {
		    var command_obj, error;
		
		    error = new Error(message);
		
		    while (this.offline_queue.length > 0) {
		        command_obj = this.offline_queue.shift();
		        if (typeof command_obj.callback === "function") {
		            try {
		                command_obj.callback(error);
		            } catch (callback_err) {
		                this.emit("error", callback_err);
		            }
		        }
		    }
		    this.offline_queue = new Queue();
		
		    while (this.command_queue.length > 0) {
		        command_obj = this.command_queue.shift();
		        if (typeof command_obj.callback === "function") {
		            try {
		                command_obj.callback(error);
		            } catch (callback_err) {
		                this.emit("error", callback_err);
		            }
		        }
		    }
		    this.command_queue = new Queue();
		};
		
		RedisClient.prototype.on_error = function (msg) {
		    var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg;
		
		    if (this.closing) {
		        return;
		    }
		
		    if (exports.debug_mode) {
		        console.warn(message);
		    }
		
		    this.flush_and_error(message);
		
		    this.connected = false;
		    this.ready = false;
		
		    this.emit("error", new Error(message));
		    // "error" events get turned into exceptions if they aren't listened for.  If the user handled this error
		    // then we should try to reconnect.
		    this.connection_gone("error");
		};
		
		RedisClient.prototype.do_auth = function () {
		    var self = this;
		
		    if (exports.debug_mode) {
		        console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id);
		    }
		    self.send_anyway = true;
		    self.send_command("auth", [this.auth_pass], function (err, res) {
		        if (err) {
		            if (err.toString().match("LOADING")) {
		                // if redis is still loading the db, it will not authenticate and everything else will fail
		                console.log("Redis still loading, trying to authenticate later");
		                setTimeout(function () {
		                    self.do_auth();
		                }, 2000); // TODO - magic number alert
		                return;
		            } else if (err.toString().match("no password is set")) {
		                console.log("Warning: Redis server does not require a password, but a password was supplied.")
		                err = null;
		                res = "OK";
		            } else {
		                return self.emit("error", new Error("Auth error: " + err.message));
		            }
		        }
		        if (res.toString() !== "OK") {
		            return self.emit("error", new Error("Auth failed: " + res.toString()));
		        }
		        if (exports.debug_mode) {
		            console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id);
		        }
		        if (self.auth_callback) {
		            self.auth_callback(err, res);
		            self.auth_callback = null;
		        }
		
		        // now we are really connected
		        self.emit("connect");
		        self.initialize_retry_vars();
		
		        if (self.options.no_ready_check) {
		            self.on_ready();
		        } else {
		            self.ready_check();
		        }
		    });
		    self.send_anyway = false;
		};
		
		RedisClient.prototype.on_connect = function () {
		    if (exports.debug_mode) {
		        console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id);
		    }
		
		    this.connected = true;
		    this.ready = false;
		    this.connections += 1;
		    this.command_queue = new Queue();
		    this.emitted_end = false;
		    if (this.options.socket_nodelay) {
		        this.stream.setNoDelay();
		    }
		    this.stream.setTimeout(0);
		
		    this.init_parser();
		
		    if (this.auth_pass) {
		        this.do_auth();
		    } else {
		        this.emit("connect");
		        this.initialize_retry_vars();
		
		        if (this.options.no_ready_check) {
		            this.on_ready();
		        } else {
		            this.ready_check();
		        }
		    }
		};
		
		RedisClient.prototype.init_parser = function () {
		    var self = this;
		
		    if (this.options.parser) {
		        if (! parsers.some(function (parser) {
		            if (parser.name === self.options.parser) {
		                self.parser_module = parser;
		                if (exports.debug_mode) {
		                    console.log("Using parser module: " + self.parser_module.name);
		                }
		                return true;
		            }
		        })) {
		            throw new Error("Couldn't find named parser " + self.options.parser + " on this system");
		        }
		    } else {
		        if (exports.debug_mode) {
		            console.log("Using default parser module: " + parsers[0].name);
		        }
		        this.parser_module = parsers[0];
		    }
		
		    this.parser_module.debug_mode = exports.debug_mode;
		
		    // return_buffers sends back Buffers from parser to callback. detect_buffers sends back Buffers from parser, but
		    // converts to Strings if the input arguments are not Buffers.
		    this.reply_parser = new this.parser_module.Parser({
		        return_buffers: self.options.return_buffers || self.options.detect_buffers || false
		    });
		
		    // "reply error" is an error sent back by Redis
		    this.reply_parser.on("reply error", function (reply) {
		        if (reply instanceof Error) {
		            self.return_error(reply);
		        } else {
		            self.return_error(new Error(reply));
		        }
		    });
		    this.reply_parser.on("reply", function (reply) {
		        self.return_reply(reply);
		    });
		    // "error" is bad.  Somehow the parser got confused.  It'll try to reset and continue.
		    this.reply_parser.on("error", function (err) {
		        self.emit("error", new Error("Redis reply parser error: " + err.stack));
		    });
		};
		
		RedisClient.prototype.on_ready = function () {
		    var self = this;
		
		    this.ready = true;
		
		    if (this.old_state !== null) {
		        this.monitoring = this.old_state.monitoring;
		        this.pub_sub_mode = this.old_state.pub_sub_mode;
		        this.selected_db = this.old_state.selected_db;
		        this.old_state = null;
		    }
		
		    // magically restore any modal commands from a previous connection
		    if (this.selected_db !== null) {
		        // this trick works if and only if the following send_command
		        // never goes into the offline queue
		        var pub_sub_mode = this.pub_sub_mode;
		        this.pub_sub_mode = false;
		        this.send_command('select', [this.selected_db]);
		        this.pub_sub_mode = pub_sub_mode;
		    }
		    if (this.pub_sub_mode === true) {
		        // only emit "ready" when all subscriptions were made again
		        var callback_count = 0;
		        var callback = function () {
		            callback_count--;
		            if (callback_count === 0) {
		                self.emit("ready");
		            }
		        };
		        Object.keys(this.subscription_set).forEach(function (key) {
		            var parts = key.split(" ");
		            if (exports.debug_mode) {
		                console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]);
		            }
		            callback_count++;
		            self.send_command(parts[0] + "scribe", [parts[1]], callback);
		        });
		        return;
		    } else if (this.monitoring) {
		        this.send_command("monitor");
		    } else {
		        this.send_offline_queue();
		    }
		    this.emit("ready");
		};
		
		RedisClient.prototype.on_info_cmd = function (err, res) {
		    var self = this, obj = {}, lines, retry_time;
		
		    if (err) {
		        return self.emit("error", new Error("Ready check failed: " + err.message));
		    }
		
		    lines = res.toString().split("\r\n");
		
		    lines.forEach(function (line) {
		        var parts = line.split(':');
		        if (parts[1]) {
		            obj[parts[0]] = parts[1];
		        }
		    });
		
		    obj.versions = [];
		    obj.redis_version.split('.').forEach(function (num) {
		        obj.versions.push(+num);
		    });
		
		    // expose info key/vals to users
		    this.server_info = obj;
		
		    if (!obj.loading || (obj.loading && obj.loading === "0")) {
		        if (exports.debug_mode) {
		            console.log("Redis server ready.");
		        }
		        this.on_ready();
		    } else {
		        retry_time = obj.loading_eta_seconds * 1000;
		        if (retry_time > 1000) {
		            retry_time = 1000;
		        }
		        if (exports.debug_mode) {
		            console.log("Redis server still loading, trying again in " + retry_time);
		        }
		        setTimeout(function () {
		            self.ready_check();
		        }, retry_time);
		    }
		};
		
		RedisClient.prototype.ready_check = function () {
		    var self = this;
		
		    if (exports.debug_mode) {
		        console.log("checking server ready state...");
		    }
		
		    this.send_anyway = true;  // secret flag to send_command to send something even if not "ready"
		    this.info(function (err, res) {
		        self.on_info_cmd(err, res);
		    });
		    this.send_anyway = false;
		};
		
		RedisClient.prototype.send_offline_queue = function () {
		    var command_obj, buffered_writes = 0;
		
		    while (this.offline_queue.length > 0) {
		        command_obj = this.offline_queue.shift();
		        if (exports.debug_mode) {
		            console.log("Sending offline command: " + command_obj.command);
		        }
		        buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback);
		    }
		    this.offline_queue = new Queue();
		    // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue
		
		    if (!buffered_writes) {
		        this.should_buffer = false;
		        this.emit("drain");
		    }
		};
		
		RedisClient.prototype.connection_gone = function (why) {
		    var self = this;
		
		    // If a retry is already in progress, just let that happen
		    if (this.retry_timer) {
		        return;
		    }
		
		    if (exports.debug_mode) {
		        console.warn("Redis connection is gone from " + why + " event.");
		    }
		    this.connected = false;
		    this.ready = false;
		
		    if (this.old_state === null) {
		        var state = {
		            monitoring: this.monitoring,
		            pub_sub_mode: this.pub_sub_mode,
		            selected_db: this.selected_db
		        };
		        this.old_state = state;
		        this.monitoring = false;
		        this.pub_sub_mode = false;
		        this.selected_db = null;
		    }
		
		    // since we are collapsing end and close, users don't expect to be called twice
		    if (! this.emitted_end) {
		        this.emit("end");
		        this.emitted_end = true;
		    }
		
		    this.flush_and_error("Redis connection gone from " + why + " event.");
		
		    // If this is a requested shutdown, then don't retry
		    if (this.closing) {
		        this.retry_timer = null;
		        if (exports.debug_mode) {
		            console.warn("connection ended from quit command, not retrying.");
		        }
		        return;
		    }
		
		    var nextDelay = Math.floor(this.retry_delay * this.retry_backoff);
		    if (this.retry_max_delay !== null && nextDelay > this.retry_max_delay) {
		        this.retry_delay = this.retry_max_delay;
		    } else {
		        this.retry_delay = nextDelay;
		    }
		
		    if (exports.debug_mode) {
		        console.log("Retry connection in " + this.retry_delay + " ms");
		    }
		
		    if (this.max_attempts && this.attempts >= this.max_attempts) {
		        this.retry_timer = null;
		        // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others
		        // want the program to exit.  Right now, we just log, which doesn't really help in either case.
		        console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts.");
		        return;
		    }
		
		    this.attempts += 1;
		    this.emit("reconnecting", {
		        delay: self.retry_delay,
		        attempt: self.attempts
		    });
		    this.retry_timer = setTimeout(function () {
		        if (exports.debug_mode) {
		            console.log("Retrying connection...");
		        }
		
		        self.retry_totaltime += self.retry_delay;
		
		        if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) {
		            self.retry_timer = null;
		            // TODO - engage Redis is Broken mode for future commands, or whatever
		            console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms.");
		            return;
		        }
		
		        self.stream.connect(self.port, self.host);
		        self.retry_timer = null;
		    }, this.retry_delay);
		};
		
		RedisClient.prototype.on_data = function (data) {
		    if (exports.debug_mode) {
		        console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString());
		    }
		
		    try {
		        this.reply_parser.execute(data);
		    } catch (err) {
		        // This is an unexpected parser problem, an exception that came from the parser code itself.
		        // Parser should emit "error" events if it notices things are out of whack.
		        // Callbacks that throw exceptions will land in return_reply(), below.
		        // TODO - it might be nice to have a different "error" event for different types of errors
		        this.emit("error", err);
		    }
		};
		
		RedisClient.prototype.return_error = function (err) {
		    var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength();
		
		    if (this.pub_sub_mode === false && queue_len === 0) {
		        this.command_queue = new Queue();
		        this.emit("idle");
		    }
		    if (this.should_buffer && queue_len <= this.command_queue_low_water) {
		        this.emit("drain");
		        this.should_buffer = false;
		    }
		
		    if (command_obj && typeof command_obj.callback === "function") {
		        try {
		            command_obj.callback(err);
		        } catch (callback_err) {
		            this.emit("error", callback_err);
		        }
		    } else {
		        console.log("node_redis: no callback to send error: " + err.message);
		        this.emit("error", err);
		    }
		};
		
		// if a callback throws an exception, re-throw it on a new stack so the parser can keep going.
		// if a domain is active, emit the error on the domain, which will serve the same function.
		// put this try/catch in its own function because V8 doesn't optimize this well yet.
		function try_callback(client, callback, reply) {
		    try {
		        callback(null, reply);
		    } catch (err) {
		        if (process.domain) {
		            process.domain.emit('error', err);
		            process.domain.exit();
		        } else {
		            client.emit("error", err);
		        }
		    }
		}
		
		// hgetall converts its replies to an Object.  If the reply is empty, null is returned.
		function reply_to_object(reply) {
		    var obj = {}, j, jl, key, val;
		
		    if (reply.length === 0) {
		        return null;
		    }
		
		    for (j = 0, jl = reply.length; j < jl; j += 2) {
		        key = reply[j].toString();
		        val = reply[j + 1];
		        obj[key] = val;
		    }
		
		    return obj;
		}
		
		function reply_to_strings(reply) {
		    var i;
		
		    if (Buffer.isBuffer(reply)) {
		        return reply.toString();
		    }
		
		    if (Array.isArray(reply)) {
		        for (i = 0; i < reply.length; i++) {
		            if (reply[i] !== null && reply[i] !== undefined) {
		                reply[i] = reply[i].toString();
		            }
		        }
		        return reply;
		    }
		
		    return reply;
		}
		
		RedisClient.prototype.return_reply = function (reply) {
		    var command_obj, len, type, timestamp, argindex, args, queue_len;
		
		    // If the "reply" here is actually a message received asynchronously due to a
		    // pubsub subscription, don't pop the command queue as we'll only be consuming
		    // the head command prematurely.
		    if (Array.isArray(reply) && reply.length > 0 && reply[0]) {
		        type = reply[0].toString();
		    }
		
		    if (this.pub_sub_mode && (type == 'message' || type == 'pmessage')) {
		        trace("received pubsub message");
		    }
		    else {
		        command_obj = this.command_queue.shift();
		    }
		
		    queue_len = this.command_queue.getLength();
		
		    if (this.pub_sub_mode === false && queue_len === 0) {
		        this.command_queue = new Queue();  // explicitly reclaim storage from old Queue
		        this.emit("idle");
		    }
		    if (this.should_buffer && queue_len <= this.command_queue_low_water) {
		        this.emit("drain");
		        this.should_buffer = false;
		    }
		
		    if (command_obj && !command_obj.sub_command) {
		        if (typeof command_obj.callback === "function") {
		            if (this.options.detect_buffers && command_obj.buffer_args === false) {
		                // If detect_buffers option was specified, then the reply from the parser will be Buffers.
		                // If this command did not use Buffer arguments, then convert the reply to Strings here.
		                reply = reply_to_strings(reply);
		            }
		
		            // TODO - confusing and error-prone that hgetall is special cased in two places
		            if (reply && 'hgetall' === command_obj.command.toLowerCase()) {
		                reply = reply_to_object(reply);
		            }
		
		            try_callback(this, command_obj.callback, reply);
		        } else if (exports.debug_mode) {
		            console.log("no callback for reply: " + (reply && reply.toString && reply.toString()));
		        }
		    } else if (this.pub_sub_mode || (command_obj && command_obj.sub_command)) {
		        if (Array.isArray(reply)) {
		            type = reply[0].toString();
		
		            if (type === "message") {
		                this.emit("message", reply[1].toString(), reply[2]); // channel, message
		            } else if (type === "pmessage") {
		                this.emit("pmessage", reply[1].toString(), reply[2].toString(), reply[3]); // pattern, channel, message
		            } else if (type === "subscribe" || type === "unsubscribe" || type === "psubscribe" || type === "punsubscribe") {
		                if (reply[2] === 0) {
		                    this.pub_sub_mode = false;
		                    if (this.debug_mode) {
		                        console.log("All subscriptions removed, exiting pub/sub mode");
		                    }
		                } else {
		                    this.pub_sub_mode = true;
		                }
		                // subscribe commands take an optional callback and also emit an event, but only the first response is included in the callback
		                // TODO - document this or fix it so it works in a more obvious way
		                // reply[1] can be null
		                var reply1String = (reply[1] === null) ? null : reply[1].toString();
		                if (command_obj && typeof command_obj.callback === "function") {
		                    try_callback(this, command_obj.callback, reply1String);
		                }
		                this.emit(type, reply1String, reply[2]); // channel, count
		            } else {
		                throw new Error("subscriptions are active but got unknown reply type " + type);
		            }
		        } else if (! this.closing) {
		            throw new Error("subscriptions are active but got an invalid reply: " + reply);
		        }
		    } else if (this.monitoring) {
		        len = reply.indexOf(" ");
		        timestamp = reply.slice(0, len);
		        argindex = reply.indexOf('"');
		        args = reply.slice(argindex + 1, -1).split('" "').map(function (elem) {
		            return elem.replace(/\\"/g, '"');
		        });
		        this.emit("monitor", timestamp, args);
		    } else {
		        throw new Error("node_redis command queue state error. If you can reproduce this, please report it.");
		    }
		};
		
		// This Command constructor is ever so slightly faster than using an object literal, but more importantly, using
		// a named constructor helps it show up meaningfully in the V8 CPU profiler and in heap snapshots.
		function Command(command, args, sub_command, buffer_args, callback) {
		    this.command = command;
		    this.args = args;
		    this.sub_command = sub_command;
		    this.buffer_args = buffer_args;
		    this.callback = callback;
		}
		
		RedisClient.prototype.send_command = function (command, args, callback) {
		    var arg, command_obj, i, il, elem_count, buffer_args, stream = this.stream, command_str = "", buffered_writes = 0, last_arg_type, lcaseCommand;
		
		    if (typeof command !== "string") {
		        throw new Error("First argument to send_command must be the command name string, not " + typeof command);
		    }
		
		    if (Array.isArray(args)) {
		        if (typeof callback === "function") {
		            // probably the fastest way:
		            //     client.command([arg1, arg2], cb);  (straight passthrough)
		            //         send_command(command, [arg1, arg2], cb);
		        } else if (! callback) {
		            // most people find this variable argument length form more convenient, but it uses arguments, which is slower
		            //     client.command(arg1, arg2, cb);   (wraps up arguments into an array)
		            //       send_command(command, [arg1, arg2, cb]);
		            //     client.command(arg1, arg2);   (callback is optional)
		            //       send_command(command, [arg1, arg2]);
		            //     client.command(arg1, arg2, undefined);   (callback is undefined)
		            //       send_command(command, [arg1, arg2, undefined]);
		            last_arg_type = typeof args[args.length - 1];
		            if (last_arg_type === "function" || last_arg_type === "undefined") {
		                callback = args.pop();
		            }
		        } else {
		            throw new Error("send_command: last argument must be a callback or undefined");
		        }
		    } else {
		        throw new Error("send_command: second argument must be an array");
		    }
		
		    if (callback && process.domain) callback = process.domain.bind(callback);
		
		    // if the last argument is an array and command is sadd or srem, expand it out:
		    //     client.sadd(arg1, [arg2, arg3, arg4], cb);
		    //  converts to:
		    //     client.sadd(arg1, arg2, arg3, arg4, cb);
		    lcaseCommand = command.toLowerCase();
		    if ((lcaseCommand === 'sadd' || lcaseCommand === 'srem') && args.length > 0 && Array.isArray(args[args.length - 1])) {
		        args = args.slice(0, -1).concat(args[args.length - 1]);
		    }
		
		    // if the value is undefined or null and command is set or setx, need not to send message to redis
		    if (command === 'set' || command === 'setex') {
		        if(args[args.length - 1] === undefined || args[args.length - 1] === null) {
		            var err = new Error('send_command: ' + command + ' value must not be undefined or null');
		            return callback && callback(err);
		        }
		    }
		
		    buffer_args = false;
		    for (i = 0, il = args.length, arg; i < il; i += 1) {
		        if (Buffer.isBuffer(args[i])) {
		            buffer_args = true;
		        }
		    }
		
		    command_obj = new Command(command, args, false, buffer_args, callback);
		
		    if ((!this.ready && !this.send_anyway) || !stream.writable) {
		        if (exports.debug_mode) {
		            if (!stream.writable) {
		                console.log("send command: stream is not writeable.");
		            }
		        }
		
		        if (this.enable_offline_queue) {
		            if (exports.debug_mode) {
		                console.log("Queueing " + command + " for next server connection.");
		            }
		            this.offline_queue.push(command_obj);
		            this.should_buffer = true;
		        } else {
		            var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false');
		            if (command_obj.callback) {
		                command_obj.callback(not_writeable_error);
		            } else {
		                throw not_writeable_error;
		            }
		        }
		
		        return false;
		    }
		
		    if (command === "subscribe" || command === "psubscribe" || command === "unsubscribe" || command === "punsubscribe") {
		        this.pub_sub_command(command_obj);
		    } else if (command === "monitor") {
		        this.monitoring = true;
		    } else if (command === "quit") {
		        this.closing = true;
		    } else if (this.pub_sub_mode === true) {
		        throw new Error("Connection in subscriber mode, only subscriber commands may be used");
		    }
		    this.command_queue.push(command_obj);
		    this.commands_sent += 1;
		
		    elem_count = args.length + 1;
		
		    // Always use "Multi bulk commands", but if passed any Buffer args, then do multiple writes, one for each arg.
		    // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
		
		    command_str = "*" + elem_count + "\r\n$" + command.length + "\r\n" + command + "\r\n";
		
		    if (! buffer_args) { // Build up a string and send entire command in one write
		        for (i = 0, il = args.length, arg; i < il; i += 1) {
		            arg = args[i];
		            if (typeof arg !== "string") {
		                arg = String(arg);
		            }
		            command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n";
		        }
		        if (exports.debug_mode) {
		            console.log("send " + this.host + ":" + this.port + " id " + this.connection_id + ": " + command_str);
		        }
		        buffered_writes += !stream.write(command_str);
		    } else {
		        if (exports.debug_mode) {
		            console.log("send command (" + command_str + ") has Buffer arguments");
		        }
		        buffered_writes += !stream.write(command_str);
		
		        for (i = 0, il = args.length, arg; i < il; i += 1) {
		            arg = args[i];
		            if (!(Buffer.isBuffer(arg) || arg instanceof String)) {
		                arg = String(arg);
		            }
		
		            if (Buffer.isBuffer(arg)) {
		                if (arg.length === 0) {
		                    if (exports.debug_mode) {
		                        console.log("send_command: using empty string for 0 length buffer");
		                    }
		                    buffered_writes += !stream.write("$0\r\n\r\n");
		                } else {
		                    buffered_writes += !stream.write("$" + arg.length + "\r\n");
		                    buffered_writes += !stream.write(arg);
		                    buffered_writes += !stream.write("\r\n");
		                    if (exports.debug_mode) {
		                        console.log("send_command: buffer send " + arg.length + " bytes");
		                    }
		                }
		            } else {
		                if (exports.debug_mode) {
		                    console.log("send_command: string send " + Buffer.byteLength(arg) + " bytes: " + arg);
		                }
		                buffered_writes += !stream.write("$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n");
		            }
		        }
		    }
		    if (exports.debug_mode) {
		        console.log("send_command buffered_writes: " + buffered_writes, " should_buffer: " + this.should_buffer);
		    }
		    if (buffered_writes || this.command_queue.getLength() >= this.command_queue_high_water) {
		        this.should_buffer = true;
		    }
		    return !this.should_buffer;
		};
		
		RedisClient.prototype.pub_sub_command = function (command_obj) {
		    var i, key, command, args;
		
		    if (this.pub_sub_mode === false && exports.debug_mode) {
		        console.log("Entering pub/sub mode from " + command_obj.command);
		    }
		    this.pub_sub_mode = true;
		    command_obj.sub_command = true;
		
		    command = command_obj.command;
		    args = command_obj.args;
		    if (command === "subscribe" || command === "psubscribe") {
		        if (command === "subscribe") {
		            key = "sub";
		        } else {
		            key = "psub";
		        }
		        for (i = 0; i < args.length; i++) {
		            this.subscription_set[key + " " + args[i]] = true;
		        }
		    } else {
		        if (command === "unsubscribe") {
		            key = "sub";
		        } else {
		            key = "psub";
		        }
		        for (i = 0; i < args.length; i++) {
		            delete this.subscription_set[key + " " + args[i]];
		        }
		    }
		};
		
		RedisClient.prototype.end = function () {
		    this.stream._events = {};
		    this.connected = false;
		    this.ready = false;
		    this.closing = true;
		    return this.stream.destroySoon();
		};
		
		function Multi(client, args) {
		    this._client = client;
		    this.queue = [["MULTI"]];
		    if (Array.isArray(args)) {
		        this.queue = this.queue.concat(args);
		    }
		}
		
		exports.Multi = Multi;
		
		// take 2 arrays and return the union of their elements
		function set_union(seta, setb) {
		    var obj = {};
		
		    seta.forEach(function (val) {
		        obj[val] = true;
		    });
		    setb.forEach(function (val) {
		        obj[val] = true;
		    });
		    return Object.keys(obj);
		}
		
		// This static list of commands is updated from time to time.  ./lib/commands.js can be updated with generate_commands.js
		commands = set_union(["get", "set", "setnx", "setex", "append", "strlen", "del", "exists", "setbit", "getbit", "setrange", "getrange", "substr",
		    "incr", "decr", "mget", "rpush", "lpush", "rpushx", "lpushx", "linsert", "rpop", "lpop", "brpop", "brpoplpush", "blpop", "llen", "lindex",
		    "lset", "lrange", "ltrim", "lrem", "rpoplpush", "sadd", "srem", "smove", "sismember", "scard", "spop", "srandmember", "sinter", "sinterstore",
		    "sunion", "sunionstore", "sdiff", "sdiffstore", "smembers", "zadd", "zincrby", "zrem", "zremrangebyscore", "zremrangebyrank", "zunionstore",
		    "zinterstore", "zrange", "zrangebyscore", "zrevrangebyscore", "zcount", "zrevrange", "zcard", "zscore", "zrank", "zrevrank", "hset", "hsetnx",
		    "hget", "hmset", "hmget", "hincrby", "hdel", "hlen", "hkeys", "hvals", "hgetall", "hexists", "incrby", "decrby", "getset", "mset", "msetnx",
		    "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo", "save", "bgsave",
		    "bgrewriteaof", "shutdown", "lastsave", "type", "multi", "exec", "discard", "sync", "flushdb", "flushall", "sort", "info", "monitor", "ttl",
		    "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch", "cluster",
		    "restore", "migrate", "dump", "object", "client", "eval", "evalsha"], require("./lib/commands"));
		
		commands.forEach(function (fullCommand) {
		    var command = fullCommand.split(' ')[0];
		
		    RedisClient.prototype[command] = function (args, callback) {
		        if (Array.isArray(args) && typeof callback === "function") {
		            return this.send_command(command, args, callback);
		        } else {
		            return this.send_command(command, to_array(arguments));
		        }
		    };
		    RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command];
		
		    Multi.prototype[command] = function () {
		        this.queue.push([command].concat(to_array(arguments)));
		        return this;
		    };
		    Multi.prototype[command.toUpperCase()] = Multi.prototype[command];
		});
		
		// store db in this.select_db to restore it on reconnect
		RedisClient.prototype.select = function (db, callback) {
		    var self = this;
		
		    this.send_command('select', [db], function (err, res) {
		        if (err === null) {
		            self.selected_db = db;
		        }
		        if (typeof(callback) === 'function') {
		            callback(err, res);
		        }
		    });
		};
		RedisClient.prototype.SELECT = RedisClient.prototype.select;
		
		// Stash auth for connect and reconnect.  Send immediately if already connected.
		RedisClient.prototype.auth = function () {
		    var args = to_array(arguments);
		    this.auth_pass = args[0];
		    this.auth_callback = args[1];
		    if (exports.debug_mode) {
		        console.log("Saving auth as " + this.auth_pass);
		    }
		
		    if (this.connected) {
		        this.send_command("auth", args);
		    }
		};
		RedisClient.prototype.AUTH = RedisClient.prototype.auth;
		
		RedisClient.prototype.hmget = function (arg1, arg2, arg3) {
		    if (Array.isArray(arg2) && typeof arg3 === "function") {
		        return this.send_command("hmget", [arg1].concat(arg2), arg3);
		    } else if (Array.isArray(arg1) && typeof arg2 === "function") {
		        return this.send_command("hmget", arg1, arg2);
		    } else {
		        return this.send_command("hmget", to_array(arguments));
		    }
		};
		RedisClient.prototype.HMGET = RedisClient.prototype.hmget;
		
		RedisClient.prototype.hmset = function (args, callback) {
		    var tmp_args, tmp_keys, i, il, key;
		
		    if (Array.isArray(args) && typeof callback === "function") {
		        return this.send_command("hmset", args, callback);
		    }
		
		    args = to_array(arguments);
		    if (typeof args[args.length - 1] === "function") {
		        callback = args[args.length - 1];
		        args.length -= 1;
		    } else {
		        callback = null;
		    }
		
		    if (args.length === 2 && (typeof args[0] === "string" || typeof args[0] === "number") && typeof args[1] === "object") {
		        // User does: client.hmset(key, {key1: val1, key2: val2})
		        // assuming key is a string, i.e. email address
		
		        // if key is a number, i.e. timestamp, convert to string
		        if (typeof args[0] === "number") {
		            args[0] = args[0].toString();
		        }
		
		        tmp_args = [ args[0] ];
		        tmp_keys = Object.keys(args[1]);
		        for (i = 0, il = tmp_keys.length; i < il ; i++) {
		            key = tmp_keys[i];
		            tmp_args.push(key);
		            tmp_args.push(args[1][key]);
		        }
		        args = tmp_args;
		    }
		
		    return this.send_command("hmset", args, callback);
		};
		RedisClient.prototype.HMSET = RedisClient.prototype.hmset;
		
		Multi.prototype.hmset = function () {
		    var args = to_array(arguments), tmp_args;
		    if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") {
		        tmp_args = [ "hmset", args[0] ];
		        Object.keys(args[1]).map(function (key) {
		            tmp_args.push(key);
		            tmp_args.push(args[1][key]);
		        });
		        if (args[2]) {
		            tmp_args.push(args[2]);
		        }
		        args = tmp_args;
		    } else {
		        args.unshift("hmset");
		    }
		
		    this.queue.push(args);
		    return this;
		};
		Multi.prototype.HMSET = Multi.prototype.hmset;
		
		Multi.prototype.exec = function (callback) {
		    var self = this;
		    var errors = [];
		    // drain queue, callback will catch "QUEUED" or error
		    // TODO - get rid of all of these anonymous functions which are elegant but slow
		    this.queue.forEach(function (args, index) {
		        var command = args[0], obj;
		        if (typeof args[args.length - 1] === "function") {
		            args = args.slice(1, -1);
		        } else {
		            args = args.slice(1);
		        }
		        if (args.length === 1 && Array.isArray(args[0])) {
		            args = args[0];
		        }
		        if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') {
		            obj = args.pop();
		            Object.keys(obj).forEach(function (key) {
		                args.push(key);
		                args.push(obj[key]);
		            });
		        }
		        this._client.send_command(command, args, function (err, reply) {
		            if (err) {
		                var cur = self.queue[index];
		                if (typeof cur[cur.length - 1] === "function") {
		                    cur[cur.length - 1](err);
		                } else {
		                    errors.push(new Error(err));
		                }
		            }
		        });
		    }, this);
		
		    // TODO - make this callback part of Multi.prototype instead of creating it each time
		    return this._client.send_command("EXEC", [], function (err, replies) {
		        if (err) {
		            if (callback) {
		                errors.push(new Error(err));
		                callback(errors);
		                return;
		            } else {
		                throw new Error(err);
		            }
		        }
		
		        var i, il, reply, args;
		
		        if (replies) {
		            for (i = 1, il = self.queue.length; i < il; i += 1) {
		                reply = replies[i - 1];
		                args = self.queue[i];
		
		                // TODO - confusing and error-prone that hgetall is special cased in two places
		                if (reply && args[0].toLowerCase() === "hgetall") {
		                    replies[i - 1] = reply = reply_to_object(reply);
		                }
		
		                if (typeof args[args.length - 1] === "function") {
		                    args[args.length - 1](null, reply);
		                }
		            }
		        }
		
		        if (callback) {
		            callback(null, replies);
		        }
		    });
		};
		Multi.prototype.EXEC = Multi.prototype.exec;
		
		RedisClient.prototype.multi = function (args) {
		    return new Multi(this, args);
		};
		RedisClient.prototype.MULTI = function (args) {
		    return new Multi(this, args);
		};
		
		
		// stash original eval method
		var eval_orig = RedisClient.prototype.eval;
		// hook eval with an attempt to evalsha for cached scripts
		RedisClient.prototype.eval = RedisClient.prototype.EVAL = function () {
		    var self = this,
		        args = to_array(arguments),
		        callback;
		
		    if (typeof args[args.length - 1] === "function") {
		        callback = args.pop();
		    }
		
		    if (Array.isArray(args[0])) {
		        args = args[0];
		    }
		
		    // replace script source with sha value
		    var source = args[0];
		    args[0] = crypto.createHash("sha1").update(source).digest("hex");
		
		    self.evalsha(args, function (err, reply) {
		        if (err && /NOSCRIPT/.test(err.message)) {
		            args[0] = source;
		            eval_orig.call(self, args, callback);
		
		        } else if (callback) {
		            callback(err, reply);
		        }
		    });
		};
		
		
		exports.createClient = function (port_arg, host_arg, options) {
		    var port = port_arg || default_port,
		        host = host_arg || default_host,
		        redis_client, net_client;
		
		    net_client = net.createConnection(port, host);
		
		    redis_client = new RedisClient(net_client, options);
		
		    redis_client.port = port;
		    redis_client.host = host;
		
		    return redis_client;
		};
		
		exports.print = function (err, reply) {
		    if (err) {
		        console.log("Error: " + err);
		    } else {
		        console.log("Reply: " + reply);
		    }
		};
		
	
	}, 'redis/lib/util.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/util.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/util.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/util.js';
		var __dirname = 'redis/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/util.js'], env: {}};
	
		/** code **/
		// Support for very old versions of node where the module was called "sys".  At some point, we should abandon this.
		
		var util;
		
		try {
		    util = require("util");
		} catch (err) {
		    util = require("sys");
		}
		
		module.exports = util;
		
	
	}, 'redis/lib/queue.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/queue.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/queue.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/queue.js';
		var __dirname = 'redis/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/queue.js'], env: {}};
	
		/** code **/
		// Queue class adapted from Tim Caswell's pattern library
		// http://github.com/creationix/pattern/blob/master/lib/pattern/queue.js
		
		function Queue() {
		    this.tail = [];
		    this.head = [];
		    this.offset = 0;
		}
		
		Queue.prototype.shift = function () {
		    if (this.offset === this.head.length) {
		        var tmp = this.head;
		        tmp.length = 0;
		        this.head = this.tail;
		        this.tail = tmp;
		        this.offset = 0;
		        if (this.head.length === 0) {
		            return;
		        }
		    }
		    return this.head[this.offset++]; // sorry, JSLint
		};
		
		Queue.prototype.push = function (item) {
		    return this.tail.push(item);
		};
		
		Queue.prototype.forEach = function (fn, thisv) {
		    var array = this.head.slice(this.offset), i, il;
		
		    array.push.apply(array, this.tail);
		
		    if (thisv) {
		        for (i = 0, il = array.length; i < il; i += 1) {
		            fn.call(thisv, array[i], i, array);
		        }
		    } else {
		        for (i = 0, il = array.length; i < il; i += 1) {
		            fn(array[i], i, array);
		        }
		    }
		
		    return array;
		};
		
		Queue.prototype.getLength = function () {
		    return this.head.length - this.offset + this.tail.length;
		};
		    
		Object.defineProperty(Queue.prototype, "length", {
		    get: function () {
		        return this.getLength();
		    }
		});
		
		
		if (typeof module !== "undefined" && module.exports) {
		    module.exports = Queue;
		}
		
	
	}, 'redis/lib/to_array.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/to_array.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/to_array.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/to_array.js';
		var __dirname = 'redis/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/to_array.js'], env: {}};
	
		/** code **/
		function to_array(args) {
		    var len = args.length,
		        arr = new Array(len), i;
		
		    for (i = 0; i < len; i += 1) {
		        arr[i] = args[i];
		    }
		
		    return arr;
		}
		
		module.exports = to_array;
		
	
	}, 'redis/lib/parser/hiredis.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/parser/hiredis.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/parser/hiredis.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/parser/hiredis.js';
		var __dirname = 'redis/lib/parser';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/parser/hiredis.js'], env: {}};
	
		/** code **/
		var events = require("events"),
		    util = require("../util"),
		    hiredis = require("hiredis");
		
		exports.debug_mode = false;
		exports.name = "hiredis";
		
		function HiredisReplyParser(options) {
		    this.name = exports.name;
		    this.options = options || {};
		    this.reset();
		    events.EventEmitter.call(this);
		}
		
		util.inherits(HiredisReplyParser, events.EventEmitter);
		
		exports.Parser = HiredisReplyParser;
		
		HiredisReplyParser.prototype.reset = function () {
		    this.reader = new hiredis.Reader({
		        return_buffers: this.options.return_buffers || false
		    });
		};
		
		HiredisReplyParser.prototype.execute = function (data) {
		    var reply;
		    this.reader.feed(data);
		    while (true) {
		        try {
		            reply = this.reader.get();
		        } catch (err) {
		            this.emit("error", err);
		            break;
		        }
		
		        if (reply === undefined) {
		            break;
		        }
		
		        if (reply && reply.constructor === Error) {
		            this.emit("reply error", reply);
		        } else {
		            this.emit("reply", reply);
		        }
		    }
		};
		
	
	}, 'redis/lib/parser/javascript.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/parser/javascript.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/parser/javascript.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/parser/javascript.js';
		var __dirname = 'redis/lib/parser';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/parser/javascript.js'], env: {}};
	
		/** code **/
		var events = require("events"),
		    util   = require("../util");
		
		function Packet(type, size) {
		    this.type = type;
		    this.size = +size;
		}
		
		exports.name = "javascript";
		exports.debug_mode = false;
		
		function ReplyParser(options) {
		    this.name = exports.name;
		    this.options = options || { };
		
		    this._buffer            = null;
		    this._offset            = 0;
		    this._encoding          = "utf-8";
		    this._debug_mode        = options.debug_mode;
		    this._reply_type        = null;
		}
		
		util.inherits(ReplyParser, events.EventEmitter);
		
		exports.Parser = ReplyParser;
		
		function IncompleteReadBuffer(message) {
		    this.name = "IncompleteReadBuffer";
		    this.message = message;
		}
		util.inherits(IncompleteReadBuffer, Error);
		
		// Buffer.toString() is quite slow for small strings
		function small_toString(buf, start, end) {
		    var tmp = "", i;
		
		    for (i = start; i < end; i++) {
		        tmp += String.fromCharCode(buf[i]);
		    }
		
		    return tmp;
		}
		
		ReplyParser.prototype._parseResult = function (type) {
		    var start, end, offset, packetHeader;
		
		    if (type === 43 || type === 45) { // + or -
		        // up to the delimiter
		        end = this._packetEndOffset() - 1;
		        start = this._offset;
		
		        // include the delimiter
		        this._offset = end + 2;
		
		        if (end > this._buffer.length) {
		            this._offset = start;
		            throw new IncompleteReadBuffer("Wait for more data.");
		        }
		
		        if (this.options.return_buffers) {
		            return this._buffer.slice(start, end);
		        } else {
		            if (end - start < 65536) { // completely arbitrary
		                return small_toString(this._buffer, start, end);
		            } else {
		                return this._buffer.toString(this._encoding, start, end);
		            }
		        }
		    } else if (type === 58) { // :
		        // up to the delimiter
		        end = this._packetEndOffset() - 1;
		        start = this._offset;
		
		        // include the delimiter
		        this._offset = end + 2;
		
		        if (end > this._buffer.length) {
		            this._offset = start;
		            throw new IncompleteReadBuffer("Wait for more data.");
		        }
		
		        if (this.options.return_buffers) {
		            return this._buffer.slice(start, end);
		        }
		
		        // return the coerced numeric value
		        return +small_toString(this._buffer, start, end);
		    } else if (type === 36) { // $
		        // set a rewind point, as the packet could be larger than the
		        // buffer in memory
		        offset = this._offset - 1;
		
		        packetHeader = new Packet(type, this.parseHeader());
		
		        // packets with a size of -1 are considered null
		        if (packetHeader.size === -1) {
		            return undefined;
		        }
		
		        end = this._offset + packetHeader.size;
		        start = this._offset;
		
		        // set the offset to after the delimiter
		        this._offset = end + 2;
		
		        if (end > this._buffer.length) {
		            this._offset = offset;
		            throw new IncompleteReadBuffer("Wait for more data.");
		        }
		
		        if (this.options.return_buffers) {
		            return this._buffer.slice(start, end);
		        } else {
		            return this._buffer.toString(this._encoding, start, end);
		        }
		    } else if (type === 42) { // *
		        offset = this._offset;
		        packetHeader = new Packet(type, this.parseHeader());
		
		        if (packetHeader.size < 0) {
		            return null;
		        }
		
		        if (packetHeader.size > this._bytesRemaining()) {
		            this._offset = offset - 1;
		            throw new IncompleteReadBuffer("Wait for more data.");
		        }
		
		        var reply = [ ];
		        var ntype, i, res;
		
		        offset = this._offset - 1;
		
		        for (i = 0; i < packetHeader.size; i++) {
		            ntype = this._buffer[this._offset++];
		
		            if (this._offset > this._buffer.length) {
		                throw new IncompleteReadBuffer("Wait for more data.");
		            }
		            res = this._parseResult(ntype);
		            if (res === undefined) {
		                res = null;
		            }
		            reply.push(res);
		        }
		
		        return reply;
		    }
		};
		
		ReplyParser.prototype.execute = function (buffer) {
		    this.append(buffer);
		
		    var type, ret, offset;
		
		    while (true) {
		        offset = this._offset;
		        try {
		            // at least 4 bytes: :1\r\n
		            if (this._bytesRemaining() < 4) {
		                break;
		            }
		
		            type = this._buffer[this._offset++];
		
		            if (type === 43) { // +
		                ret = this._parseResult(type);
		
		                if (ret === null) {
		                    break;
		                }
		
		                this.send_reply(ret);
		            } else  if (type === 45) { // -
		                ret = this._parseResult(type);
		
		                if (ret === null) {
		                    break;
		                }
		
		                this.send_error(ret);
		            } else if (type === 58) { // :
		                ret = this._parseResult(type);
		
		                if (ret === null) {
		                    break;
		                }
		
		                this.send_reply(ret);
		            } else if (type === 36) { // $
		                ret = this._parseResult(type);
		
		                if (ret === null) {
		                    break;
		                }
		
		                // check the state for what is the result of
		                // a -1, set it back up for a null reply
		                if (ret === undefined) {
		                    ret = null;
		                }
		
		                this.send_reply(ret);
		            } else if (type === 42) { // *
		                // set a rewind point. if a failure occurs,
		                // wait for the next execute()/append() and try again
		                offset = this._offset - 1;
		
		                ret = this._parseResult(type);
		
		                this.send_reply(ret);
		            }
		        } catch (err) {
		            // catch the error (not enough data), rewind, and wait
		            // for the next packet to appear
		            if (! (err instanceof IncompleteReadBuffer)) {
		              throw err;
		            }
		            this._offset = offset;
		            break;
		        }
		    }
		};
		
		ReplyParser.prototype.append = function (newBuffer) {
		    if (!newBuffer) {
		        return;
		    }
		
		    // first run
		    if (this._buffer === null) {
		        this._buffer = newBuffer;
		
		        return;
		    }
		
		    // out of data
		    if (this._offset >= this._buffer.length) {
		        this._buffer = newBuffer;
		        this._offset = 0;
		
		        return;
		    }
		
		    // very large packet
		    // check for concat, if we have it, use it
		    if (Buffer.concat !== undefined) {
		        this._buffer = Buffer.concat([this._buffer.slice(this._offset), newBuffer]);
		    } else {
		        var remaining = this._bytesRemaining(),
		            newLength = remaining + newBuffer.length,
		            tmpBuffer = new Buffer(newLength);
		
		        this._buffer.copy(tmpBuffer, 0, this._offset);
		        newBuffer.copy(tmpBuffer, remaining, 0);
		
		        this._buffer = tmpBuffer;
		    }
		
		    this._offset = 0;
		};
		
		ReplyParser.prototype.parseHeader = function () {
		    var end   = this._packetEndOffset(),
		        value = small_toString(this._buffer, this._offset, end - 1);
		
		    this._offset = end + 1;
		
		    return value;
		};
		
		ReplyParser.prototype._packetEndOffset = function () {
		    var offset = this._offset;
		
		    while (this._buffer[offset] !== 0x0d && this._buffer[offset + 1] !== 0x0a) {
		        offset++;
		
		        if (offset >= this._buffer.length) {
		            throw new IncompleteReadBuffer("didn't see LF after NL reading multi bulk count (" + offset + " => " + this._buffer.length + ", " + this._offset + ")");
		        }
		    }
		
		    offset++;
		    return offset;
		};
		
		ReplyParser.prototype._bytesRemaining = function () {
		    return (this._buffer.length - this._offset) < 0 ? 0 : (this._buffer.length - this._offset);
		};
		
		ReplyParser.prototype.parser_error = function (message) {
		    this.emit("error", message);
		};
		
		ReplyParser.prototype.send_error = function (reply) {
		    this.emit("reply error", reply);
		};
		
		ReplyParser.prototype.send_reply = function (reply) {
		    this.emit("reply", reply);
		};
		
	
	}, 'redis/lib/commands.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'redis/lib/commands.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'redis/lib/commands.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'redis/lib/commands.js';
		var __dirname = 'redis/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', 'redis/lib/commands.js'], env: {}};
	
		/** code **/
		// This file was generated by ./generate_commands.js on Sun Dec 15 2013 15:58:20 GMT+0000 (GMT)
		module.exports = [
		    "append",
		    "auth",
		    "bgrewriteaof",
		    "bgsave",
		    "bitcount",
		    "bitop",
		    "blpop",
		    "brpop",
		    "brpoplpush",
		    "client kill",
		    "client list",
		    "client getname",
		    "client setname",
		    "config get",
		    "config rewrite",
		    "config set",
		    "config resetstat",
		    "dbsize",
		    "debug object",
		    "debug segfault",
		    "decr",
		    "decrby",
		    "del",
		    "discard",
		    "dump",
		    "echo",
		    "eval",
		    "evalsha",
		    "exec",
		    "exists",
		    "expire",
		    "expireat",
		    "flushall",
		    "flushdb",
		    "get",
		    "getbit",
		    "getrange",
		    "getset",
		    "hdel",
		    "hexists",
		    "hget",
		    "hgetall",
		    "hincrby",
		    "hincrbyfloat",
		    "hkeys",
		    "hlen",
		    "hmget",
		    "hmset",
		    "hset",
		    "hsetnx",
		    "hvals",
		    "incr",
		    "incrby",
		    "incrbyfloat",
		    "info",
		    "keys",
		    "lastsave",
		    "lindex",
		    "linsert",
		    "llen",
		    "lpop",
		    "lpush",
		    "lpushx",
		    "lrange",
		    "lrem",
		    "lset",
		    "ltrim",
		    "mget",
		    "migrate",
		    "monitor",
		    "move",
		    "mset",
		    "msetnx",
		    "multi",
		    "object",
		    "persist",
		    "pexpire",
		    "pexpireat",
		    "ping",
		    "psetex",
		    "psubscribe",
		    "pubsub",
		    "pttl",
		    "publish",
		    "punsubscribe",
		    "quit",
		    "randomkey",
		    "rename",
		    "renamenx",
		    "restore",
		    "rpop",
		    "rpoplpush",
		    "rpush",
		    "rpushx",
		    "sadd",
		    "save",
		    "scard",
		    "script exists",
		    "script flush",
		    "script kill",
		    "script load",
		    "sdiff",
		    "sdiffstore",
		    "select",
		    "set",
		    "setbit",
		    "setex",
		    "setnx",
		    "setrange",
		    "shutdown",
		    "sinter",
		    "sinterstore",
		    "sismember",
		    "slaveof",
		    "slowlog",
		    "smembers",
		    "smove",
		    "sort",
		    "spop",
		    "srandmember",
		    "srem",
		    "strlen",
		    "subscribe",
		    "sunion",
		    "sunionstore",
		    "sync",
		    "time",
		    "ttl",
		    "type",
		    "unsubscribe",
		    "unwatch",
		    "watch",
		    "zadd",
		    "zcard",
		    "zcount",
		    "zincrby",
		    "zinterstore",
		    "zrange",
		    "zrangebyscore",
		    "zrank",
		    "zrem",
		    "zremrangebyrank",
		    "zremrangebyscore",
		    "zrevrange",
		    "zrevrangebyscore",
		    "zrevrank",
		    "zscore",
		    "zunionstore",
		    "scan",
		    "sscan",
		    "hscan",
		    "zscan"
		];
		
	
	}, 'cache-storage/lib/Storage/Sync/Storage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Sync/Storage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Sync/Storage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Sync/Storage.js';
		var __dirname = 'cache-storage/lib/Storage/Sync';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Sync/Storage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var BaseStorage, Cache, Storage, isWindow, moment, path, _ref,
		    __hasProp = {}.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; };
		
		  isWindow = typeof window === 'undefined' ? false : true;
		
		  if (!isWindow) {
		    path = require('path');
		  }
		
		  BaseStorage = require('../Storage');
		
		  moment = require('moment');
		
		  Cache = require('../../Cache');
		
		  Storage = (function(_super) {
		    __extends(Storage, _super);
		
		    function Storage() {
		      _ref = Storage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    Storage.prototype.async = false;
		
		    Storage.prototype.read = function(key) {
		      var data;
		      data = this.getData();
		      if (typeof data[key] === 'undefined') {
		        return null;
		      } else {
		        if (this.verify(this.findMeta(key))) {
		          return data[key];
		        } else {
		          this.remove(key);
		          return null;
		        }
		      }
		    };
		
		    Storage.prototype.write = function(key, data, dependencies) {
		      var all, meta;
		      if (dependencies == null) {
		        dependencies = {};
		      }
		      all = this.getData();
		      all[key] = data;
		      meta = this.getMeta();
		      meta[key] = dependencies;
		      return this.writeData(all, meta);
		    };
		
		    Storage.prototype.remove = function(key) {
		      var data, meta;
		      data = this.getData();
		      meta = this.getMeta();
		      if (typeof data[key] !== 'undefined') {
		        delete data[key];
		        delete meta[key];
		      }
		      return this.writeData(data, meta);
		    };
		
		    Storage.prototype.removeAll = function() {
		      return this.writeData({}, {});
		    };
		
		    Storage.prototype.clean = function(conditions) {
		      var key, tag, type, typeFn, _i, _j, _k, _len, _len1, _len2, _ref1, _ref2, _ref3, _results;
		      typeFn = Object.prototype.toString;
		      type = typeFn.call(conditions);
		      if (conditions === Cache.ALL) {
		        return this.removeAll();
		      } else if (type === '[object Object]') {
		        if (typeof conditions[Cache.TAGS] !== 'undefined') {
		          if (typeFn(conditions[Cache.TAGS]) === '[object String]') {
		            conditions[Cache.TAGS] = [conditions[Cache.TAGS]];
		          }
		          _ref1 = conditions[Cache.TAGS];
		          for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
		            tag = _ref1[_i];
		            _ref2 = this.findKeysByTag(tag);
		            for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
		              key = _ref2[_j];
		              this.remove(key);
		            }
		          }
		        }
		        if (typeof conditions[Cache.PRIORITY] !== 'undefined') {
		          _ref3 = this.findKeysByPriority(conditions[Cache.PRIORITY]);
		          _results = [];
		          for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
		            key = _ref3[_k];
		            _results.push(this.remove(key));
		          }
		          return _results;
		        }
		      }
		    };
		
		    Storage.prototype.findMeta = function(key) {
		      var meta;
		      meta = this.getMeta();
		      if (typeof meta[key] !== 'undefined') {
		        return meta[key];
		      } else {
		        return null;
		      }
		    };
		
		    Storage.prototype.findKeysByTag = function(tag) {
		      var key, meta, metas, result;
		      metas = this.getMeta();
		      result = [];
		      for (key in metas) {
		        meta = metas[key];
		        if (typeof meta[Cache.TAGS] !== 'undefined' && meta[Cache.TAGS].indexOf(tag) !== -1) {
		          result.push(key);
		        }
		      }
		      return result;
		    };
		
		    Storage.prototype.findKeysByPriority = function(priority) {
		      var key, meta, metas, result;
		      metas = this.getMeta();
		      result = [];
		      for (key in metas) {
		        meta = metas[key];
		        if (typeof meta[Cache.PRIORITY] !== 'undefined' && meta[Cache.PRIORITY] <= priority) {
		          result.push(key);
		        }
		      }
		      return result;
		    };
		
		    Storage.prototype.verify = function(meta) {
		      var file, item, mtime, time, typefn, _i, _len, _ref1, _ref2, _ref3;
		      typefn = Object.prototype.toString;
		      if (typefn.call(meta) === '[object Object]') {
		        if (typeof meta[Cache.EXPIRE] !== 'undefined') {
		          if (moment().valueOf() >= meta[Cache.EXPIRE]) {
		            return false;
		          }
		        }
		        if (typeof meta[Cache.ITEMS] !== 'undefined') {
		          _ref1 = meta[Cache.ITEMS];
		          for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
		            item = _ref1[_i];
		            item = this.findMeta(item);
		            if ((item === null) || (item !== null && this.verify(item) === false)) {
		              return false;
		            }
		          }
		        }
		        if (typeof meta[Cache.FILES] !== 'undefined') {
		          this.checkFilesSupport();
		          if (isWindow) {
		            _ref2 = meta[Cache.FILES];
		            for (file in _ref2) {
		              time = _ref2[file];
		              mtime = window.require.getStats(file).mtime;
		              if (mtime === null) {
		                throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
		              }
		              if (window.require.getStats(file).mtime.getTime() !== time) {
		                return false;
		              }
		            }
		          } else {
		            _ref3 = meta[Cache.FILES];
		            for (file in _ref3) {
		              time = _ref3[file];
		              if ((new Date(Cache.getFs().statSync(file).mtime)).getTime() !== time) {
		                return false;
		              }
		            }
		          }
		        }
		      }
		      return true;
		    };
		
		    Storage.prototype.parseDependencies = function(dependencies) {
		      var file, files, item, mtime, result, time, typefn, _i, _j, _k, _len, _len1, _len2, _ref1, _ref2, _ref3;
		      typefn = Object.prototype.toString;
		      result = {};
		      if (typefn.call(dependencies) === '[object Object]') {
		        if (typeof dependencies[Cache.PRIORITY] !== 'undefined') {
		          result[Cache.PRIORITY] = dependencies[Cache.PRIORITY];
		        }
		        if (typeof dependencies[Cache.TAGS] !== 'undefined') {
		          result[Cache.TAGS] = dependencies[Cache.TAGS];
		        }
		        if (typeof dependencies[Cache.ITEMS] !== 'undefined') {
		          result[Cache.ITEMS] = [];
		          _ref1 = dependencies[Cache.ITEMS];
		          for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
		            item = _ref1[_i];
		            result[Cache.ITEMS].push(this.cache.generateKey(item));
		          }
		        }
		        if (typeof dependencies[Cache.EXPIRE] !== 'undefined') {
		          switch (typefn.call(dependencies[Cache.EXPIRE])) {
		            case '[object String]':
		              time = moment(dependencies[Cache.EXPIRE], Cache.TIME_FORMAT);
		              break;
		            case '[object Object]':
		              time = moment().add(dependencies[Cache.EXPIRE]);
		              break;
		            default:
		              throw new Error('Expire format is not valid');
		          }
		          result[Cache.EXPIRE] = time.valueOf();
		        }
		        if (typeof dependencies[Cache.FILES] !== 'undefined') {
		          this.checkFilesSupport();
		          files = {};
		          if (isWindow) {
		            _ref2 = dependencies[Cache.FILES];
		            for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
		              file = _ref2[_j];
		              mtime = window.require.getStats(file).mtime;
		              if (mtime === null) {
		                throw new Error('File stats are disabled in your simq configuration. Can not get stats for ' + file + '.');
		              }
		              file = window.require.resolve(file);
		              files[file] = mtime.getTime();
		            }
		          } else {
		            _ref3 = dependencies[Cache.FILES];
		            for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
		              file = _ref3[_k];
		              file = path.resolve(file);
		              files[file] = (new Date(Cache.getFs().statSync(file).mtime)).getTime();
		            }
		          }
		          result[Cache.FILES] = files;
		        }
		      }
		      return result;
		    };
		
		    return Storage;
		
		  })(BaseStorage);
		
		  module.exports = Storage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Sync/BrowserLocalStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Sync/BrowserLocalStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Sync/BrowserLocalStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Sync/BrowserLocalStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Sync';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Sync/BrowserLocalStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var BrowserLocalStorage, Cache, Storage,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  Cache = require('../../Cache');
		
		  BrowserLocalStorage = (function(_super) {
		    __extends(BrowserLocalStorage, _super);
		
		    BrowserLocalStorage.TEST_VALUE = '__--cache-storage--__';
		
		    BrowserLocalStorage.prototype.allData = null;
		
		    BrowserLocalStorage.prototype.data = null;
		
		    BrowserLocalStorage.prototype.meta = null;
		
		    function BrowserLocalStorage() {
		      if (!BrowserLocalStorage.isSupported()) {
		        throw new Error('Cache storage: Local storage is not supported');
		      }
		    }
		
		    BrowserLocalStorage.isSupported = function() {
		      var e;
		      try {
		        localStorage.setItem(BrowserLocalStorage.TEST_VALUE, BrowserLocalStorage.TEST_VALUE);
		        localStorage.getItem(BrowserLocalStorage.TEST_VALUE);
		        return true;
		      } catch (_error) {
		        e = _error;
		        return false;
		      }
		    };
		
		    BrowserLocalStorage.prototype.getName = function() {
		      return '__' + this.cache.namespace;
		    };
		
		    BrowserLocalStorage.prototype.loadData = function() {
		      var data;
		      if (this.allData === null) {
		        data = localStorage.getItem(this.getName());
		        if (data === null) {
		          this.allData = {
		            data: {},
		            meta: {}
		          };
		        } else {
		          this.allData = JSON.parse(data);
		        }
		      }
		      return this.allData;
		    };
		
		    BrowserLocalStorage.prototype.getData = function() {
		      if (this.data === null) {
		        this.data = this.loadData().data;
		      }
		      return this.data;
		    };
		
		    BrowserLocalStorage.prototype.getMeta = function() {
		      if (this.meta === null) {
		        this.meta = this.loadData().meta;
		      }
		      return this.meta;
		    };
		
		    BrowserLocalStorage.prototype.writeData = function(data, meta) {
		      this.data = data;
		      this.meta = meta;
		      return localStorage.setItem(this.getName(), JSON.stringify({
		        data: this.data,
		        meta: this.meta
		      }));
		    };
		
		    return BrowserLocalStorage;
		
		  })(Storage);
		
		  module.exports = BrowserLocalStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Async/DevNullStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Async/DevNullStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Async/DevNullStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Async/DevNullStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Async';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Async/DevNullStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var DevNullStorage, Storage, _ref,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  DevNullStorage = (function(_super) {
		    __extends(DevNullStorage, _super);
		
		    function DevNullStorage() {
		      _ref = DevNullStorage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    DevNullStorage.prototype.getData = function(fn) {
		      return fn(null, {});
		    };
		
		    DevNullStorage.prototype.getMeta = function(fn) {
		      return fn(null, {});
		    };
		
		    DevNullStorage.prototype.writeData = function(data, meta, fn) {
		      return fn(null);
		    };
		
		    DevNullStorage.prototype.read = function(key, fn) {
		      return fn(null, null);
		    };
		
		    DevNullStorage.prototype.write = function(key, data, dependencies, fn) {
		      if (dependencies == null) {
		        dependencies = {};
		      }
		      if (Object.prototype.toString.call(dependencies) === '[object Function]') {
		        fn = dependencies;
		        dependencies = {};
		      }
		      return fn(null);
		    };
		
		    DevNullStorage.prototype.remove = function(key, fn) {
		      return fn(null);
		    };
		
		    return DevNullStorage;
		
		  })(Storage);
		
		  module.exports = DevNullStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Sync/DevNullStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Sync/DevNullStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Sync/DevNullStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Sync/DevNullStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Sync';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Sync/DevNullStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var DevNullStorage, Storage, _ref,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  DevNullStorage = (function(_super) {
		    __extends(DevNullStorage, _super);
		
		    function DevNullStorage() {
		      _ref = DevNullStorage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    DevNullStorage.prototype.getData = function() {
		      return {};
		    };
		
		    DevNullStorage.prototype.getMeta = function() {
		      return {};
		    };
		
		    DevNullStorage.prototype.writeData = function(data, meta) {};
		
		    DevNullStorage.prototype.read = function(key) {
		      return null;
		    };
		
		    DevNullStorage.prototype.write = function(key, data, dependencies) {
		      if (dependencies == null) {
		        dependencies = {};
		      }
		    };
		
		    DevNullStorage.prototype.remove = function(key) {};
		
		    return DevNullStorage;
		
		  })(Storage);
		
		  module.exports = DevNullStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Async/FileStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Async/FileStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Async/FileStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Async/FileStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Async';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Async/FileStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Cache, FileStorage, Storage, fs, path,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  Cache = require('../../Cache');
		
		  fs = null;
		
		  path = null;
		
		  FileStorage = (function(_super) {
		    __extends(FileStorage, _super);
		
		    FileStorage.prototype.directory = null;
		
		    FileStorage.prototype.allData = null;
		
		    FileStorage.prototype.data = null;
		
		    FileStorage.prototype.meta = null;
		
		    function FileStorage(directory) {
		      this.directory = directory;
		      if (typeof window !== 'undefined') {
		        throw new Error('FileStorage: Can not use this storage in browser');
		      }
		      fs = require('fs');
		      path = require('path');
		      this.directory = path.resolve(this.directory);
		      if (!Cache.getFs().existsSync(this.directory)) {
		        throw new Error('FileStorage: directory ' + this.directory + ' does not exists');
		      }
		      if (!Cache.getFs().statSync(this.directory).isDirectory()) {
		        throw new Error('FileStorage: path ' + this.directory + ' must be directory');
		      }
		    }
		
		    FileStorage.prototype.getFileName = function() {
		      return this.directory + '/__' + this.cache.namespace + '.json';
		    };
		
		    FileStorage.prototype.loadData = function(fn) {
		      var file,
		        _this = this;
		      if (this.allData === null) {
		        file = this.getFileName();
		        return Cache.getFs().exists(file, function(exists) {
		          if (exists) {
		            return Cache.getFs().readFile(file, {
		              encoding: 'utf8'
		            }, function(err, data) {
		              if (err) {
		                return fn(err, null);
		              } else {
		                _this.allData = JSON.parse(data);
		                return fn(null, _this.allData);
		              }
		            });
		          } else {
		            _this.allData = {
		              data: {},
		              meta: {}
		            };
		            return fn(null, _this.allData);
		          }
		        });
		      } else {
		        return fn(null, this.allData);
		      }
		    };
		
		    FileStorage.prototype.getData = function(fn) {
		      return this.loadData(function(err, data) {
		        return fn(err, data.data);
		      });
		    };
		
		    FileStorage.prototype.getMeta = function(fn) {
		      return this.loadData(function(err, data) {
		        return fn(err, data.meta);
		      });
		    };
		
		    FileStorage.prototype.writeData = function(data, meta, fn) {
		      var file;
		      this.data = data;
		      this.meta = meta;
		      this.allData = {
		        data: this.data,
		        meta: this.meta
		      };
		      file = this.getFileName();
		      Cache.getFs().writeFile(file, JSON.stringify({
		        data: this.data,
		        meta: this.meta
		      }), function(err) {
		        if (err) {
		          return fn(err);
		        } else {
		          return fn(null);
		        }
		      });
		      return this;
		    };
		
		    return FileStorage;
		
		  })(Storage);
		
		  module.exports = FileStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Sync/FileStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Sync/FileStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Sync/FileStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Sync/FileStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Sync';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Sync/FileStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Cache, FileStorage, Storage, fs, path,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  Cache = require('../../Cache');
		
		  fs = null;
		
		  path = null;
		
		  FileStorage = (function(_super) {
		    __extends(FileStorage, _super);
		
		    FileStorage.prototype.directory = null;
		
		    FileStorage.prototype.allData = null;
		
		    FileStorage.prototype.data = null;
		
		    FileStorage.prototype.meta = null;
		
		    function FileStorage(directory) {
		      this.directory = directory;
		      if (typeof window !== 'undefined') {
		        throw new Error('FileStorage: Can not use this storage in browser');
		      }
		      fs = require('fs');
		      path = require('path');
		      this.directory = path.resolve(this.directory);
		      if (!Cache.getFs().existsSync(this.directory)) {
		        throw new Error('FileStorage: directory ' + this.directory + ' does not exists');
		      }
		      if (!Cache.getFs().statSync(this.directory).isDirectory()) {
		        throw new Error('FileStorage: path ' + this.directory + ' must be directory');
		      }
		    }
		
		    FileStorage.prototype.getFileName = function() {
		      return this.directory + '/__' + this.cache.namespace + '.json';
		    };
		
		    FileStorage.prototype.loadData = function() {
		      var file;
		      if (this.allData === null) {
		        file = this.getFileName();
		        if (Cache.getFs().existsSync(file)) {
		          this.allData = JSON.parse(Cache.getFs().readFileSync(file, {
		            encoding: 'utf8'
		          }));
		        } else {
		          this.allData = {
		            data: {},
		            meta: {}
		          };
		        }
		      }
		      return this.allData;
		    };
		
		    FileStorage.prototype.getData = function() {
		      if (this.data === null) {
		        this.data = this.loadData().data;
		      }
		      return this.data;
		    };
		
		    FileStorage.prototype.getMeta = function() {
		      if (this.meta === null) {
		        this.meta = this.loadData().meta;
		      }
		      return this.meta;
		    };
		
		    FileStorage.prototype.writeData = function(data, meta) {
		      var file;
		      this.data = data;
		      this.meta = meta;
		      this.allData = {
		        data: this.data,
		        meta: this.meta
		      };
		      file = this.getFileName();
		      return Cache.getFs().writeFileSync(file, JSON.stringify({
		        data: this.data,
		        meta: this.meta
		      }));
		    };
		
		    return FileStorage;
		
		  })(Storage);
		
		  module.exports = FileStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Async/MemoryStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Async/MemoryStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Async/MemoryStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Async/MemoryStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Async';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Async/MemoryStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var MemoryStorage, Storage, _ref,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  MemoryStorage = (function(_super) {
		    __extends(MemoryStorage, _super);
		
		    function MemoryStorage() {
		      _ref = MemoryStorage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    MemoryStorage.prototype.data = null;
		
		    MemoryStorage.prototype.meta = null;
		
		    MemoryStorage.prototype.getData = function(fn) {
		      if (this.data === null) {
		        this.data = {};
		      }
		      return fn(null, this.data);
		    };
		
		    MemoryStorage.prototype.getMeta = function(fn) {
		      if (this.meta === null) {
		        this.meta = {};
		      }
		      return fn(null, this.meta);
		    };
		
		    MemoryStorage.prototype.writeData = function(data, meta, fn) {
		      this.data = data;
		      this.meta = meta;
		      return fn(null);
		    };
		
		    return MemoryStorage;
		
		  })(Storage);
		
		  module.exports = MemoryStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Sync/MemoryStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Sync/MemoryStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Sync/MemoryStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Sync/MemoryStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Sync';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Sync/MemoryStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var MemoryStorage, Storage, _ref,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  MemoryStorage = (function(_super) {
		    __extends(MemoryStorage, _super);
		
		    function MemoryStorage() {
		      _ref = MemoryStorage.__super__.constructor.apply(this, arguments);
		      return _ref;
		    }
		
		    MemoryStorage.prototype.data = null;
		
		    MemoryStorage.prototype.meta = null;
		
		    MemoryStorage.prototype.getData = function() {
		      if (this.data === null) {
		        this.data = {};
		      }
		      return this.data;
		    };
		
		    MemoryStorage.prototype.getMeta = function() {
		      if (this.meta === null) {
		        this.meta = {};
		      }
		      return this.meta;
		    };
		
		    MemoryStorage.prototype.writeData = function(data, meta) {
		      this.data = data;
		      this.meta = meta;
		    };
		
		    return MemoryStorage;
		
		  })(Storage);
		
		  module.exports = MemoryStorage;
		
		}).call(this);
		
	
	}, 'cache-storage/lib/Storage/Async/RedisStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/lib/Storage/Async/RedisStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/lib/Storage/Async/RedisStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/lib/Storage/Async/RedisStorage.js';
		var __dirname = 'cache-storage/lib/Storage/Async';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/lib/Storage/Async/RedisStorage.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var RedisStorage, Storage, assert, redis,
		    __hasProp = {}.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; };
		
		  Storage = require('./Storage');
		
		  redis = require('redis');
		
		  assert = require('assert');
		
		  RedisStorage = (function(_super) {
		    __extends(RedisStorage, _super);
		
		    RedisStorage.META_KEY = '__redis__storage__meta__key__';
		
		    RedisStorage.prototype.client = null;
		
		    function RedisStorage() {
		      if (typeof window !== 'undefined') {
		        throw new Error('FileStorage: Can not use this storage in browser');
		      }
		      this.client = redis.createClient();
		    }
		
		    RedisStorage.prototype.selectDatabase = function(database, fn) {
		      return this.client.SELECT(database, fn);
		    };
		
		    RedisStorage.prototype._read = function(name, fn, defaults) {
		      var _this = this;
		      if (defaults == null) {
		        defaults = null;
		      }
		      return this.client.GET(name, function(err, data) {
		        if (err) {
		          return fn(err, null);
		        } else if (data === null) {
		          if (defaults === null) {
		            return fn(null, null);
		          } else {
		            return _this._write(name, defaults, function(err) {
		              if (err) {
		                return fn(err, null);
		              } else {
		                return _this._read(name, function(err, data) {
		                  if (err) {
		                    return fn(err, null);
		                  } else {
		                    return fn(null, data);
		                  }
		                });
		              }
		            });
		          }
		        } else {
		          return fn(null, JSON.parse(data));
		        }
		      });
		    };
		
		    RedisStorage.prototype._write = function(name, data, fn) {
		      return this.client.SET(name, JSON.stringify(data), function(err) {
		        if (err) {
		          return fn(err);
		        } else {
		          return fn(null);
		        }
		      });
		    };
		
		    RedisStorage.prototype._remove = function(name, fn) {
		      return this.client.DEL(name, fn);
		    };
		
		    RedisStorage.prototype._removeAll = function(fn) {
		      return this.client.FLUSHDB(fn);
		    };
		
		    RedisStorage.prototype.getMeta = function(fn) {
		      return this._read(RedisStorage.META_KEY, fn, {});
		    };
		
		    RedisStorage.prototype.read = function(key, fn) {
		      var _this = this;
		      return this._read(key, function(err, data) {
		        if (err) {
		          return fn(err, null);
		        } else if (data === null) {
		          return fn(null, null);
		        } else {
		          return _this.findMeta(key, function(err, meta) {
		            if (err) {
		              return fn(err, null);
		            } else {
		              return _this.verify(meta, function(err, state) {
		                if (err) {
		                  return fn(err, null);
		                } else if (state) {
		                  return fn(null, data);
		                } else {
		                  return _this.remove(key, function() {
		                    return fn(null, null);
		                  });
		                }
		              });
		            }
		          });
		        }
		      });
		    };
		
		    RedisStorage.prototype.write = function(key, data, dependencies, fn) {
		      var _this = this;
		      if (dependencies == null) {
		        dependencies = {};
		      }
		      return this._write(key, data, function(err) {
		        if (err) {
		          return fn(err);
		        } else {
		          return _this.getMeta(function(err, meta) {
		            if (err) {
		              return fn(err);
		            } else {
		              meta[key] = dependencies;
		              return _this._write(RedisStorage.META_KEY, meta, fn);
		            }
		          });
		        }
		      });
		    };
		
		    RedisStorage.prototype.remove = function(key, fn) {
		      var _this = this;
		      return this.getMeta(function(err, meta) {
		        if (err) {
		          return fn(err);
		        } else {
		          if (typeof meta[key] !== 'undefined') {
		            delete meta[key];
		          }
		          return _this._remove(key, function(err) {
		            if (err) {
		              return fn(err);
		            } else {
		              return _this._write(RedisStorage.META_KEY, meta, fn);
		            }
		          });
		        }
		      });
		    };
		
		    RedisStorage.prototype.removeAll = function(fn) {
		      return this._removeAll(fn);
		    };
		
		    return RedisStorage;
		
		  })(Storage);
		
		  module.exports = RedisStorage;
		
		}).call(this);
		
	
	}, '/lib/Api.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/lib/Api.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/lib/Api.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/lib/Api.js';
		var __dirname = '/lib';
		var process = {cwd: function() {return '/';}, argv: ['node', '/lib/Api.js'], env: {}};
	
		/** code **/
		// Generated by CoffeeScript 1.6.3
		(function() {
		  var Api, Finder, Loader, Translator, callsite, fs, path;
		
		  if (typeof window !== 'undefined') {
		    throw new Error('Translator API can not be used in browser.');
		  }
		
		  Loader = require('./Loaders/Loader');
		
		  Translator = require('./Translator');
		
		  fs = require('fs');
		
		  path = require('path');
		
		  callsite = require('callsite');
		
		  Finder = require('fs-finder');
		
		  Api = (function() {
		    Api.prototype.configPath = null;
		
		    Api.prototype.config = null;
		
		    Api.prototype.translator = null;
		
		    Api.prototype.loader = null;
		
		    Api.prototype.language = 'en';
		
		    Api.prototype.languages = null;
		
		    function Api(configPath, language) {
		      var stack;
		      this.configPath = configPath;
		      this.language = language != null ? language : this.language;
		      if (this.configPath.charAt(0) === '.') {
		        stack = callsite();
		        this.configPath = path.join(path.dirname(stack[1].getFileName()), this.configPath);
		      }
		      this.configPath = path.normalize(this.configPath);
		      this.config = JSON.parse(fs.readFileSync(this.configPath, {
		        encoding: 'utf8'
		      }));
		      if (typeof this.config.path === 'undefined') {
		        this.config.path = '.';
		      }
		      if (typeof this.config.loader === 'undefined') {
		        this.config.loader = 'Json';
		      }
		      if (typeof this.config.languages === 'undefined') {
		        this.config.languages = [];
		      }
		      if (this.config.path.charAt(0) === '.') {
		        this.config.path = path.join(path.dirname(this.configPath), this.config.path);
		      }
		      this.translator = new Translator(this.configPath);
		      this.loader = new (require('./Loaders/' + this.config.loader))(this.config.path);
		    }
		
		    Api.prototype.release = function() {
		      return this.languages = null;
		    };
		
		    Api.prototype.getLanguages = function() {
		      var file, language, _i, _j, _len, _len1, _ref, _ref1;
		      if (this.languages === null) {
		        this.languages = [];
		        _ref = Finder.from(this.config.path).findFiles('.*.json');
		        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		          file = _ref[_i];
		          language = path.basename(file).split('.')[0];
		          if (this.languages.indexOf(language) === -1) {
		            this.languages.push(language);
		          }
		        }
		        _ref1 = this.config.languages;
		        for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
		          language = _ref1[_j];
		          if (this.languages.indexOf(language) === -1) {
		            this.languages.push(language);
		          }
		        }
		      }
		      return this.languages;
		    };
		
		    Api.prototype.hasLanguage = function(language) {
		      return this.getLanguages().indexOf(language) !== -1;
		    };
		
		    Api.prototype.addLanguage = function(language) {
		      if (!this.hasLanguage(language)) {
		        this.languages.push(language);
		        this.config.languages.push(language);
		        return fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, '\t'));
		      }
		    };
		
		    Api.prototype.getDictionaries = function() {
		      var dir, file, name, result, _i, _len, _ref;
		      result = [];
		      _ref = Finder.from(this.config.path).findFiles(this.language + '.*.json');
		      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		        file = _ref[_i];
		        name = path.relative(this.config.path, file);
		        dir = path.dirname(name);
		        name = path.basename(name, path.extname(name)).replace(new RegExp('^' + this.language + '\.'), '');
		        result.push(path.join(dir, name));
		      }
		      return this.createTree(result);
		    };
		
		    Api.prototype.addDictionary = function(dictionary) {
		      var info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.buf');
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      if (fs.existsSync(_path)) {
		        throw new Error("Dictionary '" + dictionary + "' already exists.");
		      }
		      return fs.writeFileSync(_path, '{}');
		    };
		
		    Api.prototype.renameDictionary = function(oldName, newName) {
		      var info, newInfo, newPath, _path;
		      info = this.translator.getMessageInfo(oldName + '.buf');
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      if (!fs.existsSync(_path)) {
		        throw new Error("Dictionary '" + oldName + "' does not exists.");
		      }
		      newInfo = this.translator.getMessageInfo(newName + '.buf');
		      newPath = this.loader.getFileSystemPath(newInfo.path, newInfo.category, this.language);
		      if (fs.existsSync(newPath)) {
		        throw new Error("Dictionary '" + newName + "' already exists.");
		      }
		      return fs.renameSync(_path, newPath);
		    };
		
		    Api.prototype.removeDictionary = function(dictionary) {
		      var info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.buf');
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      if (!fs.existsSync(_path)) {
		        throw new Error("Dictionary '" + dictionary + "' does not exists.");
		      }
		      return fs.unlinkSync(_path);
		    };
		
		    Api.prototype.getTranslations = function(dictionary) {
		      var files, info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.buf');
		      files = this.translator.loadCategory(info.path, info.category, this.language);
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      delete require.cache[_path];
		      return files;
		    };
		
		    Api.prototype.addTranslation = function(dictionary, name, translation) {
		      var data, info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.' + name);
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      data = this.getTranslations(dictionary);
		      if (typeof data[info.name] !== 'undefined') {
		        throw new Error("Translation '" + name + "' already exists in '" + dictionary + "' dictionary.");
		      }
		      data[info.name] = translation;
		      data = JSON.stringify(data, null, '\t');
		      return fs.writeFileSync(_path, data);
		    };
		
		    Api.prototype.editTranslation = function(dictionary, name, translation) {
		      var data, info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.' + name);
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      data = this.getTranslations(dictionary);
		      if (typeof data[info.name] === 'undefined') {
		        throw new Error("Translation '" + name + "' does not exists in '" + dictionary + "' dictionary.");
		      }
		      data[info.name] = translation;
		      data = JSON.stringify(data, null, '\t');
		      return fs.writeFileSync(_path, data);
		    };
		
		    Api.prototype.renameTranslation = function(dictionary, oldName, newName) {
		      var data, info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.' + oldName);
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      data = this.getTranslations(dictionary);
		      if (typeof data[info.name] === 'undefined') {
		        throw new Error("Translation '" + oldName + "' does not exists in '" + dictionary + "' dictionary.");
		      }
		      if (typeof data[newName] !== 'undefined') {
		        throw new Error("Translation '" + newName + "' already exists in '" + dictionary + "' dictionary.");
		      }
		      data[newName] = data[oldName];
		      delete data[oldName];
		      data = JSON.stringify(data, null, '\t');
		      return fs.writeFileSync(_path, data);
		    };
		
		    Api.prototype.removeTranslation = function(dictionary, name) {
		      var data, info, _path;
		      info = this.translator.getMessageInfo(dictionary + '.' + name);
		      _path = this.loader.getFileSystemPath(info.path, info.category, this.language);
		      data = this.getTranslations(dictionary);
		      delete data[name];
		      data = JSON.stringify(data, null, '\t');
		      return fs.writeFileSync(_path, data);
		    };
		
		    Api.prototype.createTree = function(paths) {
		      var buf, count, part, parts, result, _i, _j, _len, _len1, _path;
		      result = {};
		      count = 0;
		      for (_i = 0, _len = paths.length; _i < _len; _i++) {
		        _path = paths[_i];
		        parts = _path.split(path.sep);
		        buf = result;
		        for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
		          part = parts[_j];
		          if (typeof buf[part] === 'undefined') {
		            buf[part] = {};
		          }
		          buf = buf[part];
		        }
		        count++;
		      }
		      return result;
		    };
		
		    return Api;
		
		  })();
		
		  module.exports = Api;
		
		}).call(this);
		
	
	}, '/test/browser/tests/Translator.coffee': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/browser/tests/Translator.coffee');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/browser/tests/Translator.coffee';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/browser/tests/Translator.coffee';
		var __dirname = '/test/browser/tests';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/browser/tests/Translator.coffee'], env: {}};
	
		/** code **/
		(function() {
		  var BrowserLocalStorage, Cache, Translator, dir, translator;
		
		  Translator = require('/lib/Translator');
		
		  BrowserLocalStorage = require('cache-storage/Storage/BrowserLocalStorage');
		
		  Cache = require('cache-storage');
		
		  dir = '/test/data';
		
		  translator = null;
		
		  describe('Translator', function() {
		    beforeEach(function() {
		      translator = new Translator(dir);
		      return translator.language = 'en';
		    });
		    afterEach(function() {
		      return translator = null;
		    });
		    describe('#constructor()', function() {
		      it('should contain some plural forms', function() {
		        return expect(translator.plurals).not.to.be.eql({});
		      });
		      return it('should create translator from path in config file', function() {
		        translator = new Translator(dir + '/config.json');
		        return expect(translator.loader.directory).to.be.equal(dir);
		      });
		    });
		    describe('#normalizeTranslations()', function() {
		      it('should return normalized object with dictionary', function() {
		        return expect(translator.normalizeTranslations({
		          car: 'car',
		          bus: ['bus']
		        })).to.be.eql({
		          car: ['car'],
		          bus: ['bus']
		        });
		      });
		      it('should return normalized translations without comments', function() {
		        return expect(translator.normalizeTranslations({
		          one: ['# hello #', 'car', '# house #', 'something']
		        })).to.be.eql({
		          one: ['car', 'something']
		        });
		      });
		      it('should return normalized translations for list with comments', function() {
		        return expect(translator.normalizeTranslations({
		          one: [['first'], '# comment #', ['second', '# comment #'], ['third']]
		        })).to.be.eql({
		          one: [['first'], ['second'], ['third']]
		        });
		      });
		      return it('should return normalized translations for list with new syntax', function() {
		        return expect(translator.normalizeTranslations({
		          '-- list': ['first', 'second', 'third']
		        })).to.be.eql({
		          list: [['first'], ['second'], ['third']]
		        });
		      });
		    });
		    describe('#getMessageInfo()', function() {
		      return it('should return information about dictionary from message to translate', function() {
		        return expect(translator.getMessageInfo('web.pages.homepage.promo.title')).to.be.eql({
		          path: 'web/pages/homepage',
		          category: 'promo',
		          name: 'title'
		        });
		      });
		    });
		    describe('#loadCategory()', function() {
		      it('should load parsed dictionary', function() {
		        return expect(translator.loadCategory('web/pages/homepage', 'simple')).to.be.eql({
		          title: ['Title of promo box']
		        });
		      });
		      it('should load dictionary for different language', function() {
		        return expect(translator.loadCategory('web/pages/homepage', 'simple', 'cs')).to.be.eql({
		          title: ['Titulek promo boxu']
		        });
		      });
		      return it('should return empty object if dictionary does not exists', function() {
		        return expect(translator.loadCategory('some/unknown', 'translation')).to.be.eql({});
		      });
		    });
		    describe('#findTranslation()', function() {
		      it('should return english translations from dictionary', function() {
		        return expect(translator.findTranslation('web.pages.homepage.promo.title')).to.be.eql(['Title of promo box']);
		      });
		      it('should return translations from dictionary for different language', function() {
		        return expect(translator.findTranslation('web.pages.homepage.simple.title', 'cs')).to.be.eql(['Titulek promo boxu']);
		      });
		      it('should return null when translation does not exists', function() {
		        return expect(translator.findTranslation('some.unknown.translation')).to.be["null"];
		      });
		      return it('should return null when translation does not exists for given language', function() {
		        return expect(translator.findTranslation('some.unknown.translation', 'cs')).to.be["null"];
		      });
		    });
		    describe('#hasTranslation()', function() {
		      it('should return true when translation exists', function() {
		        return expect(translator.hasTranslation('web.pages.homepage.promo.title')).to.be["true"];
		      });
		      it('should return true when translation exists for different language', function() {
		        return expect(translator.hasTranslation('web.pages.homepage.simple.title', 'cs')).to.be["true"];
		      });
		      it('should return false when translation does not exists', function() {
		        return expect(translator.hasTranslation('some.unknown.translation')).to.be["false"];
		      });
		      return it('should return false when translation does not exists for different language', function() {
		        return expect(translator.hasTranslation('some.unknown.translation', 'cs')).to.be["false"];
		      });
		    });
		    describe('#pluralize()', function() {
		      it('should return right version of translation(s) by count', function() {
		        var cars, fruits;
		        cars = ['1 car', '%count% cars'];
		        expect(translator.pluralize('car', cars, 1)).to.be.equal('1 car');
		        expect(translator.pluralize('car', cars, 4)).to.be.equal('%count% cars');
		        fruits = [['1 apple', '%count% apples'], ['1 orange', '%count% oranges']];
		        expect(translator.pluralize('list', fruits, 1)).to.be.eql(['1 apple', '1 orange']);
		        return expect(translator.pluralize('list', fruits, 4)).to.be.eql(['%count% apples', '%count% oranges']);
		      });
		      return it('should return right version of translation(s) by count for different language', function() {
		        var cars, fruits;
		        cars = ['1 auto', '%count% auta', '%count% aut'];
		        expect(translator.pluralize('car', cars, 1, 'cs')).to.be.equal('1 auto');
		        expect(translator.pluralize('car', cars, 4, 'cs')).to.be.equal('%count% auta');
		        fruits = [['1 jablko', '%count% jablka', '%count% jablek'], ['1 pomeranč', '%count% pomeranče', '%count% pomerančů']];
		        expect(translator.pluralize('list', fruits, 1)).to.be.eql(['1 jablko', '1 pomeranč']);
		        return expect(translator.pluralize('list', fruits, 4)).to.be.eql(['%count% jablka', '%count% pomeranče']);
		      });
		    });
		    describe('#prepareTranslation()', function() {
		      return it('should return expanded translation with arguments', function() {
		        translator.addReplacement('item', 'car');
		        return expect(translator.prepareTranslation('%item% has got %count% %append%.', {
		          count: 5,
		          append: 'things'
		        })).to.be.equal('car has got 5 things.');
		      });
		    });
		    describe('#applyReplacements()', function() {
		      return it('should add replacements to text', function() {
		        return expect(translator.applyReplacements('%one% %two% %three%', {
		          one: 1,
		          two: 2,
		          three: 3
		        })).to.be.equal('1 2 3');
		      });
		    });
		    describe('#translate()', function() {
		      it('should return translated text from dictionary', function() {
		        return expect(translator.translate('web.pages.homepage.promo.title')).to.be.equal('Title of promo box');
		      });
		      it('should return original text if text is eclosed in \':\'', function() {
		        return expect(translator.translate(':do.not.translate.me:')).to.be.equal('do.not.translate.me');
		      });
		      it('should return array of list', function() {
		        return expect(translator.translate('web.pages.homepage.promo.list')).to.be.eql(['1st item', '2nd item', '3rd item', '4th item', '5th item']);
		      });
		      it('should return translation for plural form', function() {
		        return expect(translator.translate('web.pages.homepage.promo.cars', 3)).to.be.equal('3 cars');
		      });
		      it('should return translation of list for plural form', function() {
		        return expect(translator.translate('web.pages.homepage.promo.fruits', 3)).to.be.eql(['3 bananas', '3 citrons', '3 oranges']);
		      });
		      it('should return translation with replacement in message', function() {
		        translator.addReplacement('one', 1);
		        translator.addReplacement('dictionary', 'promo');
		        return expect(translator.translate('web.pages.homepage.%dictionary%.%name%', null, {
		          two: 2,
		          name: 'advanced'
		        })).to.be.equal('1 2');
		      });
		      it('should translate with parameters in place of count argument', function() {
		        return expect(translator.translate('web.pages.homepage.promo.advanced', {
		          one: '1',
		          two: 2
		        })).to.be.equal('1 2');
		      });
		      it('should translate one item from list in translate method', function() {
		        expect(translator.translate('web.pages.homepage.promo.newList[0]')).to.be.equal('first');
		        expect(translator.translate('web.pages.homepage.promo.newList[1]')).to.be.equal('second');
		        return expect(translator.translate('web.pages.homepage.promo.newList[2]')).to.be.equal('third');
		      });
		      it('should throw an error when translating one item from non-list', function() {
		        return expect(function() {
		          return translator.translate('web.pages.homepage.promo.title[5]');
		        })["throw"](Error);
		      });
		      it('should throw an error when translating one item which does not exists', function() {
		        return expect(function() {
		          return translator.translate('web.pages.homepage.promo.newList[5]');
		        })["throw"](Error);
		      });
		      it('should return translated text from dictionary for different language', function() {
		        return expect(translator.translate('cs|web.pages.homepage.simple.title')).to.be.equal('Titulek promo boxu');
		      });
		      return it('should return original text if text is eclosed in \':\'', function() {
		        return expect(translator.translate(':cs|do.not.translate.me:')).to.be.equal('do.not.translate.me');
		      });
		    });
		    describe('#translatePairs()', function() {
		      it('should throw an error if message to translate are not arrays', function() {
		        return expect(function() {
		          return translator.translatePairs('web.pages.homepage.promo', 'title', 'list');
		        })["throw"](Error);
		      });
		      it('should throw an error if keys and values have not got the same length', function() {
		        return expect(function() {
		          return translator.translatePairs('web.pages.homepage.promo', 'list', 'keys');
		        })["throw"](Error);
		      });
		      return it('should return object with keys and values translations', function() {
		        return expect(translator.translatePairs('web.pages.homepage.promo', 'keys', 'values')).to.be.eql({
		          '1st title': '1st text',
		          '2nd title': '2nd text',
		          '3rd title': '3rd text',
		          '4th title': '4th text'
		        });
		      });
		    });
		    describe('#translateMap()', function() {
		      it('should throw an error if object is not array or object', function() {
		        return expect(function() {
		          return translator.translateMap(new Date);
		        }).to["throw"](Error);
		      });
		      it('should translate array', function() {
		        return expect(translator.translateMap(['web.pages.homepage.promo.title', 'web.pages.homepage.promo.info'])).to.be.eql(['Title of promo box', 'Some info text']);
		      });
		      it('should translate object', function() {
		        var t;
		        t = {
		          title: 'web.pages.homepage.promo.title',
		          info: 'web.pages.homepage.promo.info'
		        };
		        return expect(translator.translateMap(t)).to.be.eql({
		          title: 'Title of promo box',
		          info: 'Some info text'
		        });
		      });
		      it('should translate array with plural forms translations', function() {
		        return expect(translator.translateMap(['web.pages.homepage.promo.cars', 'web.pages.homepage.promo.mobile'], 6)).to.be.eql(['6 cars', '6 mobiles']);
		      });
		      it('should translate array with arguments', function() {
		        return expect(translator.translateMap(['web.pages.homepage.promo.advanced'], {
		          one: 1,
		          two: 2
		        })).to.be.eql(['1 2']);
		      });
		      it('should translate array with base path', function() {
		        return expect(translator.translateMap(['title', 'info'], 'web.pages.homepage.promo')).to.be.eql(['Title of promo box', 'Some info text']);
		      });
		      return it('should translate array with list', function() {
		        return expect(translator.translateMap(['web.pages.homepage.promo.fruits'], 4)).to.be.eql([['4 bananas', '4 citrons', '4 oranges']]);
		      });
		    });
		    describe('#setCacheStorage()', function() {
		      it('should throw an exception if storage is not the right type', function() {
		        return expect(function() {
		          return translator.setCacheStorage(new Array);
		        })["throw"](Error);
		      });
		      return it('should create cache instance', function() {
		        translator.setCacheStorage(new BrowserLocalStorage);
		        return expect(translator.cache).to.be.an["instanceof"](Cache);
		      });
		    });
		    return describe('#expand()', function() {
		      it('should expand base translate method', function() {
		        var main;
		        main = translator.expand({});
		        return expect(main._('web.pages.homepage.promo.title')).to.be.equal('Title of promo box');
		      });
		      it('should expand translatePairs method', function() {
		        var main;
		        main = translator.expand({});
		        return expect(main._p('web.pages.homepage.promo', 'keys', 'values')).to.be.eql({
		          '1st title': '1st text',
		          '2nd title': '2nd text',
		          '3rd title': '3rd text',
		          '4th title': '4th text'
		        });
		      });
		      return it('should expand translateMap method', function() {
		        var main;
		        main = translator.expand({});
		        return expect(main._m(['web.pages.homepage.promo.title', 'web.pages.homepage.promo.info'])).to.be.eql(['Title of promo box', 'Some info text']);
		      });
		    });
		  });
		
		}).call(this);
		
	
	}, '/test/data/config.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/config.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/config.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/config.json';
		var __dirname = '/test/data';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/config.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"path": ".",
			"languages": [
				"sk"
			]
		}
		}).call(this);
		
	
	}, '/test/data/en.first.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/en.first.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/en.first.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/en.first.json';
		var __dirname = '/test/data';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/en.first.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"test": "hello"
		}
		}).call(this);
		
	
	}, '/test/data/web/pages/homepage/cs.simple.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/web/pages/homepage/cs.simple.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/web/pages/homepage/cs.simple.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/web/pages/homepage/cs.simple.json';
		var __dirname = '/test/data/web/pages/homepage';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/web/pages/homepage/cs.simple.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"title": "Titulek promo boxu"
		}
		}).call(this);
		
	
	}, '/test/data/web/pages/homepage/en.cached.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/web/pages/homepage/en.cached.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/web/pages/homepage/en.cached.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/web/pages/homepage/en.cached.json';
		var __dirname = '/test/data/web/pages/homepage';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/web/pages/homepage/en.cached.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {"variable": "1"}
		}).call(this);
		
	
	}, '/test/data/web/pages/homepage/en.promo.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/web/pages/homepage/en.promo.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/web/pages/homepage/en.promo.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/web/pages/homepage/en.promo.json';
		var __dirname = '/test/data/web/pages/homepage';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/web/pages/homepage/en.promo.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"title": "Title of promo box",
			"info": "Some info text",
			"list": [
				["1st item"],
				["2nd item"],
				["3rd item"],
				["4th item"],
				["5th item"]
			],
			"cars": [
				"1 car",
				"%count% cars"
			],
			"mobile": [
				"1 mobile",
				"%count% mobiles"
			],
			"fruits": [
				"# this is some random comment #",
				[
					"1 banana",
					"%count% bananas"
				],
				[
					"1 citron",
					"# another comment #",
					"%count% citrons"
				],
				[
					"1 orange",
					"%count% oranges"
				]
			],
			"keys": [
				["1st title"],
				["2nd title"],
				["3rd title"],
				["4th title"]
			],
			"values": [
				["1st text"],
				["2nd text"],
				["3rd text"],
				["4th text"]
			],
			"advanced": "%one% %two%",
			"-- newList": [
				"first",
				"second",
				"third"
			]
		}
		}).call(this);
		
	
	}, '/test/data/web/pages/homepage/en.simple.json': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, '/test/data/web/pages/homepage/en.simple.json');};
		require.resolve = function(name, parent) {if (parent === null) {parent = '/test/data/web/pages/homepage/en.simple.json';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = '/test/data/web/pages/homepage/en.simple.json';
		var __dirname = '/test/data/web/pages/homepage';
		var process = {cwd: function() {return '/';}, argv: ['node', '/test/data/web/pages/homepage/en.simple.json'], env: {}};
	
		/** code **/
		module.exports = (function() {
		return {
			"title": "Title of promo box"
		}
		}).call(this);
		
	
	}, 'cache-storage/Storage/BrowserLocalStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/BrowserLocalStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/BrowserLocalStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/BrowserLocalStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/BrowserLocalStorage.js'], env: {}};
	
		/** code **/
		console.log('BrowserLocalStorage is deprecated, please use BrowserLocalSyncStorage instead.');
		
		module.exports = require('../lib/Storage/Sync/BrowserLocalStorage');
	
	}, 'cache-storage/Storage/BrowserLocalSyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/BrowserLocalSyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/BrowserLocalSyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/BrowserLocalSyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/BrowserLocalSyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Sync/BrowserLocalStorage');
	
	}, 'cache-storage/Storage/DevNullAsyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/DevNullAsyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/DevNullAsyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/DevNullAsyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/DevNullAsyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Async/DevNullStorage');
	
	}, 'cache-storage/Storage/DevNullStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/DevNullStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/DevNullStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/DevNullStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/DevNullStorage.js'], env: {}};
	
		/** code **/
		console.log('DevNullStorage is deprecated, use DevNullSyncStorage instead.');
		
		module.exports = require('../lib/Storage/Sync/DevNullStorage');
	
	}, 'cache-storage/Storage/DevNullSyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/DevNullSyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/DevNullSyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/DevNullSyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/DevNullSyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Sync/DevNullStorage');
	
	}, 'cache-storage/Storage/FileAsyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/FileAsyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/FileAsyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/FileAsyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/FileAsyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Async/FileStorage');
	
	}, 'cache-storage/Storage/FileStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/FileStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/FileStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/FileStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/FileStorage.js'], env: {}};
	
		/** code **/
		console.log('FileStorage is deprecated, please use FileSyncStorage instead.');
		
		module.exports = require('../lib/Storage/Sync/FileStorage');
	
	}, 'cache-storage/Storage/FileSyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/FileSyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/FileSyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/FileSyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/FileSyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Sync/FileStorage');
	
	}, 'cache-storage/Storage/MemoryAsyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/MemoryAsyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/MemoryAsyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/MemoryAsyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/MemoryAsyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Async/MemoryStorage');
	
	}, 'cache-storage/Storage/MemoryStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/MemoryStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/MemoryStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/MemoryStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/MemoryStorage.js'], env: {}};
	
		/** code **/
		console.log('MemoryStorage is deprecated, please use MemorySyncStorage instead.');
		
		module.exports = require('../lib/Storage/Sync/MemoryStorage');
	
	}, 'cache-storage/Storage/MemorySyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/MemorySyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/MemorySyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/MemorySyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/MemorySyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Sync/MemoryStorage');
	
	}, 'cache-storage/Storage/RedisAsyncStorage.js': function(exports, module) {
	
		/** node globals **/
		var require = function(name) {return __r__c__.require(name, 'cache-storage/Storage/RedisAsyncStorage.js');};
		require.resolve = function(name, parent) {if (parent === null) {parent = 'cache-storage/Storage/RedisAsyncStorage.js';} return __r__c__.require.resolve(name, parent);};
		require.define = function(bundle) {__r__c__.require.define(bundle);};
		require.cache = __r__c__.require.cache;
		var __filename = 'cache-storage/Storage/RedisAsyncStorage.js';
		var __dirname = 'cache-storage/Storage';
		var process = {cwd: function() {return '/';}, argv: ['node', 'cache-storage/Storage/RedisAsyncStorage.js'], env: {}};
	
		/** code **/
		module.exports = require('../lib/Storage/Async/RedisStorage');
	
	}, 'cache-storage': function(exports, module) { module.exports = __r__c__.require('cache-storage/lib/Cache.js'); }
	, 'normalize-arguments': function(exports, module) { module.exports = __r__c__.require('normalize-arguments/lib/Args.js'); }
	, 'callsite': function(exports, module) { module.exports = __r__c__.require('callsite/index.js'); }
	, 'fs-finder': function(exports, module) { module.exports = __r__c__.require('fs-finder/lib/Finder.js'); }
	, 'escape-regexp': function(exports, module) { module.exports = __r__c__.require('escape-regexp/index.js'); }
	, 'q': function(exports, module) { module.exports = __r__c__.require('q/q.js'); }
	, 'async': function(exports, module) { module.exports = __r__c__.require('async/lib/async.js'); }
	, 'moment': function(exports, module) { module.exports = __r__c__.require('moment/moment.js'); }
	, 'operator-compare': function(exports, module) { module.exports = __r__c__.require('operator-compare/lib/Compare.js'); }
	, 'redis': function(exports, module) { module.exports = __r__c__.require('redis/index.js'); }
	
	});
	__r__c__.require.version = '5.6.3';
	
	window.require = __r__c__.require;
	
	/** run section **/
	
	/** /test/browser/tests/Translator **/
	__r__c__.require('/test/browser/tests/Translator');
}).call({});