<commit_before>
var Bitfinex = require("bitfinex-api-node");
var util = require('../core/util.js');
var _ = require('lodash');
var moment = require('moment');
var log = require('../core/log');

// Module-wide constants
var Trader = function(config) {
  _.bindAll(this);
  if(_.isObject(config)) {
    this.key = config.key;
    this.secret = config.secret;
  }
  this.name = 'Bitfinex';
  this.balance;
  this.price;
  this.pair = config.asset + config.currency;
  this.bitfinex = new Bitfinex(this.key, this.secret).rest;
}

// if the exchange errors we try the same call again after
// waiting 10 seconds
Trader.prototype.retry = function(method, args) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..');

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.getPortfolio = function(callback) {
  this.bitfinex.wallet_balances(function (err, data, body) {
    var portfolio = _(data).filter(function(data) {
      return data.type === 'exchange'
    }).map(function (asset) {
      return {
        name: asset.currency.toUpperCase(),
        // TODO: use .amount instead of .available?
        amount: asset.available
      }
    }).value();
    callback(err, portfolio);
  });
}

Trader.prototype.getTicker = function(callback) {
  // the function that will handle the API callback
  var process = function(err, data, body) {
    if (err) {
      // on error we need to recurse this function

      // however we don't want to hit any API ratelimits
      // so we use this.retry since this will wait first
      // before we retry.
      // the arguments we need to pass the the ticker method
      //>> Thanks Mike :)
      var args = [this.pair, process]
      return this.retry(this.bitfinex.ticker(args));
    }

    // whenever we reach this point we have valid
    // data, the callback is still the same since
    // we are inside the same javascript scope.
    callback(err, {bid: +data.bid, ask: +data.ask})
  }.bind(this);

  this.bitfinex.ticker(this.pair, process);
}

// This assumes that only limit orders are being placed, so fees are the
// "maker fee" of 0.1%.  It does not take into account volume discounts.
Trader.prototype.getFee = function(callback) {
    var makerFee = 0.1;
    callback(false, makerFee / 100);
}

Trader.prototype.function = function (submit_order(type, amount, price, callback) {
  amount = Math.floor(amount*100000000)/100000000;

  this.bitfinex.new_order(this.pair, amount + '', price + '', this.name,
    type,
    'exchange limit',
    function (err, data, body) {
      if (err)
        return log.error('unable to ' + type, err, body);

      callback(err, data.order_id);
    });
}

Trader.prototype.buy = function(amount, price, callback) {
  this.submit_order(this.bitfinex, 'buy', amount, price, callback);

}

Trader.prototype.sell = function(amount, price, callback) {
  this.submit_order(this.bitfinex, 'sell', amount, price, callback);
}

Trader.prototype.checkOrder = function(order_id, callback) {
  this.bitfinex.order_status(order_id, function (err, data, body) {
    callback(err, !data.is_live);
  });
}

Trader.prototype.cancelOrder = function(order_id, callback) {
  this.bitfinex.cancel_order(order_id, function (err, data, body) {
      if (err || !data || !data.is_cancelled)
        log.error('unable to cancel order', order_id, '(', err, data, ')');
  });
}

Trader.prototype.getTrades = function(since, callback, descending) {
  var args = _.toArray(arguments);
  var self = this;

  var path = this.pair;
  if(since)
    path += '?limit_trades=' + since;

  this.bitfinex.trades(path,  function (err, data) {
    if (err)
      return self.retry(self.getTrades, args);

    var trades = _.map(data, function (trade) {
      return {
        tid: trade.tid,
        date:  trade.timestamp,
        price: +trade.price,
        amount: +trade.amount
      }
    });

    callback(null, descending ? trades : trades.reverse());
  });
}

module.exports = Trader;
<commit_msg>bfx clean up<commit_after>
var Bitfinex = require("bitfinex-api-node");
var util = require('../core/util.js');
var _ = require('lodash');
var moment = require('moment');
var log = require('../core/log');

var Trader = function(config) {
  _.bindAll(this);
  if(_.isObject(config)) {
    this.key = config.key;
    this.secret = config.secret;
  }
  this.name = 'Bitfinex';
  this.balance;
  this.price;
  this.pair = config.asset + config.currency;
  this.bitfinex = new Bitfinex(this.key, this.secret).rest;
}

// if the exchange errors we try the same call again after
// waiting 10 seconds
Trader.prototype.retry = function(method, args) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..');

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.getPortfolio = function(callback) {
  this.bitfinex.wallet_balances(function (err, data, body) {
    var portfolio = _(data).filter(function(data) {
      return data.type === 'exchange'
    }).map(function (asset) {
      return {
        name: asset.currency.toUpperCase(),
        // TODO: use .amount instead of .available?
        amount: asset.available
      }
    }).value();
    callback(err, portfolio);
  });
}

Trader.prototype.getTicker = function(callback) {
  // the function that will handle the API callback
  var process = function(err, data, body) {
    if (err) {
      // on error we need to recurse this function

      // however we don't want to hit any API ratelimits
      // so we use this.retry since this will wait first
      // before we retry.
      // the arguments we need to pass the the ticker method
      //>> Thanks Mike :)
      var args = [this.pair, process]
      return this.retry(this.bitfinex.ticker(args));
    }

    // whenever we reach this point we have valid
    // data, the callback is still the same since
    // we are inside the same javascript scope.
    callback(err, {bid: +data.bid, ask: +data.ask})
  }.bind(this);

  this.bitfinex.ticker(this.pair, process);
}

// This assumes that only limit orders are being placed, so fees are the
// "maker fee" of 0.1%.  It does not take into account volume discounts.
Trader.prototype.getFee = function(callback) {
    var makerFee = 0.1;
    callback(false, makerFee / 100);
}

Trader.prototype.function = function (submit_order(type, amount, price, callback) {
  amount = Math.floor(amount*100000000)/100000000;

  this.bitfinex.new_order(this.pair, amount + '', price + '', this.name,
    type,
    'exchange limit',
    function (err, data, body) {
      if (err)
        return log.error('unable to ' + type, err, body);

      callback(err, data.order_id);
    });
}

Trader.prototype.buy = function(amount, price, callback) {
  this.submit_order(this.bitfinex, 'buy', amount, price, callback);

}

Trader.prototype.sell = function(amount, price, callback) {
  this.submit_order(this.bitfinex, 'sell', amount, price, callback);
}

Trader.prototype.checkOrder = function(order_id, callback) {
  this.bitfinex.order_status(order_id, function (err, data, body) {
    callback(err, !data.is_live);
  });
}

Trader.prototype.cancelOrder = function(order_id, callback) {
  this.bitfinex.cancel_order(order_id, function (err, data, body) {
      if (err || !data || !data.is_cancelled)
        log.error('unable to cancel order', order_id, '(', err, data, ')');
  });
}

Trader.prototype.getTrades = function(since, callback, descending) {
  var args = _.toArray(arguments);
  var self = this;

  var path = this.pair;
  if(since)
    path += '?limit_trades=' + since;

  this.bitfinex.trades(path,  function (err, data) {
    if (err)
      return self.retry(self.getTrades, args);

    var trades = _.map(data, function (trade) {
      return {
        tid: trade.tid,
        date:  trade.timestamp,
        price: +trade.price,
        amount: +trade.amount
      }
    });

    callback(null, descending ? trades : trades.reverse());
  });
}

module.exports = Trader;
<|endoftext|>


<commit_before>module.exports = function HawkejsRouter(Hawkejs, Blast) {

	var Router = Hawkejs.Helper.extend(function RouterHelper(view) {
		Hawkejs.Helper.call(this, view);
	});

	/**
	 * Return route name info
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 *
	 * @return   {Object}
	 */
	Router.setMethod(function routeConfig(name) {

		var section,
		    pieces,
		    routes,
		    result,
		    name,
		    key;

		routes = this.view.expose('routes');
		pieces = name.split('@');
		config = {};

		if (pieces.length == 1) {
			name = pieces[0];

			// Always look in the default section first
			if (routes.default[name] != null) {
				section = 'default';
			} else {
				for (key in routes) {
					if (routes[key][name] != null) {
						section = key
					}
				}
			}
		} else {
			section = pieces[0];
			name = pieces[1];
		}

		if (routes[section] != null && routes[section][name] != null) {
			result = {
				section: section,
				name: name,
				paths: routes[section][name]
			};

			return result;
		}

		return null;
	});

	/**
	 * Return the plain url for the given url name & parameters object
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 * @param    {Object}   parameters
	 */
	Router.setMethod(function routeUrl(name, parameters, options) {

		var config,
		    url;

		url = '';
		config = this.routeConfig(name);

		if (config != null) {
			url = config.paths[''];
			url = url.fillPlaceholders(parameters);
		}

		return url;
	});

	/**
	 * Print out an anchor
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 * @param    {Object}   parameters
	 */
	Router.setMethod(function printRoute(name, parameters, options) {

		var className,
		    config,
		    anchor,
		    inner,
		    name,
		    url;

		url = '';
		config = this.routeConfig(name);

		if (options == null) {
			options = {};
		}

		if (options.handleManual) {
			className = '';
		} else {
			className = 'js-he-link';
		}

		if (config != null) {
			url = config.paths[''];
			url = url.fillPlaceholders(parameters);

			anchor = Hawkejs.ElementBuilder.create('a');
			anchor.addClass(className)

			if (options.className) {
				anchor.addClass(options.className);
			}

			if (options.innerWrap) {
				inner = Hawkejs.ElementBuilder.create(options.innerWrap);
			} else {
				inner = anchor;
			}

			anchor.attr('href', url);
			inner.setContent(options.content || options.title || config.name);

			if (options.title){
				anchor.attr('title', options.title);
			}

			if (options.innerWrap) {
				anchor.setContent(inner);
			}

			if (options.divert) {
				anchor.data('divert', options.divert);
			}

			if (options.history === false) {
				anchor.data('history', false);
			}

			for (name in options.attributes) {
				anchor.attr(name, options.attributes[name]);
			}

			this.print(anchor);

			return anchor;
		}
	});
};<commit_msg>Add hashtag option to the Router helper<commit_after>module.exports = function HawkejsRouter(Hawkejs, Blast) {

	var Router = Hawkejs.Helper.extend(function RouterHelper(view) {
		Hawkejs.Helper.call(this, view);
	});

	/**
	 * Return route name info
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 *
	 * @return   {Object}
	 */
	Router.setMethod(function routeConfig(name) {

		var section,
		    pieces,
		    routes,
		    result,
		    name,
		    key;

		routes = this.view.expose('routes');
		pieces = name.split('@');
		config = {};

		if (pieces.length == 1) {
			name = pieces[0];

			// Always look in the default section first
			if (routes.default[name] != null) {
				section = 'default';
			} else {
				for (key in routes) {
					if (routes[key][name] != null) {
						section = key
					}
				}
			}
		} else {
			section = pieces[0];
			name = pieces[1];
		}

		if (routes[section] != null && routes[section][name] != null) {
			result = {
				section: section,
				name: name,
				paths: routes[section][name]
			};

			return result;
		}

		return null;
	});

	/**
	 * Return the plain url for the given url name & parameters object
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 * @param    {Object}   parameters
	 */
	Router.setMethod(function routeUrl(name, parameters, options) {

		var config,
		    url;

		url = '';
		config = this.routeConfig(name);

		if (config != null) {
			url = config.paths[''];
			url = url.fillPlaceholders(parameters);
		}

		return url;
	});

	/**
	 * Print out an anchor
	 *
	 * @author   Jelle De Loecker   <jelle@kipdola.be>
	 * @since    1.0.0
	 * @version  1.0.0
	 *
	 * @param    {String}   name
	 * @param    {Object}   parameters
	 */
	Router.setMethod(function printRoute(name, parameters, options) {

		var className,
		    config,
		    anchor,
		    inner,
		    name,
		    url;

		url = '';
		config = this.routeConfig(name);

		if (options == null) {
			options = {};
		}

		if (options.handleManual) {
			className = '';
		} else {
			className = 'js-he-link';
		}

		if (config != null) {
			url = config.paths[''];
			url = url.fillPlaceholders(parameters);

			if (options.hash) {
				url += '#' + options.hash;
			}

			anchor = Hawkejs.ElementBuilder.create('a');
			anchor.addClass(className)

			if (options.className) {
				anchor.addClass(options.className);
			}

			if (options.innerWrap) {
				inner = Hawkejs.ElementBuilder.create(options.innerWrap);
			} else {
				inner = anchor;
			}

			anchor.attr('href', url);
			inner.setContent(options.content || options.title || config.name);

			if (options.title){
				anchor.attr('title', options.title);
			}

			if (options.innerWrap) {
				anchor.setContent(inner);
			}

			if (options.divert) {
				anchor.data('divert', options.divert);
			}

			if (options.history === false) {
				anchor.data('history', false);
			}

			for (name in options.attributes) {
				anchor.attr(name, options.attributes[name]);
			}

			this.print(anchor);

			return anchor;
		}
	});
};<|endoftext|>


<commit_before>'use babel'

import minimatch from 'minimatch';
import process from 'process';
import $ from 'jquery';

// transform "keywords string" to "keywords object"
function transform (expression) {
    let result = {
        type : '',
        paths : '',
        expression : '',
    };
    if (typeof expression == 'symbol') {
        result.type = 'symbol';
    } else if (expression.indexOf('/') != -1 || expression.indexOf('\\') != -1) {
        result.type = 'directory';
        let speartor = expression.indexOf('/') != -1 ? '/' : '\\';
        let parts = expression.split(speartor);
        result.expression = parts.shift();
        result.paths = parts.join(speartor);
        if (result.children == '') {
            result.children = Symbol('*');
        }
    } else if (expression.indexOf('.') != -1) {
        result.type = 'file';
        result.expression = expression.indexOf('.') ? expression : '*' + expression;
    } else {
        result.type = 'string';
        result.expression = expression;
    }
    return result
}

// switch result.type to handle different situation
let actions = {
    symbol () {
        // the children file of matched directory
        return true
    },
    directory (name, result) {
        let item = this;
        if (name.toLowerCase().indexOf(result.expression.toLowerCase()) != -1 && item.hasClass('header')) {
            filter(item.next().find('.list-item'), [result.paths]);
            return true
        } else {
            return false
        }
    },
    file (name, result) {
        return minimatch(name.toLowerCase(), result.expression.toLowerCase())
    },
    string (name, result) {
        return name.toLowerCase().indexOf(result.expression.toLowerCase()) != -1
    }
};

function filter (items, keywords) {
    keywords = keywords.map(transform);
    items.each(function () {
        let item = $(this);
        let name = item.text();
        let isMatch = keywords.some((result) => item::actions[result.type](name, result));
        if (isMatch) {
            item.attr('search-bar', 'is-match');
            item.parents('.directory:not(.project-root)').attr('search-bar', 'has-match');
        }
    });
}

function render () {
    $('[search-bar="is-match"]').addClass('tree-view-search-bar--is-match');
    $('[search-bar="has-match"]').addClass('tree-view-search-bar--has-match');
}

function reset () {
    $('.tree-view-search-bar--has-match').removeClass('tree-view-search-bar--has-match');
    $('.tree-view-search-bar--is-match').removeClass('tree-view-search-bar--is-match');
    $('[search-bar]').attr('search-bar', '');
}

export default {
    filter,
    render,
    reset,
}
<commit_msg>del<commit_after><|endoftext|>


<commit_before>var express = require('express');
var app = express();
var favicon = require('serve-favicon');
var fs = require('fs');
var join = require('path').join;
var cheerio = require('cheerio');
var concat = require('concat-stream');
var notfound = require('./middleware/404');
var reloadFlag = 0;

exports.server = function (dirPath, option, callback) {
    app.configure(function () {
        if(option.log === "true"){
            app.use(express.logger());
        }
        app.use(express.compress());
        app.use(app.router);
        app.use(express.static(__dirname+'/client'));
        app.use(express.static(dirPath));
    });

    app.use(favicon(__dirname + '/client/favicon.ico'));

    app.get('/', function (req, res, next) {
        var filename = option.homepage + ".html",
            path = join(dirPath, filename),
            stream = fs.createReadStream(path, {encoding: 'utf-8'});

        stream.pipe(concat(function (data) {
            var $ = cheerio.load(data),

            injectan = "<script src='svh.min.js'></script>"
            var sel = $('body').append(injectan);

            if(sel.length === 0){
                $('*').after(injectan);
            }

            res.setHeader('Content-Type', 'text/html');
            res.write($.html());
            res.end();
        }))
    });

    app.get('/reload', function(req, res, next){

        var event = "reload";
        client = {
            "reload" : option.reload,
            "reloadFlag": reloadFlag
        };

        res.writeHead(200, {
            "Content-Type":"text/event-stream",
            "Cache-Control":"no-cache",
            "Connection":"keep-alive"
        });

        var id = (new Date()).toLocaleTimeString();

        res.write("id: " + id + '\n');
        res.write("event: " + event + "\n");
        res.write("data: "+JSON.stringify(client)+"\n\n");
        //res.write('retry: 500\n');
        reloadFlag = 0;
        res.end();
    });

    app.use(notfound.index);

    var server = app.listen(option.port, callback);
    return server;
};

exports.setReload = function(data){
    reloadFlag = data;
}
<commit_msg>add post reload from client<commit_after>var express = require('express');
var app = express();
var favicon = require('serve-favicon');
var fs = require('fs');
var join = require('path').join;
var cheerio = require('cheerio');
var concat = require('concat-stream');
var notfound = require('./middleware/404');
var reloadFlag = false;

exports.server = function (dirPath, option, callback) {
    app.configure(function () {
        if(option.log === "true"){
            app.use(express.logger());
        }

        app.use(express.bodyParser());
        app.use(express.compress());
        app.use(app.router);
        app.use(express.static(__dirname+'/client'));
        app.use(express.static(dirPath));
    });

    app.use(favicon(__dirname + '/client/favicon.ico'));

    app.get('/', function (req, res, next) {
        var filename = option.homepage + ".html",
            path = join(dirPath, filename),
            stream = fs.createReadStream(path, {encoding: 'utf-8'});

        stream.pipe(concat(function (data) {
            var $ = cheerio.load(data),

            injectan = "<script src='humane.min.js'></script><script src='svh.min.js'></script>"
            var sel = $('body').append(injectan);
            var css = $('head').append("<link rel='stylesheet' href='themes/libnotify.css'/>");

            if(sel.length === 0){
                $('*').after(injectan);
            }

            res.setHeader('Content-Type', 'text/html');
            res.write($.html());
            res.end();
        }))
    });

    app.get('/reload', function(req, res, next){

        var event = "reload";
        client = {
            "reload" : getReload(),
            "port": option.port
        };

        res.writeHead(200, {
            "Content-Type":"text/event-stream",
            "Cache-Control":"no-cache",
            "Connection":"keep-alive"
        });

        var id = (new Date()).toLocaleTimeString();
        var dataSSE = {
            id: id,
            event: event,
            client: client
        }
        createSSE(req, res, dataSSE);
    });

    app.post('/reload', function(req, res){
        if(!req.body.reload){
          reloadFlag = false;

        }
        res.json({status: true});
    });

    app.use(notfound.index);

    var server = app.listen(option.port, callback);
    return server;
};

function createSSE(req, res, data){
    res.write("id: " + data.id + '\n');
    res.write("event: " + data.event + "\n");
    res.write("data: "+JSON.stringify(data.client)+"\n\n");
    res.end();
}

exports.setReload = function(data){
    reloadFlag = data;
}

var getReload = function() {
    return reloadFlag;
}
<|endoftext|>


<commit_before>var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioElement = document.getElementById('sound');
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

var songs=[],currSongIndex=-1;
var sound = document.getElementById('sound');
var reader = new FileReader();

function init(){
	var newSongs = document.getElementById('audio');
	for(var i=0;i<newSongs.files.length;++i){
		console.log(newSongs.files[i]);
		songs.push(newSongs.files[i]);
	}
	console.log(songs);
	currSongIndex++;
	console.log(songs.length);
	reader.onload = function(e){
		console.log("load "+currSongIndex);
		sound.src = e.target.result;
		while(sound.paused)
			sound.play();
	};
	playFile();
}

function prevSong(){
	console.log("prev song");
	if(currSongIndex!=0){
		currSongIndex--;
		playFile();
	}
}
function nextSong(){
	console.log("next song");
	if(currSongIndex!=songs.length){
		currSongIndex++;
		playFile();
	}
}

function pause(){
	sound.pause();
}

function stop(){
	sound.pause();
	sound.currentTime = 0;
}

function setup(){
	if(vizType==0)
		setupRect();
	else
		setupCircle();
	resize=0;
	console.log(resize);
	play();
}

function play(){
	sound.play();
}

function playFile() {
	console.log("read "+currSongIndex);
	d3.select("#songName").text(songs[currSongIndex].name);
    reader.readAsDataURL(songs[currSongIndex]);
    play();
}

var frequencyData = new Uint8Array(200);
var width=window.innerWidth,
	height=window.innerHeight*0.84,
	barPadding = '1',
	vizType=0,resize=0;

var barScale = d3.scale.linear().domain([0,255]).range([0,height]);
var svg = d3.select("#canvas").append("svg").attr("height",height).attr("width",width);
var colorScale = d3.scale.linear().domain([0,255]).range(["black","blue"]);
var circleScale = d3.scale.linear().domain([0,200]).range(["blue","red"]);
var mixScale = d3.scale.category20();
setupRect();

function resizeSvg(){
	resize=1;
	width=window.innerWidth;
	height=window.innerHeight*0.84;
	svg.selectAll("*").remove();
	svg.attr("height",height).attr("width",width);
	barScale.range([0,height]);
	setup();
}

function changeViz(){
	svg.selectAll("*").remove();
	if(vizType==0){
		vizType=1;
		setupCircle();
	}
	else{
		vizType=0;
		setupRect();
	}
}

function setupRect(){
	svg.selectAll('rect')
   		.data(frequencyData)
    	.enter()
    	.append('rect')
    	.attr('x', function (d, i) {
      		return i * (width / frequencyData.length);
   		})
   		.attr('width', width / frequencyData.length)
   		.style("fill","white");
   	startRectViz();
}

function startRectViz(){
	if(resize==1)
		console.log("stopped");
	if(vizType==0 && resize==0)
		requestAnimationFrame(startRectViz);
	analyser.getByteFrequencyData(frequencyData);
	svg.selectAll('rect')
      .data(frequencyData)
      .attr('y', function(d) {
         return height - barScale(d);
      })
      .attr('height', function(d) {
         return barScale(d);
      })
      .style('fill', function(d) {
      		return colorScale(d);
        	return 'rgb('+0+','+0+','+d+')';
      });
}

function setupCircle(){
	svg.selectAll('rect')
	   .data(frequencyData)
	   .enter()
	   .append('circle')
	   .attr('cy', height/2)
	   .attr('cx', width/2)
	   .attr('r',0)
	   .style("fill","white")
	startCircleViz();
}

function startCircleViz(){
	if(vizType==1 && resize==0)
		requestAnimationFrame(startCircleViz);
	analyser.getByteFrequencyData(frequencyData);
	svg.selectAll('circle')
      .data(frequencyData)
      .attr('r',function(d){return barScale(d)/2.3;})
      .style('fill', function(d,i) {
         return mixScale(i);
      });
}

var currColor=0;
function changeColor(){
	var newColor = mixScale(currColor++);
	console.log(newColor);
	colorScale.range(["black",newColor]);
}

var night=0;
nightMode();
function nightMode(){
	if(night==0){
		d3.select("body").style("background-color","black");
		d3.selectAll("button")
			.style("background-color","grey")
			.style("border-color","grey");
		night=1;
	}
	else{
		d3.select("body").style("background-color","white");
		d3.selectAll("button")
			.style("background-color","white")
			.style("border-color","black");
		night=0;
	}
}

<commit_msg>Feature additions<commit_after>var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioElement = document.getElementById('sound');
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

var songs=[],currSongIndex=-1;
var sound = document.getElementById('sound');
var reader = new FileReader();

function updatePlaylist(){
	var rows=d3.select("table").select("tbody").selectAll("tr").data(songs);

	rows.exit().remove();

	var columns=rows.enter()
		.append("tr");

	d3.select("table")
		.selectAll("tr")
		.on("click" , function(d){
			var deleteIndex = $(this).index();
			console.log(deleteIndex);
			songs.splice(deleteIndex,1);
			updatePlaylist();
        })
		.html(function(d){return "<td>"+d.name+"</td>";});
}

function init(){
	var newSongs = document.getElementById('audio');
	for(var i=0;i<newSongs.files.length;++i){
		console.log(newSongs.files[i]);
		songs.push(newSongs.files[i]);
	}
	updatePlaylist();
	console.log(songs);
	currSongIndex++;
	console.log(songs.length);
	reader.onload = function(e){
		console.log("load "+currSongIndex);
		sound.src = e.target.result;
		while(sound.paused)
			sound.play();
	};
	playFile();
}

function prevSong(){
	console.log("prev song");
	if(currSongIndex!=0){
		currSongIndex--;
		playFile();
	}
}
function nextSong(){
	console.log("next song");
	if(currSongIndex!=songs.length-1){
		currSongIndex++;
		playFile();
	}
}

function pause(){
	sound.pause();
}

function stop(){
	sound.pause();
	sound.currentTime = 0;
}

var repeat = false;
d3.select("#repeatButton").style("opacity",0.5);
function toggleRepeat(){
	if(repeat){
		repeat = false;
		sound.loop = false;
		d3.select("#repeatButton").style("opacity",0.5);
		resizeSvg();
	}
	else{
		repeat = true;
		sound.loop = true;
		d3.select("#repeatButton").style("opacity",1);
		resizeSvg();
	}

}

function setup(){
	switch(vizType){
		case 0:
			setupRect();
			break;
		case 1:
			setupCircle();
			break;
		case 2:
			setupMountain();
			break;
		case 3:
			setupWave();
			break;
	}
	resize=0;
}

function play(){
	sound.play();
}

function playFile() {
	console.log("read "+currSongIndex);
	d3.select("#songName").text(songs[currSongIndex].name);
    reader.readAsDataURL(songs[currSongIndex]);
    play();
}

var frequencyData = new Uint8Array(180);
var Twidth = document.getElementById('tab').offsetWidth;
var width=window.innerWidth-Twidth-40,
	height=window.innerHeight*0.80,
	barPadding = '0',
	vizType=0,resize=0;

var barScale = d3.scale.linear().domain([0,255]).range([0,height]);
var pieScale = d3.scale.linear().domain([0,150,255]).range([0,height/4,height]);
var svg = d3.select("svg").attr("height",height).attr("width",width);
var colorScale = d3.scale.linear().domain([0,255]).range(["black","blue"]);
var circleScale = d3.scale.linear().domain([0,200]).range(["blue","red"]);
var mixScale = d3.scale.category20();
var mixScaleOdd = d3.scale.category20b();
setupRect();
var hidden=false;
var tableWidth=document.getElementById("tab").offsetWidth;
function resizeSvg(){
	resize=1;
	Twidth=hidden?0:tableWidth+40;
	//40+(hidden?0:200);
	width=window.innerWidth-Twidth;
	console.log("hidden: "+hidden);
	console.log(Twidth);
	height=window.innerHeight*0.80;
	svg.selectAll("*").remove();
	svg.attr("height",height).attr("width",width);
	barScale.range([0,height]);
	setup();
}

$(document).on("click", "#playlist", function() {
	hidden=!hidden;
  	resizeSvg();
});

var numOfViz = 4;
function changeViz(){
	svg.selectAll("*").remove();
	vizType=(vizType+1)%numOfViz;
	switch(vizType){
		case 0:
			setupRect();
			break;
		case 1:
			setupCircle();
			break;
		case 2:
			setupMountain();
			break;
		case 3:
			setupWave();
			break;
	}
}

function setupRect(){
	svg.selectAll('rect')
   		.data(frequencyData)
    	.enter()
    	.append('rect')
    	.attr('x', function (d, i) {
      		return i * (width / frequencyData.length);
   		})
   		.attr('width', width / frequencyData.length)
   		.style("fill","white");
   	startRectViz();
}

function startRectViz(){
	if(vizType==0 && resize==0)
		requestAnimationFrame(startRectViz);
	analyser.getByteFrequencyData(frequencyData);
	svg.selectAll('rect')
      .data(frequencyData)
      .attr('y', function(d) {
         return height - barScale(d);
      })
      .attr('height', function(d) {
         return barScale(d);
      })
      .style('fill', function(d) {
      		return colorScale(d);
        	return 'rgb('+0+','+0+','+d+')';
      });
}

function setupCircle(){
	svg.selectAll('circle')
	   .data(frequencyData)
	   .enter()
	   .append('circle')
	   .attr('cy', height/2)
	   .attr('cx', width/2)
	   .attr('r',0)
	   .style("fill","white")
	startCircleViz();
}

function startCircleViz(){
	if(vizType==1 && resize==0)
		requestAnimationFrame(startCircleViz);
	analyser.getByteFrequencyData(frequencyData);
	svg.selectAll('circle')
      .data(frequencyData)
      .attr('r',function(d){return pieScale(d)/2.3;})
      .style('fill', function(d,i) {
      	return mixScale(i);
        //return (i%2 == 0) ? mixScale(i) : mixScaleOdd(i);
      });
}

var tempData = new Uint8Array(frequencyData.byteLength-10);
var mountainData = new Uint8Array(2*tempData.byteLength);
var waveData = new Uint8Array(4*tempData.byteLength);

function setupMountain(){
	svg.selectAll('rect')
   		.data(mountainData)
    	.enter()
    	.append('rect')
    	.attr('x', function (d, i) {
      		return i * (width / mountainData.length);
   		})
   		.attr('width', width / mountainData.length)
   		.style("fill","white");
   	startMountainViz();
}

function startMountainViz(){
	if(vizType==2 && resize==0)
		requestAnimationFrame(startMountainViz);
	analyser.getByteFrequencyData(frequencyData);
	tempData = frequencyData.slice(10,180);
	mountainData.set(tempData,tempData.byteLength);
	tempData.reverse();
	mountainData.set(tempData,0);
	svg.selectAll('rect')
      .data(mountainData)
      .attr('y', function(d) {
         return height - barScale(d);
      })
      .attr('height', function(d) {
         return barScale(d);
      })
      .style('fill', function(d) {
      		return colorScale(d);
        	return 'rgb('+0+','+0+','+d+')';
      });
}

function setupWave(){
	svg.selectAll('rect')
   		.data(waveData)
    	.enter()
    	.append('rect')
    	.attr('x', function (d, i) {
      		return i * (width / waveData.length);
   		})
   		.attr('width', width / waveData.length)
   		.style("fill","white");
   	startWaveViz();
}

function startWaveViz(){
	if(vizType==3 && resize==0)
		requestAnimationFrame(startWaveViz);
	analyser.getByteFrequencyData(frequencyData);
	tempData = frequencyData.slice(10,180);
	waveData.set(tempData,tempData.byteLength);
	waveData.set(tempData,tempData.byteLength*3);
	tempData.reverse();
	waveData.set(tempData,0);
	waveData.set(tempData,tempData.byteLength*2);
	svg.selectAll('rect')
      .data(waveData)
      .attr('y', function(d) {
         return height - barScale(d);
      })
      .attr('height', function(d) {
         return barScale(d);
      })
      .style('fill', function(d) {
      		return colorScale(255);
        	return 'rgb('+0+','+0+','+d+')';
      });
}

var currColor=0;
function changeColor(){
	var newColor = mixScale(currColor++);
	console.log(newColor);
	colorScale.range(["black",newColor]);
}

var night=0;
nightMode();
function nightMode(){
	if(night==0){
		d3.select("body").style("background-color","black");
		d3.selectAll("button")
			.style("background-color","grey")
			.style("border-color","grey");
		night=1;
	}
	else{
		d3.select("body").style("background-color","white");
		d3.selectAll("button")
			.style("background-color","white")
			.style("border-color","black");
		night=0;
	}
}
<|endoftext|>


<commit_before>
  /***
   * @package Core
   * @description Internal utility and common methods.
   ***/

  // A few optimizations for Google Closure Compiler will save us a couple kb in the release script.
  var object = Object, array = Array, regexp = RegExp, date = Date, string = String, number = Number, math = Math, Undefined;

  // Internal toString
  var internalToString = object.prototype.toString;

  // Internal hasOwnProperty
  var internalHasOwnProperty = object.prototype.hasOwnProperty;

  // The global context
  var globalContext = typeof global !== 'undefined' ? global : this;

  // Type check methods need a way to be accessed dynamically outside global context.
  var typeChecks = {};

  // defineProperty exists in IE8 but will error when trying to define a property on
  // native objects. IE8 does not have defineProperies, however, so this check saves a try/catch block.
  var definePropertySupport = object.defineProperty && object.defineProperties;

  // Class initializers and class helpers

  var ClassNames = 'Boolean,Number,String,Array,Date,RegExp,Function'.split(',');

  var isBoolean  = buildPrimitiveClassCheck('boolean', ClassNames[0]);
  var isNumber   = buildPrimitiveClassCheck('number',  ClassNames[1]);
  var isString   = buildPrimitiveClassCheck('string',  ClassNames[2]);

  var isArray    = buildClassCheck(ClassNames[3]);
  var isDate     = buildClassCheck(ClassNames[4]);
  var isRegExp   = buildClassCheck(ClassNames[5]);
  var isFunction = buildClassCheck(ClassNames[6]);

  function isClass(obj, klass, cached) {
    var k = cached || className(obj);
    return k === '[object '+klass+']';
  }

  function buildClassCheck(klass) {
    var fn = (name === 'Array' && array.isArray) || function(obj, cached) {
      return isClass(obj, klass, cached);
    };
    typeChecks[klass] = fn;
    return fn;
  }

  function buildPrimitiveClassCheck(type, klass) {
    var fn = function(obj) {
      if(isObjectType(obj)) {
        return isClass(obj, klass);
      }
      return typeof obj === type;
    }
    typeChecks[klass] = fn;
    return fn;
  }

  function className(obj) {
    return internalToString.call(obj);
  }

  function initializeClasses() {
    initializeClass(object);
    iterateOverObject(ClassNames, function(i,name) {
      initializeClass(globalContext[name]);
    });
  }

  function initializeClass(klass) {
    if(klass['SugarMethods']) return;
    defineProperty(klass, 'SugarMethods', {});
    extend(klass, false, false, {
      'extend': function(methods, override, instance) {
        extend(klass, instance !== false, override, methods);
      },
      'sugarRestore': function() {
        return batchMethodExecute(klass, arguments, function(target, name, m) {
          defineProperty(target, name, m.method);
        });
      },
      'sugarRevert': function() {
        return batchMethodExecute(klass, arguments, function(target, name, m) {
          if(m.existed) {
            defineProperty(target, name, m.original);
          } else {
            delete target[name];
          }
        });
      }
    });
  }

  // Class extending methods

  function extend(klass, instance, override, methods) {
    var extendee = instance ? klass.prototype : klass;
    initializeClass(klass);
    iterateOverObject(methods, function(name, method) {
      var original = extendee[name];
      var existed  = hasOwnProperty(extendee, name);
      if(typeof override === 'function') {
        method = wrapNative(extendee[name], method, override);
      }
      if(override !== false || !extendee[name]) {
        defineProperty(extendee, name, method);
      }
      // If the method is internal to Sugar, then store a reference so it can be restored later.
      klass['SugarMethods'][name] = { instance: instance, method: method, original: original, existed: existed };
    });
  }

  function extendSimilar(klass, instance, override, set, fn) {
    var methods = {};
    set = isString(set) ? set.split(',') : set;
    set.forEach(function(name, i) {
      fn(methods, name, i);
    });
    extend(klass, instance, override, methods);
  }

  function batchMethodExecute(klass, args, fn) {
    var all = args.length === 0, methods = multiArgs(args), changed = false;
    iterateOverObject(klass['SugarMethods'], function(name, m) {
      if(all || methods.indexOf(name) !== -1) {
        changed = true;
        fn(m.instance ? klass.prototype : klass, name, m);
      }
    });
    return changed;
  }

  function wrapNative(nativeFn, extendedFn, condition) {
    return function() {
      var fn;
      if(nativeFn && (condition === true || !condition.apply(this, arguments))) {
        fn = nativeFn;
      } else {
        fn = extendedFn;
      }
      return fn.apply(this, arguments);
    }
  }

  function defineProperty(target, name, method) {
    if(definePropertySupport) {
      object.defineProperty(target, name, { 'value': method, 'configurable': true, 'enumerable': false, 'writable': true });
    } else {
      target[name] = method;
    }
  }

  // Argument helpers

  function multiArgs(args, fn) {
    var result = [], i, len;
    for(i = 0, len = args.length; i < len; i++) {
      result.push(args[i]);
      if(fn) fn.call(args, args[i], i);
    }
    return result;
  }

  function flattenedArgs(obj, fn, from) {
    multiArgs(array.prototype.concat.apply([], array.prototype.slice.call(obj, from || 0)), fn);
  }

  function checkCallback(fn) {
    if(!fn || !fn.call) {
      throw new TypeError('Callback is not callable');
    }
  }

  // General helpers

  function isDefined(o) {
    return o !== Undefined;
  }

  function isUndefined(o) {
    return o === Undefined;
  }

  // Object helpers

  function hasProperty(obj, prop) {
    return !isPrimitiveType(obj) && prop in obj;
  }

  function hasOwnProperty(obj, prop) {
    return !!obj && internalHasOwnProperty.call(obj, prop);
  }

  function isObjectType(obj) {
    // Check for null
    return !!obj && typeof obj === 'object';
  }

  function isPrimitiveType(obj) {
    var type = typeof obj;
    return obj == null || type === 'string' || type === 'number' || type === 'boolean';
  }

  function isPlainObject(obj, klass) {
    klass = klass || className(obj);
    try {
      // Not own constructor property must be Object
      // This code was borrowed from jQuery.isPlainObject
      if (obj.constructor &&
            !hasOwnProperty(obj, 'constructor') &&
            !hasOwnProperty(obj.constructor.prototype, 'isPrototypeOf')) {
        return false;
      }
    } catch (e) {
      // IE8,9 Will throw exceptions on certain host objects.
      return false;
    }
    // === on the constructor is not safe across iframes
    // 'hasOwnProperty' ensures that the object also inherits
    // from Object, which is false for DOMElements in IE.
    return !!obj && klass === '[object Object]' && 'hasOwnProperty' in obj;
  }

  function iterateOverObject(obj, fn) {
    var key;
    for(key in obj) {
      if(!hasOwnProperty(obj, key)) continue;
      if(fn.call(obj, key, obj[key], obj) === false) break;
    }
  }

  function simpleRepeat(n, fn) {
    for(var i = 0; i < n; i++) {
      fn(i);
    }
  }

  function simpleMerge(target, source) {
    iterateOverObject(source, function(key) {
      target[key] = source[key];
    });
    return target;
  }

  // Hash definition

  function Hash(obj) {
    simpleMerge(this, obj);
  };

  Hash.prototype.constructor = object;

  // Number helpers

  function round(val, precision, method) {
    var fn = math[method || 'round'];
    var multiplier = math.pow(10, math.abs(precision || 0));
    if(precision < 0) multiplier = 1 / multiplier;
    return fn(val * multiplier) / multiplier;
  }

  function ceil(val, precision) {
    return round(val, precision, 'ceil');
  }

  function floor(val, precision) {
    return round(val, precision, 'floor');
  }

  // Used by Number and Date

  function padNumber(num, place, sign, base) {
    var str = math.abs(num).toString(base || 10);
    str = repeatString(place - str.replace(/\.\d+/, '').length, '0') + str;
    if(sign || num < 0) {
      str = (num < 0 ? '-' : '+') + str;
    }
    return str;
  }

  function getOrdinalizedSuffix(num) {
    if(num >= 11 && num <= 13) {
      return 'th';
    } else {
      switch(num % 10) {
        case 1:  return 'st';
        case 2:  return 'nd';
        case 3:  return 'rd';
        default: return 'th';
      }
    }
  }

  // String helpers

  // WhiteSpace/LineTerminator as defined in ES5.1 plus Unicode characters in the Space, Separator category.
  function getTrimmableCharacters() {
    return '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF';
  }

  function repeatString(times, str) {
    var result = '';
    if(isUndefined(times)) {
      times = 1;
    }
    while(times-- > 0) {
      result += str;
    }
    return result;
  }

  // RegExp helpers

  function getRegExpFlags(reg, add) {
    var flags = reg.toString().match(/[^/]*$/)[0];
    if(add) {
      flags = (flags + add).split('').sort().join('').replace(/([gimy])\1+/g, '$1');
    }
    return flags;
  }

  function escapeRegExp(str) {
    if(!isString(str)) str = string(str);
    return str.replace(/([\\/\'*+?|()\[\]{}.^$])/g,'\\$1');
  }

  // Date helpers

  function callDateGet(d, method) {
    return d['get' + (d._utc ? 'UTC' : '') + method]();
  }

  function callDateSet(d, method, value) {
    return d['set' + (d._utc && method != 'ISOWeek' ? 'UTC' : '') + method](value);
  }

  function extractDurationFromString(str) {
    var match, val, unit;
    match = str.toLowerCase().match(/^(\d+)?\s?(\w+?)s?$/i);
    val = parseInt(match[1]) || 1;
    unit = match[2].slice(0,1).toUpperCase() + match[2].slice(1);
    if(unit.match(/hour|minute|second/i)) {
      unit += 's';
    } else if(unit === 'Year') {
      unit = 'FullYear';
    } else if(unit === 'Day') {
      unit = 'Date';
    }
    return [val, unit];
  }

  // Specialized helpers

  // Used by Array#unique and Object.equal

  function stringify(thing, stack) {
    var type = typeof thing,
        thingIsObject,
        thingIsArray,
        klass, value,
        arr, key, i, len;

    // Return quickly if string to save cycles
    if(type === 'string') return thing;

    klass         = internalToString.call(thing)
    thingIsObject = isPlainObject(thing, klass);
    thingIsArray  = isArray(thing, klass);

    if(thing != null && thingIsObject || thingIsArray) {
      // This method for checking for cyclic structures was egregiously stolen from
      // the ingenious method by @kitcambridge from the Underscore script:
      // https://github.com/documentcloud/underscore/issues/240
      if(!stack) stack = [];
      // Allowing a step into the structure before triggering this
      // script to save cycles on standard JSON structures and also to
      // try as hard as possible to catch basic properties that may have
      // been modified.
      if(stack.length > 1) {
        i = stack.length;
        while (i--) {
          if (stack[i] === thing) {
            return 'CYC';
          }
        }
      }
      stack.push(thing);
      value = thing.valueOf() + string(thing.constructor);
      arr = thingIsArray ? thing : object.keys(thing).sort();
      for(i = 0, len = arr.length; i < len; i++) {
        key = thingIsArray ? i : arr[i];
        value += key + stringify(thing[key], stack);
      }
      stack.pop();
    } else if(1 / thing === -Infinity) {
      value = '-0';
    } else {
      value = string(thing && thing.valueOf ? thing.valueOf() : thing);
    }
    return type + klass + value;
  }

  function isEqual(a, b) {
    if(objectIsMatchedByValue(a) && objectIsMatchedByValue(b)) {
      return stringify(a) === stringify(b);
    } else {
      return a === b;
    }
  }

  function objectIsMatchedByValue(obj) {
    // Only known objects are matched by value. This is notably excluding functions, DOM Elements, and instances of
    // user-created classes. The latter can arguably be matched by value, but distinguishing between these and
    // host objects -- which should never be compared by value -- is very tricky so not dealing with it here.
    var klass = className(obj);
    return /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/.test(klass) || isPlainObject(obj, klass);
  }

  // Used by Array#at and String#at

  function entryAtIndex(arr, args, str) {
    var result = [], length = arr.length, loop = args[args.length - 1] !== false, r;
    multiArgs(args, function(index) {
      if(isBoolean(index)) return false;
      if(loop) {
        index = index % length;
        if(index < 0) index = length + index;
      }
      r = str ? arr.charAt(index) || '' : arr[index];
      result.push(r);
    });
    return result.length < 2 ? result[0] : result;
  }

  // Object class methods implemented as instance methods

  function buildObjectInstanceMethods(set, target) {
    extendSimilar(target, true, false, set, function(methods, name) {
      methods[name + (name === 'equal' ? 's' : '')] = function() {
        return object[name].apply(null, [this].concat(multiArgs(arguments)));
      }
    });
  }

  initializeClasses();

<commit_msg>faster isFunction and (related) better type checks for environments where regexes are functions<commit_after>
  /***
   * @package Core
   * @description Internal utility and common methods.
   ***/

  // A few optimizations for Google Closure Compiler will save us a couple kb in the release script.
  var object = Object, array = Array, regexp = RegExp, date = Date, string = String, number = Number, math = Math, Undefined;

  // Internal toString
  var internalToString = object.prototype.toString;

  // Are regexes type function?
  var regexIsFunction = typeof /x/ === 'function';

  // Internal hasOwnProperty
  var internalHasOwnProperty = object.prototype.hasOwnProperty;

  // The global context
  var globalContext = typeof global !== 'undefined' ? global : this;

  // Type check methods need a way to be accessed dynamically outside global context.
  var typeChecks = {};

  // defineProperty exists in IE8 but will error when trying to define a property on
  // native objects. IE8 does not have defineProperies, however, so this check saves a try/catch block.
  var definePropertySupport = object.defineProperty && object.defineProperties;

  // Class initializers and class helpers

  var ClassNames = 'Boolean,Number,String,Array,Date,RegExp,Function'.split(',');

  var isBoolean  = buildPrimitiveClassCheck('boolean', ClassNames[0]);
  var isNumber   = buildPrimitiveClassCheck('number',  ClassNames[1]);
  var isString   = buildPrimitiveClassCheck('string',  ClassNames[2]);

  var isArray    = buildClassCheck(ClassNames[3]);
  var isDate     = buildClassCheck(ClassNames[4]);
  var isRegExp   = buildClassCheck(ClassNames[5]);

  var isFunction = function(obj) {
    // Extra check for environments where regexes are type "function".
    return typeof obj === 'function' && (!regexIsFunction || !isRegExp(obj));
  };

  typeChecks[ClassNames[6]] = isFunction;

  function isClass(obj, klass, cached) {
    var k = cached || className(obj);
    return k === '[object '+klass+']';
  }

  function buildClassCheck(klass) {
    var fn = (name === 'Array' && array.isArray) || function(obj, cached) {
      return isClass(obj, klass, cached);
    };
    typeChecks[klass] = fn;
    return fn;
  }

  function buildPrimitiveClassCheck(type, klass) {
    var fn = function(obj) {
      if(isObjectType(obj)) {
        return isClass(obj, klass);
      }
      return typeof obj === type;
    }
    typeChecks[klass] = fn;
    return fn;
  }

  function className(obj) {
    return internalToString.call(obj);
  }

  function initializeClasses() {
    initializeClass(object);
    iterateOverObject(ClassNames, function(i,name) {
      initializeClass(globalContext[name]);
    });
  }

  function initializeClass(klass) {
    if(klass['SugarMethods']) return;
    defineProperty(klass, 'SugarMethods', {});
    extend(klass, false, false, {
      'extend': function(methods, override, instance) {
        extend(klass, instance !== false, override, methods);
      },
      'sugarRestore': function() {
        return batchMethodExecute(klass, arguments, function(target, name, m) {
          defineProperty(target, name, m.method);
        });
      },
      'sugarRevert': function() {
        return batchMethodExecute(klass, arguments, function(target, name, m) {
          if(m.existed) {
            defineProperty(target, name, m.original);
          } else {
            delete target[name];
          }
        });
      }
    });
  }

  // Class extending methods

  function extend(klass, instance, override, methods) {
    var extendee = instance ? klass.prototype : klass;
    initializeClass(klass);
    iterateOverObject(methods, function(name, method) {
      var original = extendee[name];
      var existed  = hasOwnProperty(extendee, name);
      if(typeof override === 'function') {
        method = wrapNative(extendee[name], method, override);
      }
      if(override !== false || !extendee[name]) {
        defineProperty(extendee, name, method);
      }
      // If the method is internal to Sugar, then store a reference so it can be restored later.
      klass['SugarMethods'][name] = { instance: instance, method: method, original: original, existed: existed };
    });
  }

  function extendSimilar(klass, instance, override, set, fn) {
    var methods = {};
    set = isString(set) ? set.split(',') : set;
    set.forEach(function(name, i) {
      fn(methods, name, i);
    });
    extend(klass, instance, override, methods);
  }

  function batchMethodExecute(klass, args, fn) {
    var all = args.length === 0, methods = multiArgs(args), changed = false;
    iterateOverObject(klass['SugarMethods'], function(name, m) {
      if(all || methods.indexOf(name) !== -1) {
        changed = true;
        fn(m.instance ? klass.prototype : klass, name, m);
      }
    });
    return changed;
  }

  function wrapNative(nativeFn, extendedFn, condition) {
    return function() {
      var fn;
      if(nativeFn && (condition === true || !condition.apply(this, arguments))) {
        fn = nativeFn;
      } else {
        fn = extendedFn;
      }
      return fn.apply(this, arguments);
    }
  }

  function defineProperty(target, name, method) {
    if(definePropertySupport) {
      object.defineProperty(target, name, { 'value': method, 'configurable': true, 'enumerable': false, 'writable': true });
    } else {
      target[name] = method;
    }
  }

  // Argument helpers

  function multiArgs(args, fn) {
    var result = [], i, len;
    for(i = 0, len = args.length; i < len; i++) {
      result.push(args[i]);
      if(fn) fn.call(args, args[i], i);
    }
    return result;
  }

  function flattenedArgs(obj, fn, from) {
    multiArgs(array.prototype.concat.apply([], array.prototype.slice.call(obj, from || 0)), fn);
  }

  function checkCallback(fn) {
    if(!fn || !fn.call) {
      throw new TypeError('Callback is not callable');
    }
  }

  // General helpers

  function isDefined(o) {
    return o !== Undefined;
  }

  function isUndefined(o) {
    return o === Undefined;
  }

  // Object helpers

  function hasProperty(obj, prop) {
    return !isPrimitiveType(obj) && prop in obj;
  }

  function hasOwnProperty(obj, prop) {
    return !!obj && internalHasOwnProperty.call(obj, prop);
  }

  function isObjectType(obj) {
    // 1. Check for null
    // 2. Check for regexes in environments where they are "functions".
    return !!obj && (typeof obj === 'object' || (regexIsFunction && isRegExp(obj)));
  }

  function isPrimitiveType(obj) {
    var type = typeof obj;
    return obj == null || type === 'string' || type === 'number' || type === 'boolean';
  }

  function isPlainObject(obj, klass) {
    klass = klass || className(obj);
    try {
      // Not own constructor property must be Object
      // This code was borrowed from jQuery.isPlainObject
      if (obj.constructor &&
            !hasOwnProperty(obj, 'constructor') &&
            !hasOwnProperty(obj.constructor.prototype, 'isPrototypeOf')) {
        return false;
      }
    } catch (e) {
      // IE8,9 Will throw exceptions on certain host objects.
      return false;
    }
    // === on the constructor is not safe across iframes
    // 'hasOwnProperty' ensures that the object also inherits
    // from Object, which is false for DOMElements in IE.
    return !!obj && klass === '[object Object]' && 'hasOwnProperty' in obj;
  }

  function iterateOverObject(obj, fn) {
    var key;
    for(key in obj) {
      if(!hasOwnProperty(obj, key)) continue;
      if(fn.call(obj, key, obj[key], obj) === false) break;
    }
  }

  function simpleRepeat(n, fn) {
    for(var i = 0; i < n; i++) {
      fn(i);
    }
  }

  function simpleMerge(target, source) {
    iterateOverObject(source, function(key) {
      target[key] = source[key];
    });
    return target;
  }

  // Hash definition

  function Hash(obj) {
    simpleMerge(this, obj);
  };

  Hash.prototype.constructor = object;

  // Number helpers

  function round(val, precision, method) {
    var fn = math[method || 'round'];
    var multiplier = math.pow(10, math.abs(precision || 0));
    if(precision < 0) multiplier = 1 / multiplier;
    return fn(val * multiplier) / multiplier;
  }

  function ceil(val, precision) {
    return round(val, precision, 'ceil');
  }

  function floor(val, precision) {
    return round(val, precision, 'floor');
  }

  // Used by Number and Date

  function padNumber(num, place, sign, base) {
    var str = math.abs(num).toString(base || 10);
    str = repeatString(place - str.replace(/\.\d+/, '').length, '0') + str;
    if(sign || num < 0) {
      str = (num < 0 ? '-' : '+') + str;
    }
    return str;
  }

  function getOrdinalizedSuffix(num) {
    if(num >= 11 && num <= 13) {
      return 'th';
    } else {
      switch(num % 10) {
        case 1:  return 'st';
        case 2:  return 'nd';
        case 3:  return 'rd';
        default: return 'th';
      }
    }
  }

  // String helpers

  // WhiteSpace/LineTerminator as defined in ES5.1 plus Unicode characters in the Space, Separator category.
  function getTrimmableCharacters() {
    return '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF';
  }

  function repeatString(times, str) {
    var result = '';
    if(isUndefined(times)) {
      times = 1;
    }
    while(times-- > 0) {
      result += str;
    }
    return result;
  }

  // RegExp helpers

  function getRegExpFlags(reg, add) {
    var flags = reg.toString().match(/[^/]*$/)[0];
    if(add) {
      flags = (flags + add).split('').sort().join('').replace(/([gimy])\1+/g, '$1');
    }
    return flags;
  }

  function escapeRegExp(str) {
    if(!isString(str)) str = string(str);
    return str.replace(/([\\/\'*+?|()\[\]{}.^$])/g,'\\$1');
  }

  // Date helpers

  function callDateGet(d, method) {
    return d['get' + (d._utc ? 'UTC' : '') + method]();
  }

  function callDateSet(d, method, value) {
    return d['set' + (d._utc && method != 'ISOWeek' ? 'UTC' : '') + method](value);
  }

  function extractDurationFromString(str) {
    var match, val, unit;
    match = str.toLowerCase().match(/^(\d+)?\s?(\w+?)s?$/i);
    val = parseInt(match[1]) || 1;
    unit = match[2].slice(0,1).toUpperCase() + match[2].slice(1);
    if(unit.match(/hour|minute|second/i)) {
      unit += 's';
    } else if(unit === 'Year') {
      unit = 'FullYear';
    } else if(unit === 'Day') {
      unit = 'Date';
    }
    return [val, unit];
  }

  // Specialized helpers

  // Used by Array#unique and Object.equal

  function stringify(thing, stack) {
    var type = typeof thing,
        thingIsObject,
        thingIsArray,
        klass, value,
        arr, key, i, len;

    // Return quickly if string to save cycles
    if(type === 'string') return thing;

    klass         = internalToString.call(thing)
    thingIsObject = isPlainObject(thing, klass);
    thingIsArray  = isArray(thing, klass);

    if(thing != null && thingIsObject || thingIsArray) {
      // This method for checking for cyclic structures was egregiously stolen from
      // the ingenious method by @kitcambridge from the Underscore script:
      // https://github.com/documentcloud/underscore/issues/240
      if(!stack) stack = [];
      // Allowing a step into the structure before triggering this
      // script to save cycles on standard JSON structures and also to
      // try as hard as possible to catch basic properties that may have
      // been modified.
      if(stack.length > 1) {
        i = stack.length;
        while (i--) {
          if (stack[i] === thing) {
            return 'CYC';
          }
        }
      }
      stack.push(thing);
      value = thing.valueOf() + string(thing.constructor);
      arr = thingIsArray ? thing : object.keys(thing).sort();
      for(i = 0, len = arr.length; i < len; i++) {
        key = thingIsArray ? i : arr[i];
        value += key + stringify(thing[key], stack);
      }
      stack.pop();
    } else if(1 / thing === -Infinity) {
      value = '-0';
    } else {
      value = string(thing && thing.valueOf ? thing.valueOf() : thing);
    }
    return type + klass + value;
  }

  function isEqual(a, b) {
    if(objectIsMatchedByValue(a) && objectIsMatchedByValue(b)) {
      return stringify(a) === stringify(b);
    } else {
      return a === b;
    }
  }

  function objectIsMatchedByValue(obj) {
    // Only known objects are matched by value. This is notably excluding functions, DOM Elements, and instances of
    // user-created classes. The latter can arguably be matched by value, but distinguishing between these and
    // host objects -- which should never be compared by value -- is very tricky so not dealing with it here.
    var klass = className(obj);
    return /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/.test(klass) || isPlainObject(obj, klass);
  }

  // Used by Array#at and String#at

  function entryAtIndex(arr, args, str) {
    var result = [], length = arr.length, loop = args[args.length - 1] !== false, r;
    multiArgs(args, function(index) {
      if(isBoolean(index)) return false;
      if(loop) {
        index = index % length;
        if(index < 0) index = length + index;
      }
      r = str ? arr.charAt(index) || '' : arr[index];
      result.push(r);
    });
    return result.length < 2 ? result[0] : result;
  }

  // Object class methods implemented as instance methods

  function buildObjectInstanceMethods(set, target) {
    extendSimilar(target, true, false, set, function(methods, name) {
      methods[name + (name === 'equal' ? 's' : '')] = function() {
        return object[name].apply(null, [this].concat(multiArgs(arguments)));
      }
    });
  }

  initializeClasses();

<|endoftext|>


<commit_before>"use strict";

var util = require('util'),
  RouterManifest = require('./router-manifest'),
  _ = require('underscore'),
  util = require('util');

/**
 * Facet Core constructor
 *
 * @param   {Object}   options   Options object - must contain 'db' (mongoose instance)
 *                               and 'intercom' (EventEmitter instance) keys.
 *
 * @return  {void}
 */
var FacetCore = function ( options ) {
  // set the options
  this.setCommonAttributes( options );

  // load the appropriate middleware generating class
  var middlewareClass = require('./middleware/'+this.middlewareType);
  this.middleware = new middlewareClass(this);

  this.registerCoreEvents();
};

/**
 * Returns middleware that sets up a nodeStack and emits it for other modules.
 * This function is to be used when no other facet middleware is used in your app.
 *
 * @return  {function}
 */
FacetCore.prototype.facetInit = function () {
  return this.middleware.facetInitBuilder(this);
};

/**
 * Sets the common attributes for this instance
 *
 * @param   {Object}   options
 */
FacetCore.prototype.setCommonAttributes = function ( options ) {
  this.router = null;
  this.options = options;
  this.intercom = options.intercom;
  this.routerManifest = new RouterManifest();

  // set flag to toggle api access checking
  this.doAccessCheck = (options.doAccessCheck !== undefined) ? options.doAccessCheck : true;

  // the type of api auth to use, currently 'basic' and 'jwt' are supported
  this.apiAuthMethod = options.apiAuthMethod || 'basic';

  // api secret key used for encoding access tokens
  this.apiSecret = options.apiSecret || '';

  // was the api auth middleware used yet?
  this.apiAuthInitialized = false;

  // the router type dictates what signatures the middleware functions have
  this.middlewareType = options.middlewareType || 'connect';

  this._routeEventTracker = {};

  // nodeStack contains keys for req, res, next
  this.nodeStack = {};

  this._respondFacetEvent = null;
};

FacetCore.prototype.registerCoreEvents = function ( ) {
  var _this = this;

  // set the nodeStack (contains req, res, next keys)
  this.intercom.on('facet:init:nodestack', function initNodeStack(nodeStack, force) {
    _this.nodeStack = nodeStack;

  });

  // set apiAuthInitialized class variable
  this.intercom.on('facet:init:apiauth', function initApiAuth(value) {
    if( typeof value == 'boolean' ) {
      _this.apiAuthInitialized = value;
    }
  });
};

/**
 * Standard fare noop().
 */
FacetCore.prototype.noop = function(){};

FacetCore.prototype._prepareExtendedRoutes = function(routeBase, routesArr) {
  var extendedRoutes = routesArr.map(function extendedRouteMapper( routeObj ) {
    routeObj.type = 'extended';
    routeObj.route = routeBase + routeObj.route;

    return routeObj;
  });

  return extendedRoutes;
}

/**
 * Binds the routes passed into the provided router instance.
 *
 * @param   {Object}   router         Router instance (express, koa, custom, etc)
 * @param   {Object}   routeOptions   Options for route setup.
 *
 * @return  {Object}   router
 */
FacetCore.prototype.bindRoutes = function( router, routeOptions ) {
  // console.log("STARTING FacetCore::bindRoutes ", util.inspect(routeOptions, {depth:null}));
  // console.log("");

  var _this = this;
  // set the router
  this.router = router;

  // check for routes key, ie this is a composite module containing several api classes
  if(routeOptions.hasOwnProperty('routes') && _.isArray(routeOptions.routes)){
    for( var i in routeOptions.routes ) {
      var route = routeOptions.routes[i];

      if( route.hasOwnProperty('resourceReference') ) {
        var apiInstanceName = route.resourceReference;
      }
      else {
        throw new Error('A resourceReference key is required for each route');
      }

      if( route.hasOwnProperty('extended') ) {

        // console.log("-------------- extended routes found for route: ", route);

        if( _.isArray(route.extended) ) {
          var extendObj = route.extended.map(function extendedObjectMapper( currVal, idx, arr ) {
            currVal.routes = _this._prepareExtendedRoutes(currVal.routeBase, currVal.routes);
            return currVal;
          });

          for (var i = 0; i < extendObj.length; i++) {
            this[apiInstanceName].routerManifest.addRoutes(extendObj[i].routes);
          };
        }
        else if( route.hasOwnProperty('routeBase') && route.hasOwnProperty('routes') ) {
          route.routes = this._prepareExtendedRoutes(route.routeBase, route.routes);
          this[apiInstanceName].routerManifest.addRoutes(route.routes);
        }
        else {
          throw new Error('Extended routes must be defined as an object containing \'routeBase\' and \'bind\' keys or an array of such objects.')
        }
      }

      if( this.hasOwnProperty(apiInstanceName) ) {
        this[apiInstanceName].bindRoutes( this.router, {routeBase: route.routeBase} )
      }
      else {
        // TODO: errors should really be handled by a dedicated class
        throw new Error('No '+apiInstanceName+' key found on the current API class.');
      }
    } // end for( var i in routeOptions.routes )
  }
  else {
    throw new Error('The bindRoutes function requires a "routes" object or "route" string to be provided.');
  }

  return this.router;

};

/**
 * Executes a response for a given event. Determines how the data/error should
 * be handled. IF a success callback is passed, that trumps all other methods as
 * the user wants to override the flow with their own custom logic. Otherwise if
 * the current event has any listeners registered for it on intercom, the event is
 * emitted. Finally if none of those are true, a promise is returned so the user
 * can interact with it however they see fit.
 *
 * @param   {String}    fEvent      The current event
 * @param   {Object}    promise     A promise for performing a CRUD operation
 * @param   {Function}  successCb   Custom function for handling CRUD succeess
 * @param   {Function}  errorCb     Custom function for handling CRUD error
 *
 * @return  {Object} | {void}
 */
FacetCore.prototype.respond = function(fEvent, promise, successCb, errorCb) {
  // console.log('');
  // console.log('');
  // console.log('is fn successCb: ', _.isFunction(successCb));
  // console.log('listener count for ' + fEvent + ': ', this.intercom.listenerCount(fEvent));
  // console.log(promise);
  // console.log(successCb);
  // console.log('');
  // console.log('');

  // set the fEvent for access in the callback function
  this._respondFacetEvent = fEvent;

  if( _.isFunction(successCb) ) {
    if( !_.isFunction(errorCb) ){
      errorCb = this.defaultErrorCb.bind(this);
    }
    promise.then(successCb, errorCb);
  }
  else if( this.intercom.listenerCount(fEvent) > 0 ) {
    // console.log('event listener present, waiting for promise to resolve...');
    promise.then(this.defaultSuccessCb.bind(this), this.defaultErrorCb.bind(this)).end();
  }
  else {
    return promise;
  }
};

/**
 * The default Facet Core success callback function
 *
 * @param    {[type]}   data   [description]
 *
 * @return   {[type]}          [description]
 */
FacetCore.prototype.defaultSuccessCb = function(data) {
  // console.log('in defaultSuccessCb: ', data, typeof data);

  // TODO: add more checks for failure to complete operation
  if( data === null || data === 0 ) {
    var findMessage = 'No item(s) matched your criteria.';
    if(
      this.hasOwnProperty('routerManifest')
      && this.routerManifest.hasOwnProperty('manifest')
      && this.routerManifest.manifest.hasOwnProperty('routeErrorMessages')
      && this.routerManifest.manifest.routeErrorMessages.hasOwnProperty('find')
    ){
      // override the default findMessage
      findMessage = this.routerManifest.manifest.routeErrorMessages.find;
    }
    this.intercom.emit('facet:response:error', 404, findMessage);
  }
  else {
    // console.log(fEvent);
    this.intercom.emit(this._respondFacetEvent, data);
    this._respondFacetEvent = null;
  }
};

/**
 * The default Facet Core error callback function
 *
 * @param    {Object}   err   The error object
 *
 * @return   {void}
 */
FacetCore.prototype.defaultErrorCb = function(err) {
  // console.log('in defaultErrorCb: ', err);

  var status = err.status || 400,
    errors = [];

  // handle all the validation errors from mongoose
  if(err.hasOwnProperty('errors')){
    for (var i in err.errors){
      errors.push({
        message: err.errors[i].message,
        type: err.errors[i].name || err.name || 'GeneralError'
      });
    }
  } else {
    errors.push({
      message: err.message,
      type: err.name || 'GeneralError'
    })
  }

  this.intercom.emit('facet:response:error', status, errors);
};

// export the main function
exports = module.exports = FacetCore;
<commit_msg>init the strip fields struct<commit_after>"use strict";

var util = require('util'),
  RouterManifest = require('./router-manifest'),
  _ = require('underscore'),
  util = require('util');

/**
 * Facet Core constructor
 *
 * @param   {Object}   options   Options object - must contain 'db' (mongoose instance)
 *                               and 'intercom' (EventEmitter instance) keys.
 *
 * @return  {void}
 */
var FacetCore = function ( options ) {
  // set the options
  this.setCommonAttributes( options );

  // load the appropriate middleware generating class
  var middlewareClass = require('./middleware/'+this.middlewareType);
  this.middleware = new middlewareClass(this);

  this.registerCoreEvents();
};

/**
 * Returns middleware that sets up a nodeStack and emits it for other modules.
 * This function is to be used when no other facet middleware is used in your app.
 *
 * @return  {function}
 */
FacetCore.prototype.facetInit = function () {
  return this.middleware.facetInitBuilder(this);
};

/**
 * Sets the common attributes for this instance
 *
 * @param   {Object}   options
 */
FacetCore.prototype.setCommonAttributes = function ( options ) {
  this.router = null;
  this.options = options;
  this.intercom = options.intercom;
  this.routerManifest = new RouterManifest();

  // set flag to toggle api access checking
  this.doAccessCheck = (options.doAccessCheck !== undefined) ? options.doAccessCheck : true;

  // the type of api auth to use, currently 'basic' and 'jwt' are supported
  this.apiAuthMethod = options.apiAuthMethod || 'basic';

  // api secret key used for encoding access tokens
  this.apiSecret = options.apiSecret || '';

  // was the api auth middleware used yet?
  this.apiAuthInitialized = false;

  // the router type dictates what signatures the middleware functions have
  this.middlewareType = options.middlewareType || 'connect';

  this._routeEventTracker = {};

  // nodeStack contains keys for req, res, next
  this.nodeStack = {};

  this._respondFacetEvent = null;

  // init the restricted fields object
  this.STRIP_FIELDS = {
    GET: [],
    POST: [],
    PUT: []
  };
};

FacetCore.prototype.registerCoreEvents = function ( ) {
  var _this = this;

  // set the nodeStack (contains req, res, next keys)
  this.intercom.on('facet:init:nodestack', function initNodeStack(nodeStack, force) {
    _this.nodeStack = nodeStack;

  });

  // set apiAuthInitialized class variable
  this.intercom.on('facet:init:apiauth', function initApiAuth(value) {
    if( typeof value == 'boolean' ) {
      _this.apiAuthInitialized = value;
    }
  });
};

/**
 * Standard fare noop().
 */
FacetCore.prototype.noop = function(){};

FacetCore.prototype._prepareExtendedRoutes = function(routeBase, routesArr) {
  var extendedRoutes = routesArr.map(function extendedRouteMapper( routeObj ) {
    routeObj.type = 'extended';
    routeObj.route = routeBase + routeObj.route;

    return routeObj;
  });

  return extendedRoutes;
}

/**
 * Binds the routes passed into the provided router instance.
 *
 * @param   {Object}   router         Router instance (express, koa, custom, etc)
 * @param   {Object}   routeOptions   Options for route setup.
 *
 * @return  {Object}   router
 */
FacetCore.prototype.bindRoutes = function( router, routeOptions ) {
  // console.log("STARTING FacetCore::bindRoutes ", util.inspect(routeOptions, {depth:null}));
  // console.log("");

  var _this = this;
  // set the router
  this.router = router;

  // check for routes key, ie this is a composite module containing several api classes
  if(routeOptions.hasOwnProperty('routes') && _.isArray(routeOptions.routes)){
    for( var i in routeOptions.routes ) {
      var route = routeOptions.routes[i];

      if( route.hasOwnProperty('resourceReference') ) {
        var apiInstanceName = route.resourceReference;
      }
      else {
        throw new Error('A resourceReference key is required for each route');
      }

      if( route.hasOwnProperty('extended') ) {

        // console.log("-------------- extended routes found for route: ", route);

        if( _.isArray(route.extended) ) {
          var extendObj = route.extended.map(function extendedObjectMapper( currVal, idx, arr ) {
            currVal.routes = _this._prepareExtendedRoutes(currVal.routeBase, currVal.routes);
            return currVal;
          });

          for (var i = 0; i < extendObj.length; i++) {
            this[apiInstanceName].routerManifest.addRoutes(extendObj[i].routes);
          };
        }
        else if( route.hasOwnProperty('routeBase') && route.hasOwnProperty('routes') ) {
          route.routes = this._prepareExtendedRoutes(route.routeBase, route.routes);
          this[apiInstanceName].routerManifest.addRoutes(route.routes);
        }
        else {
          throw new Error('Extended routes must be defined as an object containing \'routeBase\' and \'bind\' keys or an array of such objects.')
        }
      }

      if( this.hasOwnProperty(apiInstanceName) ) {
        this[apiInstanceName].bindRoutes( this.router, {routeBase: route.routeBase} )
      }
      else {
        // TODO: errors should really be handled by a dedicated class
        throw new Error('No '+apiInstanceName+' key found on the current API class.');
      }
    } // end for( var i in routeOptions.routes )
  }
  else {
    throw new Error('The bindRoutes function requires a "routes" object or "route" string to be provided.');
  }

  return this.router;

};

/**
 * Executes a response for a given event. Determines how the data/error should
 * be handled. IF a success callback is passed, that trumps all other methods as
 * the user wants to override the flow with their own custom logic. Otherwise if
 * the current event has any listeners registered for it on intercom, the event is
 * emitted. Finally if none of those are true, a promise is returned so the user
 * can interact with it however they see fit.
 *
 * @param   {String}    fEvent      The current event
 * @param   {Object}    promise     A promise for performing a CRUD operation
 * @param   {Function}  successCb   Custom function for handling CRUD succeess
 * @param   {Function}  errorCb     Custom function for handling CRUD error
 *
 * @return  {Object} | {void}
 */
FacetCore.prototype.respond = function(fEvent, promise, successCb, errorCb) {
  // console.log('');
  // console.log('');
  // console.log('is fn successCb: ', _.isFunction(successCb));
  // console.log('listener count for ' + fEvent + ': ', this.intercom.listenerCount(fEvent));
  // console.log(promise);
  // console.log(successCb);
  // console.log('');
  // console.log('');

  // set the fEvent for access in the callback function
  this._respondFacetEvent = fEvent;

  if( _.isFunction(successCb) ) {
    if( !_.isFunction(errorCb) ){
      errorCb = this.defaultErrorCb.bind(this);
    }
    promise.then(successCb, errorCb);
  }
  else if( this.intercom.listenerCount(fEvent) > 0 ) {
    // console.log('event listener present, waiting for promise to resolve...');
    promise.then(this.defaultSuccessCb.bind(this), this.defaultErrorCb.bind(this)).end();
  }
  else {
    return promise;
  }
};

/**
 * The default Facet Core success callback function
 *
 * @param    {[type]}   data   [description]
 *
 * @return   {[type]}          [description]
 */
FacetCore.prototype.defaultSuccessCb = function(data) {
  // console.log('in defaultSuccessCb: ', data, typeof data);

  // TODO: add more checks for failure to complete operation
  if( data === null || data === 0 ) {
    var findMessage = 'No item(s) matched your criteria.';
    if(
      this.hasOwnProperty('routerManifest')
      && this.routerManifest.hasOwnProperty('manifest')
      && this.routerManifest.manifest.hasOwnProperty('routeErrorMessages')
      && this.routerManifest.manifest.routeErrorMessages.hasOwnProperty('find')
    ){
      // override the default findMessage
      findMessage = this.routerManifest.manifest.routeErrorMessages.find;
    }
    this.intercom.emit('facet:response:error', 404, findMessage);
  }
  else {
    // console.log(fEvent);
    this.intercom.emit(this._respondFacetEvent, data);
    this._respondFacetEvent = null;
  }
};

/**
 * The default Facet Core error callback function
 *
 * @param    {Object}   err   The error object
 *
 * @return   {void}
 */
FacetCore.prototype.defaultErrorCb = function(err) {
  // console.log('in defaultErrorCb: ', err);

  var status = err.status || 400,
    errors = [];

  // handle all the validation errors from mongoose
  if(err.hasOwnProperty('errors')){
    for (var i in err.errors){
      errors.push({
        message: err.errors[i].message,
        type: err.errors[i].name || err.name || 'GeneralError'
      });
    }
  } else {
    errors.push({
      message: err.message,
      type: err.name || 'GeneralError'
    })
  }

  this.intercom.emit('facet:response:error', status, errors);
};

// export the main function
exports = module.exports = FacetCore;
<|endoftext|>


<commit_before>'use strict';

var usage = require('usage'),
    psTree = require('ps-tree'),
    step = require('step'),
    _ = require('underscore');

var core = {};

core.cpuUsage = function (program) {
  var containerName = program.name;
  var cpuUsageValue = 0;

  step(
    function() {
      psTree(containerName, this);
    },
    function(err, children) {

      var displayUsage = _.after(children.length, function(){
        console.log("Processes:" + children.length);
        console.log("CPU usage:" + cpuUsageValue);
      });

      _.each(children, function(target) {
        var pid = target.PID;

        usage.lookup(pid, function(err, result) {
          if (!err) {
            var oneUsage = _.template("PID:<%= pid %>\tCPU:<%= cpu%>");
            console.log(oneUsage({pid: pid, cpu: result.cpu}));
            cpuUsageValue += result.cpu;
            displayUsage();
          }
        });

      });
    }
  );
};

module.exports = core;

<commit_msg>verboseフラグ時のみプロセス詳細表示<commit_after>'use strict';

var usage = require('usage'),
    psTree = require('ps-tree'),
    step = require('step'),
    _ = require('underscore');

var core = {};

core.cpuUsage = function (program) {
  var containerName = program.name;
  var cpuUsageValue = 0;

  console.log("Target container: " + program.name);

  step(
    function() {
      psTree(containerName, this);
    },
    function(err, children) {

      var displayUsage = _.after(children.length, function(){
        console.log("Processes:" + children.length);
        console.log("CPU usage:" + cpuUsageValue);
      });

      _.each(children, function(target) {
        var pid = target.PID;

        usage.lookup(pid, function(err, result) {
          if (!err) {
            if (program.verbose) {
              var oneUsage = _.template("PID:<%= pid %>\tCPU:<%= cpu%>");
              console.log(oneUsage({pid: pid, cpu: result.cpu}));
            }

            cpuUsageValue += result.cpu;
            displayUsage();
          }
        });

      });
    }
  );
};

module.exports = core;

<|endoftext|>