<commit_before>/*!
*  JqueryAsynchImageLoader (JAIL) : plugin for jQuery
*
* Developed by
* Sebastiano Armeli-Battana (@sebarmeli) - http://sebarmeli.com | http://blog.sebarmeli.com
*
* Licensed under MIT
*/
/* Copyright (c) 2010 Sebastiano Armeli-Battana (http://sebarmeli.com)

	Permission is hereby granted, free of charge, to any person obtaining
	a copy of this software and associated documentation files (the
	"Software"), to deal in the Software without restriction, including
	without limitation the rights to use, copy, modify, merge, publish,
	distribute, sublicense, and/or sell copies of the Software, and to
	permit persons to whom the Software is furnished to do so, subject to
	the following conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* JAIL helps loading images asynchronously and it can be used to make your page load faster.
* Selected images will be downloaded after the document is ready not blocking the page
* to render other elements. Images can be loaded after an event is triggered (like clicking
* on a link, mouseovering on some elements, scrolling up/down) or after some delay or simply the
* visible images will be loaded.
*
* First of all, this plugin requires you to make some HTML changes.
* E.g.
*
*
* You can define a noscript block in order to respect the principles of progressive
* enhancemnt
* E.g.
*
*
*
*
* You can call the function in this way
* E.g.
*	$(function(){
*		$('img.lazy').asynchImageLoader();
*	});
*
* You can also have different configurations:
*
* - timeout : number of msec after that the images will be loaded - Default: 10ms
* - effect : jQuery effect that makes the images display (Eg "fadeIn") - Default: "show"
* - speed :  string or number determining how long the animation will run  - Default: 400
* - selector : selector that you need to bind the trigger event - Default: NULL
* - event : event that triggers the image to load - Default: "load". You can choose "click", "mouseover", "scroll"
* - callback : function that will be called after the images are loaded	- Default: ""
* - placeholder : location of an image (such a loader) you want to display while waiting for the images to be loaded - Default: ""
* - delay : number of milliseconds to wait after the trigger event before loading images. Makes scrolling more performant - Default: 500 for 'scroll' events, 0 for everything else
*
*
* Tested with jQuery 1.3.2+ on FF 2/3, Opera 10+, Safari 4+, Chrome on Mac and IE 6/7/8 on Win.
*
* @link http://github.com/sebarmeli/JAIL
* @author Sebastiano Armeli-Battana
* @date 21/1/2011
* @version 0.3
*
*/

/*globals window,jQuery,setTimeout */
(function($){
	var $window = $(window);
	$.fn.asynchImageLoader = function(options) {

		// Configuration
		options = $.extend({
			timeout : 10,
			effect : 'show',
			speed : 400,
			selector: null,
			event : 'load',
			callback : jQuery.noop,
			placeholder : false,
			delay : 0
		}, options);

		if(options.event == 'scroll') {
			$.extend({ delay:500 });
		}

		this.data('triggerEl', (options.selector) ? $(options.selector) : $window);

		var images = this;

		if (options.placeholder !== false) {
			images.filter('[data-href]').each(function(){
				$(this).attr("src", options.placeholder);
			});
		}

		// When the event is not specified the images will be loaded with a delay
		if(options.event && options.event != 'load') {
			$.asynchImageLoader.onEvent.call(this, options, images);
		} else {
			$.asynchImageLoader.later.call(this, options);
		}

		return this;
	};

	// Methods cointaing the logic
	$.asynchImageLoader = {
		_loadOnEvent : function(e) {
			var $img = $(this),
			options = e.data.options;

			// Load images
			if ($img.data("loaded") !== true) {
				$.asynchImageLoader._loadImage(options, $img);
				// Image has been loaded so there is no need to listen anymore
				$img.unbind( options.event, $.asynchImageLoader._loadOnEvent );
			}

			options.callback.call(this, options);
		},

		// Images loaded triggered by en event
		onEvent : function(options, images) {
			images = images || this;

			// Check that "selector" parameter has passed
			if ( options.selector ) {
				// Bind the event to the selector specified in the config obj
				var triggerEl = images.data('triggerEl')

				triggerEl.bind(options.event, function _bufferedEventListener() {
					clearTimeout(images.data('poller'));
					images.data('poller', setTimeout(function() {
						images.filter('[data-href]').each(function _imageLoader(){
							$.asynchImageLoader._loadImageIfVisible(options, this, triggerEl);
						});

						options.callback.call(this, options, images);
				  }, options.delay));
				});
			} else {
				// Bind the event to the images
				images.bind(options.event, { options:options }, $.asynchImageLoader._loadOnEvent);
			}
		},

		// Images loaded triggered with some delay
		later : function(options) {
			var images = this;

			setTimeout(function() {
				// Images visible loaded onload
				images.filter('[data-href]').each(function(){
					$.asynchImageLoader._loadImageIfVisible(options, this, images.data('triggerEl'));
				});

				$.asynchImageLoader.onEvent( options, images );

			}, options.timeout);
		},

		// Function that checks if the images have been loaded
		_loadImageIfVisible : function(options, image, triggerEl) {
			var $img = $(image),
			container = (options.event == 'scroll' ? triggerEl : $window);

			if ($img.data("loaded") === true) {
				return;
			}

			if ($.asynchImageLoader._isInTheScreen( container, $img)) {
				$.asynchImageLoader._loadImage(options, $img);
			}
		},

		// Function that returns true if the image is visible inside the "window" (or specified container element)
		_isInTheScreen : function($ct, $img) {
			var	is_ct_window  = $ct[0] == window,
					ct_offset  = $ct.offset() || { top:0, left:0 },
					ct_top     = ct_offset.top + ( is_ct_window ? $ct.scrollTop() : 0),
					ct_left    = ct_offset.left + ( is_ct_window ? $ct.scrollLeft() : 0),
					ct_right   = ct_left + $ct.width(),
					ct_bottom  = ct_top + $ct.height(),
					img_offset = $img.offset();

			return ct_top <= img_offset.top &&
						ct_bottom >= img_offset.top &&
							ct_left <= img_offset.left &&
								ct_right >= img_offset.left;
		},

		// Main function --> Load the images copying the "data-href" attribute into the "src" attribute
		_loadImage : function(options, $img) {
			$img
				.attr("src", $img.attr("data-href"))
				.data("loaded",true)
				.removeAttr('data-href');
			$img[options.effect](options.speed);
		}
	};
}(jQuery));
<commit_msg>Fixed bug I introduced that set the options inproperly.<commit_after>/*!
*  JqueryAsynchImageLoader (JAIL) : plugin for jQuery
*
* Developed by
* Sebastiano Armeli-Battana (@sebarmeli) - http://sebarmeli.com | http://blog.sebarmeli.com
*
* Licensed under MIT
*/
/* Copyright (c) 2010 Sebastiano Armeli-Battana (http://sebarmeli.com)

	Permission is hereby granted, free of charge, to any person obtaining
	a copy of this software and associated documentation files (the
	"Software"), to deal in the Software without restriction, including
	without limitation the rights to use, copy, modify, merge, publish,
	distribute, sublicense, and/or sell copies of the Software, and to
	permit persons to whom the Software is furnished to do so, subject to
	the following conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* JAIL helps loading images asynchronously and it can be used to make your page load faster.
* Selected images will be downloaded after the document is ready not blocking the page
* to render other elements. Images can be loaded after an event is triggered (like clicking
* on a link, mouseovering on some elements, scrolling up/down) or after some delay or simply the
* visible images will be loaded.
*
* First of all, this plugin requires you to make some HTML changes.
* E.g.
*
*
* You can define a noscript block in order to respect the principles of progressive
* enhancemnt
* E.g.
*
*
*
*
* You can call the function in this way
* E.g.
*	$(function(){
*		$('img.lazy').asynchImageLoader();
*	});
*
* You can also have different configurations:
*
* - timeout : number of msec after that the images will be loaded - Default: 10ms
* - effect : jQuery effect that makes the images display (Eg "fadeIn") - Default: "show"
* - speed :  string or number determining how long the animation will run  - Default: 400
* - selector : selector that you need to bind the trigger event - Default: NULL
* - event : event that triggers the image to load - Default: "load". You can choose "click", "mouseover", "scroll"
* - callback : function that will be called after the images are loaded	- Default: ""
* - placeholder : location of an image (such a loader) you want to display while waiting for the images to be loaded - Default: ""
* - delay : number of milliseconds to wait after the trigger event before loading images. Makes scrolling more performant - Default: 500 for 'scroll' events, 0 for everything else
*
*
* Tested with jQuery 1.3.2+ on FF 2/3, Opera 10+, Safari 4+, Chrome on Mac and IE 6/7/8 on Win.
*
* @link http://github.com/sebarmeli/JAIL
* @author Sebastiano Armeli-Battana
* @date 21/1/2011
* @version 0.3
*
*/

/*globals window,jQuery,setTimeout */
(function($){
	var $window = $(window);
	$.fn.asynchImageLoader = function(options) {
		options = options || {};

		// Configuration
		options = $.extend({
			timeout : 10,
			effect : 'show',
			speed : 400,
			selector: null,
			event : 'load',
			callback : jQuery.noop,
			placeholder : false,
			delay : options.event == 'scroll' ? 500 : 0
		}, options);

		this.data('triggerEl', (options.selector) ? $(options.selector) : $window);

		var images = this;

		if (options.placeholder !== false) {
			images.filter('[data-href]').each(function(){
				$(this).attr("src", options.placeholder);
			});
		}

		// When the event is not specified the images will be loaded with a delay
		if(options.event && options.event != 'load') {
			$.asynchImageLoader.onEvent.call(this, options, images);
		} else {
			$.asynchImageLoader.later.call(this, options);
		}

		return this;
	};

	// Methods cointaing the logic
	$.asynchImageLoader = {
		_loadOnEvent : function(e) {
			var $img = $(this),
			options = e.data.options;

			// Load images
			if ($img.data("loaded") !== true) {
				$.asynchImageLoader._loadImage(options, $img);
				// Image has been loaded so there is no need to listen anymore
				$img.unbind( options.event, $.asynchImageLoader._loadOnEvent );
			}

			options.callback.call(this, options);
		},

		// Images loaded triggered by en event
		onEvent : function(options, images) {
			images = images || this;

			// Check that "selector" parameter has passed
			if ( options.selector ) {
				// Bind the event to the selector specified in the config obj
				var triggerEl = images.data('triggerEl')

				triggerEl.bind(options.event, function _bufferedEventListener() {
					clearTimeout(images.data('poller'));
					images.data('poller', setTimeout(function() {
						images.filter('[data-href]').each(function _imageLoader(){
							$.asynchImageLoader._loadImageIfVisible(options, this, triggerEl);
						});

						options.callback.call(this, options, images);
				  }, options.delay));
				});
			} else {
				// Bind the event to the images
				images.bind(options.event, { options:options }, $.asynchImageLoader._loadOnEvent);
			}
		},

		// Images loaded triggered with some delay
		later : function(options) {
			var images = this;

			setTimeout(function() {
				// Images visible loaded onload
				images.filter('[data-href]').each(function(){
					$.asynchImageLoader._loadImageIfVisible(options, this, images.data('triggerEl'));
				});

				$.asynchImageLoader.onEvent( options, images );

			}, options.timeout);
		},

		// Function that checks if the images have been loaded
		_loadImageIfVisible : function(options, image, triggerEl) {
			var $img = $(image),
			container = (options.event == 'scroll' ? triggerEl : $window);

			if ($img.data("loaded") === true) {
				return;
			}

			if ($.asynchImageLoader._isInTheScreen( container, $img)) {
				$.asynchImageLoader._loadImage(options, $img);
			}
		},

		// Function that returns true if the image is visible inside the "window" (or specified container element)
		_isInTheScreen : function($ct, $img) {
			var	is_ct_window  = $ct[0] == window,
					ct_offset  = $ct.offset() || { top:0, left:0 },
					ct_top     = ct_offset.top + ( is_ct_window ? $ct.scrollTop() : 0),
					ct_left    = ct_offset.left + ( is_ct_window ? $ct.scrollLeft() : 0),
					ct_right   = ct_left + $ct.width(),
					ct_bottom  = ct_top + $ct.height(),
					img_offset = $img.offset();

			return ct_top <= img_offset.top &&
						ct_bottom >= img_offset.top &&
							ct_left <= img_offset.left &&
								ct_right >= img_offset.left;
		},

		// Main function --> Load the images copying the "data-href" attribute into the "src" attribute
		_loadImage : function(options, $img) {
			$img
				.attr("src", $img.attr("data-href"))
				.data("loaded",true)
				.removeAttr('data-href');
			$img[options.effect](options.speed);
		}
	};
}(jQuery));
<|endoftext|>


<commit_before>'use strict';

//var https = require('https');
//var nextMeeting = '';
const fetch = require('node-fetch');
const axios = require('axios');
const cache = require('memory-cache');
const moment = require('moment-timezone');
const nextmeeting = require('../data/nextmeeting.json');

/*
 * Set up http options for the Meetup API.
 */
var httpsOptions = {
    hostname: 'api.meetup.com',
    port: 443,
    path: '/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key,
    method: 'GET'
};

/*
 * This function always sets the meeting to the correct time.
 */
function setTimeToNewYorkForArray(meetingArray) {
    if (meetingArray && meetingArray.length > 0) {
        var currTime = moment(meetingArray[0].time).utc().clone();
        meetingArray[0].time = currTime.tz('America/New_York').format('lll');
    }
}

function setTimeToNewYork(meeting) {
    const currTime = moment(meeting.time).utc().clone();
    meeting.time = currTime.tz('America/New_York').format('lll');
}

/*
 * This is the third method used for retrieving the next meetup. It uses Node 8's async and await syntax.
 */
async function getNextMeetupV3() {
    const meetingCache = cache.get('nextMeeting');
    if (meetingCache) {
        return meetingCache[0];
    } else {
        const response = await fetch('https://api.meetup.com/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key);
        const json = await response.json();
        const meetingArray = json.results;
        setTimeToNewYork(meetingArray);
        cache.put('nextMeeting', meetingArray, 3600000);
        return meetingArray[0];
    }
}

/*
 * This is the second method used for retrieving the next meetup. It used a Promise.
 */
function getNextMeetupV2() {
    return new Promise((resolve, reject) => {
        const meetingCache = cache.get('nextMeeting');
        if (meetingCache) {
            resolve(meetingCache[0]);
        } else {
            fetch('https://api.meetup.com/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key).then(response => {
                return response.json();
            }).then(json => {
                const meetingArray = json.results;
                setTimeToNewYork(meetingArray);
                cache.put('nextMeeting', meetingArray, 3600000);
                resolve(meetingArray[0]);
            }).catch(err => {
                reject(err);
            });
        }
    });
}

/*
 * This is the original method used for retrieving the next meetup. It used a error first callback
 */
function getNextMeetup(cb) {
    var sreq = https.request(httpsOptions, function (response) {
        response.setEncoding('utf8');
        response.on('data', function (chunk) {
            nextMeeting += chunk;
        });
        response.on('end', function () {
            var err = false;
            if (nextMeeting && nextMeeting.toString().slice(0, 6) !== '<html>') {
                var meetingObject = JSON.parse(nextMeeting);
                var meetingArray = meetingObject.results;
                // permanent fix for the changing timezone plus moment deprecation fix.
                setTimeToNewYork(meetingArray);
                cache.put('nextMeeting', meetingArray, 3600000);
                nextMeeting = '';
                cb(err, meetingArray[0]);
            } else {
                var meetingObject2 = {};
                meetingObject2.results = [{}];
                cb(err, meetingObject2.results[0]);
            }
        });
    });
    sreq.on('error', function (e) {
        console.log('problem with request: ' + e.message);
        var meetingObject3 = {};
        meetingObject3.results = [{}];
        cb(e, meetingObject3.results[0]);
    });
    sreq.write('data\n');
    sreq.end();
}

/*
 * This is the third method used for retrieving the next meetup. It uses Node 8's async and await syntax.
 */
async function getNextMeetupV4() {
    console.log('The getNextMeetupV4 function was called')
    return nextmeeting[0];
}

async function getNextMeetupV5() {
    const meetingCache = cache.get('nextMeeting');
    if (meetingCache) {
        return meetingCache;
    } else {
        const response = await axios.get('https://api.meetup.com/Jax-Node-js-UG/events?page=2');
        if (response.data[0] === undefined) {
            const local_meeting = nextmeeting[0];

            setTimeToNewYork(local_meeting);
            cache.put('nextMeeting', local_meeting, 3600000);
            return local_meeting;
        } else {
            const meeting = response.data[0];

            setTimeToNewYork(meeting);
            cache.put('nextMeeting', meeting, 3600000);
            return meeting;
        }

    }

    //return nextmeeting[0];
}

// module.exports = getNextMeetup;
// module.exports = getNextMeetupV2;
module.exports = getNextMeetupV5;
<commit_msg>Adding change to the meetupdata.js<commit_after>'use strict';

//var https = require('https');
//var nextMeeting = '';
const fetch = require('node-fetch');
const axios = require('axios');
const cache = require('memory-cache');
const moment = require('moment-timezone');
const nextmeeting = require('../data/nextmeeting.json');

/*
 * Set up http options for the Meetup API.
 */
var httpsOptions = {
    hostname: 'api.meetup.com',
    port: 443,
    path: '/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key,
    method: 'GET'
};

/*
 * This function always sets the meeting to the correct time.
 */
function setTimeToNewYorkForArray(meetingArray) {
    if (meetingArray && meetingArray.length > 0) {
        var currTime = moment(meetingArray[0].time).utc().clone();
        meetingArray[0].time = currTime.tz('America/New_York').format('lll');
    }
}

function setTimeToNewYork(meeting) {
    const currTime = moment(meeting.time).utc().clone();
    meeting.time = currTime.tz('America/New_York').format('lll');
}

/*
 * This is the third method used for retrieving the next meetup. It uses Node 8's async and await syntax.
 */
async function getNextMeetupV3() {
    const meetingCache = cache.get('nextMeeting');
    if (meetingCache) {
        return meetingCache[0];
    } else {
        const response = await fetch('https://api.meetup.com/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key);
        const json = await response.json();
        const meetingArray = json.results;
        setTimeToNewYork(meetingArray);
        cache.put('nextMeeting', meetingArray, 3600000);
        return meetingArray[0];
    }
}

/*
 * This is the second method used for retrieving the next meetup. It used a Promise.
 */
function getNextMeetupV2() {
    return new Promise((resolve, reject) => {
        const meetingCache = cache.get('nextMeeting');
        if (meetingCache) {
            resolve(meetingCache[0]);
        } else {
            fetch('https://api.meetup.com/2/events?&sign=true&group_id=10250862&page=20&key=' + process.env.meetupapi_key).then(response => {
                return response.json();
            }).then(json => {
                const meetingArray = json.results;
                setTimeToNewYork(meetingArray);
                cache.put('nextMeeting', meetingArray, 3600000);
                resolve(meetingArray[0]);
            }).catch(err => {
                reject(err);
            });
        }
    });
}

/*
 * This is the original method used for retrieving the next meetup. It used a error first callback
 */
function getNextMeetup(cb) {
    var sreq = https.request(httpsOptions, function (response) {
        response.setEncoding('utf8');
        response.on('data', function (chunk) {
            nextMeeting += chunk;
        });
        response.on('end', function () {
            var err = false;
            if (nextMeeting && nextMeeting.toString().slice(0, 6) !== '<html>') {
                var meetingObject = JSON.parse(nextMeeting);
                var meetingArray = meetingObject.results;
                // permanent fix for the changing timezone plus moment deprecation fix.
                setTimeToNewYork(meetingArray);
                cache.put('nextMeeting', meetingArray, 3600000);
                nextMeeting = '';
                cb(err, meetingArray[0]);
            } else {
                var meetingObject2 = {};
                meetingObject2.results = [{}];
                cb(err, meetingObject2.results[0]);
            }
        });
    });
    sreq.on('error', function (e) {
        console.log('problem with request: ' + e.message);
        var meetingObject3 = {};
        meetingObject3.results = [{}];
        cb(e, meetingObject3.results[0]);
    });
    sreq.write('data\n');
    sreq.end();
}

/*
 * This is the third method used for retrieving the next meetup. It uses Node 8's async and await syntax.
 */
async function getNextMeetupV4() {
    console.log('The getNextMeetupV4 function was called')
    return nextmeeting[0];
}

async function getNextMeetupV5() {
    const meetingCache = cache.get('nextMeeting');
    if (meetingCache) {
        return meetingCache;
    } else {
        const response = await axios.get('https://api.meetup.com/Jax-Node-js-UG/events?page=2');
        if (response.data[0] === undefined) {
            const local_meeting = nextmeeting[0];

            setTimeToNewYork(local_meeting);
            cache.put('nextMeeting', local_meeting, 3600000);
            return local_meeting;
        } else {
            const meeting = response.data[0];

            setTimeToNewYork(meeting);
            cache.put('nextMeeting', meeting, 3600000);
            return meeting;
        }

    }

    //return nextmeeting[0];
}

// module.exports = getNextMeetup;
// module.exports = getNextMeetupV2;
module.exports = getNextMeetupV5;

<|endoftext|>


<commit_before>/**
 * @fileOverview Requirejs module containing device modifier to launch HTML5 media player including fix for players that dont send buffering events correctly.
 *
 * @preserve Copyright (c) 2014 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    "antie/devices/mediaplayer/html5waitingfix",
    [
        "antie/runtimecontext",
        "antie/devices/device",
        "antie/devices/mediaplayer/mediaplayer",
        "antie/devices/mediaplayer/html5"
    ],
    function(RuntimeContext, Device, MediaPlayer, HTML5MediaPlayer) {
        "use strict";

        var Player = HTML5MediaPlayer.extend({

            init: function() {
                this._super();
                this._bufferingTimer = null;
            },

            _onStatus: function() {
                this._super();
                this._notBufferingAnymore();
                this._clearBufferingTimer();
                if(this.getState() === MediaPlayer.STATE.PLAYING) {
                    this._setBufferingTimer();
                }
            },

            _toPaused: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toStopped: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toComplete: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toError: function(errorMessage) {
                this._clearBufferingTimer();
                this._super(errorMessage);
            },

            _clearBufferingTimer: function() {
                if(this._bufferingTimer) {
                    window.clearTimeout(this._bufferingTimer);
                    this._bufferingTimer = null;
                }
            },

            _setBufferingTimer: function() {
                var self = this;
                this._bufferingTimer = window.setTimeout(function() {
                    self._onDeviceBuffering();
                }, 500);
            },

            _notBufferingAnymore: function() {
                if (this.getState() === MediaPlayer.STATE.BUFFERING) {
                    this._onFinishedBuffering();
                }
            }
        });

        var instance = new Player();

        // Mixin this MediaPlayer implementation, so that device.getMediaPlayer() returns the correct implementation for the device
        Device.prototype.getMediaPlayer = function() {
            return instance;
        };

        return Player;
    }

);
<commit_msg>Extract if into helper to make code cleaner<commit_after>/**
 * @fileOverview Requirejs module containing device modifier to launch HTML5 media player including fix for players that dont send buffering events correctly.
 *
 * @preserve Copyright (c) 2014 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    "antie/devices/mediaplayer/html5waitingfix",
    [
        "antie/runtimecontext",
        "antie/devices/device",
        "antie/devices/mediaplayer/mediaplayer",
        "antie/devices/mediaplayer/html5"
    ],
    function(RuntimeContext, Device, MediaPlayer, HTML5MediaPlayer) {
        "use strict";

        var Player = HTML5MediaPlayer.extend({

            init: function() {
                this._super();
                this._bufferingTimer = null;
            },

            _onStatus: function() {
                this._super();
                this._notBufferingAnymore();
                this._clearBufferingTimer();
                this._setBufferingTimer();
            },

            _toPaused: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toStopped: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toComplete: function() {
                this._clearBufferingTimer();
                this._super();
            },

            _toError: function(errorMessage) {
                this._clearBufferingTimer();
                this._super(errorMessage);
            },

            _clearBufferingTimer: function() {
                if(this._bufferingTimer) {
                    window.clearTimeout(this._bufferingTimer);
                    this._bufferingTimer = null;
                }
            },

            _setBufferingTimer: function() {
                var self = this;
                if(this.getState() === MediaPlayer.STATE.PLAYING) {
                    this._bufferingTimer = window.setTimeout(function() {
                        self._onDeviceBuffering();
                    }, 500);
                }
            },

            _notBufferingAnymore: function() {
                if (this.getState() === MediaPlayer.STATE.BUFFERING) {
                    this._onFinishedBuffering();
                }
            }
        });

        var instance = new Player();

        // Mixin this MediaPlayer implementation, so that device.getMediaPlayer() returns the correct implementation for the device
        Device.prototype.getMediaPlayer = function() {
            return instance;
        };

        return Player;
    }

);
<|endoftext|>


<commit_before>// Bot: greeve
// Ruleset: default
// Learning to write a bot.
// --------------------------------------------------

var greeve = function() {};

greeve.prototype = new Bot();

greeve.prototype.setup = function() {
    this.timer = 0;
    this.attrStrength = 200;
    this.safety = 1000;
    this.repStrength = 150;
    this.movements = ['strafe-right', 'strafe-left', 'forward', 'backward'];
};

greeve.prototype.getBotWithId = function(id) {
    for (i in this.state.bots) {
        if (this.state.bots[i].id == id) {
            return this.state.bots[i];
        }
    }
    return undefined;
};

greeve.prototype.getOpponentBots = function() {
    opponents = [];
    for (i in this.state.bots) {
        if (this.name != this.state.bots[i].name) {
            opponents.push(this.state.bots[i]);
        }
    }
    return opponents;
};

greeve.prototype.getTeamBots = function() {
    team = [];
    for (i in this.state.bots) {
        if (this.name == this.state.bots[i].name) {
            team.push(this.state.bots[i]);
        }
    }
    return team;
};

greeve.prototype.getTarget = function() {
    if (typeof this.state.payload.targets == 'undefined') {
        this.state.payload.targets = {}
    }
    target = this.getBotWithId(this.state.payload.targets[this.id]);
    if (target == undefined) {
        opponents = this.getOpponentBots();
        closeness = 10000;
        for (i in opponents) {
            distance = this.myDistanceToPoint(opponents[i].x, opponents[i].y);
            if (distance < closeness) {
                target = opponents[i];
                closeness = distance;
            }
        }
    }
    this.state.payload.targets[this.id] = target.id;
    return target;
};

greeve.prototype.avoidBullets = function() {
    var dx = 0;
    var dy = 0;
    for (i in this.state.weapons) {
        var bullet = this.state.weapons[i];
        if (bullet.owner != this.id && this.myDistanceToPoint(bullet.x, bullet.y) < 50) {
            deltas = this.avoidCircle(10, bullet.x, bullet.y, 25);
            dx += deltas[0];
            dy += deltas[1];
        }
    }
    return [dx, dy];
};

greeve.prototype.run = function() {
	this.timer++;
	target = undefined;

	var cmd = 'wait';
	// get the opponent's information
	target = this.getTarget();

	// have I collided with a bot?
	this.collided = false;
	if (this.collisions.length > 0) {
		for (i in this.collisions) {
			if (this.collisions[i].type == 'bot')
				this.collided = true;
            if (this.collisions[i].type == 'obstacles')
                this.collided = true;
		}
	}

	var avoidBullets = this.avoidBullets();
	var avoid = [avoidBullets[0], avoidBullets[1]]
	var avoidDirection = this.getDirection({'x': avoid[0], 'y': avoid[1]}, 0.1);

	// if I need to avoid bullets or teammates, strafe-left or right
	if (avoid[0] != 0 && avoid[1] != 0 && avoidDirection.command != 'forward' && avoidDirection.command != 'wait') {
		var behindMe = this.angle - Math.PI;
		if (avoidDirection.command == 'right')
			cmd = 'strafe-right';
		else
			cmd = 'strafe-left';
	}

	if (target != undefined) {
		direction = this.getDirection(target, 0.05);
		distance = this.myDistanceToPoint(target.x, target.y);

		if (direction.command != 'forward') {
			// if target is not in front of me, do what it takes to get there.
			cmd = direction.command;
		} else if (this.canShoot && this.weapons.bullet > 0) {
			// if the target is in front and I can shoot and I have bullets to shoot, shoot!
			cmd = "fire";
		} else if (target.health <= this.health) {
			// if the targets health is less than my own, attack!
			cmd = "forward";
		} else if (cmd == 'wait' && distance < 150 && target.health > this.health) {
			// move backwards, if the target is close enough and it's health is greater than my own.
			cmd = "backward";
		} else if (this.collided == true) {
            // move if collided with another bot
            cmd = "backward";
        }
	}

	return { command: cmd, team: this.state.payload };
};

server.registerBotScript("greeve");
<commit_msg>Minor tweaks for battle.<commit_after>// Bot: greeve
// Ruleset: default
// Learning to write a bot.
// --------------------------------------------------

var greeve = function() {};

greeve.prototype = new Bot();

greeve.prototype.setup = function() {
    this.timer = 0;
    this.attrStrength = 8;
    this.safety = 10;
    this.repStrength = 2;
    this.movements = ['strafe-right', 'strafe-left', 'forward', 'backward'];
};

greeve.prototype.getBotWithId = function(id) {
    for (i in this.state.bots) {
        if (this.state.bots[i].id == id) {
            return this.state.bots[i];
        }
    }
    return undefined;
};

greeve.prototype.getOpponentBots = function() {
    opponents = [];
    for (i in this.state.bots) {
        if (this.name != this.state.bots[i].name) {
            opponents.push(this.state.bots[i]);
        }
    }
    return opponents;
};

greeve.prototype.getTeamBots = function() {
    team = [];
    for (i in this.state.bots) {
        if (this.name == this.state.bots[i].name) {
            team.push(this.state.bots[i]);
        }
    }
    return team;
};

greeve.prototype.getTarget = function() {
    if (typeof this.state.payload.targets == 'undefined') {
        this.state.payload.targets = {}
    }
    target = this.getBotWithId(this.state.payload.targets[this.id]);
    if (target == undefined) {
        opponents = this.getOpponentBots();
        closeness = 50000;
        for (i in opponents) {
            distance = this.myDistanceToPoint(opponents[i].x, opponents[i].y);
            if (distance < closeness) {
                target = opponents[i];
                closeness = distance;
            }
        }
    }
    this.state.payload.targets[this.id] = target.id;
    return target;
};

greeve.prototype.avoidBullets = function() {
    var dx = 0;
    var dy = 0;
    for (i in this.state.weapons) {
        var bullet = this.state.weapons[i];
        if (bullet.owner != this.id && this.myDistanceToPoint(bullet.x, bullet.y) < 50) {
            deltas = this.avoidCircle(10, bullet.x, bullet.y, 25);
            dx += deltas[0];
            dy += deltas[1];
        }
    }
    return [dx, dy];
};

greeve.prototype.run = function() {
	this.timer++;
	target = undefined;

	var cmd = 'wait';
	// get the opponent's information
	target = this.getTarget();

	// have I collided with a bot?
	this.collidedWithBot = false;
	if (this.collisions.length > 0) {
		for (i in this.collisions) {
			if (this.collisions[i].type == 'bot')
				this.collidedWithBot = true;
		}
	}

	var avoidBullets = this.avoidBullets();
	var avoid = [avoidBullets[0], avoidBullets[1]]
	var avoidDirection = this.getDirection({'x': avoid[0], 'y': avoid[1]}, 0.1);

	// if I need to avoid bullets or teammates, strafe-left or right
	if (avoid[0] != 0 && avoid[1] != 0 && avoidDirection.command != 'forward' && avoidDirection.command != 'wait') {
		var behindMe = this.angle - Math.PI;
		if (avoidDirection.command == 'right')
			cmd = 'strafe-right';
		else
			cmd = 'strafe-left';
	}

	if (target != undefined) {
		direction = this.getDirection(target, 0.05);
		distance = this.myDistanceToPoint(target.x, target.y);

		if (direction.command != 'forward') {
			// if target is not in front of me, do what it takes to get there.
			cmd = direction.command;
		} else if (this.canShoot && this.weapons.bullet > 0) {
			// if the target is in front and I can shoot and I have bullets to shoot, shoot!
			cmd = "fire";
		} else if (target.health <= this.health) {
			// if the targets health is less than my own, attack!
			cmd = "forward";
		} else if (cmd == 'wait' && distance < 150 && target.health > this.health) {
			// move backwards, if the target is close enough and it's health is greater than my own.
			cmd = "backward";
		} else if (this.collidedWithBot == true) {
            // move if collided with another bot
            cmd = "backward";
        }
	}

	return { command: cmd, team: this.state.payload };
};

server.registerBotScript("greeve");
<|endoftext|>


<commit_before>import React from 'react';
import { bool, string } from 'prop-types';
import { connect } from 'react-redux';
import { storiesOf } from '@storybook/react';
import { text } from '@storybook/addon-knobs';
import { modules } from 'veritone-redux-common';
const { user } = modules;

import VeritoneApp from '../../shared/VeritoneApp';
import FilePicker from '.';
import OAuthLoginButton from '../OAuthLoginButton';

@connect(state => ({
  userIsAuthenticated: user.userIsAuthenticated(state),
  fetchUserFailed: user.fetchingFailed(state)
}))
class Story extends React.Component {
  static propTypes = {
    userIsAuthenticated: bool,
    fetchUserFailed: bool,
    sessionToken: string
  };

  state = {
    result: null
  };

  componentDidMount() {
    this._oauthButton = new OAuthLoginButton({
      elId: 'login-button-widget-asdf',
      OAuthURI: 'http://localhost:5001/auth/veritone'
    });

    this._picker = new FilePicker({
      elId: 'file-picker-widget',
      accept: ['image/*'],
      // allowUrlUpload: false
      multiple: true
    });
  }

  componentWillUnmount() {
    this._picker.destroy();
    this._oauthButton.destroy();
  }

  handleLogin = () => {
    return app.login({ sessionToken: this.props.sessionToken });
  };

  handlePick = () => {
    this._picker.pick(this.handlePickResult);
  };

  handlePickResult = (files, { warning, error, cancelled }) => {
    if (cancelled) {
      return this.handleCancelledPick();
    }

    if (error) {
      return this.handlePickError(error)
    }

    if (warning) {
      this.handlePickWarning(warning)
    }

    this.setState({ result: files });
    console.log('Result: ', files);
  };

  handleCancelledPick = () => {
    console.log('Picking was cancelled');
  };

  handlePickError = (error) => {
    console.log('Picking failed with error:', error);
  };

  handlePickWarning = (warning) => {
    console.log('Pick resulted in a warning:', warning);
  };

  render() {
    return (

        {this.props.fetchUserFailed &&
          'failed to log in-- is your token wrong?'}
        {!this.props.userIsAuthenticated && (

              <button
                onClick={this.handleLogin}
                disabled={!this.props.sessionToken}
              >
                {this.props.sessionToken
                  ? 'Log In via session token'
                  : 'Log In via session token (Please set a token in the "Knobs" panel below)'}
              </button>

            or log in via oauth:

        )}

        {this.props.userIsAuthenticated && (
          <button
            disabled={!this.props.userIsAuthenticated}
            onClick={this.handlePick}
          >
            Pick files
          </button>
        )}

        {this.state.result && (

            Result:
            {JSON.stringify(this.state.result, null, '\t')}

        )}

    );
  }
}

const app = VeritoneApp();

storiesOf('FilePickerWidget', module).add('Base', () => {
  const sessionToken = text('Api Session Token', '');

  return <Story sessionToken={sessionToken} store={app._store} />;
});
<commit_msg>fix id<commit_after>import React from 'react';
import { bool, string } from 'prop-types';
import { connect } from 'react-redux';
import { storiesOf } from '@storybook/react';
import { text } from '@storybook/addon-knobs';
import { modules } from 'veritone-redux-common';
const { user } = modules;

import VeritoneApp from '../../shared/VeritoneApp';
import FilePicker from '.';
import OAuthLoginButton from '../OAuthLoginButton';

@connect(state => ({
  userIsAuthenticated: user.userIsAuthenticated(state),
  fetchUserFailed: user.fetchingFailed(state)
}))
class Story extends React.Component {
  static propTypes = {
    userIsAuthenticated: bool,
    fetchUserFailed: bool,
    sessionToken: string
  };

  state = {
    result: null
  };

  componentDidMount() {
    this._oauthButton = new OAuthLoginButton({
      elId: 'login-button-widget',
      OAuthURI: 'http://localhost:5001/auth/veritone'
    });

    this._picker = new FilePicker({
      elId: 'file-picker-widget',
      accept: ['image/*'],
      // allowUrlUpload: false
      multiple: true
    });
  }

  componentWillUnmount() {
    this._picker.destroy();
    this._oauthButton.destroy();
  }

  handleLogin = () => {
    return app.login({ sessionToken: this.props.sessionToken });
  };

  handlePick = () => {
    this._picker.pick(this.handlePickResult);
  };

  handlePickResult = (files, { warning, error, cancelled }) => {
    if (cancelled) {
      return this.handleCancelledPick();
    }

    if (error) {
      return this.handlePickError(error)
    }

    if (warning) {
      this.handlePickWarning(warning)
    }

    this.setState({ result: files });
    console.log('Result: ', files);
  };

  handleCancelledPick = () => {
    console.log('Picking was cancelled');
  };

  handlePickError = (error) => {
    console.log('Picking failed with error:', error);
  };

  handlePickWarning = (warning) => {
    console.log('Pick resulted in a warning:', warning);
  };

  render() {
    return (

        {this.props.fetchUserFailed &&
          'failed to log in-- is your token wrong?'}
        {!this.props.userIsAuthenticated && (

              <button
                onClick={this.handleLogin}
                disabled={!this.props.sessionToken}
              >
                {this.props.sessionToken
                  ? 'Log In via session token'
                  : 'Log In via session token (Please set a token in the "Knobs" panel below)'}
              </button>

            or log in via oauth:

        )}

        {this.props.userIsAuthenticated && (
          <button
            disabled={!this.props.userIsAuthenticated}
            onClick={this.handlePick}
          >
            Pick files
          </button>
        )}

        {this.state.result && (

            Result:
            {JSON.stringify(this.state.result, null, '\t')}

        )}

    );
  }
}

const app = VeritoneApp();

storiesOf('FilePickerWidget', module).add('Base', () => {
  const sessionToken = text('Api Session Token', '');

  return <Story sessionToken={sessionToken} store={app._store} />;
});
<|endoftext|>


<commit_before>var _       = require('underscore'),
    Network = require('./network');

/**
 * Clearwing object
 * @constructor
 */
function Clearwing(options) {
	/** {@link Network} list */
	this.networks = [];

	/**
	 * Stored data
	 * @private
	 */
	this._data = {};

	/**
	 * Events
	 * @private
	 */
	this._events = {};

	/* set up data */
	this
		.set('nick', 'Fish' + Math.floor(Math.random() * 1000));

	/* set up events */
	this.use(require('./events'));
}

/**
 * Helper function for flattening lists into property-safe values
 * @param {array} prop Property name array
 * @return {string}
 */
Clearwing.stringifyPropName = function(prop) {
	// Convert [{ network: 'foobar' }, 'option']
	// to 'network.foobar option'
	return _.map(prop, function(a) {
		return _.isObject(a) && !_.isArray(a) ?
		       _.chain(a).pairs().flatten().join('.').value() :
		       a;
	}).join(' ').toLowerCase();
};

/**
 * Helper function to convert flat property names into array form
 * @param {string} prop Property string
 * @return {array}
 */
Clearwing.parsePropName = function(prop) {
	return _.map(prop.toLowerCase().split(' '), function(s) {
		// Yes, a.split('.', 2) would give us two elements, but
		// they would be equivalent to a.split('.').slice(0, 2)
		var a = s.split('.'),
		    o = {};

		if (a.length < 2)
			return s;

		o[a[0]] = a.slice(1).join('.');
		return o;
	});
};

/**
 * Lookup a property
 * @param {...object} [namespace] Namespace name
 * @param {string} property Property name
 * @return {mixed}
 */
Clearwing.prototype.get = function() {
	return this._data[Clearwing.stringifyPropName(arguments)];
};

/**
 * Set a property
 * @param {...object} [namespace] Namespace name
 * @param {string} property Property name
 * @param {mixed} value New property value
 * @return {Clearwing}
 */
Clearwing.prototype.set = function() {
	this._data[Clearwing.stringifyPropName(_.toArray(arguments).slice(0, -1))] = arguments[arguments.length - 1];
	return this;
};

/**
 * Bind an event
 * @param {...object} [namespace] Namespace name
 * @param {string|regexp} event Event name
 * @param {function} callback Callback function
 * @return {Clearwing}
 */
Clearwing.prototype.on = function() {
	var ns       = _.toArray(arguments),
	    callback = ns.splice(-1).pop(),
	    cb       = callback,
	    event    = ns.splice(-1).pop(),
	    regexp   = event,
	    prop     = '',
	    that     = this;

	ns.push(_.isRegExp(regexp) ? 'msg' : event);
	prop = Clearwing.stringifyPropName(ns);

	if (!_.isFunction(callback))
		return this;

	if (_.isRegExp(regexp)) {
		callback = function(event) {
			if (regexp.test(event.text))
				event.text.match(regexp, cb.bind(that, event));
		};
	}

	(this._events[prop] = this._events[prop] || []).push(callback);

	return this;
};

/**
 * Emit an event
 * @param {...object} [namespace] Namespace name
 * @param {string} event Event name
 * @param {object} data Event data
 * @return {bool} False if no events are bound, true otherwise
 */
Clearwing.prototype.emit = function() {
	var ns      = _.toArray(arguments),
	    data    = ns.splice(-1).pop(),
	    event   = ns.splice(-1).pop(),
	    prop    = '',
	    props   = [],
	    that    = this,
	    caught  = false,
	    target  = this,
	    replace = [
		    [/(user).[^ ]+/, '$1'],
		    [/(channel).[^ ]+/, '$1'],
		    [/(network).[^ ]+/, '$1']
	    ];

	if (arguments.length < 2)
		throw new Error('#emit() expects at least two arguments');

	if (!_.isObject(arguments[arguments.length - 1]))
		throw new Error('#emit() expected argument ' + arguments.length + ' to be object');

	if (!_.isString(arguments[arguments.length - 2]))
		throw new Error('#emit() expected argument ' + (arguments.length - 1) + ' to be string');

	prop = Clearwing.stringifyPropName(ns.concat(event));

	props.push(prop);

	replace.forEach(function(re) {
		props.forEach(function(prop) {
			props.push(prop.replace.apply(prop, re));
		});
	});

	props = _.chain(props).uniq().sortBy(function(e) {
		return (/network([. ]|$)/.test(e) || -800) +
		       (/channel([. ]|$)/.test(e) || -400) +
		       (/user([. ]|$)/.test(e)    || -200) +
		       e.length;
	}).value();

	ns.forEach(function(item) {
		var prop = _.keys(item).pop(),
		    name = item[prop];

		switch (prop) {
			case 'network': target = data.network = that.network(name); break;
			case 'user': target = data.user = data.network.user(name); break;
			case 'channel': target = data.channel = data.network.channel(name); break;
		}
	});

	data.event = event;

	props.forEach(function(path) {
		if (!_.isArray(that._events[path]) || !that._events[path].length)
			return false;

		if (!caught)
			caught = true;

		that._events[path].forEach(function(cb) {
			cb.call(target, data);
		});
	});

	if (this.get('debug') > 5)
		console.log(data);
	else if ((this.get('debug') > 4 && data.raw) || (this.get('debug') > 3 && data.raw && !caught))
		console.log(data.event, data.raw);

	return caught;
};

/**
 * Lookup a network by name
 *
 * Note: This function will also create a new {@link Network} if one is not found
 *
 * See {@link Clearwing#hasNetwork} if you want to know if a network exists
 * @param {string} network Network name
 * @param {function} [ctx] Network context
 * @return {Network}
 */
Clearwing.prototype.network = function(network, ctx) {
	network = this.networks.filter(function(n) { return n._name == network.toLowerCase(); }).pop() ||
	          this.networks[this.networks.push(new Network(this, network)) - 1];

	if (_.isFunction(ctx))
		ctx.call(network, network);

	_.defer(function() {
		if (network.get('autoconnect') && network.get('server'))
			network.connect();
	});

	return network;
};

/**
 * See if a network exists
 * @param {string} network Network name
 * @return {bool} True if network exists, false if it does not
 */
Clearwing.prototype.hasNetwork = function(network) {
	return !!this.networks.filter(function(n) { return n._name == network.toLowerCase(); }).length;
};

/**
 * Use a plugin
 * @param {function} plugin
 * @return {Clearwing}
 */
Clearwing.prototype.use = function(plugin) {
	if (_.isFunction(plugin))
		plugin.call(this, this);

	return this;
};

module.exports = Clearwing;
<commit_msg>Fix regex events<commit_after>var _       = require('underscore'),
    Network = require('./network');

/**
 * Clearwing object
 * @constructor
 */
function Clearwing(options) {
	/** {@link Network} list */
	this.networks = [];

	/**
	 * Stored data
	 * @private
	 */
	this._data = {};

	/**
	 * Events
	 * @private
	 */
	this._events = {};

	/* set up data */
	this
		.set('nick', 'Fish' + Math.floor(Math.random() * 1000));

	/* set up events */
	this.use(require('./events'));
}

/**
 * Helper function for flattening lists into property-safe values
 * @param {array} prop Property name array
 * @return {string}
 */
Clearwing.stringifyPropName = function(prop) {
	// Convert [{ network: 'foobar' }, 'option']
	// to 'network.foobar option'
	return _.map(prop, function(a) {
		return _.isObject(a) && !_.isArray(a) ?
		       _.chain(a).pairs().flatten().join('.').value() :
		       a;
	}).join(' ').toLowerCase();
};

/**
 * Helper function to convert flat property names into array form
 * @param {string} prop Property string
 * @return {array}
 */
Clearwing.parsePropName = function(prop) {
	return _.map(prop.toLowerCase().split(' '), function(s) {
		// Yes, a.split('.', 2) would give us two elements, but
		// they would be equivalent to a.split('.').slice(0, 2)
		var a = s.split('.'),
		    o = {};

		if (a.length < 2)
			return s;

		o[a[0]] = a.slice(1).join('.');
		return o;
	});
};

/**
 * Lookup a property
 * @param {...object} [namespace] Namespace name
 * @param {string} property Property name
 * @return {mixed}
 */
Clearwing.prototype.get = function() {
	return this._data[Clearwing.stringifyPropName(arguments)];
};

/**
 * Set a property
 * @param {...object} [namespace] Namespace name
 * @param {string} property Property name
 * @param {mixed} value New property value
 * @return {Clearwing}
 */
Clearwing.prototype.set = function() {
	this._data[Clearwing.stringifyPropName(_.toArray(arguments).slice(0, -1))] = arguments[arguments.length - 1];
	return this;
};

/**
 * Bind an event
 * @param {...object} [namespace] Namespace name
 * @param {string|regexp} event Event name
 * @param {function} callback Callback function
 * @return {Clearwing}
 */
Clearwing.prototype.on = function() {
	var ns       = _.toArray(arguments),
	    callback = ns.splice(-1).pop(),
	    cb       = callback,
	    event    = ns.splice(-1).pop(),
	    regexp   = event,
	    prop     = '',
	    that     = this;

	ns.push(_.isRegExp(regexp) ? 'privmsg' : event);
	prop = Clearwing.stringifyPropName(ns);

	if (!_.isFunction(callback))
		return this;

	if (_.isRegExp(regexp)) {
		callback = function(event) {
			if (!_.isString(event.text) || !regexp.test(event.text))
				return;

			event = _.clone(event);

			event.matches = event.text.match(regexp);
			event.replaced = event.text.replace(regexp, '');

			cb.call(this, event);
		};
	}

	(this._events[prop] = this._events[prop] || []).push(callback);

	return this;
};

/**
 * Emit an event
 * @param {...object} [namespace] Namespace name
 * @param {string} event Event name
 * @param {object} data Event data
 * @return {bool} False if no events are bound, true otherwise
 */
Clearwing.prototype.emit = function() {
	var ns      = _.toArray(arguments),
	    data    = ns.splice(-1).pop(),
	    event   = ns.splice(-1).pop(),
	    prop    = '',
	    props   = [],
	    that    = this,
	    caught  = false,
	    target  = this,
	    replace = [
		    [/(user).[^ ]+/, '$1'],
		    [/(channel).[^ ]+/, '$1'],
		    [/(network).[^ ]+/, '$1']
	    ];

	if (arguments.length < 2)
		throw new Error('#emit() expects at least two arguments');

	if (!_.isObject(arguments[arguments.length - 1]))
		throw new Error('#emit() expected argument ' + arguments.length + ' to be object');

	if (!_.isString(arguments[arguments.length - 2]))
		throw new Error('#emit() expected argument ' + (arguments.length - 1) + ' to be string');

	prop = Clearwing.stringifyPropName(ns.concat(event));

	props.push(prop);

	replace.forEach(function(re) {
		props.forEach(function(prop) {
			props.push(prop.replace.apply(prop, re));
		});
	});

	props = _.chain(props).uniq().sortBy(function(e) {
		return (/network([. ]|$)/.test(e) || -800) +
		       (/channel([. ]|$)/.test(e) || -400) +
		       (/user([. ]|$)/.test(e)    || -200) +
		       e.length;
	}).value();

	ns.forEach(function(item) {
		var prop = _.keys(item).pop(),
		    name = item[prop];

		switch (prop) {
			case 'network': target = data.network = that.network(name); break;
			case 'user': target = data.user = data.network.user(name); break;
			case 'channel': target = data.channel = data.network.channel(name); break;
		}
	});

	data.event = event;

	props.forEach(function(path) {
		if (!_.isArray(that._events[path]) || !that._events[path].length)
			return false;

		if (!caught)
			caught = true;

		that._events[path].forEach(function(cb) {
			cb.call(target, data);
		});
	});

	if (this.get('debug') > 5)
		console.log(data);
	else if ((this.get('debug') > 4 && data.raw) || (this.get('debug') > 3 && data.raw && !caught))
		console.log(data.event, data.raw);

	return caught;
};

/**
 * Lookup a network by name
 *
 * Note: This function will also create a new {@link Network} if one is not found
 *
 * See {@link Clearwing#hasNetwork} if you want to know if a network exists
 * @param {string} network Network name
 * @param {function} [ctx] Network context
 * @return {Network}
 */
Clearwing.prototype.network = function(network, ctx) {
	network = this.networks.filter(function(n) { return n._name == network.toLowerCase(); }).pop() ||
	          this.networks[this.networks.push(new Network(this, network)) - 1];

	if (_.isFunction(ctx))
		ctx.call(network, network);

	_.defer(function() {
		if (network.get('autoconnect') && network.get('server'))
			network.connect();
	});

	return network;
};

/**
 * See if a network exists
 * @param {string} network Network name
 * @return {bool} True if network exists, false if it does not
 */
Clearwing.prototype.hasNetwork = function(network) {
	return !!this.networks.filter(function(n) { return n._name == network.toLowerCase(); }).length;
};

/**
 * Use a plugin
 * @param {function} plugin
 * @return {Clearwing}
 */
Clearwing.prototype.use = function(plugin) {
	if (_.isFunction(plugin))
		plugin.call(this, this);

	return this;
};

module.exports = Clearwing;
<|endoftext|>


<commit_before>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // if crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.category]){
        icon = iconPath + markerImg[crime.category];
      } else {
        icon = iconPath + markerImg.DEFAULT;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        map: map,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // make a new InfoWindow and associate it to the marker
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
'
      });
      // add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        newMarker.info.open(map, newMarker);
      });

      markers[crime.id] = newMarker; // add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17
      };

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

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
        for(var i = 0; i < crimes.length; i++){
          createMarker(crimes[i]);
        }
    },

    clearMap: function() {
      // first hide all the markers by setting map to null
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
      }
      // we no longer want access to the markers so remove them
      markers = {};
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      //the filter will match the type field on the markers
      for (var markerID in markers) {

        var marker = markers[markerID];
        var cat = marker.type;

        // check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // a filter was specified
          if (filter === cat) { // filter matches marker type
            marker.setMap(map);
          } else { // filter doesn't match marker type
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['other', 'assault', 'theft'];

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      // clear the map of current markers and infowindows
      // googleMaps.clearMap();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng

    // if map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    hideKeyboard();
  };

  $scope.filterBy = function (filterArg) {
    if (!filterArg) filterArg = 'all';
    googleMaps.filterBy(filterArg);
  };

  $scope.trackLocation = function() {
    alert('Tracking');
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos){
      var lat = pos.latitude;
      var lng = pos.longitude;
      alert(lat);
      // googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 10,
      stationaryRadius: 20,
      distanceFilter: 30,
      debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<commit_msg>Removes controls and clutter from map display<commit_after>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // if crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.category]){
        icon = iconPath + markerImg[crime.category];
      } else {
        icon = iconPath + markerImg.DEFAULT;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        map: map,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // make a new InfoWindow and associate it to the marker
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
'
      });
      // add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        newMarker.info.open(map, newMarker);
      });

      markers[crime.id] = newMarker; // add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        overviewMapControl: false
      };

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

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
        for(var i = 0; i < crimes.length; i++){
          createMarker(crimes[i]);
        }
    },

    clearMap: function() {
      // first hide all the markers by setting map to null
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
      }
      // we no longer want access to the markers so remove them
      markers = {};
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      //the filter will match the type field on the markers
      for (var markerID in markers) {

        var marker = markers[markerID];
        var cat = marker.type;

        // check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // a filter was specified
          if (filter === cat) { // filter matches marker type
            marker.setMap(map);
          } else { // filter doesn't match marker type
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['other', 'assault', 'theft'];

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      // clear the map of current markers and infowindows
      // googleMaps.clearMap();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng

    // if map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    hideKeyboard();
  };

  $scope.filterBy = function (filterArg) {
    if (!filterArg) filterArg = 'all';
    googleMaps.filterBy(filterArg);
  };

  $scope.trackLocation = function() {
    alert('Tracking');
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos){
      var lat = pos.latitude;
      var lng = pos.longitude;
      alert(lat);
      // googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 10,
      stationaryRadius: 20,
      distanceFilter: 30,
      debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<|endoftext|>


<commit_before>var http = require('https')
    , qs = require('querystring')
    , Cleverbot = function (options) {
        this.configure(options);
      };

Cleverbot.prepare = function(cb){
  // noop for backwards compatibility
  cb();
};

Cleverbot.prototype = {

    configure: function (options){
      if(options && options.constructor !== Object){
        throw new TypeError("Cleverbot must be configured with an Object");
      }
      this.options = options || {};
    },

    path: function(message){
      var path = '/getreply'
        , query = {
          input: JSON.stringify(message),
          key: this.options.botapi || "CHANGEME"
        };

      if(this.state) {
        query.cs = this.state;
      }
      return [path, qs.stringify(query)].join("?");
    },

    write: function (message, callback, errorCallback) {
        var clever = this;
        var body = this.params;

        var options = {
            host: 'www.cleverbot.com',
            port: 443,
            path: this.path(message),
            method: 'GET',
            headers: { 'Content-Type': 'text/javascript' }
        };
        var cb = callback || function() { };
        var err = errorCallback || function() {};

        var req = http.request(options, function (res) {
            var chunks = [];
            res.on("data", function(data) {
              chunks.push(data);
            });
            res.on("end", function(i) {
              var body = Buffer.concat(chunks).toString();
              var responseBody;
              try{
                responseBody = JSON.parse(body);
              } catch(e) {
                try{
                  eval("responseBody = " + body);
                } catch(e) {
                  errorCallback(e, message, body);
                  return;
                }
              }
              responseBody.message = responseBody.output; //for backwards compatibility
              this.state = responseBody.cs;
              cb(responseBody);
            }.bind(this));
        }.bind(this));

        req.end();

    }
};

module.exports = Cleverbot;
<commit_msg>Fixed crash when errorCallback is not defined<commit_after>var http = require('https')
    , qs = require('querystring')
    , Cleverbot = function (options) {
        this.configure(options);
      };

Cleverbot.prepare = function(cb){
  // noop for backwards compatibility
  cb();
};

Cleverbot.prototype = {

    configure: function (options){
      if(options && options.constructor !== Object){
        throw new TypeError("Cleverbot must be configured with an Object");
      }
      this.options = options || {};
    },

    path: function(message){
      var path = '/getreply'
        , query = {
          input: JSON.stringify(message),
          key: this.options.botapi || "CHANGEME"
        };

      if(this.state) {
        query.cs = this.state;
      }
      return [path, qs.stringify(query)].join("?");
    },

    write: function (message, callback, errorCallback) {
        var clever = this;
        var body = this.params;

        var options = {
            host: 'www.cleverbot.com',
            port: 443,
            path: this.path(message),
            method: 'GET',
            headers: { 'Content-Type': 'text/javascript' }
        };
        var cb = callback || function() { };
        var err = errorCallback || function() {};

        var req = http.request(options, function (res) {
            var chunks = [];
            res.on("data", function(data) {
              chunks.push(data);
            });
            res.on("end", function(i) {
              var body = Buffer.concat(chunks).toString();
              var responseBody;
              try{
                responseBody = JSON.parse(body);
              } catch(e) {
                try{
                  eval("responseBody = " + body);
                } catch(e) {
                  err(e, message, body);
                  return;
                }
              }
              responseBody.message = responseBody.output; //for backwards compatibility
              this.state = responseBody.cs;
              cb(responseBody);
            }.bind(this));
        }.bind(this));

        req.end();

    }
};

module.exports = Cleverbot;
<|endoftext|>