<commit_before>var path						= require('path'),
		hound						= require('hound'),
		exif						= require('exif2'),
		http						= require('http'),
		MediaController	= require('./media');

/**
	* MediaTasks tasks watch the media directory for new, changed, or deleted images
	* and videos. It reads exif data from new media, converts the data into
	* something usable, adds it to the database, and passes the passes it to the
	* media controller for processing. Deleted media is removed from the database.
	*
	* @namespace MediaTasks
	*/

(function () {
	var MediaTasks;

	MediaTasks = (function (MediaTasks) {
		'use strict';

		/**
			* Watches specified directory for new, changed, or deleted media and
			* calls the appropriate funtions to handle them.
			*
			* @param {string} directory The directory to watch for changes.
			* @param {object} watcher The object returned from a call to hound.watch().
			* @param {function} createCallback The function to run when a new file is created.
			* @param {function} changeCallback The function to run when a file is modified.
			* @param {function} deleteCallback The function to run when a file is deleted.
			*
			* @memberof MediaTasks
			* @public
			*/
		MediaTasks.watchDirectory = function (directory, watcher, createCallback, changeCallback, deleteCallback) {
			console.log(directory);
			createCallback = createCallback || _readExif;
			deleteCallback = deleteCallback || _deleteMedia;
			watcher = watcher || hound.watch(directory);

			watcher.on('create', function(file, stats) {
				createCallback(file);
			});

			watcher.on('change', function(file, stats) {
				if (changeCallback !== undefined) {
					changeCallback(file);
				}
			});

			watcher.on('delete', function(file) {
				if (deleteCallback !== undefined) {
					deleteCallback(file);
				}
			});
		};

		/**
			* Reads exif data from new media and passes it to the _prepareData()
			* function.
			*
			* @param {string} file The file to read exif data from.
			*
			* @memberof MediaTasks
			*/
		function _readExif (file) {
			exif(file, function (err, obj) {
				if (err) throw err;

				_prepareData(obj);
			});
		}

		/**
			* Parses exif data from readExit() and prepares it so it is ready to be
			* submitted to the database with _submitMedia().
			*
			* @param {object} data The data from the new media.
			*
			* @memberof MediaTasks
			*/
		function _prepareData (data) {
			var preparedData = {},
					createDate,
					file,
					lastindex,
					sizearray;

			// Convert date into a string usable by JavaScript's new Date()
			if (data['create date']) {
				createDate = data['create date'].split(' ');
				createDate[0] = createDate[0].replace(/[:]/g, '-');
				createDate = createDate.join('T');
			}

			// Set up file name to be split into filename and extension
			file = data['file name'];
			lastindex = file.lastIndexOf('.');

			// Creates an array for width and height
			sizearray = (data['image size']) ? data['image size'].split('x') : [];

			preparedData.extension = file.substr(lastindex + 1);
			preparedData.filename = file.substr(0, file.length - preparedData.extension.length - 1);
			preparedData.title = preparedData.filename;
			preparedData.tags = [];
			preparedData.date = new Date(createDate);
			preparedData.description = '';
			preparedData.dimensions = data['image size'];
			preparedData.width = Number(sizearray[0]);
			preparedData.height = Number(sizearray[1]);
			preparedData.layout = (preparedData.width > preparedData.height) ? 'landscape' : 'portrait';

			if (preparedData.extension.match(/^(jpg|jpeg|png|gif)$/)) {
				preparedData.type = 'photo';
			}
			else if (preparedData.extension.match(/^(mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|webm)$/)) {
				preparedData.type = 'video';
			}
			else {
				preparedData.type = 'not allowed';
			}

			_submitMedia(preparedData);
		}

		/**
			* Passes the data from _prepareData() to the API that submits it to the
			* database via an HTTP request. Then passes the data to _optimizeImage()
			* or _optimizeVideo() to prepare the media for the web.
			*
			* @param {object} preparedData The data passed from perpareData().
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _submitMedia (preparedData, host, path, port) {
			var options,
					req,
					data = JSON.stringify(preparedData),
					callback;

			callback = (preparedData.type === 'video') ? _optimizeVideo : _optimizeImage;

			host = host || 'localhost';
			path = (preparedData.type === 'video') ? '/api/v1/videos/' + encodeURIComponent(preparedData.filename) : '/api/v1/photos/' + encodeURIComponent(preparedData.filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			req = http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					if (callback) {
						callback(preparedData);
					}
				});
			});

			req.write(data);
			req.end();
		}

		/**
			* Converts full resolution image to web optimized versions to be used on
			* on the website and other applications.
			*
			* @param {object} data The data passed from _submitMedia().
			* @param {string} imagePath The path of the full resolution image.
			* @param {string} destPath The path where new images will be placed.
			*
			* @memberof MediaTasks
			*/
		function _optimizeImage (data, imagePath, destPath) {
			imagePath = imagePath || __dirname + '/../../public/media/photos/';
			destPath = destPath || __dirname + '/../../public/images/';

			var orig = imagePath + data.filename + '.' + data.extension;

			MediaController.makeImages(orig, destPath, data.filename, data.extension);
		}

		/**
			* On delete of media from the media directory, this function will delete
			* the optimized media files and send a call to the API to delete the item
			* from the database.
			*
			* @param {string} file The file to be deleted.
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _deleteMedia (file, host, path, port) {
			var options,
					req,
					filename = '',
					extension = '';

			filename = file.substring(file.lastIndexOf('/') + 1);
			filename = filename.substring(0, filename.length - 4);
			extension = file.slice(-3);

			if (file.indexOf('/photos/') !== -1) {
				var imagePath = __dirname + '/../../public/images/';

				MediaController.removeMedia(imagePath + filename + '.thumb.' + extension);
				MediaController.removeMedia(imagePath + filename + '.mob.' + extension);
				MediaController.removeMedia(imagePath + filename + '.desk.' + extension);
				MediaController.removeMedia(imagePath + filename + '.large.' + extension);
				MediaController.removeMedia(imagePath + filename + '.bg.' + extension);
			}

			host = host || 'localhost';
			path = (file.indexOf('/photos/') === -1) ? '/api/v1/videos/' + encodeURIComponent(filename) : '/api/v1/photos/' + encodeURIComponent(filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'DELETE',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					console.log(filename + ' deleted.');
				});
			}).end();
		}

		return MediaTasks;
	})({});

	module.exports = MediaTasks;
})();<commit_msg>Check if file is an image or video before processing<commit_after>var path						= require('path'),
		hound						= require('hound'),
		exif						= require('exif2'),
		http						= require('http'),
		MediaController	= require('./media');

/**
	* MediaTasks tasks watch the media directory for new, changed, or deleted images
	* and videos. It reads exif data from new media, converts the data into
	* something usable, adds it to the database, and passes the passes it to the
	* media controller for processing. Deleted media is removed from the database.
	*
	* @namespace MediaTasks
	*/

(function () {
	var MediaTasks;

	MediaTasks = (function (MediaTasks) {
		'use strict';

		/**
			* Watches specified directory for new, changed, or deleted media and
			* calls the appropriate funtions to handle them.
			*
			* @param {string} directory The directory to watch for changes.
			* @param {object} watcher The object returned from a call to hound.watch().
			* @param {function} createCallback The function to run when a new file is created.
			* @param {function} changeCallback The function to run when a file is modified.
			* @param {function} deleteCallback The function to run when a file is deleted.
			*
			* @memberof MediaTasks
			* @public
			*/
		MediaTasks.watchDirectory = function (directory, watcher, createCallback, changeCallback, deleteCallback) {
			createCallback = createCallback || _readExif;
			deleteCallback = deleteCallback || _deleteMedia;
			watcher = watcher || hound.watch(directory);

			watcher.on('create', function(file, stats) {
				if (_checkFileType(file)) {
					createCallback(file);
				}
			});

			watcher.on('change', function(file, stats) {
				if (changeCallback !== undefined) {
					changeCallback(file);
				}
			});

			watcher.on('delete', function(file) {
				if (deleteCallback !== undefined) {
					deleteCallback(file);
				}
			});
		};

		/**
		 * Reads exif data from new media and passes it to the _prepareData()
		 * function.
		 *
		 * @param {string} file The file to read exif data from.
		 *
		 * @memberof MediaTasks
		 */
		function _checkFileType (file) {
			var lastindex = file.lastIndexOf('.'),
					type = file.substr(lastindex + 1);

			if (type.match(/^(jpg|jpeg|png|gif|mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|webm)$/)) {
				return true;
			}
			else {
				return false;
			}
		}

		/**
		 * Reads exif data from new media and passes it to the _prepareData()
		 * function.
		 *
		 * @param {string} file The file to read exif data from.
		 *
		 * @memberof MediaTasks
		 */
		function _readExif (file) {
			exif(file, function (err, obj) {
				if (err) throw err;

				_prepareData(obj);
			});
		}

		/**
			* Parses exif data from readExit() and prepares it so it is ready to be
			* submitted to the database with _submitMedia().
			*
			* @param {object} data The data from the new media.
			*
			* @memberof MediaTasks
			*/
		function _prepareData (data) {
			var preparedData = {},
					createDate,
					file,
					lastindex,
					sizearray;

			// Convert date into a string usable by JavaScript's new Date()
			if (data['create date']) {
				createDate = data['create date'].split(' ');
				createDate[0] = createDate[0].replace(/[:]/g, '-');
				createDate = createDate.join('T');
			}

			// Set up file name to be split into filename and extension
			file = data['file name'];
			lastindex = file.lastIndexOf('.');

			// Creates an array for width and height
			sizearray = (data['image size']) ? data['image size'].split('x') : [];

			preparedData.extension = file.substr(lastindex + 1);
			preparedData.filename = file.substr(0, file.length - preparedData.extension.length - 1);
			preparedData.title = preparedData.filename;
			preparedData.tags = [];
			preparedData.date = new Date(createDate);
			preparedData.description = '';
			preparedData.dimensions = data['image size'];
			preparedData.width = Number(sizearray[0]);
			preparedData.height = Number(sizearray[1]);
			preparedData.layout = (preparedData.width > preparedData.height) ? 'landscape' : 'portrait';

			if (preparedData.extension.match(/^(jpg|jpeg|png|gif)$/)) {
				preparedData.type = 'photo';
			}
			else if (preparedData.extension.match(/^(mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|webm)$/)) {
				preparedData.type = 'video';
			}
			else {
				preparedData.type = 'not allowed';
			}

			_submitMedia(preparedData);
		}

		/**
			* Passes the data from _prepareData() to the API that submits it to the
			* database via an HTTP request. Then passes the data to _optimizeImage()
			* or _optimizeVideo() to prepare the media for the web.
			*
			* @param {object} preparedData The data passed from perpareData().
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _submitMedia (preparedData, host, path, port) {
			var options,
					req,
					data = JSON.stringify(preparedData),
					callback;

			callback = (preparedData.type === 'video') ? _optimizeVideo : _optimizeImage;

			host = host || 'localhost';
			path = (preparedData.type === 'video') ? '/api/v1/videos/' + encodeURIComponent(preparedData.filename) : '/api/v1/photos/' + encodeURIComponent(preparedData.filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			req = http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					if (callback) {
						callback(preparedData);
					}
				});
			});

			req.write(data);
			req.end();
		}

		/**
			* Converts full resolution image to web optimized versions to be used on
			* on the website and other applications.
			*
			* @param {object} data The data passed from _submitMedia().
			* @param {string} imagePath The path of the full resolution image.
			* @param {string} destPath The path where new images will be placed.
			*
			* @memberof MediaTasks
			*/
		function _optimizeImage (data, imagePath, destPath) {
			imagePath = imagePath || __dirname + '/../../public/media/photos/';
			destPath = destPath || __dirname + '/../../public/images/';

			var orig = imagePath + data.filename + '.' + data.extension;

			MediaController.makeImages(orig, destPath, data.filename, data.extension);
		}

		/**
			* On delete of media from the media directory, this function will delete
			* the optimized media files and send a call to the API to delete the item
			* from the database.
			*
			* @param {string} file The file to be deleted.
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _deleteMedia (file, host, path, port) {
			var options,
					req,
					filename = '',
					extension = '';

			filename = file.substring(file.lastIndexOf('/') + 1);
			filename = filename.substring(0, filename.length - 4);
			extension = file.slice(-3);

			if (file.indexOf('/photos/') !== -1) {
				var imagePath = __dirname + '/../../public/images/';

				MediaController.removeMedia(imagePath + filename + '.thumb.' + extension);
				MediaController.removeMedia(imagePath + filename + '.mob.' + extension);
				MediaController.removeMedia(imagePath + filename + '.desk.' + extension);
				MediaController.removeMedia(imagePath + filename + '.large.' + extension);
				MediaController.removeMedia(imagePath + filename + '.bg.' + extension);
			}

			host = host || 'localhost';
			path = (file.indexOf('/photos/') === -1) ? '/api/v1/videos/' + encodeURIComponent(filename) : '/api/v1/photos/' + encodeURIComponent(filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'DELETE',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					console.log(filename + ' deleted.');
				});
			}).end();
		}

		return MediaTasks;
	})({});

	module.exports = MediaTasks;
})();<|endoftext|>


<commit_before>import {completeAssign} from 'common/utils';
import {dispatch} from 'common/functional';
import {bounce} from 'physics/collisions';

import ui from 'ui';

import Vector from 'maths/vector';

import random from 'lodash.random';
import remove from 'lodash.remove';
import is_nil from 'lodash.isnil';

import {EventEmitter} from 'events';

const keyboard = ui.keyboard;

export default function GameController(state) {
	const {ball, vaus} = state;
	const zone = state.scene.boundingBox.relative;
	const scale = state.scene.scale;
	const emitter = new EventEmitter();

	// Position helpers

	function ball_neighborhood() {
		const col = Math.round(ball.position.x);
		const row = Math.round(ball.position.y);
		return state.bricks
			.filter(brick => Math.abs(col - brick.position.x) <= 2
								&& Math.abs(row - brick.position.y) <= 1);
	}

	function reset_ball_position() {
		const vaus_box = vaus.boundingBox.absolute;
		ball.reset({x: vaus_box.center.x, y: vaus_box.topY - ball.radius});
	}

	// Collision helpers

	function ball_collides_with_bricks(ball_box, speed) {
		for (let brick of ball_neighborhood(ball)) {
			const brick_box = brick.boundingBox.absolute;
			const v = bounce(ball_box, speed, brick_box, .001);
			if (!is_nil(v)) {
				brick.hit();
				return v.add({
					x: random(-1, 1, true)/1000,
					y: random(-1, 1, true)/1000
				}).toUnit().mul(.2);
			}
		}
	}

	function ball_collides_with_vaus(ball_box, speed) {
		const v = bounce(ball_box, speed, vaus.boundingBox.absolute, 1/scale);
		if (!is_nil(v)) {
			return v;
		}
	}

	function ball_collides_with_walls(ball_box, speed) {
		if (ball_box.leftX <= zone.leftX) {
			// collide with left wall
			return Vector({x: -speed.x, y: speed.y});
		} else if (ball_box.rightX >= zone.rightX) {
			// collide with right wall
			return Vector({x: -speed.x, y: speed.y});
		} else if (ball_box.topY <= zone.topY) {
			// collide with roof
			return Vector({x: speed.x, y: -speed.y});
		} else if (ball_box.bottomY >= zone.bottomY) {
			// collide width floor
			// it should only happened if end of round has not been checked
			return Vector({x: speed.x, y: -speed.y});
		}
	}

	const ball_collides = dispatch(
		ball_collides_with_bricks,
		ball_collides_with_vaus,
		ball_collides_with_walls,
		(ball_box, speed) => speed
	);

	// Move helpers

	function update_ball() {
		if (!ball.velocity.isNull()) {
			const ball_box = ball.boundingBox.absolute.translate(ball.velocity);
			if (ball_box.bottomY >= zone.bottomY) {
				reset_ball_position(vaus, ball);
			} else {
				ball.velocity = ball_collides(ball_box, ball.velocity);
			}
		} else {
			reset_ball_position(vaus, ball);
		}
		ball.update();
	}

	function update_vaus() {
		const {leftX: vaux_left_x, rightX: vaus_right_x} = vaus.boundingBox.absolute;
		const {leftX: zone_left_x, rightX: zone_right_x} = zone;

		if (!vaus.velocity.isNull() && vaux_left_x <= zone_left_x) {
			vaus.move(Vector.Null);
			vaus.position = vaus.position.add({x: zone_left_x - vaux_left_x, y: 0});
		}

		if (!vaus.velocity.isNull() && vaus_right_x >= zone_right_x) {
			vaus.move(Vector.Null);
			vaus.position = vaus.position.add({x: zone_right_x - vaus_right_x, y: 0});
		}

		vaus.update();
	}

	// Game helpers

	function bricks_remaining() {
		return state.bricks.reduce(
			(count, brick) => brick.color === 'gold' ? count : count + 1, 0
		);
	}

	keyboard.on('direction-changed', direction => {
		vaus.move(direction);
	});
	keyboard.on('fire', () => {
		if (ball.velocity.isNull()) {
			ball.velocity = Vector({x: 1, y: -1}).toUnit().mul(.2);
		}
	});
	keyboard.on('pause', () => emitter.emit('pause'));

	return completeAssign(emitter, {
		update() {
			update_ball();
			update_vaus();
		},
		reset() {
			reset_ball_position();
			state.bricks.forEach(brick => {
				brick.on('hit', point => emitter.emit('update-score', point));
				brick.once('destroyed', () => {
					brick.removeAllListeners('destroyed');
					brick.removeAllListeners('hit');
					remove(state.bricks, brick);
					const remain = bricks_remaining();
					if (remain === 0) {
						emitter.emit('end-of-level');
					}
				});
			});
		}
	})
}
<commit_msg>fix bricks destruction<commit_after>import {completeAssign} from 'common/utils';
import {dispatch} from 'common/functional';
import {bounce} from 'physics/collisions';

import ui from 'ui';

import Vector from 'maths/vector';

import random from 'lodash.random';
import remove from 'lodash.remove';
import is_nil from 'lodash.isnil';

import {EventEmitter} from 'events';

const keyboard = ui.keyboard;

export default function GameController(state) {
	const {ball, vaus} = state;
	const zone = state.scene.boundingBox.relative;
	const scale = state.scene.scale;
	const emitter = new EventEmitter();

	// Position helpers

	function ball_neighborhood() {
		const col = Math.round(ball.position.x);
		const row = Math.round(ball.position.y);
		return state.bricks
			.filter(brick => Math.abs(col - brick.position.x) <= 2
								&& Math.abs(row - brick.position.y) <= 1);
	}

	function reset_ball_position() {
		const vaus_box = vaus.boundingBox.absolute;
		ball.reset({x: vaus_box.center.x, y: vaus_box.topY - ball.radius});
	}

	// Collision helpers

	function ball_collides_with_bricks(ball_box, speed) {
		for (let brick of ball_neighborhood(ball)) {
			const brick_box = brick.boundingBox.absolute;
			const v = bounce(ball_box, speed, brick_box, .001);
			if (!is_nil(v)) {
				brick.hit();
				return v.add({
					x: random(-1, 1, true)/1000,
					y: random(-1, 1, true)/1000
				}).toUnit().mul(.2);
			}
		}
	}

	function ball_collides_with_vaus(ball_box, speed) {
		const v = bounce(ball_box, speed, vaus.boundingBox.absolute, 1/scale);
		if (!is_nil(v)) {
			return v;
		}
	}

	function ball_collides_with_walls(ball_box, speed) {
		if (ball_box.leftX <= zone.leftX) {
			// collide with left wall
			return Vector({x: -speed.x, y: speed.y});
		} else if (ball_box.rightX >= zone.rightX) {
			// collide with right wall
			return Vector({x: -speed.x, y: speed.y});
		} else if (ball_box.topY <= zone.topY) {
			// collide with roof
			return Vector({x: speed.x, y: -speed.y});
		} else if (ball_box.bottomY >= zone.bottomY) {
			// collide width floor
			// it should only happened if end of round has not been checked
			return Vector({x: speed.x, y: -speed.y});
		}
	}

	const ball_collides = dispatch(
		ball_collides_with_bricks,
		ball_collides_with_vaus,
		ball_collides_with_walls,
		(ball_box, speed) => speed
	);

	// Move helpers

	function update_ball() {
		if (!ball.velocity.isNull()) {
			const ball_box = ball.boundingBox.absolute.translate(ball.velocity);
			if (ball_box.bottomY >= zone.bottomY) {
				reset_ball_position(vaus, ball);
			} else {
				ball.velocity = ball_collides(ball_box, ball.velocity);
			}
		} else {
			reset_ball_position(vaus, ball);
		}
		ball.update();
	}

	function update_vaus() {
		const {leftX: vaux_left_x, rightX: vaus_right_x} = vaus.boundingBox.absolute;
		const {leftX: zone_left_x, rightX: zone_right_x} = zone;

		if (!vaus.velocity.isNull() && vaux_left_x <= zone_left_x) {
			vaus.move(Vector.Null);
			vaus.position = vaus.position.add({x: zone_left_x - vaux_left_x, y: 0});
		}

		if (!vaus.velocity.isNull() && vaus_right_x >= zone_right_x) {
			vaus.move(Vector.Null);
			vaus.position = vaus.position.add({x: zone_right_x - vaus_right_x, y: 0});
		}

		vaus.update();
	}

	// Game helpers

	function bricks_remaining() {
		return state.bricks.reduce(
			(count, brick) => brick.color === 'gold' ? count : count + 1, 0
		);
	}

	keyboard.on('direction-changed', direction => {
		vaus.move(direction);
	});
	keyboard.on('fire', () => {
		if (ball.velocity.isNull()) {
			ball.velocity = Vector({x: 1, y: -1}).toUnit().mul(.2);
		}
	});
	keyboard.on('pause', () => emitter.emit('pause'));

	return completeAssign(emitter, {
		update() {
			update_ball();
			update_vaus();
		},
		reset() {
			reset_ball_position();
			state.bricks.forEach(brick => {
				brick.on('hit', point => emitter.emit('update-score', point));
				brick.once('destroyed', () => {
					brick.removeAllListeners('destroyed');
					brick.removeAllListeners('hit');
					brick.toggleRender(false);
					remove(state.bricks, brick);
					const remain = bricks_remaining();
					if (remain === 0) {
						emitter.emit('end-of-level');
					}
				});
			});
		}
	})
}
<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import {API_URL} from '../config';
import { fromJS } from 'immutable';

// Usage:
//
// import gql from './util/GraphQL';
// gql`query($var: Type) { foo }`({var: 123}).then(...)
//
// gql`...`() returns a promise that resolves to immutable Map({data, errors}).
//
// We use template string here so that Atom's language-babel does syntax highlight
// for us.
//
// GraphQL Protocol: http://dev.apollodata.com/tools/graphql-server/requests.html
//
export default (query, ...substitutions) => (variables) => {
  const queryAndVariable = {
    query: String.raw(query, ...substitutions),
  };

  if(variables) queryAndVariable.variables = variables;

  let status;

  return fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    credentials: 'include',
    body: JSON.stringify(queryAndVariable),
  }).then(r => {
    status = r.status;
    return r.json();
  }).then((resp) => {
    if(status === 400) {
      throw new Error(`GraphQL Error: ${resp.errors.map(({message}) => message).join('\n')}`);
    }
    if (resp.errors) {
      // When status is 200 but have error, just print them out.
      console.error('GraphQL operation contains error:', resp.errors);
    }
    return fromJS(resp);
  });
}
<commit_msg>Setup x-app-id header for rumors-api to identify official website client<commit_after>import fetch from 'isomorphic-fetch';
import {API_URL} from '../config';
import { fromJS } from 'immutable';

// Usage:
//
// import gql from './util/GraphQL';
// gql`query($var: Type) { foo }`({var: 123}).then(...)
//
// gql`...`() returns a promise that resolves to immutable Map({data, errors}).
//
// We use template string here so that Atom's language-babel does syntax highlight
// for us.
//
// GraphQL Protocol: http://dev.apollodata.com/tools/graphql-server/requests.html
//
export default (query, ...substitutions) => (variables) => {
  const queryAndVariable = {
    query: String.raw(query, ...substitutions),
  };

  if(variables) queryAndVariable.variables = variables;

  let status;

  return fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-app-id': 'RUMORS_SITE',
    },
    credentials: 'include',
    body: JSON.stringify(queryAndVariable),
  }).then(r => {
    status = r.status;
    return r.json();
  }).then((resp) => {
    if(status === 400) {
      throw new Error(`GraphQL Error: ${resp.errors.map(({message}) => message).join('\n')}`);
    }
    if (resp.errors) {
      // When status is 200 but have error, just print them out.
      console.error('GraphQL operation contains error:', resp.errors);
    }
    return fromJS(resp);
  });
}
<|endoftext|>


<commit_before>module.exports.name = 'voiceMute';
module.exports.alias = [
  'voicemute',
  'vm'
];

const Discord = require('discord.js');
const Util = require('../classes/Util.js');

module.exports.isAllowed = (message, server) => {
  if (server.guild.id != '189571157446492161') return false; // Only in EJLX
  return message.member.hasPermission('MUTE_MEMBERS');
};

module.exports.help = '__VW Only__ Voice mutes people. `,vm <@mentions> [reason]`';

module.exports.command = async (message, content, bot, server) => {
  let targets = message.mentions.members;
  if (targets.size === 0) {
    message.channel.send('You must mention them');
    return;
  }
  let reason = content.replace(Util.REGEX_USER, '').trim();
  if (reason == ''){
    reason = 'unspecified';
  }
  const ewbf = server.guild.channels.get('277384105245802497');
  for (let [ , member] of targets) {
    if (member.voice) {
      await member.voice.setMute(true, `by ${message.author.tag} Reason: ${reason}` );
    }

    await member.addRole('357687893566947329'); // Voice mute role
    let embed = new Discord.RichEmbed();
    embed.title = `You have been voice muted in the English-Japanese Language Exchange server by ${message.author.tag}`;
    embed.description = `Reason: ${reason}`;
    embed.color = Number('0xEC891D');
    embed.setFooter('Contact one of the mods if you need to discuss this issue.', message.author.avatarURL);
    embed.timestamp = new Date();
    await member.send({embed});
    embed = new Discord.RichEmbed();
    embed.setAuthor(`${member.user.tag} has been muted in voice chat` , member.user.avatarURL);
    embed.description = `Reason: ${reason}`;
    embed.color = Number('0xEC891D');
    embed.setFooter(`by ${message.author.tag}`, message.author.avatarURL);
    embed.timestamp = new Date();
    ewbf.send({embed});
    const warning = {
      issued: message.createdTimestamp,
      issuer: message.author.id,
      link: message.url,
      warnMessage: `Voice muted`
    }
    if (server.warnlist[member.id]) {
      server.warnlist[member.id].push(
        warning
      )
    } else {
      server.warnlist[member.id] = [
        warning
      ];
    }
  }
  message.channel.send('✅ Voice Muted');
};
<commit_msg>voicemute fix<commit_after>module.exports.name = 'voiceMute';
module.exports.alias = [
  'voicemute',
  'vm'
];

const Discord = require('discord.js');
const Util = require('../classes/Util.js');

module.exports.isAllowed = (message, server) => {
  if (server.guild.id != '189571157446492161') return false; // Only in EJLX
  return message.member.hasPermission('MUTE_MEMBERS');
};

module.exports.help = '__VW Only__ Voice mutes people. `,vm <@mentions> [reason]`';

module.exports.command = async (message, content, bot, server) => {
  content = content.replace(Util.REGEX_USER, '').trim();
  const targets = [...message.mentions.members.values()];
  const ids = content.match(Util.REGEX_RAW_ID);
  if (ids) {
    for (const id of ids) {
      const mem = server.guild.member(id);
      if (mem) {
        targets.push(mem);
      }
    }
    content = content.replace(Util.REGEX_RAW_ID, '').trim();
  }

  if (targets.size === 0) {
    message.channel.send('You must mention them');
    return;
  }
  let reason = content;
  if (!reason){
    reason = 'unspecified';
  }
  const ewbf = server.guild.channels.get('277384105245802497');
  for (const member of targets) {
    if (member.voiceChannel) {
      await member.setVoiceChannel(null);
    }
    await member.addRole('357687893566947329'); // Voice mute role
    let embed = new Discord.RichEmbed();
    embed.title = `You have been voice muted in the English-Japanese Language Exchange server by ${message.author.tag}`;
    embed.description = `Reason: ${reason}`;
    embed.color = Number('0xEC891D');
    embed.setFooter('Contact one of the mods if you need to discuss this issue.', message.author.avatarURL);
    embed.timestamp = new Date();
    await member.send({embed});
    embed = new Discord.RichEmbed();
    embed.setAuthor(`${member.user.tag} has been muted in voice chat` , member.user.avatarURL);
    embed.description = `Reason: ${reason}`;
    embed.color = Number('0xEC891D');
    embed.setFooter(`by ${message.author.tag}`, message.author.avatarURL);
    embed.timestamp = new Date();
    ewbf.send({embed});
    const warning = {
      issued: message.createdTimestamp,
      issuer: message.author.id,
      link: message.url,
      warnMessage: 'Voice muted'
    };
    if (server.warnlist[member.id]) {
      server.warnlist[member.id].push(
        warning
      );
    } else {
      server.warnlist[member.id] = [
        warning
      ];
    }
  }
  message.channel.send('✅ Voice Muted');
};
<|endoftext|>


<commit_before>var lastKey = "I"; //Keep track of last key played so that you don't replay it

/**
 * Determines how to play the given notes based on their type and quality, then loads
 * the corresponding audio files and plays them.
 *
 * @class MusicSnippet
 * @constructor
 * @param {String} type Type of the sonority
 * @param {String} quality Quality of the sonority
 * @param {String} category Category of the sonority
 * @param {String Array} notes Array of notes
 */
function MusicSnippet(type, quality, notes, category) {
	/* Constants */
	const CHORD = "chord";
	const SCALE = "scale";
	const INTERVAL = "interval";
	const TWENTIETH = "20th Century";
	const JAZZ = "jazz";

	const BPM = 80; 				//Beats per minute
	var bps = BPM/60; 				//Beats per second

	/* Variables */
	var baseNotes = notes;			//Store the base notes to transpose from
	var type = type;				//Chord, scale, or interval
	var quality = quality;			//Answer
	var category = category;		//Category
	var numNotes = notes.length;	//Number of notes

	var tempNotes = [];				//Holds current notes
	var tempSounds = [];			//Holds current sound
	var numLoaded = 0;				//Number of loaded files
	var timeouts = [];				//Timeout objects to keep track of when playing broken

	/**
	 * Plays the loaded files:
	 *  - Chords are played broken then blocked
	 *  - Scales are played broken
	 *  - Intervals are played broken
	 *
	 * @method play
	 * @param {String} style How to play the notes. No argument means play it quiz style
	 */
	this.play = function(style) {
		stop();
		clear();

		//Unload and reload
		if(tempSounds.length > 0) {
			for(var i = 0; i < numNotes; i++) {
				tempSounds[i].unload();
			}
		}
		tempSounds = loadFiles(tempNotes);

		if(style == undefined) {
			//Play arpegiated and then play block
			if(type == CHORD) {
				if(category == TWENTIETH) {
					playBlock();
				}
				else {
					playBlock();
					timeouts.push(setTimeout(function() {playBroken();}, (1/bps)*2000));
				}
			}
			//Play broken
			else if(type == SCALE) {
				playBroken();
			}
			else if(type == INTERVAL) {
				playBroken();
			}
			else {
				playBroken();
			}
		}
	}

	/**
	 * Randomly transposes the notes given from the CSV file and gives them a random octave.
	 * Then loads the corresponding audio files.
	 *
	 * @method generate
	 */
	this.generate = function() {
		stop();
		clear();
		tempSounds = generateTransposition();
	}

	/**
	 * Returns the type and quality
	 *
	 * @method answer
	 * @return {String} quality + type
	 */
	this.answer = function() {
		return quality+" "+type;
	}

	/**
	 * Stops all sound
	 *
	 * @method stopSound
	 */
	this.stopSound = function() {
		stop();
		clear();
	}

	/**
	 * Transposes and sets octave of the notes from the CSV file randomly, then loads the
	 * corresponding files
	 *
	 * @method generateTransposition
	 * @return {Howl Array} An array of Howl objects that have the loaded audio files
	 * @private
	 */
	function generateTransposition() {
		do {
			var randKey = Math.floor(Math.random()*13)-6;	//Get Random key between -7 and 7
			tempNotes = setNotes(randKey);			//Array of transposed keys
		} while(tempNotes[0] == lastKey);			//Don't generate the previously played key

		lastKey = tempNotes[0];
		tempNotes = setOctave(tempNotes);			//Set a random octave
		console.log(tempNotes);
		return loadFiles(tempNotes);				//Load the corresponding files
	}

	/**
	 * Tranposes the notes from the CSV file a given number of sharps or flats
	 *
	 * @method setNotes
	 * @param {Integer} shift How much to transpose the notes by
	 * @return {String Array} Array of the notes after transposition
	 * @private
	 */
	function setNotes(shift) {
		return transpose(baseNotes, shift);
	}

	/**
	 * Plays the note at the given index in the loaded files array
	 *
	 * @method playNote
	 * @param {Integer} i Index of the note to be played
	 * @private
	 */
	function playNote(i) {
		tempSounds[i].play();

		//Fade out scale notes. Let it kind of bleed over.
		if(type == SCALE) {
			tempSounds[i].fadeOut(0, (1/bps)*1500);
		}
	}

	/**
	 * Plays all notes at the same time
	 *
	 * @method playBlock
	 * @private
	 */
	function playBlock() {
		for(i = 0; i < numNotes; i++) {
			tempSounds[i].play();
		}
	}

	/*
	 * Plays all notes in sequence with timing based on bpm
	 *
	 * @method playBroken
	 * @private
	 */
	function playBroken() {
		//Play first note instantly
		timeouts.push(setTimeout(function() {
			playNote(0);
			playBrokenHelp(1);		//Play rest of notes
		}, (1/bps)*500));
	}

	/*
	 * Recursive helper for playBroken()
	 *
	 * @method playBrokenHelp
	 * @param {Integer} note An index representing the note to be played
	 * @private
	 */
	function playBrokenHelp(note) {
		if(note < numNotes) {
			timeouts.push(setTimeout(function() {
				playNote(note);
				playBrokenHelp(note+1);
			}, (1/bps)*1000)); //How many seconds per note given the bpm
		}
	}

	/*
	 * Stops all sound immediately
	 *
	 * @method stop
	 * @private
	 */
	function stop() {
		for(i = 0; i < tempSounds.length; i++) {
			console.log("Stopping "+i);
			tempSounds[i].stop();
		}
	}

	/*
	 * Clears all timeouts (delayed sounds)
	 *
	 * @method clear
	 * @private
	 */
	function clear() {
		var initLength = timeouts.length;
		for(i = 0; i < initLength; i++) {
			clearTimeout(timeouts[timeouts.length-1]);
			timeouts.pop();
		}
	}

	/*
	 * Takes the notes and converts them into Howl objects with the appropriate
	 * sound files.
	 *
	 * @method loadFiles
	 * @param {String Array} notes Array of notes to be loaded
	 * @return {Howl Array} Array of Howl objects containing the corresponding audio files
	 * @private
	 */
	function loadFiles(notes) {
		var midi = [];		//Store notes as midi numbers
		var files = [];		//Store file paths to corresponding files
		var sounds = [];	//Howl objects of files

		//Get midi numbers of given notes
		for(i = 0; i < numNotes; i++) {
			midi.push(noteToFileNum[notes[i]]);
			//Error checking
			if(midi[i] == undefined) {
				console.log("Error: Check notation for "+quality+" "+type);
			}
		}

		//Convert midi numbers to their corresponding file names
		files = convMidiToFile(midi);

		//Load sound files
		for(i = 0; i < numNotes; i++) {
			sounds.push(new Howl({
				urls : [files[i]],
				onload : function() {
					numLoaded++;
					//Display loaded notes
					console.log("Loaded note "+numLoaded);
					//If all notes displayed, show buttons
					if(numLoaded == numNotes) {
						document.getElementById("loading").style.display = "none";
						document.getElementById("allbuttons").style.display = "block";
						numLoaded = 0;
					}
				},
				onloaderror : function() {console.log(quality+" "+type+" loading error")}
			}));
		}
		return sounds;
	}

	/*
 	 * Converts midi numbers to their corresponding file names
 	 *
 	 * @method convMidiToFile
 	 * @param {Integer Array} midi Array of midi numbers to be converted into files
 	 * @return {String Array} Array of strings containing the proper file paths to the audio files
 	 * @private
 	 */
	function convMidiToFile(midi) {
		var files = [];
		for(i = 0; i < numNotes; i++) {
			files.push("audio/piano/piano"+midi[i]+".wav");
		}
		return files;
	}
}
<commit_msg>debugging<commit_after>var lastKey = "I"; //Keep track of last key played so that you don't replay it

/**
 * Determines how to play the given notes based on their type and quality, then loads
 * the corresponding audio files and plays them.
 *
 * @class MusicSnippet
 * @constructor
 * @param {String} type Type of the sonority
 * @param {String} quality Quality of the sonority
 * @param {String} category Category of the sonority
 * @param {String Array} notes Array of notes
 */
function MusicSnippet(type, quality, notes, category) {
	/* Constants */
	const CHORD = "chord";
	const SCALE = "scale";
	const INTERVAL = "interval";
	const TWENTIETH = "20th Century";
	const JAZZ = "jazz";

	const BPM = 80; 				//Beats per minute
	var bps = BPM/60; 				//Beats per second

	/* Variables */
	var baseNotes = notes;			//Store the base notes to transpose from
	var type = type;				//Chord, scale, or interval
	var quality = quality;			//Answer
	var category = category;		//Category
	var numNotes = notes.length;	//Number of notes

	var tempNotes = [];				//Holds current notes
	var tempSounds = [];			//Holds current sound
	var numLoaded = 0;				//Number of loaded files
	var timeouts = [];				//Timeout objects to keep track of when playing broken

	/**
	 * Plays the loaded files:
	 *  - Chords are played broken then blocked
	 *  - Scales are played broken
	 *  - Intervals are played broken
	 *
	 * @method play
	 * @param {String} style How to play the notes. No argument means play it quiz style
	 */
	this.play = function(style) {
		//Stop all sound
		stop();
		clear();

		//Unload and reload
		if(tempSounds.length > 0) {
			for(var i = 0; i < numNotes; i++) {
				tempSounds[i].unload();
			}
		}
		tempSounds = loadFiles(tempNotes);

		if(style == undefined) {
			//Play arpegiated and then play block
			if(type == CHORD) {
				if(category == TWENTIETH) {
					playBlock();
				}
				else {
					playBlock();
					timeouts.push(setTimeout(function() {playBroken();}, (1/bps)*2000));
				}
			}
			//Play broken
			else if(type == SCALE) {
				playBroken();
			}
			else if(type == INTERVAL) {
				playBroken();
			}
			else {
				playBroken();
			}
		}
	}

	/**
	 * Randomly transposes the notes given from the CSV file and gives them a random octave.
	 * Then loads the corresponding audio files.
	 *
	 * @method generate
	 */
	this.generate = function() {
		stop();
		clear();
		tempNotes = generateTransposition();
	}

	/**
	 * Returns the type and quality
	 *
	 * @method answer
	 * @return {String} quality + type
	 */
	this.answer = function() {
		return quality+" "+type;
	}

	/**
	 * Stops all sound
	 *
	 * @method stopSound
	 */
	this.stopSound = function() {
		stop();
		clear();
	}

	/**
	 * Transposes and sets octave of the notes from the CSV file randomly, then loads the
	 * corresponding files
	 *
	 * @method generateTransposition
	 * @return {Howl Array} An array of Howl objects that have the loaded audio files
	 * @private
	 */
	function generateTransposition() {
		do {
			var randKey = Math.floor(Math.random()*13)-6;	//Get Random key between -7 and 7
			tempNotes = setNotes(randKey);			//Array of transposed keys
		} while(tempNotes[0] == lastKey);			//Don't generate the previously played key

		lastKey = tempNotes[0];
		tempNotes = setOctave(tempNotes);			//Set a random octave
		console.log(tempNotes);
		// return loadFiles(tempNotes);				//Load the corresponding files
		return tempNotes;
	}

	/**
	 * Tranposes the notes from the CSV file a given number of sharps or flats
	 *
	 * @method setNotes
	 * @param {Integer} shift How much to transpose the notes by
	 * @return {String Array} Array of the notes after transposition
	 * @private
	 */
	function setNotes(shift) {
		return transpose(baseNotes, shift);
	}

	/**
	 * Plays the note at the given index in the loaded files array
	 *
	 * @method playNote
	 * @param {Integer} i Index of the note to be played
	 * @private
	 */
	function playNote(i) {
		tempSounds[i].play();

		//Fade out scale notes. Let it kind of bleed over.
		if(type == SCALE) {
			tempSounds[i].fadeOut(0, (1/bps)*1500);
		}
	}

	/**
	 * Plays all notes at the same time
	 *
	 * @method playBlock
	 * @private
	 */
	function playBlock() {
		for(i = 0; i < numNotes; i++) {
			tempSounds[i].play();
		}
	}

	/*
	 * Plays all notes in sequence with timing based on bpm
	 *
	 * @method playBroken
	 * @private
	 */
	function playBroken() {
		//Play first note instantly
		timeouts.push(setTimeout(function() {
			playNote(0);
			playBrokenHelp(1);		//Play rest of notes
		}, (1/bps)*500));
	}

	/*
	 * Recursive helper for playBroken()
	 *
	 * @method playBrokenHelp
	 * @param {Integer} note An index representing the note to be played
	 * @private
	 */
	function playBrokenHelp(note) {
		if(note < numNotes) {
			timeouts.push(setTimeout(function() {
				playNote(note);
				playBrokenHelp(note+1);
			}, (1/bps)*1000)); //How many seconds per note given the bpm
		}
	}

	/*
	 * Stops all sound immediately
	 *
	 * @method stop
	 * @private
	 */
	function stop() {
		for(i = 0; i < tempSounds.length; i++) {
			console.log("Stopping "+i);
			tempSounds[i].stop();
		}
	}

	/*
	 * Clears all timeouts (delayed sounds)
	 *
	 * @method clear
	 * @private
	 */
	function clear() {
		var initLength = timeouts.length;
		for(i = 0; i < initLength; i++) {
			clearTimeout(timeouts[timeouts.length-1]);
			timeouts.pop();
		}
	}

	/*
	 * Takes the notes and converts them into Howl objects with the appropriate
	 * sound files.
	 *
	 * @method loadFiles
	 * @param {String Array} notes Array of notes to be loaded
	 * @return {Howl Array} Array of Howl objects containing the corresponding audio files
	 * @private
	 */
	function loadFiles(notes) {
		var midi = [];		//Store notes as midi numbers
		var files = [];		//Store file paths to corresponding files
		var sounds = [];	//Howl objects of files

		//Get midi numbers of given notes
		for(i = 0; i < numNotes; i++) {
			midi.push(noteToFileNum[notes[i]]);
			//Error checking
			if(midi[i] == undefined) {
				console.log("Error: Check notation for "+quality+" "+type);
			}
		}

		//Convert midi numbers to their corresponding file names
		files = convMidiToFile(midi);

		//Load sound files
		for(i = 0; i < numNotes; i++) {
			sounds.push(new Howl({
				urls : [files[i]],
				onload : function() {
					numLoaded++;
					//Display loaded notes
					console.log("Loaded note "+numLoaded);
					//If all notes displayed, show buttons
					if(numLoaded == numNotes) {
						document.getElementById("loading").style.display = "none";
						document.getElementById("allbuttons").style.display = "block";
						numLoaded = 0;
					}
				},
				onloaderror : function() {console.log(quality+" "+type+" loading error")}
			}));
		}
		return sounds;
	}

	/*
 	 * Converts midi numbers to their corresponding file names
 	 *
 	 * @method convMidiToFile
 	 * @param {Integer Array} midi Array of midi numbers to be converted into files
 	 * @return {String Array} Array of strings containing the proper file paths to the audio files
 	 * @private
 	 */
	function convMidiToFile(midi) {
		var files = [];
		for(i = 0; i < numNotes; i++) {
			files.push("audio/piano/piano"+midi[i]+".wav");
		}
		return files;
	}
}
<|endoftext|>


<commit_before>var CONNECTED = 'CONNECTED';
var REGION_CHANGE = 'REGION_CHANGE';
var SHOW_HELP = 'SHOW_HELP';

var HabiventsES = null;
var CurrentAvatars = {};

function orientationToRotation(orientation) {
  switch (orientation) {
    case 'North':
      return 270;
    case 'West':
      return 90;
    case 'South':
      return 180;
    case 'East':
      return 0;
    default:
      return 0;
  }
}

const HTMLArrows = ['↑', '←', '↓', '→'];
const orient     = ["West", "East", "North", "South"];

function processEvent(event) {
  switch (event.type) {
    case CONNECTED:
      return;
    case REGION_CHANGE:
      console.log(event);
      $('#regionHeader').text(event.msg.description);
      $('#docsFrame').attr('src', event.msg.docsURL);
      $('#orientationHeader').text(event.msg.orientation);
      $("#compass").rotate({
        animateTo: orientationToRotation(event.msg.orientation),
      })
      var arrow = (orient.indexOf(event.msg.orientation) + 3) % 4;
      $("#northArrow").html(HTMLArrows[arrow]);
      $("#northHeader").text(event.msg.neighbors.North);
      arrow = ++arrow % 4;
      $("#westArrow").html(HTMLArrows[arrow]);
      $("#westHeader").text(event.msg.neighbors.West);
      arrow = ++arrow % 4;
      $("#southArrow").html(HTMLArrows[arrow]);
      $("#southHeader").text(event.msg.neighbors.South);
      arrow = ++arrow % 4;
      $("#eastArrow").html(HTMLArrows[arrow]);
      $("#eastHeader").text(event.msg.neighbors.East);
      return;
    case SHOW_HELP:
      $('#docsFrame').attr('src', event.msg.docsURL);
      return;
    default:
      console.log('Unknown event type: ', event.type)
      return;
  }
}

function startEventSource() {
  if (HabiventsES == null || HabiventsES.readyState == 2) {
    HabiventsES = new EventSource('/events/'+AvatarName+'/eventStream');
    HabiventsES.onerror = function(e) {
      if (HabiventsES.readyState == 2) {
        console.log('Habivents EventSource disconnected, retrying in 3 secs:', e);
        setTimeout(startEventSource, 3000);
      }
    }
    HabiventsES.addEventListener('message', function(e) {
      var event = JSON.parse(e.data);
      processEvent(event);
    }, false);
  }
}

function doAction(type, params) {
  var action = {
    type: type,
    params: {},
  }
  if (params !== undefined) {
    action.params = params;
  }
  $.ajax('/api/v1/avatar/'+AvatarName+'/action', {
    data: JSON.stringify(action),
    contentType: 'application/json',
    type: 'POST',
    success: function () {
      console.log('Successfully sent action:', type, params);
    },
  });
}

function startEsp(avatarName) {
  doAction('START_ESP', {avatar: avatarName});
}

function sendTeleportInvite(avatarName) {
  doAction('SEND_TELEPORT_INVITE', {avatar: avatarName});
}

function sendTeleportRequest(avatarName) {
  doAction('SEND_TELEPORT_REQUEST', {avatar: avatarName});
}

function appendButton(element, avatarName, btnClass, text, tooltip, onclick) {
  var newButton = $('<button>');
  newButton
    .attr('id', avatarName)
    .attr('onclick', onclick)
    .attr('type', 'button')
    .attr('class', 'action-button btn btn-sm btn-'+btnClass)
    .attr('data-toggle', 'tooltip')
    .attr('data-placement', 'top')
    .attr('title', tooltip)
    .text(text);
  element.append(newButton);
  newButton.tooltip({
    trigger : 'hover'
  });
}

function fillOnlineAvatarsTable(avatars) {
  var tbody = $("#onlineAvatarsTable").find('tbody');

  var newCurrentAvatars = {}
  avatars.forEach(function(avatarObj) {
    newCurrentAvatars[avatarObj.avatar] = avatarObj.location;
  })

  // Removes rows corresponding to Avatars that are no longer logged in.
  var currentAvatarNames = Object.keys(CurrentAvatars);
  currentAvatarNames.forEach(function(avatarName) {
    if (!(avatarName in newCurrentAvatars)) {
      $('#avatar-'+avatarName.hashCode()).remove();
    }
  })

  // Adds rows corresponding to Avatars that are newly logged in.
  avatars.forEach(function(avatarObj) {
    if (avatarObj.avatar in CurrentAvatars) {
      return;
    }

    var avatarRow = $('
');
    avatarRow.attr('id', 'avatar-'+avatarObj.avatar.hashCode());
    avatarRow.attr('class', 'avatar-row');
    var avatarCell = $('');

    var avatarIdentity = $('
');
    avatarIdentity.attr('class', 'no-margin');
    avatarIdentity.html(''+avatarObj.avatar+'
'+avatarObj.location);

    avatarCell.append(avatarIdentity);

    if (avatarObj.avatar !== AvatarName) {
      // appendButton(avatarCell, avatarObj.avatar,
      //   'primary start-esp', 'E', 'Start ESP',
      //   'startEsp("'+avatarObj.avatar+'")');
      appendButton(avatarCell, avatarObj.avatar,
        'info teleport-invite', 'I', 'Invite Avatar to Teleport Here',
        'sendTeleportInvite("'+avatarObj.avatar+'")');
      appendButton(avatarCell, avatarObj.avatar,
        'success teleport-request', 'R', 'Request to Join Avatar',
        'sendTeleportRequest("'+avatarObj.avatar+'")');
    }

    avatarRow.append(avatarCell);
    tbody.append(avatarRow);
  });

  CurrentAvatars = newCurrentAvatars;
}

function refreshAvatars() {
  $.get('/api/v1/worldview/avatars', function(data) {
    fillOnlineAvatarsTable(data.avatars);
  }, 'json');
}

function startDocentUpdates() {
  startEventSource();
  refreshAvatars();
  setInterval(refreshAvatars, 5000 + Math.floor(Math.random() * 2000));
}
<commit_msg>Removes extraneous console log<commit_after>var CONNECTED = 'CONNECTED';
var REGION_CHANGE = 'REGION_CHANGE';
var SHOW_HELP = 'SHOW_HELP';

var HabiventsES = null;
var CurrentAvatars = {};

function orientationToRotation(orientation) {
  switch (orientation) {
    case 'North':
      return 270;
    case 'West':
      return 90;
    case 'South':
      return 180;
    case 'East':
      return 0;
    default:
      return 0;
  }
}

const HTMLArrows = ['↑', '←', '↓', '→'];
const orient     = ["West", "East", "North", "South"];

function processEvent(event) {
  switch (event.type) {
    case CONNECTED:
      return;
    case REGION_CHANGE:
      $('#regionHeader').text(event.msg.description);
      $('#docsFrame').attr('src', event.msg.docsURL);
      $('#orientationHeader').text(event.msg.orientation);
      $("#compass").rotate({
        animateTo: orientationToRotation(event.msg.orientation),
      })
      var arrow = (orient.indexOf(event.msg.orientation) + 3) % 4;
      $("#northArrow").html(HTMLArrows[arrow]);
      $("#northHeader").text(event.msg.neighbors.North);
      arrow = ++arrow % 4;
      $("#westArrow").html(HTMLArrows[arrow]);
      $("#westHeader").text(event.msg.neighbors.West);
      arrow = ++arrow % 4;
      $("#southArrow").html(HTMLArrows[arrow]);
      $("#southHeader").text(event.msg.neighbors.South);
      arrow = ++arrow % 4;
      $("#eastArrow").html(HTMLArrows[arrow]);
      $("#eastHeader").text(event.msg.neighbors.East);
      return;
    case SHOW_HELP:
      $('#docsFrame').attr('src', event.msg.docsURL);
      return;
    default:
      console.log('Unknown event type: ', event.type)
      return;
  }
}

function startEventSource() {
  if (HabiventsES == null || HabiventsES.readyState == 2) {
    HabiventsES = new EventSource('/events/'+AvatarName+'/eventStream');
    HabiventsES.onerror = function(e) {
      if (HabiventsES.readyState == 2) {
        console.log('Habivents EventSource disconnected, retrying in 3 secs:', e);
        setTimeout(startEventSource, 3000);
      }
    }
    HabiventsES.addEventListener('message', function(e) {
      var event = JSON.parse(e.data);
      processEvent(event);
    }, false);
  }
}

function doAction(type, params) {
  var action = {
    type: type,
    params: {},
  }
  if (params !== undefined) {
    action.params = params;
  }
  $.ajax('/api/v1/avatar/'+AvatarName+'/action', {
    data: JSON.stringify(action),
    contentType: 'application/json',
    type: 'POST',
    success: function () {
      console.log('Successfully sent action:', type, params);
    },
  });
}

function startEsp(avatarName) {
  doAction('START_ESP', {avatar: avatarName});
}

function sendTeleportInvite(avatarName) {
  doAction('SEND_TELEPORT_INVITE', {avatar: avatarName});
}

function sendTeleportRequest(avatarName) {
  doAction('SEND_TELEPORT_REQUEST', {avatar: avatarName});
}

function appendButton(element, avatarName, btnClass, text, tooltip, onclick) {
  var newButton = $('<button>');
  newButton
    .attr('id', avatarName)
    .attr('onclick', onclick)
    .attr('type', 'button')
    .attr('class', 'action-button btn btn-sm btn-'+btnClass)
    .attr('data-toggle', 'tooltip')
    .attr('data-placement', 'top')
    .attr('title', tooltip)
    .text(text);
  element.append(newButton);
  newButton.tooltip({
    trigger : 'hover'
  });
}

function fillOnlineAvatarsTable(avatars) {
  var tbody = $("#onlineAvatarsTable").find('tbody');

  var newCurrentAvatars = {}
  avatars.forEach(function(avatarObj) {
    newCurrentAvatars[avatarObj.avatar] = avatarObj.location;
  })

  // Removes rows corresponding to Avatars that are no longer logged in.
  var currentAvatarNames = Object.keys(CurrentAvatars);
  currentAvatarNames.forEach(function(avatarName) {
    if (!(avatarName in newCurrentAvatars)) {
      $('#avatar-'+avatarName.hashCode()).remove();
    }
  })

  // Adds rows corresponding to Avatars that are newly logged in.
  avatars.forEach(function(avatarObj) {
    if (avatarObj.avatar in CurrentAvatars) {
      return;
    }

    var avatarRow = $('
');
    avatarRow.attr('id', 'avatar-'+avatarObj.avatar.hashCode());
    avatarRow.attr('class', 'avatar-row');
    var avatarCell = $('');

    var avatarIdentity = $('
');
    avatarIdentity.attr('class', 'no-margin');
    avatarIdentity.html(''+avatarObj.avatar+'
'+avatarObj.location);

    avatarCell.append(avatarIdentity);

    if (avatarObj.avatar !== AvatarName) {
      // appendButton(avatarCell, avatarObj.avatar,
      //   'primary start-esp', 'E', 'Start ESP',
      //   'startEsp("'+avatarObj.avatar+'")');
      appendButton(avatarCell, avatarObj.avatar,
        'info teleport-invite', 'I', 'Invite Avatar to Teleport Here',
        'sendTeleportInvite("'+avatarObj.avatar+'")');
      appendButton(avatarCell, avatarObj.avatar,
        'success teleport-request', 'R', 'Request to Join Avatar',
        'sendTeleportRequest("'+avatarObj.avatar+'")');
    }

    avatarRow.append(avatarCell);
    tbody.append(avatarRow);
  });

  CurrentAvatars = newCurrentAvatars;
}

function refreshAvatars() {
  $.get('/api/v1/worldview/avatars', function(data) {
    fillOnlineAvatarsTable(data.avatars);
  }, 'json');
}

function startDocentUpdates() {
  startEventSource();
  refreshAvatars();
  setInterval(refreshAvatars, 5000 + Math.floor(Math.random() * 2000));
}
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbigint = require('json-bigint');
const fbClient = require('./fb_client');
const apiaiClient = require('./apiai_client');

const WEBSERVER_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;

// Create apiai service
const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

/**
 * Process an incoming event from facebook
 *
 * @param event
 */
function processFacebookEvent(event) {

    // Get sender id
    var sender = event.sender.id.toString();

    var text = "";
    if (event.message && event.message.text) {
        text = event.message.text;
    } else if (event.postback && event.postback.payload) {
        text = event.postback.payload;
    }

    if (text) {

        // Store a new session for this sender
        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        fbClient.userInfoRequest(sender)
            .then(userInfoStr=> {
                // Initialize userInto
                var userInfo = {first_name: "friend"};
                try {
                    userInfo = JSON.parse(userInfoStr);
                } catch (err) {
                    console.error("Could not parse userInfoStr: %s", userInfoStr)
                }
                var apiaiRequest = apiAiService.textRequest(text,
                    {
                        sessionId: sessionIds.get(sender),
                        contexts: [
                            {
                                name: "generic",
                                parameters: {
                                    facebook_user: userInfo.first_name
                                }
                            }
                        ]
                    });

                // Handle response
                apiaiRequest.on('response', response => {
                    apiaiClient.handleApiAiResponse(sender, response);
                });
                apiaiRequest.on('error', error => console.error(error));
                apiaiRequest.end();

            }).catch(err => {
            console.error(err);
        });
    }
}

// Create Express Server
const app = express();

// Enable json parsing
app.use(bodyParser.text({type: 'application/json'}));

// Main webhook endpoint configuration
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(function () {
            fbClient.subscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', function (req, res) {
    try {
        // Load data
        var data = JSONbigint.parse(req.body);

        for (var i = 0; i < data.entry[0].messaging.length; i++) {
            var event = data.entry[0].messaging[i];
            processFacebookEvent(event);
        }
        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

// For testing purposes (testing api.ai-like callback posts)
app.post('/test-apiai-callback/', function (req, res) {
    try {
        // Load data
        var data = JSONbigint.parse(req.body);

        // Forward data to Api.AI
        apiaiClient.handleApiAiResponse('1217505768324329', data);

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }
});

// Start web server
app.listen(WEBSERVER_PORT, function () {
    console.log('Rest service ready on port ' + WEBSERVER_PORT);
});

// Subscribe
fbClient.subscribeRequest();<commit_msg>Fixing node module import<commit_after>/* jshint node: true */
'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('uuid');
const request = require('request');
const JSONbigint = require('json-bigint');
const fbClient = require('./fb_client');
const apiaiClient = require('./apiai_client');

const WEBSERVER_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;

// Create apiai service
const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

/**
 * Process an incoming event from facebook
 *
 * @param event
 */
function processFacebookEvent(event) {

    // Get sender id
    var sender = event.sender.id.toString();

    var text = "";
    if (event.message && event.message.text) {
        text = event.message.text;
    } else if (event.postback && event.postback.payload) {
        text = event.postback.payload;
    }

    if (text) {

        // Store a new session for this sender
        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        fbClient.userInfoRequest(sender)
            .then(userInfoStr=> {
                // Initialize userInto
                var userInfo = {first_name: "friend"};
                try {
                    userInfo = JSON.parse(userInfoStr);
                } catch (err) {
                    console.error("Could not parse userInfoStr: %s", userInfoStr)
                }
                var apiaiRequest = apiAiService.textRequest(text,
                    {
                        sessionId: sessionIds.get(sender),
                        contexts: [
                            {
                                name: "generic",
                                parameters: {
                                    facebook_user: userInfo.first_name
                                }
                            }
                        ]
                    });

                // Handle response
                apiaiRequest.on('response', response => {
                    apiaiClient.handleApiAiResponse(sender, response);
                });
                apiaiRequest.on('error', error => console.error(error));
                apiaiRequest.end();

            }).catch(err => {
            console.error(err);
        });
    }
}

// Create Express Server
const app = express();

// Enable json parsing
app.use(bodyParser.text({type: 'application/json'}));

// Main webhook endpoint configuration
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(function () {
            fbClient.subscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', function (req, res) {
    try {
        // Load data
        var data = JSONbigint.parse(req.body);

        for (var i = 0; i < data.entry[0].messaging.length; i++) {
            var event = data.entry[0].messaging[i];
            processFacebookEvent(event);
        }
        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

// For testing purposes (testing api.ai-like callback posts)
app.post('/test-apiai-callback/', function (req, res) {
    try {
        // Load data
        var data = JSONbigint.parse(req.body);

        // Forward data to Api.AI
        apiaiClient.handleApiAiResponse('1217505768324329', data);

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }
});

// Start web server
app.listen(WEBSERVER_PORT, function () {
    console.log('Rest service ready on port ' + WEBSERVER_PORT);
});

// Subscribe
fbClient.subscribeRequest();<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // ByteBuffer configuration
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {

      // Banner prepended to distribution
      banner: '/**\n' +
              ' * ByteBuffer v<%= pkg.version %>\n' +
              ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> <<%= pkg.homepage %>>\n' +
              ' *\n' +
              ' * Wrapper for ArrayBuffer/DataView maintaining index and default endianness.\n' +
              ' * Supports arbitrary reading/writing, automatic growth, slicing, cloning and\n' +
              ' * reversing as well as UTF-8 characters and NULL-terminated C-strings.\n' +
              ' *\n' +
              ' * The contents of this file are subject to the MIT License, under which\n' +
              ' * this library is licensed. See the LICENSE file for the full license.\n' +
              ' */'
    },

    // Compiles CoffeeScript source and specs
    coffee: {
      src: {
        dir: 'src',
        dest: 'build'
      },
      spec: {
        dir: 'spec',
        dest: 'build-spec'
      }
    },

    // Lints compiled JavaScript files
    lint: {
      files: [
        'grunt.js',
        'build/**/*.js',
        'build-spec/**/*.js',
        'vendor/**/*.js'
      ]
    },

    // Concatenate compiled JavaScript files
    concat: {
      dist: {
        src: [
          '<banner:meta.banner>',
          'build/byte-buffer.js'
        ],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },

    // Minified distribution
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },

    // Watch for changes to CoffeeScript files
    watch: {
      files: [
        'src/**/*.coffee',
        'spec/**/*.coffee'
      ],
      tasks: 'coffee lint buster concat'
    },

    // JSHint options
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: false,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        shadow: true
      },
      globals: {
        ByteBuffer: true,
        ArrayBuffer: true,
        DataView: true,
        Uint8Array: true,

        // BusterJS
        buster: true,
        describe: true,
        it: true,
        before: true,
        expect: true
      }
    },
    uglify: {}
  });

  grunt.loadTasks('tasks');

  grunt.registerTask('default', 'watch');
  grunt.registerTask('release', 'coffee lint buster concat min');

};
<commit_msg>Added JSLint global Uint16Array<commit_after>/*global module:false*/
module.exports = function(grunt) {

  // ByteBuffer configuration
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {

      // Banner prepended to distribution
      banner: '/**\n' +
              ' * ByteBuffer v<%= pkg.version %>\n' +
              ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> <<%= pkg.homepage %>>\n' +
              ' *\n' +
              ' * Wrapper for ArrayBuffer/DataView maintaining index and default endianness.\n' +
              ' * Supports arbitrary reading/writing, automatic growth, slicing, cloning and\n' +
              ' * reversing as well as UTF-8 characters and NULL-terminated C-strings.\n' +
              ' *\n' +
              ' * The contents of this file are subject to the MIT License, under which\n' +
              ' * this library is licensed. See the LICENSE file for the full license.\n' +
              ' */'
    },

    // Compiles CoffeeScript source and specs
    coffee: {
      src: {
        dir: 'src',
        dest: 'build'
      },
      spec: {
        dir: 'spec',
        dest: 'build-spec'
      }
    },

    // Lints compiled JavaScript files
    lint: {
      files: [
        'grunt.js',
        'build/**/*.js',
        'build-spec/**/*.js',
        'vendor/**/*.js'
      ]
    },

    // Concatenate compiled JavaScript files
    concat: {
      dist: {
        src: [
          '<banner:meta.banner>',
          'build/byte-buffer.js'
        ],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },

    // Minified distribution
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },

    // Watch for changes to CoffeeScript files
    watch: {
      files: [
        'src/**/*.coffee',
        'spec/**/*.coffee'
      ],
      tasks: 'coffee lint buster concat'
    },

    // JSHint options
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: false,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        shadow: true
      },
      globals: {
        ByteBuffer: true,
        ArrayBuffer: true,
        DataView: true,
        Uint8Array: true,
        Uint16Array: true,

        // BusterJS
        buster: true,
        describe: true,
        it: true,
        before: true,
        expect: true
      }
    },
    uglify: {}
  });

  grunt.loadTasks('tasks');

  grunt.registerTask('default', 'watch');
  grunt.registerTask('release', 'coffee lint buster concat min');

};
<|endoftext|>


<commit_before>module.exports = function (app, db) {

    app.get('/blog/:id', (req, res) => {

  });

    app.get('/blog', (req, res) => {
        db.collection('blog').find({}).toArray(function(err, blogs) {

            if(err) throw error;
            res.send(blogs);
        });
  });

    app.post('/addblog', (req, res) => {

        const note = req.body;

        db.collection('blog').insert(note, (err, result) => {
            if (err) {
                res.send({
                    'error': 'An error has occurred'
                });
            }
            else {
                res.send(result.ops[0]);
            }
        });
    });

};<commit_msg>fix json<commit_after>module.exports = function (app, db) {

    app.get('/blog/:id', (req, res) => {

  });

    app.get('/blog', (req, res) => {
        db.collection('blog').find({}).toArray(function(err, blogs) {

            if(err) throw error;
            res.send(blogs);
        });
  });

    app.post('/addblog', (req, res) => {

        const note = req.body;

        db.collection('blog').insert(note, (err, result) => {
            if (err) {
                res.send({
                    'error': 'An error has occurred'
                });
            }
            else {
                res.send(result.ops[0]);
            }
        });
    });

};<|endoftext|>


<commit_before>var app = angular.module("CBEcalc", ["xeditable"]);

app.run(function(editableOptions) {
  editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
  //editableOptions.buttons = no;
});

app.factory('classList', [function(){
  var o = {
    classList: []
  };
  return o;
}]);

app.factory('classPrefixes', [function(){
  var c = {
    classPrefixes: []
  };
  return c;
}]);

app.controller('MainCtrl', [
  '$scope',
  'classList',
  'classPrefixes',
  function($scope, classList, classPrefixes){
    $scope.classList = classList.classList;
    $scope.previousGPA = [];
    $scope.classPrefixes = classPrefixes.classPrefixes;
    $scope.gpa = (0.0).toFixed(2);
    $scope.totalCredits = 0;

    $scope.addClass = function(){
      if(!$scope.name || $scope.name === ''){
        return;
      }
      if(!$scope.grade || $scope.grade === ''){
        return;
      }
      if(!$scope.credits || $scope.credits === '' || $scope.credits != parseInt($scope.credits, 10)){
        return;
      }

      var gpa = 0;
      var tempGrade = $scope.grade;
      var letter = tempGrade.substring(0,1);
      var mod = '';
      if(tempGrade.length >= 2){
        mod = tempGrade.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }

      $scope.classList.push({
        name: $scope.name.substring(0,15),
        grade: letter.toUpperCase() + mod,
        gpa: gpa.toFixed(2),
        credits: $scope.credits
      });

      $scope.name = '';
      $scope.grade = '';
      $scope.credits = '';

      $scope.setGpa();

      return;
    };

    $scope.updatePrevious = function() {
      console.log("made it into function");
      console.log($scope.prevGPA);
      console.log($scope.prevCredits);
      if(!$scope.prevGPA || $scope.prevGPA === ''){
        return;
      }
      if(parseInt($scope.prevGPA) > 4){
        return;
      }
      if(!$scope.prevCredits || $scope.prevCredits === ''){
        return;
      }
      if($scope.prevCredits != parseInt($scope.prevCredits, 10)){
        return;
      }
      if($scope.previousGPA.length > 0){
        $scope.previousGPA.splice(0, $scope.previousGPA.length);
      }

      $scope.previousGPA.push({
        gpa: parseFloat($scope.prevGPA).toFixed(2),
        prevCredits: parseInt($scope.prevCredits)
      });

      $scope.prevGPA = '';
      $scope.prevCredits = '';

      $scope.setGpa();

      return;
    };

    $scope.setGpa = function() {
      var gpa = 0.00;
      var credits = 0.00;

      if($scope.previousGPA.length > 0){
        gpa = $scope.previousGPA[0].gpa * $scope.previousGPA[0].prevCredits;
        credits = $scope.previousGPA[0].prevCredits;
      }

      for(var i = 0 ; i < $scope.classList.length ; i++){
        gpa += (+$scope.classList[i].gpa * +$scope.classList[i].credits);
        credits += +$scope.classList[i].credits;
      }
      if(gpa != 0){
        gpa = gpa / credits;
      }
      $scope.totalCredits = credits;
      $scope.gpa = gpa.toFixed(2);
    };

    $scope.removeClass = function(item) {
      var index = $scope.classList.indexOf(item);
      $scope.classList.splice(index, 1);
      $scope.setGpa();
    };

    $scope.reCalc = function(index){
      var grades = [
        'A',
        'A-',
        'B',
        'B+',
        'B-',
        'C',
        'C+',
        'C-',
        'D',
        'D+',
        'D-',
        'F',
      ];
      var gpas = [
        4,
        3.7,
        3,
        3.3,
        2.7,
        2,
        2.3,
        1.7,
        1,
        1.3,
        0.7,
        0
      ];
      if(grades.indexOf($scope.classList[index].grade.toUpperCase()) < 0){
        $scope.classList[index].gpa = 0;
        $scope.classList[index].credits = 0;
        $scope.classList[index].grade = "invalid";
      }else{
        $scope.classList[index].gpa = gpas[grades.indexOf($scope.classList[index].grade.toUpperCase())].toFixed(2);
        $scope.classList[index].grade = $scope.classList[index].grade.toUpperCase();
      }

      $scope.setGpa();
    }

    /* Function to scrape text off page and parse out class information */
    $scope.addPrevClasses = function(info){
      var localData = String(info.data);
      var lines = localData.split('\n');
      var headers = [
        'ECON',
        'ACCT',
        'DSCI',
        'MIS',
        'FIN',
        'MRKT',
        'OPS',
        'MGMT',
        'IBUS',
        'HRM',
        'CSCI'
      ];
      var grades = [
        'A',
        'A+',
        'A-',
        'B',
        'B+',
        'B-',
        'C',
        'C+',
        'C-',
        'D',
        'D+',
        'D-',
        'F',
        'F+',
        'F-'
      ];
      for(var i = 0 ; i < lines.length ; i++){
        //split on space or group of spaces and store in lineArray
        var lineArray = lines[i].trim().split(/\s+/);

        if(headers.indexOf(lineArray[0]) >= 0){
          var tempName = (lineArray[0] + ' ' + lineArray[1]).substring(0, 8)
          var tempGrade;
          var tempCredits;
          /*
          for(var j = 0 ; j < grades.length ; j++){
            if((lineArray.indexOf(grades[j]) >= 0) || (lineArray.indexOf('K' + grades[j]) >= 0)){
              tempGrade = lineArray[j];
              break;
            }
          }*/

          for(var ind = 5; ind < lineArray.length; ind++){
            if(grades.indexOf(lineArray[ind])>=0){
              tempGrade = lineArray[ind];
              //credits are located one before the grade.
              tempCredits = lineArray[ind-1];
              break;
            }
          }

          $scope.classList.push({
            name: tempName,
            grade: tempGrade,
            gpa: getGPAValue(tempGrade).toFixed(1),
            credits: tempCredits
          });
        }
      }
      $scope.setGpa();
      return;
    };
  }
]);
//function to calculate GPA point based on letter grades
function getGPAValue(string){
  var gpa;
  var letter = string.substring(0,1);
  if(string.length >= 2){
        var mod = string.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          var mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }
  return gpa;
}

// Update the relevant fields with the new data
function setDOMInfo(info) {
  var scope = angular.element(document.getElementById("main")).scope();
  scope.$apply(function(){
    scope.classList.length = 0;
    scope.addPrevClasses(info);

  });
}

// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
  // ...query for the active tab...
  chrome.tabs.query({
    active: true,
    currentWindow: true
  }, function (tabs) {
    // ...and send a request for the DOM info...
    chrome.tabs.sendMessage(
        tabs[0].id,
        {from: 'popup', subject: 'DOMInfo'},
        // ...also specifying a callback to be called
        //    from the receiving end (content script)
        setDOMInfo);
  });
});
<commit_msg>Removed 'CSCI' from class list<commit_after>var app = angular.module("CBEcalc", ["xeditable"]);

app.run(function(editableOptions) {
  editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
  //editableOptions.buttons = no;
});

app.factory('classList', [function(){
  var o = {
    classList: []
  };
  return o;
}]);

app.factory('classPrefixes', [function(){
  var c = {
    classPrefixes: []
  };
  return c;
}]);

app.controller('MainCtrl', [
  '$scope',
  'classList',
  'classPrefixes',
  function($scope, classList, classPrefixes){
    $scope.classList = classList.classList;
    $scope.previousGPA = [];
    $scope.classPrefixes = classPrefixes.classPrefixes;
    $scope.gpa = (0.0).toFixed(2);
    $scope.totalCredits = 0;

    $scope.addClass = function(){
      if(!$scope.name || $scope.name === ''){
        return;
      }
      if(!$scope.grade || $scope.grade === ''){
        return;
      }
      if(!$scope.credits || $scope.credits === '' || $scope.credits != parseInt($scope.credits, 10)){
        return;
      }

      var gpa = 0;
      var tempGrade = $scope.grade;
      var letter = tempGrade.substring(0,1);
      var mod = '';
      if(tempGrade.length >= 2){
        mod = tempGrade.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }

      $scope.classList.push({
        name: $scope.name.substring(0,15),
        grade: letter.toUpperCase() + mod,
        gpa: gpa.toFixed(2),
        credits: $scope.credits
      });

      $scope.name = '';
      $scope.grade = '';
      $scope.credits = '';

      $scope.setGpa();

      return;
    };

    $scope.updatePrevious = function() {
      console.log("made it into function");
      console.log($scope.prevGPA);
      console.log($scope.prevCredits);
      if(!$scope.prevGPA || $scope.prevGPA === ''){
        return;
      }
      if(parseInt($scope.prevGPA) > 4){
        return;
      }
      if(!$scope.prevCredits || $scope.prevCredits === ''){
        return;
      }
      if($scope.prevCredits != parseInt($scope.prevCredits, 10)){
        return;
      }
      if($scope.previousGPA.length > 0){
        $scope.previousGPA.splice(0, $scope.previousGPA.length);
      }

      $scope.previousGPA.push({
        gpa: parseFloat($scope.prevGPA).toFixed(2),
        prevCredits: parseInt($scope.prevCredits)
      });

      $scope.prevGPA = '';
      $scope.prevCredits = '';

      $scope.setGpa();

      return;
    };

    $scope.setGpa = function() {
      var gpa = 0.00;
      var credits = 0.00;

      if($scope.previousGPA.length > 0){
        gpa = $scope.previousGPA[0].gpa * $scope.previousGPA[0].prevCredits;
        credits = $scope.previousGPA[0].prevCredits;
      }

      for(var i = 0 ; i < $scope.classList.length ; i++){
        gpa += (+$scope.classList[i].gpa * +$scope.classList[i].credits);
        credits += +$scope.classList[i].credits;
      }
      if(gpa != 0){
        gpa = gpa / credits;
      }
      $scope.totalCredits = credits;
      $scope.gpa = gpa.toFixed(2);
    };

    $scope.removeClass = function(item) {
      var index = $scope.classList.indexOf(item);
      $scope.classList.splice(index, 1);
      $scope.setGpa();
    };

    $scope.reCalc = function(index){
      var grades = [
        'A',
        'A-',
        'B',
        'B+',
        'B-',
        'C',
        'C+',
        'C-',
        'D',
        'D+',
        'D-',
        'F',
      ];
      var gpas = [
        4,
        3.7,
        3,
        3.3,
        2.7,
        2,
        2.3,
        1.7,
        1,
        1.3,
        0.7,
        0
      ];
      if(grades.indexOf($scope.classList[index].grade.toUpperCase()) < 0){
        $scope.classList[index].gpa = 0;
        $scope.classList[index].credits = 0;
        $scope.classList[index].grade = "invalid";
      }else{
        $scope.classList[index].gpa = gpas[grades.indexOf($scope.classList[index].grade.toUpperCase())].toFixed(2);
        $scope.classList[index].grade = $scope.classList[index].grade.toUpperCase();
      }

      $scope.setGpa();
    }

    /* Function to scrape text off page and parse out class information */
    $scope.addPrevClasses = function(info){
      var localData = String(info.data);
      var lines = localData.split('\n');
      var headers = [
        'ECON',
        'ACCT',
        'DSCI',
        'MIS',
        'FIN',
        'MRKT',
        'OPS',
        'MGMT',
        'IBUS',
        'HRM'
      ];
      var grades = [
        'A',
        'A+',
        'A-',
        'B',
        'B+',
        'B-',
        'C',
        'C+',
        'C-',
        'D',
        'D+',
        'D-',
        'F',
        'F+',
        'F-'
      ];
      for(var i = 0 ; i < lines.length ; i++){
        //split on space or group of spaces and store in lineArray
        var lineArray = lines[i].trim().split(/\s+/);

        if(headers.indexOf(lineArray[0]) >= 0){
          var tempName = (lineArray[0] + ' ' + lineArray[1]).substring(0, 8)
          var tempGrade;
          var tempCredits;
          /*
          for(var j = 0 ; j < grades.length ; j++){
            if((lineArray.indexOf(grades[j]) >= 0) || (lineArray.indexOf('K' + grades[j]) >= 0)){
              tempGrade = lineArray[j];
              break;
            }
          }*/

          for(var ind = 5; ind < lineArray.length; ind++){
            if(grades.indexOf(lineArray[ind])>=0){
              tempGrade = lineArray[ind];
              //credits are located one before the grade.
              tempCredits = lineArray[ind-1];
              break;
            }
          }

          $scope.classList.push({
            name: tempName,
            grade: tempGrade,
            gpa: getGPAValue(tempGrade).toFixed(1),
            credits: tempCredits
          });
        }
      }
      $scope.setGpa();
      return;
    };
  }
]);
//function to calculate GPA point based on letter grades
function getGPAValue(string){
  var gpa;
  var letter = string.substring(0,1);
  if(string.length >= 2){
        var mod = string.substring(1,2);
        if(!(mod === '+' || mod ==='-')){
          var mod = '';
        }
      }
      if(letter === "a" || letter === 'A'){
        gpa = 4;
      }else if(letter === "b" || letter === 'B'){
        gpa = 3;
      }else if(letter === "c" || letter === 'C'){
        gpa = 2;
      }else if(letter === "d" || letter === 'D'){
        gpa = 1;
      }else if(letter === "f" || letter === 'F'){
        gpa = 0;
      }else{
        return;
      }

      if(mod === '+' && gpa < 4){
        gpa += 0.3;
      }else if(mod === '-'){
        gpa -= 0.3;
      }
  return gpa;
}

// Update the relevant fields with the new data
function setDOMInfo(info) {
  var scope = angular.element(document.getElementById("main")).scope();
  scope.$apply(function(){
    scope.classList.length = 0;
    scope.addPrevClasses(info);

  });
}

// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', function () {
  // ...query for the active tab...
  chrome.tabs.query({
    active: true,
    currentWindow: true
  }, function (tabs) {
    // ...and send a request for the DOM info...
    chrome.tabs.sendMessage(
        tabs[0].id,
        {from: 'popup', subject: 'DOMInfo'},
        // ...also specifying a callback to be called
        //    from the receiving end (content script)
        setDOMInfo);
  });
});
<|endoftext|>


<commit_before>const model = new falcor.Model({
  source: new falcor.HttpDataSource('/model.json')});

//model.get('pokemon["name", "species"]').then(pokemon   => console.log(pokemon));

model
  .get('pokemon[0..10].["name", "species", "image"]')
  .then((result) => {
    debugger;
    const pokemonObject = result.json.pokemon;
    const pokemonArray = Object.keys(pokemonObject)
      .map(key => pokemonObject[key]);
    console.log(pokemonArray);
    renderTiles(pokemonArray)
  });

function renderTiles(tiles) {
  const contentDiv = document.querySelector('#content');
  contentDiv.innerHTML = tiles
    .map(tile => tileToHtml(tile)).join('');
}

function tileToHtml(tile) {
  tile.src = 'https://zemanifesto.files.wordpress.com/2014/07/bravecor1.jpg'; // temp
  return `

${tile.name}

Water

Some quick example text to build on the card title and make up the bulk of the card's content.

        Details »

  `;
}
<commit_msg>Show badges with colors<commit_after>const model = new falcor.Model({
  source: new falcor.HttpDataSource('/model.json')});

const speciesColors = {
  Normal: '#9C9C63',
  Fighting: '#AE2A24',
  Flying: '#8E6FEB',
  Poison: '#923A92',
  Ground: '#DBB54D',
  Rock: '#A48F32',
  Bug: '#97A51D',
  Ghost: '#644E88',
  Steel: '#A0A0C0',
  Fire: '#ED6D12',
  Water: '#4578ED',
  Grass: '#69C23D',
  Electric: '#F6C913',
  Ice: '#7ECECE',
  Dragon: '#5E1DF7',
  Dark: '#644E40',
  Fairy: '#E87890',
  Unknown: '',
  Shadow: '',
  Psychic: '#F73670'
};

//model.get('pokemon["name", "species"]').then(pokemon   => console.log(pokemon));

model
  .get('pokemon[0..10].["name", "species", "image"]')
  .then((result) => {
    debugger;
    const pokemonObject = result.json.pokemon;
    const pokemonArray = Object.keys(pokemonObject)
      .map(key => pokemonObject[key]);
    console.log(pokemonArray);
    renderTiles(pokemonArray)
  });

function renderTiles(tiles) {
  const contentDiv = document.querySelector('#content');
  contentDiv.innerHTML = tiles
    .map(tile => tileToHtml(tile)).join('');
}

function showBadges(species) {
  return species.map(function (type) {
    return `<span class="label" style="background-color: ${speciesColors[type]}">${type}</span>`;
  }).join(' ');
}

function tileToHtml(tile) {
  // temp
  tile.src = 'https://zemanifesto.files.wordpress.com/2014/07/bravecor1.jpg';
  tile.species = ['Water', 'Fire', 'Normal', 'Fighting'];

  return `

${tile.name}

${showBadges(tile.species)}

Some quick example text to build on the card title and make up the bulk of the card's content.

        Details »

  `;
}
<|endoftext|>