<commit_before>/**
 * Created by AsherS on 8/24/15.
 */

var _ = require('underscore');
var logger = require('./logger/logger')(module);
var flavorDownloader = require('./FlavorDownloader');
var persistenceFormat = require('./../common/PersistenceFormat');
var config = require('./../common/Configuration');
var ErrorUtils = require('./utils/error-utils');
var fsUtils = require('./utils/fs-utils');
var path = require('path');
var Q = require('q');
var qio = require('q-io/fs');
var util = require('util');
var events = require("events");
var m3u8Parser = require('./manifest/promise-m3u8');

var EntryDownloader = (function () {

    function EntryDownloader(entryObject, isNewSession) {
        events.EventEmitter.call(this);
        this.entryId = entryObject.entryId;
        this.manifestTimeWindow = entryObject.manifestTimeWindow;
        this.manifestMaxChunkCount = entryObject.maxChunkCount;
        this.flavorsDownloaders = [];
        this.isNewSession = isNewSession;
        this.streamInfo = entryObject.getStreamInfo();
    }
    util.inherits(EntryDownloader, events.EventEmitter);

    var onFlavorDownloaderStopped = function(flavor){
        var that = this;
        logger.info("Flavor " + flavor + " stopped - checking if any flavor is still active for entry " + that.entryId);
        if (_.every(that.flavorsDownloaders, function(f){ return f.runStatus === 'stopped'; }))
        {
            logger.info("No remaining active flavor downloaders for entry " + that.entryId + " - shutting down entry downloader");
            that.emit('stopped', that.entryId);
        }
    };

    var checkTranscodingProfileChange = function(entryId, flavorsObjArray) {
        var entryPath = persistenceFormat.getEntryFullPath(entryId);
        var reg = new RegExp("(?:" + entryId + "\\/)([0-9]*)\\b", "i");
        return qio.listDirectoryTree(entryPath)
            .then(function(result) {
                return _.chain(result)
                    .filter(function(d) {
                        return d.match(reg) !== null;
                    })
                    .map(function(d) {
                        return d.match(reg)[1];
                    })
                    .uniq(function(f) {
                        return f;
                    })
                    .value();
            })
            .then(function(result) {
                var playingFlavorsString = _.map(flavorsObjArray, function(f) {
                    return f.name;
                }).sort().join();
                if (result.sort().join() !== playingFlavorsString) {
                    logger.info("Transcoding profile changed, cleaning entry " + entryId + "folder");
                    return fsUtils.cleanFolder(entryPath);
                }
            })
            .then(function() {
                return flavorsObjArray;
            })
            .catch(function(error) {
                logger.error("Error cleaning folder because of transcoding profile change: " + error);
            });
    };

    var savePlaylist = function (flavorsObjArray, entryId) {
        var playlist = new m3u8Parser.M3U.create();
        playlist.set("version",3);

        _.each(flavorsObjArray, function(flavor) {
            playlist.addStreamItem({
                bandwidth: flavor.bandwidth,
                resolution: flavor.resolution.join("x"),
                uri: flavor.name+'/chunklist.m3u8'
            });
        });
        // Get the destination to save the manifest
        var destPath = path.join(config.get('rootFolderPath'), entryId, persistenceFormat.getMasterManifestName());
        var playerMasterManifest = playlist.toString();
        logger.info("Entry: " + entryId + "received master manifest:\n" + playerMasterManifest);
        return fsUtils.writeFileAtomically(destPath, playerMasterManifest)
            .then(function() {
                return flavorsObjArray;
            });
    };

    EntryDownloader.prototype.start = function () {
        var that = this;
        logger.info("Entry start requested for entry " + that.entryId);
        logger.info("Starting entry downloader for entryId: " + that.entryId + "\n");
        return that.streamInfo.getAllFlavors()
            .then(function(flavors) {
                return (!that.isNewSession) ? checkTranscodingProfileChange(that.entryId, flavors) : flavors;
            })
            .then(function(flavors) {
                return savePlaylist(flavors, that.entryId);
            })
            .then(function(flavors) {
                that.flavorsDownloaders = _.chain(flavors)
                    .uniq(function(flavor) {
                        // Iterate through the flavors array and erase duplicate flavors if they exists
                        return flavor.name;
                    })
                    .map(function (flavor) {
                        var playlistName = persistenceFormat.getManifestName();
                        var destPath = persistenceFormat.getFlavorFullPath(that.entryId, flavor.name);
                        logger.info("EntryId: " + that.entryId + " - creating flavor downloader: " + flavor.name);
                        return new flavorDownloader(flavor.liveURL, destPath, that.entryId, flavor.name, playlistName, that.manifestTimeWindow, that.manifestMaxChunkCount);
                    }).value();

                //start the download
                var promises = _.map(that.flavorsDownloaders, function (f) {
                    logger.info("EntryId: " + that.entryId + " - starting flavor downloader: " + f.flavor);
                    f.on('stopped', onFlavorDownloaderStopped.bind(that));
                    return f.start();
                });

                return Q.allSettled(promises);

            })
            .then(function(results) {
                var errs = ErrorUtils.aggregateErrors(results);

                if (errs.numErrors === results.length) {
                    // Fail if no flavor downloader could be started
                    throw new Error("Failed to start entry downloader for entry: " + that.entryId + ". All flavor downloaders failed");
                }

                if (errs.numErrors > 0) {
                    // Report an error (but proceed) if only some flavor downloaders could not be started
                    logger.error('Failed to start flavor downloaders for some of the flavors:\n',errs.err);
                }
            });
    };

    EntryDownloader.prototype.stop = function () {
        var that = this;
        if (that.stopPromise)
        {
            logger.info("Entry stop already requested for entry " + this.entryId + " ignoring request");
            return that.stopPromise;
        }

        logger.info('stopping entry downloader for entry id: ' + this.entryId);
        var stopPromises =_.map(this.flavorsDownloaders, function (downloader) {
            return downloader.stop();
        });

        that.stopPromise = Q.all(stopPromises).then(function(){
            logger.info('successfully stopped entry downloader for entry id: ' + that.entryId);
        }, function(err){
            logger.error('failed stopping flavor downloader for entry id: ' + that.entryId + ' and flavor ' + downloader.flavor + "\n" + err + "\n" + err.stack);
            throw err;
        });

        return that.stopPromise;
    };

    return EntryDownloader;
})();

module.exports = EntryDownloader;<commit_msg>fixing  DVR windows duration<commit_after>/**
 * Created by AsherS on 8/24/15.
 */

var _ = require('underscore');
var logger = require('./logger/logger')(module);
var flavorDownloader = require('./FlavorDownloader');
var persistenceFormat = require('./../common/PersistenceFormat');
var config = require('./../common/Configuration');
var ErrorUtils = require('./utils/error-utils');
var fsUtils = require('./utils/fs-utils');
var path = require('path');
var Q = require('q');
var qio = require('q-io/fs');
var util = require('util');
var events = require("events");
var m3u8Parser = require('./manifest/promise-m3u8');

var EntryDownloader = (function () {

    function EntryDownloader(entryObject, isNewSession) {
        events.EventEmitter.call(this);
        this.entryId = entryObject.entryId;
        this.manifestTimeWindow = entryObject.dvrWindow;
        this.manifestMaxChunkCount = entryObject.maxChunkCount;
        this.flavorsDownloaders = [];
        this.isNewSession = isNewSession;
        this.streamInfo = entryObject.getStreamInfo();
    }
    util.inherits(EntryDownloader, events.EventEmitter);

    var onFlavorDownloaderStopped = function(flavor){
        var that = this;
        logger.info("Flavor " + flavor + " stopped - checking if any flavor is still active for entry " + that.entryId);
        if (_.every(that.flavorsDownloaders, function(f){ return f.runStatus === 'stopped'; }))
        {
            logger.info("No remaining active flavor downloaders for entry " + that.entryId + " - shutting down entry downloader");
            that.emit('stopped', that.entryId);
        }
    };

    var checkTranscodingProfileChange = function(entryId, flavorsObjArray) {
        var entryPath = persistenceFormat.getEntryFullPath(entryId);
        var reg = new RegExp("(?:" + entryId + "\\/)([0-9]*)\\b", "i");
        return qio.listDirectoryTree(entryPath)
            .then(function(result) {
                return _.chain(result)
                    .filter(function(d) {
                        return d.match(reg) !== null;
                    })
                    .map(function(d) {
                        return d.match(reg)[1];
                    })
                    .uniq(function(f) {
                        return f;
                    })
                    .value();
            })
            .then(function(result) {
                var playingFlavorsString = _.map(flavorsObjArray, function(f) {
                    return f.name;
                }).sort().join();
                if (result.sort().join() !== playingFlavorsString) {
                    logger.info("Transcoding profile changed, cleaning entry " + entryId + "folder");
                    return fsUtils.cleanFolder(entryPath);
                }
            })
            .then(function() {
                return flavorsObjArray;
            })
            .catch(function(error) {
                logger.error("Error cleaning folder because of transcoding profile change: " + error);
            });
    };

    var savePlaylist = function (flavorsObjArray, entryId) {
        var playlist = new m3u8Parser.M3U.create();
        playlist.set("version",3);

        _.each(flavorsObjArray, function(flavor) {
            playlist.addStreamItem({
                bandwidth: flavor.bandwidth,
                resolution: flavor.resolution.join("x"),
                uri: flavor.name+'/chunklist.m3u8'
            });
        });
        // Get the destination to save the manifest
        var destPath = path.join(config.get('rootFolderPath'), entryId, persistenceFormat.getMasterManifestName());
        var playerMasterManifest = playlist.toString();
        logger.info("Entry: " + entryId + "received master manifest:\n" + playerMasterManifest);
        return fsUtils.writeFileAtomically(destPath, playerMasterManifest)
            .then(function() {
                return flavorsObjArray;
            });
    };

    EntryDownloader.prototype.start = function () {
        var that = this;
        logger.info("Entry start requested for entry " + that.entryId);
        logger.info("Starting entry downloader for entryId: " + that.entryId + "\n");
        return that.streamInfo.getAllFlavors()
            .then(function(flavors) {
                return (!that.isNewSession) ? checkTranscodingProfileChange(that.entryId, flavors) : flavors;
            })
            .then(function(flavors) {
                return savePlaylist(flavors, that.entryId);
            })
            .then(function(flavors) {
                that.flavorsDownloaders = _.chain(flavors)
                    .uniq(function(flavor) {
                        // Iterate through the flavors array and erase duplicate flavors if they exists
                        return flavor.name;
                    })
                    .map(function (flavor) {
                        var playlistName = persistenceFormat.getManifestName();
                        var destPath = persistenceFormat.getFlavorFullPath(that.entryId, flavor.name);
                        logger.info("EntryId: " + that.entryId + " - creating flavor downloader: " + flavor.name);
                        return new flavorDownloader(flavor.liveURL, destPath, that.entryId, flavor.name, playlistName, that.manifestTimeWindow, that.manifestMaxChunkCount);
                    }).value();

                //start the download
                var promises = _.map(that.flavorsDownloaders, function (f) {
                    logger.info("EntryId: " + that.entryId + " - starting flavor downloader: " + f.flavor);
                    f.on('stopped', onFlavorDownloaderStopped.bind(that));
                    return f.start();
                });

                return Q.allSettled(promises);

            })
            .then(function(results) {
                var errs = ErrorUtils.aggregateErrors(results);

                if (errs.numErrors === results.length) {
                    // Fail if no flavor downloader could be started
                    throw new Error("Failed to start entry downloader for entry: " + that.entryId + ". All flavor downloaders failed");
                }

                if (errs.numErrors > 0) {
                    // Report an error (but proceed) if only some flavor downloaders could not be started
                    logger.error('Failed to start flavor downloaders for some of the flavors:\n',errs.err);
                }
            });
    };

    EntryDownloader.prototype.stop = function () {
        var that = this;
        if (that.stopPromise)
        {
            logger.info("Entry stop already requested for entry " + this.entryId + " ignoring request");
            return that.stopPromise;
        }

        logger.info('stopping entry downloader for entry id: ' + this.entryId);
        var stopPromises =_.map(this.flavorsDownloaders, function (downloader) {
            return downloader.stop();
        });

        that.stopPromise = Q.all(stopPromises).then(function(){
            logger.info('successfully stopped entry downloader for entry id: ' + that.entryId);
        }, function(err){
            logger.error('failed stopping flavor downloader for entry id: ' + that.entryId + ' and flavor ' + downloader.flavor + "\n" + err + "\n" + err.stack);
            throw err;
        });

        return that.stopPromise;
    };

    return EntryDownloader;
})();

module.exports = EntryDownloader;<|endoftext|>


<commit_before>var dgram = require('dgram');

/*global console*/

function EphemeralSocket(options) {
    this.options = options || {};

    this.options.host = this.options.host || 'localhost';
    this.options.port = this.options.port || 8125;
    this.options.debug = this.options.debug || false;
    this.options.socket_timeout = this.options.socket_timeout || 1000;

    // Set up re-usable socket
    this._socket = undefined; // Store the socket here
    this._socketUsed = false; // Flag if it has been used
    this._socketTimer = undefined; // Reference to check-timer
}

/*
 * Check if the socket has been used in the previous socket_timeout-interval.
 * If it has, we leave it open and try again later. If it hasn't, close it.
 */
EphemeralSocket.prototype._socket_timeout = function () {
    // Is it already closed? -- then stop here
    if (!this._socket) {
        return;
    }

    // Has been used? -- reset use-flag and wait some more
    if (this._socketUsed) {
        this._socketUsed = false;
        return;
    }

    // Not used? -- close the socket
    this.close();
};

/*
 * Close the socket, if in use and cancel the interval-check, if running.
 */
EphemeralSocket.prototype.close = function () {
    if (!this._socket) {
        return;
    }

    //Make sure further errors do not propagate upwards
    this._socket.on("error", function() {});

    // Cancel the running timer
    clearInterval(this._socketTimer);

    // Wait a tick or two, so any remaining stats can be sent.
    var that = this;
    setTimeout(function () {
        that._socket.close();
        that._socket = undefined;
    }, 10);
};

EphemeralSocket.prototype._createSocket = function (callback) {
    var that = this;
    if (this._socket) {
        return callback();
    }

    this._socket = dgram.createSocket('udp4');

    // Listen on 'error'-events, so they don't bubble up to the main
    // application. Try closing the socket for now, forcing it to be re-created
    // later.
    this._socket.once('error', this.close.bind(this));

    // Call on when the socket is ready.
    this._socket.once('listening', function () {
        return callback();
    });
    this._socket.bind(0, null);

    // Start timer, if we have a positive timeout
    if (this.options.socket_timeout > 0) {
        this._socketTimer = setInterval(this._socket_timeout.bind(this), this.options.socket_timeout);
    }
};

/*
 * Send data.
 */
EphemeralSocket.prototype.send = function (data) {
    // If we don't have a socket, or we have created one but it isn't
    // ready yet, we need to enqueue data to send once the socket is ready.
    var that = this;

    this._createSocket(function () {
        that._socketUsed = true;

        // Create message
        var message = new Buffer(data);

        if (that.options.debug) {
            console.warn(message.toString());
        }

        that._socket.send(message, 0, message.length, that.options.port, that.options.host);
    });
};

module.exports = EphemeralSocket;
<commit_msg>Style conformity<commit_after>var dgram = require('dgram');

/*global console*/

function EphemeralSocket(options) {
    this.options = options || {};

    this.options.host = this.options.host || 'localhost';
    this.options.port = this.options.port || 8125;
    this.options.debug = this.options.debug || false;
    this.options.socket_timeout = this.options.socket_timeout || 1000;

    // Set up re-usable socket
    this._socket = undefined; // Store the socket here
    this._socketUsed = false; // Flag if it has been used
    this._socketTimer = undefined; // Reference to check-timer
}

/*
 * Check if the socket has been used in the previous socket_timeout-interval.
 * If it has, we leave it open and try again later. If it hasn't, close it.
 */
EphemeralSocket.prototype._socket_timeout = function () {
    // Is it already closed? -- then stop here
    if (!this._socket) {
        return;
    }

    // Has been used? -- reset use-flag and wait some more
    if (this._socketUsed) {
        this._socketUsed = false;
        return;
    }

    // Not used? -- close the socket
    this.close();
};

/*
 * Close the socket, if in use and cancel the interval-check, if running.
 */
EphemeralSocket.prototype.close = function () {
    if (!this._socket) {
        return;
    }

    //Make sure further errors do not propagate upwards
    this._socket.on("error", function () {});

    // Cancel the running timer
    clearInterval(this._socketTimer);

    // Wait a tick or two, so any remaining stats can be sent.
    var that = this;
    setTimeout(function () {
        that._socket.close();
        that._socket = undefined;
    }, 10);
};

EphemeralSocket.prototype._createSocket = function (callback) {
    var that = this;
    if (this._socket) {
        return callback();
    }

    this._socket = dgram.createSocket('udp4');

    // Listen on 'error'-events, so they don't bubble up to the main
    // application. Try closing the socket for now, forcing it to be re-created
    // later.
    this._socket.once('error', this.close.bind(this));

    // Call on when the socket is ready.
    this._socket.once('listening', function () {
        return callback();
    });
    this._socket.bind(0, null);

    // Start timer, if we have a positive timeout
    if (this.options.socket_timeout > 0) {
        this._socketTimer = setInterval(this._socket_timeout.bind(this), this.options.socket_timeout);
    }
};

/*
 * Send data.
 */
EphemeralSocket.prototype.send = function (data) {
    // If we don't have a socket, or we have created one but it isn't
    // ready yet, we need to enqueue data to send once the socket is ready.
    var that = this;

    this._createSocket(function () {
        that._socketUsed = true;

        // Create message
        var message = new Buffer(data);

        if (that.options.debug) {
            console.warn(message.toString());
        }

        that._socket.send(message, 0, message.length, that.options.port, that.options.host);
    });
};

module.exports = EphemeralSocket;
<|endoftext|>


<commit_before>/*
 * grunt-contrib-watch
 * http://gruntjs.com/
 *
 * Copyright (c) 2013 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
  'use strict';

  var path = require('path');
  var Gaze = require('gaze').Gaze;
  var taskrun = require('./lib/taskrunner')(grunt);

  var waiting = 'Waiting...';
  var changedFiles = Object.create(null);
  var watchers = [];

  // When task runner has started
  taskrun.on('start', function() {
    grunt.log.ok();
    Object.keys(changedFiles).forEach(function(filepath) {
      // Log which file has changed, and how.
      grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.');
    });
    taskrun.changedFiles = changedFiles;
    // Reset changedFiles
    changedFiles = Object.create(null);
  });

  // When task runner has ended
  taskrun.on('end', function(time) {
    if (time > 0) {
      grunt.log.writeln(String(
        'Completed in ' +
        time.toFixed(3) +
        's at ' +
        (new Date()).toString()
      ).cyan + ' - ' + waiting);
    }
  });

  // When a task run has been interrupted
  taskrun.on('interrupt', function() {
    grunt.log.writeln('').write('Scheduled tasks have been interrupted...'.yellow);
  });

  // When taskrun is reloaded
  taskrun.on('reload', function() {
    taskrun.clearRequireCache(Object.keys(changedFiles));
    grunt.log.writeln('').writeln('Reloading watch config...'.cyan);
  });

  // On shutdown, close up watchers
  process.on('SIGINT', function() {
    grunt.log.writeln('').write('Shutting down the watch task...');
    watchers.forEach(function(watcher) {
      watcher.close();
    });
    grunt.log.ok();
    process.exit();
  });

  grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) {
    var self = this;
    var name = self.name || 'watch';

    // Never gonna give you up, never gonna let you down
    if (grunt.config([name, 'options', 'forever']) !== false) {
      taskrun.forever();
    }

    if (taskrun.running === false) { grunt.log.write(waiting); }

    // initialize taskrun
    var targets = taskrun.init(name, {
      interrupt: false,
      nospawn: false,
      event: ['all'],
      target: target,
    });

    targets.forEach(function(target, i) {
      if (typeof target.files === 'string') { target.files = [target.files]; }

      // Process into raw patterns
      var patterns = grunt.util._.chain(target.files).flatten().map(function(pattern) {
        return grunt.config.process(pattern);
      }).value();

      // Validate the event option
      if (typeof target.options.event === 'string') {
        target.options.event = [target.options.event];
      }

      // Create watcher per target
      watchers.push(new Gaze(patterns, target.options, function(err) {
        if (err) {
          if (typeof err === 'string') { err = new Error(err); }
          grunt.log.writeln('ERROR'.red);
          grunt.fatal(err);
          return taskrun.done();
        }

        // Log all watched files with --verbose set
        if (grunt.option('verbose')) {
          var watched = this.watched();
          Object.keys(watched).forEach(function(watchedDir) {
            watched[watchedDir].forEach(function(watchedFile) {
              grunt.log.writeln('Watching ' + path.relative(process.cwd(), watchedFile) + ' for changes.');
            });
          });
        }

        // On changed/added/deleted
        this.on('all', function(status, filepath) {

          // Skip events not specified
          if (!grunt.util._.contains(target.options.event, 'all') &&
              !grunt.util._.contains(target.options.event, status)) {
            return;
          }

          filepath = path.relative(process.cwd(), filepath);

          // If Gruntfile.js changed, reload self task
          if (/gruntfile\.(js|coffee)/i.test(filepath)) {
            taskrun.reload = true;
          }

          // Emit watch events if anyone is listening
          if (grunt.event.listeners('watch').length > 0) {
            grunt.event.emit('watch', status, filepath);
          }

          // Run tasks if any have been specified
          if (target.tasks) {
            changedFiles[filepath] = status;
            taskrun.queue(target.name);
            taskrun.run();
          }
        });

        // On watcher error
        this.on('error', function(err) {
          if (typeof err === 'string') { err = new Error(err); }
          grunt.log.error(err.message);
        });
      }));
    });

  });
};
<commit_msg>Write new line after file change. Closes GH-86.<commit_after>/*
 * grunt-contrib-watch
 * http://gruntjs.com/
 *
 * Copyright (c) 2013 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
  'use strict';

  var path = require('path');
  var Gaze = require('gaze').Gaze;
  var taskrun = require('./lib/taskrunner')(grunt);

  var waiting = 'Waiting...';
  var changedFiles = Object.create(null);
  var watchers = [];

  // When task runner has started
  taskrun.on('start', function() {
    grunt.log.ok();
    Object.keys(changedFiles).forEach(function(filepath) {
      // Log which file has changed, and how.
      grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.');
    });
    grunt.log.writeln();
    taskrun.changedFiles = changedFiles;
    // Reset changedFiles
    changedFiles = Object.create(null);
  });

  // When task runner has ended
  taskrun.on('end', function(time) {
    if (time > 0) {
      grunt.log.writeln(String(
        'Completed in ' +
        time.toFixed(3) +
        's at ' +
        (new Date()).toString()
      ).cyan + ' - ' + waiting);
    }
  });

  // When a task run has been interrupted
  taskrun.on('interrupt', function() {
    grunt.log.writeln('').write('Scheduled tasks have been interrupted...'.yellow);
  });

  // When taskrun is reloaded
  taskrun.on('reload', function() {
    taskrun.clearRequireCache(Object.keys(changedFiles));
    grunt.log.writeln('').writeln('Reloading watch config...'.cyan);
  });

  // On shutdown, close up watchers
  process.on('SIGINT', function() {
    grunt.log.writeln('').write('Shutting down the watch task...');
    watchers.forEach(function(watcher) {
      watcher.close();
    });
    grunt.log.ok();
    process.exit();
  });

  grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) {
    var self = this;
    var name = self.name || 'watch';

    // Never gonna give you up, never gonna let you down
    if (grunt.config([name, 'options', 'forever']) !== false) {
      taskrun.forever();
    }

    if (taskrun.running === false) { grunt.log.write(waiting); }

    // initialize taskrun
    var targets = taskrun.init(name, {
      interrupt: false,
      nospawn: false,
      event: ['all'],
      target: target,
    });

    targets.forEach(function(target, i) {
      if (typeof target.files === 'string') { target.files = [target.files]; }

      // Process into raw patterns
      var patterns = grunt.util._.chain(target.files).flatten().map(function(pattern) {
        return grunt.config.process(pattern);
      }).value();

      // Validate the event option
      if (typeof target.options.event === 'string') {
        target.options.event = [target.options.event];
      }

      // Create watcher per target
      watchers.push(new Gaze(patterns, target.options, function(err) {
        if (err) {
          if (typeof err === 'string') { err = new Error(err); }
          grunt.log.writeln('ERROR'.red);
          grunt.fatal(err);
          return taskrun.done();
        }

        // Log all watched files with --verbose set
        if (grunt.option('verbose')) {
          var watched = this.watched();
          Object.keys(watched).forEach(function(watchedDir) {
            watched[watchedDir].forEach(function(watchedFile) {
              grunt.log.writeln('Watching ' + path.relative(process.cwd(), watchedFile) + ' for changes.');
            });
          });
        }

        // On changed/added/deleted
        this.on('all', function(status, filepath) {

          // Skip events not specified
          if (!grunt.util._.contains(target.options.event, 'all') &&
              !grunt.util._.contains(target.options.event, status)) {
            return;
          }

          filepath = path.relative(process.cwd(), filepath);

          // If Gruntfile.js changed, reload self task
          if (/gruntfile\.(js|coffee)/i.test(filepath)) {
            taskrun.reload = true;
          }

          // Emit watch events if anyone is listening
          if (grunt.event.listeners('watch').length > 0) {
            grunt.event.emit('watch', status, filepath);
          }

          // Run tasks if any have been specified
          if (target.tasks) {
            changedFiles[filepath] = status;
            taskrun.queue(target.name);
            taskrun.run();
          }
        });

        // On watcher error
        this.on('error', function(err) {
          if (typeof err === 'string') { err = new Error(err); }
          grunt.log.error(err.message);
        });
      }));
    });

  });
};
<|endoftext|>


<commit_before>/*
 * grunt-xcode
 * https://github.com/matiassingers/grunt-xcode
 *
 * Copyright (c) 2014 Matias Singers
 * Licensed under the MIT license.
 */
'use strict';

var Promise = require('bluebird');
var temporary = require('temporary');
var chalk = require('chalk');
var exec = require('child_process').exec;

String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        formatted = formatted.replace(
            RegExp('\\{' + i + '\\}', 'g'), arguments[i]);
    }
    return formatted;
};

function safelyWrap(string){
  return JSON.stringify(string);
}

module.exports = function(grunt) {
  function executeCommand(args){
    var command = 'xcodebuild ' + args.join(' ');
    grunt.verbose.writeln('Command:', chalk.yellow(command));

    return new Promise(function(resolve, reject){
      // See Sindre Sorhus' grunt-shell - https://github.com/sindresorhus/grunt-shell/blob/master/tasks/shell.js
      var cmd = exec(command, {maxBuffer: 1000*1024}, function(error){
        if(error) {
          grunt.warn(error);

          reject(error);
        }

        resolve();
      });

      var captureOutput = function (child, output) {
        if (grunt.option('color') === false) {
          child.on('data', function (data) {
            output.write(chalk.stripColor(data));
          });
        } else {
          child.pipe(output);
        }
      };

      if (grunt.option('verbose')) {
        captureOutput(cmd.stdout, process.stdout);
      }

      if (grunt.option('verbose')) {
        captureOutput(cmd.stderr, process.stderr);
      }
    });
  }

  grunt.registerMultiTask('xcode', 'Build and export Xcode projects with Grunt', function() {
    var done = this.async();

    var options = this.options({
      clean: true,
      export: true,
      project: '',
      configuration: '',
      workspace: '',
      scheme: '',
      allTargets: true,
      target: '',
      archivePath: '',
      exportFormat: 'IPA',
      exportPath: process.cwd(),
      exportFilename: 'export.ipa',
      exportProvisioningProfile: '',
      exportSigningIdentity: '',
      exportInstallerIdentity: '',
      arch: '',
      sdk: ''
    });

    if(!options.project && !options.workspace){
      throw new Error('`options.project` or `options.workspace` is required');
    }

    if(options.workspace && !options.scheme){
      throw new Error('`options.scheme` is required when building a workspace');
    }

    if(!options.archivePath){
      var temporaryDirectory = new temporary.Dir();
      options.archivePath = temporaryDirectory.path;
    }

    runCleanCommand()
      .then(runArchiveCommand)
      .then(runExportCommand)
      .finally(cleanUp);

    function runCleanCommand(){
      if(!options.clean){
        return Promise.resolve();
      }

      var command = ['clean'];
      if(options.project) command.push('-project', safelyWrap(options.project));

      return executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild clean` was successful');
        });
    }
    function runArchiveCommand(){
      if(!options.export) {
        return Promise.resolve();
      }

      var command = ['archive'];
      command.push('-archivePath', safelyWrap(options.archivePath));

      if(options.project) command.push('-project', safelyWrap(options.project));
      if(options.configuration) command.push('-configuration', safelyWrap(options.configuration));
      if(options.workspace) command.push('-workspace', safelyWrap(options.workspace));
      if(options.scheme) command.push('-scheme', safelyWrap(options.scheme));

      if(options.arch) command.push('-arch', safelyWrap(options.arch));
      if(options.sdk) command.push('-sdk', safelyWrap(options.sdk));

      if(options.target){
        command.push('-target', safelyWrap(options.target));
      } else if(options.allTargets && !options.scheme) {
        command.push('-alltargets');
      }

      return executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild archive` was successful');
        });
    }
    function runExportCommand(){
      if(!options.export) {
        return Promise.resolve();
      }

      var command = ['-exportArchive'];
      command.push('-archivePath "{0}.xcarchive"'.format(options.archivePath));
      command.push('-exportPath "{0}/{1}"'.format(options.exportPath, options.exportFilename));

      command.push('-exportFormat', options.exportFormat);

      if(options.exportProvisioningProfile) command.push('-exportProvisioningProfile', safelyWrap(options.exportProvisioningProfile));
      if(options.exportSigningIdentity) command.push('-exportSigningIdentity', safelyWrap(options.exportSigningIdentity));
      if(options.exportInstallerIdentity) command.push('-exportInstallerIdentity', safelyWrap(options.exportInstallerIdentity));
      if(!options.exportSigningIdentity) command.push('-exportWithOriginalSigningIdentity');

      executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild export` was successful');
        });
    }
    function cleanUp(){
      if(temporaryDirectory){
        temporaryDirectory.rmdir();
      }

      if(options.export){
        grunt.log.ok('Built and exported product to: {0}/{1}'.format(options.exportPath, options.exportFilename));
      }

      done();
    }
  });
};
<commit_msg>Add poor man's progress indicator with dots every 1000ms<commit_after>/*
 * grunt-xcode
 * https://github.com/matiassingers/grunt-xcode
 *
 * Copyright (c) 2014 Matias Singers
 * Licensed under the MIT license.
 */
'use strict';

var Promise = require('bluebird');
var temporary = require('temporary');
var chalk = require('chalk');
var exec = require('child_process').exec;

String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        formatted = formatted.replace(
            RegExp('\\{' + i + '\\}', 'g'), arguments[i]);
    }
    return formatted;
};

function safelyWrap(string){
  return JSON.stringify(string);
}

module.exports = function(grunt) {
  function executeCommand(args){
    var command = 'xcodebuild ' + args.join(' ');
    grunt.verbose.writeln('Command:', chalk.yellow(command));

    return new Promise(function(resolve, reject){
      // poor man's progress indicator
      var progress = setInterval(function(){
        grunt.log.write(chalk.green('.'));
      }, 1000);

      // See Sindre Sorhus' grunt-shell - https://github.com/sindresorhus/grunt-shell/blob/master/tasks/shell.js
      var cmd = exec(command, {maxBuffer: 1000*1024}, function(error){
        clearInterval(progress);
        grunt.log.write(' \n');

        if(error) {
          grunt.warn(error);

          reject(error);
        }

        resolve();
      });

      var captureOutput = function (child, output) {
        if (grunt.option('color') === false) {
          child.on('data', function (data) {
            output.write(chalk.stripColor(data));
          });
        } else {
          child.pipe(output);
        }
      };

      if (grunt.option('verbose')) {
        captureOutput(cmd.stdout, process.stdout);
      }

      if (grunt.option('verbose')) {
        captureOutput(cmd.stderr, process.stderr);
      }
    });
  }

  grunt.registerMultiTask('xcode', 'Build and export Xcode projects with Grunt', function() {
    var done = this.async();

    var options = this.options({
      clean: true,
      export: true,
      project: '',
      configuration: '',
      workspace: '',
      scheme: '',
      allTargets: true,
      target: '',
      archivePath: '',
      exportFormat: 'IPA',
      exportPath: process.cwd(),
      exportFilename: 'export.ipa',
      exportProvisioningProfile: '',
      exportSigningIdentity: '',
      exportInstallerIdentity: '',
      arch: '',
      sdk: ''
    });

    if(!options.project && !options.workspace){
      throw new Error('`options.project` or `options.workspace` is required');
    }

    if(options.workspace && !options.scheme){
      throw new Error('`options.scheme` is required when building a workspace');
    }

    if(!options.archivePath){
      var temporaryDirectory = new temporary.Dir();
      options.archivePath = temporaryDirectory.path;
    }

    runCleanCommand()
      .then(runArchiveCommand)
      .then(runExportCommand)
      .finally(cleanUp);

    function runCleanCommand(){
      if(!options.clean){
        return Promise.resolve();
      }

      var command = ['clean'];
      if(options.project) command.push('-project', safelyWrap(options.project));

      return executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild clean` was successful');
        });
    }
    function runArchiveCommand(){
      if(!options.export) {
        return Promise.resolve();
      }

      var command = ['archive'];
      command.push('-archivePath', safelyWrap(options.archivePath));

      if(options.project) command.push('-project', safelyWrap(options.project));
      if(options.configuration) command.push('-configuration', safelyWrap(options.configuration));
      if(options.workspace) command.push('-workspace', safelyWrap(options.workspace));
      if(options.scheme) command.push('-scheme', safelyWrap(options.scheme));

      if(options.arch) command.push('-arch', safelyWrap(options.arch));
      if(options.sdk) command.push('-sdk', safelyWrap(options.sdk));

      if(options.target){
        command.push('-target', safelyWrap(options.target));
      } else if(options.allTargets && !options.scheme) {
        command.push('-alltargets');
      }

      grunt.log.write('Archiving: ');
      return executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild archive` was successful');
        });
    }
    function runExportCommand(){
      if(!options.export) {
        return Promise.resolve();
      }

      var command = ['-exportArchive'];
      command.push('-archivePath "{0}.xcarchive"'.format(options.archivePath));
      command.push('-exportPath "{0}/{1}"'.format(options.exportPath, options.exportFilename));

      command.push('-exportFormat', options.exportFormat);

      if(options.exportProvisioningProfile) command.push('-exportProvisioningProfile', safelyWrap(options.exportProvisioningProfile));
      if(options.exportSigningIdentity) command.push('-exportSigningIdentity', safelyWrap(options.exportSigningIdentity));
      if(options.exportInstallerIdentity) command.push('-exportInstallerIdentity', safelyWrap(options.exportInstallerIdentity));
      if(!options.exportSigningIdentity) command.push('-exportWithOriginalSigningIdentity');

      grunt.log.write('Exporting: ');
      return executeCommand(command)
        .then(function(){
          grunt.verbose.ok('`xcodebuild export` was successful');
        });
    }
    function cleanUp(){
      if(temporaryDirectory){
        temporaryDirectory.rmdir();
      }

      if(options.export){
        grunt.log.ok('Built and exported product to: {0}/{1}'.format(options.exportPath, options.exportFilename));
      }

      done();
    }
  });
};
<|endoftext|>


<commit_before>"use strict";

if(!Math.randomInt)
{
	Math.randomInt = function(min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	};
}

if(!Math.randomIntExcluding)
{
	Math.randomIntExcluding = function(min, max, excluding)
	{
		excluding = Array.toArray(excluding);

		var num;
		do
		{
			num = Math.randomInt(min, max);
		} while(excluding.contains(num));

		return num;
	};
}

if(!Math.getRotatedDimensions)
{
	Math.getRotatedDimensions = function(angle_in_degrees, width, height)
	{
		var angle = angle_in_degrees * Math.PI / 180,
			sin   = Math.sin(angle),
			cos   = Math.cos(angle);
		var x1 = cos * width,
			y1 = sin * width;
		var x2 = -sin * height,
			y2 = cos * height;
		var x3 = cos * width - sin * height,
			y3 = sin * width + cos * height;
		var minX = Math.min(0, x1, x2, x3),
			maxX = Math.max(0, x1, x2, x3),
			minY = Math.min(0, y1, y2, y3),
			maxY = Math.max(0, y1, y2, y3);

		return [ Math.floor((maxX - minX)), Math.floor((maxY - minY)) ];
	};
}

if(!Math.degreesToRadians)
{
	Math.degreesToRadians = function(degrees)
	{
		return degrees * (Math.PI/180);
	};
}

if(!Math.radiansToDegrees)
{
	Math.radiansToDegrees = function(radians)
	{
		return radians * (180/Math.PI);
	};
}

if(!Math.rotatePointInBox)
{
	Math.rotatePointInBox = function(x, y, angle, width, height)
	{
		angle = Math.degreesToRadians(angle);

		var centerX = width / 2.0;
		var centerY = height / 2.0;
		var dx = x - centerX;
		var dy = y - centerY;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var a =  Math.atan2(dy, dx) + angle;
		var dx2 = Math.cos(a) * dist;
		var dy2 = Math.sin(a) * dist;

		return [ dx2 + centerX, dy2 + centerY ];
	};
}<commit_msg>Fixed an infinite loop bug if you excluded all possible numbers from random<commit_after>"use strict";

if(!Math.randomInt)
{
	Math.randomInt = function(min, max)
	{
		return Math.floor(Math.random() * (max - min + 1)) + min;
	};
}

if(!Math.randomIntExcluding)
{
	Math.randomIntExcluding = function(min, max, excluding)
	{
		excluding = Array.toArray(excluding).map(function(i) { return i.truncate(); }).filter(function(i) { return i>=min && i<=max; }).uniqueBySort();
		if(excluding.length===((max-min)+1))
			throw new RangeError("randomIntExcluding called with excluding all nums, no possible return value");

		var num;
		do
		{
			num = Math.randomInt(min, max);
		} while(excluding.contains(num));

		return num;
	};
}

if(!Math.getRotatedDimensions)
{
	Math.getRotatedDimensions = function(angle_in_degrees, width, height)
	{
		var angle = angle_in_degrees * Math.PI / 180,
			sin   = Math.sin(angle),
			cos   = Math.cos(angle);
		var x1 = cos * width,
			y1 = sin * width;
		var x2 = -sin * height,
			y2 = cos * height;
		var x3 = cos * width - sin * height,
			y3 = sin * width + cos * height;
		var minX = Math.min(0, x1, x2, x3),
			maxX = Math.max(0, x1, x2, x3),
			minY = Math.min(0, y1, y2, y3),
			maxY = Math.max(0, y1, y2, y3);

		return [ Math.floor((maxX - minX)), Math.floor((maxY - minY)) ];
	};
}

if(!Math.degreesToRadians)
{
	Math.degreesToRadians = function(degrees)
	{
		return degrees * (Math.PI/180);
	};
}

if(!Math.radiansToDegrees)
{
	Math.radiansToDegrees = function(radians)
	{
		return radians * (180/Math.PI);
	};
}

if(!Math.rotatePointInBox)
{
	Math.rotatePointInBox = function(x, y, angle, width, height)
	{
		angle = Math.degreesToRadians(angle);

		var centerX = width / 2.0;
		var centerY = height / 2.0;
		var dx = x - centerX;
		var dy = y - centerY;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var a =  Math.atan2(dy, dx) + angle;
		var dx2 = Math.cos(a) * dist;
		var dy2 = Math.sin(a) * dist;

		return [ dx2 + centerX, dy2 + centerY ];
	};
}<|endoftext|>


<commit_before>function randomPoint(rect) {
    return {x: rect.x + Math.random() * rect.width,
            y: rect.y + Math.random() * rect.height};
}

function generateRandomCircles(count, minRadius, maxRadius) {
    var range = {x : 0,  y : 0, height : 1, width : 1},
        output = [];

    for (var i = 0; i < count; ++i ) {
        var p = randomPoint(range);
        p.radius = Math.random() * (maxRadius - minRadius) + minRadius;
        output.push(p);
    }

    return output;
}

function getCombinations(input) {
    var output = [];
    function inner(i, current) {
        for (var j = i + 1; j < input.length; ++j) {
            var next = current.slice();
            next.push(input[j]);
            output.push(next);
            inner(j, next);
        }
    }
    inner(-1, []);
    return output;
}

function getAllIntersections(circles) {
    var setids = circles.map(function (x, i) { return i; });
    return getCombinations(setids).map(function (ids) {
        return {sets: ids,
                size: venn.intersectionArea(ids.map(function(i) {
                    return circles[i]; }))
            };
    });
}

function getIntersections(circles) {
    return getAllIntersections(circles)
        .filter(function(a) { return (a.sets.length <= 2); });
}

function getErrors(areas, current) {
    var intersections = areas.filter(function (a) {
        return a.sets.length ==2;
    });

    var total = 0, i;
    for (i = 0; i < areas.length; ++i) {
        total += areas[i].size;
    }

    var ret = [];
    for (i = 0; i < areas.length; ++i) {
        var area = areas[i];
        if (area.sets.length == 2) {
            var left = current[area.sets[0]], right = current[area.sets[1]],
                overlap = venn.circleOverlap(left.radius, right.radius,
                                            venn.distance(left, right)),
                delta = Math.abs(overlap - area.size);

            if (isNaN(delta)) {
                ret.push(area);
            }

            else if ((delta / (1e-10 + Math.max(area.size, overlap)) >= 0.1) &&
                (delta > total / (50000))) {
                ret.push(area);
            }
        }
    }
    return ret;
}

function hilightErrors(div, areas, current, duration) {
    // calculate success, and highlight failures in red
    var failedAreas = getErrors(areas, current);

    div.select(".venn-intersection path")
        .style("stroke-width", 0).style("fill-opacity", 0);

    for (var i = 0; i < failedAreas.length; ++i) {
        var area = failedAreas[i];
        div.selectAll('[data-venn-sets="' + area.sets[0] + "_" + area.sets[1] + '"] path')
            .style("stroke", "red")
            .style("stroke-opacity", 1)
            .style("stroke-width", 2)
            .style("fill", "red")
            .style("fill-opacity", 0.2);
    }
    return failedAreas.length === 0;
}

// converts our areas into disjoint areas for use by other libraries
// like matplotlib_venn, venneuler etc
function makeDisjoint(areas) {
    var lookup = {};
    var ret = [], i;
    for (i = 0; i < areas.length; ++i) {
        var clone = {sets: areas[i].sets, size:areas[i].size};
        lookup[areas[i].sets] = clone;
        ret.push(clone);
    }

    ret.sort(function(a, b) {
        return b.sets.length - a.sets.length;
    });

    for (i = 0; i < ret.length; ++i) {
        var area = ret[i];
        var supersets = getCombinations(area.sets);
        for (var j = 0; j < supersets.length; ++j) {
            if (supersets[j].length < area.sets.length) {
                lookup[supersets[j]].size -= area.size;
            }
        }
    }
    return ret;
}

var MIN_CIRCLES = 2, MAX_CIRCLES = 8;
function getCircleCategories() {
    var ret = [];
    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        ret.push(i);
    }
    return ret;
}

// tracks status of perfomance of each algorithm
function VennAlgorithm(name, method) {
    this.name = name;
    this.method = method;
    this.errors = {};
    this.counts = {};
    this.times = {};

    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        this.errors[i] = 0;
        this.counts[i] = 0;
        this.times[i] = 0;
    }
}

// test out the algorithm with the current circles/intersection areas
VennAlgorithm.prototype.update = function(intersections, computed, elapsed) {
    var count = intersections.filter(function(a) { return a.sets.length == 1; }).length;
    if (getErrors(intersections, computed).length > 0)  {
        this.errors[count] += 1;
    }
    this.counts[count] += 1;
    this.times[count] += elapsed;
};

VennAlgorithm.prototype.reset = function() {
    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        this.errors[i] = 0;
        this.counts[i] = 0;
        this.times[i] = 0;
    }
};

// random layout: poor choice
function randomLayout(areas) {
    var range = {x : 0,  y : 0, height : 1, width : 1};
    var ret = [];
    for (var i = 0; i < areas.length; ++i) {
        var area = areas[i];
        if (area.sets.length == 1) {
            ret.push({x : Math.random(),
                      y : Math.random(),
                      radius: Math.sqrt(area.size / Math.PI)});
        }
    }
    return ret;
}

function bestInitial(areas) {
    var g = venn.greedyLayout(areas);
    var w  = constrainedMDSLayout(areas, {restarts:5});
    if (venn.lossFunction(w, areas) < venn.lossFunction(g, areas)) {
        g = w;
    }
    return g;
}

function createPerformanceChart(selector,
                                algorithms,
                                precalcPerf,
                                precalcSpeed) {
    function getPerformanceData() {
        var columns = [];
        for (var i = 0; i < algorithms.length; ++i) {
            var algo = algorithms[i];
            var column = [algo.name];
            for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) {

                var c = algo.counts[j] || 1;
                column.push((c - algo.errors[j] ) / c);
            }
            columns.push(column);
        }

        return { 'columns' : columns };
    }
    this.getPerformanceData = getPerformanceData;

    function getSpeedData() {
        var columns = [];
        for (var i = 0; i < algorithms.length; ++i) {
            var algo = algorithms[i];
            var column = [algo.name];
            for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) {
                var c = algo.counts[j] || 1;
                column.push(algo.times[j] / c);
            }
            columns.push(column);
        }

        return { 'columns' : columns };
    }

    this.getSpeedData = getSpeedData;

    var performanceChart = c3.generate({
        bindto: selector + " #perfchart",
        axis: {
            x: {
                label: {text: 'Number of Sets', position: 'outer-center'},
                type: 'category',
                categories: getCircleCategories(),
            },
            y: {label: {text: 'Success Rate', position: 'outer-middle'},
                min:0.05,
                max:1,
                tick : {format: function(d) { return (100*d).toFixed(0) +
                "%";}}
            },
        },
        tooltip : {
            format : {
                title: function(x) { return (x + MIN_CIRCLES) + " Sets";} ,
                value: function(x) { return "" + (100*x).toFixed(2) + "%"; },
            },
        },
        data:precalcPerf || getPerformanceData() });

    var speedChart = c3.generate({
        bindto: selector + " #speedchart",
        axis: {
            x: {
                label: {text: 'Number of Sets', position: 'outer-center'},
                type: 'category',
                categories: getCircleCategories(),
            },
            y: {label: {text: 'Average Time (ms)', position: 'outer-middle'}}
        },
        tooltip : {
            format : {
                title: function(x) { return (x + MIN_CIRCLES) + " Sets";} ,
                value: function(x) { return "" + x.toFixed(2) + " ms"; },
            },
        },
        data:precalcSpeed || getSpeedData() });

    var lastCount = 0, lastTime = 0, totalCount = 0;
    var circleCount = MIN_CIRCLES;
    paused = true;
    var element = d3.select(selector);
    var pauseIcon = element.select(".pause-button .glyphicon");

    function pause() {
        paused = true;
        element.select(".pause-label").text(" Resume");
        pauseIcon.attr("class", "glyphicon glyphicon-play");
    }

    function resume() {
        paused = false;
        element.select(".pause-label").text(" Pause");
        pauseIcon.attr("class", "glyphicon glyphicon-pause");
        testIteration();
    }

    function togglePause() {
        if (paused) {
            resume();
        } else {
            pause();
        }
    }

    var minRadius = 0.1, maxRadius = 1.0;
    function setRadii(low, hi) {
        minRadius = low;
        maxRadius = hi;
        for (var i = 0; i < algorithms.length; ++i) {
            algorithms[i].reset();
        }
        lastCount = 0;
        lastTime = 0;
        totalCount = 0;
        circleCount = MIN_CIRCLES;
        resume();
    }
    this.setRadii = setRadii;

    element.select(".pause-button").on("click",  togglePause);

    var intersectionFunction = getIntersections;
    this.intersectionFunction = function(_) {
        if (!arguments.length) return intersectionFunction;
        intersectionFunction = _;
    };

    // single iteration
    function testIteration() {
        element.select("#warning").style("display", "none");
        circleCount += 1;
        if (circleCount > MAX_CIRCLES) {
            circleCount = MIN_CIRCLES;
        }

        // slightly awkkard here, needed to work properly with deferreds,
        // returns a function that when called with the computed values
        // updates the algorithm counts.
        function update(algorithm, intersections, start) {
            return function(computed) {
                var elapsed = performance.now() - start;
                algorithm.update(intersections, computed, elapsed);
            };
        }

        var circles = generateRandomCircles(circleCount, minRadius, maxRadius);

        var intersections = intersectionFunction(circles);

        var deferred = [];
        for (var i = 0; i < algorithms.length; ++i ) {
            var updateResults = update(algorithms[i], intersections, performance.now()),
                computed = algorithms[i].method(intersections);

            if ("then" in computed) {
                deferred.push(computed.then(updateResults));
            } else {
                updateResults(computed);
            }
        }

        // wait for deferred objects to finish, possibly reload graph if
        // needed
        $.when.apply($, deferred).then(function() {
            var count = 0;
            for (var i = MIN_CIRCLES; i < MAX_CIRCLES; ++i) {
                count += algorithms[0].counts[i];
            }
            element.select("#iterations").text("Total trails: " + count);

            // constantly reloading the charts causes issues with hover
            // slow it down to every 10 seconds, with faster reloads at beginning
            if (((Math.log(count) - Math.log(lastCount))  >= 0.1) ||
                (performance.now() >= lastTime + 10 * 1000))  {
                performanceChart.load(getPerformanceData());
                speedChart.load(getSpeedData());
                lastCount = count;
                lastTime = performance.now();
            }

            if (!paused) {
                window.setTimeout(testIteration, 0);
            }
        }, function(error) {
            console.log("Failed to run performance test");
            console.log(error);
            element.select("#warning").html("Failed! Well that didn't work, is everything running ok?").style("display", "block");
            pause();
        });
    }
}
<commit_msg>clear previous hilight<commit_after>function randomPoint(rect) {
    return {x: rect.x + Math.random() * rect.width,
            y: rect.y + Math.random() * rect.height};
}

function generateRandomCircles(count, minRadius, maxRadius) {
    var range = {x : 0,  y : 0, height : 1, width : 1},
        output = [];

    for (var i = 0; i < count; ++i ) {
        var p = randomPoint(range);
        p.radius = Math.random() * (maxRadius - minRadius) + minRadius;
        output.push(p);
    }

    return output;
}

function getCombinations(input) {
    var output = [];
    function inner(i, current) {
        for (var j = i + 1; j < input.length; ++j) {
            var next = current.slice();
            next.push(input[j]);
            output.push(next);
            inner(j, next);
        }
    }
    inner(-1, []);
    return output;
}

function getAllIntersections(circles) {
    var setids = circles.map(function (x, i) { return i; });
    return getCombinations(setids).map(function (ids) {
        return {sets: ids,
                size: venn.intersectionArea(ids.map(function(i) {
                    return circles[i]; }))
            };
    });
}

function getIntersections(circles) {
    return getAllIntersections(circles)
        .filter(function(a) { return (a.sets.length <= 2); });
}

function getErrors(areas, current) {
    var intersections = areas.filter(function (a) {
        return a.sets.length ==2;
    });

    var total = 0, i;
    for (i = 0; i < areas.length; ++i) {
        total += areas[i].size;
    }

    var ret = [];
    for (i = 0; i < areas.length; ++i) {
        var area = areas[i];
        if (area.sets.length == 2) {
            var left = current[area.sets[0]], right = current[area.sets[1]],
                overlap = venn.circleOverlap(left.radius, right.radius,
                                            venn.distance(left, right)),
                delta = Math.abs(overlap - area.size);

            if (isNaN(delta)) {
                ret.push(area);
            }

            else if ((delta / (1e-10 + Math.max(area.size, overlap)) >= 0.1) &&
                (delta > total / (50000))) {
                ret.push(area);
            }
        }
    }
    return ret;
}

function hilightErrors(div, areas, current, duration) {
    // calculate success, and highlight failures in red
    var failedAreas = getErrors(areas, current);

    div.selectAll(".venn-intersection path")
        .style("stroke-width", 0).style("fill-opacity", 0);

    for (var i = 0; i < failedAreas.length; ++i) {
        var area = failedAreas[i];
        div.selectAll('[data-venn-sets="' + area.sets[0] + "_" + area.sets[1] + '"] path')
            .style("stroke", "red")
            .style("stroke-opacity", 1)
            .style("stroke-width", 2)
            .style("fill", "red")
            .style("fill-opacity", 0.2);
    }
    return failedAreas.length === 0;
}

// converts our areas into disjoint areas for use by other libraries
// like matplotlib_venn, venneuler etc
function makeDisjoint(areas) {
    var lookup = {};
    var ret = [], i;
    for (i = 0; i < areas.length; ++i) {
        var clone = {sets: areas[i].sets, size:areas[i].size};
        lookup[areas[i].sets] = clone;
        ret.push(clone);
    }

    ret.sort(function(a, b) {
        return b.sets.length - a.sets.length;
    });

    for (i = 0; i < ret.length; ++i) {
        var area = ret[i];
        var supersets = getCombinations(area.sets);
        for (var j = 0; j < supersets.length; ++j) {
            if (supersets[j].length < area.sets.length) {
                lookup[supersets[j]].size -= area.size;
            }
        }
    }
    return ret;
}

var MIN_CIRCLES = 2, MAX_CIRCLES = 8;
function getCircleCategories() {
    var ret = [];
    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        ret.push(i);
    }
    return ret;
}

// tracks status of perfomance of each algorithm
function VennAlgorithm(name, method) {
    this.name = name;
    this.method = method;
    this.errors = {};
    this.counts = {};
    this.times = {};

    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        this.errors[i] = 0;
        this.counts[i] = 0;
        this.times[i] = 0;
    }
}

// test out the algorithm with the current circles/intersection areas
VennAlgorithm.prototype.update = function(intersections, computed, elapsed) {
    var count = intersections.filter(function(a) { return a.sets.length == 1; }).length;
    if (getErrors(intersections, computed).length > 0)  {
        this.errors[count] += 1;
    }
    this.counts[count] += 1;
    this.times[count] += elapsed;
};

VennAlgorithm.prototype.reset = function() {
    for (var i = MIN_CIRCLES; i <= MAX_CIRCLES; ++i) {
        this.errors[i] = 0;
        this.counts[i] = 0;
        this.times[i] = 0;
    }
};

// random layout: poor choice
function randomLayout(areas) {
    var range = {x : 0,  y : 0, height : 1, width : 1};
    var ret = [];
    for (var i = 0; i < areas.length; ++i) {
        var area = areas[i];
        if (area.sets.length == 1) {
            ret.push({x : Math.random(),
                      y : Math.random(),
                      radius: Math.sqrt(area.size / Math.PI)});
        }
    }
    return ret;
}

function bestInitial(areas) {
    var g = venn.greedyLayout(areas);
    var w  = constrainedMDSLayout(areas, {restarts:5});
    if (venn.lossFunction(w, areas) < venn.lossFunction(g, areas)) {
        g = w;
    }
    return g;
}

function createPerformanceChart(selector,
                                algorithms,
                                precalcPerf,
                                precalcSpeed) {
    function getPerformanceData() {
        var columns = [];
        for (var i = 0; i < algorithms.length; ++i) {
            var algo = algorithms[i];
            var column = [algo.name];
            for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) {

                var c = algo.counts[j] || 1;
                column.push((c - algo.errors[j] ) / c);
            }
            columns.push(column);
        }

        return { 'columns' : columns };
    }
    this.getPerformanceData = getPerformanceData;

    function getSpeedData() {
        var columns = [];
        for (var i = 0; i < algorithms.length; ++i) {
            var algo = algorithms[i];
            var column = [algo.name];
            for (var j = MIN_CIRCLES; j <= MAX_CIRCLES; ++j) {
                var c = algo.counts[j] || 1;
                column.push(algo.times[j] / c);
            }
            columns.push(column);
        }

        return { 'columns' : columns };
    }

    this.getSpeedData = getSpeedData;

    var performanceChart = c3.generate({
        bindto: selector + " #perfchart",
        axis: {
            x: {
                label: {text: 'Number of Sets', position: 'outer-center'},
                type: 'category',
                categories: getCircleCategories(),
            },
            y: {label: {text: 'Success Rate', position: 'outer-middle'},
                min:0.05,
                max:1,
                tick : {format: function(d) { return (100*d).toFixed(0) +
                "%";}}
            },
        },
        tooltip : {
            format : {
                title: function(x) { return (x + MIN_CIRCLES) + " Sets";} ,
                value: function(x) { return "" + (100*x).toFixed(2) + "%"; },
            },
        },
        data:precalcPerf || getPerformanceData() });

    var speedChart = c3.generate({
        bindto: selector + " #speedchart",
        axis: {
            x: {
                label: {text: 'Number of Sets', position: 'outer-center'},
                type: 'category',
                categories: getCircleCategories(),
            },
            y: {label: {text: 'Average Time (ms)', position: 'outer-middle'}}
        },
        tooltip : {
            format : {
                title: function(x) { return (x + MIN_CIRCLES) + " Sets";} ,
                value: function(x) { return "" + x.toFixed(2) + " ms"; },
            },
        },
        data:precalcSpeed || getSpeedData() });

    var lastCount = 0, lastTime = 0, totalCount = 0;
    var circleCount = MIN_CIRCLES;
    paused = true;
    var element = d3.select(selector);
    var pauseIcon = element.select(".pause-button .glyphicon");

    function pause() {
        paused = true;
        element.select(".pause-label").text(" Resume");
        pauseIcon.attr("class", "glyphicon glyphicon-play");
    }

    function resume() {
        paused = false;
        element.select(".pause-label").text(" Pause");
        pauseIcon.attr("class", "glyphicon glyphicon-pause");
        testIteration();
    }

    function togglePause() {
        if (paused) {
            resume();
        } else {
            pause();
        }
    }

    var minRadius = 0.1, maxRadius = 1.0;
    function setRadii(low, hi) {
        minRadius = low;
        maxRadius = hi;
        for (var i = 0; i < algorithms.length; ++i) {
            algorithms[i].reset();
        }
        lastCount = 0;
        lastTime = 0;
        totalCount = 0;
        circleCount = MIN_CIRCLES;
        resume();
    }
    this.setRadii = setRadii;

    element.select(".pause-button").on("click",  togglePause);

    var intersectionFunction = getIntersections;
    this.intersectionFunction = function(_) {
        if (!arguments.length) return intersectionFunction;
        intersectionFunction = _;
    };

    // single iteration
    function testIteration() {
        element.select("#warning").style("display", "none");
        circleCount += 1;
        if (circleCount > MAX_CIRCLES) {
            circleCount = MIN_CIRCLES;
        }

        // slightly awkkard here, needed to work properly with deferreds,
        // returns a function that when called with the computed values
        // updates the algorithm counts.
        function update(algorithm, intersections, start) {
            return function(computed) {
                var elapsed = performance.now() - start;
                algorithm.update(intersections, computed, elapsed);
            };
        }

        var circles = generateRandomCircles(circleCount, minRadius, maxRadius);

        var intersections = intersectionFunction(circles);

        var deferred = [];
        for (var i = 0; i < algorithms.length; ++i ) {
            var updateResults = update(algorithms[i], intersections, performance.now()),
                computed = algorithms[i].method(intersections);

            if ("then" in computed) {
                deferred.push(computed.then(updateResults));
            } else {
                updateResults(computed);
            }
        }

        // wait for deferred objects to finish, possibly reload graph if
        // needed
        $.when.apply($, deferred).then(function() {
            var count = 0;
            for (var i = MIN_CIRCLES; i < MAX_CIRCLES; ++i) {
                count += algorithms[0].counts[i];
            }
            element.select("#iterations").text("Total trails: " + count);

            // constantly reloading the charts causes issues with hover
            // slow it down to every 10 seconds, with faster reloads at beginning
            if (((Math.log(count) - Math.log(lastCount))  >= 0.1) ||
                (performance.now() >= lastTime + 10 * 1000))  {
                performanceChart.load(getPerformanceData());
                speedChart.load(getSpeedData());
                lastCount = count;
                lastTime = performance.now();
            }

            if (!paused) {
                window.setTimeout(testIteration, 0);
            }
        }, function(error) {
            console.log("Failed to run performance test");
            console.log(error);
            element.select("#warning").html("Failed! Well that didn't work, is everything running ok?").style("display", "block");
            pause();
        });
    }
}
<|endoftext|>


<commit_before>
var net = require('net');
var util = require('util');
var binding = require('bindings')('abstract_socket.node');

var socket  = binding.socket;
var bind    = binding.bind;
var connect = binding.connect;
var close   = binding.close;

function errnoException(errorno, syscall) {
    // TODO: having the errno message here would be nice
    var e = new Error(syscall + ' ' + errorno);
    e.errno = e.code = errorno;
    e.syscall = syscall;
    return e;
}

function AbstractSocketServer(connectionListener) {
    net.Server.call(this, connectionListener);
}
util.inherits(AbstractSocketServer, net.Server);

AbstractSocketServer.prototype.listen = function(name, listeningListener) {
    var err = socket();
    if (err < 0)
        throw errnoException(err, 'socket');

    var handle = {fd: err};

    err = bind(err, name);
    if (err < 0) {
        close(handle.fd);
        throw errnoException(err, 'bind');
    }

    net.Server.prototype.listen.call(this, handle, listeningListener);
};

exports.createServer = function(connectionListener) {
    return new AbstractSocketServer(connectionListener);
};

exports.connect = function(name, connectListener) {
    var err = socket();
    if (err < 0)
        throw errnoException(err, 'socket');

    var options = {fd: err, readable: true, writable: true};

    // yes, connect is synchronous, so sue me
    err = connect(err, name);
    if (err < 0) {
        close(options.fd);
        throw errnoException(err, 'connect');
    }

    return new net.Socket(options);
};

<commit_msg>createConnection as a synonym to `connect`<commit_after>
var net = require('net');
var util = require('util');
var binding = require('bindings')('abstract_socket.node');

var socket  = binding.socket;
var bind    = binding.bind;
var connect = binding.connect;
var close   = binding.close;

function errnoException(errorno, syscall) {
    // TODO: having the errno message here would be nice
    var e = new Error(syscall + ' ' + errorno);
    e.errno = e.code = errorno;
    e.syscall = syscall;
    return e;
}

function AbstractSocketServer(connectionListener) {
    net.Server.call(this, connectionListener);
}
util.inherits(AbstractSocketServer, net.Server);

AbstractSocketServer.prototype.listen = function(name, listeningListener) {
    var err = socket();
    if (err < 0)
        throw errnoException(err, 'socket');

    var handle = {fd: err};

    err = bind(err, name);
    if (err < 0) {
        close(handle.fd);
        throw errnoException(err, 'bind');
    }

    net.Server.prototype.listen.call(this, handle, listeningListener);
};

exports.createServer = function(connectionListener) {
    return new AbstractSocketServer(connectionListener);
};

exports.connect = function(name, connectListener) {
    var err = socket();
    if (err < 0)
        throw errnoException(err, 'socket');

    var options = {fd: err, readable: true, writable: true};

    // yes, connect is synchronous, so sue me
    err = connect(err, name);
    if (err < 0) {
        close(options.fd);
        throw errnoException(err, 'connect');
    }

    return new net.Socket(options);
};

exports.createConnection = exports.connect;

<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var UndoManager = function() {
    this.$undoStack = [];
    this.$redoStack = [];
};

(function() {

    /*this.$doc = null;
    this.setDocument = function(doc) {
        this.$doc = doc;
    };*/

    this.execute = function(options) {
        var deltas = options.args[0];
        this.$doc  = options.args[1];
        this.$undoStack.push(deltas);
    };

    this.undo = function() {
        var deltas = this.$undoStack.pop();
        if (deltas) {
            this.$doc.undoChanges(deltas);
            this.$redoStack.push(deltas);
        }
    };

    this.redo = function() {
        var deltas = this.$redoStack.pop();
        if (deltas) {
            this.$doc.redoChanges(deltas);
            this.$undoStack.push(deltas);
        }
    };

}).call(UndoManager.prototype);

exports.UndoManager = UndoManager;
});
<commit_msg>remove dead code<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var UndoManager = function() {
    this.$undoStack = [];
    this.$redoStack = [];
};

(function() {

    this.execute = function(options) {
        var deltas = options.args[0];
        this.$doc  = options.args[1];
        this.$undoStack.push(deltas);
    };

    this.undo = function() {
        var deltas = this.$undoStack.pop();
        if (deltas) {
            this.$doc.undoChanges(deltas);
            this.$redoStack.push(deltas);
        }
    };

    this.redo = function() {
        var deltas = this.$redoStack.pop();
        if (deltas) {
            this.$doc.redoChanges(deltas);
            this.$undoStack.push(deltas);
        }
    };

}).call(UndoManager.prototype);

exports.UndoManager = UndoManager;
});
<|endoftext|>


<commit_before>var util = require('util'),
    ActivityTask = require('./activity-task').ActivityTask,
    Poller = require('./poller').Poller;

/**
 * Polls Amazon SWF for new Activity Tasks
 * @constructor
 * @param {Object} config Ex: { domain: "my-domain", taskList: {name: "my-taskList"} }
 * @param {Object} [swfClient]
 * @augments Poller
 * @fires ActivityPoller#activityTask
 * @fires Poller#poll
 * @fires Poller#error
 */
var ActivityPoller = exports.ActivityPoller = function (config, swfClient) {

    Poller.apply(this, arguments);

    config = this.config;
    if (!config.domain || !config.taskList || !config.taskList.name) {
        throw new Error("ActivityPoller: domain and taskList must be set");
    }

    // For the Poller class
    this.pollMethod = "pollForActivityTask";

};

util.inherits(ActivityPoller, Poller);

ActivityPoller.prototype._onNewTask = function(result) {
    var activityTask = new ActivityTask(result, this.swfClient);

    /**
     * Emitted for every activity task received from Amazon SWF
     *
     * @event ActivityPoller#activityTask
     * @property {ActivityTask} activityTask
     */
    var self = this
    this.taskQueue.push(function(callback){
        activityTask.onDone = function(){
            self.logger.debug({"task":activityTask}, "activity done")
            try{
                callback()
            }
            catch(e){
                self.logger.debug({
                    "e":e,
                    "task":activityTask
                }, "How do you trun this on?")
            }
        };
        self.emit('activityTask', activityTask);
    });

};
<commit_msg>Fix activity poller debug logging<commit_after>var util = require('util'),
    ActivityTask = require('./activity-task').ActivityTask,
    Poller = require('./poller').Poller;

/**
 * Polls Amazon SWF for new Activity Tasks
 * @constructor
 * @param {Object} config Ex: { domain: "my-domain", taskList: {name: "my-taskList"} }
 * @param {Object} [swfClient]
 * @augments Poller
 * @fires ActivityPoller#activityTask
 * @fires Poller#poll
 * @fires Poller#error
 */
var ActivityPoller = exports.ActivityPoller = function (config, swfClient) {

    Poller.apply(this, arguments);

    config = this.config;
    if (!config.domain || !config.taskList || !config.taskList.name) {
        throw new Error("ActivityPoller: domain and taskList must be set");
    }

    // For the Poller class
    this.pollMethod = "pollForActivityTask";

};

util.inherits(ActivityPoller, Poller);

ActivityPoller.prototype._onNewTask = function(result) {
    var activityTask = new ActivityTask(result, this.swfClient);

    /**
     * Emitted for every activity task received from Amazon SWF
     *
     * @event ActivityPoller#activityTask
     * @property {ActivityTask} activityTask
     */
    var self = this
    this.taskQueue.push(function(callback){
        activityTask.onDone = function(){
            self.logger.info({"task":activityTask}, "activity done")
            try{
                callback()
            }
            catch(e){
                self.logger.info({
                    "e":e,
                    "task":activityTask
                }, "How do you trun this on?")
            }
        };
        self.emit('activityTask', activityTask);
    });

};
<|endoftext|>


<commit_before>'use strict';
let amqp = require('amqplib/callback_api');
let debug = require('debug')('sn:core:amqp:connection');
let Channel = require('./channel');

function Connection(address) {
  let _connection = null;
  let _channel = null;

  this.connect = (done) => {
    if(_connection !== null) {
      return done(null, _connection);
    }
    debug('connecting...');
    amqp.connect(address, (err, ok) => {
      _connection = ok;
      done(err);
    });
  };
  this.close = (done) => {
    if(_connection === null) {
      debug('connection already disconnected');
      return done();
    }
    debug('disconnecting...');
    _connection.close(() => {
      _connection = null;
      _channel = null;
      done();
    });
  };
  this.createChannel = (done) => {
    if(_channel !== null) {
      return done(null, _channel);
    }
    debug('creating channel');
    _connection.createChannel((err, ok) => {
      _channel = new Channel(ok);
      done(err, _channel);
    });
  };
  return Object.freeze(this);
}
module.exports = Connection;
<commit_msg>Better handling of connection errors<commit_after>'use strict';
let amqp = require('amqplib/callback_api');
let debug = require('debug')('sn:core:amqp:connection');
let Channel = require('./channel');

function Connection(address) {
  let _connection = null;
  let _channel = null;

  this.connect = (done) => {
    if(_connection !== null) {
      return done(null, _connection);
    }
    debug('connecting...');
    amqp.connect(address, (err, ok) => {
      if(err) {
        debug('connection failed!');
        return done(err);
      }

      debug('connection established!', ok);
      _connection = ok;
      done();
    });
  };
  this.close = (done) => {
    if(_connection === null) {
      debug('connection already disconnected');
      return done();
    }
    debug('disconnecting...');
    _connection.close(() => {
      _connection = null;
      _channel = null;
      done();
    });
  };
  this.createChannel = (done) => {
    if(_channel !== null) {
      return done(null, _channel);
    }
    debug('creating channel');
    _connection.createChannel((err, ok) => {
      _channel = new Channel(ok);
      done(err, _channel);
    });
  };
  return Object.freeze(this);
}
module.exports = Connection;
<|endoftext|>


<commit_before>'use strict';
exports.info = {
  desc: 'Get the Twitch ID for a specified user.',
  usage: '<name|id>',
  aliases: [],
  permissions: ['SEND_MESSAGES'],
};

const request = require('snekfetch');

exports.run = (client, msg, params = []) => new Promise(async (resolve, reject) => {
  if (params.length === 0) {
    client.utils.usage(msg, exports.info).then(resolve).catch(reject);
    return;
  }
  const query = params.join(' ').trim().toLowerCase();
  const user = await client.twitch.getUserData(query);
  if (!user) {
    msg.channel.send(`The Twitch channel **${params[0]}** does not exist.`).then(resolve).catch(reject);
    return;
  }

  const uri = client.utils.buildUri('https://api.twitch.tv/helix/subscriptions', {
    user_id: user.id,
    broadcaster_id: client.config.twitch.id,
  });
  const subscription = client.utils.get(['body', 'data', 0],
      await request.get(uri)
          .set({
            'Client-ID': client.config.twitch.client_id,
            Authorization: `Bearer ${client.config.twitch.access_token}`,
          }));

  const name = client.twitch.displayName(user);
  const type = `\n${client.utils.capitalize(user.broadcaster_type)}`;
  const sub = `\nSubscribed: ${Boolean(subscription)}`;
  let str = /^\d+$/.test(query) ? `${user.id} => **${name}**` : `${name} => **${user.id}**`;
  if (user.broadcaster_type) str += type;
  if (subscription) str += sub;
  msg.channel.send(str)
    .then(resolve).catch(reject);
});
<commit_msg>bold bool<commit_after>'use strict';
exports.info = {
  desc: 'Get the Twitch ID for a specified user.',
  usage: '<name|id>',
  aliases: [],
  permissions: ['SEND_MESSAGES'],
};

const request = require('snekfetch');

exports.run = (client, msg, params = []) => new Promise(async (resolve, reject) => {
  if (params.length === 0) {
    client.utils.usage(msg, exports.info).then(resolve).catch(reject);
    return;
  }
  const query = params.join(' ').trim().toLowerCase();
  const user = await client.twitch.getUserData(query);
  if (!user) {
    msg.channel.send(`The Twitch channel **${params[0]}** does not exist.`).then(resolve).catch(reject);
    return;
  }

  const uri = client.utils.buildUri('https://api.twitch.tv/helix/subscriptions', {
    user_id: user.id,
    broadcaster_id: client.config.twitch.id,
  });
  const subscription = client.utils.get(['body', 'data', 0],
      await request.get(uri)
          .set({
            'Client-ID': client.config.twitch.client_id,
            Authorization: `Bearer ${client.config.twitch.access_token}`,
          }));

  const name = client.twitch.displayName(user);
  const type = `\n${client.utils.capitalize(user.broadcaster_type)}`;
  const sub = `\nSubscribed: **${Boolean(subscription)}**`;
  let str = /^\d+$/.test(query) ? `${user.id} => **${name}**` : `${name} => **${user.id}**`;
  if (user.broadcaster_type) str += type;
  if (subscription) str += sub;
  msg.channel.send(str)
    .then(resolve).catch(reject);
});
<|endoftext|>


<commit_before>module.exports = {
  command: 'volume [amount|direction]',
  desc: 'Getting / Setting the volume',
  aliases: ['vol'],
  handler: function (argv) {
    if (argv.amount) {
      if (['up', 'down'].includes(argv.amount)) {
        argv.amount = parseInt(argv.db.state.volume) + (argv.amount === 'up' ? 5 : -5);
      }

      if(isNaN(argv.amount)) {
        argv.db.post(`${argv.amount} is not a number`);
        return;
      }

      argv.amount = parseInt(argv.amount)
      argv.amount = Math.max(Math.min(argv.amount, 100), 0);

      argv.db.logger.info('Setting volume to %d', argv.amount)
      argv.db.mopidy.mixer.setVolume([argv.amount])
        .then(function (volume) {
          argv.db.post(argv.db.attachments.volume(argv.amount))
        })
    } else {
      argv.db.logger.info('Getting volume')
      argv.db.mopidy.mixer.getVolume()
        .then(function (volume) {
          argv.db.post(argv.db.attachments.volume(volume))
        })
    }
  }
}
<commit_msg>removed semicolons<commit_after>module.exports = {
  command: 'volume [amount|direction]',
  desc: 'Getting / Setting the volume',
  aliases: ['vol'],
  handler: function (argv) {
    if (argv.amount) {
      if (['up', 'down'].includes(argv.amount)) {
        argv.amount = parseInt(argv.db.state.volume) + (argv.amount === 'up' ? 5 : -5)
      }

      if(isNaN(argv.amount)) {
        argv.db.post(`${argv.amount} is not a number`)
        return
      }

      argv.amount = parseInt(argv.amount)
      argv.amount = Math.max(Math.min(argv.amount, 100), 0)

      argv.db.logger.info('Setting volume to %d', argv.amount)
      argv.db.mopidy.mixer.setVolume([argv.amount])
        .then(function (volume) {
          argv.db.post(argv.db.attachments.volume(argv.amount))
        })
    } else {
      argv.db.logger.info('Getting volume')
      argv.db.mopidy.mixer.getVolume()
        .then(function (volume) {
          argv.db.post(argv.db.attachments.volume(volume))
        })
    }
  }
}
<|endoftext|>