<commit_before>/**
 * JavaScript for the BucketList FieldFrame field type.
 *
 * @package		BucketList
 * @author 		Stephen Lewis (http://eepro.co.uk/)
 * @copyright 	Copyright (c) 2009, Stephen Lewis
 * @link 		http://eepro.co.uk/bucketlist/
 */

// Is the downloads status bar visible?
statusActive = false;

/**
 * Controls the display of the status bar.
 *
 * @access	private
 * @param 	bool	showStatus		Show or hide the status bar (default true).
 * @return 	void
 */
function displayStatusBar(showStatus) {

	// Enough with the typing.
	$statusBar = $('#bucketload-status');

	// Where are we heading to?
	targetBottom = (showStatus === false) ? -$statusBar.outerHeight(true) * 1.5 : 0;

	// Animate!
	$statusBar.stop(true, false).animate({bottom : targetBottom}, 500, function() {
		statusActive = (showStatus !== false);
	});
}

/**
 * Removes an upload item from the list.
 *
 * @access	private
 * @param 	string		uploadId		The upload ID of the item to remove.
 * @return 	void.
 */
function removeUpload(uploadId) {

	// Shorthand.
	$item = $('#bucketload-status-' + uploadId);

	// Hide the item.
	$item.animate({width : 'hide', opacity : 0}, 500, function() {
		// If this is the last item, hide the bar.
		if ($(this).siblings().length == 0) {
			displayStatusBar(false);
		}

		// Remove this item.
		$(this).remove();
	});
}

/**
 * Notifies the user of a successful upload.
 *
 * @access	private
 * @param 	object		params		listItem, message, status, uploadId.
 */
function uploadSuccess(params) {
	$('li#bucketload-status-' + params['uploadId'])
		.removeClass('active')
		.addClass('complete')
		.html(params.message);

	setTimeout('removeUpload("' + params.uploadId + '")', 1500);
}

/**
 * Notifies the user of a failed upload.
 *
 * @access	private
 * @param	object		params		listItem, message, status, uploadId.
 */
function uploadFailure(params) {
	if (params.message == '' || params.message == 'undefined') {
		params.message = languageStrings.uploadFailureGeneric;
	}

	$('#bucketload-status li#bucketload-status-' + params.uploadId)
		.removeClass('active')
		.addClass('error')
		.html(params.message);
}

/**
 * Notifies the user that the upload has started, by adding an item
 * to the upload list.
 *
 * @access	private
 * @param	object		params		fileName, uploadId.
 */
function uploadStart(params) {
	// Stupid IE has to be different, and include some nonsense path with the file name.
	fileName = params.fileName.replace(/.*(\/|\\)/, '');

	// Create the new item, append it to the list, and fade it in.
	$li = $('
' + fileName + '
');
	$li.appendTo('#bucketload-status ul').hide().fadeIn('fast');

	// If the status bar is currently hidden, show it.
	if (statusActive == false) {
		displayStatusBar(true);
	}
}

/**
 * Alerts the user to in-progress uploads when he attempts to save, preview, or quick save
 * the page. If there are no in-progress uploads, we let him proceed without question.
 *
 * @access	public
 * @param 	object		e		jQuery event object.
 */
function handleSubmit(e) {
	pendingUploads = $('#bucketload-status li').length;

	if (typeof(pendingUploads) == 'number' && pendingUploads > 0) {
		return confirm(languageStrings.confirmExit);
	}
}

/**
 * Alerts the user to in-progress uploads when he attempts to navigate away from
 * the page, or close the window. If there are no in-progress uploads, we let him
 * proceed without question.
 *
 * @access	public
 * @param 	object		e		Native browser event object (event not bound using jQuery)
 */
function handleNavigate(e) {
	pendingUploads = $('#bucketload-status li').length;

	if (typeof(pendingUploads) == 'number' && pendingUploads > 0) {
		return languageStrings.confirmExit;
	}
}

/**
 * ------------------------------------------------------------------
 * Initialisation.
 * ------------------------------------------------------------------
 */

$(document).ready(function() {

	selector = 'input[type="submit"][name="preview"], input[type="submit"][name="save"], input[type="submit"][name="submit"]';

	$(selector).bind('click', handleSubmit);
	window.onbeforeunload = handleNavigate;		// Do it the old-fashioned way. The jQuery event seems rather flakey.

	/**
	 * We post any AJAX requests back to the current URL, to be handled by
	 * the sessions_start hook.
	 *
	 * The advantages of doing it this way are two-fold:
	 * 1. We know for certain that the FieldFrame extension will be instantiated
	 * for this page, so all the FF-dependent gumpf in the BucketList fieldtype
	 * will work as expected.
	 *
	 * 2. Everything will work in the CP, and in a SAEF. Spiffing.
	 */

	// Create the upload status bar.
	$('body').append('

');

	// Hide the status bar, in case it isn't already.
	displayStatusBar(false);

	targetURL = document.location.href;

	$.fn.bucketlist.defaults.ajaxScriptURL 		= targetURL;
	$.fn.bucketlist.defaults.uploadFormAction	= targetURL;
	$.fn.bucketlist.defaults.onUploadFailure 	= uploadFailure;
	$.fn.bucketlist.defaults.onUploadStart		= uploadStart;
	$.fn.bucketlist.defaults.onUploadSuccess	= uploadSuccess;

	// Initialise non-matrix file trees.
	$('.ff-ft > .eepro-co-uk > .bucketlist-ui').each(function() {
		$(this).bucketlist({initialFile : $(this).next(':hidden').val()});
	});

	// Initialise matrix file trees.
	if (typeof $.fn.ffMatrix != 'undefined') {

		/**
		 * Initialise matrix file trees. Also handles new table cells as
		 * they are created.
		 *
		 * This is the only way of doing this at present, but by Brandon's
		 * own admission it's a trifle flakey, and has a habit of running
		 * twice.
		 *
		 * I tried checking for the presence of the BucketList file tree,
		 * but that wasn't working. Setting a class 'flag' on the td
		 * works fine though.
		 *
		 * Of course, we're screwed if FF Matrix ever fails to trigger
		 * this method.
		 */

		$.fn.ffMatrix.onDisplayCell.bucketlist = function(td, matrix) {
			$td = $(td);

			if ($td.hasClass('.bucketlist-ready') == false) {
				$td.addClass('bucketlist-ready').find('.bucketlist-ui').each(function() {
					$(this).bucketlist({
						initialFile : $(this).parents('.eepro-co-uk').find('input:hidden').val()
					});
				});
			}
		}
	}
});<commit_msg>Rearranged things to bypass problem with jQuery.noConflict() being used in other add-ons.<commit_after>/**
 * JavaScript for the BucketList FieldFrame field type.
 *
 * @package		BucketList
 * @author 		Stephen Lewis (http://eepro.co.uk/)
 * @copyright 	Copyright (c) 2009, Stephen Lewis
 * @link 		http://eepro.co.uk/bucketlist/
 */

jQuery.noConflict();
jQuery(document).ready(function($) {

	// Is the downloads status bar visible?
	statusActive = false;

	/**
	 * Controls the display of the status bar.
	 *
	 * @access	private
	 * @param 	bool	showStatus		Show or hide the status bar (default true).
	 * @return 	void
	 */
	function displayStatusBar(showStatus) {

		// Enough with the typing.
		$statusBar = $('#bucketload-status');

		// Where are we heading to?
		targetBottom = (showStatus === false) ? -$statusBar.outerHeight(true) * 1.5 : 0;

		// Animate!
		$statusBar.stop(true, false).animate({bottom : targetBottom}, 500, function() {
			statusActive = (showStatus !== false);
		});
	}

	/**
	 * Removes an upload item from the list.
	 *
	 * @access	private
	 * @param 	string		uploadId		The upload ID of the item to remove.
	 * @return 	void.
	 */
	function removeUpload(uploadId) {

		// Shorthand.
		$item = $('#bucketload-status-' + uploadId);

		// Hide the item.
		$item.animate({width : 'hide', opacity : 0}, 500, function() {
			// If this is the last item, hide the bar.
			if ($(this).siblings().length == 0) {
				displayStatusBar(false);
			}

			// Remove this item.
			$(this).remove();
		});
	}

	/**
	 * Notifies the user of a successful upload.
	 *
	 * @access	private
	 * @param 	object		params		listItem, message, status, uploadId.
	 */
	function uploadSuccess(params) {
		$('li#bucketload-status-' + params['uploadId'])
			.removeClass('active')
			.addClass('complete')
			.html(params.message);

		setTimeout('removeUpload("' + params.uploadId + '")', 1500);
	}

	/**
	 * Notifies the user of a failed upload.
	 *
	 * @access	private
	 * @param	object		params		listItem, message, status, uploadId.
	 */
	function uploadFailure(params) {
		if (params.message == '' || params.message == 'undefined') {
			params.message = languageStrings.uploadFailureGeneric;
		}

		$('#bucketload-status li#bucketload-status-' + params.uploadId)
			.removeClass('active')
			.addClass('error')
			.html(params.message);
	}

	/**
	 * Notifies the user that the upload has started, by adding an item
	 * to the upload list.
	 *
	 * @access	private
	 * @param	object		params		fileName, uploadId.
	 */
	function uploadStart(params) {
		// Stupid IE has to be different, and include some nonsense path with the file name.
		fileName = params.fileName.replace(/.*(\/|\\)/, '');

		// Create the new item, append it to the list, and fade it in.
		$li = $('
' + fileName + '
');
		$li.appendTo('#bucketload-status ul').hide().fadeIn('fast');

		// If the status bar is currently hidden, show it.
		if (statusActive == false) {
			displayStatusBar(true);
		}
	}

	/**
	 * Alerts the user to in-progress uploads when he attempts to save, preview, or quick save
	 * the page. If there are no in-progress uploads, we let him proceed without question.
	 *
	 * @access	public
	 * @param 	object		e		jQuery event object.
	 */
	function handleSubmit(e) {
		pendingUploads = $('#bucketload-status li').length;

		if (typeof(pendingUploads) == 'number' && pendingUploads > 0) {
			return confirm(languageStrings.confirmExit);
		}
	}

	/**
	 * Alerts the user to in-progress uploads when he attempts to navigate away from
	 * the page, or close the window. If there are no in-progress uploads, we let him
	 * proceed without question.
	 *
	 * @access	public
	 * @param 	object		e		Native browser event object (event not bound using jQuery)
	 */
	function handleNavigate(e) {
		pendingUploads = $('#bucketload-status li').length;

		if (typeof(pendingUploads) == 'number' && pendingUploads > 0) {
			return languageStrings.confirmExit;
		}
	}

	/**
	 * ------------------------------------------------------------------
	 * Initialisation.
	 * ------------------------------------------------------------------
	 */

	selector = 'input[type="submit"][name="preview"], input[type="submit"][name="save"], input[type="submit"][name="submit"]';

	$(selector).bind('click', handleSubmit);
	window.onbeforeunload = handleNavigate;		// Do it the old-fashioned way. The jQuery event seems rather flakey.

	/**
	 * We post any AJAX requests back to the current URL, to be handled by
	 * the sessions_start hook.
	 *
	 * The advantages of doing it this way are two-fold:
	 * 1. We know for certain that the FieldFrame extension will be instantiated
	 * for this page, so all the FF-dependent gumpf in the BucketList fieldtype
	 * will work as expected.
	 *
	 * 2. Everything will work in the CP, and in a SAEF. Spiffing.
	 */

	// Create the upload status bar.
	$('body').append('

');

	// Hide the status bar, in case it isn't already.
	displayStatusBar(false);

	targetURL = document.location.href;

	$.fn.bucketlist.defaults.ajaxScriptURL 		= targetURL;
	$.fn.bucketlist.defaults.uploadFormAction	= targetURL;
	$.fn.bucketlist.defaults.onUploadFailure 	= uploadFailure;
	$.fn.bucketlist.defaults.onUploadStart		= uploadStart;
	$.fn.bucketlist.defaults.onUploadSuccess	= uploadSuccess;

	// Initialise non-matrix file trees.
	$('.ff-ft > .eepro-co-uk > .bucketlist-ui').each(function() {
		$(this).bucketlist({initialFile : $(this).next(':hidden').val()});
	});

	// Initialise matrix file trees.
	if (typeof $.fn.ffMatrix != 'undefined') {

		/**
		 * Initialise matrix file trees. Also handles new table cells as
		 * they are created.
		 *
		 * This is the only way of doing this at present, but by Brandon's
		 * own admission it's a trifle flakey, and has a habit of running
		 * twice.
		 *
		 * I tried checking for the presence of the BucketList file tree,
		 * but that wasn't working. Setting a class 'flag' on the td
		 * works fine though.
		 *
		 * Of course, we're screwed if FF Matrix ever fails to trigger
		 * this method.
		 */

		$.fn.ffMatrix.onDisplayCell.bucketlist = function(td, matrix) {
			$td = $(td);

			if ($td.hasClass('.bucketlist-ready') == false) {
				$td.addClass('bucketlist-ready').find('.bucketlist-ui').each(function() {
					$(this).bucketlist({
						initialFile : $(this).parents('.eepro-co-uk').find('input:hidden').val()
					});
				});
			}
		}
	}
});<|endoftext|>


<commit_before>import { templateLoader } from 'template-loader';
import * as data from 'data';
import { router } from 'main';

// fix empty cell property - level4
const $root = $('#root'),
    $popupDiv = $('<div/>')
        .attr('id', 'endgame-message')
        .hide(),
    $img = $('<img/>').appendTo($popupDiv),
    $message = $('<span/>').appendTo($popupDiv),
    $btn = $('<a/>')
        .attr('class', 'btn')
        .attr('href', '#/map')
        .html('Continue')
        .appendTo($popupDiv);

const promise = new Promise(function (resolve, reject) {
    resolve($popupDiv);
});

function endGame(message, img, $original) {
    $message.text(message);
    $img.attr('src', img);
    promise
        .then(($popupDiv) => {
            $('.container').addClass('stop-game');
            $('iframe').hide();
            $popupDiv.show()
            return Promise.resolve($original);
        })
        .then(($original) => {
            $('.btn').on('click', function () {
                $('.container').replaceWith($original.clone());
                $popupDiv.hide();
                $('iframe').show();
                router.navigate('map');
            });
        });
}

export function get(params) {
    const { level } = params;
    Promise.all([
        templateLoader.get('puzzle'),
        data.getPuzzle(level)
    ])
        .then(([template, puzzle]) => {
            $root.html(template(puzzle));
            const $original = $('.container').clone();
            $popupDiv.appendTo($root);

            return Promise.resolve([puzzle, $original]);
        })
        .then(([puzzle, $original]) => {
            let counter = 0;
            let pointsFunc = setInterval(function () { decreasePoints() }, 2000); // promise
            function decreasePoints() {
                let points = $('#current-points').html();
                points -= 1;
                if (points <= 0) {
                    points = 0;
                    clearInterval(pointsFunc);
                    endGame("Sorry! You couldn't solved The Lemon-Miner puzzle! Try again",
                        '../../css/images/sad-ninja.jpg',
                        $original);
                }
                $('#current-points').html(points);
            }

            $('.cell').on('click', function () {
                const emptyCellsCount = (puzzle.size * puzzle.size / 2 | 0) + puzzle.difficultness;
                const col = $(this).parent().children().index($(this));
                const row = $(this).parent().parent().children().index($(this).parent());
                $(this).removeClass('close');
                $(this).removeClass('mark');
                if (puzzle.field[row - 1][col - 1].isMine) {
                    $(this).addClass('mine');
                    let points = $('#current-points').html();
                    points -= 10;
                    if (points <= 0) {
                        points = 0;
                        clearInterval(pointsFunc);
                        endGame("Sorry! You couldn't solved The Lemon-Miner puzzle! Try again",
                            '../../css/images/sad-ninja.jpg',
                            $original);
                    }
                    $('#current-points').html(points);
                }
                else {
                    counter += 1;
                }

                if (counter === emptyCellsCount) {
                    clearInterval(pointsFunc);

                    let points = $('#current-points').html();
                    data.getReachedLevel() //puzzle.level
                        .then(currentLevel => {
                            data.saveScore(points, puzzle.level);
                            if (currentLevel == puzzle.level) {
                                const reachedLevel = currentLevel + 1;
                                data.updateReachedLevel(reachedLevel);
                            }
                        });

                    endGame("Great! You have solved The Lemon-Miner puzzle!",
                        '../../css/images//won-game.jpg',
                        $original);
                }
            });

            $('.cell').on('contextmenu', function () {
                if ($(this).hasClass('close')) {
                    $(this).toggleClass('mark');
                }
            });
        });
}<commit_msg>fix bug<commit_after>import { templateLoader } from 'template-loader';
import * as data from 'data';
import { router } from 'main';

// fix empty cell property - level4
const $root = $('#root'),
    $popupDiv = $('<div/>')
        .attr('id', 'endgame-message')
        .hide(),
    $img = $('<img/>').appendTo($popupDiv),
    $message = $('<span/>').appendTo($popupDiv),
    $btn = $('<a/>')
        .attr('class', 'btn')
        .attr('href', '#/map')
        .html('Continue')
        .appendTo($popupDiv);

const promise = new Promise(function (resolve, reject) {
    resolve($popupDiv);
});

function endGame(message, img, $original) {
    $message.text(message);
    $img.attr('src', img);
    promise
        .then(($popupDiv) => {
            $('.container').addClass('stop-game');
            $('iframe').hide();
            $popupDiv.show()
            return Promise.resolve($original);
        })
        .then(($original) => {
            $('.btn').on('click', function () {
                $('.container').replaceWith($original.clone());
                $popupDiv.hide();
                $('iframe').show();
                router.navigate('map');
            });
        });
}

export function get(params) {
    const { level } = params;
    Promise.all([
        templateLoader.get('puzzle'),
        data.getPuzzle(level)
    ])
        .then(([template, puzzle]) => {
            $root.html(template(puzzle));
            const $original = $('.container').clone();
            $popupDiv.appendTo($root);

            return Promise.resolve([puzzle, $original]);
        })
        .then(([puzzle, $original]) => {
            let counter = 0;
            let pointsFunc = setInterval(function () { decreasePoints() }, 2000); // promise
            function decreasePoints() {
                let points = $('#current-points').html();
                points -= 1;
                if (points <= 0) {
                    points = 0;
                    clearInterval(pointsFunc);
                    endGame("Sorry! You couldn't solved The Lemon-Miner puzzle! Try again",
                        '../../css/images/sad-ninja.jpg',
                        $original);
                }
                $('#current-points').html(points);
            }

            $('.cell').on('click', function () {
                  const minesCount = (puzzle.size * puzzle.size / 2 | 0) + 1 - puzzle.difficultness,
emptyCellsCount = puzzle.size * puzzle.size - minesCount;
                const col = $(this).parent().children().index($(this));
                const row = $(this).parent().parent().children().index($(this).parent());
                $(this).removeClass('close');
                $(this).removeClass('mark');
                if (puzzle.field[row - 1][col - 1].isMine) {
                    $(this).addClass('mine');
                    let points = $('#current-points').html();
                    points -= 10;
                    if (points <= 0) {
                        points = 0;
                        clearInterval(pointsFunc);
                        endGame("Sorry! You couldn't solved The Lemon-Miner puzzle! Try again",
                            '../../css/images/sad-ninja.jpg',
                            $original);
                    }
                    $('#current-points').html(points);
                }
                else {
                    counter += 1;
                }

                if (counter === emptyCellsCount) {
                    clearInterval(pointsFunc);

                    let points = $('#current-points').html();
                    data.getReachedLevel() //puzzle.level
                        .then(currentLevel => {
                            data.saveScore(points, puzzle.level);
                            if (currentLevel == puzzle.level) {
                                const reachedLevel = currentLevel + 1;
                                data.updateReachedLevel(reachedLevel);
                            }
                        });

                    endGame("Great! You have solved The Lemon-Miner puzzle!",
                        '../../css/images//won-game.jpg',
                        $original);
                }
            });

            $('.cell').on('contextmenu', function () {
                if ($(this).hasClass('close')) {
                    $(this).toggleClass('mark');
                }
            });
        });
}<|endoftext|>


<commit_before>// 16: object-literal - computed properties
// To do: make all tests pass, leave the assert lines unchanged!
// Follow the hints of the failure messages!

describe('Object literal properties may be computed values', () => {

  it('a computed property `x` needs to be surrounded by `[]`', () => {
    const propertyName = 'x';
    const obj = {[propertyName]: 2};
    assert.equal(obj.x, 1);
  });

  it('can also get a function assigned', () => {
    const key = 'func';
    const obj = {[key]: 'seven'};
    assert.equal(obj.func(), 'seven');
  });

  it('the key may also be the result of a function call', () => {
    const getName = () => 'propertyName';
    const obj = {[getName]() {return 'seven'}};
    assert.equal(obj.propertyName(), 'seven');
  });

  it('the key can also be constructed by an expression', () => {
    const what = 'Key';
    const obj = {['proper' + what]: null};
    assert.equal('propertyName' in obj, true);
  });

  it('accessor keys can be computed names too', () => {
    const obj = {
      set ['key'](_) {return 1}
    };
    assert.equal(obj.key, 1);
  });
});
<commit_msg>Katafy.<commit_after>// 16: object-literal - computed properties
// To do: make all tests pass, leave the assert lines unchanged!
// Follow the hints of the failure messages!

describe('Object literal properties may be computed values', () => {
  it('a computed property `x` needs to be surrounded by `[]`', () => {
    const propertyName = 'x';
    //// const obj = {propertyName: 1};
    const obj = {[propertyName]: 1};
    assert.equal(obj.x, 1);
  });
  it('can also get a function assigned', () => {
    const key = 'func';
    //// const obj = {[key]: 'seven'};
    const obj = {[key]: () => 'seven'};
    assert.equal(obj.func(), 'seven');
  });
  it('the key may also be the result of a function call', () => {
    const getName = () => 'propertyName';
    //// const obj = {[getName]() {return 'seven'}};
    const obj = {[getName()]() {return 'seven'}};
    assert.equal(obj.propertyName(), 'seven');
  });
  it('the key can also be constructed by an expression', () => {
    //// const what = 'Key';
    const what = 'tyName';
    const obj = {['proper' + what]: null};
    assert('propertyName' in obj);
  });
  it('accessor keys can be computed names too', () => {
    const obj = {
      set ['key'](_) {return 1},
      ////
      get ['key']() {return 1}
    };
    assert.equal(obj.key, 1);
  });
});
<|endoftext|>


<commit_before>// Paste this into node
// SLang = {};
// console.log ("SLang now defined");
// .load grammar.js
// console.log ("Grammar loaded");
// .load absyn.js
// console.log ("Absyn loaded");
// .load env.js
// console.log ("Environment loaded");
// .load interpreter.js
// console.log ("Interpreter loaded");
//
//   <script src="./scripts/grammar.js"></script>
//   <script src="./scripts/absyn.js"></script>
//   <script src="./scripts/env.js"></script>
//   <script src="./scripts/interpreter.js"></script>

//////////////////////

var x = 5;
var y = 6;

var util = require('util');
function print(struct) {
	 util.puts(util.inspect(struct, false ,null,true));
}

var name1 = require.resolve('./grammar');
delete require.cache[name1];
// var name2 = require.resolve('./absyn');
// delete require.cache[name2];
// var name3 = require.resolve('./env');
// delete require.cache[name3];

SLang = {};
var parser = require("./grammar");

//var absyn = require("./absyn");
.load absyn.js
//var env = require("./env");
.load env.js
.load interpreter.js

// To see environment, put the following at the beginning of the evalExp funtion in the interpreter
// require('util').puts(require('util').inspect(envir, false ,10,true));

// Examples:
print(parser.parse("+ (2,3)"));

print(parser.parse("(fn (x) => *(x,x) +(x,y))"));

SLang.interpret("(fn (x) => *(x,x) +(x,y))");

<commit_msg>removed emacs-related script that was incorrectly added<commit_after><|endoftext|>


<commit_before>"use strict";

class gswaSynth {
	constructor() {
		const gsdata = new GSDataSynth( {
				dataCallbacks: {
					addOsc: this._addOsc.bind( this ),
					removeOsc: this._removeOsc.bind( this ),
					updateOsc: this._updateOsc.bind( this ),
					updateLFO: this._updateLFO.bind( this ),
				},
			} );

		this._bps = 1;
		this.gsdata = gsdata;
		this.ctx =
		this.connectedTo = null;
		this.nyquist = 24000;
		this._nodes = new Map();
		this._startedKeys = new Map();
		Object.seal( this );
	}

	// Context, dis/connect
	// .........................................................................
	setContext( ctx ) {
		this.stopAllKeys();
		this.disconnect();
		this.ctx = ctx;
		this.nyquist = ctx.sampleRate / 2;
		this.gsdata.recall();
	}
	setBPM( bpm ) {
		this._bps = bpm / 60;
	}
	change( obj ) {
		this.gsdata.change( obj );
	}
	connect( dest ) {
		this._nodes.forEach( obj => obj.gain.connect( dest ) );
		this.connectedTo = dest;
	}
	disconnect() {
		this._nodes.forEach( obj => obj.gain.disconnect() );
		this.connectedTo = null;
	}

	// add/remove/update oscs
	// .........................................................................
	_removeOsc( id ) {
		const obj = this._nodes.get( id );

		obj.pan.disconnect();
		obj.gain.disconnect();
		this._startedKeys.forEach( key => {
			this._destroyOscNode( key.oscs.get( id ) );
			key.oscs.delete( id );
		} );
		this._nodes.delete( id );
	}
	_addOsc( id, osc ) {
		const gain = this.ctx.createGain(),
			pan = this.ctx.createStereoPanner();

		this._nodes.set( id, { gain, pan } );
		pan.pan.value = osc.pan;
		gain.gain.value = osc.gain;
		pan.connect( gain );
		if ( this.connectedTo ) {
			gain.connect( this.connectedTo );
		}
		this._startedKeys.forEach( key => key.oscs.set( id, this._createOscNode( key, id ) ) );
	}
	_updateOsc( id, obj ) {
		for ( const prop in obj ) {
			const val = obj[ prop ];

			switch ( prop ) {
				case "pan": this._nodes.get( id ).pan.pan.value = val; break;
				case "gain": this._nodes.get( id ).gain.gain.value = val; break;
				case "type":
				case "detune":
					this._startedKeys.forEach( prop === "detune"
						? key => key.oscs.get( id ).detune.value = val
						: key => this._nodeOscSetType( key.oscs.get( id ), val ) );
			}
		}
	}
	_updateLFO( obj ) {
		const nobj = Object.assign( {}, obj );

		if ( "delay" in obj ) { nobj.delay /= this._bps; }
		if ( "attack" in obj ) { nobj.attack /= this._bps; }
		if ( "speed" in obj ) { nobj.speed *= this._bps; }
		this._startedKeys.forEach( k => k.oscs.forEach( node => node._waLFO.change( nobj ) ) );
	}

	// start
	// .........................................................................
	startKey( blocks, when, off, dur ) {
		const id = ++gswaSynth._startedMaxId.value,
			oscs = new Map(),
			blcsLen = blocks.length,
			blc0 = blocks[ 0 ][ 1 ],
			blcLast = blocks[ blcsLen - 1 ][ 1 ],
			blc0when = blc0.when,
			bps = this._bps,
			key = {
				oscs,
				when,
				off,
				dur,
				pan: blc0.pan,
				midi: blc0.key,
				gain: blc0.gain,
				lowpass: blc0.lowpass,
				highpass: blc0.highpass,
				attack: blc0.attack / bps || .005,
				release: blcLast.release / bps || .005,
			};

		if ( blcsLen > 1 ) {
			key.variations = [];
			blocks.reduce( ( prev, [ , blc ] ) => {
				if ( prev ) {
					const prevWhen = prev.when - blc0when,
						when = ( prevWhen + prev.duration ) / bps;

					key.variations.push( {
						when,
						duration: ( blc.when - blc0when ) / bps - when,
						pan: [ prev.pan, blc.pan ],
						midi: [ prev.key, blc.key ],
						gain: [ prev.gain, blc.gain ],
						lowpass: [
							this._calcLowpass( prev.lowpass ),
							this._calcLowpass( blc.lowpass ),
						],
						highpass: [
							this._calcHighpass( prev.highpass ),
							this._calcHighpass( blc.highpass ),
						],
					} );
				}
				return blc;
			}, null );
		}
		Object.keys( this.gsdata.data.oscillators )
			.forEach( oscId => oscs.set( oscId, this._createOscNode( key, oscId ) ) );
		this._startedKeys.set( id, key );
		return id;
	}

	// stop
	// .........................................................................
	stopAllKeys() {
		this._startedKeys.forEach( ( _key, id ) => this.stopKey( id ) );
	}
	stopKey( id ) {
		const key = this._startedKeys.get( id );

		if ( key ) {
			const oscs = key.oscs;

			if ( Number.isFinite( key.dur ) ) {
				this._stopKey( id, oscs );
			} else {
				oscs.forEach( node => {
					node._gainNode.gain.setValueCurveAtTime(
						new Float32Array( [ key.gain, .1 ] ), this.ctx.currentTime + .01, .02 );
				} );
				setTimeout( this._stopKey.bind( this, id, oscs ), .033 * 1000 );
			}
		} else {
			console.error( "gswaSynth: stopKey id invalid", id );
		}
	}
	_stopKey( id, oscs ) {
		oscs.forEach( this._destroyOscNode, this );
		this._startedKeys.delete( id );
	}

	// private:
	_calcLowpass( val ) {
		return this._calcExp( val, this.nyquist, 2 );
	}
	_calcHighpass( val ) {
		return this._calcExp( 1 - val, this.nyquist, 3 );
	}
	_calcExp( x, total, exp ) {
		return exp === 0
			? x
			: Math.expm1( x ) ** exp / ( ( Math.E - 1 ) ** exp ) * total;
	}

	// default gain envelope
	_scheduleOscNodeGain( key, node ) {
		const va = key.variations,
			par = node._gainNode.gain,
			{ when, dur, gain, attack, release } = key;

		par.cancelScheduledValues( 0 );
		if ( !va || va[ 0 ].when > key.off ) {
			if ( key.off < .0001 ) {
				par.setValueAtTime( 0, when );
				par.setValueCurveAtTime( new Float32Array( [ 0, gain ] ), when, attack );
			} else {
				par.setValueAtTime( gain, when );
			}
		}
		if ( Number.isFinite( dur ) && dur - attack >= release ) {
			const vaLast = va && va[ va.length - 1 ],
				relWhen = when + dur - release;

			if ( !vaLast || when - key.off + vaLast.when + vaLast.duration < relWhen ) {
				const gainEnd = vaLast ? vaLast.gain[ 1 ] : gain;

				par.setValueCurveAtTime( new Float32Array( [ gainEnd, 0 ] ), relWhen, release );
			}
		}
	}

	// keys linked, variations
	_scheduleVariations( key, node ) {
		if ( key.variations ) {
			key.variations.forEach( va => {
				const when = key.when - key.off + va.when,
					dur = va.duration,
					freqArr = new Float32Array( [
						gswaSynth.midiKeyToHz[ va.midi[ 0 ] ],
						gswaSynth.midiKeyToHz[ va.midi[ 1 ] ]
					] );

				if ( when > this.ctx.currentTime && dur > 0 ) {
					node.frequency.setValueCurveAtTime( freqArr, when, dur );
					node._panNode.pan.setValueCurveAtTime( new Float32Array( va.pan ), when, dur );
					node._gainNode.gain.setValueCurveAtTime( new Float32Array( va.gain ), when, dur );
					node._lowpassNode.frequency.setValueCurveAtTime( new Float32Array( va.lowpass ), when, dur );
					node._highpassNode.frequency.setValueCurveAtTime( new Float32Array( va.highpass ), when, dur );
				}
			} );
		}
	}

	// createOscNode
	_createOscNode( key, oscId ) {
		const ctx = this.ctx,
			lfo = this.gsdata.data.lfo,
			osc = this.gsdata.data.oscillators[ oscId ],
			finite = Number.isFinite( key.dur ),
			atTime = key.when - key.off,
			waLFO = new gswaLFO( ctx ),
			node = ctx.createOscillator(),
			panNode = ctx.createStereoPanner(),
			gainNode = ctx.createGain(),
			lowpassNode = ctx.createBiquadFilter(),
			highpassNode = ctx.createBiquadFilter();

		node._waLFO = waLFO;
		node._panNode = panNode;
		node._gainNode = gainNode;
		node._lowpassNode = lowpassNode;
		node._highpassNode = highpassNode;
		lowpassNode.type = "lowpass";
		highpassNode.type = "highpass";
		this._nodeOscSetType( node, osc.type );
		node
			.connect( waLFO.node )
			.connect( panNode )
			.connect( lowpassNode )
			.connect( highpassNode )
			.connect( gainNode )
			.connect( this._nodes.get( oscId ).pan );
		node.detune.setValueAtTime( osc.detune, atTime );
		panNode.pan.setValueAtTime( key.pan, atTime );
		node.frequency.setValueAtTime( gswaSynth.midiKeyToHz[ key.midi ], atTime );
		lowpassNode.frequency.setValueAtTime( this._calcLowpass( key.lowpass ), atTime );
		highpassNode.frequency.setValueAtTime( this._calcHighpass( key.highpass ), atTime );
		this._scheduleOscNodeGain( key, node );
		this._scheduleVariations( key, node );
		node.start( key.when );
		waLFO.start( {
			toggle: lfo.toggle,
			when: key.when,
			whenStop: finite ? key.when + key.dur : 0,
			offset: key.offset,
			type: lfo.type,
			delay: lfo.delay / this._bps,
			attack: lfo.attack / this._bps,
			speed: lfo.speed * this._bps,
			amp: lfo.amp,
		} );
		if ( finite ) {
			node.stop( key.when + key.dur );
		}
		return node;
	}
	_destroyOscNode( node ) {
		node.stop();
		node.disconnect();
		node._waLFO.destroy();
		node._gainNode.disconnect();
	}
	_nodeOscSetType( node, type ) {
		if ( gswaSynth.nativeTypes.indexOf( type ) > -1 ) {
			node.type = type;
		} else {
			const w = gswaPeriodicWaves.get( type );

			node.setPeriodicWave( this.ctx.createPeriodicWave( w.real, w.imag ) );
		}
	}
}

gswaSynth._startedMaxId = Object.seal( { value: 0 } );
gswaSynth.nativeTypes = Object.freeze( [ "sine", "triangle", "sawtooth", "square" ] );
gswaSynth.midiKeyToHz = [];

Object.freeze( gswaSynth );
<commit_msg>gswaSynth: beautify<commit_after>"use strict";

class gswaSynth {
	constructor() {
		const gsdata = new GSDataSynth( {
				dataCallbacks: {
					addOsc: this._addOsc.bind( this ),
					removeOsc: this._removeOsc.bind( this ),
					updateOsc: this._updateOsc.bind( this ),
					updateLFO: this._updateLFO.bind( this ),
				},
			} );

		this._bps = 1;
		this.gsdata = gsdata;
		this.ctx =
		this.connectedTo = null;
		this.nyquist = 24000;
		this._nodes = new Map();
		this._startedKeys = new Map();
		Object.seal( this );
	}

	// Context, dis/connect
	// .........................................................................
	setContext( ctx ) {
		this.stopAllKeys();
		this.disconnect();
		this.ctx = ctx;
		this.nyquist = ctx.sampleRate / 2;
		this.gsdata.recall();
	}
	setBPM( bpm ) {
		this._bps = bpm / 60;
	}
	change( obj ) {
		this.gsdata.change( obj );
	}
	connect( dest ) {
		this._nodes.forEach( obj => obj.gain.connect( dest ) );
		this.connectedTo = dest;
	}
	disconnect() {
		this._nodes.forEach( obj => obj.gain.disconnect() );
		this.connectedTo = null;
	}

	// add/remove/update oscs
	// .........................................................................
	_removeOsc( id ) {
		const obj = this._nodes.get( id );

		obj.pan.disconnect();
		obj.gain.disconnect();
		this._startedKeys.forEach( key => {
			this._destroyOscNode( key.oscs.get( id ) );
			key.oscs.delete( id );
		} );
		this._nodes.delete( id );
	}
	_addOsc( id, osc ) {
		const gain = this.ctx.createGain(),
			pan = this.ctx.createStereoPanner();

		this._nodes.set( id, { gain, pan } );
		pan.pan.value = osc.pan;
		gain.gain.value = osc.gain;
		pan.connect( gain );
		if ( this.connectedTo ) {
			gain.connect( this.connectedTo );
		}
		this._startedKeys.forEach( key => key.oscs.set( id, this._createOscNode( key, id ) ) );
	}
	_updateOsc( id, obj ) {
		for ( const prop in obj ) {
			const val = obj[ prop ];

			switch ( prop ) {
				case "pan": this._nodes.get( id ).pan.pan.value = val; break;
				case "gain": this._nodes.get( id ).gain.gain.value = val; break;
				case "type":
				case "detune":
					this._startedKeys.forEach( prop === "detune"
						? key => key.oscs.get( id ).keyOsc.detune.value = val
						: key => this._nodeOscSetType( key.oscs.get( id ).keyOsc, val ) );
			}
		}
	}
	_updateLFO( obj ) {
		const nobj = Object.assign( {}, obj );

		if ( "delay" in obj ) { nobj.delay /= this._bps; }
		if ( "attack" in obj ) { nobj.attack /= this._bps; }
		if ( "speed" in obj ) { nobj.speed *= this._bps; }
		this._startedKeys.forEach( k => k.oscs.forEach( nodes => nodes.keyLFO.change( nobj ) ) );
	}

	// start
	// .........................................................................
	startKey( blocks, when, off, dur ) {
		const id = ++gswaSynth._startedMaxId.value,
			oscs = new Map(),
			blcsLen = blocks.length,
			blc0 = blocks[ 0 ][ 1 ],
			blcLast = blocks[ blcsLen - 1 ][ 1 ],
			blc0when = blc0.when,
			bps = this._bps,
			key = {
				oscs,
				when,
				off,
				dur,
				pan: blc0.pan,
				midi: blc0.key,
				gain: blc0.gain,
				lowpass: blc0.lowpass,
				highpass: blc0.highpass,
				attack: blc0.attack / bps || .005,
				release: blcLast.release / bps || .005,
			};

		if ( blcsLen > 1 ) {
			key.variations = [];
			blocks.reduce( ( prev, [ , blc ] ) => {
				if ( prev ) {
					const prevWhen = prev.when - blc0when,
						when = ( prevWhen + prev.duration ) / bps;

					key.variations.push( {
						when,
						duration: ( blc.when - blc0when ) / bps - when,
						pan: [ prev.pan, blc.pan ],
						midi: [ prev.key, blc.key ],
						gain: [ prev.gain, blc.gain ],
						lowpass: [
							this._calcLowpass( prev.lowpass ),
							this._calcLowpass( blc.lowpass ),
						],
						highpass: [
							this._calcHighpass( prev.highpass ),
							this._calcHighpass( blc.highpass ),
						],
					} );
				}
				return blc;
			}, null );
		}
		Object.keys( this.gsdata.data.oscillators )
			.forEach( oscId => oscs.set( oscId, this._createOscNode( key, oscId ) ) );
		this._startedKeys.set( id, key );
		return id;
	}

	// stop
	// .........................................................................
	stopAllKeys() {
		this._startedKeys.forEach( ( _key, id ) => this.stopKey( id ) );
	}
	stopKey( id ) {
		const key = this._startedKeys.get( id );

		if ( key ) {
			const oscs = key.oscs;

			if ( Number.isFinite( key.dur ) ) {
				this._stopKey( id, oscs );
			} else {
				oscs.forEach( nodes => {
					nodes.keyGain.gain.setValueCurveAtTime(
						new Float32Array( [ key.gain, .1 ] ), this.ctx.currentTime + .01, .02 );
				} );
				setTimeout( this._stopKey.bind( this, id, oscs ), .033 * 1000 );
			}
		} else {
			console.error( "gswaSynth: stopKey id invalid", id );
		}
	}
	_stopKey( id, oscs ) {
		oscs.forEach( this._destroyOscNode, this );
		this._startedKeys.delete( id );
	}

	// private:
	_calcLowpass( val ) {
		return this._calcExp( val, this.nyquist, 2 );
	}
	_calcHighpass( val ) {
		return this._calcExp( 1 - val, this.nyquist, 3 );
	}
	_calcExp( x, total, exp ) {
		return exp === 0
			? x
			: Math.expm1( x ) ** exp / ( ( Math.E - 1 ) ** exp ) * total;
	}

	// default gain envelope
	_scheduleOscNodeGain( key, nodes ) {
		const va = key.variations,
			par = nodes.keyGain.gain,
			{ when, dur, gain, attack, release } = key;

		par.cancelScheduledValues( 0 );
		if ( !va || va[ 0 ].when > key.off ) {
			if ( key.off < .0001 ) {
				par.setValueAtTime( 0, when );
				par.setValueCurveAtTime( new Float32Array( [ 0, gain ] ), when, attack );
			} else {
				par.setValueAtTime( gain, when );
			}
		}
		if ( Number.isFinite( dur ) && dur - attack >= release ) {
			const vaLast = va && va[ va.length - 1 ],
				relWhen = when + dur - release;

			if ( !vaLast || when - key.off + vaLast.when + vaLast.duration < relWhen ) {
				const gainEnd = vaLast ? vaLast.gain[ 1 ] : gain;

				par.setValueCurveAtTime( new Float32Array( [ gainEnd, 0 ] ), relWhen, release );
			}
		}
	}

	// keys linked, variations
	_scheduleVariations( key, nodes ) {
		if ( key.variations ) {
			key.variations.forEach( va => {
				const when = key.when - key.off + va.when,
					dur = va.duration,
					freqArr = new Float32Array( [
						gswaSynth.midiKeyToHz[ va.midi[ 0 ] ],
						gswaSynth.midiKeyToHz[ va.midi[ 1 ] ]
					] );

				if ( when > this.ctx.currentTime && dur > 0 ) {
					nodes.keyOsc.frequency.setValueCurveAtTime( freqArr, when, dur );
					nodes.keyPan.pan.setValueCurveAtTime( new Float32Array( va.pan ), when, dur );
					nodes.keyGain.gain.setValueCurveAtTime( new Float32Array( va.gain ), when, dur );
					nodes.keyLowpass.frequency.setValueCurveAtTime( new Float32Array( va.lowpass ), when, dur );
					nodes.keyHighpass.frequency.setValueCurveAtTime( new Float32Array( va.highpass ), when, dur );
				}
			} );
		}
	}

	// createOscNode
	_createOscNode( key, oscId ) {
		const ctx = this.ctx,
			lfo = this.gsdata.data.lfo,
			osc = this.gsdata.data.oscillators[ oscId ],
			finite = Number.isFinite( key.dur ),
			atTime = key.when - key.off,
			keyLFO = new gswaLFO( ctx ),
			keyOsc = ctx.createOscillator(),
			keyPan = ctx.createStereoPanner(),
			keyGain = ctx.createGain(),
			keyLowpass = ctx.createBiquadFilter(),
			keyHighpass = ctx.createBiquadFilter(),
			nodes = Object.freeze( {
				keyOsc,
				keyLFO,
				keyPan,
				keyGain,
				keyLowpass,
				keyHighpass,
			} );

		this._nodeOscSetType( keyOsc, osc.type );
		keyOsc.detune.setValueAtTime( osc.detune, atTime );
		keyPan.pan.setValueAtTime( key.pan, atTime );
		keyOsc.frequency.setValueAtTime( gswaSynth.midiKeyToHz[ key.midi ], atTime );
		keyLowpass.frequency.setValueAtTime( this._calcLowpass( key.lowpass ), atTime );
		keyHighpass.frequency.setValueAtTime( this._calcHighpass( key.highpass ), atTime );
		keyLowpass.type = "lowpass";
		keyHighpass.type = "highpass";
		this._scheduleOscNodeGain( key, nodes );
		this._scheduleVariations( key, nodes );
		keyOsc
			.connect( keyLFO.node )
			.connect( keyPan )
			.connect( keyLowpass )
			.connect( keyHighpass )
			.connect( keyGain )
			.connect( this._nodes.get( oscId ).pan );
		keyOsc.start( key.when );
		keyLFO.start( {
			toggle: lfo.toggle,
			when: key.when,
			whenStop: finite ? key.when + key.dur : 0,
			offset: key.offset,
			type: lfo.type,
			delay: lfo.delay / this._bps,
			attack: lfo.attack / this._bps,
			speed: lfo.speed * this._bps,
			amp: lfo.amp,
		} );
		if ( finite ) {
			keyOsc.stop( key.when + key.dur );
		}
		return nodes;
	}
	_destroyOscNode( nodes ) {
		nodes.keyOsc.stop();
		nodes.keyOsc.disconnect();
		nodes.keyLFO.destroy();
		nodes.keyGain.disconnect();
	}
	_nodeOscSetType( oscNode, type ) {
		if ( gswaSynth.nativeTypes.indexOf( type ) > -1 ) {
			oscNode.type = type;
		} else {
			const w = gswaPeriodicWaves.get( type );

			oscNode.setPeriodicWave( this.ctx.createPeriodicWave( w.real, w.imag ) );
		}
	}
}

gswaSynth._startedMaxId = Object.seal( { value: 0 } );
gswaSynth.nativeTypes = Object.freeze( [ "sine", "triangle", "sawtooth", "square" ] );
gswaSynth.midiKeyToHz = [];

Object.freeze( gswaSynth );
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';
import appRootDir from 'app-root-dir';

export default () => {
  const rootDir = appRootDir.get();
  const setupTestFilePath = path.resolve(rootDir, 'stanza', 'setup-test.js');
  const setupTestsFile = fs.existsSync(setupTestFilePath) ? setupTestFilePath : undefined;

  return {
    rootDir,
    setupTestFrameworkScriptFile: setupTestsFile,
    testEnvironment: 'node',
    testURL: 'http://localhost',
    moduleFileExtensions: [
      'js',
      'jsx',
    ],
    moduleDirectories: [
      'src',
      'shared',
      'node_modules',
    ],
    transform: {
      '^.+\\.(js|jsx)$': path.resolve(__dirname, 'babel-transform.js'),
    },
    moduleNameMapper: {
      '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': path.resolve(__dirname, 'asset-mock.js'),
      '\\.(css|less)$': path.resolve(__dirname, 'style-mock.js'),
    },
    testPathIgnorePatterns: [
      '<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]',
      '/_fixtures',
    ],
    collectCoverage: true,
    coverageReporters: [
      'json',
      'html',
      'text-summary',
    ],
    collectCoverageFrom: ['src/**/*.{js,jsx}'],
    coveragePathIgnorePatterns: [
      '/node_modules',
      '/test',
    ],
  };
};
<commit_msg>add sass extensions to jest module name mapper<commit_after>import fs from 'fs';
import path from 'path';
import appRootDir from 'app-root-dir';

export default () => {
  const rootDir = appRootDir.get();
  const setupTestFilePath = path.resolve(rootDir, 'stanza', 'setup-test.js');
  const setupTestsFile = fs.existsSync(setupTestFilePath) ? setupTestFilePath : undefined;

  return {
    rootDir,
    setupTestFrameworkScriptFile: setupTestsFile,
    testEnvironment: 'node',
    testURL: 'http://localhost',
    moduleFileExtensions: [
      'js',
      'jsx',
    ],
    moduleDirectories: [
      'src',
      'shared',
      'node_modules',
    ],
    transform: {
      '^.+\\.(js|jsx)$': path.resolve(__dirname, 'babel-transform.js'),
    },
    moduleNameMapper: {
      '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': path.resolve(__dirname, 'asset-mock.js'),
      '\\.(css|less|sass|scss)$': path.resolve(__dirname, 'style-mock.js'),
    },
    testPathIgnorePatterns: [
      '<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]',
      '/_fixtures',
    ],
    collectCoverage: true,
    coverageReporters: [
      'json',
      'html',
      'text-summary',
    ],
    collectCoverageFrom: ['src/**/*.{js,jsx}'],
    coveragePathIgnorePatterns: [
      '/node_modules',
      '/test',
    ],
  };
};
<|endoftext|>


<commit_before>/*jshint asi: true */
var duoshuoQuery = {short_name: 'thx'}

KISSY.use('node,event', function(S, Node) {

    function store(p, v) {
        if (!window.localStorage) {
            return
        }

        if (typeof v == 'undefined') {
            return localStorage.getItem(p)
        }
        else {
            localStorage.setItem(p, v)
        }
    }

    var settings = store('settings') ? JSON.parse(store('settings')) : {}
    var classList = []

    for (var p in settings) {
        if (typeof settings[p] === 'boolean') {
            classList.push('body-' + p)
        }
        else {
            classList.push(settings[p])
        }
    }
    S.one('body').addClass(classList.join(' '))

    S.one('#J_toggler').on('click', function(e) {
        if (Node(e.currentTarget).outerWidth() > 0) {
            S.one('#page').toggleClass('page-dodged')
            e.stopPropagation()
        }
    })

    S.one('#J_settingsToggler').on('click', function(e) {
        S.one('.settings').toggleClass('settings-visible')
        e.stopPropagation()
    })

    S.one('body').on('click', function() {
        S.one('#page').removeClass('page-dodged')
        S.one('.settings').removeClass('settings-visible')
    })

    S.one('.settings').delegate('click', '.type-set-label', function(e) {
        var fontSize = e.currentTarget.getAttribute('data-font-size')
        var klass = e.currentTarget.getAttribute('data-class')
        var body = S.one('body')

        if (fontSize) {
            klass = 'body-font-' + fontSize
            body.removeClass('body-font-small')
            body.removeClass('body-font-middle')
            body.removeClass('body-font-large')
            body.addClass(klass)
            settings.fontSize = klass
        }
        else if (klass) {
            body.toggleClass('body-' + klass)
            settings[klass] = body.hasClass('body-' + klass)
        }

        store('settings', JSON.stringify(settings))
    })

    S.one(window).on('scroll', function(e) {
        var ceilingHeight = S.one('#ceiling').outerHeight()
        if (S.one('body').scrollTop() > ceilingHeight) {
            S.one('#nav').addClass('fixed')
            S.one('#stoc').addClass('fixed')
        }
        else {
            S.one('#nav').removeClass('fixed')
            S.one('#stoc').removeClass('fixed')
        }
    })

    S.ready(function() {
        S.getScript('http://static.duoshuo.com/embed.js')
    })
})

KISSY.config('packages', {
    mosaics: {
        base: 'http://g.tbcdn.cn/a',
        combine: true,
        debug: false,
        ignorePackageNameInUri: true,
        tag: '20130905'
    }
})

KISSY.use('brix/app,node', function(S, app, Node) {
    app.config({
        imports: {
            mosaics: {
                stoc: '0.0.2'
            }
        }
    })

    app.bootStyle(function() {
        app.boot().done(function(root) {
            root.on('ready', pageReady)
        })
    })

    function pageReady() {
        var ol = S.one('#stoc ol')

        if (matchMedia('(min-width: 1200px)').matches) {
            ol.one('li').removeClass('folded')
        }

        this.find('mosaics/stoc').on('mosaics:stoc:change', function(e) {
            var li = e.currentEntry

            while (li.parent('li')) {
                li = li.parent('li')
            }
            li.siblings().addClass('folded')
            li.removeClass('folded')
        })

        ol.delegate('click', '.folded', function(e) {
            var li = Node(e.currentTarget)

            li.siblings().addClass('folded')
            li.removeClass('folded')
        })

        S.all('article').all('h2,h3,h4,h5,h6').each(function(heading) {
            var id = heading.attr('id')
            heading.prepend('')
            heading.prepend('')
        })

        S.one('#J_tocToggler').on('click', function() {
            S.one('.stoc ol').children().toggleClass('folded')
        })
    }
})
<commit_msg>Updated cube<commit_after>/*jshint asi: true */
var duoshuoQuery = {short_name: 'thx'}

KISSY.use('node,event', function(S, Node) {

    function store(p, v) {
        if (!window.localStorage) {
            return
        }

        if (typeof v == 'undefined') {
            return localStorage.getItem(p)
        }
        else {
            localStorage.setItem(p, v)
        }
    }

    var settings = store('settings') ? JSON.parse(store('settings')) : {}
    var classList = []

    for (var p in settings) {
        if (typeof settings[p] === 'boolean' && settings[p]) {
            classList.push('body-' + p)
        }
        else {
            classList.push(settings[p])
        }
    }
    S.one('body').addClass(classList.join(' '))

    S.one('#J_toggler').on('click', function(e) {
        if (Node(e.currentTarget).outerWidth() > 0) {
            S.one('#page').toggleClass('page-dodged')
            e.stopPropagation()
        }
    })

    S.one('#J_settingsToggler').on('click', function(e) {
        S.one('.settings').toggleClass('settings-visible')
        e.stopPropagation()
    })

    S.one('body').on('click', function() {
        S.one('#page').removeClass('page-dodged')
        S.one('.settings').removeClass('settings-visible')
    })

    S.one('.settings').delegate('click', '.type-set-label', function(e) {
        var fontSize = e.currentTarget.getAttribute('data-font-size')
        var klass = e.currentTarget.getAttribute('data-class')
        var body = S.one('body')

        if (fontSize) {
            klass = 'body-font-' + fontSize
            body.removeClass('body-font-small')
            body.removeClass('body-font-middle')
            body.removeClass('body-font-large')
            body.addClass(klass)
            settings.fontSize = klass
        }
        else if (klass) {
            body.toggleClass('body-' + klass)
            settings[klass] = body.hasClass('body-' + klass)
        }

        store('settings', JSON.stringify(settings))
    })

    S.one(window).on('scroll', function(e) {
        var ceilingHeight = S.one('#ceiling').outerHeight()
        if (S.one('body').scrollTop() > ceilingHeight) {
            S.one('#nav').addClass('fixed')
            S.one('#stoc').addClass('fixed')
        }
        else {
            S.one('#nav').removeClass('fixed')
            S.one('#stoc').removeClass('fixed')
        }
    })

    S.ready(function() {
        S.getScript('http://static.duoshuo.com/embed.js')
    })
})

KISSY.config('packages', {
    mosaics: {
        base: 'http://g.tbcdn.cn/a',
        combine: true,
        debug: false,
        ignorePackageNameInUri: true,
        tag: '20130905'
    }
})

KISSY.use('brix/app,node', function(S, app, Node) {
    app.config({
        imports: {
            mosaics: {
                stoc: '0.0.2'
            }
        }
    })

    app.bootStyle(function() {
        app.boot().done(function(root) {
            root.on('ready', pageReady)
        })
    })

    function pageReady() {
        var ol = S.one('#stoc ol')

        if (matchMedia('(min-width: 1200px)').matches) {
            ol.one('li').removeClass('folded')
        }

        this.find('mosaics/stoc').on('mosaics:stoc:change', function(e) {
            var li = e.currentEntry

            while (li.parent('li')) {
                li = li.parent('li')
            }
            li.siblings().addClass('folded')
            li.removeClass('folded')
        })

        ol.delegate('click', '.folded', function(e) {
            var li = Node(e.currentTarget)

            li.siblings().addClass('folded')
            li.removeClass('folded')
        })

        S.all('article').all('h2,h3,h4,h5,h6').each(function(heading) {
            var id = heading.attr('id')
            heading.prepend('')
            heading.prepend('')
        })

        S.one('#J_tocToggler').on('click', function() {
            S.one('.stoc ol').children().toggleClass('folded')
        })
    }
})
<|endoftext|>


<commit_before>/* table sort */
$(document).ready(function() {
  $('#allrequestTable').dataTable();
} );<commit_msg>Fixed the sorting issue over #10 while causing a new bug of not limiting to 10 responses being shown.<commit_after>/* table sort */
$(document).ready(function() {
  $('#allrequestTable').dataTable({
    "aoColumns": [
      { "sType": "num-html" }
    ]
  });
} );<|endoftext|>


<commit_before>class App extends React.Component {
  render() {
    return (

          <Content
            activities={activities}
          />

    );
  }
}

class Header extends React.Component {
  render() {
    return (

          {this.props.title}

        <input
          type="text"
          className="searchInput"
          placeholder="Search ..." />

    );
  }
}

class Content extends React.Component {
  render() {
    const {activity} = this.props;
    return (

        activities.map((activity) => {
          return (

                  {activity.user.name}

                {activity.timestamp}

{activity.text}

                {activity.comments.length}

          );
        })

    )
  }
}

const info = [
  {
  title: "Howdy, React"
  }
];

const activities = [
  {
    timestamp: new Date().getTime(),
    text: "Ate lunch",
    user: {
      id: 1,
      name: "Nate",
      avatar: "http://www.croop.cl/UI/twitter/images/doug.jpg"
    },
    comments: [
      {
        from: 'Ari',
        text: 'Me too!'
      }
    ]
  }
];

var mount = document.getElementById('app');
ReactDOM.render(
  <App
    title={info.title}
    timestamp={activities.timestamp}
    text={activities.text}
    user={activities.user}
    comments={activities.comments}
   />, mount);
<commit_msg>errors gone<commit_after>class App extends React.Component {
  render() {
    return (

          <Content
            activities={activities}
          />

    );
  }
}

class Header extends React.Component {
  render() {
    return (

          {this.props.title}

        <input
          type="text"
          className="searchInput"
          placeholder="Search ..." />

    );
  }
}

class Content extends React.Component {
  render() {
    const {activity} = this.props;
    return (

        {activities.map((activity) => {
          return (

                  {activity.user.name}

                {activity.timestamp}

{activity.text}

                {activity.comments.length}

          );
        })}

    )
  }
}

const info = [
  {
  title: "Howdy, React"
  }
];

const activities = [
  {
    timestamp: new Date().getTime(),
    text: "Ate lunch",
    user: {
      id: 1,
      name: "Nate",
      avatar: "http://www.croop.cl/UI/twitter/images/doug.jpg"
    },
    comments: [
      {
        from: 'Ari',
        text: 'Me too!'
      }
    ]
  }
];

var mount = document.getElementById('app');
ReactDOM.render(
  <App />, mount);
<|endoftext|>


<commit_before>// Copyright 2019, University of Colorado Boulder

/**
 * generates sounds for when the user switches between screens
 *
 * @author John Blanco (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  const MultiClip = require( 'TAMBO/sound-generators/MultiClip' );
  const tambo = require( 'TAMBO/tambo' );

  // sounds
  const screenSelectedSound = require( 'sound!TAMBO/screen-selection.mp3' );
  const homeSelectedSound = require( 'sound!TAMBO/screen-selection-home-v2.mp3' );

  class ScreenSelectionSoundGenerator extends MultiClip {

    /**
     * @param {Property.<Screen|null>} currentScreenProperty - an axon property that indicates which sim screen is
     * currently selected
     */
    constructor( currentScreenProperty ) {

      super( [ homeSelectedSound, screenSelectedSound ] );

      currentScreenProperty.lazyLink( currentScreen => {

        // play one sound for the home screen, another for all other screens
        this.playByIndex( currentScreen === null ? 0 : 1 );
      } );
    }
  }

  return tambo.register( 'ScreenSelectionSoundGenerator', ScreenSelectionSoundGenerator );
} );<commit_msg>Migrated ScreenSelectionSoundGenerator to ES6<commit_after>// Copyright 2019, University of Colorado Boulder

/**
 * generates sounds for when the user switches between screens
 *
 * @author John Blanco (PhET Interactive Simulations)
 */
define( require => {
  'use strict';

  // modules
  const MultiClip = require( 'TAMBO/sound-generators/MultiClip' );
  const tambo = require( 'TAMBO/tambo' );

  // sounds
  const screenSelectedSound = require( 'sound!TAMBO/screen-selection.mp3' );
  const homeSelectedSound = require( 'sound!TAMBO/screen-selection-home-v2.mp3' );

  class ScreenSelectionSoundGenerator extends MultiClip {

    /**
     * @param {Property.<Screen|null>} currentScreenProperty - an axon property that indicates which sim screen is
     * currently selected
     */
    constructor( currentScreenProperty ) {

      super( [ homeSelectedSound, screenSelectedSound ] );

      currentScreenProperty.lazyLink( currentScreen => {

        // play one sound for the home screen, another for all other screens
        this.playByIndex( currentScreen === null ? 0 : 1 );
      } );
    }
  }

  return tambo.register( 'ScreenSelectionSoundGenerator', ScreenSelectionSoundGenerator );
} );<|endoftext|>


<commit_before>import Promise from 'bluebird';
import R from 'ramda';
import _request from 'request';

import CONFIG from '../config';
const request = Promise.promisify(_request);

const help_text = `League of Legends help commands
Accepted positions are **Top**, **Mid**, **ADC**, **Jungle**, and **Support**.

**\`!lol counters champ-name position\`**
		Get the top 10 counters for a Champion and Position
**\`!lol skills champ-name position\`**
		Get the highest win skills for a Champion and Position
**\`!lol items champ-name position\`**
		Get the highest win item sets for a Champion and Position
**\`!lol server-status\`**
		Get the LoL Game and Client server status for all regions`;

// List of possible phrases used for positions
const positions = {
  top: 'Top',
  mid: 'Middle',
  middle: 'Middle',
  jungle: 'Jungle',
  jg: 'Jungle',
  adc: 'ADC',
  support: 'Support',
  sup: 'Support',
  supp: 'Support'
};

function _makeRequest(options) {
  let default_options = {
    qs: {api_key: CONFIG.championgg_api},
    json: true
  };
  return request(R.merge(default_options, options))
    .then(R.prop('body'))
    .tap(body => {
      if (body.error) throw new Error(body.error);
    });
}

function counters(bot, msg, suffix) {
  let query = suffix.replace('counters ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/matchup`
  };
  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have counters for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(R.prop('matchups'))
    .then(R.sortBy(R.prop('winRate')))
    .filter(data => data.games >= 200) // Only show champs where over 200 games have been played.
    .then(R.slice(0, 10))
    .map(data => `**${data.key}** - ${100 - data.winRate}% win rate over ${data.games} games.`)
    .then(R.prepend(`Sure! Here's the top 10 counters for ${champ} ${position}:\n`))
    .then(R.join('\n'))
    .then(text => bot.sendMessage(msg.channel, text))
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

// Retrieves all items from Riot, then parses just the names.
function _itemNames(item_data) {
  let options = {
    url: 'https://ddragon.leagueoflegends.com/cdn/5.24.2/data/en_US/item.json',
    json: true
  };

  return request(options)
    .then(R.path(['body', 'data']))
    .then(data => R.zipObj(R.keys(data), R.pluck('name')(R.values(data))))
    .then(items_list => {
      item_data.item_names = R.map(item_id => {
        return items_list[item_id];
      }, item_data.items);

      return item_data;
    });
}

function items(bot, msg, suffix) {
  let query = suffix.replace('items ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/items/finished/mostWins`
  };

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have item sets for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(_itemNames)
    .then(item_data => {
      let title = `Sure! Here's the highest win item set for **${champ}** **${position}** with a ${item_data.winPercent}% winrate.\n`;
      let reply = R.join('\n', R.prepend(title, item_data.item_names));
      bot.sendMessage(msg.channel, reply);
    })
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

function skills(bot, msg, suffix) {
  let query = suffix.replace('skills ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/skills/mostWins`
  };

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have skill orders for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(R.prop('order'))
    .then(skills => {
			// Calculate skill order.
      let skill_count = R.countBy(R.toLower)(skills);
      delete skill_count.R;
      skill_count = R.invertObj(skill_count);
      let counts = R.keys(skill_count).sort().reverse();
      let skill_order = R.join('>', R.map(count_num => {
        return R.toUpper(skill_count[count_num]);
      }, counts));

      let text = `Sure! Here's the skill order for ${champ} ${position}.

**Skill Priority:** ${skill_order}
**Full Order:** ${skills.join(',')}`;

      bot.sendMessage(msg.channel, text);
    })
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

function serverStatus(bot, msg, suffix) {
  let options = {
    url: 'http://status.leagueoflegends.com/shards',
    json: true
  };

  request(options)
    .then(R.prop('body'))
    .then(R.pluck('slug'))
    .map(slug => {
      let options = {
        url: `http://status.leagueoflegends.com/shards/${slug}`,
        json: true
      };

      return request(options)
        .then(R.path(['body', 'services']))
        .then(services => {
          let client = R.find(R.propEq('slug', 'client'), services);
          let game = R.find(R.propEq('slug', 'game'), services);
          return `${slug.toUpperCase()}:
- Game: **${game.status}**
- Client: **${client.status}**`;
        });
    }, {concurrency: Infinity})
    .then(R.join('\n'))
    .then(text => bot.sendMessage(msg.channel, text))
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

export default {
  lol: (bot, msg, suffix) => {
    if (!CONFIG.championgg_api) {
      return bot.sendMessage(msg.channel, 'Please setup Champion.gg to use the `!lol` command.');
    }

    let command = suffix.split(' ')[0];

    if (command === 'counters') return counters(bot, msg, suffix);
    if (command === 'items') return items(bot, msg, suffix);
    if (command === 'skills') return skills(bot, msg, suffix);
    if (command === 'server-status') return serverStatus(bot, msg, suffix);
    if (command === 'serverstatus') return serverStatus(bot, msg, suffix);
    return bot.sendMessage(msg.channel, help_text);
  }
};
<commit_msg>remove R<commit_after>import Promise from 'bluebird';
import R from 'ramda';
import _request from 'request';

import CONFIG from '../config';
const request = Promise.promisify(_request);

const help_text = `League of Legends help commands
Accepted positions are **Top**, **Mid**, **ADC**, **Jungle**, and **Support**.

**\`!lol counters champ-name position\`**
		Get the top 10 counters for a Champion and Position
**\`!lol skills champ-name position\`**
		Get the highest win skills for a Champion and Position
**\`!lol items champ-name position\`**
		Get the highest win item sets for a Champion and Position
**\`!lol server-status\`**
		Get the LoL Game and Client server status for all regions`;

// List of possible phrases used for positions
const positions = {
  top: 'Top',
  mid: 'Middle',
  middle: 'Middle',
  jungle: 'Jungle',
  jg: 'Jungle',
  adc: 'ADC',
  support: 'Support',
  sup: 'Support',
  supp: 'Support'
};

function _makeRequest(options) {
  let default_options = {
    qs: {api_key: CONFIG.championgg_api},
    json: true
  };
  return request(R.merge(default_options, options))
    .then(R.prop('body'))
    .tap(body => {
      if (body.error) throw new Error(body.error);
    });
}

function counters(bot, msg, suffix) {
  let query = suffix.replace('counters ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/matchup`
  };
  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have counters for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(R.prop('matchups'))
    .then(R.sortBy(R.prop('winRate')))
    .filter(data => data.games >= 200) // Only show champs where over 200 games have been played.
    .then(R.slice(0, 10))
    .map(data => `**${data.key}** - ${100 - data.winRate}% win rate over ${data.games} games.`)
    .then(R.prepend(`Sure! Here's the top 10 counters for ${champ} ${position}:\n`))
    .then(R.join('\n'))
    .then(text => bot.sendMessage(msg.channel, text))
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

// Retrieves all items from Riot, then parses just the names.
function _itemNames(item_data) {
  let options = {
    url: 'https://ddragon.leagueoflegends.com/cdn/5.24.2/data/en_US/item.json',
    json: true
  };

  return request(options)
    .then(R.path(['body', 'data']))
    .then(data => R.zipObj(R.keys(data), R.pluck('name')(R.values(data))))
    .then(items_list => {
      item_data.item_names = R.map(item_id => {
        return items_list[item_id];
      }, item_data.items);

      return item_data;
    });
}

function items(bot, msg, suffix) {
  let query = suffix.replace('items ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/items/finished/mostWins`
  };

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have item sets for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(_itemNames)
    .then(item_data => {
      let title = `Sure! Here's the highest win item set for **${champ}** **${position}** with a ${item_data.winPercent}% winrate.\n`;
      let reply = R.join('\n', R.prepend(title, item_data.item_names));
      bot.sendMessage(msg.channel, reply);
    })
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

function skills(bot, msg, suffix) {
  let query = suffix.replace('skills ', '');
  let position = R.last(query.split(' '));
  let champ = query.replace(` ${position}`, '');

  if (position === champ) return bot.sendMessage(msg.channel, 'You didn\'t specifiy a position. Did you mean top, mid, adc, support, or jungle?');

  let options = {
    url: `http://api.champion.gg/champion/${champ.replace(/[^a-z]/g, '')}/skills/mostWins`
  };

  if (!R.contains(position, R.keys(positions))) return bot.sendMessage(msg.channel, `I don't understand position **${position}**. Did you mean top, mid, adc, support, or jungle?`);
  let gg_position = positions[position];

  return _makeRequest(options)
    .then(body => {
      let results = R.zipObj(R.pluck('role')(body), body);
      if (!R.contains(gg_position, R.keys(results))) throw new Error(`I don't have skill orders for ${champ} ${position}.`);
      return results[gg_position];
    })
    .then(R.prop('order'))
    .then(skills => {
			// Calculate skill order.
      let skill_count = R.countBy(R.toLower)(R.slice(0, 9, skills));
      delete skill_count.r;
      skill_count = R.invertObj(skill_count);
      let counts = R.keys(skill_count).sort().reverse();
      let skill_order = R.join('>', R.map(count_num => {
        return R.toUpper(skill_count[count_num]);
      }, counts));

      let text = `Sure! Here's the skill order for ${champ} ${position}.

**Skill Priority:** ${skill_order}
**Full Order:** ${skills.join(',')}`;

      bot.sendMessage(msg.channel, text);
    })
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

function serverStatus(bot, msg, suffix) {
  let options = {
    url: 'http://status.leagueoflegends.com/shards',
    json: true
  };

  request(options)
    .then(R.prop('body'))
    .then(R.pluck('slug'))
    .map(slug => {
      let options = {
        url: `http://status.leagueoflegends.com/shards/${slug}`,
        json: true
      };

      return request(options)
        .then(R.path(['body', 'services']))
        .then(services => {
          let client = R.find(R.propEq('slug', 'client'), services);
          let game = R.find(R.propEq('slug', 'game'), services);
          return `${slug.toUpperCase()}:
- Game: **${game.status}**
- Client: **${client.status}**`;
        });
    }, {concurrency: Infinity})
    .then(R.join('\n'))
    .then(text => bot.sendMessage(msg.channel, text))
    .catch(err => bot.sendMessage(msg.channel, `Error: ${err.message}`));
}

export default {
  lol: (bot, msg, suffix) => {
    if (!CONFIG.championgg_api) {
      return bot.sendMessage(msg.channel, 'Please setup Champion.gg to use the `!lol` command.');
    }

    let command = suffix.split(' ')[0];

    if (command === 'counters') return counters(bot, msg, suffix);
    if (command === 'items') return items(bot, msg, suffix);
    if (command === 'skills') return skills(bot, msg, suffix);
    if (command === 'server-status') return serverStatus(bot, msg, suffix);
    if (command === 'serverstatus') return serverStatus(bot, msg, suffix);
    return bot.sendMessage(msg.channel, help_text);
  }
};
<|endoftext|>


<commit_before>describe('Team', function() {
    describe('addTeamSkills', function() {
        it('test addTeamSkills', function() {
            var teamSkills = ["AngularJS", "Firebase"];
            var userSkills = ["Python", "C++", "AngularJS", "Firebase"];

            var expected = ["AngularJS", "Firebase", "Python", "C++"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });

        it('the team does not have the skills yet', function() {
            var teamSkills = ["AngularJS"];
            var userSkills = ["Firebase"];

            var expected = ["AngularJS", "Firebase"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });

        it('the team has the skills already', function() {
            var teamSkills = ["AngularJS"];
            var userSkills = ["AngularJS"];

            var expected = ["AngularJS"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });
    });

    describe('removeTeamSkills', function() {
        it('test removeTeamSkills', function() {
            var teamSkills = ["Python", "C++", "AngularJS", "Firebase"];
            var teamMembers = [
                {uid: "0", name: "member to be removed", skills: ["Python", "C++", "AngularJS", "Firebase"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS", "Firebase"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["Python", "C++", "AngularJS", "Firebase"]};

            var expected = ["AngularJS", "Firebase"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });

        it('other members does not have the skills', function() {
            var teamSkills = ["AngularJS", "Firebase"];
            var teamMembers = [
                {uid: "0", name: "member to be removed", skills: ["Firebase"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["Firebase"]};

            var expected = ["AngularJS"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });

        it('other members have the skills', function() {
            var teamSkills = ["AngularJS"];
            var teamMembers = [
                {uid: "0", name: "member to be remove", skills: ["AngularJS"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["AngularJS"]};

            var expected = ["AngularJS"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });
    });
});

describe("Team Controller", function() {
    beforeEach(module("teamform-team-app"));

    var $controller, $firebaseObject, $firebaseArray;

    beforeEach(inject(function(_$controller_, _$firebaseObject_, _$firebaseArray_) {
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $controller = _$controller_;
        $firebaseObject = _$firebaseObject_;
        $firebaseArray = _$firebaseArray_;
    }));

    describe("$scope.changeCurrentTeamSize", function() {
        var $scope, controller;

        beforeEach(function() {
            $scope = {};
            controller = $controller("TeamCtrl", {$scope: $scope, $firebaseObject: $firebaseObject, $firebaseArray: $firebaseArray});
        });

        it("increase size", function() {
            $scope.size = 5;
            $scope.currentTeamSize = 4;
            $scope.minTeamSize = 1;
            $scope.maxTeamSize = 10;

            $scope.changeCurrentTeamSize(1);

            expect($scope.size).toEqual(6);
        });

        // it("decrease size", function() {
        //     $scope.size = 5;
        //     $scope.currentTeamSize = 4;
        //     $scope.minTeamSize = 1;
        //     $scope.maxTeamSize = 10;
        //
        //     $scope.changeCurrentTeamSize(-1);
        //
        //     expect($scope.size).toEqual(4);
        // });
    });
});
<commit_msg>Delete the firebase app after each test<commit_after>describe('Team', function() {
    describe('addTeamSkills', function() {
        it('test addTeamSkills', function() {
            var teamSkills = ["AngularJS", "Firebase"];
            var userSkills = ["Python", "C++", "AngularJS", "Firebase"];

            var expected = ["AngularJS", "Firebase", "Python", "C++"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });

        it('the team does not have the skills yet', function() {
            var teamSkills = ["AngularJS"];
            var userSkills = ["Firebase"];

            var expected = ["AngularJS", "Firebase"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });

        it('the team has the skills already', function() {
            var teamSkills = ["AngularJS"];
            var userSkills = ["AngularJS"];

            var expected = ["AngularJS"];

            expect(addTeamSkills(teamSkills, userSkills)).toEqual(expected);
        });
    });

    describe('removeTeamSkills', function() {
        it('test removeTeamSkills', function() {
            var teamSkills = ["Python", "C++", "AngularJS", "Firebase"];
            var teamMembers = [
                {uid: "0", name: "member to be removed", skills: ["Python", "C++", "AngularJS", "Firebase"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS", "Firebase"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["Python", "C++", "AngularJS", "Firebase"]};

            var expected = ["AngularJS", "Firebase"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });

        it('other members does not have the skills', function() {
            var teamSkills = ["AngularJS", "Firebase"];
            var teamMembers = [
                {uid: "0", name: "member to be removed", skills: ["Firebase"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["Firebase"]};

            var expected = ["AngularJS"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });

        it('other members have the skills', function() {
            var teamSkills = ["AngularJS"];
            var teamMembers = [
                {uid: "0", name: "member to be remove", skills: ["AngularJS"]},
                {uid: "1", name: "team member 1", skills: ["AngularJS"]}
            ];
            var member = {uid: "0", name: "Man", skills: ["AngularJS"]};

            var expected = ["AngularJS"];

            expect(removeTeamSkills(teamSkills, teamMembers, member)).toEqual(expected);
        });
    });
});

describe("Team Controller", function() {
    beforeEach(module("teamform-team-app"));

    var $controller, $firebaseObject, $firebaseArray;

    beforeEach(inject(function(_$controller_, _$firebaseObject_, _$firebaseArray_) {
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $controller = _$controller_;
        $firebaseObject = _$firebaseObject_;
        $firebaseArray = _$firebaseArray_;
    }));

    afterEach(function() {
        firebase.app().delete();
    });

    describe("$scope.changeCurrentTeamSize", function() {
        var $scope, controller;

        beforeEach(function() {
            $scope = {};
            controller = $controller("TeamCtrl", {$scope: $scope, $firebaseObject: $firebaseObject, $firebaseArray: $firebaseArray});
        });

        it("increase size", function() {
            $scope.size = 5;
            $scope.currentTeamSize = 4;
            $scope.minTeamSize = 1;
            $scope.maxTeamSize = 10;

            $scope.changeCurrentTeamSize(1);

            expect($scope.size).toEqual(6);
        });

        it("decrease size", function() {
            $scope.size = 5;
            $scope.currentTeamSize = 4;
            $scope.minTeamSize = 1;
            $scope.maxTeamSize = 10;

            $scope.changeCurrentTeamSize(-1);

            expect($scope.size).toEqual(4);
        });
    });
});
<|endoftext|>


<commit_before>/*jslint node: true */
"use strict";

var utils = require("../utils");
var log = require("npmlog");

var msgs_recv = 0;

module.exports = function(defaultFuncs, api, ctx) {
  var shouldStop = false;
  var currentlyRunning = null;
  var stopListening = function() {
    shouldStop = true;
    if(currentlyRunning) clearTimeout(currentlyRunning);
  };

  var prev = Date.now();
  var tmpPrev = Date.now();
  var lastSync = Date.now();

  var form = {
    'channel' : 'p_' + ctx.userID,
    'seq' : '0',
    'partition' : '-2',
    'clientid' : ctx.clientID,
    'viewer_uid' : ctx.userID,
    'uid' : ctx.userID,
    'state' : 'active',
    'idle' : 0,
    'cap' : '8',
    'msgs_recv':msgs_recv
  };

  var globalCallback = null;

  function listen() {
    if(shouldStop) return;

    form.idle = ~~(Date.now()/1000) - prev;
    prev = ~~(Date.now()/1000);

    utils.get("https://0-edge-chat.facebook.com/pull", ctx.jar, form)
    .then(utils.parseResponse)
    .then(function(resData) {
      var now = Date.now();
      log.info("Got answer in ", now - tmpPrev);
      tmpPrev = now;

      if(resData && resData.t === "lb") {
        form.sticky_token = resData.lb_info.sticky;
        form.sticky_pool = resData.lb_info.pool;
      }

      if(resData && resData.t === 'fullReload') {
        form.seq = resData.seq;
        delete form.sticky_pool;
        delete form.sticky_token;
        var form4 = {
          'lastSync' : ~~(lastSync/1000),
        };
        defaultFuncs.get("https://www.facebook.com/notifications/sync/", ctx.jar, form4)
        .then(utils.saveCookies(ctx.jar))
        .then(function(res) {
          lastSync = Date.now();
          var form6 = {
            'client' : 'mercury',
            'folders[0]': 'inbox',
            'last_action_timestamp' : ~~(Date.now() - 60)
          };
          defaultFuncs.post("https://www.facebook.com/ajax/mercury/thread_sync.php", ctx.jar, form)
          .then(function(res) {
            log.info("thread sync --->", res.body);
            currentlyRunning = setTimeout(listen, 1000);
          });
        });
        return;
      }

      if(resData.ms) {
        msgs_recv += resData.ms.length;
        var atLeastOne = false;
        resData.ms.sort(function(a, b) {
          return a.timestamp - b.timestamp;
        }).map(function parsePackets(v) {
          switch (v.type) {
            case 'buddylist_overlay':
              // TODO: what happens when you're logged in as a page?
              if(!ctx.globalOptions.updatePresence) return;

              // There should be only one key inside overlay
              Object.keys(v.overlay).map(function(userID) {
                var formattedPresence = utils.formatPresence(v.overlay[userID], userID);
                if(!shouldStop) globalCallback(null, formattedPresence);
              });
              break;
            case 'mercury':
              if(ctx.globalOptions.pageID) return;
              if(!ctx.globalOptions.listenEvents) return;
              v.actions.map(function(v2) {
                var formattedEvent = utils.formatEvent(v2);
                if(!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID.toString()) return;

                if (!shouldStop) globalCallback(null, formattedEvent);
              });
              break;
            case 'messaging':
              if(ctx.globalOptions.pageID) return;
              if(v.event !== "deliver") return;
              if(!ctx.globalOptions.selfListen && v.message.sender_fbid.toString() === ctx.userID.toString()) return;
              atLeastOne = true;
              if (!shouldStop) globalCallback(null, utils.formatMessage(v));
              break;
            case 'pages_messaging':
              if(!ctx.globalOptions.pageID) return;
              if(v.event !== "deliver") return;
              if(!ctx.globalOptions.selfListen && (v.message.sender_fbid.toString() === ctx.userID.toString() || v.message.sender_fbid.toString() === ctx.globalOptions.pageID.toString())) return;
              if(v.realtime_viewer_fbid !== ctx.globalOptions.pageID) return;

              atLeastOne = true;
              if (!shouldStop) globalCallback(null, utils.formatMessage(v));
              break;
          }
        });

        if(atLeastOne) {
          // Send deliveryReceipt notification to the server
          var formDeliveryReceipt = {};

          for (var i = 0; i < resData.ms.length; i++) {
            if(resData.ms[i].message && resData.ms[i].message.mid) formDeliveryReceipt["[" + i + "]"] = resData.ms[i].message.mid;
          }

          // If there's at least one, we do the post request
          if(formDeliveryReceipt["[0]"]) {
            defaultFuncs.post("https://www.facebook.com/ajax/mercury/delivery_receipts.php", ctx.jar, formDeliveryReceipt);
          }
        }
      }

      if(resData.seq) form.seq = resData.seq;
      if(resData.tr) form.traceid = resData.tr;
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);

    })
    .catch(function(err) {
      log.error("ERROR in listen --> ", err);
      globalCallback(err);
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);
    });
  }

  return function(callback) {
    globalCallback = callback;

    if (!currentlyRunning) currentlyRunning = setTimeout(listen, Math.random() * 200 + 50, callback);

    return stopListening;
  };
};
<commit_msg>Fix #49. `userID` and `threadID` always a string.<commit_after>/*jslint node: true */
"use strict";

var utils = require("../utils");
var log = require("npmlog");

var msgs_recv = 0;

module.exports = function(defaultFuncs, api, ctx) {
  var shouldStop = false;
  var currentlyRunning = null;
  var stopListening = function() {
    shouldStop = true;
    if(currentlyRunning) clearTimeout(currentlyRunning);
  };

  var prev = Date.now();
  var tmpPrev = Date.now();
  var lastSync = Date.now();

  var form = {
    'channel' : 'p_' + ctx.userID,
    'seq' : '0',
    'partition' : '-2',
    'clientid' : ctx.clientID,
    'viewer_uid' : ctx.userID,
    'uid' : ctx.userID,
    'state' : 'active',
    'idle' : 0,
    'cap' : '8',
    'msgs_recv':msgs_recv
  };

  var globalCallback = null;

  function listen() {
    if(shouldStop) return;

    form.idle = ~~(Date.now()/1000) - prev;
    prev = ~~(Date.now()/1000);

    utils.get("https://0-edge-chat.facebook.com/pull", ctx.jar, form)
    .then(utils.parseResponse)
    .then(function(resData) {
      var now = Date.now();
      log.info("Got answer in ", now - tmpPrev);
      tmpPrev = now;

      if(resData && resData.t === "lb") {
        form.sticky_token = resData.lb_info.sticky;
        form.sticky_pool = resData.lb_info.pool;
      }

      if(resData && resData.t === 'fullReload') {
        form.seq = resData.seq;
        delete form.sticky_pool;
        delete form.sticky_token;
        var form4 = {
          'lastSync' : ~~(lastSync/1000),
        };
        defaultFuncs.get("https://www.facebook.com/notifications/sync/", ctx.jar, form4)
        .then(utils.saveCookies(ctx.jar))
        .then(function(res) {
          lastSync = Date.now();
          var form6 = {
            'client' : 'mercury',
            'folders[0]': 'inbox',
            'last_action_timestamp' : ~~(Date.now() - 60)
          };
          defaultFuncs.post("https://www.facebook.com/ajax/mercury/thread_sync.php", ctx.jar, form)
          .then(function(res) {
            log.info("thread sync --->", res.body);
            currentlyRunning = setTimeout(listen, 1000);
          });
        });
        return;
      }

      if(resData.ms) {
        msgs_recv += resData.ms.length;
        var atLeastOne = false;
        resData.ms.sort(function(a, b) {
          return a.timestamp - b.timestamp;
        }).map(function parsePackets(v) {
          switch (v.type) {
            case 'buddylist_overlay':
              // TODO: what happens when you're logged in as a page?
              if(!ctx.globalOptions.updatePresence) return;

              // There should be only one key inside overlay
              Object.keys(v.overlay).map(function(userID) {
                var formattedPresence = utils.formatPresence(v.overlay[userID], userID);
                if(!shouldStop) globalCallback(null, formattedPresence);
              });
              break;
            case 'mercury':
              if(ctx.globalOptions.pageID) return;
              if(!ctx.globalOptions.listenEvents) return;
              v.actions.map(function(v2) {
                var formattedEvent = utils.formatEvent(v2);
                if(!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) return;

                if (!shouldStop) globalCallback(null, formattedEvent);
              });
              break;
            case 'messaging':
              if(ctx.globalOptions.pageID) return;
              if(v.event !== "deliver") return;
              if(!ctx.globalOptions.selfListen && v.message.sender_fbid.toString() === ctx.userID) return;
              atLeastOne = true;
              if (!shouldStop) globalCallback(null, utils.formatMessage(v));
              break;
            case 'pages_messaging':
              if(!ctx.globalOptions.pageID) return;
              if(v.event !== "deliver") return;
              if(!ctx.globalOptions.selfListen && (v.message.sender_fbid.toString() === ctx.userID || v.message.sender_fbid.toString() === ctx.globalOptions.pageID)) return;
              if(v.realtime_viewer_fbid !== ctx.globalOptions.pageID) return;

              atLeastOne = true;
              if (!shouldStop) globalCallback(null, utils.formatMessage(v));
              break;
          }
        });

        if(atLeastOne) {
          // Send deliveryReceipt notification to the server
          var formDeliveryReceipt = {};

          resData.ms.filter(function(v) {
            return v.message && v.message.mid && v.message.sender_fbid.toString() !== ctx.userID;
          }).forEach(function(val, i) {
            formDeliveryReceipt["[" + i + "]"] = val.message.mid;
          });

          // If there's at least one, we do the post request
          if(formDeliveryReceipt["[0]"]) {
            defaultFuncs.post("https://www.facebook.com/ajax/mercury/delivery_receipts.php", ctx.jar, formDeliveryReceipt);
          }
        }
      }

      if(resData.seq) form.seq = resData.seq;
      if(resData.tr) form.traceid = resData.tr;
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);

    })
    .catch(function(err) {
      log.error("ERROR in listen --> ", err);
      globalCallback(err);
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);
    });
  }

  return function(callback) {
    globalCallback = callback;

    if (!currentlyRunning) currentlyRunning = setTimeout(listen, Math.random() * 200 + 50, callback);

    return stopListening;
  };
};
<|endoftext|>


<commit_before>/* global $ */
'use strict'

/**
 * Email repeat
 */
function EmailRepeat (element, config) {
  var options = {}

  $.extend(options, config)

  // Private variables
  var hintWrapper
  var hint

  /**
   * Set everything up
   */
  function create () {
    // Bail out if we don't have the proper element to act upon
    if (!element) {
      return
    }

    hintWrapper = $('

Please ensure your email address is displayed correctly below. We will need this if you need to reset your password in future.

')

    hint = $(hintWrapper).find('.email-hint-value')

    $(element).on('change', updateHint)
    $(element).on('input', updateHint)
  }

  /**
   *
   */
  function updateHint () {
    $(element).after(hintWrapper)

    // If the input field gets emptied out again, remove the hint
    if (element.value.length === 0) {
      hintWrapper.remove()
      return
    }

    // Update the hint to match the input value
    hint.text(element.value)
  }

  /**
   * Tear everything down again
   */
  function destroy () {
    hintWrapper.remove()

    $(element).off('change', updateHint)
    $(element).off('input', updateHint)
  }

  var self = {
    create: create,
    destroy: destroy
  }

  return self
}

export { EmailRepeat }
<commit_msg>Fix IE8 bug with email repeat<commit_after>/* global $ */
'use strict'

/**
 * Email repeat
 */
function EmailRepeat (element, config) {
  var options = {}

  $.extend(options, config)

  // Private variables
  var hintWrapper
  var hint

  /**
   * Set everything up
   */
  function create () {
    // Bail out if we don't have the proper element to act upon
    if (!element) {
      return
    }

    hintWrapper = $('

Please ensure your email address is displayed correctly below. We will need this if you need to reset your password in future.

')

    hint = $('

')
    $(hintWrapper).append(hint)

    $(element).on('change', updateHint)
    $(element).on('input', updateHint)
  }

  /**
   *
   */
  function updateHint () {
    $(element).after(hintWrapper)

    // If the input field gets emptied out again, remove the hint
    if (element.value.length === 0) {
      hintWrapper.remove()
      return
    }

    // Update the hint to match the input value
    hint.text(element.value)
  }

  /**
   * Tear everything down again
   */
  function destroy () {
    hintWrapper.remove()

    $(element).off('change', updateHint)
    $(element).off('input', updateHint)
  }

  var self = {
    create: create,
    destroy: destroy
  }

  return self
}

export { EmailRepeat }
<|endoftext|>