<commit_before>var http = require('http');
var Promise = require('./promise');
var request = require('./request.js');
var headers = { 'User-Agent': 'lukehoban', 'Authorization': 'token 3e9852ce188aa2f097a1e5dd6fbd36f73020a1d5' };

// Promise-returning asynchronous function
async function getCollaboratorImages(full_name) {
    // any exceptions thrown here will propogate into try/catch in callers - same as synchronous
    var url = 'https://api.github.com/repos/' + full_name + '/collaborators';
    // await a promise-returning async HTTP GET - same as synchronous
    var res = await request({url: url, headers: headers});
    return JSON.parse(res.body).map(function(collab) {
        return collab.avatar_url;
    });
}

// can use a `async function` here because createServer doesn't care what this returns
http.createServer(async function (req, res) {
    console.log('starting...')
    var url = 'https://api.github.com/search/repositories?per_page=100&q=' + 'tetris';
    var results = [];
    // write a normal 'synchronous' while loop
    while(true) {
        console.log('Got ' + results.length + ' items total.  Next: ' + url);
        // use normal exception handling
        try {
            // promise-returning async HTTP GET
            var res = await request({url: url, headers: headers});
            var items = JSON.parse(res.body).items;
            // nested parallel work is still possible with await* ( or `await Promise.all`)
            var newItems = await* items.map(async function (item) {
                return {
                    full_name: item.full_name,
                    collabs_images: await getCollaboratorImages(item.full_name)
               }
            });
            results = results.concat(newItems);
            url = (/<(.*)>; rel="next"/.exec(res.headers.link) || [])[1];
            // break once there is no 'next' link
            if(!url) break;
        } catch(err) {
            console.log('backing off... ' + err);
            // backoff on any error
            await Promise.delay(1000);
            // then try again
            continue;
        }
    }
    // when done, write response - appears in the usual synchronous 'at the end'
    console.log('Done. Got ' + results.length + ' items total.');
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(results));
}).listen(process.env.port || 1337);
console.log("Listening on http://127.0.0.1:" + (process.env.port || 1337));
<commit_msg>Convert `await* ...` to `await Promise.all(...)`<commit_after>var http = require('http');
var Promise = require('./promise');
var request = require('./request.js');
var headers = { 'User-Agent': 'lukehoban', 'Authorization': 'token 3e9852ce188aa2f097a1e5dd6fbd36f73020a1d5' };

// Promise-returning asynchronous function
async function getCollaboratorImages(full_name) {
    // any exceptions thrown here will propogate into try/catch in callers - same as synchronous
    var url = 'https://api.github.com/repos/' + full_name + '/collaborators';
    // await a promise-returning async HTTP GET - same as synchronous
    var res = await request({url: url, headers: headers});
    return JSON.parse(res.body).map(function(collab) {
        return collab.avatar_url;
    });
}

// can use a `async function` here because createServer doesn't care what this returns
http.createServer(async function (req, res) {
    console.log('starting...')
    var url = 'https://api.github.com/search/repositories?per_page=100&q=' + 'tetris';
    var results = [];
    // write a normal 'synchronous' while loop
    while(true) {
        console.log('Got ' + results.length + ' items total.  Next: ' + url);
        // use normal exception handling
        try {
            // promise-returning async HTTP GET
            var res = await request({url: url, headers: headers});
            var items = JSON.parse(res.body).items;
            // can do nested parallel work by constructing promises in
            // parallel then awaiting them, e.g. with Promise.all
            var newItems = await Promise.all(items.map(async function (item) {
                return {
                    full_name: item.full_name,
                    collabs_images: await getCollaboratorImages(item.full_name)
               }
            }));
            results = results.concat(newItems);
            url = (/<(.*)>; rel="next"/.exec(res.headers.link) || [])[1];
            // break once there is no 'next' link
            if(!url) break;
        } catch(err) {
            console.log('backing off... ' + err);
            // backoff on any error
            await Promise.delay(1000);
            // then try again
            continue;
        }
    }
    // when done, write response - appears in the usual synchronous 'at the end'
    console.log('Done. Got ' + results.length + ' items total.');
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(results));
}).listen(process.env.port || 1337);
console.log("Listening on http://127.0.0.1:" + (process.env.port || 1337));
<|endoftext|>


<commit_before>'use strict';

var Record = require('../models/record');
var Call = require('../models/call');
var clarify = require('clarifyio');
var config = require('../config');
var clarifyClient = new clarify.Client('api.clarify.io', config.clarify.API_KEY);
var _ = require('lodash');
var fs = require('fs');

var handleData = function (data) {
    return data.replace(/^data:audio\/ogg; codecs=opus;base64,/, '');
};

var gatherHits = function (itemResult, terms) {
    var hits = [];
    (itemResult.term_results || []).forEach(function (tr, i) {
        var term = terms[i] || '';
        var matches = tr.matches || [];
        matches.forEach(function (m) {
            if (m.type === 'audio') {
                m.hits.forEach(function (h) {
                    h.term = term;
                    hits.push(h);
                });
            }
        });
    });
    return hits;
};

exports.create = function (req, res) {
    Call.findById(req.body.call, function (err, call) {
        Record.create({
            call: call,
            user: req.user
        }, function (err, record) {
            call.records.push(record);
            call.save();
            fs.writeFile('./public/uploads/' + record._id + '.ogg', '', 'base64');
            res.status(200).json({id: record._id});
        });
    });
};

exports.update = function (req, res) {
    var data = handleData(req.body.data);
    fs.appendFile('./public/uploads/' + req.params.id + '.ogg', data, 'base64');
    res.status(200).json({id: req.params.id});
};

exports.finish = function (req, res) {
    Record.findById(req.params.id)
        .exec(function (err, record) {
            var metadata = {
                recordId: record._id
            };
            clarifyClient.createBundle({
                name: 'Test',
                media_url: config.BASE_URL + '/uploads/533746.mp3', // + record._id + '.ogg',
                notify_url: config.BASE_URL + '/records/notify',
                external_id: record._id.toString(),
                metadata: JSON.stringify(metadata)
            }, function(err){
                console.log(err);
            });
            res.sendStatus(200);
        });
};

exports.notify = function (req, res) {
    var io = req.app.get('io');
    console.log(req);
    if ('bundle_processing_cost' in req.body) {
        Record.findById(req.body.external_id, function (err, record) {
            if (record) {
                record.processing_cost = req.body.bundle_processing_cost;
            }
        });
    }

    if (req.body.track_id) {
        var trackData = req.body._embedded['clarify:track'];
        Record.findById(req.body.external_id, function (err, record) {
            if (record) {
                record.clarify.bundle_id = req.body.bundle_id;
                record.clarify.indexedAt = Date.now();
                record.clarify.duration = trackData.duration;
            }
        });
    }
    res.sendStatus(200);
};

exports.search = function (req, res) {
    var query = req.body.query;
    var searchResult = {
        results: []
    };

    clarifyClient.search({query: query, embed: 'metadata'}, function (err, result) {
        var terms = (result.search_terms || []).map(function (t) {
            return t.term;
        });
        var count = Math.min(result.total, result.limit);

        var ids = [];
        if (count > 0) {
            ids = result._embedded.items.map(function (item) {
                return item._embedded['clarify:metadata'].data.recordId;
            });
        }

        Record.find({'_id': {'$in': ids}, user: req.user}, function (err, data) {
            var records = _.transform(data, function (trecords, item) {
                trecords[item.id] = item;
            });

            for (var i = 0; i < count; i++) {
                var metadata = result._embedded.items[i]._embedded['clarify:metadata'].data;
                var itemResult = result.item_results[i];
                var media = records[metadata.recordId];
                if (media) {
                    var item = {
                        id: media._id,
                        mediaUrl: media.url,
                        name: media.name,
                        score: itemResult.score,
                        hits: gatherHits(itemResult, terms),
                        duration: media.duration,
                        searchTermResults: itemResult.term_results
                    };
                    searchResult.results.push(item);
                }
            }
            res.status(200).json(searchResult);
        });
    });
};

<commit_msg>code clean up<commit_after>'use strict';

var Record = require('../models/record');
var Call = require('../models/call');
var clarify = require('clarifyio');
var config = require('../config');
var clarifyClient = new clarify.Client('api.clarify.io', config.clarify.API_KEY);
var _ = require('lodash');
var fs = require('fs');

var handleData = function (data) {
    return data.replace(/^data:audio\/ogg; codecs=opus;base64,/, '');
};

var gatherHits = function (itemResult, terms) {
    var hits = [];
    (itemResult.term_results || []).forEach(function (tr, i) {
        var term = terms[i] || '';
        var matches = tr.matches || [];
        matches.forEach(function (m) {
            if (m.type === 'audio') {
                m.hits.forEach(function (h) {
                    h.term = term;
                    hits.push(h);
                });
            }
        });
    });
    return hits;
};

exports.create = function (req, res) {
    Call.findById(req.body.call, function (err, call) {
        Record.create({
            call: call,
            user: req.user
        }, function (err, record) {
            call.records.push(record);
            call.save();
            fs.writeFile('./public/uploads/' + record._id + '.ogg', '', 'base64');
            res.status(200).json({id: record._id});
        });
    });
};

exports.update = function (req, res) {
    var data = handleData(req.body.data);
    fs.appendFile('./public/uploads/' + req.params.id + '.ogg', data, 'base64');
    res.status(200).json({id: req.params.id});
};

exports.finish = function (req, res) {
    Record.findById(req.params.id)
        .exec(function (err, record) {
            var metadata = {
                recordId: record._id
            };
            clarifyClient.createBundle({
                name: 'Test',
                media_url: config.BASE_URL + '/uploads/' + record._id + '.ogg',
                notify_url: config.BASE_URL + '/records/notify',
                external_id: record._id.toString(),
                metadata: JSON.stringify(metadata)
            }, function(err){
                console.log(err);
            });
            res.sendStatus(200);
        });
};

exports.notify = function (req, res) {
    var io = req.app.get('io');
    console.log(req);
    if ('bundle_processing_cost' in req.body) {
        Record.findById(req.body.external_id, function (err, record) {
            if (record) {
                record.processing_cost = req.body.bundle_processing_cost;
            }
        });
    }

    if (req.body.track_id) {
        var trackData = req.body._embedded['clarify:track'];
        Record.findById(req.body.external_id, function (err, record) {
            if (record) {
                record.clarify.bundle_id = req.body.bundle_id;
                record.clarify.indexedAt = Date.now();
                record.clarify.duration = trackData.duration;
            }
        });
    }
    res.sendStatus(200);
};

exports.search = function (req, res) {
    var query = req.body.query;
    var searchResult = {
        results: []
    };

    clarifyClient.search({query: query, embed: 'metadata'}, function (err, result) {
        var terms = (result.search_terms || []).map(function (t) {
            return t.term;
        });
        var count = Math.min(result.total, result.limit);

        var ids = [];
        if (count > 0) {
            ids = result._embedded.items.map(function (item) {
                return item._embedded['clarify:metadata'].data.recordId;
            });
        }

        Record.find({'_id': {'$in': ids}, user: req.user}, function (err, data) {
            var records = _.transform(data, function (trecords, item) {
                trecords[item.id] = item;
            });

            for (var i = 0; i < count; i++) {
                var metadata = result._embedded.items[i]._embedded['clarify:metadata'].data;
                var itemResult = result.item_results[i];
                var media = records[metadata.recordId];
                if (media) {
                    var item = {
                        id: media._id,
                        mediaUrl: media.url,
                        name: media.name,
                        score: itemResult.score,
                        hits: gatherHits(itemResult, terms),
                        duration: media.duration,
                        searchTermResults: itemResult.term_results
                    };
                    searchResult.results.push(item);
                }
            }
            res.status(200).json(searchResult);
        });
    });
};

<|endoftext|>


<commit_before>/* Magic Mirror
 * Log
 *
 * This logger is very simple, but needs to be extended.
 * This system can eventually be used to push the log messages to an external target.
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
(function (root, factory) {
	if (typeof exports === "object") {
		if (process.env.JEST_WORKER_ID === undefined) {
			// add timestamps in front of log messages
			require("console-stamp")(console, {
				pattern: "yyyy-mm-dd HH:MM:ss.l",
				include: ["debug", "log", "info", "warn", "error"]
			});
		}

		// Node, CommonJS-like
		module.exports = factory(root.config);
	} else {
		// Browser globals (root is window)
		root.Log = factory(root.config);
	}
})(this, function (config) {
	let logLevel;
	if (process.env.JEST_WORKER_ID === undefined) {
		logLevel = {
			debug: Function.prototype.bind.call(console.debug, console),
			log: Function.prototype.bind.call(console.log, console),
			info: Function.prototype.bind.call(console.info, console),
			warn: Function.prototype.bind.call(console.warn, console),
			error: Function.prototype.bind.call(console.error, console),
			group: Function.prototype.bind.call(console.group, console),
			groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console),
			groupEnd: Function.prototype.bind.call(console.groupEnd, console),
			time: Function.prototype.bind.call(console.time, console),
			timeEnd: Function.prototype.bind.call(console.timeEnd, console),
			timeStamp: Function.prototype.bind.call(console.timeStamp, console)
		};

		logLevel.setLogLevel = function (newLevel) {
			if (newLevel) {
				Object.keys(logLevel).forEach(function (key, index) {
					if (!newLevel.includes(key.toLocaleUpperCase())) {
						logLevel[key] = function () {};
					}
				});
			}
		};
	} else {
		logLevel = {
			debug: function () {},
			log: function () {},
			info: function () {},
			warn: function () {},
			error: function () {},
			group: function () {},
			groupCollapsed: function () {},
			groupEnd: function () {},
			time: function () {},
			timeEnd: function () {},
			timeStamp: function () {}
		};
	}

	return logLevel;
});
<commit_msg>again logger.js due to problem with e2e test<commit_after>/* Magic Mirror
 * Log
 *
 * This logger is very simple, but needs to be extended.
 * This system can eventually be used to push the log messages to an external target.
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 */
(function (root, factory) {
	if (typeof exports === "object") {
		// add timestamps in front of log messages
		require("console-stamp")(console, {
			pattern: "yyyy-mm-dd HH:MM:ss.l",
			include: ["debug", "log", "info", "warn", "error"]
		});

		// Node, CommonJS-like
		module.exports = factory(root.config);
	} else {
		// Browser globals (root is window)
		root.Log = factory(root.config);
	}
})(this, function (config) {
	let logLevel;
	if (process.env.JEST_WORKER_ID === undefined) {
		logLevel = {
			debug: Function.prototype.bind.call(console.debug, console),
			log: Function.prototype.bind.call(console.log, console),
			info: Function.prototype.bind.call(console.info, console),
			warn: Function.prototype.bind.call(console.warn, console),
			error: Function.prototype.bind.call(console.error, console),
			group: Function.prototype.bind.call(console.group, console),
			groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console),
			groupEnd: Function.prototype.bind.call(console.groupEnd, console),
			time: Function.prototype.bind.call(console.time, console),
			timeEnd: Function.prototype.bind.call(console.timeEnd, console),
			timeStamp: Function.prototype.bind.call(console.timeStamp, console)
		};
	} else {
		logLevel = {
			debug: Function.prototype.bind.call(console.debug, console),
			log: Function.prototype.bind.call(console.log, console),
			info: Function.prototype.bind.call(console.info, console),
			warn: Function.prototype.bind.call(console.warn, console),
			error: Function.prototype.bind.call(console.error, console),
			group: Function.prototype.bind.call(console.group, console),
			groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console),
			groupEnd: Function.prototype.bind.call(console.groupEnd, console),
			time: Function.prototype.bind.call(console.time, console),
			timeEnd: Function.prototype.bind.call(console.timeEnd, console)
		};
	}

	logLevel.setLogLevel = function (newLevel) {
		if (newLevel) {
			Object.keys(logLevel).forEach(function (key, index) {
				if (!newLevel.includes(key.toLocaleUpperCase())) {
					logLevel[key] = function () {};
				}
			});
		}
	};

	return logLevel;
});
<|endoftext|>


<commit_before>import moment from 'moment';

Meteor.methods({
	sendMessage(message) {
		check(message, Object);

		if (!Meteor.userId()) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'sendMessage'
			});
		}

		if (!message.rid) {
			throw new Error('The \'rid\' property on the message object is missing.');
		}

		if (message.ts) {
			const tsDiff = Math.abs(moment(message.ts).diff());
			if (tsDiff > 60000) {
				throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', {
					method: 'sendMessage',
					message_ts: message.ts,
					server_ts: new Date().getTime()
				});
			} else if (tsDiff > 10000) {
				message.ts = new Date();
			}
		} else {
			message.ts = new Date();
		}

		if (message.msg && message.msg.length > RocketChat.settings.get('Message_MaxAllowedSize')) {
			throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', {
				method: 'sendMessage'
			});
		}

		const user = RocketChat.models.Users.findOneById(Meteor.userId(), {
			fields: {
				username: 1,
				name: 1
			}
		});

		const room = Meteor.call('canAccessRoom', message.rid, user._id);
		if (!room) {
			return false;
		}

		const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId());
		if (subscription && (subscription.blocked || subscription.blocker)) {
			RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
				_id: Random.id(),
				rid: room._id,
				ts: new Date,
				msg: TAPi18n.__('room_is_blocked', {}, user.language)
			});
			return false;
		}

		if ((room.muted || []).includes(user.username)) {
			RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
				_id: Random.id(),
				rid: room._id,
				ts: new Date,
				msg: TAPi18n.__('You_have_been_muted', {}, user.language)
			});
			return false;
		}

		if (message.alias == null && RocketChat.settings.get('Message_SetNameToAliasEnabled')) {
			message.alias = user.name;
		}

		if (Meteor.settings['public'].sandstorm) {
			message.sandstormSessionId = this.connection.sandstormSessionId();
		}

		RocketChat.metrics.messagesSent.inc(); // TODO This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736
		return RocketChat.sendMessage(user, message, room);
	}
});
// Limit a user, who does not have the "bot" role, to sending 5 msgs/second
RocketChat.RateLimiter.limitMethod('sendMessage', 5, 1000, {
	userId(userId) {
		return !RocketChat.authz.hasPermission(userId, 'send-many-messages');
	}
});
<commit_msg>[FIX] Send a message when muted returns inconsistent result in chat.sendMessage (#10720)<commit_after>import moment from 'moment';

Meteor.methods({
	sendMessage(message) {
		check(message, Object);

		if (!Meteor.userId()) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'sendMessage'
			});
		}

		if (!message.rid) {
			throw new Error('The \'rid\' property on the message object is missing.');
		}

		if (message.ts) {
			const tsDiff = Math.abs(moment(message.ts).diff());
			if (tsDiff > 60000) {
				throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', {
					method: 'sendMessage',
					message_ts: message.ts,
					server_ts: new Date().getTime()
				});
			} else if (tsDiff > 10000) {
				message.ts = new Date();
			}
		} else {
			message.ts = new Date();
		}

		if (message.msg && message.msg.length > RocketChat.settings.get('Message_MaxAllowedSize')) {
			throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', {
				method: 'sendMessage'
			});
		}

		const user = RocketChat.models.Users.findOneById(Meteor.userId(), {
			fields: {
				username: 1,
				name: 1
			}
		});

		const room = Meteor.call('canAccessRoom', message.rid, user._id);
		if (!room) {
			return false;
		}

		const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId());
		if (subscription && (subscription.blocked || subscription.blocker)) {
			RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
				_id: Random.id(),
				rid: room._id,
				ts: new Date,
				msg: TAPi18n.__('room_is_blocked', {}, user.language)
			});
			throw new Meteor.Error('You can\'t send messages because you are blocked');
		}

		if ((room.muted || []).includes(user.username)) {
			RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
				_id: Random.id(),
				rid: room._id,
				ts: new Date,
				msg: TAPi18n.__('You_have_been_muted', {}, user.language)
			});
			throw new Meteor.Error('You can\'t send messages because you have been muted');
		}

		if (message.alias == null && RocketChat.settings.get('Message_SetNameToAliasEnabled')) {
			message.alias = user.name;
		}

		if (Meteor.settings['public'].sandstorm) {
			message.sandstormSessionId = this.connection.sandstormSessionId();
		}

		RocketChat.metrics.messagesSent.inc(); // TODO This line needs to be moved to it's proper place. See the comments on: https://github.com/RocketChat/Rocket.Chat/pull/5736
		return RocketChat.sendMessage(user, message, room);
	}
});
// Limit a user, who does not have the "bot" role, to sending 5 msgs/second
RocketChat.RateLimiter.limitMethod('sendMessage', 5, 1000, {
	userId(userId) {
		return !RocketChat.authz.hasPermission(userId, 'send-many-messages');
	}
});
<|endoftext|>


<commit_before>app.Router = Backbone.Router.extend({
  routes: {
    'map/:mapid/line/:lineid(/)': 'line',
    'map/:mapid(/)': 'map',
    '': 'home',
    '*default': 'error'
  },

  initialize: function(options) {
    Backbone.history.start({ pushState: true, root: '/' });
  },

  home: function() {
    if (this.view) this.view.remove();
    this.view = new app.HomeView();
    $('body').append(this.view.render().el);
  },

  map: function(mapId) {
    this._loadMap(mapId, function(model) {
      model.unselect();
    });
  },

  line: function(mapId, lineId) {
    this._loadMap(mapId, function(model) {
      model.select(lineId);
    });
  },

  _loadMap: function(mapId, callback) {
    // If we already have a view with the apropriate model, we just need
    // to handle the select/unselect events, and skip data load / view rendering
    if (this.view && this.view.model && this.view.model.id === mapId) {
      callback(this.view.model);
      return;
    }

    var renderMap = function(model) {
      if (this.view) this.view.remove();
      this.view = new app.MapView({ model: model });
      $('body').append(this.view.render().el);
      callback(model);
    };

    var map = new app.Map({ id: mapId });
    map.fetch({ success: _.bind(renderMap, this)});
  },

  error: function() {
    console.log('Route not found. Mild moment of panic.');
    this.navigate('', { trigger: true });
  },
});
<commit_msg>Fix string comparison bug that was causing view reloads on each select.<commit_after>app.Router = Backbone.Router.extend({
  routes: {
    'map/:mapid/line/:lineid(/)': 'line',
    'map/:mapid(/)': 'map',
    '': 'home',
    '*default': 'error'
  },

  initialize: function(options) {
    Backbone.history.start({ pushState: true, root: '/' });
  },

  home: function() {
    if (this.view) this.view.remove();
    this.view = new app.HomeView();
    $('body').append(this.view.render().el);
  },

  map: function(mapId) {
    this._loadMap(mapId, function(model) {
      model.unselect();
    });
  },

  line: function(mapId, lineId) {
    this._loadMap(mapId, function(model) {
      model.select(lineId);
    });
  },

  _loadMap: function(mapId, callback) {
    // If we already have a view with the apropriate model, we just need
    // to handle the select/unselect events, and skip data load / view rendering
    if (this.view && this.view.model && this.view.model.id.toString() === mapId) {
      callback(this.view.model);
      return;
    }

    var renderMap = function(model) {
      if (this.view) this.view.remove();
      this.view = new app.MapView({ model: model });
      $('body').append(this.view.render().el);
      callback(model);
    };

    var map = new app.Map({ id: mapId });
    map.fetch({ success: _.bind(renderMap, this)});
  },

  error: function() {
    console.log('Route not found. Mild moment of panic.');
    this.navigate('', { trigger: true });
  },
});
<|endoftext|>


<commit_before>var GENEMAP = GENEMAP || {};

GENEMAP.Chromosome = function (userConfig) {
  var defaultConfig = {
    border: false,
    longestChromosome: 100,
    bands: "basemap",
    layout: {
      width: 10,
      height: 100,
      x: 0,
      y: 0,
    },
    scale : 1,
    onAnnotationSelectFunction: $.noop(),
    drawing: null,
  };

  var config = _.merge({}, defaultConfig, userConfig);

  var buildYScale = function () {
    return d3.scale.linear().range([0, config.layout.height]).domain([0, config.longestChromosome]);
  };

  // function to update a single chromosome element given the enter + update selection
  // and data. This assumes the basic element structure is in place.
  var updateChromosome = function (chromosome) {
    var y = buildYScale();
    var height = y(chromosome.length);
    var chromosomeGroup = d3.select(this);

    chromosomeGroup.attr({
      id: 'chromosome_' + chromosome.number,
      transform: 'translate(' + config.layout.x + ',' + config.layout.y + ')',
    });

    chromosomeGroup.select('defs').html('')
      .append('mask').attr({
        id: 'chromosome_mask_' + chromosome.number,
      })
      .append('rect').attr({
        class: 'mask_rect',
      });

    chromosomeGroup.select('#chromosome_mask_' + chromosome.number).attr({
      width: config.layout.width,
      height: height,
    });

    var chromosomeShape = {
      width: config.layout.width,
      height: height,
      rx: config.layout.height * 0.01,
      ry: config.layout.height * 0.01,
    };

    chromosomeGroup.select('.mask_rect').attr(chromosomeShape);
    chromosomeGroup.select('rect.background').attr(chromosomeShape);
    chromosomeGroup.select('rect.outline').attr(chromosomeShape);

    var selection = [];

    var updateSelection = function(){

      var gSelect = chromosomeGroup.selectAll('rect.selection').data(selection);

      gSelect.enter()
        .append('rect')
        .attr( 'class', 'selection')
        .style( {
          'fill' : 'gray',
          'opacity' : 0.2,
        });

      gSelect
        .attr( {
          'x': 0,
          'y': function(d){ return Math.min(d.start, d.end)},
          'width': config.layout.width,
          'height': function(d){ return Math.abs(d.end - d.start)},
        });

      gSelect.exit()
        .remove();
    }

    var drag = d3.behavior.drag()
      .on( 'dragstart', function(event){
        //log.info(y.invert( d3.event.y))
        var pos = d3.mouse(this);
        selection.push({
          'start' : pos[1],
          'end' : pos[1]
        });
        updateSelection();
        d3.event.sourceEvent.stopPropagation();
      })
      .on( 'drag', function(event){
        selection[0].end = d3.event.y;
        updateSelection();
        d3.event.sourceEvent.stopPropagation();
        d3.event.sourceEvent.preventDefault();
      })
      .on( 'dragend', function(event){
        d3.event.sourceEvent.stopPropagation();
        var geneStart = y.invert(selection[0].start);
        var geneEnd = y.invert(selection[0].end);
        if( geneStart > geneEnd){
          var temp = geneStart;
          geneStart = geneEnd;
          geneEnd = temp;
        }

        var nodesToUpdate = chromosome.layout.geneBandNodes.filter( function(node){
          return (node.data.midpoint > geneStart && node.data.midpoint < geneEnd )
        }
        );

        nodesToUpdate.forEach( function(node){
          if (node.data.type == "gene") {
            node.data.visible  = true;
          }
          else if ( node.data.type == "geneslist"){
            node.data.genesList.forEach( function(gene) {
              gene.visible = true;
            });
            }
        } );

        config.onAnnotationSelectFunction();

        selection = [];
        updateSelection();

      });

    chromosomeGroup.select('rect.background')
      .call(drag);

    if (config.border) {
      chromosomeGroup.select('rect.border')
        .attr({
          width: config.layout.width,
          height: config.layout.height,
        });
    }

    // setup the chromosome bands
    var bandsContainer = chromosomeGroup.select('.bands_container');

    var drawBands;
    if (config.bands == "basemap"){
      drawBands = drawBasemapBands;
    }
    else if (config.bands == "genes"){
      drawBands = drawGeneLines;
    }

    drawBands( bandsContainer, chromosome);

    chromosomeGroup.select('.bands_container').style({
      mask: 'url(#chromosome_mask_' + chromosome.number + ')',
    });
  };

  var drawBasemapBands = function( bandsContainer, chromosome){

    var y = buildYScale();
    var bands = bandsContainer.selectAll('rect.band').data(chromosome.bands);
    bands.enter().append('rect').attr('class', 'band');

    bands.attr({
      width: config.layout.width,
      y: function (d) { return y(d.start); },
      height: function (d) { return y(d.end - d.start); },
      fill: function (d) { return d.color; },
    });

    bands.exit().remove();
  }

  var generateGeneLineAttr = function (y, gene){
    var rawHeight = gene.end - gene.start;
    var rawDY = y(rawHeight);

    var result;

    if (rawDY * config.scale > 2 )  {
      result =  {y: y(gene.start), height: rawDY};
    }
    else {
      height = Math.min( 2 / config.scale, 2)
      result =  { y: y(gene.midpoint) - height / 2,  height: height};
    }

    result.fill = gene.color;
    result.width = config.layout.width;
    result['fill-opacity'] = 0.8;
    result['stroke-dasharray'] = [
      0, config.layout.width, result.height, config.layout.width + result.height];
    result['stroke-width'] = config.layout.width / 5;

    return result;
  }

  var drawGeneLines = function( bandsContainer, chromosome){

    var y = buildYScale();
    var bands = bandsContainer.selectAll('rect.band').data(chromosome.layout.geneBandNodes);
    bands.enter().append('rect').attr({
      'id': function(d){ return d.data.id},
      'class': 'band geneline infobox'
    });

    bands.each( function(band) {
      attribs = generateGeneLineAttr(y, band);
      d3.select(this).attr( attribs );
    } );

    bands.classed( "selected", function(d){
     return d.data.selected
    }
    );

    bands.on('click', function (d) {
      //If user clicks on a gene, toggle gene selection
      if (d.data.type == "gene") {
        log.info('gene annotation click');

        if (d.data.displayed && !d.data.visible && !d.data.hidden) {
          //this gene was annotated automatically - hide it
          d.data.visible = false;
          d.data.hidden = true;
        }
        else {
          //toggle visibility
          d.data.visible = !d.data.visible;
        }

        config.onAnnotationSelectFunction();
      }

      //If user clicks on a cluster of genes, expand that cluster
      if (d.data.type == "geneslist") {
        log.info('geneslist annotation click');

        clusterCurrentlyHidden = d.data.genesList.some( function(gene){
          return !(gene.displayed) } );

        d.data.genesList.forEach( function(gene){
          gene.visible = clusterCurrentlyHidden;
          gene.hidden = !clusterCurrentlyHidden;
        });

        config.onAnnotationSelectFunction();
      }
    });

    bands.exit().remove();
  }

  // An SVG representation of a chromosome with banding data. This is expecting the passed selection to be within an
  // SVG element and to have a list of chromosome JSON objects as its data.
  function my(selection) {
    selection.each(function (d) {
      // build up the selection of chromosome objects
      var chromosomes = d3.select(this).selectAll('.chromosome').data([d]);

      // setup a basic element structure for any new chromosomes
      var enterGroup = chromosomes.enter().append('g').attr('class', 'chromosome');
      enterGroup.append('defs');
      enterGroup.append('rect').classed('background', true);
      enterGroup.append('g').classed('bands_container', true);
      enterGroup.append('rect').classed('outline', true);

      if (config.border) {
        enterGroup.append('rect').classed('border', true);
      }

      // update each of the chromosomes
      chromosomes.each(updateChromosome);

      // remove any missing elements
      chromosomes.exit().remove();
    });
  }

  my.onAnnotationSelectFunction = function (value) {
    if (!arguments.length) {
      return config.onAnnotationSelectFunction;
    }

    config.onAnnotationSelectFunction = value;
    return my;
  };

  my.layout = function (value) {
    if (!arguments.length) {
      return config.layout;
    }

    config.layout = value;
    return my;
  };

  my.drawing = function (value) {
    if (!arguments.length) {
      return config.drawing;
    }

    config.drawing = value;
    return my;
  };

  my.longestChromosome = function (value) {
    if (!arguments.length) {
      return config.longestChromosome;
    }

    config.longestChromosome = value;
    return my;
  };

  my.bands = function (value) {
    if (!arguments.length) {
      return config.bands;
    }

    config.bands = value;
    return my;
  };

  my.scale = function (value) {
    if (!arguments.length) {
      return config.scale;
    }

    config.scale = value;
    return my;
  };

  my.infoBoxManager = function (value) {
    if (!arguments.length) {
      return config.infoBoxManager;
    }

    config.infoBoxManager = value;
    return my;
  };

  return my;
};
<commit_msg>Base chromosome curve radius on width instead of height<commit_after>var GENEMAP = GENEMAP || {};

GENEMAP.Chromosome = function (userConfig) {
  var defaultConfig = {
    border: false,
    longestChromosome: 100,
    bands: "basemap",
    layout: {
      width: 10,
      height: 100,
      x: 0,
      y: 0,
    },
    scale : 1,
    onAnnotationSelectFunction: $.noop(),
    drawing: null,
  };

  var config = _.merge({}, defaultConfig, userConfig);

  var buildYScale = function () {
    return d3.scale.linear().range([0, config.layout.height]).domain([0, config.longestChromosome]);
  };

  // function to update a single chromosome element given the enter + update selection
  // and data. This assumes the basic element structure is in place.
  var updateChromosome = function (chromosome) {
    var y = buildYScale();
    var height = y(chromosome.length);
    var chromosomeGroup = d3.select(this);

    chromosomeGroup.attr({
      id: 'chromosome_' + chromosome.number,
      transform: 'translate(' + config.layout.x + ',' + config.layout.y + ')',
    });

    chromosomeGroup.select('defs').html('')
      .append('mask').attr({
        id: 'chromosome_mask_' + chromosome.number,
      })
      .append('rect').attr({
        class: 'mask_rect',
      });

    chromosomeGroup.select('#chromosome_mask_' + chromosome.number).attr({
      width: config.layout.width,
      height: height,
    });

    var chromosomeShape = {
      width: config.layout.width,
      height: height,
      rx: Math.min(config.layout.width * 0.25, config.layout.height* 0.01),
      ry: Math.min(config.layout.width * 0.25, config.layout.height* 0.01),
    };

    chromosomeGroup.select('.mask_rect').attr(chromosomeShape);
    chromosomeGroup.select('rect.background').attr(chromosomeShape);
    chromosomeGroup.select('rect.outline').attr(chromosomeShape);

    var selection = [];

    var updateSelection = function(){

      var gSelect = chromosomeGroup.selectAll('rect.selection').data(selection);

      gSelect.enter()
        .append('rect')
        .attr( 'class', 'selection')
        .style( {
          'fill' : 'gray',
          'opacity' : 0.2,
        });

      gSelect
        .attr( {
          'x': 0,
          'y': function(d){ return Math.min(d.start, d.end)},
          'width': config.layout.width,
          'height': function(d){ return Math.abs(d.end - d.start)},
        });

      gSelect.exit()
        .remove();
    }

    var drag = d3.behavior.drag()
      .on( 'dragstart', function(event){
        //log.info(y.invert( d3.event.y))
        var pos = d3.mouse(this);
        selection.push({
          'start' : pos[1],
          'end' : pos[1]
        });
        updateSelection();
        d3.event.sourceEvent.stopPropagation();
      })
      .on( 'drag', function(event){
        selection[0].end = d3.event.y;
        updateSelection();
        d3.event.sourceEvent.stopPropagation();
        d3.event.sourceEvent.preventDefault();
      })
      .on( 'dragend', function(event){
        d3.event.sourceEvent.stopPropagation();
        var geneStart = y.invert(selection[0].start);
        var geneEnd = y.invert(selection[0].end);
        if( geneStart > geneEnd){
          var temp = geneStart;
          geneStart = geneEnd;
          geneEnd = temp;
        }

        var nodesToUpdate = chromosome.layout.geneBandNodes.filter( function(node){
          return (node.data.midpoint > geneStart && node.data.midpoint < geneEnd )
        }
        );

        nodesToUpdate.forEach( function(node){
          if (node.data.type == "gene") {
            node.data.visible  = true;
          }
          else if ( node.data.type == "geneslist"){
            node.data.genesList.forEach( function(gene) {
              gene.visible = true;
            });
            }
        } );

        config.onAnnotationSelectFunction();

        selection = [];
        updateSelection();

      });

    chromosomeGroup.select('rect.background')
      .call(drag);

    if (config.border) {
      chromosomeGroup.select('rect.border')
        .attr({
          width: config.layout.width,
          height: config.layout.height,
        });
    }

    // setup the chromosome bands
    var bandsContainer = chromosomeGroup.select('.bands_container');

    var drawBands;
    if (config.bands == "basemap"){
      drawBands = drawBasemapBands;
    }
    else if (config.bands == "genes"){
      drawBands = drawGeneLines;
    }

    drawBands( bandsContainer, chromosome);

    chromosomeGroup.select('.bands_container').style({
      mask: 'url(#chromosome_mask_' + chromosome.number + ')',
    });
  };

  var drawBasemapBands = function( bandsContainer, chromosome){

    var y = buildYScale();
    var bands = bandsContainer.selectAll('rect.band').data(chromosome.bands);
    bands.enter().append('rect').attr('class', 'band');

    bands.attr({
      width: config.layout.width,
      y: function (d) { return y(d.start); },
      height: function (d) { return y(d.end - d.start); },
      fill: function (d) { return d.color; },
    });

    bands.exit().remove();
  }

  var generateGeneLineAttr = function (y, gene){
    var rawHeight = gene.end - gene.start;
    var rawDY = y(rawHeight);

    var result;

    if (rawDY * config.scale > 2 )  {
      result =  {y: y(gene.start), height: rawDY};
    }
    else {
      height = Math.min( 2 / config.scale, 2)
      result =  { y: y(gene.midpoint) - height / 2,  height: height};
    }

    result.fill = gene.color;
    result.width = config.layout.width;
    result['fill-opacity'] = 0.8;
    result['stroke-dasharray'] = [
      0, config.layout.width, result.height, config.layout.width + result.height];
    result['stroke-width'] = config.layout.width / 5;

    return result;
  }

  var drawGeneLines = function( bandsContainer, chromosome){

    var y = buildYScale();
    var bands = bandsContainer.selectAll('rect.band').data(chromosome.layout.geneBandNodes);
    bands.enter().append('rect').attr({
      'id': function(d){ return d.data.id},
      'class': 'band geneline infobox'
    });

    bands.each( function(band) {
      attribs = generateGeneLineAttr(y, band);
      d3.select(this).attr( attribs );
    } );

    bands.classed( "selected", function(d){
     return d.data.selected
    }
    );

    bands.on('click', function (d) {
      //If user clicks on a gene, toggle gene selection
      if (d.data.type == "gene") {
        log.info('gene annotation click');

        if (d.data.displayed && !d.data.visible && !d.data.hidden) {
          //this gene was annotated automatically - hide it
          d.data.visible = false;
          d.data.hidden = true;
        }
        else {
          //toggle visibility
          d.data.visible = !d.data.visible;
        }

        config.onAnnotationSelectFunction();
      }

      //If user clicks on a cluster of genes, expand that cluster
      if (d.data.type == "geneslist") {
        log.info('geneslist annotation click');

        clusterCurrentlyHidden = d.data.genesList.some( function(gene){
          return !(gene.displayed) } );

        d.data.genesList.forEach( function(gene){
          gene.visible = clusterCurrentlyHidden;
          gene.hidden = !clusterCurrentlyHidden;
        });

        config.onAnnotationSelectFunction();
      }
    });

    bands.exit().remove();
  }

  // An SVG representation of a chromosome with banding data. This is expecting the passed selection to be within an
  // SVG element and to have a list of chromosome JSON objects as its data.
  function my(selection) {
    selection.each(function (d) {
      // build up the selection of chromosome objects
      var chromosomes = d3.select(this).selectAll('.chromosome').data([d]);

      // setup a basic element structure for any new chromosomes
      var enterGroup = chromosomes.enter().append('g').attr('class', 'chromosome');
      enterGroup.append('defs');
      enterGroup.append('rect').classed('background', true);
      enterGroup.append('g').classed('bands_container', true);
      enterGroup.append('rect').classed('outline', true);

      if (config.border) {
        enterGroup.append('rect').classed('border', true);
      }

      // update each of the chromosomes
      chromosomes.each(updateChromosome);

      // remove any missing elements
      chromosomes.exit().remove();
    });
  }

  my.onAnnotationSelectFunction = function (value) {
    if (!arguments.length) {
      return config.onAnnotationSelectFunction;
    }

    config.onAnnotationSelectFunction = value;
    return my;
  };

  my.layout = function (value) {
    if (!arguments.length) {
      return config.layout;
    }

    config.layout = value;
    return my;
  };

  my.drawing = function (value) {
    if (!arguments.length) {
      return config.drawing;
    }

    config.drawing = value;
    return my;
  };

  my.longestChromosome = function (value) {
    if (!arguments.length) {
      return config.longestChromosome;
    }

    config.longestChromosome = value;
    return my;
  };

  my.bands = function (value) {
    if (!arguments.length) {
      return config.bands;
    }

    config.bands = value;
    return my;
  };

  my.scale = function (value) {
    if (!arguments.length) {
      return config.scale;
    }

    config.scale = value;
    return my;
  };

  my.infoBoxManager = function (value) {
    if (!arguments.length) {
      return config.infoBoxManager;
    }

    config.infoBoxManager = value;
    return my;
  };

  return my;
};
<|endoftext|>


<commit_before>// Now we are faking email sending a bit
// Here we are manually adding 1200ms wait time to mimic
// Actual time spent on sending emails

var orig = AppConfig.configurePackage;
AppConfig.configurePackage = function(type) {
  if(type == 'email') {
    Meteor._sleepForMs(2300);
  }
  return orig.apply(this, arguments);
};<commit_msg>added new override machanism<commit_after>// nastly hack to prevent to delay email sending
// dev mode email is simply printing it to the console
// so we are going to use that to delay

var Fiber = Npm.require('fibers');
var origWrite = process.stdout.write;
process.stdout.write = function() {
  if(Fiber.current) {
    Meteor._sleepForMs(1000);
  }
  return origWrite.apply(process.stdout, arguments);
};<|endoftext|>


<commit_before>// Mini Ludum Dare 63 Game
// Theme: Fusion
// Code by: Marshall Ehlinger

// Set-up
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);

bgColor = "#000000";

// Graphical Assets
var pcReady = false;
var pcImage = new Image();
pcImage.onload = function() {
	pcReady = true;
};
pcImage.src = "images/pc.png";
pcImageSize = (pcImage.height + pcImage.width) / 2;

// Game Objects
var pc = {
	speed : 500, //in pixels per second
	x : 0,
	y : 0,
	renderX : 0,
	renderY : 0
};

var map = {
	height : 10000,
	width: 10000
};

var stars = [];
var starsOnMap = 10000;

// User Input
var keysPressed = {};

addEventListener("keydown", function(e) {keysPressed[e.keyCode] = true;}, false);
addEventListener("keyup", function(e) {delete keysPressed[e.keyCode];}, false);

var setup = function() {
	pc.x = map.width / 2;
	pc.y = map.height / 2;
	pc.renderX = canvas.width / 2;
	pc.renderY = canvas.height / 2;

	for (i = 0; i < starsOnMap; i++) {
		stars.push([Math.random() * map.width, Math.random() * map.height]);
	}
};

// Update
var update = function (modifier) {
	if (38 in keysPressed) {
		//up
		newY = pc.y - pc.speed * modifier;
		if (newY >= 32) {
			pc.y = newY;
		}
	}
	if (40 in keysPressed) {
		//down
		newY = pc.y + pc.speed * modifier;
		if (newY <= map.height-32) {
			pc.y = newY
		}
	}
	if (37 in keysPressed) {
		// left
		newX = pc.x - pc.speed * modifier;
		if (newX >= 32) {
			pc.x = newX;
		}
	}
	if (39 in keysPressed) {
		// right
		newX = pc.x + pc.speed * modifier;
		if (newX <= map.width-32) {
			pc.x = newX;
		}
	}
};

var isOnScreen = function(objectInSpaceX, objectInSpaceY) {
	if (
		(objectInSpaceX <= pc.x + canvas.width - (canvas.width - pc.renderX))
		&& (objectInSpaceX >= pc.x - canvas.width - pc.renderX)
		&& (objectInSpaceY <= pc.y + canvas.height - (canvas.height - pc.renderY))
		&& (objectInSpaceY >= pc.y - canvas.height - pc.renderY)
		) {
		return true;
	}
};

// Render Everything
var render = function() {
	context.clearRect(0, 0, canvas.width, canvas.height);

	context.fillStyle = bgColor;
	context.fillRect(0, 0, canvas.width, canvas.height);

	for (i = 0; i < stars.length; i++) {
		context.fillStyle = "#FFFFFF";
		if (isOnScreen(stars[i][0], stars[i][1])) {
			context.fillRect(pc.renderX - (pc.x - stars[i][0]) , pc.renderY - (pc.y - stars[i][1]), 1, 1);
		}
	}

	if (pcReady) {
		// render pc in center of view at all times...
		pc.renderX = canvas.width / 2;
		pc.renderY = canvas.height / 2;
		// ... unless pc is near edges of map.
		// NOTE: this is for bounded map. Try wrapping, alternatively??
		if (pc.x >= map.width - (canvas.width / 2)) {
			pc.renderX = canvas.width - (map.width - pc.x);
		} else if (pc.x <= canvas.width / 2) {
			pc.renderX = pc.x;
		}
		if (pc.y >= map.height - (canvas.height / 2)) {
			pc.renderY = canvas.height - (map.height -pc.y);
		} else if (pc.y <= canvas.height / 2) {
			pc.renderY = pc.y;
		}
		context.drawImage(pcImage, pc.renderX - pcImageSize/2, pc.renderY - pcImageSize/2);
	}
};

// Main Loop
var main = function() {
	var MILLISECONDS = 1000;
	var now = Date.now();
	var delta = now - lastUpdate;

	update(delta / MILLISECONDS);
	render();
	lastUpdate = now;
	requestAnimationFrame(main);
};

// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;

/////////////
// EXECUTE //
/////////////
var lastUpdate = Date.now();
setup();
main();<commit_msg>Optimize star rendering every so barely<commit_after>// Mini Ludum Dare 63 Game
// Theme: Fusion
// Code by: Marshall Ehlinger

// Set-up
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);

bgColor = "#000000";

// Graphical Assets
var pcReady = false;
var pcImage = new Image();
pcImage.onload = function() {
	pcReady = true;
};
pcImage.src = "images/pc.png";
pcImageSize = (pcImage.height + pcImage.width) / 2;

// Game Objects
var pc = {
	speed : 500, //in pixels per second
	x : 0,
	y : 0,
	renderX : 0,
	renderY : 0
};

var map = {
	height : 10000,
	width: 10000
};

var stars = [];
var starsOnMap = 10000;

// User Input
var keysPressed = {};

addEventListener("keydown", function(e) {keysPressed[e.keyCode] = true;}, false);
addEventListener("keyup", function(e) {delete keysPressed[e.keyCode];}, false);

var setup = function() {
	pc.x = map.width / 2;
	pc.y = map.height / 2;
	pc.renderX = canvas.width / 2;
	pc.renderY = canvas.height / 2;

	for (i = 0; i < starsOnMap; i++) {
		stars.push([Math.random() * map.width, Math.random() * map.height]);
	}
	stars.sort(function(a, b) {a[0] - b[0]}); // stars' x-values, sorted left->right
};

// Update
var update = function (modifier) {
	if (38 in keysPressed) {
		//up
		newY = pc.y - pc.speed * modifier;
		if (newY >= 32) {
			pc.y = newY;
		}
	}
	if (40 in keysPressed) {
		//down
		newY = pc.y + pc.speed * modifier;
		if (newY <= map.height-32) {
			pc.y = newY
		}
	}
	if (37 in keysPressed) {
		// left
		newX = pc.x - pc.speed * modifier;
		if (newX >= 32) {
			pc.x = newX;
		}
	}
	if (39 in keysPressed) {
		// right
		newX = pc.x + pc.speed * modifier;
		if (newX <= map.width-32) {
			pc.x = newX;
		}
	}
};

var isOnScreen = function(objectInSpaceX, objectInSpaceY) {
	if (
		(objectInSpaceX <= pc.x + canvas.width - (canvas.width - pc.renderX))
		&& (objectInSpaceX >= pc.x - canvas.width - pc.renderX)
		&& (objectInSpaceY <= pc.y + canvas.height - (canvas.height - pc.renderY))
		&& (objectInSpaceY >= pc.y - canvas.height - pc.renderY)
		) {
		return true;
	}
	return false;
};

// Render Everything
var render = function() {
	context.clearRect(0, 0, canvas.width, canvas.height);

	context.fillStyle = bgColor;
	context.fillRect(0, 0, canvas.width, canvas.height);

	context.fillStyle = "#FFFFFF";
	//Below is a phenomenally pointless "optimization," not really.
	xRangeStarRenderCandidates = [(pc.x < stars[stars.length/2][0]) ? 0 : stars.length/2, (pc.x < stars[stars.length/2][0]) ? stars.length / 2 : stars.length];
	for (i = xRangeStarRenderCandidates[0]; i < xRangeStarRenderCandidates[1]; i++) {
		if (isOnScreen(stars[i][0], stars[i][1])) {
			context.fillRect(pc.renderX - (pc.x - stars[i][0]) , pc.renderY - (pc.y - stars[i][1]), 1, 1)
		}
	}

	if (pcReady) {
		// render pc in center of view at all times...
		pc.renderX = canvas.width / 2;
		pc.renderY = canvas.height / 2;
		// ... unless pc is near edges of map.
		// NOTE: this is for bounded map. Try wrapping, alternatively??
		if (pc.x >= map.width - (canvas.width / 2)) {
			pc.renderX = canvas.width - (map.width - pc.x);
		} else if (pc.x <= canvas.width / 2) {
			pc.renderX = pc.x;
		}
		if (pc.y >= map.height - (canvas.height / 2)) {
			pc.renderY = canvas.height - (map.height -pc.y);
		} else if (pc.y <= canvas.height / 2) {
			pc.renderY = pc.y;
		}
		context.drawImage(pcImage, pc.renderX - pcImageSize/2, pc.renderY - pcImageSize/2);
	}
};

// Main Loop
var main = function() {
	var MILLISECONDS = 1000;
	var now = Date.now();
	var delta = now - lastUpdate;

	update(delta / MILLISECONDS);
	render();
	lastUpdate = now;
	requestAnimationFrame(main);
};

// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;

/////////////
// EXECUTE //
/////////////
var lastUpdate = Date.now();
setup();
main();<|endoftext|>


<commit_before>const listeners = [];
const orientation = {
  device: {},
  screen: window.orientation || 0,
  supported: !!window.DeviceMotionEvent,
  update: false,
};

const SCREEN_ORIENTATION_MAP = {
  'landscape-primary': 90,
  'landscape-secondary': -90,
  'portrait-secondary': 180,
  'portrait-primary': 0,
};

function noOp() {}

function onDeviceOrientationChangeEvent(evt) {
  orientation.device = evt;
  if (!Number.isFinite(evt.alpha)) {
    orientation.supported = false;
  }
}

function onScreenOrientationChangeEvent() {
  orientation.screen = SCREEN_ORIENTATION_MAP[window.screen.orientation || window.screen.mozOrientation] || window.orientation || 0;
}

function addWindowListeners() {
  window.addEventListener('orientationchange', onScreenOrientationChangeEvent, false);
  window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
  orientation.update = true;
  listeners.filter(i => !!i).map(i => i.renderWindowInteractor.requestAnimation());
}

function removeWindowListeners() {
  window.removeEventListener('orientationchange', onScreenOrientationChangeEvent, false);
  window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
  orientation.update = false;
  listeners.filter(i => !!i).map(i => i.renderWindowInteractor.cancelAnimation());
}

function addCameraToSynchronize(renderWindowInteractor, camera, render = noOp) {
  function onAnimation() {
    if (orientation.update) {
      const { alpha, beta, gamma } = orientation.device;
      const screen = orientation.screen;
      camera.setDeviceAngles(alpha, beta, gamma, screen);
      render();
    }
  }

  const subscription = renderWindowInteractor.onAnimation(onAnimation);
  const listener = { subscription, renderWindowInteractor };
  const listenerId = listeners.length;
  listeners.push(listener);

  if (orientation.update) {
    listener.renderWindowInteractor.requestAnimation();
  }

  return listenerId;
}

function removeCameraToSynchronize(id, cancelAnimation = true) {
  const listener = listeners[id];
  if (listener) {
    listener.subscription.unsubscribe();
    if (cancelAnimation) {
      listener.renderWindowInteractor.cancelAnimation();
    }
  }
  listeners[id] = null;
}

function isDeviceOrientationSupported() {
  return orientation.supported;
}

export default {
  addCameraToSynchronize,
  addWindowListeners,
  isDeviceOrientationSupported,
  removeCameraToSynchronize,
  removeWindowListeners,
};
<commit_msg>refactor(DeviceOrientationToCamera): Better code style<commit_after>const listeners = [];
const orientation = {
  device: {},
  screen: window.orientation || 0,
  supported: !!window.DeviceMotionEvent,
  update: false,
};

const SCREEN_ORIENTATION_MAP = {
  'landscape-primary': 90,
  'landscape-secondary': -90,
  'portrait-secondary': 180,
  'portrait-primary': 0,
};

function noOp() {}

function onDeviceOrientationChangeEvent(evt) {
  orientation.device = evt;
  if (!Number.isFinite(evt.alpha)) {
    orientation.supported = false;
  }
}

function onScreenOrientationChangeEvent() {
  orientation.screen = SCREEN_ORIENTATION_MAP[window.screen.orientation || window.screen.mozOrientation] || window.orientation || 0;
}

function addWindowListeners() {
  window.addEventListener('orientationchange', onScreenOrientationChangeEvent, false);
  window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
  orientation.update = true;
  listeners.filter(i => !!i).forEach(i => i.renderWindowInteractor.requestAnimation());
}

function removeWindowListeners() {
  window.removeEventListener('orientationchange', onScreenOrientationChangeEvent, false);
  window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
  orientation.update = false;
  listeners.filter(i => !!i).forEach(i => i.renderWindowInteractor.cancelAnimation());
}

function addCameraToSynchronize(renderWindowInteractor, camera, render = noOp) {
  function onAnimation() {
    if (orientation.update) {
      const { alpha, beta, gamma } = orientation.device;
      const screen = orientation.screen;
      camera.setDeviceAngles(alpha, beta, gamma, screen);
      render();
    }
  }

  const subscription = renderWindowInteractor.onAnimation(onAnimation);
  const listener = { subscription, renderWindowInteractor };
  const listenerId = listeners.length;
  listeners.push(listener);

  if (orientation.update) {
    listener.renderWindowInteractor.requestAnimation();
  }

  return listenerId;
}

function removeCameraToSynchronize(id, cancelAnimation = true) {
  const listener = listeners[id];
  if (listener) {
    listener.subscription.unsubscribe();
    if (cancelAnimation) {
      listener.renderWindowInteractor.cancelAnimation();
    }
  }
  listeners[id] = null;
}

function isDeviceOrientationSupported() {
  return orientation.supported;
}

export default {
  addCameraToSynchronize,
  addWindowListeners,
  isDeviceOrientationSupported,
  removeCameraToSynchronize,
  removeWindowListeners,
};
<|endoftext|>


<commit_before>
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var CMConstants = require('../constants/CMConstants');
var assign = require('object-assign');

var CHANGE_EVENT = 'change';

var _contacts = [];
var _editContact = {};

// saving new contact
function create(newContact) {
  var id = Math.round(Math.random() * 9999999);
  _contacts[id] = {
    id: id,
    name: newContact.name,
    phone: newContact.phone,
    email: newContact.email,
    avatar: newContact.avatar
  };
}

// sending edit id to controller view
function edit(contact) {
  _editContact = {
    id: contact.id,
    name: contact.name,
    phone: contact.phone,
    email: contact.email,
    avatar: contact.avatar
  };
}

// saving edited contact
function save(contact) {
  _contacts[contact.id] = {
    id: contact.id,
    name: contact.name,
    phone: contact.phone,
    email: contact.email,
    avatar: contact.avatar
  };
}

var CMStore = assign({}, EventEmitter.prototype, {
  /**
   * Get the entire Contacts.
   * @return {object}
   */
  getEditContact: function() {
    return _editContact;
  },
  getAll: function() {
    return _contacts;
  },

  emitChange: function() {
    this.emit(CHANGE_EVENT);
  },

  /**
   * @param {function} callback
   */
  addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
  },

  /**
   * @param {function} callback
   */
  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  }
});

// Register callback to handle all updates
AppDispatcher.register(function(action) {
  var text;

  switch(action.actionType) {
    case CMConstants.CM_CREATE:
      text = action.name.trim();
      if (text !== '') {
        create(action);
        CMStore.emitChange();
      }
      break;

    case CMConstants.CM_EDIT:
      edit(action);
      CMStore.emitChange();
      break;

    case CMConstants.CM_SAVE:
      save(action);
      CMStore.emitChange();
      break;

    default:
      // no op
  }
});

module.exports = CMStore;<commit_msg>changing id from random to incremental<commit_after>
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var CMConstants = require('../constants/CMConstants');
var assign = require('object-assign');

var CHANGE_EVENT = 'change';

var _contacts = [];
var _editContact = {};

// will be used to incremental id for contacts
var currentId = 0;

// saving new contact
function create(newContact) {
  _contacts[currentId] = {
    id: currentId,
    name: newContact.name,
    phone: newContact.phone,
    email: newContact.email,
    avatar: newContact.avatar
  };
  currentId+=1;
}

// sending edit id to controller view
function edit(contact) {
  _editContact = {
    id: contact.id,
    name: contact.name,
    phone: contact.phone,
    email: contact.email,
    avatar: contact.avatar
  };
}

// saving edited contact
function save(contact) {
  _contacts[contact.id] = {
    id: contact.id,
    name: contact.name,
    phone: contact.phone,
    email: contact.email,
    avatar: contact.avatar
  };
}

var CMStore = assign({}, EventEmitter.prototype, {
  /**
   * Get the entire Contacts.
   * @return {object}
   */
  getEditContact: function() {
    return _editContact;
  },
  getAll: function() {
    return _contacts;
  },

  emitChange: function() {
    this.emit(CHANGE_EVENT);
  },

  /**
   * @param {function} callback
   */
  addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
  },

  /**
   * @param {function} callback
   */
  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  }
});

// Register callback to handle all updates
AppDispatcher.register(function(action) {
  var text;

  switch(action.actionType) {
    case CMConstants.CM_CREATE:
      text = action.name.trim();
      if (text !== '') {
        create(action);
        CMStore.emitChange();
      }
      break;

    case CMConstants.CM_EDIT:
      edit(action);
      CMStore.emitChange();
      break;

    case CMConstants.CM_SAVE:
      save(action);
      CMStore.emitChange();
      break;

    default:
      // no op
  }
});

module.exports = CMStore;<|endoftext|>


<commit_before>/**
 * Cangraph
 *
 * Graphing and function plotting for the HTML5 canvas. Main function plotting
 * engine was taken from the link below and modified.
 *
 * @link http://www.javascripter.net/faq/plotafunctiongraph.htm
 */
(function ($) {

    /**
     * Constructor and initialization
     *
     * @class Cangraph
     *
     * @param {String} canvasId The canvas element to draw on
     * @param {Object} options Allows us to change defaults upon instantiation
     */
    function Cangraph(canvasId, options) {
        var defaults = {
            axes: {
                xOffset: 0,
                yOffset: 0,
                scale: 40,
                showNegativeX: true,
                strokeColor: '#000000',
                showXAxis: true,
                showYAxis: true,
                markings: {
                    showX: true,
                    showY: true,
                    xInterval: 10,
                    xHeight: 5
                }
            },
            graph: {
                strokeColor: '#1fcd38',
                lineWidth: '1',
                scale: 4
            }
        };
        var canvas;

        // Set canvas and context
        this.set('canvasId', canvasId);
        canvas = document.getElementById(this.canvasId);
        this.set('canvas', canvas);
        this.setContext();

        // Merge defaults with passed in options
        this.options = options || {};
        this.options = $.extend(true, {}, defaults, this.options);

        this.setDerivedAxesProperties();
        this.setDerivedGraphProperties();
    }

    Cangraph.prototype.set = function (name, value) {
        if (value === null || typeof value === 'undefined') {
            console.log(name, 'is undefined or null!');

            return false;
        }

        this[name] = value;
    };

    Cangraph.prototype.setContext = function () {
        var context = this.canvas.getContext('2d');

        this.set('context', context);
    };

    Cangraph.prototype.setDerivedAxesProperties = function () {
        this.set('x0', this.options.axes.xOffset + .5 * this.canvas.width);
        this.set('y0', this.options.axes.yOffset + .5 * this.canvas.height);

        if (this.options.axes.showNegativeX) {
            this.set('xMin', 0);
        } else {
            this.set('xMin', this.x0);
        }
    };

    Cangraph.prototype.setDerivedGraphProperties = function () {
        this.set('graphPlottingMax', Math.round((this.canvas.width - this.x0) / this.options.graph.scale));

        if (this.options.axes.showNegativeX) {
            this.set('graphPlottingMin', Math.round(-this.x0 / this.options.graph.scale));
        } else {
            this.set('graphPlottingMin', 0);
        }
    };

    Cangraph.prototype.drawAxes = function (fx) {
        this.context.beginPath();
        this.context.strokeStyle = this.options.axes.strokeColor;

        if (this.options.axes.showXAxis) {
            this.context.moveTo(this.xMin, this.y0);
            this.context.lineTo(this.canvas.width, this.y0);
        }

        if (this.options.axes.showYAxis) {
            this.context.moveTo(this.x0, 0);
            this.context.lineTo(this.x0, this.canvas.height);
        }

        this.drawAxesMarkingsHelper();
        this.context.stroke();
    };

    Cangraph.prototype.drawAxesMarkingsHelper = function () {
        var iX;
        var iXMax = Math.ceil(this.canvas.width - this.xMin);
        var iXMaxScale = Math.ceil((this.canvas.width - this.xMin) / this.options.axes.markings.xInterval);

        if (this.options.axes.markings.showX) {
            for (iX = Math.floor(this.xMin); iX <= iXMax; iX += 1) {
                if (iX % iXMaxScale === 0) {
                    this.context.moveTo(iX, this.y0 + this.options.axes.markings.xHeight);
                    this.context.lineTo(iX, this.y0 - this.options.axes.markings.xHeight);
                    this.context.strokeStyle = this.options.axes.strokeColor;
                }
            }
        }
    };

    Cangraph.prototype.drawGraph = function (fx) {
        var x;
        var y;
        var i;

        this.context.beginPath();
        this.context.lineWidth = this.options.graph.lineWidth;
        this.context.strokeStyle = this.options.graph.strokeColor;

        for (i = this.graphPlottingMin; i <= this.graphPlottingMax; i += 1) {
            x = this.options.graph.scale * i;
            y = this.options.axes.scale * fx(x / this.options.axes.scale);

            if (i === this.graphPlottingMin) {
                this.context.moveTo(this.x0 + x, this.y0 - y);
            } else {
                this.context.lineTo(this.x0 + x, this.y0 - y);
            }
        }

        this.context.stroke();
    };

    // Attach object to global namespace
    this.Cangraph = Cangraph;
}).call(this, $);<commit_msg>Remove unnecessary argument<commit_after>/**
 * Cangraph
 *
 * Graphing and function plotting for the HTML5 canvas. Main function plotting
 * engine was taken from the link below and modified.
 *
 * @link http://www.javascripter.net/faq/plotafunctiongraph.htm
 */
(function ($) {

    /**
     * Constructor and initialization
     *
     * @class Cangraph
     *
     * @param {String} canvasId The canvas element to draw on
     * @param {Object} options Allows us to change defaults upon instantiation
     */
    function Cangraph(canvasId, options) {
        var defaults = {
            axes: {
                xOffset: 0,
                yOffset: 0,
                scale: 40,
                showNegativeX: true,
                strokeColor: '#000000',
                showXAxis: true,
                showYAxis: true,
                markings: {
                    showX: true,
                    showY: true,
                    xInterval: 10,
                    xHeight: 5
                }
            },
            graph: {
                strokeColor: '#1fcd38',
                lineWidth: '1',
                scale: 4
            }
        };
        var canvas;

        // Set canvas and context
        this.set('canvasId', canvasId);
        canvas = document.getElementById(this.canvasId);
        this.set('canvas', canvas);
        this.setContext();

        // Merge defaults with passed in options
        this.options = options || {};
        this.options = $.extend(true, {}, defaults, this.options);

        this.setDerivedAxesProperties();
        this.setDerivedGraphProperties();
    }

    Cangraph.prototype.set = function (name, value) {
        if (value === null || typeof value === 'undefined') {
            console.log(name, 'is undefined or null!');

            return false;
        }

        this[name] = value;
    };

    Cangraph.prototype.setContext = function () {
        var context = this.canvas.getContext('2d');

        this.set('context', context);
    };

    Cangraph.prototype.setDerivedAxesProperties = function () {
        this.set('x0', this.options.axes.xOffset + .5 * this.canvas.width);
        this.set('y0', this.options.axes.yOffset + .5 * this.canvas.height);

        if (this.options.axes.showNegativeX) {
            this.set('xMin', 0);
        } else {
            this.set('xMin', this.x0);
        }
    };

    Cangraph.prototype.setDerivedGraphProperties = function () {
        this.set('graphPlottingMax', Math.round((this.canvas.width - this.x0) / this.options.graph.scale));

        if (this.options.axes.showNegativeX) {
            this.set('graphPlottingMin', Math.round(-this.x0 / this.options.graph.scale));
        } else {
            this.set('graphPlottingMin', 0);
        }
    };

    Cangraph.prototype.drawAxes = function () {
        this.context.beginPath();
        this.context.strokeStyle = this.options.axes.strokeColor;

        if (this.options.axes.showXAxis) {
            this.context.moveTo(this.xMin, this.y0);
            this.context.lineTo(this.canvas.width, this.y0);
        }

        if (this.options.axes.showYAxis) {
            this.context.moveTo(this.x0, 0);
            this.context.lineTo(this.x0, this.canvas.height);
        }

        this.drawAxesMarkingsHelper();
        this.context.stroke();
    };

    Cangraph.prototype.drawAxesMarkingsHelper = function () {
        var iX;
        var iXMax = Math.ceil(this.canvas.width - this.xMin);
        var iXMaxScale = Math.ceil((this.canvas.width - this.xMin) / this.options.axes.markings.xInterval);

        if (this.options.axes.markings.showX) {
            for (iX = Math.floor(this.xMin); iX <= iXMax; iX += 1) {
                if (iX % iXMaxScale === 0) {
                    this.context.moveTo(iX, this.y0 + this.options.axes.markings.xHeight);
                    this.context.lineTo(iX, this.y0 - this.options.axes.markings.xHeight);
                    this.context.strokeStyle = this.options.axes.strokeColor;
                }
            }
        }
    };

    Cangraph.prototype.drawGraph = function (fx) {
        var x;
        var y;
        var i;

        this.context.beginPath();
        this.context.lineWidth = this.options.graph.lineWidth;
        this.context.strokeStyle = this.options.graph.strokeColor;

        for (i = this.graphPlottingMin; i <= this.graphPlottingMax; i += 1) {
            x = this.options.graph.scale * i;
            y = this.options.axes.scale * fx(x / this.options.axes.scale);

            if (i === this.graphPlottingMin) {
                this.context.moveTo(this.x0 + x, this.y0 - y);
            } else {
                this.context.lineTo(this.x0 + x, this.y0 - y);
            }
        }

        this.context.stroke();
    };

    // Attach object to global namespace
    this.Cangraph = Cangraph;
}).call(this, $);<|endoftext|>


<commit_before>var
    http = require("http")
    url = require("url"),
    events = require('events')
    util = require('util'),
    fs = require('fs'),
    crypto = require('crypto');

var currentUsers = [];
var port = 8080;

/* If the EventEmitter does not have a 'once' method (because it's an older
 * version), we're monkeypatching it in
 */
if (events.EventEmitter.prototype.once === undefined) {

    events.EventEmitter.prototype.once = function(event, listener) {

        var self = this;
        this.on(event, function() {

            listener.apply(self, arguments);
            self.removeListener(event,listener);

        });

    };

}

/**
 * The ChatEvents object keeps track of all events happening
 * on the chat. It also assigns a sequence number and allows clients
 * to fetch previous (missed) events.
 *
 * Only events with the name 'broadcast' are retained.
 */
function ChatEvents() {

    events.EventEmitter.call(this);

}

util.inherits(ChatEvents, events.EventEmitter);

ChatEvents.prototype.sequence = 0;
ChatEvents.prototype.previousEvents = [];
ChatEvents.prototype.emit = function(eventName, eventData) {

    if (eventName!=='broadcast') {
        return ChatEvents.super_.prototype.emit.apply(this, arguments);
    }

    this.sequence++;
    eventData.sequence = this.sequence;
    eventData.dateTime = new Date();
    console.log("Event is pushed with sequence: " + this.sequence);
    this.previousEvents.push(eventData);

    ChatEvents.super_.prototype.emit.apply(this,[eventName,eventData]);

}

ChatEvents.prototype.getPreviousEvents = function(since) {

    if (!since) since = 0;
    return this.previousEvents.filter(function(elem) {
        return elem.sequence > since;
    });

}

var chatEvents = new ChatEvents();

/** Helper functions for 'currentUsers' **/
function updateLastSeen(userInfo, longPoll) {

    console.log('updateLastSeen: ' + userInfo.nickName);
    var found = null;
    for(var ii=0; ii < currentUsers.length; ii++) {
        if (currentUsers[ii].nickName === userInfo.nickName) {
            found = currentUsers[ii];
            break;
        }
    }

    if (found) {
        console.log('found');
        found.lastSeen = new Date();
        if (longPoll !== undefined) {
            found.longPoll = longPoll;
        }
    } else {
        console.log('not found');
        userInfo.lastSeen = new Date();
        if (longPoll !== undefined) {
            userInfo.longPoll = longPoll;
        }
        currentUsers.push(userInfo);
        chatEvents.emit('broadcast', {
            type: 'join',
            nickName: userInfo.nickName?userInfo.nickName:'ERROR',
            email: userInfo.email,
            gravatar : "http://www.gravatar.com/avatar/" + crypto.createHash('md5').update(userInfo.email).digest('hex')
        });
    }

};

setInterval(function() {

    console.log('Cleanup sequence. Currently there are ' + currentUsers.length + ' users online.');

    var removeUsers = [];
    for(var ii=0; ii < currentUsers.length; ii++) {

        var user = currentUsers[ii];

        var time = currentUsers[ii].lastSeen.getTime();
        var current = new Date().getTime();

        // Timeout = 60 seconds
        var timeout = 60;
        if (user.longPoll) {
            timeout = 600;
        }

        console.log(user.nickName + ' ' + (time + (timeout * 1000) - current));

        if(time + (timeout * 1000) < current) {
            removeUsers.push(ii);

            chatEvents.emit('broadcast', {
                type: 'part',
                nickName: user.nickName,
                email: user.email
            });

        }

    }

    console.log(removeUsers.length + ' users are cleaned up');
    console.log(removeUsers);
    currentUsers = currentUsers.filter(function(item,key) {
        return (removeUsers.indexOf(key) === -1);
    });

},6000);

/* Logging */
chatEvents.on('broadcast', function(ev) {

    switch(ev.type) {

        case 'join' :
            console.log('JOIN: ' + ev.nickName);
            break;

        case 'part' :
            console.log('PART: ' + ev.nickName);
            break;

        case 'message' :
            console.log('Message: ' + ev.nickName + ': ' + ev.message);
            break;

    }

});

/**
 * Creates the chat server
 */
http.createServer(function(request, response) {

    console.log(request.method + ' ' + request.url);

    var urlParts = url.parse(request.url, true);

    // I know.. ugly..
    if (urlParts.pathname.indexOf('/client/') === 0) {
        var subPath = urlParts.pathname.slice(8);
        urlParts.pathname = '/client';
    }

    switch(urlParts.pathname) {

        case '/message' :
            if (!urlParts.query || !urlParts.query.message) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'message' GET variable"}));
                return;
            }
            if (!urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }

            updateLastSeen({
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
            });
            chatEvents.emit('broadcast', {
                type: 'message',
                message: urlParts.query.message,
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
                gravatar : "http://www.gravatar.com/avatar/" + crypto.createHash('md5').update(urlParts.query.email).digest('hex')
            });

            response.writeHead(200);
            response.end('Thanks for your message!');
            break;

        case '/join' :
            if (!urlParts.query || !urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }

            updateLastSeen({
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
            });
            response.writeHead(200);
            response.end('Thanks for joining!');
            break;

        case '/eventpoll' :
            if (!urlParts.query || !urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }
            var since = 0;
            if (urlParts.query && urlParts.query.since) {
                since = urlParts.query.since;
            }
            var events = chatEvents.getPreviousEvents(since);
            // If there were events, we'll return them right away
            if (events.length > 0) {
                response.writeHead(200, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify(events));

                updateLastSeen({
                    nickName: urlParts.query.nickName,
                    email: urlParts.query.email,
                },false);

            } else {
                updateLastSeen({
                    nickName: urlParts.query.nickName,
                    email: urlParts.query.email
                },true);
                var ref = chatEvents.once('broadcast', function(ev) {

                    updateLastSeen({
                        nickName: urlParts.query.nickName,
                        email: urlParts.query.email
                    },false);

                    response.writeHead(200, {'Content-Type' : 'application/json'});
                    response.end(JSON.stringify([ev]));
                });
            }
            break;
        case '/client' :
            fs.readFile('../client/' + subPath, function(error, content) {
                if (error) {
                    response.writeHead(500, {'Content-Type' : 'text/plain' });
                    response.end('Error opening file :S');
                } else {
                    var extension = subPath.slice(subPath.lastIndexOf('.'));
                    var mime = 'text/plain';
                    switch(extension) {
                        case '.html' :
                            mime = 'text/html';
                            break;
                        case '.js' :
                            mime = 'text/javascript';
                            break;
                        case '.css' :
                            mime = 'text/css';
                            break;
                    }

                    response.writeHead(200, {'Content-Type' : mime});
                    response.end(content);
                }

            });
            break;

        default :
            response.writeHead(404, {'Content-Type' : 'text/plain'});
            response.end('404 Not Found!\n\nThis url is not recognized');
            break;

    }

}).listen(port);

console.log('ChatApp Server v0.2 - (c)2011 by Evert Pot');
console.log('Now listening for connections on port ' + port);
<commit_msg>Send proper content-type with success responses, or Firefox will complain about syntax errors (it expects XML for some reason)<commit_after>var
    http = require("http")
    url = require("url"),
    events = require('events')
    util = require('util'),
    fs = require('fs'),
    crypto = require('crypto');

var currentUsers = [];
var port = 8080;

/* If the EventEmitter does not have a 'once' method (because it's an older
 * version), we're monkeypatching it in
 */
if (events.EventEmitter.prototype.once === undefined) {

    events.EventEmitter.prototype.once = function(event, listener) {

        var self = this;
        this.on(event, function() {

            listener.apply(self, arguments);
            self.removeListener(event,listener);

        });

    };

}

/**
 * The ChatEvents object keeps track of all events happening
 * on the chat. It also assigns a sequence number and allows clients
 * to fetch previous (missed) events.
 *
 * Only events with the name 'broadcast' are retained.
 */
function ChatEvents() {

    events.EventEmitter.call(this);

}

util.inherits(ChatEvents, events.EventEmitter);

ChatEvents.prototype.sequence = 0;
ChatEvents.prototype.previousEvents = [];
ChatEvents.prototype.emit = function(eventName, eventData) {

    if (eventName!=='broadcast') {
        return ChatEvents.super_.prototype.emit.apply(this, arguments);
    }

    this.sequence++;
    eventData.sequence = this.sequence;
    eventData.dateTime = new Date();
    console.log("Event is pushed with sequence: " + this.sequence);
    this.previousEvents.push(eventData);

    ChatEvents.super_.prototype.emit.apply(this,[eventName,eventData]);

}

ChatEvents.prototype.getPreviousEvents = function(since) {

    if (!since) since = 0;
    return this.previousEvents.filter(function(elem) {
        return elem.sequence > since;
    });

}

var chatEvents = new ChatEvents();

/** Helper functions for 'currentUsers' **/
function updateLastSeen(userInfo, longPoll) {

    console.log('updateLastSeen: ' + userInfo.nickName);
    var found = null;
    for(var ii=0; ii < currentUsers.length; ii++) {
        if (currentUsers[ii].nickName === userInfo.nickName) {
            found = currentUsers[ii];
            break;
        }
    }

    if (found) {
        console.log('found');
        found.lastSeen = new Date();
        if (longPoll !== undefined) {
            found.longPoll = longPoll;
        }
    } else {
        console.log('not found');
        userInfo.lastSeen = new Date();
        if (longPoll !== undefined) {
            userInfo.longPoll = longPoll;
        }
        currentUsers.push(userInfo);
        chatEvents.emit('broadcast', {
            type: 'join',
            nickName: userInfo.nickName?userInfo.nickName:'ERROR',
            email: userInfo.email,
            gravatar : "http://www.gravatar.com/avatar/" + crypto.createHash('md5').update(userInfo.email).digest('hex')
        });
    }

};

setInterval(function() {

    console.log('Cleanup sequence. Currently there are ' + currentUsers.length + ' users online.');

    var removeUsers = [];
    for(var ii=0; ii < currentUsers.length; ii++) {

        var user = currentUsers[ii];

        var time = currentUsers[ii].lastSeen.getTime();
        var current = new Date().getTime();

        // Timeout = 60 seconds
        var timeout = 60;
        if (user.longPoll) {
            timeout = 600;
        }

        console.log(user.nickName + ' ' + (time + (timeout * 1000) - current));

        if(time + (timeout * 1000) < current) {
            removeUsers.push(ii);

            chatEvents.emit('broadcast', {
                type: 'part',
                nickName: user.nickName,
                email: user.email
            });

        }

    }

    console.log(removeUsers.length + ' users are cleaned up');
    console.log(removeUsers);
    currentUsers = currentUsers.filter(function(item,key) {
        return (removeUsers.indexOf(key) === -1);
    });

},6000);

/* Logging */
chatEvents.on('broadcast', function(ev) {

    switch(ev.type) {

        case 'join' :
            console.log('JOIN: ' + ev.nickName);
            break;

        case 'part' :
            console.log('PART: ' + ev.nickName);
            break;

        case 'message' :
            console.log('Message: ' + ev.nickName + ': ' + ev.message);
            break;

    }

});

/**
 * Creates the chat server
 */
http.createServer(function(request, response) {

    console.log(request.method + ' ' + request.url);

    var urlParts = url.parse(request.url, true);

    // I know.. ugly..
    if (urlParts.pathname.indexOf('/client/') === 0) {
        var subPath = urlParts.pathname.slice(8);
        urlParts.pathname = '/client';
    }

    switch(urlParts.pathname) {

        case '/message' :
            if (!urlParts.query || !urlParts.query.message) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'message' GET variable"}));
                return;
            }
            if (!urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }

            updateLastSeen({
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
            });
            chatEvents.emit('broadcast', {
                type: 'message',
                message: urlParts.query.message,
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
                gravatar : "http://www.gravatar.com/avatar/" + crypto.createHash('md5').update(urlParts.query.email).digest('hex')
            });

            response.writeHead(200, {'Content-Type' : 'text/plain'});
            response.end('Thanks for your message!');
            break;

        case '/join' :
            if (!urlParts.query || !urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }

            updateLastSeen({
                nickName: urlParts.query.nickName,
                email: urlParts.query.email,
            });
            response.writeHead(200, {'Content-Type' : 'text/plain'});
            response.end('Thanks for joining!');
            break;

        case '/eventpoll' :
            if (!urlParts.query || !urlParts.query.nickName) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'nickName' GET variable"}));
                return;
            }
            if (!urlParts.query.email) {
                response.writeHead(400, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify({ code : 400, info: "You must specify the 'email' GET variable"}));
                return;
            }
            var since = 0;
            if (urlParts.query && urlParts.query.since) {
                since = urlParts.query.since;
            }
            var events = chatEvents.getPreviousEvents(since);
            // If there were events, we'll return them right away
            if (events.length > 0) {
                response.writeHead(200, {'Content-Type' : 'application/json'});
                response.end(JSON.stringify(events));

                updateLastSeen({
                    nickName: urlParts.query.nickName,
                    email: urlParts.query.email,
                },false);

            } else {
                updateLastSeen({
                    nickName: urlParts.query.nickName,
                    email: urlParts.query.email
                },true);
                var ref = chatEvents.once('broadcast', function(ev) {

                    updateLastSeen({
                        nickName: urlParts.query.nickName,
                        email: urlParts.query.email
                    },false);

                    response.writeHead(200, {'Content-Type' : 'application/json'});
                    response.end(JSON.stringify([ev]));
                });
            }
            break;
        case '/client' :
            fs.readFile('../client/' + subPath, function(error, content) {
                if (error) {
                    response.writeHead(500, {'Content-Type' : 'text/plain' });
                    response.end('Error opening file :S');
                } else {
                    var extension = subPath.slice(subPath.lastIndexOf('.'));
                    var mime = 'text/plain';
                    switch(extension) {
                        case '.html' :
                            mime = 'text/html';
                            break;
                        case '.js' :
                            mime = 'text/javascript';
                            break;
                        case '.css' :
                            mime = 'text/css';
                            break;
                    }

                    response.writeHead(200, {'Content-Type' : mime});
                    response.end(content);
                }

            });
            break;

        default :
            response.writeHead(404, {'Content-Type' : 'text/plain'});
            response.end('404 Not Found!\n\nThis url is not recognized');
            break;

    }

}).listen(port);

console.log('ChatApp Server v0.2 - (c)2011 by Evert Pot');
console.log('Now listening for connections on port ' + port);
<|endoftext|>


<commit_before>/**
 * @file This sample demonstrates using wConsequence for synchronization the several asynchronous process by example of
 * sleeping barber problem. In this example appending clients in barber shop and servicing them by barber are
 * asynchronous.
 */

if( typeof module !== 'undefined' )
{
  var _ = require( 'wTools' );
  /* require( 'wConsequence' ); */
  require( '../staging/abase/syn/Consequence.s' );
  var TheDiningPhilosophersProblem = require( './TheDiningPhilosophersProblem.js' );
}

var con = new wConsequence();

function STheDiningPhilosophersProblem () {};

STheDiningPhilosophersProblem.prototype = Object.create( TheDiningPhilosophersProblem, {
  informAboutHungry:
  {
    value: function( c ) {
      console.log( '>>' );
      console.log( 'philosopher want to eat : ' + c.philosopher.name + _.timeSpent( ' ',c.time ) );
      tryToEat( c );
    }
  }
} );

var theDiningPhilosophersProblem = new STheDiningPhilosophersProblem();
theDiningPhilosophersProblem.simulateHungryEvent();

var forks = [
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
];

function tryToEat(c)
{
  // draft
  var name = c.philosopher.name;
  takeFork(forks[ name - 1 ] );
  takeFork(forks[ name % 5 ] );
  eat( c.philosopher.duration );

  putFork(forks[ name - 1 ] );
  putFork(forks[ name % 5 ] );

}

function takeFork(fork) {
  return fork.got();
}

function putFork(fork) {
  return fork.give();
}

function eat( duration ) {}<commit_msg>beautify TheDiningPhilosophersSolution.js a bit<commit_after>/**
 * @file This sample demonstrates using wConsequence for synchronization the several asynchronous process by example of
 * sleeping barber problem. In this example appending clients in barber shop and servicing them by barber are
 * asynchronous.
 */

if( typeof module !== 'undefined' )
{
  var _ = require( 'wTools' );
  /* require( 'wConsequence' ); */
  require( '../staging/abase/syn/Consequence.s' );
  var TheDiningPhilosophersProblem = require( './TheDiningPhilosophersProblem.js' );
}

var con = new wConsequence();

function STheDiningPhilosophersProblem () {};

STheDiningPhilosophersProblem.prototype = Object.create( TheDiningPhilosophersProblem, {
  informAboutHungry :
  {
    value : function( c )
    {
      console.log( '>>' );
      console.log( 'philosopher want to eat : ' + c.philosopher.name + _.timeSpent( ' ',c.time ) );
      tryToEat( c );
    }
  }
} );

var theDiningPhilosophersProblem = new STheDiningPhilosophersProblem();
theDiningPhilosophersProblem.simulateHungryEvent();

var forks =
[
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
  wConsequence().give(),
];

function tryToEat(c)
{
  // draft
  var name = c.philosopher.name;
  takeFork(forks[ name - 1 ] );
  takeFork(forks[ name % 5 ] );
  eat( c.philosopher.duration );

  putFork(forks[ name - 1 ] );
  putFork(forks[ name % 5 ] );

}

function takeFork(fork) {
  return fork.got();
}

function putFork(fork) {
  return fork.give();
}

function eat( duration ) {}
<|endoftext|>