<commit_before>var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');
var fs = require('fs');
var escodegen = require('escodegen');
var glob = require('glob');
var _ = require('lodash');
var mkdirp = require('mkdirp');
var strUtils = require('./string-utils');

// TODO: generator arguments everywhere should be optional. A better way to handle this could be to have a "Global" variable

promptModuleName = {
  type: 'string',
  name: 'moduleName',
  optional: false,
  message: 'What\'s the module\'s name?'
};
promptAppName = {
  type: 'string',
  name: 'appName',
  optional: false,
  message: 'What\'s the app\'s name?'
};

module.exports = {

  // this var has de purpose of persist data during the execution of several generators in a row
  // For example the module generator, executes controller and view before and would need their routes on its template
  contextData: {},
  base: undefined,

  welcome: function() {
    this.log(yosay(
      'Welcome to the jungle and have fun with the ' + chalk.red('generator-angular-scalable') + ' generator!'
    ));
  },

  setGenerator: function (generator) {
    this.generator = generator;
  },

  generateStyles: function () {
    var foldersToCreate = ['styles/auto-imports'];
    this.copyAndReplaceFileNames('../../stylesheet/templates/**/*', null, foldersToCreate);
    this.updateIncludeSourceGrunt(this.lastWrittenFolder);
  },

  updateIncludeSourceGrunt: function (lastWrittenFolder) {
    // gets the last style file name edited
    var styleFileName = this.lastFileNamesEdited.filter(function (a) {return a.indexOf('scss') !== -1});
    // get the variable
    var gruntTree = this.generator.gruntfile.gruntfile;

    // if doesn't exist, create it
    if(gruntTree.var("includeSourceFiles").value().length === 0) gruntTree.body.append('var includeSourceFiles = {}');

    // write the variable in the tree with the new style path
    var includeSourceFiles = gruntTree.var("includeSourceFiles").value();
    // style path to variable
    includeSourceFiles.key("'"+lastWrittenFolder+styleFileName+"'").value('"'+lastWrittenFolder+styleFileName+'"');
    // insert the variable content
    this.generator.gruntfile.insertVariable("includeSourceFiles", escodegen.generate(includeSourceFiles.node));

    // write the gruntfile
    fs.writeFileSync('Gruntfile.js', this.generator.gruntfile.toString());
  },

  calculateBase: function () {
    return 'app/' + (this.generator.props.isCommon ? 'common/' : 'components/') + strUtils.dasherize(this.generator.props.moduleName);
  },

  createBasicContextData: function () {
    var self = this;
    return {appName: self.generator.config.get('appName'),
            moduleName: self.generator.props.moduleName,
            componentName: self.generator.props.componentName};
  },

  copyAndReplaceFileNames: function (templatePath, destinationPath, foldersToCreate, extraContextData) {

    var self = this;
    var filesAndNewNameToReplace;

    // paths calculation
    this.base = this.base || this.calculateBase();
    filesAndNewNameToReplace = this.getFilesWithNewNamesAndUpdateContext(templatePath);
    destinationPath = this.generator.destinationPath(destinationPath || this.base);

    // context data
    contextData = this.createBasicContextData();
    _.extend(contextData, extraContextData);
    if( !this.contextData.viewUrl ) {
      this.contextData.viewUrl = filesAndNewNameToReplace.filter(function(a){return a.to.indexOf('view.html') !== -1})[0];
      if( this.contextData.viewUrl ) this.contextData.viewUrl = this.contextData.viewUrl.to;
    } else contextData.viewUrl = this.contextData.viewUrl;

    // template generation
    this.generator.template (
      this.generator.templatePath(templatePath),
      destinationPath,
      contextData
    ).on('end', function () {
      self.replaceFileNames(filesAndNewNameToReplace);
    });

    // folder creation
    if ( foldersToCreate ) foldersToCreate.forEach(function (folder) { mkdirp.sync(destinationPath + '/' + folder); });

    // updates context
    this.lastWrittenFolder = destinationPath;

    return destinationPath;

  },

  replaceFileNames: function (filesAndNewName) {
    filesAndNewName.forEach(function (file) {
      fs.rename(file.from, file.to);
    });
  },

  getFilesWithNewNamesAndUpdateContext: function (templatePath) {
    var self = this;
    this.lastFileNamesEdited = [];
    var filesAndNewName = [];

    glob.sync(this.generator.templatePath(templatePath)).forEach(function (file) {
      var lastUrlPart = file.substr(file.indexOf('templates') + 'templates'.length);
      var fileToReplace = self.generator.destinationPath(self.base) + lastUrlPart;
      // replaces fileName content inside %%
      var fileReplaced = fileToReplace.replace(/%.*%/g, function (a) {
        var toReplace = _.camelCase(a.substr(1, a.length - 2));
        return strUtils.dasherize(self.generator.config.get(toReplace) || self.generator.props[toReplace]);
      });
      filesAndNewName.push({from: fileToReplace, to: fileReplaced});
      // updates context
      self.lastFileNamesEdited.push(fileReplaced);
    });

    return filesAndNewName;
  },

  replaceCopiedFiles: function (templatePath) {
    this.replaceFileNames(this.getFilesWithNewNamesAndUpdateContext(templatePath));
  },

  subModuleWritting: function(extraContextData, foldersToCreate) {

    var self = this;
    var destinationPath;

    contextData = this.createBasicContextData();
    this.base = this.base || this.calculateBase();

    function copyTemplate() {
      _.extend(contextData, extraContextData);
      return self.copyAndReplaceFileNames('**/*', null, foldersToCreate, contextData);
    };

    //exec

    // if the module subgenerator is being runned, it's not needed to check if the path exists, because the main module files will be created anyways
    if(this.generator.templatePath().indexOf('module') !== -1) copyTemplate(this.generator);
    else {

      try {// if the path doesn't exists, it needs basic module configuration
        var fsBasePath = fs.lstatSync(this.base);
      } catch (err) {
        destinationPath = self.copyAndReplaceFileNames('../../module/templates/*', null, foldersToCreate);
      } finally {
        destinationPath = copyTemplate(this.generator);
      }

    }

    return destinationPath;

  },

  createBasicSubPrompts: function () {
    var prompts = [];
    if (!this.props || !this.props.isCommon) {
      prompts.push({
        type: 'confirm',
        name: 'isCommon',
        message: 'Is it a common module?',
        default: false
      });
    }
    if (!this.props || !this.props.componentName) {
      prompts.push({
        type: 'string',
        name: 'componentName',
        message: 'What\'s the name of this component?',
        optional: false,
      });
    }
    if (!this.props || !this.props.moduleName) prompts.push(promptModuleName);

    if(!this.config.get('appName')) {
      prompts.unshift(promptAppName);
    }

    return prompts;
  },
  saveAppName: function(appName) {
    this.config.set('appName', appName);
  },
  promptModuleName: promptModuleName,
  promptAppName: promptAppName
};
<commit_msg>fix(styles): Inclusion on gruntfiles var<commit_after>var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');
var fs = require('fs');
var escodegen = require('escodegen');
var glob = require('glob');
var _ = require('lodash');
var mkdirp = require('mkdirp');
var strUtils = require('./string-utils');

// TODO: generator arguments everywhere should be optional. A better way to handle this could be to have a "Global" variable

promptModuleName = {
  type: 'string',
  name: 'moduleName',
  optional: false,
  message: 'What\'s the module\'s name?'
};
promptAppName = {
  type: 'string',
  name: 'appName',
  optional: false,
  message: 'What\'s the app\'s name?'
};

module.exports = {

  // this var has de purpose of persist data during the execution of several generators in a row
  // For example the module generator, executes controller and view before and would need their routes on its template
  contextData: {},
  base: undefined,

  welcome: function() {
    this.log(yosay(
      'Welcome to the jungle and have fun with the ' + chalk.red('generator-angular-scalable') + ' generator!'
    ));
  },

  setGenerator: function (generator) {
    this.generator = generator;
  },

  generateStyles: function () {
    var foldersToCreate = ['styles/auto-imports'];
    this.copyAndReplaceFileNames('../../stylesheet/templates/**/*', null, foldersToCreate);
    this.updateIncludeSourceGrunt();
  },

  updateIncludeSourceGrunt: function () {
    // gets the last style file name edited
    var styleFileName = this.lastFileNamesEdited.filter(function (a) {return a.indexOf('scss') !== -1})[0];
    styleFileName = styleFileName.substring(styleFileName.indexOf('app'));

    // get the variable
    var gruntTree = this.generator.gruntfile.gruntfile;

    // if doesn't exist, create it
    if(gruntTree.var("includeSourceFiles").value().length === 0) gruntTree.body.append('var includeSourceFiles = {}');

    // write the variable in the tree with the new style path
    var includeSourceFiles = gruntTree.var("includeSourceFiles").value();
    // style path to variable
    includeSourceFiles.key("'"+styleFileName+"'").value('"'+styleFileName+'"');
    // insert the variable content
    this.generator.gruntfile.insertVariable("includeSourceFiles", escodegen.generate(includeSourceFiles.node));

    // write the gruntfile
    fs.writeFileSync('Gruntfile.js', this.generator.gruntfile.toString());
  },

  calculateBase: function () {
    return 'app/' + (this.generator.props.isCommon ? 'common/' : 'components/') + strUtils.dasherize(this.generator.props.moduleName);
  },

  createBasicContextData: function () {
    var self = this;
    return {appName: self.generator.config.get('appName'),
            moduleName: self.generator.props.moduleName,
            componentName: self.generator.props.componentName};
  },

  copyAndReplaceFileNames: function (templatePath, destinationPath, foldersToCreate, extraContextData) {

    var self = this;
    var filesAndNewNameToReplace;

    // paths calculation
    this.base = this.base || this.calculateBase();
    filesAndNewNameToReplace = this.getFilesWithNewNamesAndUpdateContext(templatePath);
    destinationPath = this.generator.destinationPath(destinationPath || this.base);

    // context data
    contextData = this.createBasicContextData();
    _.extend(contextData, extraContextData);
    if( !this.contextData.viewUrl ) {
      this.contextData.viewUrl = filesAndNewNameToReplace.filter(function(a){return a.to.indexOf('view.html') !== -1})[0];
      if( this.contextData.viewUrl ) this.contextData.viewUrl = this.contextData.viewUrl.to;
    } else contextData.viewUrl = this.contextData.viewUrl;

    // template generation
    this.generator.template (
      this.generator.templatePath(templatePath),
      destinationPath,
      contextData
    ).on('end', function () {
      self.replaceFileNames(filesAndNewNameToReplace);
    });

    // folder creation
    if ( foldersToCreate ) foldersToCreate.forEach(function (folder) { mkdirp.sync(destinationPath + '/' + folder); });

    // updates context
    this.lastWrittenFolder = destinationPath;

    return destinationPath;

  },

  replaceFileNames: function (filesAndNewName) {
    filesAndNewName.forEach(function (file) {
      fs.rename(file.from, file.to);
    });
  },

  getFilesWithNewNamesAndUpdateContext: function (templatePath) {
    var self = this;
    this.lastFileNamesEdited = [];
    var filesAndNewName = [];

    glob.sync(this.generator.templatePath(templatePath)).forEach(function (file) {
      var lastUrlPart = file.substr(file.indexOf('templates') + 'templates'.length);
      var fileToReplace = self.generator.destinationPath(self.base) + lastUrlPart;
      // replaces fileName content inside %%
      var fileReplaced = fileToReplace.replace(/%.*%/g, function (a) {
        var toReplace = _.camelCase(a.substr(1, a.length - 2));
        return strUtils.dasherize(self.generator.config.get(toReplace) || self.generator.props[toReplace]);
      });
      filesAndNewName.push({from: fileToReplace, to: fileReplaced});
      // updates context
      self.lastFileNamesEdited.push(fileReplaced);
    });

    return filesAndNewName;
  },

  replaceCopiedFiles: function (templatePath) {
    this.replaceFileNames(this.getFilesWithNewNamesAndUpdateContext(templatePath));
  },

  subModuleWritting: function(extraContextData, foldersToCreate) {

    var self = this;
    var destinationPath;

    contextData = this.createBasicContextData();
    this.base = this.base || this.calculateBase();

    function copyTemplate() {
      _.extend(contextData, extraContextData);
      return self.copyAndReplaceFileNames('**/*', null, foldersToCreate, contextData);
    };

    //exec

    // if the module subgenerator is being runned, it's not needed to check if the path exists, because the main module files will be created anyways
    if(this.generator.templatePath().indexOf('module') !== -1) copyTemplate(this.generator);
    else {

      try {// if the path doesn't exists, it needs basic module configuration
        var fsBasePath = fs.lstatSync(this.base);
      } catch (err) {
        destinationPath = self.copyAndReplaceFileNames('../../module/templates/*', null, foldersToCreate);
      } finally {
        destinationPath = copyTemplate(this.generator);
      }

    }

    return destinationPath;

  },

  createBasicSubPrompts: function () {
    var prompts = [];
    if (!this.props || !this.props.isCommon) {
      prompts.push({
        type: 'confirm',
        name: 'isCommon',
        message: 'Is it a common module?',
        default: false
      });
    }
    if (!this.props || !this.props.componentName) {
      prompts.push({
        type: 'string',
        name: 'componentName',
        message: 'What\'s the name of this component?',
        optional: false,
      });
    }
    if (!this.props || !this.props.moduleName) prompts.push(promptModuleName);

    if(!this.config.get('appName')) {
      prompts.unshift(promptAppName);
    }

    return prompts;
  },
  saveAppName: function(appName) {
    this.config.set('appName', appName);
  },
  promptModuleName: promptModuleName,
  promptAppName: promptAppName
};
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const _ = require('lodash')
const beautify = require('js-beautify').js_beautify;
const jsBeautifyOptions = { indent_size: 2, preserve_newlines: false, end_with_newline: true };

// Defining Markers
exports.COMPONENT_MARKER = '// Add new components above';
exports.SERVICE_MARKER = '// Add new services above';
exports.PAGE_MARKER = '// Add new pages above';
exports.DIRECTIVE_MARKER = '// Add new directives above';

exports.COMPONENT_NESTED_MARKER = '// Add new nested components above';
exports.SERVICE_NESTED_MARKER = '// Add new nested services above';
exports.DIRECTIVE_NESTED_MARKER = '// Add new nested directives above';

exports.IMPORT_MODULE_MARKER = '// Add module imports above';
exports.IMPORT_STYLE_MARKER = '// Add style imports above';
exports.IMPORT_DIRECTIVE_MARKER = '// Add directive imports above';
exports.IMPORT_SERVICE_MARKER = '// Add service imports above';
exports.IMPORT_DEPENDENCY_MARKER = '// Add module dependencies above';

exports.ADD_DIRECTIVE_TOMODULE_MARKER = '// Add directive to module above';
exports.ADD_SERVICE_TOMODULE_MARKER = '// Add service to module above';

exports.MAIN_SCSS_MARKER = '// Add Main SCSS Above';
exports.ROUTE_MARKER = '// Add new routes above';
exports.STATE_MARKER = '// Add new states above';

exports.DOCS_ASSETS_PATH = '/docs/docs-assets';
exports.DOCS_STORAGE_FILENAME = 'docs.js';

// Defining utility functions

/*
 * writes a line to a file before a marker
 * takes as inputs the file name, line to add, marker, and full path
 */
exports.addToFile = function(filename,lineToAdd,beforeMarker,fullpathI){
    try {
        let fullPath = path.resolve(fullpathI,filename);
        let fileSrc = fs.readFileSync(fullPath,'utf8');

        let indexOf = fileSrc.indexOf(beforeMarker);
        let lineStart = fileSrc.substring(0,indexOf).lastIndexOf('\n') + 1;
        let indent = fileSrc.substring(lineStart,indexOf);
        fileSrc = fileSrc.substring(0,indexOf) + lineToAdd + "\n" + indent + fileSrc.substring(indexOf);

        fs.writeFileSync(fullPath,fileSrc);
        // console.log('Written data to files');
    } catch(e) {
      console.log('Could not write data to files');
      throw e;
    }
};

exports.removeLineFromFile = function(filename,lineToRemove, fullpathI, indent, fullLine){
    try {
        let fullPath = path.resolve(fullpathI,filename);
        let fileSrc = fs.readFileSync(fullPath,'utf8');
        let indexOf = fileSrc.indexOf(lineToRemove);
        if(indexOf===-1){
          throw new Error('line not found');
        }
        let topHalf = fileSrc.substring(0,indexOf);
        topHalf = topHalf.substring(0, topHalf.lastIndexOf('\n'))
        let bottomHalf = fileSrc.substring(indexOf);
        fileSrc = topHalf + bottomHalf.substring(bottomHalf.indexOf('\n'));
        // fileSrc = beautify(fileSrc, jsBeautifyOptions);
        fs.writeFileSync(fullPath,fileSrc);
        // console.log('Written data to files');
    } catch(e) {
      console.log('Could not remove data from files');
      throw e;
    }
};

/*
 * checks if a given path exists synchronously
 */
exports.existsSync = function(path){
  return fs.existsSync(path);
};

exports.isHasPackage = function (obj) {
    return _.isObject(obj) && obj.package && obj.import !== false;
}

exports.stripPackageName = function (pkgName) {
    let regexp = /(.*?)@/;
    let match = pkgName.match(regexp);
    if (match) {
        return match[1];
    }
    return pkgName;
}

exports.deleteDirRecursive = function(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).forEach(function(file, index) {
      var curPath = path + "/" + file;
      if (fs.lstatSync(curPath).isDirectory()) { // recurse
        exports.deleteDirRecursive(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }else{
    console.log("invalid path: " + path);
    // throw new Error("Could not remove directory due to invalid path.");
  }
};
<commit_msg>enhance remove dire log msg<commit_after>'use strict';
const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const _ = require('lodash')
const beautify = require('js-beautify').js_beautify;
const jsBeautifyOptions = { indent_size: 2, preserve_newlines: false, end_with_newline: true };

// Defining Markers
exports.COMPONENT_MARKER = '// Add new components above';
exports.SERVICE_MARKER = '// Add new services above';
exports.PAGE_MARKER = '// Add new pages above';
exports.DIRECTIVE_MARKER = '// Add new directives above';

exports.COMPONENT_NESTED_MARKER = '// Add new nested components above';
exports.SERVICE_NESTED_MARKER = '// Add new nested services above';
exports.DIRECTIVE_NESTED_MARKER = '// Add new nested directives above';

exports.IMPORT_MODULE_MARKER = '// Add module imports above';
exports.IMPORT_STYLE_MARKER = '// Add style imports above';
exports.IMPORT_DIRECTIVE_MARKER = '// Add directive imports above';
exports.IMPORT_SERVICE_MARKER = '// Add service imports above';
exports.IMPORT_DEPENDENCY_MARKER = '// Add module dependencies above';

exports.ADD_DIRECTIVE_TOMODULE_MARKER = '// Add directive to module above';
exports.ADD_SERVICE_TOMODULE_MARKER = '// Add service to module above';

exports.MAIN_SCSS_MARKER = '// Add Main SCSS Above';
exports.ROUTE_MARKER = '// Add new routes above';
exports.STATE_MARKER = '// Add new states above';

exports.DOCS_ASSETS_PATH = '/docs/docs-assets';
exports.DOCS_STORAGE_FILENAME = 'docs.js';

// Defining utility functions

/*
 * writes a line to a file before a marker
 * takes as inputs the file name, line to add, marker, and full path
 */
exports.addToFile = function(filename,lineToAdd,beforeMarker,fullpathI){
    try {
        let fullPath = path.resolve(fullpathI,filename);
        let fileSrc = fs.readFileSync(fullPath,'utf8');

        let indexOf = fileSrc.indexOf(beforeMarker);
        let lineStart = fileSrc.substring(0,indexOf).lastIndexOf('\n') + 1;
        let indent = fileSrc.substring(lineStart,indexOf);
        fileSrc = fileSrc.substring(0,indexOf) + lineToAdd + "\n" + indent + fileSrc.substring(indexOf);

        fs.writeFileSync(fullPath,fileSrc);
        // console.log('Written data to files');
    } catch(e) {
      console.log('Could not write data to files');
      throw e;
    }
};

exports.removeLineFromFile = function(filename,lineToRemove, fullpathI, indent, fullLine){
    try {
        let fullPath = path.resolve(fullpathI,filename);
        let fileSrc = fs.readFileSync(fullPath,'utf8');
        let indexOf = fileSrc.indexOf(lineToRemove);
        if(indexOf===-1){
          throw new Error('line not found');
        }
        let topHalf = fileSrc.substring(0,indexOf);
        topHalf = topHalf.substring(0, topHalf.lastIndexOf('\n'))
        let bottomHalf = fileSrc.substring(indexOf);
        fileSrc = topHalf + bottomHalf.substring(bottomHalf.indexOf('\n'));
        // fileSrc = beautify(fileSrc, jsBeautifyOptions);
        fs.writeFileSync(fullPath,fileSrc);
        // console.log('Written data to files');
    } catch(e) {
      console.log('Could not remove data from files');
      throw e;
    }
};

/*
 * checks if a given path exists synchronously
 */
exports.existsSync = function(path){
  return fs.existsSync(path);
};

exports.isHasPackage = function (obj) {
    return _.isObject(obj) && obj.package && obj.import !== false;
}

exports.stripPackageName = function (pkgName) {
    let regexp = /(.*?)@/;
    let match = pkgName.match(regexp);
    if (match) {
        return match[1];
    }
    return pkgName;
}

exports.deleteDirRecursive = function(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).forEach(function(file, index) {
      var curPath = path + "/" + file;
      if (fs.lstatSync(curPath).isDirectory()) { // recurse
        exports.deleteDirRecursive(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }else{
    console.log("invalid path: " + path + " was not deleted.");
  }
};
<|endoftext|>


<commit_before>// Written by Edwin Jones - http://edwinjones.me.uk
// Documentation and Discord.js integration by Jason Browne - https://jbrowne.io

'use strict';

//dependencies
const discord = require('discord.js');
const log = require('debug')('catbot')
const request = require('request-promise');

const stats = require('./stats');
const auth = require('./auth.json'); //you need to make this file yourself!

const helpmsg =
    "You can ask me for a random cat fact with **!catfact**, picture with **!catpic** " +
    "or you can stroke me with **!stroke** - " +
    "I do love to be stroked **:3**\n" +
    "I can also provide interesting stats with the **!catstats** command.";

/**
 * Error handler
 *
 * @param channel the text channel to send the message to
 * @param err the error message to log
 */
async function onError(channel, err) {
    log(err);
    await channel.send("Sorry, I'm catnapping now. Please ask me later.");
}

/**
 * Sends an image (via a url) to discord
 *
 * @param channel the text channel to send the message to
 * @param url the url of the image
 */
function sendImage(channel, url) {
    return channel.send({
        embed: {
            color: 4954687, //RGB value cast from hex to int. This is green!
            image: { url }
        }
    });
}

/**
 * Use this function to post a cat fact into the relevant discord channel
 *
 * @param channel the text channel to send the message to
 */
async function getCatFact(channel) {

    var options = {
        method: 'GET',
        uri: 'https://polite-catfacts.herokuapp.com/catfact',
        json: true
    }

    let response = await request(options);

    await channel.send(response.fact);
    await stats.incrementStat("catfacts");
    log("catfact command completed");
}

/**
 * Use this function to get cat pictures and post them into the relevant discord channel
 *
 * @param channel the channel to send the image to
 */
async function getCatPic(channel) {

    var include_href = function (body, response, resolveWithFullResponse) {
        return { 'href': response.request.href };
    };

    var options = {
        method: 'GET',
        uri: 'http://thecatapi.com/api/images/get?format=src',
        transform: include_href,
    }

    let response = await request(options);
    await sendImage(channel, response.href)
    await stats.incrementStat("catpics");

    log("catpic command completed");
}

/**
 * Use this function to stroke catbot!
 *
 * @param channel the channel to send the image to
 * @param userID the user ID of the person who stroked catbot
 */
async function stroke(channel, userID) {

    await channel.send(`**puuurrrrrrrrrr!** Thank you <@${userID}> **:3**`);
    await stats.incrementStat("catstrokes");
    log("catstroke command completed");
}

// Initialize Discord Bot
var bot = new discord.Client();

//log when the bot is ready
bot.on('ready', (evt) => {

    log('connected');
    log('logged in as: ');
    log(`${bot.user.username} - (${bot.user.id})`);
});

//handle disconnects by auto reconnecting
bot.on('disconnect', (erMsg, code) => {

    log(`----- bot disconnected from Discord with code ${code} for reason: ${erMsg} -----`);
    bot.connect();
})

// Decide what to do when the bot get a message. NOTE: discord supports markdown syntax.
bot.on('message', async (message) => {

    try {
        // catbot needs to know if it will execute a command
        // It will listen for messages that will start with `!`
        if (message.content.substring(0, 1) == '!') {
            log('recieved a command!')

            let args = message.content.substring(1).split(' ');
            let cmd = args[0];
            args = args.splice(1);

            switch (cmd) {
                // handle commands
                case 'help':
                    await message.channel.send(helpmsg);
                    log("help command executed");
                    break;

                case 'catfact':
                    await getCatFact(message.channel);
                    log("catfact command executed");
                    break;

                case 'catpic':
                    await getCatPic(message.channel);
                    log("catpic command executed");
                    break;

                case 'stroke':
                    await stroke(message.channel, message.author.id);
                    log("stroke command executed");
                    break;

                case 'catstats':
                    var statsText = await stats.getStats();
                    await message.channel.send(statsText);
                    log("catstats command executed");
                    break;
            }
        }
    }
    catch (err) {

        onError(message.channel, err);
    }
});

bot.login(auth.token);<commit_msg>more formatting<commit_after>// Written by Edwin Jones - http://edwinjones.me.uk
// Documentation and Discord.js integration by Jason Browne - https://jbrowne.io

'use strict';

//dependencies
const discord = require('discord.js');
const log = require('debug')('catbot')
const request = require('request-promise');

const stats = require('./stats');
const auth = require('./auth.json'); //you need to make this file yourself!

const helpmsg =
    "You can ask me for a random cat fact with **!catfact**, picture with **!catpic** " +
    "or you can stroke me with **!stroke** - " +
    "I do love to be stroked **:3**\n" +
    "I can also provide interesting stats with the **!catstats** command.";

/**
 * Error handler
 *
 * @param channel the text channel to send the message to
 * @param err the error message to log
 */
async function onError(channel, err) {
    log(err);
    await channel.send("Sorry, I'm catnapping now. Please ask me later.");
}

/**
 * Sends an image (via a url) to discord
 *
 * @param channel the text channel to send the message to
 * @param url the url of the image
 */
function sendImage(channel, url) {

    return channel.send({
        embed: {
            color: 4954687, //RGB value cast from hex to int. This is green!
            image: { url }
        }
    });
}

/**
 * Use this function to post a cat fact into the relevant discord channel
 *
 * @param channel the text channel to send the message to
 */
async function getCatFact(channel) {

    var options = {
        method: 'GET',
        uri: 'https://polite-catfacts.herokuapp.com/catfact',
        json: true
    }

    let response = await request(options);

    await channel.send(response.fact);
    await stats.incrementStat("catfacts");
    log("catfact command completed");
}

/**
 * Use this function to get cat pictures and post them into the relevant discord channel
 *
 * @param channel the channel to send the image to
 */
async function getCatPic(channel) {

    var include_href = function (body, response, resolveWithFullResponse) {
        return { 'href': response.request.href };
    };

    var options = {
        method: 'GET',
        uri: 'http://thecatapi.com/api/images/get?format=src',
        transform: include_href,
    }

    let response = await request(options);
    await sendImage(channel, response.href)
    await stats.incrementStat("catpics");

    log("catpic command completed");
}

/**
 * Use this function to stroke catbot!
 *
 * @param channel the channel to send the image to
 * @param userID the user ID of the person who stroked catbot
 */
async function stroke(channel, userID) {

    await channel.send(`**puuurrrrrrrrrr!** Thank you <@${userID}> **:3**`);
    await stats.incrementStat("catstrokes");
    log("catstroke command completed");
}

// Initialize Discord Bot
var bot = new discord.Client();

//log when the bot is ready
bot.on('ready', (evt) => {

    log('connected');
    log('logged in as: ');
    log(`${bot.user.username} - (${bot.user.id})`);
});

//handle disconnects by auto reconnecting
bot.on('disconnect', (erMsg, code) => {

    log(`----- bot disconnected from Discord with code ${code} for reason: ${erMsg} -----`);
    bot.connect();
})

// Decide what to do when the bot get a message. NOTE: discord supports markdown syntax.
bot.on('message', async (message) => {

    try {
        // catbot needs to know if it will execute a command
        // It will listen for messages that will start with `!`
        if (message.content.substring(0, 1) == '!') {
            log('recieved a command!')

            let args = message.content.substring(1).split(' ');
            let cmd = args[0];
            args = args.splice(1);

            switch (cmd) {
                // handle commands
                case 'help':
                    await message.channel.send(helpmsg);
                    log("help command executed");
                    break;

                case 'catfact':
                    await getCatFact(message.channel);
                    log("catfact command executed");
                    break;

                case 'catpic':
                    await getCatPic(message.channel);
                    log("catpic command executed");
                    break;

                case 'stroke':
                    await stroke(message.channel, message.author.id);
                    log("stroke command executed");
                    break;

                case 'catstats':
                    var statsText = await stats.getStats();
                    await message.channel.send(statsText);
                    log("catstats command executed");
                    break;
            }
        }
    }
    catch (err) {

        onError(message.channel, err);
    }
});

bot.login(auth.token);<|endoftext|>


<commit_before>var extend = require('xtend')
var getFormData = require('form-data-set/element')

var BaseEvent = require('./base-event.js')

var VALID_CHANGE = ['checkbox', 'file', 'select-multiple', 'select-one'];
var VALID_INPUT = ['color', 'date', 'datetime', 'datetime-local', 'email',
    'month', 'number', 'password', 'range', 'search', 'tel', 'text', 'time',
    'url', 'week'];

module.exports = BaseEvent(changeLambda);

function changeLambda(ev, broadcast) {
    var target = ev.target

    var isValid =
        (ev.type === 'input' && VALID_INPUT.indexOf(target.type) !== -1) ||
        (ev.type === 'change' && VALID_CHANGE.indexOf(target.type) !== -1);

    if (!isValid) {
        if (ev.startPropagation) {
            ev.startPropagation()
        }
        return
    }

    var value = getFormData(ev.currentTarget)
    var data = extend(value, this.data)

    broadcast(data)
}
<commit_msg>Allow textarea as a valid input source<commit_after>var extend = require('xtend')
var getFormData = require('form-data-set/element')

var BaseEvent = require('./base-event.js')

var VALID_CHANGE = ['checkbox', 'file', 'select-multiple', 'select-one'];
var VALID_INPUT = ['color', 'date', 'datetime', 'datetime-local', 'email',
    'month', 'number', 'password', 'range', 'search', 'tel', 'text', 'time',
    'url', 'week', 'textarea'];

module.exports = BaseEvent(changeLambda);

function changeLambda(ev, broadcast) {
    var target = ev.target

    var isValid =
        (ev.type === 'input' && VALID_INPUT.indexOf(target.type) !== -1) ||
        (ev.type === 'change' && VALID_CHANGE.indexOf(target.type) !== -1);

    if (!isValid) {
        if (ev.startPropagation) {
            ev.startPropagation()
        }
        return
    }

    var value = getFormData(ev.currentTarget)
    var data = extend(value, this.data)

    broadcast(data)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Novedia Group 2012.
 *
 *     This file is part of Hubiquitus.
 *
 *     Hubiquitus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Hubiquitus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with Hubiquitus.  If not, see <http://www.gnu.org/licenses/>.
 */
//Make it compatible with node and web browser
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(
    ['./strophe.pubsub', '../../codes', '../../sessionStorage'],
    function(Strophe, codes, sessionStorageAux){

        //Load correct modules if running on Node
        if(typeof module !== 'undefined' && module.exports){
            $iq     = Strophe.$iq;
            $msg    = Strophe.$msg;
            $pres   = Strophe.$pres;
            $build  = Strophe.$build;
        }

        //Taking care of session Storage. Sometimes the browser doesn't find it
        //And if it's node or we don't have support so we use 'our version'
        if(!sessionStorage){
            if(typeof window !== 'undefined' && window.sessionStorage)
                var sessionStorage = window.sessionStorage;
            else
                var sessionStorage = sessionStorageAux.sessionStorage;
        }

        var Strophe = Strophe.Strophe;
        var errors = codes.errors;
        var statuses = codes.statuses;
        var types = codes.types;

        // Constructor
        var hSessionBosh = function(opts) {
            this.params = opts;
            this.callback = opts.hCallback;
            this.pubsub =  "pubsub." + this.params.publisher.split('@')[1];
            this.retryIntervals = this.params.retryIntervals;
            this.status = statuses.DISCONNECTED;
            this.errorCode = errors.NO_ERROR;
            this.userDisconnect = false; //True when the user wants to disconnect

            //Create a Strophe connection
            this.conn = new Strophe.Connection(this.params.endpoint);
        };

        hSessionBosh.prototype = {

            /**
             * Tries to recover and reattach and old connection or connect to a new one.
             * @param force (boolean, optional). If defined and true. A reattach won't be tried and
             * a new connection will be started.
             */
            connect: function(force) {
                var re = new RegExp(this.params.publisher,"i");
                if( !force &&
                    typeof sessionStorage.getItem('publisher') === 'string'){
                    if(sessionStorage.getItem('publisher').search(re) != -1){
                        // Tell the user we are reattaching.
                        this.onStatus(true, {status: statuses.REATTACHING, errorCode: errors.NO_ERROR});
                        this.conn.attach(
                            sessionStorage.getItem('publisher'),
                            sessionStorage.getItem('sid'),
                            sessionStorage.getItem('rid'),
                            this.onStatus.bind(this, false),
                            null, null, null)
                    }else{
                        //We have an open connection but JIDs do not match, send an error.
                        this.onStatus(true, {status: statuses.CONNECTED, errorCode: errors.ALREADY_CONNECTED});
                    }
                }else{
                    //We don't have enough information to restablish the connection. Establish a new one
                    this.conn.connect(
                        this.params.publisher,
                        this.params.password,
                        this.onStatus.bind(this, false),
                        null, null, null
                    );
                }
            },

            /**
             * Callback for the connection status. Accepts Strophe or proper hStatus as values
             * @param isHStatus - if the status should be interpreted as an hStatus or an Strophe Status
             * @param status - The status to send to the client.
             * @param msg - Specific message sent --sometimes-- by strophe to indicate the error
             */
            onStatus: function(isHStatus, value, msg)
            {
                var errorCode;
                var statusCode;
                var errorMsg;
                var status = value;
                var self = this;

                function _onConnection(){
                    //Send Presence
                    self.conn.send($pres());

                    //Add Handlers
                    self.conn.addHandler(self.handleIQ.bind(self), null, 'iq', 'get',null, null, {matchBare: true});
                    self.conn.addHandler(self.handleMessage.bind(self), Strophe.NS.PUBSUB_EVENT,'message',
                        null, null, self.pubsub, {matchBare: true});
                    self.conn.addHandler(self.handleHResult.bind(self), null, 'message',
                        null, null, self.hnode, {matchBare: true});

                    //Save attrs when changing pages/refreshing (only browser)
                    if(typeof window !== 'undefined')
                        window.onunload = function(){
                            sessionStorage.setItem('publisher', self.conn.jid);
                            sessionStorage.setItem('sid', self.conn.sid);
                            sessionStorage.setItem('rid', self.conn.rid);
                        };

                    self.retryIntervals = self.params.retryIntervals; //Resets the reconnection counter
                }
                function _onError(){
                    sessionStorage.removeItem('publisher');
                    sessionStorage.removeItem('sid');
                    sessionStorage.removeItem('rid');

                    var timeout = self.retryIntervals.length == 1 ? self.retryIntervals[0] : self.retryIntervals.pop();
                    self.connect_retry = setTimeout(self.connect.bind(self, true),timeout*1000);
                }

                if(!isHStatus){
                    switch(value){
                        case Strophe.Status.ATTACHED:
                            statusCode = statuses.REATTACHED;
                        case Strophe.Status.CONNECTED:
                            statusCode = statusCode || statuses.CONNECTED;
                            _onConnection();
                            break;
                        case Strophe.Status.CONNFAIL:
                        case Strophe.Status.ERROR:
                            errorCode = errors.CONN_TIMEOUT;
                            statusCode = statuses.CONNECTING;
                            errorMsg = msg;
                            _onError();
                            break;
                        case Strophe.Status.CONNECTING:
                            //This removes  the second connecting after a connection error
                            statusCode = this.errorCode != errors.NO_ERROR ? undefined : statuses.CONNECTING;
                            break;
                        case Strophe.Status.DISCONNECTING:
                            //Clear the reconnection timeout
                            clearTimeout(this.connect_retry);
                            //If the disconnection was not by the user, treat it as an error.
                            if(this.userDisconnect)
                                statusCode = statuses.DISCONNECTING;
                            else{
                                statusCode = statuses.DISCONNECTED;
                                errorCode = errors.TECH_ERROR;
                            }
                            break;
                        case Strophe.Status.DISCONNECTED:
                            statusCode = statuses.DISCONNECTED;
                            //If the disconnection was not by the user, treat it as an error.
                            if(!this.userDisconnect)
                                _onError();
                            break;
                        case Strophe.Status.AUTHFAIL:
                            statusCode = statuses.DISCONNECTED;
                            errorCode = errors.AUTH_FAILED;
                            break;
                    }
                    status = {status: statusCode, errorCode: errorCode || errors.NO_ERROR, errorMsg: errorMsg};
                }
                if(status.status){
                    this.status = status.status;
                    this.errorCode = status.errorCode || errors.NO_ERROR;
                    this.sendCallback(types.hStatus, status);
                }
            },

            //Handle to retrieve items
            handleMessage: function(stanza) {
                var parsedItems = [];
                var _data = stanza.getElementsByTagName('items')[0];
                var _channel = _data.getAttribute('node');

                var items = _data.getElementsByTagName('item');
                for(var i = 0; i < items.length; i++)
                    parsedItems.push(items[i].childNodes[0].childNodes[0].textContent);

                //Calling client callback with the extracted message
                for(var i = 0; i < parsedItems.length; i++)
                    this.callback({type: 'message', data :
                    {channel: _channel, message: parsedItems[i]}})
                return true;
            },

            //Handles an hResult from the server
            handleHResult: function(stanza){
                var body = stanza.getElementsByTagName('body');
                body = body ? body[0] : undefined;

                if(body && body.getAttribute('type') == 'hresult'){
                    try{
                        var hResult = JSON.parse(body.textContent);
                        this.callback({type: 'hResult', data: hResult});
                    }
                    catch(err){
                        console.log('Error parsing hResult');
                    }
                }
                return true;
            },

            //In case we receive an iq-get request, send an error cause we don't allow them
            handleIQ : function(stanza){
                var msg = $iq({
                    to: stanza.attributes.from.nodeValue,
                    type: 'error',
                    id: stanza.attributes.id.nodeValue
                })
                    .c(stanza.firstChild.nodeName, {xmlns: stanza.firstChild.attributes.xmlns.nodeValue}).up()
                    .c('error', { type: 'cancel'})
                    .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'});

                console.log("Received an IQ from the server. Responding.");
                this.conn.send(msg);
                return true; //If it doesn't return true, Strophe will remove it from Handler's list
            },

            disconnect: function() {
                clearTimeout(this.connect_retry);
                //Remove our attrs
                sessionStorage.removeItem('publisher');
                sessionStorage.removeItem('sid');
                sessionStorage.removeItem('rid');
                //Set user intention of disconnecting
                this.userDisconnect = true;
                //In case there is an error, disconnected or a disconnection
                // Do not tell strophe to disconnect again
                if( this.status == statuses.DISCONNECTED || this.status == statuses.DISCONNECTING ) return;
                this.conn.flush();
                this.conn.disconnect();
            },

            unsubscribe : function(channel){
                function _success(stanza){
                    this.callback({type: 'result', data:
                    {type: 'unsubscribe', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                function _failure(stanza){
                    this.callback({type: 'error', data:
                    {type: 'unsubscribe', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                return this.conn.pubsub.unsubscribe(
                    channel,
                    undefined,
                    undefined,
                    _success.bind(this),
                    _failure.bind(this));
            },

            publish : function(channel,item){
                function _callback(stanza){
                    if(stanza.getAttribute('type') == 'error')
                        this.callback({type: 'error', data:
                        {type: 'publish', channel: channel, msgid: stanza.getAttribute('id')}});
                    else
                        this.callback({type: 'result', data:
                        {type: 'publish', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                return this.conn.pubsub.publish(
                    channel,
                    [{  data: $build("entry", {}).t(item).tree(),
                        attrs: {}
                    }],
                    _callback.bind(this));
            },

            getMessages : function(channel){
                function _failure(stanza){
                    this.callback({type: 'error', data:
                    {type: 'get_messages', channel: channel, msgid: stanza.getAttribute('id')}});
                }
                return this.conn.pubsub.items(channel,
                    this.handleMessage.bind(this), _failure.bind(this));
            },

            sendhCommand : function(hCommand){
                var msg = $msg({to: hCommand.entity})
                    .c('body', {type: 'hcommand'}, JSON.stringify(hCommand));
                this.conn.send(msg);
            },

            sendCallback : function(type, data){
                this.callback({
                    type: type,
                    data: data
                })
            }
        };

        //requireJS way to import
        return{
            hSessionBosh : hSessionBosh
        }
    }
);
<commit_msg>Complying to new message<commit_after>/*
 * Copyright (c) Novedia Group 2012.
 *
 *     This file is part of Hubiquitus.
 *
 *     Hubiquitus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Hubiquitus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with Hubiquitus.  If not, see <http://www.gnu.org/licenses/>.
 */
//Make it compatible with node and web browser
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(
    ['./strophe.pubsub', '../../codes', '../../sessionStorage'],
    function(Strophe, codes, sessionStorageAux){

        //Load correct modules if running on Node
        if(typeof module !== 'undefined' && module.exports){
            $iq     = Strophe.$iq;
            $msg    = Strophe.$msg;
            $pres   = Strophe.$pres;
            $build  = Strophe.$build;
        }

        //Taking care of session Storage. Sometimes the browser doesn't find it
        //And if it's node or we don't have support so we use 'our version'
        if(!sessionStorage){
            if(typeof window !== 'undefined' && window.sessionStorage)
                var sessionStorage = window.sessionStorage;
            else
                var sessionStorage = sessionStorageAux.sessionStorage;
        }

        var Strophe = Strophe.Strophe;
        var errors = codes.errors;
        var statuses = codes.statuses;
        var types = codes.types;

        // Constructor
        var hSessionBosh = function(opts) {
            this.params = opts;
            this.callback = opts.hCallback;
            this.pubsub =  "pubsub." + this.params.publisher.split('@')[1];
            this.retryIntervals = this.params.retryIntervals;
            this.status = statuses.DISCONNECTED;
            this.errorCode = errors.NO_ERROR;
            this.userDisconnect = false; //True when the user wants to disconnect

            //Create a Strophe connection
            this.conn = new Strophe.Connection(this.params.endpoint);
        };

        hSessionBosh.prototype = {

            /**
             * Tries to recover and reattach and old connection or connect to a new one.
             * @param force (boolean, optional). If defined and true. A reattach won't be tried and
             * a new connection will be started.
             */
            connect: function(force) {
                var re = new RegExp(this.params.publisher,"i");
                if( !force &&
                    typeof sessionStorage.getItem('publisher') === 'string'){
                    if(sessionStorage.getItem('publisher').search(re) != -1){
                        // Tell the user we are reattaching.
                        this.onStatus(true, {status: statuses.REATTACHING, errorCode: errors.NO_ERROR});
                        this.conn.attach(
                            sessionStorage.getItem('publisher'),
                            sessionStorage.getItem('sid'),
                            sessionStorage.getItem('rid'),
                            this.onStatus.bind(this, false),
                            null, null, null)
                    }else{
                        //We have an open connection but JIDs do not match, send an error.
                        this.onStatus(true, {status: statuses.CONNECTED, errorCode: errors.ALREADY_CONNECTED});
                    }
                }else{
                    //We don't have enough information to restablish the connection. Establish a new one
                    this.conn.connect(
                        this.params.publisher,
                        this.params.password,
                        this.onStatus.bind(this, false),
                        null, null, null
                    );
                }
            },

            /**
             * Callback for the connection status. Accepts Strophe or proper hStatus as values
             * @param isHStatus - if the status should be interpreted as an hStatus or an Strophe Status
             * @param status - The status to send to the client.
             * @param msg - Specific message sent --sometimes-- by strophe to indicate the error
             */
            onStatus: function(isHStatus, value, msg)
            {
                var errorCode;
                var statusCode;
                var errorMsg;
                var status = value;
                var self = this;

                function _onConnection(){
                    //Send Presence
                    self.conn.send($pres());

                    //Add Handlers
                    self.conn.addHandler(self.handleIQ.bind(self), null, 'iq', 'get',null, null, {matchBare: true});
                    self.conn.addHandler(self.handleMessage.bind(self), Strophe.NS.PUBSUB_EVENT,'message',
                        null, null, self.pubsub, {matchBare: true});
                    self.conn.addHandler(self.handleHResult.bind(self), null, 'message',
                        null, null, self.hnode, {matchBare: true});

                    //Save attrs when changing pages/refreshing (only browser)
                    if(typeof window !== 'undefined')
                        window.onunload = function(){
                            sessionStorage.setItem('publisher', self.conn.jid);
                            sessionStorage.setItem('sid', self.conn.sid);
                            sessionStorage.setItem('rid', self.conn.rid);
                        };

                    self.retryIntervals = self.params.retryIntervals; //Resets the reconnection counter
                }
                function _onError(){
                    sessionStorage.removeItem('publisher');
                    sessionStorage.removeItem('sid');
                    sessionStorage.removeItem('rid');

                    var timeout = self.retryIntervals.length == 1 ? self.retryIntervals[0] : self.retryIntervals.pop();
                    self.connect_retry = setTimeout(self.connect.bind(self, true),timeout*1000);
                }

                if(!isHStatus){
                    switch(value){
                        case Strophe.Status.ATTACHED:
                            statusCode = statuses.REATTACHED;
                        case Strophe.Status.CONNECTED:
                            statusCode = statusCode || statuses.CONNECTED;
                            _onConnection();
                            break;
                        case Strophe.Status.CONNFAIL:
                        case Strophe.Status.ERROR:
                            errorCode = errors.CONN_TIMEOUT;
                            statusCode = statuses.CONNECTING;
                            errorMsg = msg;
                            _onError();
                            break;
                        case Strophe.Status.CONNECTING:
                            //This removes  the second connecting after a connection error
                            statusCode = this.errorCode != errors.NO_ERROR ? undefined : statuses.CONNECTING;
                            break;
                        case Strophe.Status.DISCONNECTING:
                            //Clear the reconnection timeout
                            clearTimeout(this.connect_retry);
                            //If the disconnection was not by the user, treat it as an error.
                            if(this.userDisconnect)
                                statusCode = statuses.DISCONNECTING;
                            else{
                                statusCode = statuses.DISCONNECTED;
                                errorCode = errors.TECH_ERROR;
                            }
                            break;
                        case Strophe.Status.DISCONNECTED:
                            statusCode = statuses.DISCONNECTED;
                            //If the disconnection was not by the user, treat it as an error.
                            if(!this.userDisconnect)
                                _onError();
                            break;
                        case Strophe.Status.AUTHFAIL:
                            statusCode = statuses.DISCONNECTED;
                            errorCode = errors.AUTH_FAILED;
                            break;
                    }
                    status = {status: statusCode, errorCode: errorCode || errors.NO_ERROR, errorMsg: errorMsg};
                }
                if(status.status){
                    this.status = status.status;
                    this.errorCode = status.errorCode || errors.NO_ERROR;
                    this.sendCallback(types.hStatus, status);
                }
            },

            //Handle to retrieve items
            handleMessage: function(stanza) {
                var parsedItems = [];
                var _data = stanza.getElementsByTagName('items')[0];
                var _channel = _data.getAttribute('node');

                var items = _data.getElementsByTagName('item');
                for(var i = 0; i < items.length; i++)
                    parsedItems.push(items[i].childNodes[0].childNodes[0].textContent);

                //Calling client callback with the extracted message
                for(var i = 0; i < parsedItems.length; i++)
                    this.callback({type: 'message', data :
                    {channel: _channel, message: parsedItems[i]}})
                return true;
            },

            //Handles an hResult from the server
            handleHResult: function(stanza){
                var body = stanza.getElementsByTagName('hbody');
                body = body ? body[0] : undefined;

                if(body && body.getAttribute('type') == 'hresult'){
                    try{
                        var hResult = JSON.parse(body.textContent);
                        this.callback({type: 'hResult', data: hResult});
                    }
                    catch(err){
                        console.log('Error parsing hResult');
                    }
                }
                return true;
            },

            //In case we receive an iq-get request, send an error cause we don't allow them
            handleIQ : function(stanza){
                var msg = $iq({
                    to: stanza.attributes.from.nodeValue,
                    type: 'error',
                    id: stanza.attributes.id.nodeValue
                })
                    .c(stanza.firstChild.nodeName, {xmlns: stanza.firstChild.attributes.xmlns.nodeValue}).up()
                    .c('error', { type: 'cancel'})
                    .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'});

                console.log("Received an IQ from the server. Responding.");
                this.conn.send(msg);
                return true; //If it doesn't return true, Strophe will remove it from Handler's list
            },

            disconnect: function() {
                clearTimeout(this.connect_retry);
                //Remove our attrs
                sessionStorage.removeItem('publisher');
                sessionStorage.removeItem('sid');
                sessionStorage.removeItem('rid');
                //Set user intention of disconnecting
                this.userDisconnect = true;
                //In case there is an error, disconnected or a disconnection
                // Do not tell strophe to disconnect again
                if( this.status == statuses.DISCONNECTED || this.status == statuses.DISCONNECTING ) return;
                this.conn.flush();
                this.conn.disconnect();
            },

            unsubscribe : function(channel){
                function _success(stanza){
                    this.callback({type: 'result', data:
                    {type: 'unsubscribe', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                function _failure(stanza){
                    this.callback({type: 'error', data:
                    {type: 'unsubscribe', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                return this.conn.pubsub.unsubscribe(
                    channel,
                    undefined,
                    undefined,
                    _success.bind(this),
                    _failure.bind(this));
            },

            publish : function(channel,item){
                function _callback(stanza){
                    if(stanza.getAttribute('type') == 'error')
                        this.callback({type: 'error', data:
                        {type: 'publish', channel: channel, msgid: stanza.getAttribute('id')}});
                    else
                        this.callback({type: 'result', data:
                        {type: 'publish', channel: channel, msgid: stanza.getAttribute('id')}});
                }

                return this.conn.pubsub.publish(
                    channel,
                    [{  data: $build("entry", {}).t(item).tree(),
                        attrs: {}
                    }],
                    _callback.bind(this));
            },

            getMessages : function(channel){
                function _failure(stanza){
                    this.callback({type: 'error', data:
                    {type: 'get_messages', channel: channel, msgid: stanza.getAttribute('id')}});
                }
                return this.conn.pubsub.items(channel,
                    this.handleMessage.bind(this), _failure.bind(this));
            },

            sendhCommand : function(hCommand){
                var msg = $msg({to: hCommand.entity})
                    .c('hbody', {type: 'hcommand'}, JSON.stringify(hCommand));
                this.conn.send(msg);
            },

            sendCallback : function(type, data){
                this.callback({
                    type: type,
                    data: data
                })
            }
        };

        //requireJS way to import
        return{
            hSessionBosh : hSessionBosh
        }
    }
);
<|endoftext|>


<commit_before>var ko = require('knockout'),
    _ = require('underscore'),
    Shuffler = require('./shuffler').Shuffler;

var LightCardsViewModel = exports.LightCardsViewModel = function(cards) {
  var self = this;

  this.cards = cards;
  this.shuffledCards = new Shuffler(cards);
  this.currentCard = ko.observable(this.shuffledCards.next());
  this.learnedCards = ko.observableArray();

  this.learnedRate = ko.computed(function() {
    return Math.round(self.learnedCards().length / self.cards.length * 100);
  });

  this.input = ko.observable('');
  this.showTranslation = ko.observable(false);
  this.animationToggle = ko.observable(true);

  this.handlers = {
    keyup: function(_, e) {
      if (e.keyCode === 13) { this.checkAnswer(this.input());
      } else if (e.keyCode === 40) { self.showHelp(); }
    },
    blur: function(_, e) { setTimeout(function() { e.target.focus(); }, 1); }
  };
};

LightCardsViewModel.prototype.reset = function() {
  this.showTranslation(false);
  this.input(null);
};

LightCardsViewModel.prototype.normalizeAnswer = function(answer) {
  return answer.replace(/5| /g, '');
};

LightCardsViewModel.prototype.markLearned = function(card) {
  this.learnedCards.push(card);
  this.learnedCards(_.unique(this.learnedCards()));
};

LightCardsViewModel.prototype.markNotLearned = function(card) {
  this.learnedCards.remove(card);
};

LightCardsViewModel.prototype.nextCard = function() {
  var self = this;
  this.reset();
  this.animationToggle(false);
  setTimeout(function() {
    self.animationToggle(true);
    self.currentCard(self.shuffledCards.next());
  }, 1);
};

LightCardsViewModel.prototype.checkAnswer = function(answer) {
  var isCorrect = this.normalizeAnswer(answer) ===
                  this.normalizeAnswer(this.currentCard().transcription);
  if (isCorrect) {
    this.markLearned(this.currentCard());
    this.nextCard();
  } else {
    this.markNotLearned(this.currentCard());
  }
};

LightCardsViewModel.prototype.showHelp = function() {
  this.markNotLearned(this.currentCard());
  if (!this.showTranslation()) { this.showTranslation(true);
  } else { this.input(this.currentCard().transcription); }
};
<commit_msg>Correctly handle incorrect answers<commit_after>var ko = require('knockout'),
    _ = require('underscore'),
    Shuffler = require('./shuffler').Shuffler;

var LightCardsViewModel = exports.LightCardsViewModel = function(cards) {
  var self = this;

  this.cards = cards;
  this.shuffledCards = new Shuffler(cards);
  this.currentCard = ko.observable(this.shuffledCards.next());
  this.learnedCards = ko.observableArray();
  this.userHasAnsweredIncorrectly = ko.observable();

  this.learnedRate = ko.computed(function() {
    return Math.round(self.learnedCards().length / self.cards.length * 100);
  });

  this.input = ko.observable('');
  this.showTranslation = ko.observable(false);
  this.animationToggle = ko.observable(true);

  this.handlers = {
    keyup: function(_, e) {
      if (e.keyCode === 13) { this.checkAnswer(this.input());
      } else if (e.keyCode === 40) { self.showHelp(); }
    },
    blur: function(_, e) { setTimeout(function() { e.target.focus(); }, 1); }
  };
};

LightCardsViewModel.prototype.reset = function() {
  this.showTranslation(false);
  this.input(null);
  this.userHasAnsweredIncorrectly(false);
};

LightCardsViewModel.prototype.normalizeAnswer = function(answer) {
  return answer.replace(/5| /g, '');
};

LightCardsViewModel.prototype.markLearned = function(card) {
  this.learnedCards.push(card);
  this.learnedCards(_.unique(this.learnedCards()));
};

LightCardsViewModel.prototype.markNotLearned = function(card) {
  this.learnedCards.remove(card);
};

LightCardsViewModel.prototype.nextCard = function() {
  var self = this;
  this.reset();
  this.animationToggle(false);
  setTimeout(function() {
    self.animationToggle(true);
    self.currentCard(self.shuffledCards.next());
  }, 1);
};

LightCardsViewModel.prototype.checkAnswer = function(answer) {
  var isCorrect = this.normalizeAnswer(answer) ===
                  this.normalizeAnswer(this.currentCard().transcription);
  if (isCorrect) {
    if (!this.userHasAnsweredIncorrectly()) {
      this.markLearned(this.currentCard());
    }
    this.nextCard();
  } else {
    this.markNotLearned(this.currentCard());
    this.userHasAnsweredIncorrectly(true);
  }
};

LightCardsViewModel.prototype.showHelp = function() {
  this.markNotLearned(this.currentCard());
  if (!this.showTranslation()) { this.showTranslation(true);
  } else { this.input(this.currentCard().transcription); }
};
<|endoftext|>


<commit_before>import dns from 'dns'
import { promisify } from 'util'
import isFQDN from 'validator/lib/isFQDN'
import isIP from 'validator/lib/isIP'
import isPort from 'validator/lib/isPort'

const dnsLookup = promisify(dns.lookup)

/**
 * Helper function to check a hostname in the format hostname:port is valid for passing to node-grpc.
 * @param {string} host A hostname + optional port in the format [hostname]:[port?]
 * @returns {Promise<Boolean>}
 */
export const validateHost = async host => {
  var splits = host.split(':')
  const lndHost = splits[0]
  const lndPort = splits[1]

  // If the hostname starts with a number, ensure that it is a valid IP address.
  if (!isFQDN(lndHost, { require_tld: false }) && !isIP(lndHost)) {
    const error = new Error(`${lndHost} is not a valid IP address or hostname`)
    error.code = 'LND_GRPC_HOST_ERROR'
    return Promise.reject(error)
  }

  // If the host includes a port, ensure that it is a valid.
  if (lndPort && !isPort(lndPort)) {
    const error = new Error(`${lndPort} is not a valid port`)
    error.code = 'LND_GRPC_HOST_ERROR'
    return Promise.reject(error)
  }

  // Do a DNS lookup to ensure that the host is reachable.
  return dnsLookup(lndHost)
    .then(() => true)
    .catch(e => {
      const error = new Error(`${lndHost} is not accessible: ${e.message}`)
      error.code = 'LND_GRPC_HOST_ERROR'
      return Promise.reject(error)
    })
}
<commit_msg>refactor(ui): cleanup validateHost<commit_after>import dns from 'dns'
import { promisify } from 'util'
import isFQDN from 'validator/lib/isFQDN'
import isIP from 'validator/lib/isIP'
import isPort from 'validator/lib/isPort'

const dnsLookup = promisify(dns.lookup)

/**
 * Helper function to check a hostname in the format hostname:port is valid for passing to node-grpc.
 * @param {string} host A hostname + optional port in the format [hostname]:[port?]
 * @returns {Promise<Boolean>}
 */
export const validateHost = async host => {
  const createError = (msg, code) => {
    const error = new Error(msg)
    error.code = code
    return Promise.reject(error)
  }

  try {
    const [lndHost, lndPort] = host.split(':')

    // If the hostname starts with a number, ensure that it is a valid IP address.
    if (!isFQDN(lndHost, { require_tld: false }) && !isIP(lndHost)) {
      return createError(`${lndHost} is not a valid IP address or hostname`, 'LND_GRPC_HOST_ERROR')
    }

    // If the host includes a port, ensure that it is a valid.
    if (lndPort && !isPort(lndPort)) {
      return createError(`${lndPort} is not a valid port`, 'LND_GRPC_HOST_ERROR')
    }

    try {
      // Do a DNS lookup to ensure that the host is reachable.
      await dnsLookup(lndHost)
      return true
    } catch (e) {
      return createError(`${lndHost} is not accessible: ${e.message}`)
    }
  } catch (e) {
    return createError(`Host is invalid`, 'LND_GRPC_HOST_ERROR')
  }
}
<|endoftext|>


<commit_before>const iconv = require('iconv-lite');
const rp = require('request-promise');
const striptags = require('striptags');

const LyricBase = require('../include/lyric_base');

const keyword = 'kashinavi';

class Lyric extends LyricBase {
  find_song_id(url) {
    const pattern = /\?([0-9]+)/;
    return this.get_first_group_by_pattern(url, pattern);
  }

  async find_lyric(url, html) {
    const prefix = 'oncopy="return false;" unselectable="on;">';
    const suffix = '
';
    let lyric = this.find_string_by_prefix_suffix(html, prefix, suffix, false);
    lyric = lyric.replace(/

/g, '\n\n');
    lyric = lyric.replace(/
/g, '\n');
    lyric = striptags(lyric);
    lyric = lyric.trim();

    this.lyric = lyric;
    return true;
  }

  async find_info(url, html) {
    const prefix = '
';
    const suffix = '
';
    const table_str = this.find_string_by_prefix_suffix(html, prefix, suffix, false);

    const patterns = {
      title: '<h.>([^<]+?)[♪<]',
      artist: '(.+?)',
      lyricist: '作詞　：　([^<]+)
',
      composer: '作曲　：　([^<]+)	',
    };

    this.fill_song_info(table_str, patterns);
  }

  async get_html(url) {
    const raw = await rp({ url, encoding: null });
    const html = iconv.decode(raw, 'Shift_JIS');

    return html;
  }

  async parse_page() {
    const { url } = this;

    const html = await this.get_html(url);

    this.find_lyric(url, html);
    this.find_info(url, html);

    return true;
  }
}

exports.keyword = keyword;
exports.Lyric = Lyric;

if (require.main === module) {
  (async () => {
    const url = 'https://kashinavi.com/song_view.html?77597';
    const obj = new Lyric(url);
    const lyric = await obj.get();
    console.log(lyric);
  })();
}
<commit_msg>fix kashinavi info<commit_after>const iconv = require('iconv-lite');
const rp = require('request-promise');
const striptags = require('striptags');

const LyricBase = require('../include/lyric_base');

const keyword = 'kashinavi';

class Lyric extends LyricBase {
  find_song_id(url) {
    const pattern = /\?([0-9]+)/;
    return this.get_first_group_by_pattern(url, pattern);
  }

  async find_lyric(url, html) {
    const prefix = 'oncopy="return false;" unselectable="on;">';
    const suffix = '
';
    let lyric = this.find_string_by_prefix_suffix(html, prefix, suffix, false);
    lyric = lyric.replace(/

/g, '\n\n');
    lyric = lyric.replace(/
/g, '\n');
    lyric = striptags(lyric);
    lyric = lyric.trim();

    this.lyric = lyric;
    return true;
  }

  async find_info(url, html) {
    const prefix = '';
    const suffix = '
';
    const table_str = this.find_string_by_prefix_suffix(html, prefix, suffix, false);

    const patterns = {
      title: '

([^<]+?)[♪<]',
      artist: '(.+?)',
      lyricist: '作詞　：　([^<]+)
',
      composer: '作曲　：　([^<]+)</.+>',
    };

    this.fill_song_info(table_str, patterns);
  }

  async get_html(url) {
    const raw = await rp({ url, encoding: null });
    const html = iconv.decode(raw, 'Shift_JIS');

    return html;
  }

  async parse_page() {
    const { url } = this;

    const html = await this.get_html(url);

    this.find_lyric(url, html);
    this.find_info(url, html);

    return true;
  }
}

exports.keyword = keyword;
exports.Lyric = Lyric;

if (require.main === module) {
  (async () => {
    const url = 'https://kashinavi.com/song_view.html?77597';
    const obj = new Lyric(url);
    const lyric = await obj.get();
    console.log(lyric);
  })();
}
<|endoftext|>


<commit_before>// get-constructors.js

this.constructors = function () {
  'use strict';

  // getProto
  var getProto = Object.getPrototypeOf ? Object.getPrototypeOf :
    function getProto(obj) { return obj.__proto__ };

  // constructors
  function constructors(obj) {
    // supports: getter and normal function
    if (arguments.length === 0) obj = this;

    // convert to object from primitives
    if (obj != null && typeof obj !== 'object' && typeof obj !== 'function')
      obj = Object(obj);

    var classes = [];

    if (obj instanceof Function)
      // for Class/constructor
      for (; obj; obj = getProto(obj))
        if (typeof obj === 'function')
          classes.push(obj);

    else
      // for instance/object
      for (; obj; obj = getProto(obj))
        if (obj.hasOwnProperty('constructor'))
          classes.push(obj.constructor);

    return classes;
  }

  // extendPrototype
  constructors.extendPrototype = function extendPrototype(ctor) {
    ctor = ctor || Object;

    if (!ctor.prototype.hasOwnProperty('constructors'))
      Object.defineProperty(ctor.prototype, 'constructors',
        {get: constructors, configurable: true});

    return this;
  };

  // exports
  if (typeof module === 'object' && module.exports)
    module.exports = exports = constructors;

  return constructors;

}();
<commit_msg>fix bug<commit_after>// get-constructors.js

this.constructors = function () {
  'use strict';

  // getProto
  var getProto = Object.getPrototypeOf ? Object.getPrototypeOf :
    function getProto(obj) { return obj.__proto__; };

  // constructors
  function constructors(obj) {
    // supports: getter and normal function
    if (arguments.length === 0) obj = this;

    // convert to object from primitives
    if (obj != null && typeof obj !== 'object' && typeof obj !== 'function')
      obj = Object(obj);

    var classes = [];

    if (obj instanceof Function)
      // for Class/constructor
      for (; obj; obj = getProto(obj))
        typeof obj === 'function' &&
          classes.push(obj);

    else
      // for instance/object
      for (; obj; obj = getProto(obj))
        obj.hasOwnProperty('constructor') &&
          classes.push(obj.constructor);

    return classes;
  }

  // extendPrototype
  constructors.extendPrototype = function extendPrototype(ctor) {
    ctor = ctor || Object;

    if (!ctor.prototype.hasOwnProperty('constructors'))
      Object.defineProperty(ctor.prototype, 'constructors',
        {get: constructors, configurable: true});

    return this;
  };

  // exports
  if (typeof module === 'object' && module.exports)
    module.exports = exports = constructors;

  return constructors;

}();
<|endoftext|>


<commit_before>/**
 * Created by andreas on 04.05.14.
 */
avnav.provide('avnav.nav.GpsData');

/**
 * the handler for the gps data
 * query the server...
 * @param {avnav.util.PropertyHandler} propertyHandler
 * @param {avnav.nav.NavObject} navobject
 * @constructor
 */
avnav.nav.GpsData=function(propertyHandler,navobject){
    /** @private */
    this.propertyHandler=propertyHandler;
    /** @private */
    this.navobject=navobject;
    /** @private */
    this.gpsdata=new avnav.nav.navdata.GpsInfo();
    /** @private */
    this.formattedData= {
        gpsPosition:"NO FIX",
        gpsCourse:"0",
        gpsSpeed:"0",
        gpsTime:"---",
        nmeaStatusColor:"red",
        nmeaStatusText:"???",
        aisStatusColor: "red",
        aisStatusText: "???"
    };
    /** {avnav.util.Formatter} @private */
    this.formatter=new avnav.util.Formatter();
    this.timer=null;
    /** {Boolean} @private */
    this.validPosition=false;
    this.gpsErrors=0;
    this.NM=this.propertyHandler.getProperties().NM;
    this.startQuery();
    for (var k in this.formattedData){
        this.navobject.registerValueProvider(k,this,this.getFormattedGpsValue);
    }
};

/**
 *
 * @param data
 * @private
 */
avnav.nav.GpsData.prototype.handleGpsResponse=function(data){
    var gpsdata=new avnav.nav.navdata.GpsInfo();
    gpsdata.rtime=null;
    if (data.time != null) gpsdata.rtime=new Date(data.time);
    gpsdata.lon=data.lon;
    gpsdata.lat=data.lat;
    gpsdata.course=data.course;
    if (gpsdata.course === undefined) gpsdata.course=data.track;
    gpsdata.speed=data.speed*3600/this.NM;
    gpsdata.valid=true;
    gpsdata.raw=data.raw;
    this.gpsdata=gpsdata;
    var formattedData={};
    formattedData.gpsPosition=this.formatter.formatLonLats(gpsdata);
    formattedData.gpsCourse=this.formatter.formatDecimal(gpsdata.course||0,3,0);
    formattedData.gpsSpeed=this.formatter.formatDecimal(gpsdata.speed||0,2,1);
    formattedData.gpsTime=this.formatter.formatTime(gpsdata.rtime||new Date());
    formattedData.nmeaStatusColor="red";
    formattedData.nmeaStatusText="???"
    try {
        if (data.raw && data.raw.status && data.raw.status.nmea){
            formattedData.nmeaStatusColor = data.raw.status.nmea.status;
            formattedData.nmeaStatusText=data.raw.status.nmea.source+":"+data.raw.status.nmea.info;
        }
    }catch(e){}
    formattedData.aisStatusColor="red";
    formattedData.aisStatusText="???"
    try {
        if (data.raw && data.raw.status && data.raw.status.ais){
            formattedData.aisStatusColor = data.raw.status.ais.status;
            formattedData.aisStatusText=data.raw.status.ais.source+":"+data.raw.status.ais.info;
        }
    }catch(e){}

    this.formattedData=formattedData;
};

/**
 * @private
 */
avnav.nav.GpsData.prototype.startQuery=function(){
    var url=this.propertyHandler.getProperties().navUrl;
    var timeout=this.propertyHandler.getProperties().positionQueryTimeout;
    var self=this;
    $.ajax({
        url: url,
        dataType: 'json',
        cache:	false,
        success: function(data,status){
            if (data['class'] != null && data['class'] == "TPV" &&
                data.tag != null && data.lon != null && data.lat != null &&
                data['mode'] != null && data['mode'] >=1){
                self.handleGpsResponse(data);
                log("gpsdata: "+self.formattedData.gpsPosition);
                self.handleGpsStatus(true);
            }
            else{
                self.handleGpsStatus(false);
            }
            self.timer=window.setTimeout(function(){
                self.startQuery();
            },timeout);
        },
        error: function(status,data,error){
            log("query position error");
            self.handleGpsStatus(false);
            self.timer=window.setTimeout(function(){
                self.startQuery();
            },timeout);
        },
        timeout: 10000
    });

};

/**
 * handle the status and trigger the FPS event
 * @param success
 */
avnav.nav.GpsData.prototype.handleGpsStatus=function(success){
    if (! success){
        this.gpsErrors++;
        if (this.gpsErrors > this.propertyHandler.getProperties().maxGpsErrors){
            log("lost gps");
            this.validPosition=false;
            this.gpsdata.valid=false;
            //continue to count errrors...
        }
        else{
            return;
        }
    }
    else {
        this.gpsErrors=0;
        this.validPosition=true;
    }
    this.navobject.gpsEvent();
};

/**
 * return the current gpsdata
 * @returns {avnav.nav.navdata.GpsInfo}
 */
avnav.nav.GpsData.prototype.getGpsData=function(){
    return this.gpsdata;
};

/**
 * get the formatted value of a GPS item
 * currently the status is not considered
 * @param name
 * @returns {*}
 */
avnav.nav.GpsData.prototype.getFormattedGpsValue=function(name){
    return this.formattedData[name];
};

/**
 * get the currently defined names for formatted data
 * @returns {Array}
 */
avnav.nav.GpsData.prototype.getValueNames=function(){
    var rt=new Array();
    for (var k in this.formattedData){
        rt.push(k);
    }
    return rt;
};

<commit_msg>reset status when no gps data arrives<commit_after>/**
 * Created by andreas on 04.05.14.
 */
avnav.provide('avnav.nav.GpsData');

/**
 * the handler for the gps data
 * query the server...
 * @param {avnav.util.PropertyHandler} propertyHandler
 * @param {avnav.nav.NavObject} navobject
 * @constructor
 */
avnav.nav.GpsData=function(propertyHandler,navobject){
    /** @private */
    this.propertyHandler=propertyHandler;
    /** @private */
    this.navobject=navobject;
    /** @private */
    this.gpsdata=new avnav.nav.navdata.GpsInfo();
    /** @private */
    this.formattedData= {
        gpsPosition:"NO FIX",
        gpsCourse:"0",
        gpsSpeed:"0",
        gpsTime:"---",
        nmeaStatusColor:"red",
        nmeaStatusText:"???",
        aisStatusColor: "red",
        aisStatusText: "???"
    };
    /** {avnav.util.Formatter} @private */
    this.formatter=new avnav.util.Formatter();
    this.timer=null;
    /** {Boolean} @private */
    this.validPosition=false;
    this.gpsErrors=0;
    this.NM=this.propertyHandler.getProperties().NM;
    this.startQuery();
    for (var k in this.formattedData){
        this.navobject.registerValueProvider(k,this,this.getFormattedGpsValue);
    }
};

/**
 *
 * @param data
 * @private
 */
avnav.nav.GpsData.prototype.handleGpsResponse=function(data){
    var gpsdata=new avnav.nav.navdata.GpsInfo();
    gpsdata.rtime=null;
    if (data.time != null) gpsdata.rtime=new Date(data.time);
    gpsdata.lon=data.lon;
    gpsdata.lat=data.lat;
    gpsdata.course=data.course;
    if (gpsdata.course === undefined) gpsdata.course=data.track;
    gpsdata.speed=data.speed*3600/this.NM;
    gpsdata.valid=true;
    gpsdata.raw=data.raw;
    this.gpsdata=gpsdata;
    var formattedData={};
    formattedData.gpsPosition=this.formatter.formatLonLats(gpsdata);
    formattedData.gpsCourse=this.formatter.formatDecimal(gpsdata.course||0,3,0);
    formattedData.gpsSpeed=this.formatter.formatDecimal(gpsdata.speed||0,2,1);
    formattedData.gpsTime=this.formatter.formatTime(gpsdata.rtime||new Date());
    formattedData.nmeaStatusColor="red";
    formattedData.nmeaStatusText="???"
    try {
        if (data.raw && data.raw.status && data.raw.status.nmea){
            formattedData.nmeaStatusColor = data.raw.status.nmea.status;
            formattedData.nmeaStatusText=data.raw.status.nmea.source+":"+data.raw.status.nmea.info;
        }
    }catch(e){}
    formattedData.aisStatusColor="red";
    formattedData.aisStatusText="???"
    try {
        if (data.raw && data.raw.status && data.raw.status.ais){
            formattedData.aisStatusColor = data.raw.status.ais.status;
            formattedData.aisStatusText=data.raw.status.ais.source+":"+data.raw.status.ais.info;
        }
    }catch(e){}

    this.formattedData=formattedData;
};

/**
 * @private
 */
avnav.nav.GpsData.prototype.startQuery=function(){
    var url=this.propertyHandler.getProperties().navUrl;
    var timeout=this.propertyHandler.getProperties().positionQueryTimeout;
    var self=this;
    $.ajax({
        url: url,
        dataType: 'json',
        cache:	false,
        success: function(data,status){
            if (data['class'] != null && data['class'] == "TPV" &&
                data.tag != null && data.lon != null && data.lat != null &&
                data['mode'] != null && data['mode'] >=1){
                self.handleGpsResponse(data);
                log("gpsdata: "+self.formattedData.gpsPosition);
                self.handleGpsStatus(true);
            }
            else{
                self.handleGpsStatus(false);
            }
            self.timer=window.setTimeout(function(){
                self.startQuery();
            },timeout);
        },
        error: function(status,data,error){
            log("query position error");
            self.handleGpsStatus(false);
            self.timer=window.setTimeout(function(){
                self.startQuery();
            },timeout);
        },
        timeout: 10000
    });

};

/**
 * handle the status and trigger the FPS event
 * @param success
 */
avnav.nav.GpsData.prototype.handleGpsStatus=function(success){
    if (! success){
        this.gpsErrors++;
        if (this.gpsErrors > this.propertyHandler.getProperties().maxGpsErrors){
            log("lost gps");
            this.handleGpsResponse({});
            this.validPosition=false;
            this.gpsdata.valid=false;

            //continue to count errrors...
        }
        else{
            return;
        }
    }
    else {
        this.gpsErrors=0;
        this.validPosition=true;
    }
    this.navobject.gpsEvent();
};

/**
 * return the current gpsdata
 * @returns {avnav.nav.navdata.GpsInfo}
 */
avnav.nav.GpsData.prototype.getGpsData=function(){
    return this.gpsdata;
};

/**
 * get the formatted value of a GPS item
 * currently the status is not considered
 * @param name
 * @returns {*}
 */
avnav.nav.GpsData.prototype.getFormattedGpsValue=function(name){
    return this.formattedData[name];
};

/**
 * get the currently defined names for formatted data
 * @returns {Array}
 */
avnav.nav.GpsData.prototype.getValueNames=function(){
    var rt=new Array();
    for (var k in this.formattedData){
        rt.push(k);
    }
    return rt;
};

<|endoftext|>


<commit_before>var element = document.getElementById('vis');

var camera, scene, renderer, first, world;

var line_material = new THREE.LineBasicMaterial({
  linewidth: 2,
  color: 0x000000,
  transparent: true,
  opacity: 0.4
});

console.log("WEBGL3d")

var m = location.hash.match('box=(.*)$');
if(!m) throw new Error("no box selected");

box = m[1].split(',').map(parseFloat);

var w = 600, h = 600;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, w / h, 0.00000001, 1000 );

renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize( w, h );
renderer.setClearColor( 0xeeeeee );
element.appendChild( renderer.domElement );

world = new THREE.Object3D();
scene.add(world)

var globe_geometry = new THREE.IcosahedronGeometry( 6371000, 5 );
var globe_material = new THREE.MeshBasicMaterial( {
  color: 0x0ccccc,
  transparent:true,
  opacity: 0.2,
  wireframe: true
} );
var globe = new THREE.Mesh( globe_geometry, globe_material );
world.add( globe );

// find target from bounding box (url hash)
var p = geofn.cartesian(box);
var target = new THREE.Vector3( p[0], p[1], p[2] )

// rotate so that target is at 0,0 in the world view
world.quaternion.setFromUnitVectors(target.clone().normalize(), new THREE.Vector3(0,1,0))
world.position.y = - target.length()

window.focusOn = function(coords){
  // todo animate
  var p = geofn.cartesian(coords);
  var target = new THREE.Vector3( p[0], p[1], p[2] )

  // rotate so that target is at 0,0 in the world view
  world.quaternion.setFromUnitVectors(target.clone().normalize(), new THREE.Vector3(0,1,0))
  world.position.y = - target.length()
}

camera.position.z = 200;
camera.position.y = 100;

controls = new THREE.OrbitControls( camera );
controls.damping = 0.2;

db
  .activities

  .filter(function(activity){
    return activity.path && activity.path.length
  })

  .each(function(activity){

    // could simplify here if we hit any problems

    var data = new Float32Array(activity.path.length * 3);

    activity.path.forEach(function(p, i){
      data.set(geofn.cartesian([p.longitude, p.latitude, p.altitude]), i*3)
    });

    var geometry = new THREE.BufferGeometry();

    geometry.addAttribute( 'position', new THREE.BufferAttribute( data, 3 ) );
    geometry.computeBoundingSphere();

    mesh = new THREE.Line( geometry, line_material );

    globe.add( mesh );

  })

function render() {
	requestAnimationFrame( render );
	renderer.render( scene, camera );
}
render();
<commit_msg>track webgl draw time (2.6s on iMac)<commit_after>var element = document.getElementById('vis');

var camera, scene, renderer, first, world;

var line_material = new THREE.LineBasicMaterial({
  linewidth: 2,
  color: 0x000000,
  transparent: true,
  opacity: 0.4
});

console.log("WEBGL3d")

var m = location.hash.match('box=(.*)$');
if(!m) throw new Error("no box selected");

box = m[1].split(',').map(parseFloat);

var w = 600, h = 600;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, w / h, 0.00000001, 1000 );

renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize( w, h );
renderer.setClearColor( 0xeeeeee );
element.appendChild( renderer.domElement );

world = new THREE.Object3D();
scene.add(world)

var globe_geometry = new THREE.IcosahedronGeometry( 6371000, 5 );
var globe_material = new THREE.MeshBasicMaterial( {
  color: 0x0ccccc,
  transparent:true,
  opacity: 0.2,
  wireframe: true
} );
var globe = new THREE.Mesh( globe_geometry, globe_material );
world.add( globe );

// find target from bounding box (url hash)
var p = geofn.cartesian(box);
var target = new THREE.Vector3( p[0], p[1], p[2] )

// rotate so that target is at 0,0 in the world view
world.quaternion.setFromUnitVectors(target.clone().normalize(), new THREE.Vector3(0,1,0))
world.position.y = - target.length()

window.focusOn = function(coords){
  // todo animate
  var p = geofn.cartesian(coords);
  var target = new THREE.Vector3( p[0], p[1], p[2] )

  // rotate so that target is at 0,0 in the world view
  world.quaternion.setFromUnitVectors(target.clone().normalize(), new THREE.Vector3(0,1,0))
  world.position.y = - target.length()
}

camera.position.z = 200;
camera.position.y = 100;

controls = new THREE.OrbitControls( camera );
controls.damping = 0.2;

db
  .activities

  .filter(function(activity){
    return activity.path && activity.path.length
  })

  .each(function(activity){

    // could simplify here if we hit any problems

    var data = new Float32Array(activity.path.length * 3);

    activity.path.forEach(function(p, i){
      data.set(geofn.cartesian([p.longitude, p.latitude, p.altitude]), i*3)
    });

    var geometry = new THREE.BufferGeometry();

    geometry.addAttribute( 'position', new THREE.BufferAttribute( data, 3 ) );
    geometry.computeBoundingSphere();

    mesh = new THREE.Line( geometry, line_material );

    globe.add( mesh );

  })

  .then(function(){
    console.log('render time: %s seconds', (window.performance.now()/1000).toFixed(2))
  })

function render() {
	requestAnimationFrame( render );
	renderer.render( scene, camera );
}
render();
<|endoftext|>


<commit_before>/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
  var major;
  var count = 0;
  var mid = (nums.length >> 1);

  for (var i = 0; i< nums.length; i ++) {
    var val = nums[i];
    if (count === 0) {
      count = 1;
      major = val;
    } else if (major === val) {
      count ++;
    } else {
      count --;
    }

    if (count > mid) break;
  }

  return major;
};

var eq = require('assert').equal;
eq(majorityElement([1, 2, 3, 4, 5, 5, 5, 5, 5]), 5);
eq(majorityElement([1, 2, 5, 5, 5, 5]), 5);
eq(majorityElement([5, 5, 3]), 5);
<commit_msg>add commment<commit_after>/**
 * @param {number[]} nums
 * @return {number}
 */
// a genius solution, check http://is.gd/j5nJsb
var majorityElement = function(nums) {
  var major;
  var count = 0;
  var mid = (nums.length >> 1);

  for (var i = 0; i< nums.length; i ++) {
    var val = nums[i];
    if (count === 0) {
      count = 1;
      major = val;
    } else if (major === val) {
      count ++;
    } else {
      count --;
    }

    if (count > mid) break;
  }

  return major;
};

var eq = require('assert').equal;
eq(majorityElement([1, 2, 3, 4, 5, 5, 5, 5, 5]), 5);
eq(majorityElement([1, 2, 5, 5, 5, 5]), 5);
eq(majorityElement([5, 5, 3]), 5);
<|endoftext|>