<commit_before>module.exports = {
    places: {
        meta: '',
        items: [{
            id: 4017,
            station_id: 34523,
            slug: 'sao-paulo-tiete-sp',
            locale: 'pt-BR',
            name: '',
            is_primary: 'true',
            created_at: '2014-09-05 13:04:27',
            updated_at: '2014-09-05 13:04:59',
            place: {
                id: 34523,
                place_id: 4017,
                locale: 'pt-BR',
                name: 'Sao Paulo, SP - Tiete',
                created_at: '2014-09-05 13:04:27',
                updated_at: '2014-09-05 13:04:59',
                latitude: '-9.0237964',
                longitude: '-70.8119953',
                state: {
                    code: '',
                    name: 'Sao Paulo, SP - Tiete'
                }
            }
        },
        {
            id: 9209,
            station_id: 7648,
            slug: 'santos-sp',
            locale: 'pt-BR',
            name: 'Santos, SP',
            is_primary: 'true',
            created_at: '2014-05-26 16:19:36',
            updated_at: '2014-05-26 16:38:32',
            place: {
                id: 7648,
                place_id: 7648,
                locale: 'pt-BR',
                name: 'Santos, SP',
                created_at: '2014-05-26 16:19:36',
                updated_at: '2014-05-26 16:38:32',
                latitude: '',
                longitude: '',
                state: {
                    code: '',
                    name: 'Santos, SP'
                }
            }
        }]
    },
    trips: {
        meta: '',
        items: [{
            from: 'Sao Paulo, SP - Tiete',
            to: 'Santos, SP',
            parts: [{
                trip_id: '2949',
                departure: {
                    price: '2191',
                    waypoint: {
                        id: '4016',
                        prices: [{
                            waypoint: '3935',
                            price: '2191'
                        }],
                        schedule: {
                            id:
    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                            date: '2015-02-11',
                            time: '01:00',
                            timezone: 'America/Sao_Paulo'
                        },
                        context: 'departure',
                        place: {
                            country: 'BRA',
                            state: '',
                            city: 'Sao Paulo, SP - Tiete',
                            station: {
                                current: {
                                    id: '4016',
                                    name: 'Sao Paulo, SP - Tiete',
                                    locale: 'en_US'
                                },
                                default: {
                                    id: '',
                                    name: '',
                                    locale: ''
                                }
                            },
                            locale: 'pt_BR',
                            id: '4016'
                        },
                        isDeparture: 'true',
                        position: '0'
                    }
                },
                arrival: {
                    price: '2191',
                    waypoint: {
                        id: '3935',
                        prices: [{
                            waypoint: '',
                            price: ''
                        }],
                        schedule: {
                            id:
    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                            date: '2015-02-11',
                            time: '02:10',
                            timezone: 'America/Sao_Paulo'
                        },
                        context: 'arrival',
                        place: {
                            country: 'BRA',
                            state: '',
                            city: 'Santos, SP',
                            station: {
                                current: {
                                    id: '111',
                                    name: 'Santos, SP',
                                    locale: 'pt_BR'
                                },
                                default: {
                                    id: '',
                                    name: '',
                                    locale: ''
                                }
                            },
                            locale: 'pt_BR',
                            id: '3935'
                        },
                        isDeparture: 'false',
                        position: '0'
                    }
                },
                busCompany: {
                    name: 'Cometa',
                    id: '7',
                    logo: 'https://api-evaluation.clickbus.com.br/bundles/frontend/img/logos/buslines/small/bl-demon-s.png'
                },
                bus: {
                    serviceClass: 'Convencional',
                    name: 'Convencional',
                    id: '1'
                },
                waypoints: [{
                    id: '4016',
                    prices: [{
                        waypoint: '3935',
                        price: '2191'
                    }],
                    schedule: {
                        id:
    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                        date: '2015-02-11',
                        time: '01:00',
                        timezone: 'America/Sao_Paulo'
                    },
                    context: 'departure',
                    place: {
                        country: 'BRA',
                        state: 'SÃ£o Paulo',
                        city: 'SÃ£o Paulo',
                        station: {
                            current: {
                                id: '4016',
                                name: 'Sao Paulo, SP - Tiete',
                                locale: 'pt_BR'
                            },
                            default: {
                                id: '',
                                name: '',
                                locale: ''
                            }
                        },
                        locale: 'pt_BR',
                        id: '123'
                    },
                    isDeparture: 'true',
                    position: '0'
                },
                {
                    id: '3935',
                    prices: [{
                        waypoint: '',
                        price: '2191'
                    }],
                    schedule: {
                        id:
    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                        date: '2015-02-11',
                        time: '01:00',
                        timezone: 'America/Sao_Paulo'
                    },
                    context: 'arrival',
                    place: {
                        country: 'BRA',
                        state: '',
                        city: 'Santos, SP',
                        station: {
                            current: {
                                id: '3935',
                                name: 'Santos, SP',
                                locale: 'pt_BR'
                            },
                            default: {
                                id: '',
                                name: '',
                                locale: ''
                            }
                        },
                        locale: 'pt_BR',
                        id: ''
                    },
                    isDeparture: false,
                    position: 0
                }],
                seatTypes: [],
                products: [],
                availableSeats: '44'
            }]
        }]
    },
    tripsJ1: {
        error: [{
            code: 'J1',
            type: 'Invalid Parameters',
            message: 'Please provide the `from` parameter'
        }]
    },
    tripsJ9: {
        error: [{
            code: 'J9',
            type: 'Invalid Parameters',
            message: 'The `departure` date cannot occur in a day before today.'
        }]
    }
};
<commit_msg>minor<commit_after>module.exports = {
    places: {
        meta: '',
        items: [{
            id: 4017,
            station_id: 34523,
            slug: 'sao-paulo-tiete-sp',
            locale: 'pt-BR',
            name: '',
            is_primary: 'true',
            created_at: '2014-09-05 13:04:27',
            updated_at: '2014-09-05 13:04:59',
            place: {
                id: 34523,
                place_id: 4017,
                locale: 'pt-BR',
                name: 'Sao Paulo, SP - Tiete',
                created_at: '2014-09-05 13:04:27',
                updated_at: '2014-09-05 13:04:59',
                latitude: '-9.0237964',
                longitude: '-70.8119953',
                state: {
                    code: '',
                    name: 'Sao Paulo, SP - Tiete'
                }
            }
        },
        {
            id: 9209,
            station_id: 7648,
            slug: 'santos-sp',
            locale: 'pt-BR',
            name: 'Santos, SP',
            is_primary: 'true',
            created_at: '2014-05-26 16:19:36',
            updated_at: '2014-05-26 16:38:32',
            place: {
                id: 7648,
                place_id: 7648,
                locale: 'pt-BR',
                name: 'Santos, SP',
                created_at: '2014-05-26 16:19:36',
                updated_at: '2014-05-26 16:38:32',
                latitude: '',
                longitude: '',
                state: {
                    code: '',
                    name: 'Santos, SP'
                }
            }
        }]
    },
    trips: {
        meta: '',
        items: [{
            from: 'Sao Paulo, SP - Tiete',
            to: 'Santos, SP',
            parts: [{
                trip_id: '2949',
                departure: {
                    price: '2191',
                    waypoint: {
                        id: '4016',
                        prices: [{
                            waypoint: '3935',
                            price: '2191'
                        }],
                        schedule: {
                            id:
                        'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                            date: '2015-02-11',
                            time: '01:00',
                            timezone: 'America/Sao_Paulo'
                        },
                        context: 'departure',
                        place: {
                            country: 'BRA',
                            state: '',
                            city: 'Sao Paulo, SP - Tiete',
                            station: {
                                current: {
                                    id: '4016',
                                    name: 'Sao Paulo, SP - Tiete',
                                    locale: 'en_US'
                                },
                                default: {
                                    id: '',
                                    name: '',
                                    locale: ''
                                }
                            },
                            locale: 'pt_BR',
                            id: '4016'
                        },
                        isDeparture: 'true',
                        position: '0'
                    }
                },
                arrival: {
                    price: '2191',
                    waypoint: {
                        id: '3935',
                        prices: [{
                            waypoint: '',
                            price: ''
                        }],
                        schedule: {
                            id:
                        'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                            date: '2015-02-11',
                            time: '02:10',
                            timezone: 'America/Sao_Paulo'
                        },
                        context: 'arrival',
                        place: {
                            country: 'BRA',
                            state: '',
                            city: 'Santos, SP',
                            station: {
                                current: {
                                    id: '111',
                                    name: 'Santos, SP',
                                    locale: 'pt_BR'
                                },
                                default: {
                                    id: '',
                                    name: '',
                                    locale: ''
                                }
                            },
                            locale: 'pt_BR',
                            id: '3935'
                        },
                        isDeparture: 'false',
                        position: '0'
                    }
                },
                busCompany: {
                    name: 'Cometa',
                    id: '7',
                    logo: 'https://api-evaluation.clickbus.com.br/bundles/frontend/img/logos/buslines/small/bl-demon-s.png'
                },
                bus: {
                    serviceClass: 'Convencional',
                    name: 'Convencional',
                    id: '1'
                },
                waypoints: [{
                    id: '4016',
                    prices: [{
                        waypoint: '3935',
                        price: '2191'
                    }],
                    schedule: {
                        id:
                    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                        date: '2015-02-11',
                        time: '01:00',
                        timezone: 'America/Sao_Paulo'
                    },
                    context: 'departure',
                    place: {
                        country: 'BRA',
                        state: 'SÃ£o Paulo',
                        city: 'SÃ£o Paulo',
                        station: {
                            current: {
                                id: '4016',
                                name: 'Sao Paulo, SP - Tiete',
                                locale: 'pt_BR'
                            },
                            default: {
                                id: '',
                                name: '',
                                locale: ''
                            }
                        },
                        locale: 'pt_BR',
                        id: '123'
                    },
                    isDeparture: 'true',
                    position: '0'
                },
                {
                    id: '3935',
                    prices: [{
                        waypoint: '',
                        price: '2191'
                    }],
                    schedule: {
                        id:
                    'NDAxNi0tMzkzNS0tMjAxNS0wMi0xMSAwMTowMC0tNy0tMjk0OS0tMS0tMS0tMS0tQ09OVg==',
                        date: '2015-02-11',
                        time: '01:00',
                        timezone: 'America/Sao_Paulo'
                    },
                    context: 'arrival',
                    place: {
                        country: 'BRA',
                        state: '',
                        city: 'Santos, SP',
                        station: {
                            current: {
                                id: '3935',
                                name: 'Santos, SP',
                                locale: 'pt_BR'
                            },
                            default: {
                                id: '',
                                name: '',
                                locale: ''
                            }
                        },
                        locale: 'pt_BR',
                        id: ''
                    },
                    isDeparture: false,
                    position: 0
                }],
                seatTypes: [],
                products: [],
                availableSeats: '44'
            }]
        }]
    },
    tripsJ1: {
        error: [{
            code: 'J1',
            type: 'Invalid Parameters',
            message: 'Please provide the `from` parameter'
        }]
    },
    tripsJ9: {
        error: [{
            code: 'J9',
            type: 'Invalid Parameters',
            message: 'The `departure` date cannot occur in a day before today.'
        }]
    }
};
<|endoftext|>


<commit_before>'use strict';

var chalk = require('chalk');
var spawn = require('hexo-util/lib/spawn');
var pathFn = require('path');

module.exports = function(args) {
  if (!args.host || !args.user || !args.root) {
    var help = '';

    help += 'You should configure deployment settings in _config.yml first!\n\n';
    help += 'Example:\n';
    help += '  deploy:\n';
    help += '    type: rsync\n';
    help += '    host: <host>\n';
    help += '    user: <user>\n';
    help += '    root: <root>\n';
    help += '    port: [port] # Default is 22\n';
    help += '    delete: [true|false] # Default is true\n';
    help += '    args: <rsync args>\n';
    help += '    verbose: [true|false] # Default is true\n';
    help += '    ignore_errors: [true|false] # Default is false\n\n';
    help += 'For more help, you can check the docs: ' + chalk.underline('http://hexo.io/docs/deployment.html');

    console.log(help);
    return;
  }

  if (!args.hasOwnProperty('delete')) args.delete = true;
  if (!args.hasOwnProperty('verbose')) args.verbose = true;
  if (!args.hasOwnProperty('ignore_errors')) args.ignore_errors = false;

  var params = [
    '-az',
    process.platform === 'win32' ? pathFn.basename(this.public_dir) + '/' : this.public_dir,
    args.user + '@' + args.host + ':' + args.root
  ];

  if (args.port && args.port > 0 && args.port < 65536){
     params.splice(params.length - 2, 0, '-e');
     params.splice(params.length - 2, 0, 'ssh -p ' + args.port);
  }
  if (args.verbose) params.unshift('-v');
  if (args.ignore_errors) params.unshift('--ignore-errors');
  if (args.delete) params.unshift('--delete');
  if (args.args) params.unshift(args.args);

  return spawn('rsync', params, {verbose: true});
};
<commit_msg>Add missing space<commit_after>'use strict';

var chalk = require('chalk');
var spawn = require('hexo-util/lib/spawn');
var pathFn = require('path');

module.exports = function(args) {
  if (!args.host || !args.user || !args.root) {
    var help = '';

    help += 'You should configure deployment settings in _config.yml first!\n\n';
    help += 'Example:\n';
    help += '  deploy:\n';
    help += '    type: rsync\n';
    help += '    host: <host>\n';
    help += '    user: <user>\n';
    help += '    root: <root>\n';
    help += '    port: [port] # Default is 22\n';
    help += '    delete: [true|false] # Default is true\n';
    help += '    args: <rsync args>\n';
    help += '    verbose: [true|false] # Default is true\n';
    help += '    ignore_errors: [true|false] # Default is false\n\n';
    help += 'For more help, you can check the docs: ' + chalk.underline('http://hexo.io/docs/deployment.html');

    console.log(help);
    return;
  }

  if (!args.hasOwnProperty('delete')) args.delete = true;
  if (!args.hasOwnProperty('verbose')) args.verbose = true;
  if (!args.hasOwnProperty('ignore_errors')) args.ignore_errors = false;

  var params = [
    '-az',
    process.platform === 'win32' ? pathFn.basename(this.public_dir) + '/' : this.public_dir,
    args.user + '@' + args.host + ':' + args.root
  ];

  if (args.port && args.port > 0 && args.port < 65536) {
     params.splice(params.length - 2, 0, '-e');
     params.splice(params.length - 2, 0, 'ssh -p ' + args.port);
  }
  if (args.verbose) params.unshift('-v');
  if (args.ignore_errors) params.unshift('--ignore-errors');
  if (args.delete) params.unshift('--delete');
  if (args.args) params.unshift(args.args);

  return spawn('rsync', params, {verbose: true});
};
<|endoftext|>


<commit_before>// module dependencies.
var path = require('path');
var fs = require('fs');
var util = require('util');
var _ = require('lodash');

// singleton instance reference.
var _instance;

/**
 * Builds the filename of the json config file based on
 * the configuration name.
 * @param configName - The configuration name.
 * @returns {string} - the file name of the config file.
 */
function getConfigFileName(configName) {
  return configName + '.json';
}

/**
 * Replaces your default delimiter with the nconf delimiter.
 * @param key - The key to replace your custom delimiter in.
 * @param delimiter - Your custom delimiter.
 * @returns {string} - The nconf formatted key.
 */
function cleanKey (key, delimiter) {
  // make sure the delimiter is present.
  if (_.contains(key, delimiter)) {
    return key.split(delimiter).join(':');
  }
  else {
    return key;
  }
}

/**
 * Constructor for the server config module.
 * @constructor
 * @param configJsonDirectory - The file path to the config json directory holding all the json config files.
 */
var ServerConfig = function (configJsonDirectory) {
  // set the config directory.
  this.configDirectory = configJsonDirectory;

  // set the default delimiter for nested keys.
  this.delimiter = ":";

  if (_.isUndefined(this.configDirectory) || _.isEmpty(this.configDirectory) || !fs.existsSync(this.configDirectory)) {
    // print a message.
    util.debug('Config directory is invalid.');

    // return null.
    return null;
  }

  // save reference to nconf module.
  this.nconf = require('nconf');

  // load the command line and environment variables first.
  this.nconf.argv().env();
};

/**
 * Gets the file path of the configuration file to use.
 * @param configName - The configuration name (local, dev, test, prod).
 * @return {String} - The file path of the configuration file or UNDEFINED if file path
 * was not created correctly.
 */
ServerConfig.prototype.getConfigFilePath = function(configName) {
  // set file path to undefined by default.
  var filePath = undefined;

  // build the file name
  var fileName = getConfigFileName(configName);

  // combine the file name and config directory into a path string.
  var tempPath = path.join(this.configDirectory, fileName);

  // check that the filePath is valid and return it if it is.
  // if not, return undefined.
  if (fs.existsSync(tempPath)) {
    filePath = tempPath;

    // debug print.
    util.debug('Loading config file: ' + fileName);
  }
  else {
    util.debug('Failed to load config file for configuration: ' + configName);
  }

  // return the file path.
  return filePath;
}

/**
 * Loads a config json file.
 * @param configName - The name of the configuration.
 */
ServerConfig.prototype.loadConfig = function(configName) {
  // get the file path of the json file which holds settings for the specified config name.
  var configFilePath = this.getConfigFilePath(configName);

  // load the config file settings into nconf.
  this.nconf.file('configName', configFilePath);
};

/**
 * Loads the environment specific config file.
 */
ServerConfig.prototype.loadEnvironmentConfig = function(defaultConfig) {
  // get config name if present
  var configName = null;

  // check if an environment was specified.
  if (process.env.NODE_ENV) {
    configName = process.env.NODE_ENV;
  }
  else { // check if the environment was specified as a regular command line parameter instead.
    // check for command line parameters.
    if (process.argv.length > 2) {
      // get the last item in the argv array.
      configName = (process.argv[process.argv.length -1]).toString();

      // print out which environment its using.
      util.debug('Running as: ' + configName);
    }
    else {
      // set the config name.
      configName = defaultConfig;

      // debug print to tell the user that the server is running on the default config.
      util.debug('Running as: ' + defaultConfig);
    }
  }

  // get the config file path.
  var configFilePath = this.getConfigFilePath(configName);

  // check if the config file path is undefined.
  // this happens when a config file path was not created correctly.
  if (!_.isUndefined(configFilePath)) {
    // load the config filePath.
    this.nconf.file('environmentConfig', configFilePath);
  }

  // add the config name to nconf.
  this.nconf.set('environmentName', configName);
};

/**
 * Setter for the delimiter for nested key values.
 * @param delimiter - The delimiter to use.
 */
ServerConfig.prototype.setDelimiter = function(delimiter) {
  if (_.isUndefined(delimiter) || _.isNull(delimiter) || _.isEmpty(delimiter) || !_.isString(delimiter)) {
    util.debug('Invalid delimiter specified.');
    return;
  }

  // set the new delimiter.
  this.delimiter = delimiter;
};

/**
 * Getter method that takes a variable number of parameters and traverses the main settings object for the value.
 * @param {*} - One or more key params in order of how to traverse the settings object.
 * @returns {*} - The value requested.
 */
ServerConfig.prototype.get = function() {
  // set the current value to null
  var currentValue = null;

  // check if there are arguments
  if (arguments.length > 0) {
    // set current value to the first argument.
    currentValue = this.nconf.get(cleanKey(arguments[0], this.delimiter));
  }

  // check if you need to traverse further.
  if (arguments.length > 1) {
    for (var i = 1; i < arguments.length; i++) {
      currentValue = currentValue[cleanKey(arguments[i], this.delimiter)];
    }
  }

  // return the value.
  return currentValue;
};

/**
 * Gets the environment name.
 * @return {String} - The environment name.
 */
ServerConfig.prototype.getEnvironmentName = function() {
  return this.nconf.get('environmentName');
};

/**
 * return the singleton instance of the server config module.
 * @param configJsonDirectory - The directory where the json config files live.
 * @returns {*} - The singleton instance.
 */
module.exports = function(configJsonDirectory) {
  // check if the current instance is undefined.
  // if so, create a new server config instance and save it.
  if (_.isUndefined(_instance)) {
    _instance = new ServerConfig(configJsonDirectory)
  }

  // return the instance.
  return _instance;
};<commit_msg>adding debug mode.<commit_after>// module dependencies.
var path = require('path');
var fs = require('fs');
var util = require('util');
var _ = require('lodash');

// singleton instance reference.
var _instance;

/**
 * Builds the filename of the json config file based on
 * the configuration name.
 * @param configName - The configuration name.
 * @returns {string} - the file name of the config file.
 */
function getConfigFileName(configName) {
  return configName + '.json';
}

/**
 * Replaces your default delimiter with the nconf delimiter.
 * @param key - The key to replace your custom delimiter in.
 * @param delimiter - Your custom delimiter.
 * @returns {string} - The nconf formatted key.
 */
function cleanKey (key, delimiter) {
  // make sure the delimiter is present.
  if (_.contains(key, delimiter)) {
    return key.split(delimiter).join(':');
  }
  else {
    return key;
  }
}

/**
 * Constructor for the server config module.
 * @constructor
 * @param configJsonDirectory - The file path to the config json directory holding all the json config files.
 */
var ServerConfig = function (configJsonDirectory) {
  // set the config directory.
  this.configDirectory = configJsonDirectory;

  // set the default delimiter for nested keys.
  this.delimiter = ":";

  if (_.isUndefined(this.configDirectory) || _.isEmpty(this.configDirectory) || !fs.existsSync(this.configDirectory)) {
    // print a message.
    util.error('Config directory is invalid.');

    // return null.
    return null;
  }

  // save reference to nconf module.
  this.nconf = require('nconf');

  // load the command line and environment variables first.
  this.nconf.argv().env();

  // create a debug flag and set it to false initially.
  this.debug = false;
};

/**
 * Setter method for the debug flag.
 * @param debugModeOn - If the module should be in debug mode or not.
 */
ServerCongif.prototype.setDebugMode(debugModeOn) {
  this.debug = debugModeOn;
};

/**
 * Gets the file path of the configuration file to use.
 * @param configName - The configuration name (local, dev, test, prod).
 * @return {String} - The file path of the configuration file or UNDEFINED if file path
 * was not created correctly.
 */
ServerConfig.prototype.getConfigFilePath = function(configName) {
  // set file path to undefined by default.
  var filePath = undefined;

  // build the file name
  var fileName = getConfigFileName(configName);

  // combine the file name and config directory into a path string.
  var tempPath = path.join(this.configDirectory, fileName);

  // check that the filePath is valid and return it if it is.
  // if not, return undefined.
  if (fs.existsSync(tempPath)) {
    filePath = tempPath;

    // debug print.
    if (this.debug) {
      util.log('Loading config file: ' + fileName);
    }
  }
  else {
    util.error('Failed to load config file for configuration: ' + configName);
  }

  // return the file path.
  return filePath;
}

/**
 * Loads a config json file.
 * @param configName - The name of the configuration.
 */
ServerConfig.prototype.loadConfig = function(configName) {
  // get the file path of the json file which holds settings for the specified config name.
  var configFilePath = this.getConfigFilePath(configName);

  // load the config file settings into nconf.
  this.nconf.file('configName', configFilePath);
};

/**
 * Loads the environment specific config file.
 */
ServerConfig.prototype.loadEnvironmentConfig = function(defaultConfig) {
  // get config name if present
  var configName = null;

  // check if an environment was specified.
  if (process.env.NODE_ENV) {
    configName = process.env.NODE_ENV;
  }
  else { // check if the environment was specified as a regular command line parameter instead.
    // check for command line parameters.
    if (process.argv.length > 2) {
      // get the last item in the argv array.
      configName = (process.argv[process.argv.length -1]).toString();

      // print out which environment its using.
      if (this.debug) {
        util.log('Running as: ' + configName);
      }
    }
    else {
      // set the config name.
      configName = defaultConfig;

      // debug print to tell the user that the server is running on the default config.
      if (this.debug) {
        util.log('Running as: ' + defaultConfig);
      }
    }
  }

  // get the config file path.
  var configFilePath = this.getConfigFilePath(configName);

  // check if the config file path is undefined.
  // this happens when a config file path was not created correctly.
  if (!_.isUndefined(configFilePath)) {
    // load the config filePath.
    this.nconf.file('environmentConfig', configFilePath);
  }

  // add the config name to nconf.
  this.nconf.set('environmentName', configName);
};

/**
 * Setter for the delimiter for nested key values.
 * @param delimiter - The delimiter to use.
 */
ServerConfig.prototype.setDelimiter = function(delimiter) {
  if (_.isUndefined(delimiter) || _.isNull(delimiter) || _.isEmpty(delimiter) || !_.isString(delimiter)) {
    util.error('Invalid delimiter specified.');
    return;
  }

  // set the new delimiter.
  this.delimiter = delimiter;
};

/**
 * Getter method that takes a variable number of parameters and traverses the main settings object for the value.
 * @param {*} - One or more key params in order of how to traverse the settings object.
 * @returns {*} - The value requested.
 */
ServerConfig.prototype.get = function() {
  // set the current value to null
  var currentValue = null;

  // check if there are arguments
  if (arguments.length > 0) {
    // set current value to the first argument.
    currentValue = this.nconf.get(cleanKey(arguments[0], this.delimiter));
  }

  // check if you need to traverse further.
  if (arguments.length > 1) {
    for (var i = 1; i < arguments.length; i++) {
      currentValue = currentValue[cleanKey(arguments[i], this.delimiter)];
    }
  }

  // return the value.
  return currentValue;
};

/**
 * Gets the environment name.
 * @return {String} - The environment name.
 */
ServerConfig.prototype.getEnvironmentName = function() {
  return this.nconf.get('environmentName');
};

/**
 * return the singleton instance of the server config module.
 * @param configJsonDirectory - The directory where the json config files live.
 * @returns {*} - The singleton instance.
 */
module.exports = function(configJsonDirectory) {
  // check if the current instance is undefined.
  // if so, create a new server config instance and save it.
  if (_.isUndefined(_instance)) {
    _instance = new ServerConfig(configJsonDirectory)
  }

  // return the instance.
  return _instance;
};<|endoftext|>


<commit_before>var reCache = {}
,match = function (str, handlers, res, fn) {
  if (typeof res === 'function') {
    fn = res;
    res = reCache;
  }
  for (var i in handlers) {
    if (!res[i]) res[i] = new RegExp(i);
    var m = res[i].exec(str);
    if (m) {
      fn(handlers[i], m.splice(1));
    }
  }
};
exports.match = match;

var route = function (key, handlers, fn) {
  if (key in handlers) {
    handlers[key]();
  } else {
    fn();
  }
};
exports.route = route;

var Dispatch = function (handlers) {
  this.handlers = handlers;
  this.res = {};
}
Dispatch.prototype = {
  match: function (str, fn) {
    match(str, this.handlers, this.res, fn);
  }
  ,route: function (key, fn) {
    route(key, this.handlers, fn);
  }
};
exports.Dispatch = Dispatch;

<commit_msg>Removed Dispatch class.<commit_after>var reCache = {}
,match =
exports.match = function (str, handlers, res, fn) {
  if (typeof res === 'function') {
    fn = res;
    res = reCache;
  }
  for (var i in handlers) {
    if (!res[i]) res[i] = new RegExp(i);
    var m = res[i].exec(str);
    if (m) {
      fn(handlers[i], m.splice(1));
    }
  }
}
,route =
exports.route = function (key, handlers, fn, otherwise) {
  if (key in handlers) {
    fn(handlers[key]);
  } else if (otherwise) {
    otherwise();
  }
};
<|endoftext|>


<commit_before>var exec = require('child_process').exec;
var colors = require('colors/safe');

var io = function(error, stdout, stderr) {
  console.log(colors.green(stdout));
  console.log(colors.red(stderr));
};

var ADB = function(data) {
  if (!(this instanceof ADB)) {
    return new ADB(data);
  }
  exec("adb devices", io);
};

ADB.prototype.sms = function(recipient, message) {
  exec("adb shell am start -a android.intent.action.SENDTO -d sms:" + recipient +  " --es sms_body '" + message + "' --ez exit_on_sent true", io);
  exec("adb shell input keyevent 22", io);
  exec("adb shell input keyevent 66", io);
  exec("adb shell input keyevent 82 && adb shell am start -n com.nolanlawson.android.simpletalker/.MainActivity -e text 'Omerxi a dit : SMS envoyé'", io);
};

module.exports = {
  getInstance: function(data) {
    return new ADB(data);
  }
};
<commit_msg>fixed keyevent calls<commit_after>var exec = require('child_process').exec;
var colors = require('colors/safe');

var io = function(error, stdout, stderr) {
  console.log(colors.green(stdout));
  console.log(colors.red(stderr));
};

var ADB = function(data) {
  if (!(this instanceof ADB)) {
    return new ADB(data);
  }
  exec("adb devices", io);
};

ADB.prototype.sms = function(recipient, message) {
  exec("adb shell input keyevent 82", io);
  exec("adb shell input keyevent 3", io);
  exec("adb shell am start -a android.intent.action.SENDTO -d sms:" + recipient + " --es sms_body '" + message + "' --ez exit_on_sent true && adb shell input keyevent 22 && adb shell input keyevent 66", io);
  //exec("adb shell input keyevent 22", io);
  //exec("adb shell input keyevent 66", io);
  //exec("adb shell input keyevent 82 && adb shell am start -n com.nolanlawson.android.simpletalker/.MainActivity -e text 'Omerxi a dit : SMS envoyé'", io);
};

module.exports = {
  getInstance: function(data) {
    return new ADB(data);
  }
};
<|endoftext|>


<commit_before>
// Based on Resig's pretty date
function prettyDate(time) {
  var diff = (Date.now() - time) / 1000;
  var day_diff = Math.floor(diff / 86400);

  if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
    return '';

  return day_diff == 0 && (
          diff < 60 && 'just now' ||
          diff < 120 && '1 minute ago' ||
          diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' ||
          diff < 7200 && '1 hour ago' ||
          diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago') ||
          day_diff == 1 && 'Yesterday' ||
          day_diff < 7 && day_diff + ' days ago' ||
          day_diff < 31 && Math.ceil( day_diff / 7 ) + ' weeks ago';
};

var MessageManager = {
  getMessages: function mm_getMessages(callback, filter, invert) {
    var request = navigator.mozSms.getMessages(filter, !invert);

    var messages = [];
    request.onsuccess = function() {
      var result = request.result;
      if (!result) {
        callback(messages);
        return;
      }

      var message = result.message;
      messages.push(message);
      result.next();
    };

    request.onerror = function() {
      alert('Something wrong has happened while reading the database. Error code: ' + request.errorCode);
    }
  },

  send: function mm_send(number, text, callback) {
    var result = navigator.mozSms.send(number, text);
    result.onsuccess = callback;
    result.onerror = callback;
  },

  delete: function mm_delete(id) {
    navigator.mozSms.delete(id);
  }
};

if (!('mozSms' in navigator)) {
  MessageManager.messages = [];

  MessageManager.getMessages = function mm_getMessages(callback, filter, invert) {
    function applyFilter(msgs) {
      if (!filter)
        return msgs;

      if (filter.number) {
        msgs = msgs.filter(function(element, index, array) {
            return (filter.number && (filter.number == element.sender ||
                    filter.number == element.receiver));
        });
      }

      return msgs;
    }

    if (this.messages.length) {
      var msg = this.messages.slice();
      if (invert)
        msg.reverse();
      callback(applyFilter(msg));
      return;
    }

    var messages = [
      {
        sender: null,
        receiver: '+33601010101',
        body: 'Nothing :)',
        timestamp: Date.now() - 44000000,
      },
      {
        sender: '+33601010101',
        body: 'Hey! What\s up?',
        timestamp: Date.now() - 50000000,
      }
    ];

    for (var i = 0; i < 40; i++)
      messages.push({
        sender: '+33602020202',
        body: 'Hello world!',
        timestamp: Date.now() - 60000000,
      });

    this.messages = messages;

    var msg = this.messages.slice();
    if (invert)
      msg.reverse();
    callback(applyFilter(msg));
  }

  MessageManager.send = function mm_send(number, text, callback) {
    var message = {
      sender: null,
      receiver: number,
      body: text,
      timestamp: Date.now()
    }
    var event = document.createEvent('CustomEvent');
    event.initCustomEvent('smssent', true, false, message);
    var windows = window.top.document.getElementById('windows');
    parentWindow = windows.lastChild.previousSibling.contentWindow;
    setTimeout(function(evt) {
      parentWindow.dispatchEvent(event);
      window.dispatchEvent(event);
      callback();
    }, 1000);
  }

  MessageManager.handleEvent = function handleEvent(evt) {
    this.messages.unshift(evt.detail);
  }

  window.addEventListener('smssent', MessageManager, true);
  window.addEventListener('smsreceived', MessageManager, true);
};

var MessageView = {
  init: function init() {
    window.addEventListener('smsreceived', this, true);
    window.addEventListener('smssent', this, true);

    this.showConversations();
  },

  get conversationView() {
    delete this.conversationView;
    return this.conversationView = document.getElementById('conversation');
  },

  openConversationView: function openConversationView(num) {
    if (!num)
      return;

    var url = 'sms/sms_conversation.html';
    if (num && num != '*')
      url += '?' + num;
    window.top.openApplication(url);
  },

  get view() {
    delete this.view;
    return this.view = document.getElementById('messages');
  },

  showConversations: function showConversations() {
    var self = this;
    MessageManager.getMessages(function(messages) {
      var conversations = {};
      for (var i = 0; i < messages.length; i++) {
        var message = messages[i];
        var sender = message.sender || message.receiver;
        if (conversations[sender]) {
          conversations[sender].count++;
          continue;
        }

        conversations[sender] = {
          sender: message.sender,
          receiver: message.receiver,
          body: message.body,
          timestamp: prettyDate(message.timestamp),
          count: 1
        }
      }

      var fragment = '
' +
                     '
New Message
' +
                     '
Write a message
' +
                     '
';
      for (var conversation in conversations) {
        var msg = self.createNewMessage(conversations[conversation]);
        fragment += msg;
      }
      self.view.innerHTML = fragment;
    }, null);
  },

  createNewMessage: function createNewMessage(msg) {
    var className = 'class="message ' +
                    (msg.sender ? 'sender' : 'receiver') + '"';

    var num = (msg.sender || msg.receiver);
    var dataNum = 'data-num="' + num + '"';

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.tel == num)
        num = contact.name;
    });
    var title = num + ' (' + msg.count + ')';

    return '
' +
           '
' +
           '
' + title + '
' +
           '
' +
           '      ' + msg.body + '' +
           '      ' + msg.timestamp + '' +
           '
' +
           '
' +
           '
';
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'smssent':
      case 'smsreceived':
        // TODO Remove the delay once the native SMS application is disabled
        setTimeout(function(self) {
          self.showConversations();
        }, 800, this);
        break;
    }
  }
};

var ConversationView = {
  get view() {
    delete this.view;
    return this.view = document.getElementById('conversation');
  },

  get filter() {
    delete this.filter;
    return this.filter = document.location.toString().split('?')[1] || null;
  },

  init: function cv_init() {
    window.addEventListener('smssent', this, true);
    window.addEventListener('smsreceived', this, true);
    this.showConversation();
  },

  showConversation: function cv_showConversation() {
    if (!this.filter)
      return;

    var view = this.view;
    var filter = ('SmsFilter' in window) ? new SmsFilter() : {};
    filter.number = this.filter;

    MessageManager.getMessages(function (messages) {
      var fragment = '';
      for (var i = 0; i < messages.length; i++) {
        var msg = messages[i];
        var uuid = msg.hasOwnProperty('uuid') ? msg.uuid : '';
        var dataId = 'data-id="' + uuid +'"';

        var dataNum = 'data-num="' + (msg.sender || msg.receiver) + '"';

        var className = 'class="message ' +
                        (msg.sender ? 'sender' : 'receiver') + '"';

        var time = prettyDate(msg.timestamp);
        fragment += '
' +
                    '

' +
                    '
' +
                    '    ' + msg.body + '' +
                    '    ' + time + '' +
                    '
' +
                    '
';
      }

      view.innerHTML = fragment;
      setTimeout(function() {
        view.scrollTop = view.scrollHeight;
      }, 0);
    }, filter, true);
  },

  deleteMessage: function deleteMessage(evt) {
    var uuid = evt.target.getAttribute('data-id');
    if (!uuid)
      return;
    MessageManager.delete(uuid);
    this.showConversation();
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'smssent':
      case 'smsreceived':
        // TODO Remove the delay once the native SMS application is disabled
        setTimeout(function(self) {
          self.showConversation();
        }, 800, this);
        break;
    }
  }
};

<commit_msg>Replace the use of openApplication() in sms.js since the API has changed<commit_after>
// Based on Resig's pretty date
function prettyDate(time) {
  var diff = (Date.now() - time) / 1000;
  var day_diff = Math.floor(diff / 86400);

  if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
    return '';

  return day_diff == 0 && (
          diff < 60 && 'just now' ||
          diff < 120 && '1 minute ago' ||
          diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' ||
          diff < 7200 && '1 hour ago' ||
          diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago') ||
          day_diff == 1 && 'Yesterday' ||
          day_diff < 7 && day_diff + ' days ago' ||
          day_diff < 31 && Math.ceil( day_diff / 7 ) + ' weeks ago';
};

var MessageManager = {
  getMessages: function mm_getMessages(callback, filter, invert) {
    var request = navigator.mozSms.getMessages(filter, !invert);

    var messages = [];
    request.onsuccess = function() {
      var result = request.result;
      if (!result) {
        callback(messages);
        return;
      }

      var message = result.message;
      messages.push(message);
      result.next();
    };

    request.onerror = function() {
      alert('Something wrong has happened while reading the database. Error code: ' + request.errorCode);
    }
  },

  send: function mm_send(number, text, callback) {
    var result = navigator.mozSms.send(number, text);
    result.onsuccess = callback;
    result.onerror = callback;
  },

  delete: function mm_delete(id) {
    navigator.mozSms.delete(id);
  }
};

if (!('mozSms' in navigator)) {
  MessageManager.messages = [];

  MessageManager.getMessages = function mm_getMessages(callback, filter, invert) {
    function applyFilter(msgs) {
      if (!filter)
        return msgs;

      if (filter.number) {
        msgs = msgs.filter(function(element, index, array) {
            return (filter.number && (filter.number == element.sender ||
                    filter.number == element.receiver));
        });
      }

      return msgs;
    }

    if (this.messages.length) {
      var msg = this.messages.slice();
      if (invert)
        msg.reverse();
      callback(applyFilter(msg));
      return;
    }

    var messages = [
      {
        sender: null,
        receiver: '+33601010101',
        body: 'Nothing :)',
        timestamp: Date.now() - 44000000,
      },
      {
        sender: '+33601010101',
        body: 'Hey! What\s up?',
        timestamp: Date.now() - 50000000,
      }
    ];

    for (var i = 0; i < 40; i++)
      messages.push({
        sender: '+33602020202',
        body: 'Hello world!',
        timestamp: Date.now() - 60000000,
      });

    this.messages = messages;

    var msg = this.messages.slice();
    if (invert)
      msg.reverse();
    callback(applyFilter(msg));
  }

  MessageManager.send = function mm_send(number, text, callback) {
    var message = {
      sender: null,
      receiver: number,
      body: text,
      timestamp: Date.now()
    }
    var event = document.createEvent('CustomEvent');
    event.initCustomEvent('smssent', true, false, message);
    var windows = window.top.document.getElementById('windows');
    parentWindow = windows.lastChild.previousSibling.contentWindow;
    setTimeout(function(evt) {
      parentWindow.dispatchEvent(event);
      window.dispatchEvent(event);
      callback();
    }, 1000);
  }

  MessageManager.handleEvent = function handleEvent(evt) {
    this.messages.unshift(evt.detail);
  }

  window.addEventListener('smssent', MessageManager, true);
  window.addEventListener('smsreceived', MessageManager, true);
};

var MessageView = {
  init: function init() {
    window.addEventListener('smsreceived', this, true);
    window.addEventListener('smssent', this, true);

    this.showConversations();
  },

  get conversationView() {
    delete this.conversationView;
    return this.conversationView = document.getElementById('conversation');
  },

  openConversationView: function openConversationView(num) {
    if (!num)
      return;

    var url = 'sms/sms_conversation.html';
    if (num && num != '*')
      url += '?' + num;
    window.parent.WindowManager.open(url);
  },

  get view() {
    delete this.view;
    return this.view = document.getElementById('messages');
  },

  showConversations: function showConversations() {
    var self = this;
    MessageManager.getMessages(function(messages) {
      var conversations = {};
      for (var i = 0; i < messages.length; i++) {
        var message = messages[i];
        var sender = message.sender || message.receiver;
        if (conversations[sender]) {
          conversations[sender].count++;
          continue;
        }

        conversations[sender] = {
          sender: message.sender,
          receiver: message.receiver,
          body: message.body,
          timestamp: prettyDate(message.timestamp),
          count: 1
        }
      }

      var fragment = '
' +
                     '
New Message
' +
                     '
Write a message
' +
                     '
';
      for (var conversation in conversations) {
        var msg = self.createNewMessage(conversations[conversation]);
        fragment += msg;
      }
      self.view.innerHTML = fragment;
    }, null);
  },

  createNewMessage: function createNewMessage(msg) {
    var className = 'class="message ' +
                    (msg.sender ? 'sender' : 'receiver') + '"';

    var num = (msg.sender || msg.receiver);
    var dataNum = 'data-num="' + num + '"';

    var contacts = window.navigator.mozContacts.contacts;
    contacts.forEach(function(contact) {
      if (contact.tel == num)
        num = contact.name;
    });
    var title = num + ' (' + msg.count + ')';

    return '
' +
           '
' +
           '
' + title + '
' +
           '
' +
           '      ' + msg.body + '' +
           '      ' + msg.timestamp + '' +
           '
' +
           '
' +
           '
';
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'smssent':
      case 'smsreceived':
        // TODO Remove the delay once the native SMS application is disabled
        setTimeout(function(self) {
          self.showConversations();
        }, 800, this);
        break;
    }
  }
};

var ConversationView = {
  get view() {
    delete this.view;
    return this.view = document.getElementById('conversation');
  },

  get filter() {
    delete this.filter;
    return this.filter = document.location.toString().split('?')[1] || null;
  },

  init: function cv_init() {
    window.addEventListener('smssent', this, true);
    window.addEventListener('smsreceived', this, true);
    this.showConversation();
  },

  showConversation: function cv_showConversation() {
    if (!this.filter)
      return;

    var view = this.view;
    var filter = ('SmsFilter' in window) ? new SmsFilter() : {};
    filter.number = this.filter;

    MessageManager.getMessages(function (messages) {
      var fragment = '';
      for (var i = 0; i < messages.length; i++) {
        var msg = messages[i];
        var uuid = msg.hasOwnProperty('uuid') ? msg.uuid : '';
        var dataId = 'data-id="' + uuid +'"';

        var dataNum = 'data-num="' + (msg.sender || msg.receiver) + '"';

        var className = 'class="message ' +
                        (msg.sender ? 'sender' : 'receiver') + '"';

        var time = prettyDate(msg.timestamp);
        fragment += '
' +
                    '

' +
                    '
' +
                    '    ' + msg.body + '' +
                    '    ' + time + '' +
                    '
' +
                    '
';
      }

      view.innerHTML = fragment;
      setTimeout(function() {
        view.scrollTop = view.scrollHeight;
      }, 0);
    }, filter, true);
  },

  deleteMessage: function deleteMessage(evt) {
    var uuid = evt.target.getAttribute('data-id');
    if (!uuid)
      return;
    MessageManager.delete(uuid);
    this.showConversation();
  },

  handleEvent: function handleEvent(evt) {
    switch (evt.type) {
      case 'smssent':
      case 'smsreceived':
        // TODO Remove the delay once the native SMS application is disabled
        setTimeout(function(self) {
          self.showConversation();
        }, 800, this);
        break;
    }
  }
};

<|endoftext|>


<commit_before>var _          = require("underscore")
  , CollectionFactory = require("./collection")
  , inflection = require("./inflection")
  , Parser     = require("./parser")
  , util       = require("./util")

/**
 * A Factory that, given markup, can generate template constructors.  The
 * markup is parsed and the results of the parsed markup are given to the
 * generated Template function as it's prototype.
 **/
function TemplateFactory(markup, opts) {
  opts = opts || {}
  //wrap it in a div so that we always have a root element
  if(!opts.container) {
    opts.container = $("<div>")
  }
  this.container = opts.container
  this.markup = this.container.html(markup)
  this.templateProto = { models: {}, collectionFactories: {}, keys: {}, subTemplateFactories: {} }
  this.templateProto.structure = []

  //parse unless the user didn't EXPLICITLY tell the factory not to parse the markup
  if(opts.parse !== false)
    this.parse()
}

var viewRegistry = {}
CollectionFactory.setViewRegistry(viewRegistry)
TemplateFactory.registerView = function(name, View) {
  viewRegistry[name] = View
}

/**
 * Sets up a configuration of a replaceable element.  Will be used as the
 * prototype of the generated Template function.
 *
 * key - the name of the variable to replace, this will key className- or #{key}
 * in the template
 *
 * element - the element that has the key.
 *
 * name - attribute name to set, will be innerHTML if we want to set the
 * contents of an element.
 *
 * value - The entire value of the attribute, we use this to memoize the
 * initial value, and then replace the #{ part when we set something.
 *
 * @api private
 **/
TemplateFactory.prototype.mapElement = function(key, element, name, value) {
  var type = (name == "innerHTML") ? "innerHTML" : "attribute"
    , selector = util.getSelector(element, this.markup)

  var keyConfig = {
    selector: selector,
    type: type
  }

  if(type === "attribute") {
    var match = key.match(/([a-zA-Z ]+)(?:\?([a-zA-Z ]*)\s*)?(?:\:\s*([a-zA-Z ]*))?/)
      , valueIfTrue
    key = match[1].replace(/^\s+|\s+$/g, "")
    if(match[2]) {
      valueIfTrue = match[2].replace(/^\s+|\s+$/g, "")
      keyConfig.valueIfTrue = valueIfTrue
    }
    if(match[3]) {
      valueIfFalse = match[3].replace(/^\s+|\s+$/g, "")
      keyConfig.valueIfFalse = valueIfFalse
    }
    keyConfig.attributeName = name
    keyConfig.attributeValue = value
  }
  this.templateProto.structure.push({ key: key, selector: selector, type: "variable" })

  if(this.templateProto.keys[key]) {
    this.templateProto.keys[key].push(keyConfig)
  } else {
    this.templateProto.keys[key] = [keyConfig]
  }
}

/**
 * Maps the collection `name` at element.
 **/
TemplateFactory.prototype.mapCollection = function(name, element, polymorphicKey) {
  var selector = util.getSelector(element, this.markup)
  this.templateProto.structure.push({ key: name, selector: selector, type: "collection" })
  return this.templateProto.collectionFactories[name] = new CollectionFactory(inflection.singularize(name), selector, polymorphicKey)
}

TemplateFactory.prototype.mapView = function(key, element) {
  var selector = util.getSelector(element, this.markup)
  this.templateProto.structure.push({ key: key, selector: selector, type: "view" })
}

TemplateFactory.prototype.mapConditional = function(key, element) {
  var selector = util.getSelector(element, this.markup)
    , keyConfig = { selector: selector, type: "conditional" }
  this.templateProto.structure.push({ key: key, selector: selector, type: "conditional" })

  if(this.templateProto.keys[key]) {
    this.templateProto.keys[key].push(keyConfig)
  } else {
    this.templateProto.keys[key] = [keyConfig]
  }
}

/**
 * Maps a model (scope), at element
 **/
TemplateFactory.prototype.mapModel = function(name, el) {
  var selector = util.getSelector(el, this.markup)
  this.templateProto.structure.push({ key: name, selector: selector, type: "model" })
  return this.templateProto.subTemplateFactories[name] = new TemplateFactory(el.contents(), { parse: false, container: el })
}

/**
 * Listens to events on parser and maps the elements found.
 **/
TemplateFactory.prototype.parse = function() {
  var stack = [ this ]
    , collections = []

  this.parser = new Parser(this.markup)

  this.parser.on("collection", function(name, el, polymorphicKey) {
    collection = _(stack).last().mapCollection(name, el, polymorphicKey)
    stack.push(collection)
    collections.push(collection)
  })

  this.parser.on("model", function(name, el, polymorphicValue) {
    var templateFactory
      , parentScope = _(stack).last()
    // if this node's parent is a Collection, we use this model as that
    // collections item template.
    if(parentScope instanceof CollectionFactory) {
      if(polymorphicValue && !parentScope.polymorphicKey) {
        throw new Error("Setting a polymorphic value: " + polymorphicValue + " for a non polymorphic collection")
      } else if(polymorphicValue && !parentScope.polymorphicKey) {
        throw new Error("Polymorphic template with classes " + classes + " has no polymorphic value")
      } else if(!polymorphicValue) { //it's not a polymorphic collection, so we'll name it default
        polymorphicValue = "default" //TODO this should be decided by the collection
      }
      templateFactory = parentScope.setTemplateFactory(polymorphicValue, new TemplateFactory(el.remove(), { parse: false }))
    } else {
      templateFactory = parentScope.mapModel(name, el)
    }
    stack.push(templateFactory)
  })
  //call map element on the last item on the stack if it's a variable
  this.parser.on("variable", function(key, element, name, value) {
    _(stack).last().mapElement(key, element, name, value)
  })

  this.parser.on("conditional", function(key, element) {
    _(stack).last().mapConditional(key, element)
  })

  this.parser.on("view", function(key, element) {
    _(stack).last().mapView(key, element)
  })

  this.parser.on("close", function(name) {
    stack.pop()
  })
  this.parser.parse()
}

var TemplateMethods = {}

TemplateFactory.prototype.generate = function() {
  var that = this
  function Template(data, opts) {
    opts = opts || {}
    data = data || {}
    //only take the inner html to "unwrap" the containing div from above
    this.template = $(that.markup.html())
    this.container = opts.container

    this.collections = {}
    this.models = {}

    this.bind(data, opts.parentView || null)
  }

  Template.prototype = _.extend({}, this.templateProto, TemplateMethods)
  return Template
}

TemplateMethods.getFrom = function(name, object) {
  return (typeof object.get === "function") ? object.get(name) : object[name]
}

TemplateMethods.setFrom = function(name, object) {
  this.set(name, this.getFrom(name, object))
}

TemplateMethods.bindTo = function(name, model) {
  var that = this
  if(typeof model.on === "function") {
    model.on("change:" + name, function() {
      that.set(name, model.get(name))
    })
  }
}

TemplateMethods.bindFrom = function(element, name, model) {
  var that = this
  if(typeof model.set === "function") {
    element.on("change", function() {
      model.set(name, $(this).val())
    })
  }
}

function jqts(element) {
  return $("<div>").append(element.clone()).html()
}

TemplateMethods.bind = function(data, view) {
  var modelStack = [ data ]
    , viewStack = [ view || null ]

  this.view = view

  this.traverse(function(name, type, element) {
    if(type == "variable" || type == "conditional") {
      this.setFrom(name, _(modelStack).last())
      this.bindTo(name, _(modelStack).last())
      if(element.is(":input:not(button)")) {
        this.bindFrom(element, name, _(modelStack).last())
      }
    } else if(type == "collection") {
      var Factory = this.collectionFactories[name]
        , CollectionTemplate = Factory.generate(this.template)
        , collectionModel = this.getFrom(name, _(modelStack).last())

      this.collections[name] = new CollectionTemplate(collectionModel, { parentView : _(viewStack).last() || null })
      modelStack.push(collectionModel)
    } else if(type == "view") {
      var View = viewRegistry[inflection.capitalize(name)]
        , parent = _(viewStack).last() || null
        , model = _(modelStack).last()

      if(!View) {
        throw new Error("No such view class " + inflection.capitalize(name))
      }

      opts = { parent: parent, el: element, template: this, model: model }
      view = new View(opts)

      if(element.is(this.template)) {
        this.view = view
      }
      viewStack.push(view)
    } else if(type === "model") {
      var Factory = this.subTemplateFactories[name]
        , Template = Factory.generate()
        , templateModel = this.getFrom(name, _(modelStack).last() || {})
        , template = this.models[name] = new Template(templateModel, { parentView : _(viewStack).last() || null, container: element })
      element.html(template.template)
      modelStack.push(templateModel)
    }
  })
}

function findDescendantsAndSelf(element, selector) {
  var matches = element.find(selector)
  element.each(function(index, element) {
    if(element.nodeType == 1 && $(element).is(selector)) {
      matches = matches.add(element)
    }
  })
  return matches
}

/**
 * Sets any elements referenced by key in the current scope to value in the
 * template.
 **/
TemplateMethods.set = function(key, value) {
  var that = this
    , keyConfigs

  if(typeof key === "object") {
    //iterate attributes if backbone model
    if(key.attributes) {
      key = key.attributes
    }
    return _(key).each(function(v, k) {
      that.set(k, v)
    })
  }
  if(model = that.models[key]) {
    model.bind(value)
  }
  if(coll = that.collections[key]) {
    coll.push(value)
  }
  if(keyConfigs = that.keys[key]) {
    _(keyConfigs).each(function(keyConfig) {
      var element = findDescendantsAndSelf(that.template, keyConfig.selector)
      if(keyConfig.type === "innerHTML") {
        if(element.is(":input:not(button)")) {
          element.val(value)
        } else {
          element.html(value)
        }
      } else if(keyConfig.type === "conditional") {
        if(value === false)
          element.hide()
        else
          element.show()
      } else {
        that.setAttribute(element, keyConfig.attributeName, keyConfig.attributeValue, key, value, keyConfig.valueIfTrue, keyConfig.valueIfFalse)
      }
    })
  }
}
/* Given a name, return the collection or template
 * for the given name.
 *
 * Should it return views? idk, but I don't need it now.
 */
TemplateMethods.get = function(name) {
  if(this.collections[name]) {
    return this.collections[name]
  } else if(this.models[name]) {
    return this.models[name]
  } else {
    throw new Error("Could not find template: " + name)
  }
}

TemplateMethods.traverse = function(iterator) {
  _(this.structure).each(function(node) {
    if(node.selector == "") {
      element = this.container
    } else {
      var element = findDescendantsAndSelf(this.template, node.selector)
    }
    iterator.call(this, node.key, node.type, element)
  }, this)
}

TemplateMethods.setAttribute = function(element, attributeName, attributeValue, replaceKey, replaceValue, valueIfTrue, valueIfFalse) {
  valueIfFalse = valueIfFalse || ""
  if(valueIfTrue) {
    replaceValue = (replaceValue === false) ? valueIfFalse : valueIfTrue
  }

  var regex = "#{\\s*" + replaceKey + "\\s*"
  if(valueIfTrue) {
    regex += "\\?\\s*" + valueIfTrue + "\\s*"
  }
  if(valueIfFalse) {
    regex += "\\:\\s*" + valueIfFalse + "\\s*"
  }
  regex += "}"
  var newValue = attributeValue.replace(new RegExp(regex), replaceValue)
  element.attr(attributeName, newValue)
}

module.exports = TemplateFactory
<commit_msg>Revert "store the view"<commit_after>var _          = require("underscore")
  , CollectionFactory = require("./collection")
  , inflection = require("./inflection")
  , Parser     = require("./parser")
  , util       = require("./util")

/**
 * A Factory that, given markup, can generate template constructors.  The
 * markup is parsed and the results of the parsed markup are given to the
 * generated Template function as it's prototype.
 **/
function TemplateFactory(markup, opts) {
  opts = opts || {}
  //wrap it in a div so that we always have a root element
  if(!opts.container) {
    opts.container = $("<div>")
  }
  this.container = opts.container
  this.markup = this.container.html(markup)
  this.templateProto = { models: {}, collectionFactories: {}, keys: {}, subTemplateFactories: {} }
  this.templateProto.structure = []

  //parse unless the user didn't EXPLICITLY tell the factory not to parse the markup
  if(opts.parse !== false)
    this.parse()
}

var viewRegistry = {}
CollectionFactory.setViewRegistry(viewRegistry)
TemplateFactory.registerView = function(name, View) {
  viewRegistry[name] = View
}

/**
 * Sets up a configuration of a replaceable element.  Will be used as the
 * prototype of the generated Template function.
 *
 * key - the name of the variable to replace, this will key className- or #{key}
 * in the template
 *
 * element - the element that has the key.
 *
 * name - attribute name to set, will be innerHTML if we want to set the
 * contents of an element.
 *
 * value - The entire value of the attribute, we use this to memoize the
 * initial value, and then replace the #{ part when we set something.
 *
 * @api private
 **/
TemplateFactory.prototype.mapElement = function(key, element, name, value) {
  var type = (name == "innerHTML") ? "innerHTML" : "attribute"
    , selector = util.getSelector(element, this.markup)

  var keyConfig = {
    selector: selector,
    type: type
  }

  if(type === "attribute") {
    var match = key.match(/([a-zA-Z ]+)(?:\?([a-zA-Z ]*)\s*)?(?:\:\s*([a-zA-Z ]*))?/)
      , valueIfTrue
    key = match[1].replace(/^\s+|\s+$/g, "")
    if(match[2]) {
      valueIfTrue = match[2].replace(/^\s+|\s+$/g, "")
      keyConfig.valueIfTrue = valueIfTrue
    }
    if(match[3]) {
      valueIfFalse = match[3].replace(/^\s+|\s+$/g, "")
      keyConfig.valueIfFalse = valueIfFalse
    }
    keyConfig.attributeName = name
    keyConfig.attributeValue = value
  }
  this.templateProto.structure.push({ key: key, selector: selector, type: "variable" })

  if(this.templateProto.keys[key]) {
    this.templateProto.keys[key].push(keyConfig)
  } else {
    this.templateProto.keys[key] = [keyConfig]
  }
}

/**
 * Maps the collection `name` at element.
 **/
TemplateFactory.prototype.mapCollection = function(name, element, polymorphicKey) {
  var selector = util.getSelector(element, this.markup)
  this.templateProto.structure.push({ key: name, selector: selector, type: "collection" })
  return this.templateProto.collectionFactories[name] = new CollectionFactory(inflection.singularize(name), selector, polymorphicKey)
}

TemplateFactory.prototype.mapView = function(key, element) {
  var selector = util.getSelector(element, this.markup)
  this.templateProto.structure.push({ key: key, selector: selector, type: "view" })
}

TemplateFactory.prototype.mapConditional = function(key, element) {
  var selector = util.getSelector(element, this.markup)
    , keyConfig = { selector: selector, type: "conditional" }
  this.templateProto.structure.push({ key: key, selector: selector, type: "conditional" })

  if(this.templateProto.keys[key]) {
    this.templateProto.keys[key].push(keyConfig)
  } else {
    this.templateProto.keys[key] = [keyConfig]
  }
}

/**
 * Maps a model (scope), at element
 **/
TemplateFactory.prototype.mapModel = function(name, el) {
  var selector = util.getSelector(el, this.markup)
  this.templateProto.structure.push({ key: name, selector: selector, type: "model" })
  return this.templateProto.subTemplateFactories[name] = new TemplateFactory(el.contents(), { parse: false, container: el })
}

/**
 * Listens to events on parser and maps the elements found.
 **/
TemplateFactory.prototype.parse = function() {
  var stack = [ this ]
    , collections = []

  this.parser = new Parser(this.markup)

  this.parser.on("collection", function(name, el, polymorphicKey) {
    collection = _(stack).last().mapCollection(name, el, polymorphicKey)
    stack.push(collection)
    collections.push(collection)
  })

  this.parser.on("model", function(name, el, polymorphicValue) {
    var templateFactory
      , parentScope = _(stack).last()
    // if this node's parent is a Collection, we use this model as that
    // collections item template.
    if(parentScope instanceof CollectionFactory) {
      if(polymorphicValue && !parentScope.polymorphicKey) {
        throw new Error("Setting a polymorphic value: " + polymorphicValue + " for a non polymorphic collection")
      } else if(polymorphicValue && !parentScope.polymorphicKey) {
        throw new Error("Polymorphic template with classes " + classes + " has no polymorphic value")
      } else if(!polymorphicValue) { //it's not a polymorphic collection, so we'll name it default
        polymorphicValue = "default" //TODO this should be decided by the collection
      }
      templateFactory = parentScope.setTemplateFactory(polymorphicValue, new TemplateFactory(el.remove(), { parse: false }))
    } else {
      templateFactory = parentScope.mapModel(name, el)
    }
    stack.push(templateFactory)
  })
  //call map element on the last item on the stack if it's a variable
  this.parser.on("variable", function(key, element, name, value) {
    _(stack).last().mapElement(key, element, name, value)
  })

  this.parser.on("conditional", function(key, element) {
    _(stack).last().mapConditional(key, element)
  })

  this.parser.on("view", function(key, element) {
    _(stack).last().mapView(key, element)
  })

  this.parser.on("close", function(name) {
    stack.pop()
  })
  this.parser.parse()
}

var TemplateMethods = {}

TemplateFactory.prototype.generate = function() {
  var that = this
  function Template(data, opts) {
    opts = opts || {}
    data = data || {}
    //only take the inner html to "unwrap" the containing div from above
    this.template = $(that.markup.html())
    this.container = opts.container

    this.collections = {}
    this.models = {}

    this.bind(data, opts.parentView || null)
  }

  Template.prototype = _.extend({}, this.templateProto, TemplateMethods)
  return Template
}

TemplateMethods.getFrom = function(name, object) {
  return (typeof object.get === "function") ? object.get(name) : object[name]
}

TemplateMethods.setFrom = function(name, object) {
  this.set(name, this.getFrom(name, object))
}

TemplateMethods.bindTo = function(name, model) {
  var that = this
  if(typeof model.on === "function") {
    model.on("change:" + name, function() {
      that.set(name, model.get(name))
    })
  }
}

TemplateMethods.bindFrom = function(element, name, model) {
  var that = this
  if(typeof model.set === "function") {
    element.on("change", function() {
      model.set(name, $(this).val())
    })
  }
}

function jqts(element) {
  return $("<div>").append(element.clone()).html()
}

TemplateMethods.bind = function(data, view) {
  var modelStack = [ data ]
    , viewStack = [ view || null ]

  this.traverse(function(name, type, element) {
    if(type == "variable" || type == "conditional") {
      this.setFrom(name, _(modelStack).last())
      this.bindTo(name, _(modelStack).last())
      if(element.is(":input:not(button)")) {
        this.bindFrom(element, name, _(modelStack).last())
      }
    } else if(type == "collection") {
      var Factory = this.collectionFactories[name]
        , CollectionTemplate = Factory.generate(this.template)
        , collectionModel = this.getFrom(name, _(modelStack).last())

      this.collections[name] = new CollectionTemplate(collectionModel, { parentView : _(viewStack).last() || null })
      modelStack.push(collectionModel)
    } else if(type == "view") {
      var View = viewRegistry[inflection.capitalize(name)]
        , parent = _(viewStack).last() || null
        , model = _(modelStack).last()

      if(!View) {
        throw new Error("No such view class " + inflection.capitalize(name))
      }

      opts = { parent: parent, el: element, template: this, model: model }
      view = new View(opts)
      viewStack.push(view)
    } else if(type === "model") {
      var Factory = this.subTemplateFactories[name]
        , Template = Factory.generate()
        , templateModel = this.getFrom(name, _(modelStack).last() || {})
        , template = this.models[name] = new Template(templateModel, { parentView : _(viewStack).last() || null, container: element })
      element.html(template.template)
      modelStack.push(templateModel)
    }
  })
}

function findDescendantsAndSelf(element, selector) {
  var matches = element.find(selector)
  element.each(function(index, element) {
    if(element.nodeType == 1 && $(element).is(selector)) {
      matches = matches.add(element)
    }
  })
  return matches
}

/**
 * Sets any elements referenced by key in the current scope to value in the
 * template.
 **/
TemplateMethods.set = function(key, value) {
  var that = this
    , keyConfigs

  if(typeof key === "object") {
    //iterate attributes if backbone model
    if(key.attributes) {
      key = key.attributes
    }
    return _(key).each(function(v, k) {
      that.set(k, v)
    })
  }
  if(model = that.models[key]) {
    model.bind(value)
  }
  if(coll = that.collections[key]) {
    coll.push(value)
  }
  if(keyConfigs = that.keys[key]) {
    _(keyConfigs).each(function(keyConfig) {
      var element = findDescendantsAndSelf(that.template, keyConfig.selector)
      if(keyConfig.type === "innerHTML") {
        if(element.is(":input:not(button)")) {
          element.val(value)
        } else {
          element.html(value)
        }
      } else if(keyConfig.type === "conditional") {
        if(value === false)
          element.hide()
        else
          element.show()
      } else {
        that.setAttribute(element, keyConfig.attributeName, keyConfig.attributeValue, key, value, keyConfig.valueIfTrue, keyConfig.valueIfFalse)
      }
    })
  }
}
/* Given a name, return the collection or template
 * for the given name.
 *
 * Should it return views? idk, but I don't need it now.
 */
TemplateMethods.get = function(name) {
  if(this.collections[name]) {
    return this.collections[name]
  } else if(this.models[name]) {
    return this.models[name]
  } else {
    throw new Error("Could not find template: " + name)
  }
}

TemplateMethods.traverse = function(iterator) {
  _(this.structure).each(function(node) {
    if(node.selector == "") {
      element = this.container
    } else {
      var element = findDescendantsAndSelf(this.template, node.selector)
    }
    iterator.call(this, node.key, node.type, element)
  }, this)
}

TemplateMethods.setAttribute = function(element, attributeName, attributeValue, replaceKey, replaceValue, valueIfTrue, valueIfFalse) {
  valueIfFalse = valueIfFalse || ""
  if(valueIfTrue) {
    replaceValue = (replaceValue === false) ? valueIfFalse : valueIfTrue
  }

  var regex = "#{\\s*" + replaceKey + "\\s*"
  if(valueIfTrue) {
    regex += "\\?\\s*" + valueIfTrue + "\\s*"
  }
  if(valueIfFalse) {
    regex += "\\:\\s*" + valueIfFalse + "\\s*"
  }
  regex += "}"
  var newValue = attributeValue.replace(new RegExp(regex), replaceValue)
  element.attr(attributeName, newValue)
}

module.exports = TemplateFactory
<|endoftext|>


<commit_before>module.exports = function (inherits, EventEmitter) {
	var MAX_COUNT = Math.pow(2, 31) // largest smi value
	var clock = Date.now()
	setInterval(function () { clock = Date.now() }, 10)
	function noop() { return false }

	//
	// http: either require('http') or require('https')
	// ip: host ip
	// port: host port
	// options: {
	//   ping: ping path (no ping checks)
	//   pingTimeout: in ms (2000)
	//   maxPending: number of requests pending before returning an error (500)
	//   maxSockets: max concurrent open sockets (20)
	//   timeout: default request timeout in ms (60000)
	//   resolution: how often timeouts are checked in ms (1000)
	// }
	function Endpoint(http, ip, port, options) {
		options = options || {}

		this.http = http
		this.ip = ip
		this.port = port
		this.healthy = false
		this.name = this.ip + ':' + this.port
		this.address = this.ip
		this.pingPath = options.ping
		this.pingTimeout = options.pingTimeout || 2000

		this.agent = new http.Agent()
		this.agent.maxSockets = options.maxSockets || 20

		this.requests = {}
		this.requestCount = 0
		this.requestsLastCheck = 0
		this.requestRate = 0
		this.pending = 0
		this.successes = 0
		this.failures = 0

		this.maxPending = options.maxPending || 500
		this.timeout = options.timeout || (60 * 1000)
		this.resolution = options.resolution || 1000
		this.timeoutInterval = setInterval(this.checkTimeouts.bind(this), this.resolution)

		this.ping()
	}
	inherits(Endpoint, EventEmitter)

	Endpoint.prototype.checkTimeouts = function () {
		var keys = Object.keys(this.requests)
		for (var i = 0; i < keys.length; i++) {
			var r = this.requests[keys[i]]
			var expireTime = clock - r.options.timeout
			if (r.lastTouched <= expireTime) {
				this.emit("timeout", r)
				r.abort()
			}
			if (!this.healthy) {
				this.ping()
			}
		}
		this.requestRate = this.requestCount - this.requestsLastCheck
		this.requestsLastCheck = this.requestCount
	}

	Endpoint.prototype.resetCounters = function () {
		this.requestsLastCheck = this.requestRate - this.pending
		this.requestCount = this.pending
		this.successes = 0
		this.failures = 0
	}

	Endpoint.prototype.setPending = function () {
		this.pending = this.requestCount - (this.successes + this.failures)
		if (this.requestCount === MAX_COUNT) {
			this.resetCounters()
		}
	}

	Endpoint.prototype.complete = function (error, request, response, body) {
		this.deleteRequest(request.id)
		this.setPending()
		request.callback(error, response, body)
		request.callback = null
	}

	Endpoint.prototype.succeeded = function (request, response, body) {
		this.successes++
		this.complete(null, request, response, body)
	}

	Endpoint.prototype.failed = function (error, request) {
		this.failures++
		this.complete(error, request)
	}

	Endpoint.prototype.busyness = function () {
		return this.pending
	}

	// options: {
	//   agent:
	//   path:
	//   method:
	//   retryFilter:
	//   timeout: request timeout in ms (this.timeout)
	//   encoding: response body encoding (utf8)
	//   data: string or buffer
	// }
	// callback: function (error, response, body) {}
	Endpoint.prototype.request = function (options, callback) {
		if (this.pending >= this.maxPending && options.path !== this.pingPath) {
			return callback(
				{ reason: 'full'
				, message: 'too many pending requests ' + this.pending + '/' + this.maxPending
				})
		}
		options.host = this.ip
		options.port = this.port
		options.retryFilter = options.retryFilter || noop
		options.timeout = options.timeout || this.timeout
		if (options.agent !== false) {
			options.agent = this.agent
		}
		if (options.encoding !== null) {
			options.encoding = options.encoding || 'utf8'
		}

		var data = options.data
		if (data) {
			options.headers = options.headers || {}
			options.headers["Content-Length"] =
				Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)
		}
		var req = this.http.request(options)
		req.node = this
		req.options = options
		req.id = this.requestCount++
		req.lastTouched = clock
		req.callback = callback || noop
		req.on('response', gotResponse)
		req.on('error', gotError)
		req.end(data)

		this.setPending()
		this.requests[req.id] = req
	}

	Endpoint.prototype.setHealthy = function (newState) {
		if (this.healthy !== newState) {
			this.healthy = newState
			if (!this.healthy) {
				this.ping() // ping may set this back to healthy
				if (!this.healthy) {
					this.emit('health', this)
				}
			}
			else {
				this.emit('health', this)
			}
		}
	}

	Endpoint.prototype.deleteRequest = function (id) {
		delete this.requests[id]
	}

	function gotPingResponse(error, response, body) {
		this.node.setHealthy(!error && response.statusCode === 200)
	}

	Endpoint.prototype.ping = function () {
		if (this.pingPath) {
			this.request(
				{ path: this.pingPath
				, method: 'GET'
				, timeout: this.pingTimeout
				}
				, gotPingResponse)
		}
		else {
			this.setHealthy(true)
		}
	}

	// this = request
	function gotResponse(response) {
		response.bodyChunks = []
		response.bodyLength = 0
		response.request = this
		response.on('data', gotData)
		response.on('end', gotEnd)
		response.on('aborted', gotAborted)
	}

	// this = request
	function gotError(error) {
		this.node.failed(
			{ reason: error.message
			, attempt: this
			, message: this.node.ip + ':' + this.node.port + ' error: ' + error.message
			}
			, this)
		this.node.setHealthy(false)
	}

	// this = response
	function gotData(chunk) {
		this.request.lastTouched = clock
		this.bodyChunks.push(chunk)
		this.bodyLength += chunk.length
	}

	// this = response
	function gotEnd() {
		var req = this.request
		var opt = req.options
		var node = req.node

		if (req.callback === null) { return }
		node.setHealthy(true)

		var buffer = new Buffer(this.bodyLength)
		var offset = 0
		for (var i = 0; i < this.bodyChunks.length; i++) {
			var chunk = this.bodyChunks[i]
			chunk.copy(buffer, offset, 0, chunk.length)
			offset += chunk.length
		}

		var body = (opt.encoding !== null) ? buffer.toString(opt.encoding) : buffer

		var delay = opt.retryFilter(opt, this, body)
		if (delay !== false) { // delay may be 0
			return node.failed(
			{ delay: delay
			, reason: 'filter'
			, attempt: req
			, message: node.ip + ':' + node.port + ' error: rejected by filter'
			}
			, req)
		}
		node.succeeded(req, this, body)
	}

	// this = response
	function gotAborted() {
		this.request.node.failed(
			{ reason: 'aborted'
			, attempt: this.request
			, message: this.request.node.ip + ':' + this.request.node.port + ' error: connection aborted'
			}
			, this.request)
	}

	return Endpoint
}
<commit_msg>fixed runaway pings<commit_after>module.exports = function (inherits, EventEmitter) {
	var MAX_COUNT = Math.pow(2, 31) // largest smi value
	var clock = Date.now()
	setInterval(function () { clock = Date.now() }, 10)
	function noop() { return false }

	//
	// http: either require('http') or require('https')
	// ip: host ip
	// port: host port
	// options: {
	//   ping: ping path (no ping checks)
	//   pingTimeout: in ms (2000)
	//   maxPending: number of requests pending before returning an error (500)
	//   maxSockets: max concurrent open sockets (20)
	//   timeout: default request timeout in ms (60000)
	//   resolution: how often timeouts are checked in ms (1000)
	// }
	function Endpoint(http, ip, port, options) {
		options = options || {}

		this.http = http
		this.ip = ip
		this.port = port
		this.healthy = false
		this.name = this.ip + ':' + this.port
		this.address = this.ip
		this.pingPath = options.ping
		this.pingTimeout = options.pingTimeout || 2000

		this.agent = new http.Agent()
		this.agent.maxSockets = options.maxSockets || 20

		this.requests = {}
		this.requestCount = 0
		this.requestsLastCheck = 0
		this.requestRate = 0
		this.pending = 0
		this.successes = 0
		this.failures = 0

		this.maxPending = options.maxPending || 500
		this.timeout = options.timeout || (60 * 1000)
		this.resolution = options.resolution || 1000
		this.timeoutInterval = setInterval(this.checkTimeouts.bind(this), this.resolution)

		this.ping()
	}
	inherits(Endpoint, EventEmitter)

	Endpoint.prototype.checkTimeouts = function () {
		var keys = Object.keys(this.requests)
		for (var i = 0; i < keys.length; i++) {
			var r = this.requests[keys[i]]
			var expireTime = clock - r.options.timeout
			if (r.lastTouched <= expireTime) {
				this.emit("timeout", r)
				r.abort()
			}
		}
		if (!this.healthy) {
			this.ping()
		}
		this.requestRate = this.requestCount - this.requestsLastCheck
		this.requestsLastCheck = this.requestCount
	}

	Endpoint.prototype.resetCounters = function () {
		this.requestsLastCheck = this.requestRate - this.pending
		this.requestCount = this.pending
		this.successes = 0
		this.failures = 0
	}

	Endpoint.prototype.setPending = function () {
		this.pending = this.requestCount - (this.successes + this.failures)
		if (this.requestCount === MAX_COUNT) {
			this.resetCounters()
		}
	}

	Endpoint.prototype.complete = function (error, request, response, body) {
		this.deleteRequest(request.id)
		this.setPending()
		request.callback(error, response, body)
		request.callback = null
	}

	Endpoint.prototype.succeeded = function (request, response, body) {
		this.successes++
		this.complete(null, request, response, body)
	}

	Endpoint.prototype.failed = function (error, request) {
		this.failures++
		this.complete(error, request)
	}

	Endpoint.prototype.busyness = function () {
		return this.pending
	}

	// options: {
	//   agent:
	//   path:
	//   method:
	//   retryFilter:
	//   timeout: request timeout in ms (this.timeout)
	//   encoding: response body encoding (utf8)
	//   data: string or buffer
	// }
	// callback: function (error, response, body) {}
	Endpoint.prototype.request = function (options, callback) {
		if (this.pending >= this.maxPending && options.path !== this.pingPath) {
			return callback(
				{ reason: 'full'
				, message: 'too many pending requests ' + this.pending + '/' + this.maxPending
				})
		}
		options.host = this.ip
		options.port = this.port
		options.retryFilter = options.retryFilter || noop
		options.timeout = options.timeout || this.timeout
		if (options.agent !== false) {
			options.agent = this.agent
		}
		if (options.encoding !== null) {
			options.encoding = options.encoding || 'utf8'
		}

		var data = options.data
		if (data) {
			options.headers = options.headers || {}
			options.headers["Content-Length"] =
				Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)
		}
		var req = this.http.request(options)
		req.node = this
		req.options = options
		req.id = this.requestCount++
		req.lastTouched = clock
		req.callback = callback || noop
		req.on('response', gotResponse)
		req.on('error', gotError)
		req.end(data)

		this.setPending()
		this.requests[req.id] = req
	}

	Endpoint.prototype.setHealthy = function (newState) {
		if (this.healthy !== newState) {
			this.healthy = newState
			if (!this.healthy) {
				this.ping() // ping may set this back to healthy
				if (!this.healthy) {
					this.emit('health', this)
				}
			}
			else {
				this.emit('health', this)
			}
		}
	}

	Endpoint.prototype.deleteRequest = function (id) {
		delete this.requests[id]
	}

	function gotPingResponse(error, response, body) {
		this.node.setHealthy(!error && response.statusCode === 200)
	}

	Endpoint.prototype.ping = function () {
		if (this.pingPath) {
			this.request(
				{ path: this.pingPath
				, method: 'GET'
				, timeout: this.pingTimeout
				}
				, gotPingResponse)
		}
		else {
			this.setHealthy(true)
		}
	}

	// this = request
	function gotResponse(response) {
		response.bodyChunks = []
		response.bodyLength = 0
		response.request = this
		response.on('data', gotData)
		response.on('end', gotEnd)
		response.on('aborted', gotAborted)
	}

	// this = request
	function gotError(error) {
		this.node.failed(
			{ reason: error.message
			, attempt: this
			, message: this.node.ip + ':' + this.node.port + ' error: ' + error.message
			}
			, this)
		this.node.setHealthy(false)
	}

	// this = response
	function gotData(chunk) {
		this.request.lastTouched = clock
		this.bodyChunks.push(chunk)
		this.bodyLength += chunk.length
	}

	// this = response
	function gotEnd() {
		var req = this.request
		var opt = req.options
		var node = req.node

		if (req.callback === null) { return }
		node.setHealthy(true)

		var buffer = new Buffer(this.bodyLength)
		var offset = 0
		for (var i = 0; i < this.bodyChunks.length; i++) {
			var chunk = this.bodyChunks[i]
			chunk.copy(buffer, offset, 0, chunk.length)
			offset += chunk.length
		}

		var body = (opt.encoding !== null) ? buffer.toString(opt.encoding) : buffer

		var delay = opt.retryFilter(opt, this, body)
		if (delay !== false) { // delay may be 0
			return node.failed(
			{ delay: delay
			, reason: 'filter'
			, attempt: req
			, message: node.ip + ':' + node.port + ' error: rejected by filter'
			}
			, req)
		}
		node.succeeded(req, this, body)
	}

	// this = response
	function gotAborted() {
		this.request.node.failed(
			{ reason: 'aborted'
			, attempt: this.request
			, message: this.request.node.ip + ':' + this.request.node.port + ' error: connection aborted'
			}
			, this.request)
	}

	return Endpoint
}
<|endoftext|>


<commit_before>module.exports = function (io, util, problem, math) {
  var currentProblem,
      correctAnswer;

  var leaderboard = {};

  io.sockets.on('connection', function (socket) {

    socket.on('disconnect', function () {
      socket.get('username', function (err, username) {
        if (err) return console.dir(err);
        delete leaderboard[username];

        // send leaderboard
        io.sockets.emit('leaderboard',
          util.assocArrayify(leaderboard).sort(util.sortAssocArray));
      });

    });

    if (currentProblem && correctAnswer) {
      socket.emit('problem', currentProblem);
    }

    socket.on('set username', function (username) {

      // if username already exists
      if (leaderboard.hasOwnProperty(username)) {
        socket.emit('username nak');

      // if username doesn't exist
      } else {
        socket.emit('username ack');
        socket.set('username', username, function () {
          console.log('SET USERNAME: ' + username);
          leaderboard[username] = 0;
          console.log(leaderboard);
        });

        if (currentProblem === undefined) {
          currentProblem = problem.create().trim();
          console.dir(currentProblem);
          correctAnswer  = Math.floor(math.eval(currentProblem));
          io.sockets.emit('problem', currentProblem);
        }

      }
    });

    socket.on('guess', function (guess) {
      var guess = Number(guess);

      if (guess === correctAnswer) {
        socket.get('username', function (err, username) {
          console.log('CORRECT ANSWER BY: ' + username);
          leaderboard[username]++
        });

        socket.emit('guess status', 'correct');

        io.sockets.emit('leaderboard',
          util.assocArrayify(leaderboard).sort(util.sortAssocArray));

        currentProblem = problem.create();
        correctAnswer  = Math.floor(math.eval(currentProblem));
        io.sockets.emit('problem', currentProblem);
      } else {
        socket.emit('guess status', 'incorrect');
      }
    });
  });
}
<commit_msg>sockets remove whitespace<commit_after>module.exports = function (io, util, problem, math) {
  var currentProblem,
      correctAnswer;

  var leaderboard = {};

  io.sockets.on('connection', function (socket) {

    socket.on('disconnect', function () {
      socket.get('username', function (err, username) {
        if (err) return console.dir(err);
        delete leaderboard[username];

        // send leaderboard
        io.sockets.emit('leaderboard',
          util.assocArrayify(leaderboard).sort(util.sortAssocArray));
      });
    });

    if (currentProblem && correctAnswer) {
      socket.emit('problem', currentProblem);
    }

    socket.on('set username', function (username) {

      // if username already exists
      if (leaderboard.hasOwnProperty(username)) {
        socket.emit('username nak');

      // if username doesn't exist
      } else {
        socket.emit('username ack');
        socket.set('username', username, function () {
          console.log('SET USERNAME: ' + username);
          leaderboard[username] = 0;
          console.log(leaderboard);
        });

        if (currentProblem === undefined) {
          currentProblem = problem.create().trim();
          console.dir(currentProblem);
          correctAnswer  = Math.floor(math.eval(currentProblem));
          io.sockets.emit('problem', currentProblem);
        }
      }
    });

    socket.on('guess', function (guess) {
      var guess = Number(guess);

      if (guess === correctAnswer) {
        socket.get('username', function (err, username) {
          console.log('CORRECT ANSWER BY: ' + username);
          leaderboard[username]++
        });

        socket.emit('guess status', 'correct');

        io.sockets.emit('leaderboard',
          util.assocArrayify(leaderboard).sort(util.sortAssocArray));

        currentProblem = problem.create();
        correctAnswer  = Math.floor(math.eval(currentProblem));
        io.sockets.emit('problem', currentProblem);
      } else {
        socket.emit('guess status', 'incorrect');
      }
    });
  });
}
<|endoftext|>


<commit_before>'use strict';

module.exports = [
  'gulp',
  'assemble',
  'grunt',
  'generator',
  'handlebars',
  'helper'
];<commit_msg>Added postcss exclude<commit_after>'use strict';

module.exports = [
  'gulp',
  'assemble',
  'grunt',
  'generator',
  'handlebars',
  'helper',
  'postcss'
];
<|endoftext|>