<commit_before>var express = require('express');
var router = express.Router();

var randomstring = require('randomstring');

var authSignature = require('oauth-signature');

var request = require('request');

var md5 = require('md5');

var async = require('async');

var ig = require('instagram-node').instagram();

var forEach = require('async-foreach').forEach;

var _ = require('underscore');

/* GET popular locations given a LATITUDE / LONGITUDE */
router.get('/search/:LATITUDE/:LONGITUDE/', function(req, res, next) {
	var latitude = req.params.LATITUDE;
	var longitude = req.params.LONGITUDE;

	if (!latitude || !longitude) {
		res.json({ 'error': true, 'message': 'MISSING PARAMETER' });
	}

	if (isNaN(latitude) || isNaN(longitude)) {
		res.json({ 'error': true, 'message': 'PARAMETER NaN' });
	}

	function sortInstagram(unsorted, callback)
	{
		var locations = {};
		forEach(unsorted, function(image, result, array) {
			var imageLocationID = unsorted[result].location.id;
			if (locations[imageLocationID]) {
				locations[imageLocationID].push(unsorted[result]);
			} else {
				locations[imageLocationID] = [unsorted[result]];
			}
		}, function(notAborted, array)
		{
			callback(locations);
		});
	}

	function pushIntoArray(toBeExploded, toBePushed, callback)
	{
		var newArray = toBePushed;
		forEach(toBeExploded, function(exploded, index)
		{
			newArray.push(exploded);
		}, function(notAborted, array)
		{
			callback(newArray);
		});
	}

	function loadInstagramPhotos(MAX_TIMESTAMP, callback)
	{
		var url;
		if (MAX_TIMESTAMP) {
			url = config.get('instagram').FQDN + '?distance=5000&max_timestamp='+MAX_TIMESTAMP+'&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
		} else {
			url = config.get('instagram').FQDN + '?distance=5000&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
		}
		request(url, function(error, response, body)
		{
			if (error) {
				callback(error, null);
			}
			if (body && response.statusCode == 200) {
				var results = JSON.parse(body);
				callback(null, results);
			} else {
				callback('Error contacting Instagram API', null);
			}
		});
	}

	async.parallel({
		instagramLocations: function(callback)
		{
			var start = new Date();
			start.setHours(start.getHours-4);
			start = start / 1000;
			var url = config.get('instagram').FQDN + '?distance=5000&MIN_TIMESTAMP='+start+'&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
			var rawUnsorted = [];
			var iterations = 5;
			function instagramify(MAX_TIMESTAMP, callback)
			{
				loadInstagramPhotos(MAX_TIMESTAMP, function(error, results)
				{
					if (error) {
						console.error(error);
					}
					pushIntoArray(results.data, rawUnsorted, function(newResult) {
						rawUnsorted = newResult;
						callback();
					});
				});
			}
			forEach(_.range(5), function(item, index)
			{
				var done = this.async();
				var iteration = null;
				if (index > 0) {
					iterationIndex = (index*20)-1;
					if (rawUnsorted[iterationIndex]) {
						iteration = rawUnsorted[iterationIndex].created_time;
					} else {
						iteration = null;
					}
				}
				if ((index > 0 && iteration != null) || index == 0 ) {
					instagramify(iteration, function()
					{
						done();
					});
				} else {
					done();
				}
			}, function(notAborted, array)
			{
				sortInstagram(rawUnsorted, function(newlySorted)
				{
					callback(null, newlySorted);
				})
			});
		},
		twitter: function(callback)
		{
			var query_search_term = "";
			var parameters = {
				'oauth_consumer_key': config.get('twitter').consumer_key,
				'oauth_nonce': randomstring.generate({charset: 'alphabetic'}),
				'oauth_signature_method': 'HMAC-SHA1',
				'oauth_timestamp': Math.floor(new Date() / 1000),
				'oauth_token': config.get('twitter').oauth_token,
				'oauth_version': '1.0',
				'q': query_search_term,
				'geocode': '"'+latitude+','+longitude+',2mi"',
				'count': 100
			};
			var signature = authSignature.generate('GET',
													config.get('twitter').FQDN + "search/tweets.json",
													parameters,
													config.get('twitter').consumer_secret,
													config.get('twitter').oauth_token_secret);
			var options = {
				url: config.get('twitter').FQDN + 'search/tweets.json?q='+query_search_term+'&geocode="'+latitude+','+longitude+',2mi"&count=100',
				headers: {
					'Authorization': 'OAuth oauth_consumer_key="'+parameters['oauth_consumer_key']+'", oauth_nonce="'+parameters['oauth_nonce']+'", oauth_signature="'+signature+'", oauth_signature_method="'+parameters['oauth_signature_method']+'", oauth_timestamp="'+parameters['oauth_timestamp']+'", oauth_token="'+parameters['oauth_token']+'", oauth_version="'+parameters['oauth_version']+'"'
				}
			};
			request(options, function(error, response, body)
			{
				if (error) {
					callback(error, null);
				}
				if (body && response.statusCode == 200) {
					callback(null, JSON.parse(body))
				} else {
					callback(true, body)
				}
			});
		}
	}, function(error, results)
	{
		if (error) {
			res.send({'error': true, 'message': error})
		} else {
			var masterObject = [];

			// Get Sentiment First
			forEach(results['twitter']['statuses'], function(tweet, tweetIndex, array)
			{
				// Calculate sentiment
				// var sentimentURL = config.get('alchemy').Endpoint + "?outputMode=json&apikey=" + config.get('alchemy').API_KEY + "&text=" + results['twitter']['statuses'][tweetIndex].text;
				// request(sentimentURL, function(err, response, body)
				// {
				// 	if (err) {
				// 		console.log(err);
				// 	}

				// 	if (body && response.statusCode == 200) {
				// 		var doc = JSON.parse(body);
				// 		if (doc.status == "OK") {
				// 			var docSentiment = doc.docSentiment;
				// 			var sentiment = 0;
				// 			if (docSentiment.score) {
				// 				sentiment = docSentiment.score;
				// 			}
				// 			results['twitter']['statuses'][tweetIndex].sentiment = sentiment;
				// 		} else {
				// 			if (results['twitter']['statuses'][tweetIndex] != undefined) {
				// 				results['twitter']['statuses'][tweetIndex].sentiment = null;
				// 			}
				// 		}
				// 	} else {
				// 		if (results['twitter']['statuses'][tweetIndex] != undefined) {
				// 			results['twitter']['statuses'][tweetIndex].sentiment = null;
				// 		}
				// 	}
				// });
			}, function(notAborted, array)
			{
				function getFoursquareInformation(name, latitude, longitude, callback)
				{
					var url = config.get('foursquare').FQDN + 'venues/search?query='+ name +'&ll=' + latitude + ',' + longitude + '&intent=match&client_id='+ config.get('foursquare').client_id +'&client_secret=' + config.get('foursquare').client_secret + '&v=20140806';
					request(url, function(error, response, body)
					{
						if (error) {
							callback(error, null);
						}
						var fs = JSON.parse(body);
						var v = fs.response['venues'];
						if (v.length > 0) {
							callback(null, v[0])
						} else {
							callback(null, {});
						}
					});
				}
				forEach(_.range(Object.keys(results['instagramLocations']).length), function(object, index)
				{
					var i = Object.keys(results['instagramLocations'])[index]
					console.log(i)

					var ig = results['instagramLocations'][i.toString()];
					var location = ig[0].location;

					// Create new popular location Object
					var popular = {};
					popular.uuid = md5(location.latitude + "," + location.longitude);
					popular.name = location.name;
					popular.instagram = [];
					popular.tweets = [];
					popular.foursquare = {};
					popular.location = {};

					console.log(location.name)

					// Basic spam checker (removes any object with name that contains .com/.net/.org)
					if (popular.name.indexOf('.com') > -1 || popular.name.indexOf('.net') > -1 || popular.name.indexOf('.org') > -1) {
						return;
					}

					// Populate popular location Object with instagram photos
					for (photoIndex in ig)
					{
						var photo = ig[photoIndex];

						if (!photo.location || photo.type != 'image') {
							return;
						}

						popular.loc = photo.location;

						var photoData = {};
						photoData.loc = photo.location;
						photoData.created_time = photo.created_time;
						photoData.link = photo.link;
						photoData.fullResImageData = photo.images.standard_resolution;
						photoData.caption = photo.caption;

						popular.instagram.push(photoData);
					}

					var done = this.async();
					async.parallel({
						foursquare: function(callback)
						{
							getFoursquareInformation(location.name, location.latitude, location.longitude, function(error, results)
							{
								callback(null, results);
							});
						},
						twitter: function(callback)
						{
							var locationTweets = [];
							forEach(results['twitter']['statuses'], function (item, tweetIndex, array)
							{
								var tweet = results['twitter']['statuses'][tweetIndex];
								if (tweet) {
									// Remove from tweet object -- It's of little value to us
									if (tweet.geo == null) {
										results['twitter']['statuses'].splice(tweetIndex, 1);
									} else {
										// Compare lat/long
										var photoLat  = popular.loc.latitude;
										var photoLong = popular.loc.longitude;
										var tweetLat  = tweet.geo.coordinates[0];
										var tweetLong = tweet.geo.coordinates[1];

										if ((tweetLat > photoLat - .001 && tweetLat < photoLat + .001) && (tweetLong > photoLong - .001 && tweetLong < photoLong + .001)) {
											var tweetData = {};
											tweetData.text = tweet.text;
											tweetData.id = tweet.id;
											tweetData.created_at = tweet.created_at;
											tweetData.geo = tweet.geo;

											// Remove from tweet array now that we know where it belongs
											results['twitter']['statuses'].slice(tweetIndex, 1);

											locationTweets.push(tweetData);
										}
									}
								}
							}, function(notAborted, array)
							{
								callback(null, locationTweets);
							});
						}
					}, function(error, results)
					{
						popular.tweets = results['twitter'];
						popular.foursquare = results['foursquare'];
						masterObject.push(popular);
						done()
					});
				}, function(notAborted, array)
				{
					res.json(masterObject);
				});
			});
		}
	});
});

/* GET popular locations given a LATITUDE / LONGITUDE */
router.get('/event/:LATITUDE/:LONGITUDE/:NAME/', function(req, res, next) {

	var latitude = req.params.LATITUDE;
	var longitude = req.params.LONGITUDE;
	var name = req.params.NAME;

	if (!latitude || !longitude || !name) {
		res.json({ 'error': true, 'message': 'MISSING PARAMETER' });
	}

	if (isNaN(latitude) || isNaN(longitude)) {
		res.json({ 'error': true, 'message': 'PARAMETER NaN' });
	}

	res.json({'data': 'THERE WILL BE SOMETHING HERE EVENTUALLY'});
});
module.exports = router;
<commit_msg>Removed extraneous console.logs()<commit_after>var express = require('express');
var router = express.Router();

var randomstring = require('randomstring');

var authSignature = require('oauth-signature');

var request = require('request');

var md5 = require('md5');

var async = require('async');

var ig = require('instagram-node').instagram();

var forEach = require('async-foreach').forEach;

var _ = require('underscore');

/* GET popular locations given a LATITUDE / LONGITUDE */
router.get('/search/:LATITUDE/:LONGITUDE/', function(req, res, next) {
	var latitude = req.params.LATITUDE;
	var longitude = req.params.LONGITUDE;

	if (!latitude || !longitude) {
		res.json({ 'error': true, 'message': 'MISSING PARAMETER' });
	}

	if (isNaN(latitude) || isNaN(longitude)) {
		res.json({ 'error': true, 'message': 'PARAMETER NaN' });
	}

	function sortInstagram(unsorted, callback)
	{
		var locations = {};
		forEach(unsorted, function(image, result, array) {
			var imageLocationID = unsorted[result].location.id;
			if (locations[imageLocationID]) {
				locations[imageLocationID].push(unsorted[result]);
			} else {
				locations[imageLocationID] = [unsorted[result]];
			}
		}, function(notAborted, array)
		{
			callback(locations);
		});
	}

	function pushIntoArray(toBeExploded, toBePushed, callback)
	{
		var newArray = toBePushed;
		forEach(toBeExploded, function(exploded, index)
		{
			newArray.push(exploded);
		}, function(notAborted, array)
		{
			callback(newArray);
		});
	}

	function loadInstagramPhotos(MAX_TIMESTAMP, callback)
	{
		var url;
		if (MAX_TIMESTAMP) {
			url = config.get('instagram').FQDN + '?distance=5000&max_timestamp='+MAX_TIMESTAMP+'&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
		} else {
			url = config.get('instagram').FQDN + '?distance=5000&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
		}
		request(url, function(error, response, body)
		{
			if (error) {
				callback(error, null);
			}
			if (body && response.statusCode == 200) {
				var results = JSON.parse(body);
				callback(null, results);
			} else {
				callback('Error contacting Instagram API', null);
			}
		});
	}

	async.parallel({
		instagramLocations: function(callback)
		{
			var start = new Date();
			start.setHours(start.getHours-4);
			start = start / 1000;
			var url = config.get('instagram').FQDN + '?distance=5000&MIN_TIMESTAMP='+start+'&access_token=' + config.get('instagram').access_token + '&lat=' + latitude + '&lng=' + longitude;
			var rawUnsorted = [];
			var iterations = 5;
			function instagramify(MAX_TIMESTAMP, callback)
			{
				loadInstagramPhotos(MAX_TIMESTAMP, function(error, results)
				{
					if (error) {
						console.error(error);
					}
					pushIntoArray(results.data, rawUnsorted, function(newResult) {
						rawUnsorted = newResult;
						callback();
					});
				});
			}
			forEach(_.range(5), function(item, index)
			{
				var done = this.async();
				var iteration = null;
				if (index > 0) {
					iterationIndex = (index*20)-1;
					if (rawUnsorted[iterationIndex]) {
						iteration = rawUnsorted[iterationIndex].created_time;
					} else {
						iteration = null;
					}
				}
				if ((index > 0 && iteration != null) || index == 0 ) {
					instagramify(iteration, function()
					{
						done();
					});
				} else {
					done();
				}
			}, function(notAborted, array)
			{
				sortInstagram(rawUnsorted, function(newlySorted)
				{
					callback(null, newlySorted);
				})
			});
		},
		twitter: function(callback)
		{
			var query_search_term = "";
			var parameters = {
				'oauth_consumer_key': config.get('twitter').consumer_key,
				'oauth_nonce': randomstring.generate({charset: 'alphabetic'}),
				'oauth_signature_method': 'HMAC-SHA1',
				'oauth_timestamp': Math.floor(new Date() / 1000),
				'oauth_token': config.get('twitter').oauth_token,
				'oauth_version': '1.0',
				'q': query_search_term,
				'geocode': '"'+latitude+','+longitude+',2mi"',
				'count': 100
			};
			var signature = authSignature.generate('GET',
													config.get('twitter').FQDN + "search/tweets.json",
													parameters,
													config.get('twitter').consumer_secret,
													config.get('twitter').oauth_token_secret);
			var options = {
				url: config.get('twitter').FQDN + 'search/tweets.json?q='+query_search_term+'&geocode="'+latitude+','+longitude+',2mi"&count=100',
				headers: {
					'Authorization': 'OAuth oauth_consumer_key="'+parameters['oauth_consumer_key']+'", oauth_nonce="'+parameters['oauth_nonce']+'", oauth_signature="'+signature+'", oauth_signature_method="'+parameters['oauth_signature_method']+'", oauth_timestamp="'+parameters['oauth_timestamp']+'", oauth_token="'+parameters['oauth_token']+'", oauth_version="'+parameters['oauth_version']+'"'
				}
			};
			request(options, function(error, response, body)
			{
				if (error) {
					callback(error, null);
				}
				if (body && response.statusCode == 200) {
					callback(null, JSON.parse(body))
				} else {
					callback(true, body)
				}
			});
		}
	}, function(error, results)
	{
		if (error) {
			res.send({'error': true, 'message': error})
		} else {
			var masterObject = [];

			// Get Sentiment First
			forEach(results['twitter']['statuses'], function(tweet, tweetIndex, array)
			{
				// Calculate sentiment
				// var sentimentURL = config.get('alchemy').Endpoint + "?outputMode=json&apikey=" + config.get('alchemy').API_KEY + "&text=" + results['twitter']['statuses'][tweetIndex].text;
				// request(sentimentURL, function(err, response, body)
				// {
				// 	if (err) {
				// 		console.log(err);
				// 	}

				// 	if (body && response.statusCode == 200) {
				// 		var doc = JSON.parse(body);
				// 		if (doc.status == "OK") {
				// 			var docSentiment = doc.docSentiment;
				// 			var sentiment = 0;
				// 			if (docSentiment.score) {
				// 				sentiment = docSentiment.score;
				// 			}
				// 			results['twitter']['statuses'][tweetIndex].sentiment = sentiment;
				// 		} else {
				// 			if (results['twitter']['statuses'][tweetIndex] != undefined) {
				// 				results['twitter']['statuses'][tweetIndex].sentiment = null;
				// 			}
				// 		}
				// 	} else {
				// 		if (results['twitter']['statuses'][tweetIndex] != undefined) {
				// 			results['twitter']['statuses'][tweetIndex].sentiment = null;
				// 		}
				// 	}
				// });
			}, function(notAborted, array)
			{
				function getFoursquareInformation(name, latitude, longitude, callback)
				{
					var url = config.get('foursquare').FQDN + 'venues/search?query='+ name +'&ll=' + latitude + ',' + longitude + '&intent=match&client_id='+ config.get('foursquare').client_id +'&client_secret=' + config.get('foursquare').client_secret + '&v=20140806';
					request(url, function(error, response, body)
					{
						if (error) {
							callback(error, null);
						}
						var fs = JSON.parse(body);
						var v = fs.response['venues'];
						if (v.length > 0) {
							callback(null, v[0])
						} else {
							callback(null, {});
						}
					});
				}
				forEach(_.range(Object.keys(results['instagramLocations']).length), function(object, index)
				{
					var i = Object.keys(results['instagramLocations'])[index]

					var ig = results['instagramLocations'][i.toString()];
					var location = ig[0].location;

					// Create new popular location Object
					var popular = {};
					popular.uuid = md5(location.latitude + "," + location.longitude);
					popular.name = location.name;
					popular.instagram = [];
					popular.tweets = [];
					popular.foursquare = {};
					popular.location = {};

					// Basic spam checker (removes any object with name that contains .com/.net/.org)
					if (popular.name.indexOf('.com') > -1 || popular.name.indexOf('.net') > -1 || popular.name.indexOf('.org') > -1) {
						return;
					}

					// Populate popular location Object with instagram photos
					for (photoIndex in ig)
					{
						var photo = ig[photoIndex];

						if (!photo.location || photo.type != 'image') {
							return;
						}

						popular.loc = photo.location;

						var photoData = {};
						photoData.loc = photo.location;
						photoData.created_time = photo.created_time;
						photoData.link = photo.link;
						photoData.fullResImageData = photo.images.standard_resolution;
						photoData.caption = photo.caption;

						popular.instagram.push(photoData);
					}

					var done = this.async();
					async.parallel({
						foursquare: function(callback)
						{
							getFoursquareInformation(location.name, location.latitude, location.longitude, function(error, results)
							{
								callback(null, results);
							});
						},
						twitter: function(callback)
						{
							var locationTweets = [];
							forEach(results['twitter']['statuses'], function (item, tweetIndex, array)
							{
								var tweet = results['twitter']['statuses'][tweetIndex];
								if (tweet) {
									// Remove from tweet object -- It's of little value to us
									if (tweet.geo == null) {
										results['twitter']['statuses'].splice(tweetIndex, 1);
									} else {
										// Compare lat/long
										var photoLat  = popular.loc.latitude;
										var photoLong = popular.loc.longitude;
										var tweetLat  = tweet.geo.coordinates[0];
										var tweetLong = tweet.geo.coordinates[1];

										if ((tweetLat > photoLat - .001 && tweetLat < photoLat + .001) && (tweetLong > photoLong - .001 && tweetLong < photoLong + .001)) {
											var tweetData = {};
											tweetData.text = tweet.text;
											tweetData.id = tweet.id;
											tweetData.created_at = tweet.created_at;
											tweetData.geo = tweet.geo;

											// Remove from tweet array now that we know where it belongs
											results['twitter']['statuses'].slice(tweetIndex, 1);

											locationTweets.push(tweetData);
										}
									}
								}
							}, function(notAborted, array)
							{
								callback(null, locationTweets);
							});
						}
					}, function(error, results)
					{
						popular.tweets = results['twitter'];
						popular.foursquare = results['foursquare'];
						masterObject.push(popular);
						done()
					});
				}, function(notAborted, array)
				{
					res.json(masterObject);
				});
			});
		}
	});
});

/* GET popular locations given a LATITUDE / LONGITUDE */
router.get('/event/:LATITUDE/:LONGITUDE/:NAME/', function(req, res, next) {

	var latitude = req.params.LATITUDE;
	var longitude = req.params.LONGITUDE;
	var name = req.params.NAME;

	if (!latitude || !longitude || !name) {
		res.json({ 'error': true, 'message': 'MISSING PARAMETER' });
	}

	if (isNaN(latitude) || isNaN(longitude)) {
		res.json({ 'error': true, 'message': 'PARAMETER NaN' });
	}

	res.json({'data': 'THERE WILL BE SOMETHING HERE EVENTUALLY'});
});
module.exports = router;
<|endoftext|>


<commit_before>// Adapted from: https://gist.github.com/gnomeontherun/5678505
(function(angular, document){
  'use strict';

  angular.module('pzgps').factory('intercept', ['$q', '$rootScope', '$log', function($q, $rootScope, $log) {
    $log.log("intercept factory is running");

    var request = function(obj) {
      // Access to lots of great stuff in here...
      // obj.headers (object), obj.method (string), obj.url (string), obj.withCredentials (boolean)
      //$log.log("intercept: request");
      //$log.log(obj);
      // transform the response here if you need to, the request config is in config
      return obj || $q.when(obj);
    };

    var requestError = function(obj) { // a failed request
      //$log.log("intercept: requestError");
      //$log.log(obj);
      return $q.reject(obj);
    };

    var response = function(obj) { // a succuesful response
      //$log.log("intercept: response");
      //$log.log(obj);
      // transform the response here if you need to, the deserialize JSON is in obj.data
      return obj || $q.when(obj);
    };

    var responseError = function(obj) { // a failed response
      $log.log("intercept factory caught an error: " + obj.status);
      //$log.log(obj); // this object is handed to $http and .then() fires with the object
      return $q.reject(obj);
    };

    return {
      'request': request,
      'requestError': requestError,
      'response': response,
      'responseError': responseError
    };

  }]);

}(window.angular, document));
<commit_msg>removed the document<commit_after>// Adapted from: https://gist.github.com/gnomeontherun/5678505
(function(angular){
  'use strict';

  angular.module('pzgps').factory('intercept', ['$q', '$rootScope', '$log', function($q, $rootScope, $log) {
    $log.log("intercept factory is running");

    var request = function(obj) {
      // Access to lots of great stuff in here...
      // obj.headers (object), obj.method (string), obj.url (string), obj.withCredentials (boolean)
      //$log.log("intercept: request");
      //$log.log(obj);
      // transform the response here if you need to, the request config is in config
      return obj || $q.when(obj);
    };

    var requestError = function(obj) { // a failed request
      //$log.log("intercept: requestError");
      //$log.log(obj);
      return $q.reject(obj);
    };

    var response = function(obj) { // a succuesful response
      //$log.log("intercept: response");
      //$log.log(obj);
      // transform the response here if you need to, the deserialize JSON is in obj.data
      return obj || $q.when(obj);
    };

    var responseError = function(obj) { // a failed response
      $log.log("intercept factory caught an error: " + obj.status);
      //$log.log(obj); // this object is handed to $http and .then() fires with the object
      return $q.reject(obj);
    };

    return {
      'request': request,
      'requestError': requestError,
      'response': response,
      'responseError': responseError
    };

  }]);

}(window.angular));
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var isProbability = require( '@stdlib/math/base/assert/is-probability' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var ln = require( '@stdlib/math/base/special/ln' );
var PINF = require( '@stdlib/constants/math/float64-pinf' );
var NINF = require( '@stdlib/constants/math/float64-ninf' );

// MAIN //

/**
* Evaluates the logit function.
*
* @param {Probability} p - input value
* @returns {number} function value
*
* @example
* var y = logit( 0.2 );
* // returns ~-1.386
*
* @example
* var y = logit( 0.9 );
* // returns ~2.197
*
* @example
* var y = logit( -4.0 );
* // returns NaN
*
* @example
* var y = logit( 1.5 );
* // returns NaN
*
* @example
* var y = logit( NaN );
* // returns NaN
*/
function logit( p ) {
	if ( isnan( p ) ) {
		return p;
	}
	if ( !isProbability( p ) ) {
		return NaN;
	}
	if ( p === 0.0 ) {
		return NINF;
	}
	if ( p === 1.0 ) {
		return PINF;
	}
	return ln( p / ( 1.0 - p ) );
} // end FUNCTION logit()

// EXPORTS //

module.exports = logit;
<commit_msg>Remove spaces<commit_after>'use strict';

// MODULES //

var isProbability = require( '@stdlib/math/base/assert/is-probability' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var ln = require( '@stdlib/math/base/special/ln' );
var PINF = require( '@stdlib/constants/math/float64-pinf' );
var NINF = require( '@stdlib/constants/math/float64-ninf' );

// MAIN //

/**
* Evaluates the logit function.
*
* @param {Probability} p - input value
* @returns {number} function value
*
* @example
* var y = logit( 0.2 );
* // returns ~-1.386
*
* @example
* var y = logit( 0.9 );
* // returns ~2.197
*
* @example
* var y = logit( -4.0 );
* // returns NaN
*
* @example
* var y = logit( 1.5 );
* // returns NaN
*
* @example
* var y = logit( NaN );
* // returns NaN
*/
function logit( p ) {
	if ( isnan( p ) ) {
		return p;
	}
	if ( !isProbability( p ) ) {
		return NaN;
	}
	if ( p === 0.0 ) {
		return NINF;
	}
	if ( p === 1.0 ) {
		return PINF;
	}
	return ln( p / ( 1.0-p ) );
} // end FUNCTION logit()

// EXPORTS //

module.exports = logit;
<|endoftext|>


<commit_before>
import React, {Component, PropTypes} from 'react';
import * as ReactDOM from 'react-dom';
import {_} from "./help.js";

class Swipe extends Component {
     constructor(props) {
        super(props);
        this.state = {
          value: props.value,
          isShowLoad:true
        };

        this.scrollInit = this.scrollInit.bind(this);
        //this.scrollEnd = this.scrollEnd.bind(this);
        //this.upFn = this.upFn.bind(this);
        //this.handleBlur = this.handleBlur.bind(this);
    }
    componentWillMount(){
        let _this = this;
        _this.AlloyTouch = false;
        require.ensure([], () => {
           _this.AlloyTouch = require("./alloyTouch.js");
        })
    }
    componentWillReceiveProps(nextProps){

        if(nextProps.isShowLoad!==undefined&&nextProps.isShowLoad!==this.state.isShowLoad){
            this.setState({
                isShowLoad:nextProps.isShowLoad
            })
        }
    }
    componentDidUpdate(prevProps,prevState){
       /* if(this.AlloyTouch&&prevState.isShowLoad!==this.state.isShowLoad){
            //console.log("掉用这里？")
            this.scrollInit();
        }*/

        let {stopPro,property,width,min,max,step,findScroller,vertical,findDis,touchMove} = this.props;
        if(min==="auto"&&this.alloyTouch&&vertical===true&&property==="translateY"){
            // debugger;
              let target = ReactDOM.findDOMNode(this.refs.swipe);
            let dom = ReactDOM.findDOMNode(this.refs.touch); //offsetTop
            let length = -(target.clientHeight-dom.clientHeight);
            this.alloyTouch.min = length>0?0:length;
         }
         //dom.children[0].style.transform="translateY(0px)";
    }
    componentDidMount(){
        let _this = this;
        if(_this.AlloyTouch){
            _this.scrollInit()
        }else{
            require.ensure([], () => {
               _this.AlloyTouch = require("./alloyTouch.js");
               _this.scrollInit();
            })
        }
    }
    componentWillUnmount(){
        //debugger
        this.alloyTouch&&this.alloyTouch.destory();
    }
    scrollInit(){
        let dom = ReactDOM.findDOMNode(this.refs.touch); //offsetTop
         let target = ReactDOM.findDOMNode(this.refs.swipe);
        let {intervals,stopPro,property,width,min,max,step,findScroller,vertical,findDis,touchMove} = this.props;
        let prevTarget = false;
        //let $ = this.$;

        // if(findDis!==false){
        //     let dis = $(findDis,$(dom)).eq(0).width();
        //     min = -dis;
        //     step = dis;
        // }

        //console.log("dom",dom);
        if(min==="auto"){
            min = -1000;
            min = -((vertical===false?target.offsetWidth:target.offsetHeight)-(vertical===false?dom.offsetWidth:dom.offsetHeight));
            console.log(min);
            min = min>0?0:min;
        }
        this.alloyTouch = new this.AlloyTouch({
            touch: dom,//反馈触摸的dom
            vertical: vertical,//不必需，默认是true代表监听竖直方向touch
            target: target, //运动的对象
            property: property,  //被运动的属性
            sensitivity: 1,//不必需,触摸区域的灵敏度，默认值为1，可以为负数
            factor: 1,//不必需,表示触摸位移与被运动属性映射关系，默认值是1
            min: min, //不必需,运动属性的最小值
            max: max, //不必需,滚动属性的最大值
            step: step,
            spring: true, //不必需,是否有回弹效果。默认是true
            inertia: true, //不必需,是否有惯性。默认是true
            intelligentCorrection: true,
            stopPro:stopPro,
            touchStart: function (value,target) {
                console.log("heheda ",value)
            },
            touchMove:_.throttle(function(){
                touchMove(this,arguments);
            },intervals),

        });

    }
    render() {
        let {onClick} = this.props;
        return (

                    {this.props.children}

        );
    }
}

Swipe.defaultProps={
    property:"translateX",
    width:false,
    min:0,
    max:0,
    step:0,
    vertical:false,
    findScroller:false,
    target:"",
    className:"",
    findDis:false,
    stopPro:true,
    intervals:300,//间隔时间
    touchMove:function(x){
        //console.error("sssssss",this,x)
    },
    onClick:function(){

    }

}

module.exports = Swipe;
<commit_msg>Swipe update<commit_after>
import React, {Component, PropTypes} from 'react';
import * as ReactDOM from 'react-dom';
import {_} from "./help.js";

class Swipe extends Component {
     constructor(props) {
        super(props);
        this.state = {
          value: props.value,
          isShowLoad:true
        };

        this.scrollInit = this.scrollInit.bind(this);
        //this.scrollEnd = this.scrollEnd.bind(this);
        //this.upFn = this.upFn.bind(this);
        //this.handleBlur = this.handleBlur.bind(this);
    }
    componentWillMount(){
        let _this = this;
        _this.AlloyTouch = false;
        require.ensure([], () => {
           _this.AlloyTouch = require("./alloyTouch.js");
        })
    }
    componentWillReceiveProps(nextProps){

        if(nextProps.isShowLoad!==undefined&&nextProps.isShowLoad!==this.state.isShowLoad){
            this.setState({
                isShowLoad:nextProps.isShowLoad
            })
        }
    }
    componentDidUpdate(prevProps,prevState){
       /* if(this.AlloyTouch&&prevState.isShowLoad!==this.state.isShowLoad){
            //console.log("掉用这里？")
            this.scrollInit();
        }*/

        let {stopPro,property,width,min,max,step,findScroller,vertical,findDis,touchMove} = this.props;
        if(min==="auto"&&this.alloyTouch&&vertical===true&&property==="translateY"){
            // debugger;
              let target = ReactDOM.findDOMNode(this.refs.swipe);
            let dom = ReactDOM.findDOMNode(this.refs.touch); //offsetTop
            let length = -(target.clientHeight-dom.clientHeight);
            this.alloyTouch.min = length>0?0:length;
         }
         //dom.children[0].style.transform="translateY(0px)";
    }
    componentDidMount(){
        let _this = this;
        if(_this.AlloyTouch){
            _this.scrollInit()
        }else{
            require.ensure([], () => {
               _this.AlloyTouch = require("./alloyTouch.js");
               _this.scrollInit();
            })
        }
    }
    componentWillUnmount(){
        //debugger
        this.alloyTouch&&this.alloyTouch.destory();
    }
    scrollInit(){
        let dom = ReactDOM.findDOMNode(this.refs.touch); //offsetTop
         let target = ReactDOM.findDOMNode(this.refs.swipe);
        let {intervals,stopPro,property,width,min,max,step,findScroller,vertical,findDis,touchMove,inertia} = this.props;
        let prevTarget = false;
        //let $ = this.$;

        // if(findDis!==false){
        //     let dis = $(findDis,$(dom)).eq(0).width();
        //     min = -dis;
        //     step = dis;
        // }

        //console.log("dom",dom);
        if(min==="auto"){
            min = -1000;
            min = -((vertical===false?target.offsetWidth:target.offsetHeight)-(vertical===false?dom.offsetWidth:dom.offsetHeight));
            console.log(min);
            min = min>0?0:min;
        }
        this.alloyTouch = new this.AlloyTouch({
            touch: dom,//反馈触摸的dom
            vertical: vertical,//不必需，默认是true代表监听竖直方向touch
            target: target, //运动的对象
            property: property,  //被运动的属性
            sensitivity: 1,//不必需,触摸区域的灵敏度，默认值为1，可以为负数
            factor: 1,//不必需,表示触摸位移与被运动属性映射关系，默认值是1
            min: min, //不必需,运动属性的最小值
            max: max, //不必需,滚动属性的最大值
            step: step,
            spring: true, //不必需,是否有回弹效果。默认是true
            inertia: inertia, //不必需,是否有惯性。默认是true
            intelligentCorrection: true,
            stopPro:stopPro,
            touchStart: function (value,target) {
                console.log("heheda ",value)
            },
            touchMove:_.throttle(function(){
                touchMove(this,arguments);
            },intervals),

        });

    }
    render() {
        let {onClick} = this.props;
        return (

                    {this.props.children}

        );
    }
}

Swipe.defaultProps={
    property:"translateX",
    width:false,
    min:0,
    max:0,
    step:0,
    vertical:false,
    findScroller:false,
    target:"",
    className:"",
    findDis:false,
    stopPro:true,
    inertia:true,
    intervals:300,//间隔时间
    touchMove:function(x){
        //console.error("sssssss",this,x)
    },
    onClick:function(){

    }

}

module.exports = Swipe;
<|endoftext|>


<commit_before>/*
 * Url module. Required for resolving relative paths.
 */

var url = require("url");

/*
 * Regexp from origin Arc90 Readability.
 */

var regexps = {
  unlikelyCandidatesRe: /combx|pager|comment|disqus|foot|header|menu|meta|nav|rss|shoutbox|sidebar|sponsor|share|bookmark|social|advert|leaderboard|instapaper_ignore/i,
  okMaybeItsACandidateRe: /and|article|body|column|main/i,
  positiveRe: /article|body|content|entry|hentry|page|pagination|post|text/i,
  negativeRe: /combx|comment|captcha|contact|foot|footer|footnote|link|media|meta|promo|related|scroll|shoutbox|sponsor|utility|tags|widget/i,
  divToPElementsRe: /<(a|blockquote|dl|div|img|ol|p|pre|table|ul)/i,
  replaceBrsRe: /(
]*>[ \n\r\t]*){2,}/gi,
  replaceFontsRe: /<(\/?)font[^>]*>/gi,
  trimRe: /^\s+|\s+$/g,
  normalizeRe: /\s{2,}/g,
  killBreaksRe: /(
(\s| ?)*){1,}/g,
  videoRe: /http:\/\/(www\.)?(youtube|vimeo|youku|tudou|56|yinyuetai)\.com/i
};

/**
 * Node Types and their classification
 **/

var nodeTypes = {
  'mostPositive': ['div'],
  'positive': ['pre', 'td', 'blockquote'],
  'negative': ['address', 'ol', 'ul', 'dl', 'dd', 'dt', 'li'],
  'mostNegative': ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'th']
}

/**
 * We're getting only the readable content + images, no other nodes are needed.
 **/

var trashNodes = 'meta,iframe,noscript,style,aside,object,form,script';

/**
 * Select the TopCandidate from all possible candidates
 **/

function getArticle(candidates, $) {
  var topCandidate = null;

  candidates.forEach(function(elem) {
    var linkDensity = getLinkDensity(elem, $);
    var score = elem.data('readabilityScore');
    var siblings = elem.find("*").length;

    elem.data('readabilityScore', Math.max(2, siblings) * score * (1 - linkDensity));
    if (!topCandidate || elem.data('readabilityScore') > topCandidate.data('readabilityScore')) {
      topCandidate = elem;
    }
  });

  /**
   * If we still have no top candidate, just use the body as a last resort.
   * We also have to copy the body node so it is something we can modify.
   **/
  if (topCandidate === null) {
    // With no top candidate, bail out if no body tag exists as last resort.
    if (!$('body')) return new Error("No body tag was found.");
    return $('body');
  }
  // Perhaps the topCandidate is the parent?
  if (topCandidate.children().length > 5) {
    return filterCandidates(topCandidate, topCandidate.children(), $);
  } else {
    return filterCandidates(topCandidate, topCandidate.parent().children(), $);
  }
}

/**
 * Filter TopCandidate Siblings (Children) based on their Link Density, and readabilityScore
 * Append the nodes to articleContent
 **/

function filterCandidates(topCandidate, siblings, $) {

  var articleContent = $("

");
  var siblingScoreThreshold = Math.max(10, topCandidate.data('readabilityScore') * 0.2);

  siblings.each(function(index, elem) {
    var sibling = $(this);
    var append = false;
    var type = sibling.get(0).name;
    var score = sibling.data('readabilityScore');
    var children = siblings.contents().length;

    if (sibling === topCandidate || score > siblingScoreThreshold) {
      append = true;
    }

    if (children > 0) {
      siblings.contents().each(function(index, elem) {
        if (elem.name == "img") append = true;
      });
    }

    if (!append && type == 'p') {
      var linkDensity = getLinkDensity(sibling, $);
      var len = sibling.text().length;
      if (len < 3) return;

      if (len > 80 && linkDensity < 0.25) {
        append = true;
      } else if (len < 80 && linkDensity == 0 && sibling.text().search(/\.( |$)/) !== -1) {
        append = true;
      }
    }
    if (append) {
      articleContent.append(sibling);
    }
  });
  return articleContent;
}

/**
 * Traverse all Nodes and remove unlikely Candidates.
 **/

function getCandidates($, base) {

  $(trashNodes).remove();
  // Candidates Array
  var candidates = [];

  // Iterate over all Nodes in body
  $('*', 'body').each(function(index, element) {
    var node = $(this);
    if (!node) return; // Avoid Illegal Access error
    var nodeType = node.get(0).name;

    // Remove Unlikely Candidates
    var classAndID = (node.attr('class') || "") + (node.attr('id') || "");
    if (classAndID.search(regexps.unlikelyCandidatesRe) !== -1 && classAndID.search(regexps.okMaybeItsACandidateRe) == -1) {
      node.remove();
      return;
    }

    // Remove Elements that have no children and have no content
    if (nodeType == "div" && node.children().length < 1 && node.html().length < 1) {
      node.remove();
      return;
    }

    // Remove Style
    node.removeAttr('style');

    if (nodeType == "p") {
      var txt = node.text();
      // Ignore too small nodes
      if (txt.length < 25) return;

      var contentScore = 0;

      // Add a point for the paragraph itself as a base. */
      ++contentScore;

      // Add points for any commas within this paragraph */
      // support Chinese commas.
      contentScore += txt.replace('，', ',').split(',').length;

      // Add points for stops.
      contentScore += txt.split(".").length;

      // For every 100 characters in this paragraph, add another point. Up to 3 points. */
      contentScore += Math.min(Math.floor(txt.length / 100), 3);
      var parent = node.parent();

      // Initialize Parent and Grandparent
      // First initialize the parent node with contentScore / 1, then grandParentNode with contentScore / 2
      for (var i = 1; i <= 2; i++) {
        if (typeof parent.data('readabilityScore') == "undefined" && parent.get(0) != "undefined") {
          var score = initializeNode(parent);
          parent.data('readabilityScore', score + contentScore / i)
          candidates.push(parent);
        }
        parent = parent.parent();
      }
    }

    // Resolve URLs
    if(base){
        if (nodeType == "img" && typeof node.attr('href') != "undefined") {
          node.attr('src', url.resolve(base, node.attr('src')));
        }
        if (nodeType == "a" && typeof node.attr('href') != "undefined") {
          node.attr('href', url.resolve(base, node.attr('href')));
        }
    }

    // Clean the headers
    if (["h1", "h2", "h3", "h4", "h5", "h6"].indexOf(nodeType) !== -1) {
      var weight = getClassWeight(node, $);
      var density = getLinkDensity(node, $);
      if (weight < 0 || density > 0.3) {
        node.remove();
      }
    }

  });
  return candidates;
}

/**
 * Check the type of node, and get its Weight
 **/

function initializeNode(node) {
  if (typeof node.get(0) == "undefined") return 0;
  var tag = node.get(0).name;
  if (nodeTypes['mostPositive'].indexOf(tag)) return 5 + getClassWeight(node);
  if (nodeTypes['positive'].indexOf(tag)) return 3 + getClassWeight(node);
  if (nodeTypes['negative'].indexOf(tag)) return -3 + getClassWeight(node);
  if (nodeTypes['mostNegative'].indexOf(tag)) return -5 + getClassWeight(node);
}

/**
 * Node Weight is calculated based on className and ID of the node.
 **/

function getClassWeight(node) {
  if (node == null) return 0;
  var classAndID = (node.attr('class') || "") + (node.attr('id') || "");
  var weight = 0;

  if (node.get(0).name == "article") weight += 25;
  if (classAndID.search(regexps.negativeRe) !== -1) weight -= 25;
  if (classAndID.search(regexps.positiveRe) !== -1) weight += 25;

  return weight;
}

/**
 * Get Link density of this node.
 * Total length of link text in this node divided by the total text of the node.
 * Relative links are not included.
 **/

function getLinkDensity(node, $) {
  var links = node.find('a');
  var textLength = node.text().length;
  var linkLength = 0;
  links.each(function(index, elem) {
    var href = $(this).attr('href');
    if (!href || (href.length > 0 && href[0] === '#')) return;
    linkLength += $(this).text().length;
  });
  return (linkLength / textLength) || 0;
}

/**
 * Main method
 * If the first run does not succeed, try the body element;
 **/

module.exports.extract = function($, base) {
  var candidates = getCandidates($, base);
  article = getArticle(candidates, $);
  if (article.length < 1) {
    article = getArticle([$('body')], $)
  }
  return article;
}<commit_msg>BUG FIX: 1. paragraph start with blank 2. score candicate<commit_after>/*
 * Url module. Required for resolving relative paths.
 */

var url = require("url");

/*
 * Regexp from origin Arc90 Readability.
 */

var regexps = {
  unlikelyCandidatesRe: /combx|pager|comment|disqus|foot|header|menu|meta|nav|rss|shoutbox|sidebar|sponsor|share|bookmark|social|advert|leaderboard|instapaper_ignore/i,
  okMaybeItsACandidateRe: /and|article|body|column|main/i,
  positiveRe: /article|body|content|entry|hentry|page|pagination|post|text/i,
  negativeRe: /combx|comment|captcha|contact|foot|footer|footnote|link|media|meta|promo|related|scroll|shoutbox|sponsor|utility|tags|widget/i,
  divToPElementsRe: /<(a|blockquote|dl|div|img|ol|p|pre|table|ul)/i,
  replaceBrsRe: /(
]*>[ \n\r\t]*){2,}/gi,
  replaceFontsRe: /<(\/?)font[^>]*>/gi,
  trimRe: /^\s+|\s+$/g,
  normalizeRe: /\s{2,}/g,
  killBreaksRe: /(
(\s| ?)*){1,}/g,
  videoRe: /http:\/\/(www\.)?(youtube|vimeo|youku|tudou|56|yinyuetai)\.com/i
};

/**
 * Node Types and their classification
 **/

var nodeTypes = {
  'mostPositive': ['div'],
  'positive': ['pre', 'td', 'blockquote'],
  'negative': ['address', 'ol', 'ul', 'dl', 'dd', 'dt', 'li'],
  'mostNegative': ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'th']
}

/**
 * We're getting only the readable content + images, no other nodes are needed.
 **/

var trashNodes = 'meta,iframe,noscript,style,aside,object,form,script';

/**
 * Select the TopCandidate from all possible candidates
 **/

function getArticle(candidates, $) {
  var topCandidate = null;

  candidates.forEach(function(elem) {
    var linkDensity = getLinkDensity(elem, $);
    var score = elem.data('readabilityScore');
    var siblings = elem.find("*").length;

    elem.data('readabilityScore', Math.max(2, siblings) * score * (1 - linkDensity));
    if (!topCandidate || elem.data('readabilityScore') > topCandidate.data('readabilityScore')) {
      topCandidate = elem;
    }
  });
  /**
   * If we still have no top candidate, just use the body as a last resort.
   * We also have to copy the body node so it is something we can modify.
   **/
  if (topCandidate === null) {
    // With no top candidate, bail out if no body tag exists as last resort.
    if (!$('body')) return new Error("No body tag was found.");
    return $('body');
  }
  // Perhaps the topCandidate is the parent?
  if (topCandidate.children().length > 5) {
    return filterCandidates(topCandidate, topCandidate.children(), $);
  } else {
    return filterCandidates(topCandidate, topCandidate.parent().children(), $);
  }
}

/**
 * Filter TopCandidate Siblings (Children) based on their Link Density, and readabilityScore
 * Append the nodes to articleContent
 **/

function filterCandidates(topCandidate, siblings, $) {

  var articleContent = $("

");
  var siblingScoreThreshold = Math.max(10, topCandidate.data('readabilityScore') * 0.2);

  siblings.each(function(index, elem) {
    var sibling = $(this);
    var append = false;
    var type = sibling.get(0).name;
    var score = sibling.data('readabilityScore');
    var children = siblings.contents().length;

    if (sibling === topCandidate || score > siblingScoreThreshold) {
      append = true;
    }
    if (children > 0) {
      siblings.contents().each(function(index, elem) {
        if (elem.name == "img") append = true;
      });
    }

    if (!append && type == 'p') {
      var linkDensity = getLinkDensity(sibling, $);
      var len = sibling.text().length;
      if (len < 3) return;

      if (len > 80 && linkDensity < 0.25) {
        append = true;
      } else if (len < 80 && linkDensity == 0 && sibling.text().replace(regexps.trimRe, "")) {
        append = true;
      }
    }
    if (append) {
      articleContent.append(sibling);
    }
  });
  return articleContent;
}

/**
 * Traverse all Nodes and remove unlikely Candidates.
 **/

function getCandidates($, base) {

  $(trashNodes).remove();
  // Candidates Array
  var candidates = [];

  // Iterate over all Nodes in body
  $('*', 'body').each(function(index, element) {
    var node = $(this);
    if (!node) return; // Avoid Illegal Access error
    var nodeType = node.get(0).name;

    // Remove Unlikely Candidates
    var classAndID = (node.attr('class') || "") + (node.attr('id') || "");
    if (classAndID.search(regexps.unlikelyCandidatesRe) !== -1 && classAndID.search(regexps.okMaybeItsACandidateRe) == -1) {
      node.remove();
      return;
    }

    // Remove Elements that have no children and have no content
    if (nodeType == "div" && node.children().length < 1 && node.html().length < 1) {
      node.remove();
      return;
    }

    // Remove Style
    node.removeAttr('style');

    if (nodeType == "p") {
      var txt = node.text();
      // Ignore too small nodes
      if (txt.length < 25) return;

      var contentScore = 0;

      // Add a point for the paragraph itself as a base. */
      ++contentScore;

      // Add points for any commas within this paragraph */
      // support Chinese commas.
      contentScore += txt.replace('，', ',').split(',').length;

      // Add points for stops.
      contentScore += txt.split(".").length;

      // For every 100 characters in this paragraph, add another point. Up to 3 points. */
      contentScore += Math.min(Math.floor(txt.length / 100), 3);

      // Initialize Parent and Grandparent
      // First initialize the parent node with contentScore / 1, then grandParentNode with contentScore / 2
      var parent = node.parent();

      if(parent && parent.get(0) != "undefined"){
        scoreCandicate(parent, contentScore, candidates);
        var grandParent = parent.parent();
        if(grandParent && grandParent.get(0) != "undefined"){
          scoreCandicate(parent, contentScore/2, candidates);
        }
      }
    }

    // Resolve URLs
    if(base){
      if (nodeType == "img" && typeof node.attr('href') != "undefined") {
        node.attr('src', url.resolve(base, node.attr('src')));
      }
      if (nodeType == "a" && typeof node.attr('href') != "undefined") {
        node.attr('href', url.resolve(base, node.attr('href')));
      }
    }

    // Clean the headers
    if (["h1", "h2", "h3", "h4", "h5", "h6"].indexOf(nodeType) !== -1) {
      var weight = getClassWeight(node, $);
      var density = getLinkDensity(node, $);
      if (weight < 0 || density > 0.3) {
        node.remove();
      }
    }

  });
  return candidates;
}

function scoreCandicate(parent, contentScore, candidates){
  var score;
  if (typeof parent.data('readabilityScore') == "undefined") {
    score = initializeNode(parent);
    candidates.push(parent);
  }else{
    score = parent.data('readabilityScore') || 0;
  }
  parent.data('readabilityScore', score + contentScore)
}
/**
 * Check the type of node, and get its Weight
 **/

function initializeNode(node) {
  if (typeof node.get(0) == "undefined") return 0;
  var tag = node.get(0).name;
  if (nodeTypes['mostPositive'].indexOf(tag)) return 5 + getClassWeight(node);
  if (nodeTypes['positive'].indexOf(tag)) return 3 + getClassWeight(node);
  if (nodeTypes['negative'].indexOf(tag)) return -3 + getClassWeight(node);
  if (nodeTypes['mostNegative'].indexOf(tag)) return -5 + getClassWeight(node);
}

/**
 * Node Weight is calculated based on className and ID of the node.
 **/

function getClassWeight(node) {
  if (node == null) return 0;
  var classAndID = (node.attr('class') || "") + (node.attr('id') || "");
  var weight = 0;

  if (node.get(0).name == "article") weight += 25;
  if (classAndID.search(regexps.negativeRe) !== -1) weight -= 25;
  if (classAndID.search(regexps.positiveRe) !== -1) weight += 25;

  return weight;
}

/**
 * Get Link density of this node.
 * Total length of link text in this node divided by the total text of the node.
 * Relative links are not included.
 **/

function getLinkDensity(node, $) {
  var links = node.find('a');
  var textLength = node.text().length;
  var linkLength = 0;
  links.each(function(index, elem) {
    var href = $(this).attr('href');
    if (!href || (href.length > 0 && href[0] === '#')) return;
    linkLength += $(this).text().length;
  });
  return (linkLength / textLength) || 0;
}

/**
 * Main method
 * If the first run does not succeed, try the body element;
 **/

module.exports.extract = function($, base) {
  var candidates = getCandidates($, base);
  article = getArticle(candidates, $);
  if (article.length < 1) {
    article = getArticle([$('body')], $)
  }
  return article;
}<|endoftext|>


<commit_before>var RED_PIN = 16;
var GREEN_PIN = 20;
var BLUE_PIN = 21;

var Blaster = require('pi-blaster.js');

module.exports = { set: set };

function set(colorParams){
  try{
    color = colorParams.color;
    Blaster.setPwm(RED_PIN, normalizeColorValue(color.r) );
    Blaster.setPwm(GREEN_PIN,normalizeColorValue(color.g) );
    Blaster.setPwm(BLUE_PIN, normalizeColorValue(color.b) );
    if(colorParams.success){
      colorParams.success(color);
    }
  } catch(ex) {
    if(colorParams.error){
      colorParams.error(ex);
    }
  }

}

function normalizeColorValue(val){
  return (val % 256)/255;
}
<commit_msg>Change pinouts<commit_after>var RED_PIN = 17;
var GREEN_PIN = 27;
var BLUE_PIN = 22;

var Blaster = require('pi-blaster.js');

module.exports = { set: set };

function set(colorParams){
  try{
    color = colorParams.color;
    Blaster.setPwm(RED_PIN, normalizeColorValue(color.r) );
    Blaster.setPwm(GREEN_PIN,normalizeColorValue(color.g) );
    Blaster.setPwm(BLUE_PIN, normalizeColorValue(color.b) );
    if(colorParams.success){
      colorParams.success(color);
    }
  } catch(ex) {
    if(colorParams.error){
      colorParams.error(ex);
    }
  }

}

function normalizeColorValue(val){
  return (val % 256)/255;
}
<|endoftext|>


<commit_before>import { trimEnd } from 'lodash'

class CraftingGenerator {
  /**
   * Constructs a new crafting generator
   * @param input
   * @param output
   * @param tags
   * @param extras
   */
  constructor (input, output, tags, { ...extras }) {
    this.input = input || []
    this.output = output || []
    this.tags = tags || {}
    this.extras = extras || {}
  }

  /**
   * Returns the possible characters for the keys
   * @returns {[string,*]}
   */
  getPatternCharacters () {
    return [
      '#',
      ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ]
  }

  /**
   * Returns a default item object
   * @returns {{item: string}}
   */
  getItem () {
    return {
      item: ''
    }
  }

  /**
   * Returns the default for a shapeless crafting
   * @returns {object}
   */
  getShapelessDefault () {
    const { extras } = this
    let shapeless = {
      type: 'minecraft:crafting_shapeless',
      ingredients: [],
      result: {}
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        shapeless[extraKey] = extras[extraKey]
      }
    }
    return shapeless
  }

  /**
   * Returns the default for shaped crafting
   * @returns {object}
   */
  getShapedDefault () {
    const { extras } = this
    let shaped = {
      type: 'minecraft:crafting_shaped',
      pattern: [],
      key: {},
      result: {}
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        shaped[extraKey] = extras[extraKey]
      }
    }
    return shaped
  }

  /**
   * Returns the default for cooking
   * @returns {object}
   */
  getCookingDefault (tab) {
    const { extras } = this

    const type = {
      'furnace': 'minecraft:smelting',
      'blast': 'minecraft:blasting',
      'smoking': 'minecraft:smoking',
      'campfire': 'minecraft:campfire_cooking',
    }[tab]

    let cooking = {
      type,
      ingredient: {},
      result: {},
      experience: 0,
      cookingtime: 0
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        cooking[extraKey] = extras[extraKey]
      }
    }
    return cooking
  }

  /**
   * Returns the generic default type
   * @returns {object}
   */
  getGenericDefault (tab) {
    const { extras } = this

    const type = {
      'stonecutter': 'minecraft:stonecutting'
    }[tab]

    let generic = {
      type,
      ingredient: {},
      result: ''
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        generic[extraKey] = extras[extraKey]
      }
    }
    return generic
  }

  /**
   * Returns a character for an item
   * @param item
   * @param keyMap
   * @returns {string|boolean}
   */
  dinnerboneChallenge (item, keyMap) {
    // dinnerbone actually said for an 'ascii to item chart', http://i.thedestruc7i0n.ca/b4p518.png
    // while I probs don't have enough time for that, this should do... pls dinnerbone
    const stickTypes = ['minecraft:end_rod', 'minecraft:blaze_rod', 'minecraft:stick']
    const slabCheck = (item) => item.indexOf('slab') !== -1
    const ingotCheck = (item) => item.indexOf('ingot') !== -1

    // remove minecraft
    let name = item.replace('minecraft:', '')

    if (stickTypes.indexOf(item) !== -1) {
      return '/'
    }

    if (slabCheck(item)) {
      return '_'
    }

    if (ingotCheck(item)) {
      return name[0].toLowerCase()
    }

    // I need to stay with the original eh?
    if (Object.keys(keyMap).length === 0) {
      return '#'
    }

    if (name[0]) return name[0].toUpperCase()
    return false
  }

  /**
   * Returns the item based on the item provided
   * @param ingredient
   * @param rest
   * @returns {object|array}
   */
  getItemType (ingredient, ...rest) {
    const itemType = this.getItem()
    if (ingredient.ingredient_type === 'item') {
      return {
        ...itemType,
        item: ingredient.id,
        item_h: ingredient.getComparableString(),
        ...ingredient.customData,
        ...rest
      }
    } else if (ingredient.ingredient_type === 'tag') {
      const tag = this.tags[ingredient.tag]
      if (tag) {
        // store it as the ingredient for further checking...
        // handle the conversion to the format later
        return {
          tag: ingredient
        }
      }
    }
  }

  /**
   * Handles the tags
   * @param tag
   * @returns {*}
   */
  handleTags (tag) {
    if (tag.asTag) {
      return {
        tag: `${tag.namespace}:${tag.name}`
      }
    } else {
      // create a list of items instead
      return tag.items.map((item) => ({ item: item.id }))
    }
  }

  /**
   * Returns a shapeless crafting of the input and output provided
   * @returns {object}
   */
  shapeless () {
    // clone element
    const { input, output } = this

    let shape = { ...this.getShapelessDefault() }

    // go over each ingredient
    for (let ingredient of input) {
      // only if populated
      if (ingredient.isPopulated()) {
        shape.ingredients.push(
          this.getItemType(ingredient)
        )
      }
    }

    // now handle tags...
    shape.ingredients = shape.ingredients.map((ingredient) => {
      if (ingredient.tag) {
        const tag = this.tags[ingredient.tag.tag]
        return this.handleTags(tag)
      }
      return ingredient
    })

    if (output.isPopulated()) {
      const itemType = this.getItemType(output)
      if (itemType.item_h) delete itemType.item_h
      shape.result = {
        ...itemType,
        count: output.count
      }
    }

    return shape
  }

  /**
   * Returns a shaped crafting of the input and output provided
   * @param removeEmptySpace {boolean}
   * @returns {object}
   */
  shaped (removeEmptySpace = false) {
    // clone element
    const { input, output } = this
    const patternCharacters = this.getPatternCharacters()

    let shape = { ...this.getShapedDefault() }
    // key for the characters
    let keyMap = {}

    let keysString = ''

    const byItem = (item) => {
      let keys = Object.keys(keyMap)
      for (let key of keys) {
        let mapping = keyMap[key]
        if (item.ingredient_type === 'tag') {
          if (mapping.tag) {
            // check that the tag id is the same
            if (mapping.tag.tag === item.tag) {
              return key
            }
          }
        }
        if (mapping.item === item.id && mapping.item_h === item.getComparableString()) {
          return key
        }
      }

      return false
    }

    const keyExists = (key) => Object.keys(keyMap).indexOf(key) !== -1
    const getKey = (ingredient) => {
      let name = ingredient.getComparableString()
      // name from tag name rather than item id
      if (ingredient.ingredient_type === 'tag') {
        const tag = this.tags[ingredient.tag]
        name = tag.name
      }
      let key = this.dinnerboneChallenge(name, keyMap)

      // choose a key if the special ones don't work
      let flag = true
      while (flag) {
        if (keyExists(key) || !key) {
          key = patternCharacters[Math.floor(patternCharacters.length * Math.random())]
        } else {
          flag = false
        }
      }

      return key
    }

    for (let ingredient of input) {
      if (ingredient.isPopulated()) {
        let key = byItem(ingredient)

        if (key) {
          keysString += key
        } else {
          let key = getKey(ingredient)
          keyMap[key] = this.getItemType(ingredient)
          // add the key to the string
          keysString += key
        }
      } else {
        // add a space
        keysString += ' '
      }
    }

    // handle tags now
    keyMap = Object.keys(keyMap).reduce((acc, key) => {
      const value = keyMap[key]
      if (value.tag) {
        const tag = this.tags[value.tag.tag]
        acc[key] = this.handleTags(tag)
      } else {
        if (value.item_h) delete value.item_h
        acc[key] = value
      }
      return acc
    }, {})
    // append the keymap
    shape.key = keyMap

    // split into groups of three
    let splitKeys = keysString.match(/.{1,3}/g)

    // init lines
    let lines = [...splitKeys]
    // check if needed to remove space
    if (removeEmptySpace) {
      // if removing empty space, remove the end
      // trim the end
      let noTrailing = splitKeys.map((line) => trimEnd(line))

      // get longest string from the trimmed strings
      let longest = Math.max(...noTrailing.map(({ length }) => length))

      // trim until longest
      let trimmed = splitKeys.map((line) => {
        return line.substring(0, longest)
      })

      // remove empty line
      lines = trimmed.filter((line) => /\S/.test(line))
      // get amount of leading whitespace
      let leadingWhitespace = lines.map((line) => line.search(/\S/))

      // get shortest amount
      let leadingWhitespaceAmount = Math.min(...leadingWhitespace)

      // trim the start
      lines = lines.map((line) => line.substring(leadingWhitespaceAmount))
    }
    // append mapping
    shape.pattern = lines

    // result
    if (output.isPopulated()) {
      const itemType = this.getItemType(output)
      if (itemType.item_h) delete itemType.item_h
      shape.result = {
        ...itemType,
        count: output.count
      }
    }

    return shape
  }

  /**
   * Returns a cooking type crafting of the input provided
   * @param time
   * @param experience
   * @returns {object}
   */
  cooking (time = 0, experience = 0, tab) {
    const { input, output } = this

    let shape = { ...this.getCookingDefault(tab) }

    // add the ingredient
    let ingredient = input

    // only if populated
    if (ingredient.isPopulated()) {
      shape.ingredient = this.getItemType(ingredient)

      // handle tags...
      if (shape.ingredient.tag) {
        const tag = this.tags[shape.ingredient.tag.tag]
        shape.ingredient = this.handleTags(tag)
      }
    }

    if (output.isPopulated()) {
      shape.result = output.id
    }

    shape.cookingtime = time || 0
    shape.experience = experience || 0

    return shape
  }

  /**
   * Returns a generic type crafting of the input provided
   * @returns {object}
   */
  generic (type) {
    const { input, output } = this

    let shape = { ...this.getGenericDefault(type) }

    // add the ingredient
    let ingredient = input

    // only if populated
    if (ingredient.isPopulated()) {
      shape.ingredient = this.getItemType(ingredient)

      // handle tags...
      if (shape.ingredient.tag) {
        const tag = this.tags[shape.ingredient.tag.tag]
        shape.ingredient = this.handleTags(tag)
      }
    }

    if (output.isPopulated()) {
      shape.result = output.id
    }

    shape.count = output.count

    return shape
  }
}

export default CraftingGenerator
<commit_msg>Remove the comparable from output<commit_after>import { trimEnd } from 'lodash'

class CraftingGenerator {
  /**
   * Constructs a new crafting generator
   * @param input
   * @param output
   * @param tags
   * @param extras
   */
  constructor (input, output, tags, { ...extras }) {
    this.input = input || []
    this.output = output || []
    this.tags = tags || {}
    this.extras = extras || {}
  }

  /**
   * Returns the possible characters for the keys
   * @returns {[string,*]}
   */
  getPatternCharacters () {
    return [
      '#',
      ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ]
  }

  /**
   * Returns a default item object
   * @returns {{item: string}}
   */
  getItem () {
    return {
      item: ''
    }
  }

  /**
   * Returns the default for a shapeless crafting
   * @returns {object}
   */
  getShapelessDefault () {
    const { extras } = this
    let shapeless = {
      type: 'minecraft:crafting_shapeless',
      ingredients: [],
      result: {}
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        shapeless[extraKey] = extras[extraKey]
      }
    }
    return shapeless
  }

  /**
   * Returns the default for shaped crafting
   * @returns {object}
   */
  getShapedDefault () {
    const { extras } = this
    let shaped = {
      type: 'minecraft:crafting_shaped',
      pattern: [],
      key: {},
      result: {}
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        shaped[extraKey] = extras[extraKey]
      }
    }
    return shaped
  }

  /**
   * Returns the default for cooking
   * @returns {object}
   */
  getCookingDefault (tab) {
    const { extras } = this

    const type = {
      'furnace': 'minecraft:smelting',
      'blast': 'minecraft:blasting',
      'smoking': 'minecraft:smoking',
      'campfire': 'minecraft:campfire_cooking',
    }[tab]

    let cooking = {
      type,
      ingredient: {},
      result: {},
      experience: 0,
      cookingtime: 0
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        cooking[extraKey] = extras[extraKey]
      }
    }
    return cooking
  }

  /**
   * Returns the generic default type
   * @returns {object}
   */
  getGenericDefault (tab) {
    const { extras } = this

    const type = {
      'stonecutter': 'minecraft:stonecutting'
    }[tab]

    let generic = {
      type,
      ingredient: {},
      result: ''
    }
    // go through the extras and add to the object
    for (let extraKey of Object.keys(extras)) {
      let extra = extras[extraKey]
      if (extra) {
        generic[extraKey] = extras[extraKey]
      }
    }
    return generic
  }

  /**
   * Returns a character for an item
   * @param item
   * @param keyMap
   * @returns {string|boolean}
   */
  dinnerboneChallenge (item, keyMap) {
    // dinnerbone actually said for an 'ascii to item chart', http://i.thedestruc7i0n.ca/b4p518.png
    // while I probs don't have enough time for that, this should do... pls dinnerbone
    const stickTypes = ['minecraft:end_rod', 'minecraft:blaze_rod', 'minecraft:stick']
    const slabCheck = (item) => item.indexOf('slab') !== -1
    const ingotCheck = (item) => item.indexOf('ingot') !== -1

    // remove minecraft
    let name = item.replace('minecraft:', '')

    if (stickTypes.indexOf(item) !== -1) {
      return '/'
    }

    if (slabCheck(item)) {
      return '_'
    }

    if (ingotCheck(item)) {
      return name[0].toLowerCase()
    }

    // I need to stay with the original eh?
    if (Object.keys(keyMap).length === 0) {
      return '#'
    }

    if (name[0]) return name[0].toUpperCase()
    return false
  }

  /**
   * Returns the item based on the item provided
   * @param ingredient
   * @param comparable
   * @param rest
   * @returns {object|array}
   */
  getItemType (ingredient, comparable = true, ...rest) {
    const itemType = this.getItem()
    if (ingredient.ingredient_type === 'item') {
      return {
        ...itemType,
        item: ingredient.id,
        ...(comparable && { item_h: ingredient.getComparableString() }),
        ...ingredient.customData,
        ...rest
      }
    } else if (ingredient.ingredient_type === 'tag') {
      const tag = this.tags[ingredient.tag]
      if (tag) {
        // store it as the ingredient for further checking...
        // handle the conversion to the format later
        return {
          tag: ingredient
        }
      }
    }
  }

  /**
   * Handles the tags
   * @param tag
   * @returns {*}
   */
  handleTags (tag) {
    if (tag.asTag) {
      return {
        tag: `${tag.namespace}:${tag.name}`
      }
    } else {
      // create a list of items instead
      return tag.items.map((item) => ({ item: item.id }))
    }
  }

  /**
   * Returns a shapeless crafting of the input and output provided
   * @returns {object}
   */
  shapeless () {
    // clone element
    const { input, output } = this

    let shape = { ...this.getShapelessDefault() }

    // go over each ingredient
    for (let ingredient of input) {
      // only if populated
      if (ingredient.isPopulated()) {
        const itemType = this.getItemType(ingredient, false)
        shape.ingredients.push(
          itemType
        )
      }
    }

    // now handle tags...
    shape.ingredients = shape.ingredients.map((ingredient) => {
      if (ingredient.tag) {
        const tag = this.tags[ingredient.tag.tag]
        return this.handleTags(tag)
      }
      return ingredient
    })

    if (output.isPopulated()) {
      const itemType = this.getItemType(output, false)
      shape.result = {
        ...itemType,
        count: output.count
      }
    }

    return shape
  }

  /**
   * Returns a shaped crafting of the input and output provided
   * @param removeEmptySpace {boolean}
   * @returns {object}
   */
  shaped (removeEmptySpace = false) {
    // clone element
    const { input, output } = this
    const patternCharacters = this.getPatternCharacters()

    let shape = { ...this.getShapedDefault() }
    // key for the characters
    let keyMap = {}

    let keysString = ''

    const byItem = (item) => {
      let keys = Object.keys(keyMap)
      for (let key of keys) {
        let mapping = keyMap[key]
        if (item.ingredient_type === 'tag') {
          if (mapping.tag) {
            // check that the tag id is the same
            if (mapping.tag.tag === item.tag) {
              return key
            }
          }
        }
        if (mapping.item === item.id && mapping.item_h === item.getComparableString()) {
          return key
        }
      }

      return false
    }

    const keyExists = (key) => Object.keys(keyMap).indexOf(key) !== -1
    const getKey = (ingredient) => {
      let name = ingredient.getComparableString()
      // name from tag name rather than item id
      if (ingredient.ingredient_type === 'tag') {
        const tag = this.tags[ingredient.tag]
        name = tag.name
      }
      let key = this.dinnerboneChallenge(name, keyMap)

      // choose a key if the special ones don't work
      let flag = true
      while (flag) {
        if (keyExists(key) || !key) {
          key = patternCharacters[Math.floor(patternCharacters.length * Math.random())]
        } else {
          flag = false
        }
      }

      return key
    }

    for (let ingredient of input) {
      if (ingredient.isPopulated()) {
        let key = byItem(ingredient)

        if (key) {
          keysString += key
        } else {
          let key = getKey(ingredient)
          keyMap[key] = this.getItemType(ingredient)
          // add the key to the string
          keysString += key
        }
      } else {
        // add a space
        keysString += ' '
      }
    }

    // handle tags now
    keyMap = Object.keys(keyMap).reduce((acc, key) => {
      const value = keyMap[key]
      if (value.tag) {
        const tag = this.tags[value.tag.tag]
        acc[key] = this.handleTags(tag)
      } else {
        if (value.item_h) delete value.item_h
        acc[key] = value
      }
      return acc
    }, {})
    // append the keymap
    shape.key = keyMap

    // split into groups of three
    let splitKeys = keysString.match(/.{1,3}/g)

    // init lines
    let lines = [...splitKeys]
    // check if needed to remove space
    if (removeEmptySpace) {
      // if removing empty space, remove the end
      // trim the end
      let noTrailing = splitKeys.map((line) => trimEnd(line))

      // get longest string from the trimmed strings
      let longest = Math.max(...noTrailing.map(({ length }) => length))

      // trim until longest
      let trimmed = splitKeys.map((line) => {
        return line.substring(0, longest)
      })

      // remove empty line
      lines = trimmed.filter((line) => /\S/.test(line))
      // get amount of leading whitespace
      let leadingWhitespace = lines.map((line) => line.search(/\S/))

      // get shortest amount
      let leadingWhitespaceAmount = Math.min(...leadingWhitespace)

      // trim the start
      lines = lines.map((line) => line.substring(leadingWhitespaceAmount))
    }
    // append mapping
    shape.pattern = lines

    // result
    if (output.isPopulated()) {
      const itemType = this.getItemType(output, false)
      shape.result = {
        ...itemType,
        count: output.count
      }
    }

    return shape
  }

  /**
   * Returns a cooking type crafting of the input provided
   * @param time
   * @param experience
   * @returns {object}
   */
  cooking (time = 0, experience = 0, tab) {
    const { input, output } = this

    let shape = { ...this.getCookingDefault(tab) }

    // add the ingredient
    let ingredient = input

    // only if populated
    if (ingredient.isPopulated()) {
      shape.ingredient = this.getItemType(ingredient, false)

      // handle tags...
      if (shape.ingredient.tag) {
        const tag = this.tags[shape.ingredient.tag.tag]
        shape.ingredient = this.handleTags(tag)
      }
    }

    if (output.isPopulated()) {
      shape.result = output.id
    }

    shape.cookingtime = time || 0
    shape.experience = experience || 0

    return shape
  }

  /**
   * Returns a generic type crafting of the input provided
   * @returns {object}
   */
  generic (type) {
    const { input, output } = this

    let shape = { ...this.getGenericDefault(type) }

    // add the ingredient
    let ingredient = input

    // only if populated
    if (ingredient.isPopulated()) {
      shape.ingredient = this.getItemType(ingredient, false)

      // handle tags...
      if (shape.ingredient.tag) {
        const tag = this.tags[shape.ingredient.tag.tag]
        shape.ingredient = this.handleTags(tag)
      }
    }

    if (output.isPopulated()) {
      shape.result = output.id
    }

    shape.count = output.count

    return shape
  }
}

export default CraftingGenerator
<|endoftext|>


<commit_before>var canvas = require('canvas');
var persist = require("persist");
var type = persist.type;
var models = require('../models');
var utils = require('./api.utils');
var db = require('./api.db');
var path = require('path');

exports.get = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.get failed")
      throw err;
    }

    var options = req.originalUrl.replace("/api/get", "").split("/");
    var tagsFilter = null;

    var i = 0;
    while(options.length > 0) {
      var option = options.shift();
      if (option == "tag") {
        tagsFilter = unescape(options.shift()).split("+");
      }
    }

    //limit(5) - paging
    models.Image.using(connection).orderBy('id', 'desc').include("tags").all(function(err, imagesData) {
      var images = [];
      var totalFilteredOut = 0;
      imagesData = imagesData || [];
      imagesData.forEach(function(imageData) {
        var image = {
          id: imageData.id,
          title: imageData.title,
          referer: imageData.referer,
          originalUrl : imageData.originalUrl,
          cachedUrl : imageData.cachedUrl,
          thumbUrl : imageData.thumbUrl,
          ratio : imageData.ratio,
          tags: []
        }
        var hasTags = 0;
        var filteredOut = false;
        imageData.tags.forEach(function(tagData) {
          if (tagsFilter && (tagsFilter.indexOf(tagData.name) !== -1)) {
            hasTags++;
          }
          image.tags.push(tagData.name);
        });

        if (tagsFilter && hasTags != tagsFilter.length) {
          filteredOut = true;
          totalFilteredOut++;
        }
        else {
          images.push(image);
        }

        if (images.length + totalFilteredOut == imagesData.length) {
            res.send(JSON.stringify(images));
        }
      });
    });
    connection.close();
  });
};

exports.post = function(req, res) {
  var callback = req.query.callback;

  var imageData = {
    title: req.query.title || "Unknown",
    referer: req.query.referer,
    originalUrl : req.query.img,
    cachedUrl : "",
    thumbUrl : "",
    ratio : 1,
    tags: req.query.tags.split(" ")
  }

  console.log("Downloading...", imageData);

  utils.downloadAndCreateThumb(imageData.originalUrl, function(err, cachedUrl, thumbUrl, ratio) {
    imageData.cachedUrl = cachedUrl;
    imageData.thumbUrl = thumbUrl;
    imageData.ratio = ratio;

    console.log("Downloaded...", imageData);

    res.setHeader("Content-Type", "text/javascript");
    var id = -1;
    if (err != null) {
      var body = "{0}({1},{2})".format(callback, err, id);
      res.send(body);
    }
    else {
      db.saveImage(imageData, function(err) {
        var body = "{0}({1},{2})".format(callback, err || "null", id);
        res.send(body);
      })
    }
  })
}

exports.update = function(req, res) {
  var imageId = req.query.id;

  persist.connect(function(err, connection) {
    if(err) { throw err; }

    if (req.query.title) {
      models.Image.update(connection, Number(imageId), { title: req.query.title}, function(err) {
        if (err) res.send(err);
        else res.send("OK");
      });
    }
    if (req.query.referer) {
      models.Image.update(connection, Number(imageId), { referer: req.query.referer}, function(err) {
        if (err) res.send(err);
        else res.send("OK");
      });
    }
    else if (req.query.tags) {
      var updatedTags = req.query.tags.split(",");
      console.log("updatedTags", updatedTags);
      db.findTags(connection, updatedTags, function(tags, newTags) {
        function saveUpdatedImage() {
          models.Image.using(connection).where('id = ?', imageId).all(function(err, imagesData) {
            console.log("tags.length", tags.length, newTags.length);
            imagesData[0].tags = tags;
            imagesData[0].save(connection, function(err) {
              if (err) res.send(err);
              else res.send("OK " + JSON.stringify(newTags));
            });
          });
        }

        if (newTags) {
          connection.save(newTags, saveUpdatedImage);
        }
        else {
          saveUpdatedImage();
        }

      })
    }

    connection.close();
  });
}

exports.tags = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.tags failed");
      throw err;
    }

    var tagsQuery = "SELECT name, COUNT(tag_id) as count FROM images_tags it JOIN tags t ON it.tag_id = t.id GROUP BY tag_id ORDER BY COUNT(tag_id) DESC";

    connection.runSqlAll(tagsQuery, [], function(err, tags) {
      res.send(JSON.stringify(tags));
    });

    connection.close();
  });
}

exports.latest = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.latest failed");
      throw err;
    }

    var latestQuery = "SELECT thumb_url, ratio FROM images JOIN images_tags ON images.id = images_tags.image_id JOIN tags ON images_tags.tag_id = tags.id WHERE tags.name = ? ORDER BY images.id DESC LIMIT 5";

    connection.runSqlAll(latestQuery, [req.query.tag], function(err, images) {
      res.send(JSON.stringify(images));
    });

    connection.close();
  });
}

exports.delete = function(req, res) {
  db.delete(req.query.imageId, function(err, chachedImageFile, thumbImageFile) {
    utils.deleteImageFile(chachedImageFile);
    utils.deleteImageFile(thumbImageFile);
    res.send(JSON.stringify({ err: err }));
  })
}

exports.upload = function(req, res) {
  var file = req.files.file;

  var imageData = {
    title: file.name,
    referer: "",
    originalUrl : "",
    cachedUrl : "",
    thumbUrl : "",
    ratio : 1,
    tags: null
  }

  utils.copyAndCreateThumb(file, function(err, cachedUrl, thumbUrl, ratio) {
    imageData.cachedUrl = cachedUrl;
    imageData.thumbUrl = thumbUrl;
    imageData.ratio = ratio;

    console.log("Downloaded...", imageData);

    res.setHeader("Content-Type", "text/javascript");
    var id = -1;
    if (err != null) {
      var body = "{0}({1},{2})".format(callback, err, id);
      res.send(body);
    }
    else {
      db.saveImage(imageData, function(err, imageId) {
        imageData.id = imageId;
        res.send(JSON.stringify(imageData));
      })
    }
  })

  //setTimeout(function() {
  //  res.contentType('application/json');
  //  res.send({name:file.name, bla:file.path, rnd: Math.random()});
  //  res.end();
  //}, Math.floor(Math.random() * 2000));
}
<commit_msg>Removed unused canvas import<commit_after>var persist = require("persist");
var type = persist.type;
var models = require('../models');
var utils = require('./api.utils');
var db = require('./api.db');
var path = require('path');

exports.get = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.get failed")
      throw err;
    }

    var options = req.originalUrl.replace("/api/get", "").split("/");
    var tagsFilter = null;

    var i = 0;
    while(options.length > 0) {
      var option = options.shift();
      if (option == "tag") {
        tagsFilter = unescape(options.shift()).split("+");
      }
    }

    //limit(5) - paging
    models.Image.using(connection).orderBy('id', 'desc').include("tags").all(function(err, imagesData) {
      var images = [];
      var totalFilteredOut = 0;
      imagesData = imagesData || [];
      imagesData.forEach(function(imageData) {
        var image = {
          id: imageData.id,
          title: imageData.title,
          referer: imageData.referer,
          originalUrl : imageData.originalUrl,
          cachedUrl : imageData.cachedUrl,
          thumbUrl : imageData.thumbUrl,
          ratio : imageData.ratio,
          tags: []
        }
        var hasTags = 0;
        var filteredOut = false;
        imageData.tags.forEach(function(tagData) {
          if (tagsFilter && (tagsFilter.indexOf(tagData.name) !== -1)) {
            hasTags++;
          }
          image.tags.push(tagData.name);
        });

        if (tagsFilter && hasTags != tagsFilter.length) {
          filteredOut = true;
          totalFilteredOut++;
        }
        else {
          images.push(image);
        }

        if (images.length + totalFilteredOut == imagesData.length) {
            res.send(JSON.stringify(images));
        }
      });
    });
    connection.close();
  });
};

exports.post = function(req, res) {
  var callback = req.query.callback;

  var imageData = {
    title: req.query.title || "Unknown",
    referer: req.query.referer,
    originalUrl : req.query.img,
    cachedUrl : "",
    thumbUrl : "",
    ratio : 1,
    tags: req.query.tags.split(" ")
  }

  console.log("Downloading...", imageData);

  utils.downloadAndCreateThumb(imageData.originalUrl, function(err, cachedUrl, thumbUrl, ratio) {
    imageData.cachedUrl = cachedUrl;
    imageData.thumbUrl = thumbUrl;
    imageData.ratio = ratio;

    console.log("Downloaded...", imageData);

    res.setHeader("Content-Type", "text/javascript");
    var id = -1;
    if (err != null) {
      var body = "{0}({1},{2})".format(callback, err, id);
      res.send(body);
    }
    else {
      db.saveImage(imageData, function(err) {
        var body = "{0}({1},{2})".format(callback, err || "null", id);
        res.send(body);
      })
    }
  })
}

exports.update = function(req, res) {
  var imageId = req.query.id;

  persist.connect(function(err, connection) {
    if(err) { throw err; }

    if (req.query.title) {
      models.Image.update(connection, Number(imageId), { title: req.query.title}, function(err) {
        if (err) res.send(err);
        else res.send("OK");
      });
    }
    if (req.query.referer) {
      models.Image.update(connection, Number(imageId), { referer: req.query.referer}, function(err) {
        if (err) res.send(err);
        else res.send("OK");
      });
    }
    else if (req.query.tags) {
      var updatedTags = req.query.tags.split(",");
      console.log("updatedTags", updatedTags);
      db.findTags(connection, updatedTags, function(tags, newTags) {
        function saveUpdatedImage() {
          models.Image.using(connection).where('id = ?', imageId).all(function(err, imagesData) {
            console.log("tags.length", tags.length, newTags.length);
            imagesData[0].tags = tags;
            imagesData[0].save(connection, function(err) {
              if (err) res.send(err);
              else res.send("OK " + JSON.stringify(newTags));
            });
          });
        }

        if (newTags) {
          connection.save(newTags, saveUpdatedImage);
        }
        else {
          saveUpdatedImage();
        }

      })
    }

    connection.close();
  });
}

exports.tags = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.tags failed");
      throw err;
    }

    var tagsQuery = "SELECT name, COUNT(tag_id) as count FROM images_tags it JOIN tags t ON it.tag_id = t.id GROUP BY tag_id ORDER BY COUNT(tag_id) DESC";

    connection.runSqlAll(tagsQuery, [], function(err, tags) {
      res.send(JSON.stringify(tags));
    });

    connection.close();
  });
}

exports.latest = function(req, res) {
  persist.connect(function(err, connection) {
    if(err) {
      console.log("api.latest failed");
      throw err;
    }

    var latestQuery = "SELECT thumb_url, ratio FROM images JOIN images_tags ON images.id = images_tags.image_id JOIN tags ON images_tags.tag_id = tags.id WHERE tags.name = ? ORDER BY images.id DESC LIMIT 5";

    connection.runSqlAll(latestQuery, [req.query.tag], function(err, images) {
      res.send(JSON.stringify(images));
    });

    connection.close();
  });
}

exports.delete = function(req, res) {
  db.delete(req.query.imageId, function(err, chachedImageFile, thumbImageFile) {
    utils.deleteImageFile(chachedImageFile);
    utils.deleteImageFile(thumbImageFile);
    res.send(JSON.stringify({ err: err }));
  })
}

exports.upload = function(req, res) {
  var file = req.files.file;

  var imageData = {
    title: file.name,
    referer: "",
    originalUrl : "",
    cachedUrl : "",
    thumbUrl : "",
    ratio : 1,
    tags: null
  }

  utils.copyAndCreateThumb(file, function(err, cachedUrl, thumbUrl, ratio) {
    imageData.cachedUrl = cachedUrl;
    imageData.thumbUrl = thumbUrl;
    imageData.ratio = ratio;

    console.log("Downloaded...", imageData);

    res.setHeader("Content-Type", "text/javascript");
    var id = -1;
    if (err != null) {
      var body = "{0}({1},{2})".format(callback, err, id);
      res.send(body);
    }
    else {
      db.saveImage(imageData, function(err, imageId) {
        imageData.id = imageId;
        res.send(JSON.stringify(imageData));
      })
    }
  })

  //setTimeout(function() {
  //  res.contentType('application/json');
  //  res.send({name:file.name, bla:file.path, rnd: Math.random()});
  //  res.end();
  //}, Math.floor(Math.random() * 2000));
}
<|endoftext|>


<commit_before>require('dotenv').config();
const debug = require('debug')('chase:user-adaptor');
const AWS = require('aws-sdk');

const Pocket = require('./PocketAPI');

const s3 = new AWS.S3();

function successResponseBuilder(bodyObj) {
  return {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify(bodyObj),
  };
}

function errorResponseBuilder(error) {
  debug(error);
  const res = error.response || { headers: {} };
  const response = {
    statusCode: res.status,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify({
      message: res.statusText,
    }),
  };
  return response;
}

module.exports.register = (event, context, callback) => {
  const params = JSON.parse(event.body);
  debug('[register]>>>>', params);
  if (!params.accesstoken.match(/^[a-z0-9-]+$/)) {
    errorResponseBuilder('Invalid access token.');
  }
  const obj = {
    Bucket: process.env.BUCKET,
    Key: `accesstokens/${params.accesstoken}.json`,
    Body: JSON.stringify('', null, 2),
  };
  s3.putObject(obj, (err, data) => {
    if (err) {
      callback(null, errorResponseBuilder(err));
    } else {
      callback(null, successResponseBuilder(data));
    }
  });
};

function extractAccesstokens() {
  return new Promise((rv, rj) => {
    const opts = {
      Bucket: process.env.BUCKET,
      Prefix: 'accesstokens/',
      MaxKeys: 10,
    };
    s3.listObjectsV2(opts, (err, data) => {
      if (err) {
        rj(err.stack);
      } else {
        const files = data.Contents.filter(d => d.Key.match(/\.json$/));
        const tokens = files.map(d => d.Key.match(/^accesstokens\/([a-z0-9-]+)\.json$/)[1]);
        rv(tokens);
      }
    });
  });
}

function getPocketEntries(at) {
  const ck = process.env.POCKET_CONSUMER_KEY;
  const params = { count: 3 };
  return Pocket.get(ck, at, params).then((d) => {
    debug(`GET RESULT of ${at} IS:`, Object.keys(d.list).length);
    return d;
  }).catch((err) => {
    debug('(Skipped) Failed to get with Access Token:', at);
    debug(err);
  });
}

module.exports.prepare = (event, context, callback) => {
  debug('[prepare]>>>>');
  extractAccesstokens().then((tokens) => {
    debug(tokens);
    Promise.all(tokens.map(at => getPocketEntries(at)));
  })
    .then(() => callback(null, successResponseBuilder()))
    .catch(err => callback(null, errorResponseBuilder(err)));
};
<commit_msg>:construction: userprepare<commit_after>require('dotenv').config();
const debug = require('debug')('chase:user-adaptor');
const AWS = require('aws-sdk');

const Pocket = require('./PocketAPI');
const LibraAdaptor = require('./LibraAdaptor');

const s3 = new AWS.S3();

function successResponseBuilder(bodyObj) {
  return {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify(bodyObj),
  };
}

function errorResponseBuilder(error) {
  debug(error);
  const res = error.response || { headers: {} };
  const response = {
    statusCode: res.status,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify({
      message: res.statusText,
    }),
  };
  return response;
}

module.exports.register = (event, context, callback) => {
  const params = JSON.parse(event.body);
  debug('[register]>>>>', params);
  if (!params.accesstoken.match(/^[a-z0-9-]+$/)) {
    errorResponseBuilder('Invalid access token.');
  }
  const obj = {
    Bucket: process.env.BUCKET,
    Key: `accesstokens/${params.accesstoken}.json`,
    Body: JSON.stringify('', null, 2),
  };
  s3.putObject(obj, (err, data) => {
    if (err) {
      callback(null, errorResponseBuilder(err));
    } else {
      callback(null, successResponseBuilder(data));
    }
  });
};

function extractAccesstokens() {
  return new Promise((rv, rj) => {
    const opts = {
      Bucket: process.env.BUCKET,
      Prefix: 'accesstokens/',
      MaxKeys: 10,
    };
    s3.listObjectsV2(opts, (err, data) => {
      if (err) {
        rj(err.stack);
      } else {
        const files = data.Contents.filter(d => d.Key.match(/\.json$/));
        const tokens = files.map(d => d.Key.match(/^accesstokens\/([a-z0-9-]+)\.json$/)[1]);
        rv(tokens);
      }
    });
  });
}

function getPocketEntrySet(at) {
  const ck = process.env.POCKET_CONSUMER_KEY;
  const params = { count: 3, detailType: 'complete' };
  return Pocket.get(ck, at, params).then((d) => {
    debug(`GET RESULT of ${at} IS:`, Object.keys(d.list).length);
    return d.list;
  }).catch((err) => {
    debug('(Skipped) Failed to get with Access Token:', at);
    debug(err);
  });
}

function moldEntry(pocketRawItem) {
  const m = pocketRawItem;
  const url = m.resolved_url ? m.resolved_url : m.given_url;
  const is = (m.has_image === '1') ? m.image.src : '';
  return { pocket_id: m.item_id, url, image_suggested: is };
}

module.exports.prepare = (event, context, callback) => {
  debug('[prepare]>>>>');
  extractAccesstokens().then((tokens) => {
    debug(tokens);
    Promise.all(tokens.map(at => getPocketEntrySet(at).then((set) => {
      const items = Object.keys(set).map(id => moldEntry(set[id]));
      return items;
    }).then((items) => {
      Promise.all(items.map((params) => {
        debug(params);
        return LibraAdaptor.libraInfo(params);
      }));
    })));
  })
    .then(() => callback(null, successResponseBuilder()))
    .catch(err => callback(null, errorResponseBuilder(err)));
};
<|endoftext|>