<commit_before>// Concats js/css resources per-bundle
//

'use strict';

// stdlib
var fs      = require('fs');
var path    = require('path');
var format  = require('util').format;

// 3rd-party
var _       = require('lodash');
var fstools = require('fs-tools');

// internal
var stopwatch = require('../utils/stopwatch');

////////////////////////////////////////////////////////////////////////////////

// Returns package styesheet string
//
function readPackageStylesheet(pkgName, sandbox) {
  var filename = path.join(sandbox.tmpdir, "styles", pkgName + ".css");
  return fs.existsSync(filename) ? fs.readFileSync(filename, "utf8") : "";
}

// Returns map of { <locale> : <source>, ... }
//
function readPackageJavascripts(pkgName, sandbox, withLocales) {
  var data = { "*" : "" }
    , tmpdir = sandbox.tmpdir
    , N = sandbox.N;

  //
  // Join locale-independent data. The order matters since `views` depends on
  // `N.views` created in `client` files.
  //

  ['vendor', 'client', 'views'].forEach(function (part) {
    var filename = path.join(tmpdir, part, pkgName + '.js');

    if (fs.existsSync(filename)) {
      data["*"] += ';' + fs.readFileSync(filename, "utf8");
    }
  });

  //
  // prepare localized data if required
  //

  if (withLocales) {
    N.config.locales['enabled'].forEach(function (locale) {
      var filename = path.join(tmpdir, 'i18n', pkgName, locale + '.js');

      if (fs.existsSync(filename)) {
        data[locale] = data["*"] + ';' + fs.readFileSync(filename, "utf8");
      }
    });
  }

  return data;
}

// Reads stylesheets and javascripts for each package. Concatenate javascripts
// per-language if needed.
//
// Returns hash with package -> assets:
//
//    {
//      forum: {
//        stylesheet: <String>,
//        javascripts: {
//          "en-US": <String>,
//          ...
//        }
//      },
//
//      lib: {
//        stylesheet: <String>,
//        javascripts: {
//          "*": <String>
//        }
//      },
//
//      ...
//    }
//
function concatFilesPerPackage(sandbox) {
  var assets = {};

  _.keys(sandbox.config.packages).forEach(function (pkgName) {
    var withLocales = _.contains(sandbox.clientI18nPackages, pkgName);

    assets[pkgName] = {
      stylesheet:   readPackageStylesheet(pkgName, sandbox),
      javascripts:  readPackageJavascripts(pkgName, sandbox, withLocales)
    };
  });

  return assets;
}

// Concat builded stylesheets from different packages and writes bundled
// stylesheet if it's non-empty
//
function writeBundleStylesheet(bndlName, sandbox, assets) {
  var stylesheet  = ""
    , filename    = path.join(sandbox.tmpdir, "bundle", "bundle-" + bndlName + ".css");

  _.each(assets, function (data) {
    stylesheet += data.stylesheet;
  });

  if (!stylesheet) {
    return null;
  }

  fs.writeFileSync(filename, stylesheet, "utf8");
  return filename;
}

// Concat all javascripts per-bundle / locale
//
function writeBundleJavascripts(bndlName, sandbox, assets) {
  var withLocales = _.any(assets, function (data) {
        // data always contains at least one key `*`.
        // if it has more than one key, then it contains locales
        return data.javascripts && 1 < _.keys(data.javascripts).length;
      })
    , N = sandbox.N
    , tmpdir = sandbox.tmpdir;

  function writeFile(locale) {
    var
    javascript  = "",
    suffix      = (locale ? ("." + locale) : "") + ".js",
    filename    = path.join(tmpdir, "bundle", "bundle-" + bndlName + suffix);

    _.each(assets, function (data) {
      javascript += data.javascripts[locale] || data.javascripts['*'] || '';
    });

    if (!javascript) {
      return null;
    }

    fs.writeFileSync(filename, javascript, "utf8");
    return filename;
  }

  var data = {};

  if (!withLocales) {
    data["*"] = writeFile();
  } else {
    N.config.locales["enabled"].forEach(function (locale) {
      data[locale] = writeFile(locale);
    });
  }

  return data;
}

// Write bundle files
//
//    bundle/<name>.css
//    bundle/<name>.<locale>.js
//
function writeAssetsPerBundle(sandbox, assets) {
  var data = {};

  _.each(sandbox.config.bundles, function (packages, bndlName) {
    var bndlAssets = _.pick(assets, packages);

    data[bndlName] = {
      stylesheet:   writeBundleStylesheet(bndlName, sandbox, bndlAssets),
      javascripts:  writeBundleJavascripts(bndlName, sandbox, bndlAssets)
    };
  });

  return data;
}

// Walks over all packages in the given distibution and composes queues of
// packages and stylesheets on each.
//
// The resulting package queues are full lists of packages are needed to load in
// order to load the given package. In the exact order. These include also the
// concerned package ifself at the last position.
//
// The resulting stylesheet queues are intended to use in the view layouts for
// linking initial page stylesheets.
//
function composeLoadingQueues(sandbox, distribution) {
  _.each(distribution, function (localeDist) {
    _.each(localeDist, function (pkgDist, pkgName) {
      var packagesQueue = []
        , stylesQueue  = [];

      // This function is used to recursively populate the loading queue.
      function processPackage(processPkgName) {
        var processPkgConfig = sandbox.config.packages[processPkgName];

        // Yield dependences of the current package first.
        if (processPkgConfig.depends) {
          processPkgConfig.depends.forEach(function (dependency) {
            if (-1 === packagesQueue.indexOf(dependency)) {
              processPackage(dependency);
            }
          });
        }

        // Yield the current package itself at the last.
        packagesQueue.push(processPkgName);
      }

      // Compose the loading queue.
      processPackage(pkgName);

      // Compose the styles queue.
      packagesQueue.forEach(function (depName) {
        var depDist = localeDist[depName];

        if (depDist && depDist.stylesheet) {
          if (-1 === stylesQueue.indexOf(depDist.stylesheet)) {
            stylesQueue.push(depDist.stylesheet);
          }
        }
      });

      // Expose the queues to the package distribution.
      pkgDist.packagesQueue = packagesQueue;
      pkgDist.stylesQueue   = stylesQueue;
    });
  });
}

// Returns assets distribution map that will be used by loader
//
//    <locale>:
//      <pkgName>:
//        stylesheets:
//          - <file>
//          - ...
//        javascripts:
//          - <file>
//          - ...
//
function createLoaderPkgsMap(sandbox, bundleAssets) {
  var // map of { <packageName>: <bundleName>, ... }
      pkgBundle = {}
      // map of { <packageName>: { <locale>: { <assets> }, ... } }
    , distribution = {}
    , N = sandbox.N;

  //
  // get bundles list
  //

  _.each(sandbox.config.bundles, function (packages, bndlName) {
    _.each(packages, function (pkgName) {
      pkgBundle[pkgName] = bndlName;
    });
  });

  //
  // collect assets for each package per locale
  //

  N.config.locales["enabled"].forEach(function (locale) {
    distribution[locale] = {};

    _.keys(sandbox.config.packages).forEach(function (pkgName) {
      var assets, stylesheet, javascript;

      assets = bundleAssets[pkgBundle[pkgName]];

      if(!assets) {
        throw new Error(format(
              'Package `%s` defined, but not assigned to any bundle, ' +
              'check `bundle.yml` in appropriate application root', pkgName));
      }

      distribution[locale][pkgName] = {
        packagesQueue: null,
        stylesQueue:   null,
        stylesheet:    null,
        javascript:    null
      };

      stylesheet = assets.stylesheet;
      javascript = assets.javascripts[locale] || assets.javascripts["*"];

      if (stylesheet) {
        stylesheet = sandbox.assets.environment.findAsset(stylesheet);

        distribution[locale][pkgName].stylesheet = stylesheet.logicalPath;
        sandbox.assets.files.push(stylesheet.logicalPath);
      }

      if (javascript) {
        javascript = sandbox.assets.environment.findAsset(javascript);

        distribution[locale][pkgName].javascript = javascript.logicalPath;
        sandbox.assets.files.push(javascript.logicalPath);
      }
    });
  });

  return distribution;
}

////////////////////////////////////////////////////////////////////////////////

module.exports = function (sandbox) {
  var timer   = stopwatch()
    , N       = sandbox.N
    , bndlDir = path.join(sandbox.tmpdir, 'bundle')
    , compiledPkgs
    , compiledBndls;

  fstools.mkdirSync(bndlDir);

  compiledPkgs  = concatFilesPerPackage(sandbox);
  compiledBndls = writeAssetsPerBundle(sandbox, compiledPkgs);

  sandbox.assets.environment.appendPath(bndlDir);

  sandbox.assets.distribution = createLoaderPkgsMap(sandbox, compiledBndls);
  composeLoadingQueues(sandbox, sandbox.assets.distribution);

  N.logger.debug('Concatenated dynamic assets %s', timer.elapsed);
};
<commit_msg>Revert "Correct join order of resources in the bundler."<commit_after>// Concats js/css resources per-bundle
//

'use strict';

// stdlib
var fs      = require('fs');
var path    = require('path');
var format  = require('util').format;

// 3rd-party
var _       = require('lodash');
var fstools = require('fs-tools');

// internal
var stopwatch = require('../utils/stopwatch');

////////////////////////////////////////////////////////////////////////////////

// Returns package styesheet string
//
function readPackageStylesheet(pkgName, sandbox) {
  var filename = path.join(sandbox.tmpdir, "styles", pkgName + ".css");
  return fs.existsSync(filename) ? fs.readFileSync(filename, "utf8") : "";
}

// Returns map of { <locale> : <source>, ... }
//
function readPackageJavascripts(pkgName, sandbox, withLocales) {
  var data = { "*" : "" }
    , tmpdir = sandbox.tmpdir
    , N = sandbox.N;

  //
  // join locale-independent data
  //

  [ "vendor", "views", "client" ].forEach(function (part) {
    var filename = path.join(tmpdir, part, pkgName + '.js');

    if (fs.existsSync(filename)) {
      data["*"] += ';' + fs.readFileSync(filename, "utf8");
    }
  });

  //
  // prepare localized data if required
  //

  if (withLocales) {
    N.config.locales['enabled'].forEach(function (locale) {
      var filename = path.join(tmpdir, 'i18n', pkgName, locale + '.js');

      if (fs.existsSync(filename)) {
        data[locale] = data["*"] + ';' + fs.readFileSync(filename, "utf8");
      }
    });
  }

  return data;
}

// Reads stylesheets and javascripts for each package. Concatenate javascripts
// per-language if needed.
//
// Returns hash with package -> assets:
//
//    {
//      forum: {
//        stylesheet: <String>,
//        javascripts: {
//          "en-US": <String>,
//          ...
//        }
//      },
//
//      lib: {
//        stylesheet: <String>,
//        javascripts: {
//          "*": <String>
//        }
//      },
//
//      ...
//    }
//
function concatFilesPerPackage(sandbox) {
  var assets = {};

  _.keys(sandbox.config.packages).forEach(function (pkgName) {
    var withLocales = _.contains(sandbox.clientI18nPackages, pkgName);

    assets[pkgName] = {
      stylesheet:   readPackageStylesheet(pkgName, sandbox),
      javascripts:  readPackageJavascripts(pkgName, sandbox, withLocales)
    };
  });

  return assets;
}

// Concat builded stylesheets from different packages and writes bundled
// stylesheet if it's non-empty
//
function writeBundleStylesheet(bndlName, sandbox, assets) {
  var stylesheet  = ""
    , filename    = path.join(sandbox.tmpdir, "bundle", "bundle-" + bndlName + ".css");

  _.each(assets, function (data) {
    stylesheet += data.stylesheet;
  });

  if (!stylesheet) {
    return null;
  }

  fs.writeFileSync(filename, stylesheet, "utf8");
  return filename;
}

// Concat all javascripts per-bundle / locale
//
function writeBundleJavascripts(bndlName, sandbox, assets) {
  var withLocales = _.any(assets, function (data) {
        // data always contains at least one key `*`.
        // if it has more than one key, then it contains locales
        return data.javascripts && 1 < _.keys(data.javascripts).length;
      })
    , N = sandbox.N
    , tmpdir = sandbox.tmpdir;

  function writeFile(locale) {
    var
    javascript  = "",
    suffix      = (locale ? ("." + locale) : "") + ".js",
    filename    = path.join(tmpdir, "bundle", "bundle-" + bndlName + suffix);

    _.each(assets, function (data) {
      javascript += data.javascripts[locale] || data.javascripts['*'] || '';
    });

    if (!javascript) {
      return null;
    }

    fs.writeFileSync(filename, javascript, "utf8");
    return filename;
  }

  var data = {};

  if (!withLocales) {
    data["*"] = writeFile();
  } else {
    N.config.locales["enabled"].forEach(function (locale) {
      data[locale] = writeFile(locale);
    });
  }

  return data;
}

// Write bundle files
//
//    bundle/<name>.css
//    bundle/<name>.<locale>.js
//
function writeAssetsPerBundle(sandbox, assets) {
  var data = {};

  _.each(sandbox.config.bundles, function (packages, bndlName) {
    var bndlAssets = _.pick(assets, packages);

    data[bndlName] = {
      stylesheet:   writeBundleStylesheet(bndlName, sandbox, bndlAssets),
      javascripts:  writeBundleJavascripts(bndlName, sandbox, bndlAssets)
    };
  });

  return data;
}

// Walks over all packages in the given distibution and composes queues of
// packages and stylesheets on each.
//
// The resulting package queues are full lists of packages are needed to load in
// order to load the given package. In the exact order. These include also the
// concerned package ifself at the last position.
//
// The resulting stylesheet queues are intended to use in the view layouts for
// linking initial page stylesheets.
//
function composeLoadingQueues(sandbox, distribution) {
  _.each(distribution, function (localeDist) {
    _.each(localeDist, function (pkgDist, pkgName) {
      var packagesQueue = []
        , stylesQueue  = [];

      // This function is used to recursively populate the loading queue.
      function processPackage(processPkgName) {
        var processPkgConfig = sandbox.config.packages[processPkgName];

        // Yield dependences of the current package first.
        if (processPkgConfig.depends) {
          processPkgConfig.depends.forEach(function (dependency) {
            if (-1 === packagesQueue.indexOf(dependency)) {
              processPackage(dependency);
            }
          });
        }

        // Yield the current package itself at the last.
        packagesQueue.push(processPkgName);
      }

      // Compose the loading queue.
      processPackage(pkgName);

      // Compose the styles queue.
      packagesQueue.forEach(function (depName) {
        var depDist = localeDist[depName];

        if (depDist && depDist.stylesheet) {
          if (-1 === stylesQueue.indexOf(depDist.stylesheet)) {
            stylesQueue.push(depDist.stylesheet);
          }
        }
      });

      // Expose the queues to the package distribution.
      pkgDist.packagesQueue = packagesQueue;
      pkgDist.stylesQueue   = stylesQueue;
    });
  });
}

// Returns assets distribution map that will be used by loader
//
//    <locale>:
//      <pkgName>:
//        stylesheets:
//          - <file>
//          - ...
//        javascripts:
//          - <file>
//          - ...
//
function createLoaderPkgsMap(sandbox, bundleAssets) {
  var // map of { <packageName>: <bundleName>, ... }
      pkgBundle = {}
      // map of { <packageName>: { <locale>: { <assets> }, ... } }
    , distribution = {}
    , N = sandbox.N;

  //
  // get bundles list
  //

  _.each(sandbox.config.bundles, function (packages, bndlName) {
    _.each(packages, function (pkgName) {
      pkgBundle[pkgName] = bndlName;
    });
  });

  //
  // collect assets for each package per locale
  //

  N.config.locales["enabled"].forEach(function (locale) {
    distribution[locale] = {};

    _.keys(sandbox.config.packages).forEach(function (pkgName) {
      var assets, stylesheet, javascript;

      assets = bundleAssets[pkgBundle[pkgName]];

      if(!assets) {
        throw new Error(format(
              'Package `%s` defined, but not assigned to any bundle, ' +
              'check `bundle.yml` in appropriate application root', pkgName));
      }

      distribution[locale][pkgName] = {
        packagesQueue: null,
        stylesQueue:   null,
        stylesheet:    null,
        javascript:    null
      };

      stylesheet = assets.stylesheet;
      javascript = assets.javascripts[locale] || assets.javascripts["*"];

      if (stylesheet) {
        stylesheet = sandbox.assets.environment.findAsset(stylesheet);

        distribution[locale][pkgName].stylesheet = stylesheet.logicalPath;
        sandbox.assets.files.push(stylesheet.logicalPath);
      }

      if (javascript) {
        javascript = sandbox.assets.environment.findAsset(javascript);

        distribution[locale][pkgName].javascript = javascript.logicalPath;
        sandbox.assets.files.push(javascript.logicalPath);
      }
    });
  });

  return distribution;
}

////////////////////////////////////////////////////////////////////////////////

module.exports = function (sandbox) {
  var timer   = stopwatch()
    , N       = sandbox.N
    , bndlDir = path.join(sandbox.tmpdir, 'bundle')
    , compiledPkgs
    , compiledBndls;

  fstools.mkdirSync(bndlDir);

  compiledPkgs  = concatFilesPerPackage(sandbox);
  compiledBndls = writeAssetsPerBundle(sandbox, compiledPkgs);

  sandbox.assets.environment.appendPath(bndlDir);

  sandbox.assets.distribution = createLoaderPkgsMap(sandbox, compiledBndls);
  composeLoadingQueues(sandbox, sandbox.assets.distribution);

  N.logger.debug('Concatenated dynamic assets %s', timer.elapsed);
};
<|endoftext|>


<commit_before>/**
 * This file (misc.js) contains miscellaneous methods, usually entirely self-contained
 * They are put here since they do not require their own specific file for readability
 */

let config = require('./config');
let request = require('request-promise');
let fs = require('fs');

/**
 *  @param {message} message  A message object as defined in discord.js
 *  @param {string[]} cmds
 */
 function urbanDefine(message, cmds) {
   let term = cmds.slice(1).join('+');

   let options = {
     uri: config.urban_url + term,
     json: true
   };

   request(options)
      .then(function (body) {
        if (body.result_type == "no_results") {
          console.log('No results for ' + term);
          message.channel.send("There are no results for: " + term.replace('+', ' '))
            .catch( reason => { console.log("Rejected Urban Null Promise for " + reason); });
        } else {
          let firstDef = body.list[0];
          message.channel.send('**' + cmds.slice(1).join(' ') + ':**\n' + firstDef.definition + '\n' + firstDef.example)
            .catch( reason => { console.log("Rejected Urban Definition Promise for " + reason); });
        }
      }).catch(function (err) {
        console.log('Error accessing Urban Dictionary\'s API:\n' + err);
        message.channel.send("Error accessing Urban Dictionary")
          .catch( reason => { console.log("Rejected Urban Reject Promise for " + reason); });
      });
 }

/**
 * @param {message} message A message object as defined in discord.js
 * @param {string} user A string representation of the user either as an id or username
 */
 function getAvatar(message, user) {
   console.log("Looking for: " + user)
   let memberName = user.toLowerCase();
   let avatarURL = '';

   if (memberName.charAt(1) == '@') {
     let obj = message.guild.members.get(memberName.substring(2, memberName.length - 1));
     if (typeof obj !== 'undefined') {
      avatarURL = obj.user.displayAvatarURL;
      console.log("Found " + obj.displayName + "'s avatar at " + avatarURL);
     }
   } else {
     for (var [id, memberObj] of message.guild.members) {
       let displayName = memberObj.displayName.toLowerCase();
       let username = memberObj.user.username.toLowerCase();

       if (displayName == memberName || username == memberName) {
        avatarURL = memberObj.user.displayAvatarURL;
        console.log("Found " + memberObj.displayName + "'s avatar at " + avatarURL);
        break;
       }
     }
   }

   if (avatarURL) {
     avatarURL = avatarURL.replace('jpg', 'png');
     message.channel.send(avatarURL)
      .catch( reason => { console.log("Rejected Avatar Result for " + reason); });
   } else {
     console.log("Could not find member " + user);
     message.channel.send("I couldn't find that member!")
      .catch( reason => { console.log("Rejected Avatar Null Promise for " + reason); });
   }
 }

/**
* @param {message} message A message object as defined in discord.js
*/
 function coinFlip(message) {
   let coin;
   let flip = Math.floor(Math.random() * 100 + 1);

   if (flip < 50) {
     coin = 'tails';
   } else if (flip > 50) {
     coin = 'heads';
   } else {
     message.channel.send('Uhm... the coin landed on its side, flipping again.')
      .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
    message.channel.send('!coinflip')
      .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
   }
   message.channel.send('You flipped **' + coin + '**')
    .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
 }

 /**
  *  @param {message} message  A message object as defined in discord.js
  *  @param {string[]} cmds Strings that need to be joined and rated
  * Consider replacing the random function with another thing, maybe tied to stocks or time
  */
 function rate(message, cmds) {
   let str = message.content.split(' ').slice(1).join(' ');
   let rating = rateAlgorithm(str);

   if (str.toLowerCase() == 'staed') {
     message.channel.send("Staeds are great! I'll give Staed a 10/10!")
      .catch( reason => { console.log("Rejected Rate Staed Promise for " + reason); });
     console.log('Rated a Staed');
   } else if (str.toLowerCase() == 'sawai') {
     message.channel.send("Sawais are :put_litter_in_its_place: I'll give Sawai a 0/10")
      .catch( reason => { console.log("Rejected Rate Sawai Promise for " + reason); });
     console.log('Rated a Sawai');
   } else {
     console.log('Rated ' + str + ' as ' + rating + '/10');
     message.channel.send("I'd rate " + str + ' ' + rating + '/10')
      .catch( reason => { console.log("Rejected Rate Response Promise for " + reason); });
   }
 }

/**
 * @param {string} text A string containing the thing to be rated
 * @return {int} A number between 1 and 10 inclusive
 */
 function rateAlgorithm(text) {
   return Math.floor(Math.random() * 10 + 1);
 }

 module.exports = {urbanDefine, getAvatar, coinFlip, rate};
<commit_msg>Added a missing break in !coinflip command<commit_after>/**
 * This file (misc.js) contains miscellaneous methods, usually entirely self-contained
 * They are put here since they do not require their own specific file for readability
 */

let config = require('./config');
let request = require('request-promise');
let fs = require('fs');

/**
 *  @param {message} message  A message object as defined in discord.js
 *  @param {string[]} cmds
 */
 function urbanDefine(message, cmds) {
   let term = cmds.slice(1).join('+');

   let options = {
     uri: config.urban_url + term,
     json: true
   };

   request(options)
      .then(function (body) {
        if (body.result_type == "no_results") {
          console.log('No results for ' + term);
          message.channel.send("There are no results for: " + term.replace('+', ' '))
            .catch( reason => { console.log("Rejected Urban Null Promise for " + reason); });
        } else {
          let firstDef = body.list[0];
          message.channel.send('**' + cmds.slice(1).join(' ') + ':**\n' + firstDef.definition + '\n' + firstDef.example)
            .catch( reason => { console.log("Rejected Urban Definition Promise for " + reason); });
        }
      }).catch(function (err) {
        console.log('Error accessing Urban Dictionary\'s API:\n' + err);
        message.channel.send("Error accessing Urban Dictionary")
          .catch( reason => { console.log("Rejected Urban Reject Promise for " + reason); });
      });
 }

/**
 * @param {message} message A message object as defined in discord.js
 * @param {string} user A string representation of the user either as an id or username
 */
 function getAvatar(message, user) {
   console.log("Looking for: " + user)
   let memberName = user.toLowerCase();
   let avatarURL = '';

   if (memberName.charAt(1) == '@') {
     let obj = message.guild.members.get(memberName.substring(2, memberName.length - 1));
     if (typeof obj !== 'undefined') {
      avatarURL = obj.user.displayAvatarURL;
      console.log("Found " + obj.displayName + "'s avatar at " + avatarURL);
     }
   } else {
     for (var [id, memberObj] of message.guild.members) {
       let displayName = memberObj.displayName.toLowerCase();
       let username = memberObj.user.username.toLowerCase();

       if (displayName == memberName || username == memberName) {
        avatarURL = memberObj.user.displayAvatarURL;
        console.log("Found " + memberObj.displayName + "'s avatar at " + avatarURL);
        break;
       }
     }
   }

   if (avatarURL) {
     avatarURL = avatarURL.replace('jpg', 'png');
     message.channel.send(avatarURL)
      .catch( reason => { console.log("Rejected Avatar Result for " + reason); });
   } else {
     console.log("Could not find member " + user);
     message.channel.send("I couldn't find that member!")
      .catch( reason => { console.log("Rejected Avatar Null Promise for " + reason); });
   }
 }

/**
* @param {message} message A message object as defined in discord.js
*/
 function coinFlip(message) {
   let coin;
   let flip = Math.floor(Math.random() * 100 + 1);

   if (flip < 50) {
     coin = 'tails';
   } else if (flip > 50) {
     coin = 'heads';
   } else {
     message.channel.send('Uhm... the coin landed on its side, flipping again.')
      .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
    message.channel.send('!coinflip')
      .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
    break;
   }
   message.channel.send('You flipped **' + coin + '**')
    .catch( reason => { console.log("Rejected Coin Flip Promise for " + reason); });
 }

 /**
  *  @param {message} message  A message object as defined in discord.js
  *  @param {string[]} cmds Strings that need to be joined and rated
  * Consider replacing the random function with another thing, maybe tied to stocks or time
  */
 function rate(message, cmds) {
   let str = message.content.split(' ').slice(1).join(' ');
   let rating = rateAlgorithm(str);

   if (str.toLowerCase() == 'staed') {
     message.channel.send("Staeds are great! I'll give Staed a 10/10!")
      .catch( reason => { console.log("Rejected Rate Staed Promise for " + reason); });
     console.log('Rated a Staed');
   } else if (str.toLowerCase() == 'sawai') {
     message.channel.send("Sawais are :put_litter_in_its_place: I'll give Sawai a 0/10")
      .catch( reason => { console.log("Rejected Rate Sawai Promise for " + reason); });
     console.log('Rated a Sawai');
   } else {
     console.log('Rated ' + str + ' as ' + rating + '/10');
     message.channel.send("I'd rate " + str + ' ' + rating + '/10')
      .catch( reason => { console.log("Rejected Rate Response Promise for " + reason); });
   }
 }

/**
 * @param {string} text A string containing the thing to be rated
 * @return {int} A number between 1 and 10 inclusive
 */
 function rateAlgorithm(text) {
   return Math.floor(Math.random() * 10 + 1);
 }

 module.exports = {urbanDefine, getAvatar, coinFlip, rate};
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var EventEmitter = require('./lib/event_emitter');
var inherits = require('util').inherits;

var errors = require('./errors');
var States = require('./reqres_states');

var emptyBuffer = Buffer(0);

function TChannelInRequest(id, options) {
    var self = this;

    EventEmitter.call(self);
    self.errorEvent = self.defineEvent('error');
    self.finishEvent = self.defineEvent('finish');
    self.channel = options.channel;

    self.timeout = options.timeout || 0;
    self.tracing = options.tracing || null;
    self.serviceName = options.serviceName || '';
    self.headers = options.headers || {};
    self.checksum = options.checksum || null;
    self.retryFlags = options.retryFlags || null;
    self.connection = options.connection || null;

    self.state = States.Initial;
    self.id = id || 0;
    self.remoteAddr = null;
    self.streamed = false;
    self.arg1 = emptyBuffer;
    self.endpoint = null;
    self.arg2 = emptyBuffer;
    self.arg3 = emptyBuffer;
    self.forwardTrace = false;
    self.span = null;
    self.start = self.channel.timers.now();
    self.timedOut = false;
    self.res = null;

    if (options.tracer) {
        self.setupTracing(options);
    }
}

inherits(TChannelInRequest, EventEmitter);

TChannelInRequest.prototype.type = 'tchannel.incoming-request';

TChannelInRequest.prototype.setupTracing = function setupTracing(options) {
    var self = this;

    self.span = options.tracer.setupNewSpan({
        spanid: self.tracing.spanid,
        traceid: self.tracing.traceid,
        parentid: self.tracing.parentid,
        flags: self.tracing.flags,
        remoteName: options.hostPort,
        serviceName: self.serviceName,
        name: '' // fill this in later
    });

    self.span.annotateBinary('cn', self.headers.cn);
    self.span.annotateBinary('as', self.headers.as);
    if (self.connection) {
        self.span.annotateBinary('src', self.connection.remoteName);
    }

    self.span.annotate('sr');
};

TChannelInRequest.prototype.handleFrame = function handleFrame(parts) {
    var self = this;
    if (!parts) {
        return;
    }

    if (parts.length !== 3 || self.state !== States.Initial) {
        self.errorEvent.emit(self, new Error(
            'un-streamed argument defragmentation is not implemented'));
    }

    self.arg1 = parts[0] || emptyBuffer;
    self.endpoint = String(self.arg1);
    self.arg2 = parts[1] || emptyBuffer;
    self.arg3 = parts[2] || emptyBuffer;

    if (self.span) {
        self.span.name = self.endpoint;
    }

    self.emitFinish();
};

TChannelInRequest.prototype.emitFinish = function emitFinish() {
    var self = this;

    self.state = States.Done;
    self.finishEvent.emit(self);
};

TChannelInRequest.prototype.checkTimeout = function checkTimeout() {
    var self = this;
    if (!self.timedOut) {
        var elapsed = self.channel.timers.now() - self.start;
        if (elapsed > self.timeout) {
            self.timedOut = true;
            // TODO: send an error frame response?
            // TODO: emit error on self.res instead / in additon to?
            // TODO: should cancel any pending handler
            process.nextTick(function deferInReqTimeoutErrorEmit() {
                self.errorEvent.emit(self, errors.RequestTimeoutError({
                    id: self.id,
                    start: self.start,
                    elapsed: elapsed,
                    timeout: self.timeout
                }));
            });
        }
    }
    return self.timedOut;
};

TChannelInRequest.prototype.withArg1 = function withArg1(callback) {
    var self = this;
    callback(null, self.arg1);
};

TChannelInRequest.prototype.withArg2 = function withArg23(callback) {
    var self = this;
    callback(null, self.arg2);
};

TChannelInRequest.prototype.withArg23 = function withArg23(callback) {
    var self = this;
    callback(null, self.arg2, self.arg3);
};

module.exports = TChannelInRequest;
<commit_msg>TChannelInRequest: trivial cleanup<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var EventEmitter = require('./lib/event_emitter');
var inherits = require('util').inherits;

var errors = require('./errors');
var States = require('./reqres_states');

var emptyBuffer = Buffer(0);

function TChannelInRequest(id, options) {
    var self = this;

    EventEmitter.call(self);
    self.errorEvent = self.defineEvent('error');
    self.finishEvent = self.defineEvent('finish');
    self.channel = options.channel;

    self.timeout = options.timeout || 0;
    self.tracing = options.tracing || null;
    self.serviceName = options.serviceName || '';
    self.headers = options.headers || {};
    self.checksum = options.checksum || null;
    self.retryFlags = options.retryFlags || null;
    self.connection = options.connection || null;

    self.state = States.Initial;
    self.id = id || 0;
    self.remoteAddr = null;
    self.streamed = false;
    self.arg1 = emptyBuffer;
    self.endpoint = null;
    self.arg2 = emptyBuffer;
    self.arg3 = emptyBuffer;
    self.forwardTrace = false;
    self.span = null;
    self.start = self.channel.timers.now();
    self.timedOut = false;
    self.res = null;

    if (options.tracer) {
        self.setupTracing(options);
    }
}

inherits(TChannelInRequest, EventEmitter);

TChannelInRequest.prototype.type = 'tchannel.incoming-request';

TChannelInRequest.prototype.setupTracing = function setupTracing(options) {
    var self = this;

    self.span = options.tracer.setupNewSpan({
        spanid: self.tracing.spanid,
        traceid: self.tracing.traceid,
        parentid: self.tracing.parentid,
        flags: self.tracing.flags,
        remoteName: options.hostPort,
        serviceName: self.serviceName,
        name: '' // fill this in later
    });

    self.span.annotateBinary('cn', self.headers.cn);
    self.span.annotateBinary('as', self.headers.as);
    if (self.connection) {
        self.span.annotateBinary('src', self.connection.remoteName);
    }

    self.span.annotate('sr');
};

TChannelInRequest.prototype.handleFrame = function handleFrame(parts) {
    var self = this;
    if (!parts) {
        return;
    }

    if (parts.length !== 3 || self.state !== States.Initial) {
        self.errorEvent.emit(self, new Error(
            'un-streamed argument defragmentation is not implemented'));
    }

    self.arg1 = parts[0] || emptyBuffer;
    self.endpoint = String(self.arg1);
    self.arg2 = parts[1] || emptyBuffer;
    self.arg3 = parts[2] || emptyBuffer;

    if (self.span) {
        self.span.name = self.endpoint;
    }

    self.emitFinish();
};

TChannelInRequest.prototype.emitFinish = function emitFinish() {
    var self = this;

    self.state = States.Done;
    self.finishEvent.emit(self);
};

TChannelInRequest.prototype.checkTimeout = function checkTimeout() {
    var self = this;
    if (!self.timedOut) {
        var elapsed = self.channel.timers.now() - self.start;
        if (elapsed > self.timeout) {
            self.timedOut = true;
            // TODO: send an error frame response?
            // TODO: emit error on self.res instead / in additon to?
            // TODO: should cancel any pending handler
            process.nextTick(deferInReqTimeoutErrorEmit);
        }
    }
    return self.timedOut;

    function deferInReqTimeoutErrorEmit() {
        self.errorEvent.emit(self, errors.RequestTimeoutError({
            id: self.id,
            start: self.start,
            elapsed: elapsed,
            timeout: self.timeout
        }));
    }
};

TChannelInRequest.prototype.withArg1 = function withArg1(callback) {
    var self = this;
    callback(null, self.arg1);
};

TChannelInRequest.prototype.withArg2 = function withArg23(callback) {
    var self = this;
    callback(null, self.arg2);
};

TChannelInRequest.prototype.withArg23 = function withArg23(callback) {
    var self = this;
    callback(null, self.arg2, self.arg3);
};

module.exports = TChannelInRequest;
<|endoftext|>


<commit_before>var map;
var addressBar;

function init() {
   var mapOptions = {
      center: new google.maps.LatLng(43.020054,-83.693008),
      zoom: 9,
      mapTypeId: 'roadmap',
   };

   map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

   // a new Info Window is created
   addressBar = new google.maps.InfoWindow();

   // close the Info Window with a click on the map
   google.maps.event.addListener(map, 'click', function() {
      addressBar.close();
   });

	// function called to create markers
   createMarkers();

}
google.maps.event.addDomListener(window, 'load', init);

function createMarkers(){

   // this variable sets the map bounds according to markers position
   var bounds = new google.maps.LatLngBounds();

   // for loop traverses markersData array calling createMarker function for each marker
   for (var i = 0; i < markersData.length; i++){

      addAdressesToMap(i);

      // marker position is added to bounds variable
      bounds.extend(latlng);
   }

   // Finally the bounds variable is used to set the map bounds
   // with fitBounds() function
   map.fitBounds(bounds);
}
//STEVE
function addAdressesToMap(i){
	var addresses = firebase.database().ref('Resources').orderByKey();
	addresses.once('value', function(snapshot){
  	var addressArray = new Array();
  	snapshot.forEach(function(childSnapshot){
  	var addr = childSnapshot.key;
  	var childData = addr;
  	addressArray.push(childData);
  })
  createmap(addressArray, i);
})

}
//STEVE
//currently testing using name1 all other values created here aren't used
//instead just passing values from arry through
//name1 being set to one to avoid errors from being null during testing
//name1 will output on all markers on map for testing purposes
function createmap(aArray, i){

	  var ref1 = firebase.database().ref('Resources').child(aArray[i]);
	  ref1.once('value', function(snapshot){
      var refval = snapshot.val();
      var address = refval.address;
	  //var latlng = refval.latlng;
	  var lat = refval.lat;
	  var lng = refval.lng;
      var name = refval.name;
      var phone = refval.phone;
	  var type = refval.type;
	  var latlng = new google.maps.LatLng(lat, lng);
	  createMarker(latlng, name, address, phone, type)
    })

}

// creates marker and set Info Window content
function createMarker(latlng, name, address, phone, type){
   if (type ==="Office Space"){
		   var marker = new google.maps.Marker({
			  map: map,
			  position: latlng,
			  title: name,
			  icon: "img/GMM/space.png"
		   });
   }
		else if (type ==="Business Consultation"){
			var marker = new google.maps.Marker({
			  map: map,
			  position: latlng,
			  title: name,
			  icon: "img/GMM/Business Consultation.png"
		   });
		}
		else if (type === "Business Resource"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/financial.png"
			   });
		}
		else if (type ==="Information Resource"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/Information.png"
			   });
		}
		else if (type === "Legal"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/legal.png"
			   });
		}
		else{
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/contract.png"
			   });
   }
   //click on a marker
   google.maps.event.addListener(marker, 'click', function() {

      //insert info to addressBar
      var iwContent = '
' +
            '
' + name + '
' +
         '
' + address + '
' +
         phone + '

';

      // including content to the Info Window.
      addressBar.setContent(iwContent);

      // open the Info Window at the current marker location.
      addressBar.open(map, marker);
   });
}
<commit_msg>Update resourcemap.js<commit_after>var map;
var addressBar;

// markersData
var markersData = [
   {
      lat: 43.040906,
      lng: -83.693678,
      name: "Oak Business Center",
      address1:"2712 Saginaw St# 106,",
      address2: "Flint, MI 48505",
      phone: "(810) 235-5555",
	  type: "Business Consultation"
   },
   {
      lat: 43.016650,
      lng: -83.687726,
      name: "Flint Foodworks",
      address1:"300 E. First St.",
      address2: "Flint, MI 48502",
      phone: "(810) 447-0714",
	  type: "Business Resource"
   },
   {
      lat: 43.021609,
      lng: -83.679291,
      name: "Flint Public Library",
      address1:"1026 E Kearsley St,",
      address2: "Flint, MI 48503",
      phone: "(810) 232-7111",
	  type: "Information Resource"

   },
   {
      lat: 43.020796,
      lng: -83.641771,
      name: "Goodwill Industries flint",
      address1:"501 S Averill Ave,",
      address2: "Flint, MI 48506",
      phone: "(810) 762-9960",
	  type: "Office Space"

   },
   {
      lat: 43.015820,
      lng: -83.690112,
      name: "Flint & Genesee Chamber of Commerce",
      address1:"519 Saginaw St #200,",
      address2: "Flint, MI 48502",
      phone: "(810) 600-1404",
	  type: "Legal"
   },
   {
      lat: 43.012367,
      lng: -83.712643,
      name: "Small Business Development Center",
      address1:"1700 University Ave,",
      address2: "Flint, MI 48504",
      phone: "(810) 762-9660",
	  type: "Business Consultation"
   },
   {
      lat: 43.015594,
      lng: -83.691933,
      name: "Flint Steamworks",
      address1:"124 W 1st St,",
      address2: "Flint, MI 48502",
      phone: "N/A",
	  type: "Information Resource"
   }
];

function init() {
   var mapOptions = {
      center: new google.maps.LatLng(43.020054,-83.693008),
      zoom: 9,
      mapTypeId: 'roadmap',
   };

   map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

   // a new Info Window is created
   addressBar = new google.maps.InfoWindow();

   // close the Info Window with a click on the map
   google.maps.event.addListener(map, 'click', function() {
      addressBar.close();
   });

	// function called to create markers
   createMarkers();

}
google.maps.event.addDomListener(window, 'load', init);

function createMarkers(){

   // this variable sets the map bounds according to markers position
   var bounds = new google.maps.LatLngBounds();

   // for loop traverses markersData array calling createMarker function for each marker
   for (var i = 0; i < markersData.length; i++){

      var latlng = new google.maps.LatLng(markersData[i].lat, markersData[i].lng);
      var name = markersData[i].name;
      var address1 = markersData[i].address1;
      var address2 = markersData[i].address2;
      var phone = markersData[i].phone;
	  var type = markersData[i].type;

      addAdressesToMap(i);

      // marker position is added to bounds variable
      bounds.extend(latlng);
   }

   // Finally the bounds variable is used to set the map bounds
   // with fitBounds() function
   map.fitBounds(bounds);
}
//STEVE
function addAdressesToMap(i){
	var addresses = firebase.database().ref('Resources').orderByKey();
	addresses.once('value', function(snapshot){
  	var addressArray = new Array();
  	snapshot.forEach(function(childSnapshot){
  	var addr = childSnapshot.key;
  	var childData = addr;
  	addressArray.push(childData);
  })
  createmap(addressArray, i);
})

}
//STEVE
//currently testing using name1 all other values created here aren't used
//instead just passing values from arry through
//name1 being set to one to avoid errors from being null during testing
//name1 will output on all markers on map for testing purposes
function createmap(aArray, i){

	  var ref1 = firebase.database().ref('Resources').child(aArray[i]);
	  ref1.once('value', function(snapshot){
      var refval = snapshot.val();
      var address = refval.address;
	  //var latlng = refval.latlng;
	  var lat = refval.lat;
	  var lng = refval.lng;
      var name = refval.name;
      var phone = refval.phone;
	  var type = refval.type;
	  var latlng = new google.maps.LatLng(lat, lng);
	  createMarker(latlng, name, address, phone, type)
    })

}

// creates marker and set Info Window content
function createMarker(latlng, name, address, phone, type){
   if (type ==="Office Space"){
		   var marker = new google.maps.Marker({
			  map: map,
			  position: latlng,
			  title: name,
			  icon: "img/GMM/space.png"
		   });
   }
		else if (type ==="Business Consultation"){
			var marker = new google.maps.Marker({
			  map: map,
			  position: latlng,
			  title: name,
			  icon: "img/GMM/Business Consultation.png"
		   });
		}
		else if (type === "Business Resource"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/financial.png"
			   });
		}
		else if (type ==="Information Resource"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/Information.png"
			   });
		}
		else if (type === "Legal"){
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/legal.png"
			   });
		}
		else{
			var marker = new google.maps.Marker({
				  map: map,
				  position: latlng,
				  title: name,
				  icon: "img/GMM/contract.png"
			   });
   }
   //click on a marker
   google.maps.event.addListener(marker, 'click', function() {

      //insert info to addressBar
      var iwContent = '
' +
            '
' + name + '
' +
         '
' + address + '
' +
         phone + '

';

      // including content to the Info Window.
      addressBar.setContent(iwContent);

      // open the Info Window at the current marker location.
      addressBar.open(map, marker);
   });
}
<|endoftext|>


<commit_before>import CRUDExtend from '../extends/crud'
import { buildURL } from '../utils/helpers'

class AccountsEndpoint extends CRUDExtend {
  constructor(endpoint) {
    super(endpoint)
    this.endpoint = 'accounts'
  }

  Create(body) {
    return this.request.send(this.endpoint, 'POST', { data: body })
  }

  Get({ accountId, token = null }) {
    return this.request.send(
      `${this.endpoint}/${accountId}`,
      'GET',
      undefined,
      token
    )
  }

  Update(accountId, body, token = null) {
    return this.request.send(
      `${this.endpoint}/${accountId}`,
      'PUT',
      body.data,
      token
    )
  }

  All(token = null, headers = {}) {
    const { limit, offset } = this

    this.call = this.request.send(
      buildURL(this.endpoint, {
        limit,
        offset
      }),
      'GET',
      undefined,
      token,
      this,
      headers
    )

    return this.call
  }
}

export default AccountsEndpoint
<commit_msg>fix: Removed wrapper for account.Create()<commit_after>import CRUDExtend from '../extends/crud'
import { buildURL } from '../utils/helpers'

class AccountsEndpoint extends CRUDExtend {
  constructor(endpoint) {
    super(endpoint)
    this.endpoint = 'accounts'
  }

  Create(body) {
    return this.request.send(this.endpoint, 'POST', body)
  }

  Get({ accountId, token = null }) {
    return this.request.send(
      `${this.endpoint}/${accountId}`,
      'GET',
      undefined,
      token
    )
  }

  Update(accountId, body, token = null) {
    return this.request.send(
      `${this.endpoint}/${accountId}`,
      'PUT',
      body.data,
      token
    )
  }

  All(token = null, headers = {}) {
    const { limit, offset } = this

    this.call = this.request.send(
      buildURL(this.endpoint, {
        limit,
        offset
      }),
      'GET',
      undefined,
      token,
      this,
      headers
    )

    return this.call
  }
}

export default AccountsEndpoint
<|endoftext|>


<commit_before>'use strict'

const path     = require('path')
const https    = require('https')
const url      = require('url')
const basename = path.basename
const get      = https.get
const parse    = url.parse

const async    = require('async')
const concat   = require('concat-stream')
const npm      = require('npm-remote-ls')
const RemoteLS = npm.RemoteLS

const COVERALL_IO = 'https://coveralls.io/github'

/**
 * Asynchronously returns the test coverage of a dependency
 * @example
 *   getPercentageProject('git+https://github.com/piranna/coverdeeps.git', function(err, percentage) {})
 * @param    {String}   repo     The Name of the dependency
 * @param    {Function} callback The callback
 * @requires path:basename
 * @requires https:get
 * @requires url:parse
 * @returns  {Function}          Returns the callback with an error if the
 *                              http code is higher or equal 400, or it returns
 *                              the percentage for the dependency
 *
 */
function getPercentageProject(repo, callback)
{
  repo = parse(repo).pathname.split('/')

  const user = repo[repo.length-2]
  repo = basename(repo[repo.length-1], '.git')

  get(COVERALL_IO+'/'+user+'/'+repo+'.json',
  function(res)
  {
    if(res.statusCode >= 400) return callback(null, 0)

    res.on('error', callback)

    res.pipe(concat(function(body)
    {
      body = JSON.parse(body)
      if(!body) return callback(null, 0)

      callback(null, body.covered_percent/100)  // Per-unit to easier calcs
    }))
  })
}

function getPercentageDependencies(dependencies, callback)
{
  if(!dependencies) return callback(null, 1)

  const keys = Object.keys(dependencies)
  if(!keys.length) return callback(null, 1)

  async.map(dependencies, function(dependency, callback)
  {
    if(typeof dependency === 'string') return callback(null, 1)

    calcPercentage(dependency, callback)
  },
  function(error, results)
  {
    if(error) return callback(error)

    const covered = keys.reduce(function(prev, key)
    {
      return prev + (results[key].covered_combined || 0)
    }, 0)

    callback(null, covered / keys.length)
  })
}

function calcPercentage(module, callback)
{
  async.parallel({
    module:       getPercentageProject     .bind(null, module.repository.url),
    dependencies: getPercentageDependencies.bind(null, module.dependencies)
  },
  function(error, result)
  {
    if(error) return callback(error)

    module.covered          = result.module
    module.covered_combined = result.module * result.dependencies

    callback(null, module)
  })
}

function coverdeeps(moduleName, callback)
{
  RemoteLS({development: false}).ls(moduleName, 'latest', function(tree) {
    if(!tree) return callback(new Error(moduleName+' not found on NPM registry'))

    calcPercentage(tree, callback)
  });
}

module.exports = coverdeeps
<commit_msg>Add variable documentation<commit_after>'use strict'

// Dependencies
const path     = require('path')
const https    = require('https')
const url      = require('url')
const basename = path.basename
const get      = https.get
const parse    = url.parse

const async    = require('async')
const concat   = require('concat-stream')
const npm      = require('npm-remote-ls')
const RemoteLS = npm.RemoteLS

/**
 * @constant
 * @type {String}
 * @default
 */
const COVERALL_IO = 'https://coveralls.io/github'

/**
 * Asynchronously returns the test coverage of a dependency
 * @example
 *   getPercentageProject('git+https://github.com/piranna/coverdeeps.git', function(err, percentage) {})
 * @param    {String}   repo     The Name of the dependency
 * @param    {Function} callback The callback
 * @requires path:basename
 * @requires https:get
 * @requires url:parse
 * @returns  {Function}          Returns the callback with an error if the
 *                              http code is higher or equal 400, or it returns
 *                              the percentage for the dependency
 *
 */
function getPercentageProject(repo, callback)
{
  repo = parse(repo).pathname.split('/')

  const user = repo[repo.length-2]
  repo = basename(repo[repo.length-1], '.git')

  get(COVERALL_IO+'/'+user+'/'+repo+'.json',
  function(res)
  {
    if(res.statusCode >= 400) return callback(null, 0)

    res.on('error', callback)

    res.pipe(concat(function(body)
    {
      body = JSON.parse(body)
      if(!body) return callback(null, 0)

      callback(null, body.covered_percent/100)  // Per-unit to easier calcs
    }))
  })
}

function getPercentageDependencies(dependencies, callback)
{
  if(!dependencies) return callback(null, 1)

  const keys = Object.keys(dependencies)
  if(!keys.length) return callback(null, 1)

  async.map(dependencies, function(dependency, callback)
  {
    if(typeof dependency === 'string') return callback(null, 1)

    calcPercentage(dependency, callback)
  },
  function(error, results)
  {
    if(error) return callback(error)

    const covered = keys.reduce(function(prev, key)
    {
      return prev + (results[key].covered_combined || 0)
    }, 0)

    callback(null, covered / keys.length)
  })
}

function calcPercentage(module, callback)
{
  async.parallel({
    module:       getPercentageProject     .bind(null, module.repository.url),
    dependencies: getPercentageDependencies.bind(null, module.dependencies)
  },
  function(error, result)
  {
    if(error) return callback(error)

    module.covered          = result.module
    module.covered_combined = result.module * result.dependencies

    callback(null, module)
  })
}

function coverdeeps(moduleName, callback)
{
  RemoteLS({development: false}).ls(moduleName, 'latest', function(tree) {
    if(!tree) return callback(new Error(moduleName+' not found on NPM registry'))

    calcPercentage(tree, callback)
  });
}

module.exports = coverdeeps
<|endoftext|>


<commit_before>var path = require('path');
var chain = require('stack-chain');
var _ = require('lodash');

var currentFilter = null;
var cucumberPath = path.join(__dirname, '..');

function isFrameInCucumber(frame) {
  var fileName = frame.getFileName() || '';
  return fileName.indexOf(cucumberPath) !== -1;
}

function filter() {
  currentFilter = chain.filter.attach(function (error, frames) {
    if (isFrameInCucumber(frames[0])) {
      return frames;
    }
    return frames.filter(_.negate(isFrameInCucumber));
  });
}

function unfilter() {
  chain.filter.deattach(currentFilter);
}

module.exports = {
  filter: filter,
  unfilter: unfilter
};
<commit_msg>prevent error when stack trace has no frames<commit_after>var path = require('path');
var chain = require('stack-chain');
var _ = require('lodash');

var currentFilter = null;
var cucumberPath = path.join(__dirname, '..');

function isFrameInCucumber(frame) {
  var fileName = frame.getFileName() || '';
  return fileName.indexOf(cucumberPath) !== -1;
}

function filter() {
  currentFilter = chain.filter.attach(function (error, frames) {
    if (frames.length > 0 && isFrameInCucumber(frames[0])) {
      return frames;
    }
    return frames.filter(_.negate(isFrameInCucumber));
  });
}

function unfilter() {
  chain.filter.deattach(currentFilter);
}

module.exports = {
  filter: filter,
  unfilter: unfilter
};
<|endoftext|>


<commit_before>(function() {
    'use strict';

    var MailChimpWebhook = require('mailchimp').MailChimpWebhook;
    var CapsuleCRM = require('capsule-crm');

    var config = require('./config');

    var webhook = new MailChimpWebhook(config.webhook);
    var capsule = CapsuleCRM.createConnection(config.capsule.account, config.capsule.token);

    console.log('UCN Hooks server listening on port ' + config.webhook.port + '...');

    var _extractSegments = function(data) {
        var segments = [];
        data.merges.GROUPINGS.forEach(function(grouping) {
            console.log('grouping', grouping);
            if (grouping.groups) {
                var groups = grouping.groups.split(',');
                groups.forEach(function(group) {
                    segments.push(group.trim());
                });
            }
        });
        console.log('segments', segments);
        return segments;
    };

    var _segmentsToFields = function(segments, tag_name) {
        var fields = [];
        config.capsule.datatags[tag_name].forEach(function(tag_label) {
            var field = {
                tag: tag_name,
                label: tag_label
            };
            if (segments.indexOf(tag_label) >= 0) {
                field.boolean = true;
            }
            fields.push(field);
        });
        console.log('fields', fields);
        return fields;
    };

    webhook.on('error', function (error) {
        console.log('error', error);
    });

    webhook.on('subscribe', function (data, meta) {
        var mailing_list_id = data.list_id;
        console.log(data.email + ' subscribed to your newsletter!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);

        capsule.personByEmail(data.email, function(err, data) {
            console.log('personByEmail err', err);
            console.log('personByEmail data', data);
            if (typeof data.parties.person !== 'undefined' && data.parties.person.id) {
                var person_id = data.parties.person.id;
                var mailing_list = config.mailchimp.lists[mailing_list_id];

                var note = { historyItem: { note: 'Contact has subscribed to mailing list ' + mailing_list.name } };
                capsule.addHistoryFor('party', person_id, note, function(err, data) {
                    console.log('addHistoryFor err', err);
                    console.log('addHistoryFor data', data);
                });

                var tag_name = mailing_list.tag;
                if (tag_name && config.capsule.datatags[tag_name]) {
                    var tags = { customFields: { customField: _segmentsToFields(_extractSegments(data), tag_name) } };
                    console.log('tags', tags);
                    capsule.setCustomFieldFor('party', person_id, tags, function(err, data) {
                        console.log('setCustomFieldFor err', err);
                        console.log('setCustomFieldFor data', data);
                        capsule.setPartyTag(person_id, tag_name, function(err, data) {
                            console.log('setPartyTag err', err);
                            console.log('setPartyTag data', data);
                        });
                    });
                }
            }
        });

    });
    webhook.on('unsubscribe', function (data, meta) {
        console.log(data.email + ' unsubscribed from your newsletter!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });

    webhook.on('profile', function (data, meta) {
        console.log(data.email + ' updated his profile!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });
    webhook.on('upemail', function (data, meta) {
        console.log(data.email + ' updated his email address!');
        console.log('data', data);
        console.log('meta', meta);
    });
    webhook.on('cleaned', function (data, meta) {
        console.log(data.email + ' has been cleaned from your newsletter!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });

    webhook.on('campaign', function (data, meta) {
        console.log('status of campaign \'' + data.subject + '\' has been changed!');
        console.log('data', data);
        console.log('meta', meta);
    });
})();
<commit_msg>More webhook data fixes [#113206659]<commit_after>(function() {
    'use strict';

    var MailChimpWebhook = require('mailchimp').MailChimpWebhook;
    var CapsuleCRM = require('capsule-crm');

    var config = require('./config');

    var webhook = new MailChimpWebhook(config.webhook);
    var capsule = CapsuleCRM.createConnection(config.capsule.account, config.capsule.token);

    console.log('UCN Hooks server listening on port ' + config.webhook.port + '...');

    var _extractSegments = function(data) {
        var segments = [];
        data.merges.GROUPINGS.forEach(function(grouping) {
            console.log('grouping', grouping);
            if (grouping.groups) {
                var groups = grouping.groups.split(',');
                groups.forEach(function(group) {
                    segments.push(group.trim());
                });
            }
        });
        console.log('segments', segments);
        return segments;
    };

    var _segmentsToFields = function(segments, tag_name) {
        var fields = [];
        config.capsule.datatags[tag_name].forEach(function(tag_label) {
            var field = {
                tag: tag_name,
                label: tag_label
            };
            if (segments.indexOf(tag_label) >= 0) {
                field.boolean = true;
            }
            fields.push(field);
        });
        console.log('fields', fields);
        return fields;
    };

    webhook.on('error', function (error) {
        console.log('error', error);
    });

    webhook.on('subscribe', function (data, meta) {
        var webhook_data = data;
        console.log(webhook_data.email + ' subscribed to your newsletter!');
        console.log('webhook_data', webhook_data);
        console.log('GROUPINGS', webhook_data.merges.GROUPINGS);
        console.log('meta', meta);

        capsule.personByEmail(data.email, function(err, data) {
            console.log('personByEmail err', err);
            console.log('personByEmail data', data);
            if (typeof data.parties.person !== 'undefined' && data.parties.person.id) {
                var person_id = data.parties.person.id;
                var mailing_list = config.mailchimp.lists[webhook_data.list_id];

                var note = { historyItem: { note: 'Contact has subscribed to mailing list ' + mailing_list.name } };
                capsule.addHistoryFor('party', person_id, note, function(err, data) {
                    console.log('addHistoryFor err', err);
                    console.log('addHistoryFor data', data);
                });

                var tag_name = mailing_list.tag;
                if (tag_name && config.capsule.datatags[tag_name]) {
                    var tags = { customFields: { customField: _segmentsToFields(_extractSegments(webhook_data), tag_name) } };
                    console.log('tags', tags);
                    capsule.setCustomFieldFor('party', person_id, tags, function(err, data) {
                        console.log('setCustomFieldFor err', err);
                        console.log('setCustomFieldFor data', data);
                        capsule.setPartyTag(person_id, tag_name, function(err, data) {
                            console.log('setPartyTag err', err);
                            console.log('setPartyTag data', data);
                        });
                    });
                }
            }
        });

    });
    webhook.on('unsubscribe', function (data, meta) {
        console.log(data.email + ' unsubscribed from your newsletter!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });

    webhook.on('profile', function (data, meta) {
        console.log(data.email + ' updated his profile!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });
    webhook.on('upemail', function (data, meta) {
        console.log(data.email + ' updated his email address!');
        console.log('data', data);
        console.log('meta', meta);
    });
    webhook.on('cleaned', function (data, meta) {
        console.log(data.email + ' has been cleaned from your newsletter!');
        console.log('data', data);
        console.log('GROUPINGS', data.merges.GROUPINGS);
        console.log('meta', meta);
    });

    webhook.on('campaign', function (data, meta) {
        console.log('status of campaign \'' + data.subject + '\' has been changed!');
        console.log('data', data);
        console.log('meta', meta);
    });
})();
<|endoftext|>


<commit_before>/**
 * the function to convert the from into json
 * @returns {{string: string}} - the from converted to json
 */
function jsonifyForm () {
    var form = {}
    $.each($('form').serializeArray(), function (i, field) {
        form[field.name] = field.value || ''
    })
    return form
}

/**
 * the function to run the error modal
 * @param htmlMsg {string} - the message to display, you can put html in it
 */
function runModal (htmlMsg) {
    $('#error-modal-message').html(htmlMsg)
    $('#error-modal').modal()
}

function doAjax (url, extension) {
    var form = jsonifyForm()
    $.extend(form, {file_extension: extension})
    $.ajax({
            type: 'POST',
            url: url,
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            data: JSON.stringify(form),
            complete: function (response) {
                $('#dendrogram-result').html(response['responseJSON']['dendroDiv'])
            },
            error: function (jqXHR, textStatus, errorThrown) {
                runModal('backend fail to plot the dendrogram.')
            }
        }
    )
}

/**
 * the error message for the submission
 * @returns {string | null} - if it is null, it means no error, else then the string is the error message
 */
function submissionError () {
    const err = 'A dendrogram requires at least 2 active documents to be created.'
    const activeFiles = $('#num_active_files').val()
    if (activeFiles < 2)
        return err
    else
        return null
}

/**
 * When the HTML documents finish loading
 */
$(document).ready(function () {

    /**
     * the events after dendrogram is clicked
     */
    $('#getdendro').on('click', function () {
        const error = submissionError()  // the error happens during submission

        if (error === null) {  // if there is no error
            doAjax('/dendrogramDiv')
        }
        else {
            runModal(error)
        }

    })

    /**
     * The events after any download button is clicked
     */
    $('#dendroPDFdownload, #dendroSVGdownload, #dendroPNGdownload').on('click', function () {

        const error = submissionError()  // the error happens during submission
        const fileExtension = $(this).attr('data-file-extension')  // the file extension

        if (error === null) { // if there is no error
            doAjax('/dendrogramDownload', fileExtension)
        }
        else {
            runModal(error)
        }
    })

})
<commit_msg>add documentation<commit_after>/**
 * the function to convert the from into json
 * @returns {{string: string}} - the from converted to json
 */
function jsonifyForm () {
    var form = {}
    $.each($('form').serializeArray(), function (i, field) {
        form[field.name] = field.value || ''
    })
    return form
}

/**
 * the function to run the error modal
 * @param htmlMsg {string} - the message to display, you can put html in it
 */
function runModal (htmlMsg) {
    $('#error-modal-message').html(htmlMsg)
    $('#error-modal').modal()
}

/**
 * the function to do ajax in dendrogram
 * @param url {string} - the url to do post
 * @param extension {string | null} - used to download dendrogram, to specify the file type to download. if unused, this will be null
 */
function doAjax (url, extension) {
    var form = jsonifyForm()
    $.extend(form, {file_extension: extension})
    $.ajax({
            type: 'POST',
            url: url,
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            data: JSON.stringify(form),
            complete: function (response) {
                $('#dendrogram-result').html(response['responseJSON']['dendroDiv'])
            },
            error: function (jqXHR, textStatus, errorThrown) {
                runModal('backend fail to plot the dendrogram.')
            }
        }
    )
}

/**
 * the error message for the submission
 * @returns {string | null} - if it is null, it means no error, else then the string is the error message
 */
function submissionError () {
    const err = 'A dendrogram requires at least 2 active documents to be created.'
    const activeFiles = $('#num_active_files').val()
    if (activeFiles < 2)
        return err
    else
        return null
}

/**
 * When the HTML documents finish loading
 */
$(document).ready(function () {

    /**
     * the events after dendrogram is clicked
     */
    $('#getdendro').on('click', function () {
        const error = submissionError()  // the error happens during submission

        if (error === null) {  // if there is no error
            doAjax('/dendrogramDiv', null)
        }
        else {
            runModal(error)
        }

    })

    /**
     * The events after any download button is clicked
     */
    $('#dendroPDFdownload, #dendroSVGdownload, #dendroPNGdownload').on('click', function () {

        const error = submissionError()  // the error happens during submission
        const fileExtension = $(this).attr('data-file-extension')  // the file extension

        if (error === null) { // if there is no error
            doAjax('/dendrogramDownload', fileExtension)
        }
        else {
            runModal(error)
        }
    })

})
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var port = process.env.PORT || 3001;

app.use(bodyParser.json());

app.post('', function(request, response) {
  response.writeHead(200, { 'Content-Type': 'application/json' });
  console.log("### POST ###");
  const body = request.body;
  console.log("### BODY ### %s", JSON.stringify(body));
  response.end(JSON.stringify(body));
});

var server = app.listen(port, function() {
  console.log("Server it's up and running at http://localhost:" + port);
})
<commit_msg>no debug comments<commit_after>'use strict';

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var port = process.env.PORT || 3001;

app.use(bodyParser.json());

app.post('', function(request, response) {
  response.writeHead(200, { 'Content-Type': 'application/json' });
  const body = request.body;
  response.end(JSON.stringify(body));
});

var server = app.listen(port, function() {
  console.log("Server it's up and running at http://localhost:" + port);
})
<|endoftext|>


<commit_before><commit_msg>MOB-297 Removed obsolete tests and added new test to check for network connection based on the offline event instead.<commit_after><|endoftext|>


<commit_before>(function() {
    angular
        .module("spidey")
        .controller("SpideyPaginationController", [
            "$location",
            "$scope",
            SpideyPaginationController
        ]);

    function SpideyPaginationController($location, $scope) {
        var self = this;

        self.pages = [];
        self.current_page = $scope.page;

        self.can_go_prev = function() {
            return true;
        };

        self.can_go_next = function() {
            return true;
        };

        self.go_prev = function() {
            console.log("going prev");
        };

        self.go_next = function() {
            console.log("going next");
        };

        self.go_to = function(page_href) {
            $location.url(page_href);
        };

        self.is_active = function(page_index) {
            return (page_index == self.current_page);
        };

        (function init() {
            self.pages[Math.ceil($scope.totalElements/$scope.elementsPerPage)] = {};

            self.pages = _.map(self.pages, function(__, key) {
                return {
                    "index": key+1,
                    "href": $scope.hrefMoc.replace("*", key+1)
                };
            });
        })();

        console.log($scope);
    }
})();
<commit_msg>pagination ok<commit_after>(function() {
    angular
        .module("spidey")
        .controller("SpideyPaginationController", [
            "$location",
            "$scope",
            SpideyPaginationController
        ]);

    function SpideyPaginationController($location, $scope) {
        var self = this;

        self.pages = [];
        self.current_page = parseInt($scope.page);

        self.can_go_prev = function() {
            return (self.current_page > 1);
        };

        self.can_go_next = function() {
            return (self.current_page < Math.ceil($scope.totalElements/$scope.elementsPerPage));
        };

        self.go_prev = function() {
            if (self.can_go_prev())
                $location.url($scope.hrefMoc.replace("*", self.current_page-1));
        };

        self.go_next = function() {
            if (self.can_go_next())
                $location.url($scope.hrefMoc.replace("*", self.current_page+1));
        };

        self.go_to = function(page_href) {
            $location.url(page_href);
        };

        self.is_active = function(page_index) {
            return (page_index == self.current_page);
        };

        (function init() {
            var max_per_view = 5;
            var min = 3;
            var max = Math.ceil($scope.totalElements/$scope.elementsPerPage);
            var offset = 2;

            if (self.current_page <= min) {
                for (var i = 1; i <= max_per_view; i++) {
                    self.pages.push({
                        "index": i,
                        "href": $scope.hrefMoc.replace("*", i)
                    });
                }
            } else if (self.current_page >= (max-offset)) {
                for (var i = max; i > (max-max_per_view); i--) {
                    self.pages.unshift({
                        "index": i,
                        "href": $scope.hrefMoc.replace("*", i)
                    });
                }
            } else {
                var temp = [];

                for (var i = (self.current_page-offset); i <= (self.current_page+offset); i++) {
                    temp.push({
                        "index": i,
                        "href": $scope.hrefMoc.replace("*", i)
                    });
                }

                self.pages = _.sortBy(temp, function(page) {
                    return page.index;
                });

                temp = null;
            }
        })();
    }
})();
<|endoftext|>


<commit_before>Handlebars.registerHelper('ifIsNull', function (value, options) {
  if (value === null) {
    return options.fn(this);
  } else {
    return options.inverse(this);
  }
});

Handlebars.registerHelper('formatDate', function (value) {
  var localFormat = i18n.getDateFormat();
  return moment(value, facebook.fbDateFormats).format("HH:mm " + localFormat);
});

Handlebars.registerHelper('trans', function (value) {
  return i18n.translate(value);
});

/**
 * Convert new line (\n\r) to

 * from http://phpjs.org/functions/nl2br:480
 */
// https://github.com/danharper/Handlebars-Helpers/blob/master/helpers.js
Handlebars.registerHelper('nl2br', function(text) {
  var nl2br = (text + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
  return new Handlebars.SafeString(nl2br);
});

$helpers = (function () {
  var isScrolledIntoView = function (selector, fully) {
    // http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(selector).offset().top;
    var elemBottom = elemTop + $(selector).height();

    var isVisible = (elemBottom <= docViewBottom) && (elemTop >= docViewTop);
    if (fully) {
      return isVisible = isVisible && (elemBottom >= docViewTop) && (elemTop <= docViewBottom);
    }
    return isVisible;
  }

  var scrollTo = function (selector) {
    $('html, body').animate({
      scrollTop: $(selector).offset().top
    }, 500);
  }

  var scrollToIfHidden = function (selector, partially, destinationSelector) {
    if (!isScrolledIntoView(selector, partially)) {
      scrollTo(destinationSelector);
    }
  }

  var forceAllToSameHeight = function (selector) {
    var heights = [];
    $(selector).each(function () {
      heights.push($(this).height());
    });
    var maxHeight = _.max(heights);
    $(selector).css("height", maxHeight);
  }

  return {
    scrollTo: scrollTo,
    scrollToIfHidden: scrollToIfHidden,
    forceAllToSameHeight: forceAllToSameHeight
  };
})();
<commit_msg>forceAllToSameHeight only when step-fluid is inline-block<commit_after>Handlebars.registerHelper('ifIsNull', function (value, options) {
  if (value === null) {
    return options.fn(this);
  } else {
    return options.inverse(this);
  }
});

Handlebars.registerHelper('formatDate', function (value) {
  var localFormat = i18n.getDateFormat();
  return moment(value, facebook.fbDateFormats).format("HH:mm " + localFormat);
});

Handlebars.registerHelper('trans', function (value) {
  return i18n.translate(value);
});

/**
 * Convert new line (\n\r) to

 * from http://phpjs.org/functions/nl2br:480
 */
// https://github.com/danharper/Handlebars-Helpers/blob/master/helpers.js
Handlebars.registerHelper('nl2br', function(text) {
  var nl2br = (text + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
  return new Handlebars.SafeString(nl2br);
});

$helpers = (function () {
  var isScrolledIntoView = function (selector, fully) {
    // http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(selector).offset().top;
    var elemBottom = elemTop + $(selector).height();

    var isVisible = (elemBottom <= docViewBottom) && (elemTop >= docViewTop);
    if (fully) {
      return isVisible = isVisible && (elemBottom >= docViewTop) && (elemTop <= docViewBottom);
    }
    return isVisible;
  }

  var scrollTo = function (selector) {
    $('html, body').animate({
      scrollTop: $(selector).offset().top
    }, 500);
  }

  var scrollToIfHidden = function (selector, partially, destinationSelector) {
    if (!isScrolledIntoView(selector, partially)) {
      scrollTo(destinationSelector);
    }
  }

  var forceAllToSameHeight = function (selector) {
    if ($(".step-fluid").css("display") === "inline-block") {
      var heights = [];
      $(selector).each(function () {
        heights.push($(this).height());
      });
      var maxHeight = _.max(heights);
      $(selector).css("height", maxHeight);
    }
  }

  return {
    scrollTo: scrollTo,
    scrollToIfHidden: scrollToIfHidden,
    forceAllToSameHeight: forceAllToSameHeight
  };
})();
<|endoftext|>