<commit_before>/* global Module */

/* Magic Mirror
 * Module: CurrentWeather
 *
 * By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 */

Module.register("currentweather",{

	// Default module config.
	defaults: {
		location: "",
		appid: "",
		units: config.units,
		updateInterval: 10 * 60 * 1000, // every 10 minutes
		animationSpeed: 1000,
		timeFormat: config.timeFormat,
		showPeriod: true,
		showPeriodUpper: false,
		showWindDirection: true,
		useBeaufort: true,
		lang: config.language,

		initialLoadDelay: 0, // 0 seconds delay
		retryDelay: 2500,

		apiVersion: "2.5",
		apiBase: "http://api.openweathermap.org/data/",
		weatherEndpoint: "weather",

		iconTable: {
			"01d": "wi-day-sunny",
			"02d": "wi-day-cloudy",
			"03d": "wi-cloudy",
			"04d": "wi-cloudy-windy",
			"09d": "wi-showers",
			"10d": "wi-rain",
			"11d": "wi-thunderstorm",
			"13d": "wi-snow",
			"50d": "wi-fog",
			"01n": "wi-night-clear",
			"02n": "wi-night-cloudy",
			"03n": "wi-night-cloudy",
			"04n": "wi-night-cloudy",
			"09n": "wi-night-showers",
			"10n": "wi-night-rain",
			"11n": "wi-night-thunderstorm",
			"13n": "wi-night-snow",
			"50n": "wi-night-alt-cloudy-windy"
		},
	},

	// Define required scripts.
	getScripts: function() {
		return ["moment.js"];
	},

	// Define required scripts.
	getStyles: function() {
		return ["weather-icons.css", "currentweather.css"];
	},

	// Define required translations.
	getTranslations: function() {
		// The translations for the defaut modules are defined in the core translation files.
		// Therefor we can just return false. Otherwise we should have returned a dictionairy.
		// If you're trying to build yiur own module including translations, check out the documentation.
		return false;
	},

	// Define start sequence.
	start: function() {
		Log.info("Starting module: " + this.name);

		// Set locale.
		moment.locale(config.language);

		this.windSpeed = null;
		this.windDirection = null;
		this.sunriseSunsetTime = null;
		this.sunriseSunsetIcon = null;
		this.temperature = null;
		this.weatherType = null;

		this.loaded = false;
		this.scheduleUpdate(this.config.initialLoadDelay);

		this.updateTimer = null;

	},

	// Override dom generator.
	getDom: function() {
		var wrapper = document.createElement("div");

		if (this.config.appid === "") {
			wrapper.innerHTML = "Please set the correct openweather appid in the config for module: " + this.name + ".";
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		if (this.config.location === "") {
			wrapper.innerHTML = "Please set the openweather location in the config for module: " + this.name + ".";
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		if (!this.loaded) {
			wrapper.innerHTML = this.translate('LOADING');
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		var small = document.createElement("div");
		small.className = "normal medium";

		var windIcon = document.createElement("span");
		windIcon.className = "wi wi-strong-wind dimmed";
		small.appendChild(windIcon);

		var windSpeed = document.createElement("span");
		windSpeed.innerHTML = " " + this.windSpeed;
		small.appendChild(windSpeed);

		if (this.config.showWindDirection) {
			var windDirection = document.createElement("sup");
			windDirection.innerHTML = " " + this.translate(this.windDirection);
			small.appendChild(windDirection);
		}
		var spacer = document.createElement("span");
		spacer.innerHTML = " ";
		small.appendChild(spacer);

		var sunriseSunsetIcon = document.createElement("span");
		sunriseSunsetIcon.className = "wi dimmed " + this.sunriseSunsetIcon;
		small.appendChild(sunriseSunsetIcon);

		var sunriseSunsetTime = document.createElement("span");
		sunriseSunsetTime.innerHTML = " " + this.sunriseSunsetTime;
		small.appendChild(sunriseSunsetTime);

		var large = document.createElement("div");
		large.className = "large light";

		var weatherIcon = document.createElement("span");
		weatherIcon.className = "wi weathericon " + this.weatherType;
		large.appendChild(weatherIcon);

		var temperature = document.createElement("span");
		temperature.className = "bright";
		temperature.innerHTML = " " + this.temperature + "°";
		large.appendChild(temperature);

		wrapper.appendChild(small);
		wrapper.appendChild(large);
		return wrapper;
	},

	/* updateWeather(compliments)
	 * Requests new data from openweather.org.
	 * Calls processWeather on succesfull response.
	 */
	updateWeather: function() {
		var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + this.getParams();
		var self = this;
		var retry = true;

		var weatherRequest = new XMLHttpRequest();
		weatherRequest.open("GET", url, true);
		weatherRequest.onreadystatechange = function() {
			if (this.readyState === 4) {
				if (this.status === 200) {
					self.processWeather(JSON.parse(this.response));
				} else if (this.status === 401) {
					self.config.appid = "";
					self.updateDom(self.config.animationSpeed);

					Log.error(self.name + ": Incorrect APPID.");
					retry = false;
				} else {
					Log.error(self.name + ": Could not load weather.");
				}

				if (retry) {
					self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay);
				}
			}
		};
		weatherRequest.send();
	},

	/* getParams(compliments)
	 * Generates an url with api parameters based on the config.
	 *
	 * return String - URL params.
	 */
	getParams: function() {
		var params = "?";
		params += "q=" + this.config.location;
		params += "&units=" + this.config.units;
		params += "&lang=" + this.config.lang;
		params += "&APPID=" + this.config.appid;

		return params;
	},

	/* processWeather(data)
	 * Uses the received data to set the various values.
	 *
	 * argument data object - Weather information received form openweather.org.
	 */
	processWeather: function(data) {
		this.temperature = this.roundValue(data.main.temp);

		if (this.config.useBeaufort){
			this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
		}else {
			this.windSpeed = parseFloat(data.wind.speed).toFixed(0);
		}

		this.windDirection = this.deg2Cardinal(data.wind.deg);
		this.weatherType = this.config.iconTable[data.weather[0].icon];

		var now = new Date();
		var sunrise = new Date(data.sys.sunrise * 1000);
		var sunset = new Date(data.sys.sunset * 1000);

		// The moment().format('h') method has a bug on the Raspberry Pi.
		// So we need to generate the timestring manually.
		// See issue: https://github.com/MichMich/MagicMirror/issues/181
		var sunriseSunsetDateObject = (sunrise < now && sunset > now) ? sunset : sunrise;
		var timeString = moment(sunriseSunsetDateObject).format('HH:mm');
		if (this.config.timeFormat !== 24) {
			//var hours = sunriseSunsetDateObject.getHours() % 12 || 12;
			if (this.config.showPeriod) {
				if (this.config.showPeriodUpper) {
					//timeString = hours + moment(sunriseSunsetDateObject).format(':mm A');
					timeString = moment(sunriseSunsetDateObject).format('h:mm A');
				} else {
					//timeString = hours + moment(sunriseSunsetDateObject).format(':mm a');
					timeString = moment(sunriseSunsetDateObject).format('h:mm a');
				}
			} else {
				//timeString = hours + moment(sunriseSunsetDateObject).format(':mm');
				timeString = moment(sunriseSunsetDateObject).format('h:mm');
			}
		}

		this.sunriseSunsetTime = timeString;
		this.sunriseSunsetIcon = (sunrise < now && sunset > now) ? "wi-sunset" : "wi-sunrise";

		this.loaded = true;
		this.updateDom(this.config.animationSpeed);
	},

	/* scheduleUpdate()
	 * Schedule next update.
	 *
	 * argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
	 */
	scheduleUpdate: function(delay) {
		var nextLoad = this.config.updateInterval;
		if (typeof delay !== "undefined" && delay >= 0) {
			nextLoad = delay;
		}

		var self = this;
		setTimeout(function() {
			self.updateWeather();
		}, nextLoad);
	},

	/* ms2Beaufort(ms)
	 * Converts m2 to beaufort (windspeed).
	 *
	 * argument ms number - Windspeed in m/s.
	 *
	 * return number - Windspeed in beaufort.
	 */
	ms2Beaufort: function(ms) {
		var kmh = ms * 60 * 60 / 1000;
		var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
		for (var beaufort in speeds) {
			var speed = speeds[beaufort];
			if (speed > kmh) {
				return beaufort;
			}
		}
		return 12;
	},

	/* function(temperature)
	 * Rounds a temperature to 1 decimal.
	 *
	 * argument temperature number - Temperature.
	 *
	 * return number - Rounded Temperature.
	 */

	deg2Cardinal: function(deg) {
                if (deg>11.25 && deg<=33.75){
                        return "NNE";
                } else if (deg > 33.75 && deg <= 56.25) {
                        return "ENE";
                } else if (deg > 56.25 && deg <= 78.75) {
                        return "E";
                } else if (deg > 78.75 && deg <= 101.25) {
                        return "ESE";
                } else if (deg > 101.25 && deg <= 123.75) {
                        return "ESE";
                } else if (deg > 123.75 && deg <= 146.25) {
                        return "SE";
                } else if (deg > 146.25 && deg <= 168.75) {
                        return "SSE";
                } else if (deg > 168.75 && deg <= 191.25) {
                        return "S";
                } else if (deg > 191.25 && deg <= 213.75) {
                        return "SSW";
                } else if (deg > 213.75 && deg <= 236.25) {
                        return "SW";
                } else if (deg > 236.25 && deg <= 258.75) {
                        return "WSW";
                } else if (deg > 258.75 && deg <= 281.25) {
                        return "W";
                } else if (deg > 281.25 && deg <= 303.75) {
                        return "WNW";
                } else if (deg > 303.75 && deg <= 326.25) {
                        return "NW";
                } else if (deg > 326.25 && deg <= 348.75) {
                        return "NNW";
                } else {
                         return "N";
                }
	},

	roundValue: function(temperature) {
		return parseFloat(temperature).toFixed(1);
	}
});
<commit_msg>Fix deg2Cardinal function in currentweather module<commit_after>/* global Module */

/* Magic Mirror
 * Module: CurrentWeather
 *
 * By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 */

Module.register("currentweather",{

	// Default module config.
	defaults: {
		location: "",
		appid: "",
		units: config.units,
		updateInterval: 10 * 60 * 1000, // every 10 minutes
		animationSpeed: 1000,
		timeFormat: config.timeFormat,
		showPeriod: true,
		showPeriodUpper: false,
		showWindDirection: true,
		useBeaufort: true,
		lang: config.language,

		initialLoadDelay: 0, // 0 seconds delay
		retryDelay: 2500,

		apiVersion: "2.5",
		apiBase: "http://api.openweathermap.org/data/",
		weatherEndpoint: "weather",

		iconTable: {
			"01d": "wi-day-sunny",
			"02d": "wi-day-cloudy",
			"03d": "wi-cloudy",
			"04d": "wi-cloudy-windy",
			"09d": "wi-showers",
			"10d": "wi-rain",
			"11d": "wi-thunderstorm",
			"13d": "wi-snow",
			"50d": "wi-fog",
			"01n": "wi-night-clear",
			"02n": "wi-night-cloudy",
			"03n": "wi-night-cloudy",
			"04n": "wi-night-cloudy",
			"09n": "wi-night-showers",
			"10n": "wi-night-rain",
			"11n": "wi-night-thunderstorm",
			"13n": "wi-night-snow",
			"50n": "wi-night-alt-cloudy-windy"
		},
	},

	// Define required scripts.
	getScripts: function() {
		return ["moment.js"];
	},

	// Define required scripts.
	getStyles: function() {
		return ["weather-icons.css", "currentweather.css"];
	},

	// Define required translations.
	getTranslations: function() {
		// The translations for the defaut modules are defined in the core translation files.
		// Therefor we can just return false. Otherwise we should have returned a dictionairy.
		// If you're trying to build yiur own module including translations, check out the documentation.
		return false;
	},

	// Define start sequence.
	start: function() {
		Log.info("Starting module: " + this.name);

		// Set locale.
		moment.locale(config.language);

		this.windSpeed = null;
		this.windDirection = null;
		this.sunriseSunsetTime = null;
		this.sunriseSunsetIcon = null;
		this.temperature = null;
		this.weatherType = null;

		this.loaded = false;
		this.scheduleUpdate(this.config.initialLoadDelay);

		this.updateTimer = null;

	},

	// Override dom generator.
	getDom: function() {
		var wrapper = document.createElement("div");

		if (this.config.appid === "") {
			wrapper.innerHTML = "Please set the correct openweather appid in the config for module: " + this.name + ".";
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		if (this.config.location === "") {
			wrapper.innerHTML = "Please set the openweather location in the config for module: " + this.name + ".";
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		if (!this.loaded) {
			wrapper.innerHTML = this.translate('LOADING');
			wrapper.className = "dimmed light small";
			return wrapper;
		}

		var small = document.createElement("div");
		small.className = "normal medium";

		var windIcon = document.createElement("span");
		windIcon.className = "wi wi-strong-wind dimmed";
		small.appendChild(windIcon);

		var windSpeed = document.createElement("span");
		windSpeed.innerHTML = " " + this.windSpeed;
		small.appendChild(windSpeed);

		if (this.config.showWindDirection) {
			var windDirection = document.createElement("sup");
			windDirection.innerHTML = " " + this.translate(this.windDirection);
			small.appendChild(windDirection);
		}
		var spacer = document.createElement("span");
		spacer.innerHTML = " ";
		small.appendChild(spacer);

		var sunriseSunsetIcon = document.createElement("span");
		sunriseSunsetIcon.className = "wi dimmed " + this.sunriseSunsetIcon;
		small.appendChild(sunriseSunsetIcon);

		var sunriseSunsetTime = document.createElement("span");
		sunriseSunsetTime.innerHTML = " " + this.sunriseSunsetTime;
		small.appendChild(sunriseSunsetTime);

		var large = document.createElement("div");
		large.className = "large light";

		var weatherIcon = document.createElement("span");
		weatherIcon.className = "wi weathericon " + this.weatherType;
		large.appendChild(weatherIcon);

		var temperature = document.createElement("span");
		temperature.className = "bright";
		temperature.innerHTML = " " + this.temperature + "°";
		large.appendChild(temperature);

		wrapper.appendChild(small);
		wrapper.appendChild(large);
		return wrapper;
	},

	/* updateWeather(compliments)
	 * Requests new data from openweather.org.
	 * Calls processWeather on succesfull response.
	 */
	updateWeather: function() {
		var url = this.config.apiBase + this.config.apiVersion + "/" + this.config.weatherEndpoint + this.getParams();
		var self = this;
		var retry = true;

		var weatherRequest = new XMLHttpRequest();
		weatherRequest.open("GET", url, true);
		weatherRequest.onreadystatechange = function() {
			if (this.readyState === 4) {
				if (this.status === 200) {
					self.processWeather(JSON.parse(this.response));
				} else if (this.status === 401) {
					self.config.appid = "";
					self.updateDom(self.config.animationSpeed);

					Log.error(self.name + ": Incorrect APPID.");
					retry = false;
				} else {
					Log.error(self.name + ": Could not load weather.");
				}

				if (retry) {
					self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay);
				}
			}
		};
		weatherRequest.send();
	},

	/* getParams(compliments)
	 * Generates an url with api parameters based on the config.
	 *
	 * return String - URL params.
	 */
	getParams: function() {
		var params = "?";
		params += "q=" + this.config.location;
		params += "&units=" + this.config.units;
		params += "&lang=" + this.config.lang;
		params += "&APPID=" + this.config.appid;

		return params;
	},

	/* processWeather(data)
	 * Uses the received data to set the various values.
	 *
	 * argument data object - Weather information received form openweather.org.
	 */
	processWeather: function(data) {
		this.temperature = this.roundValue(data.main.temp);

		if (this.config.useBeaufort){
			this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
		}else {
			this.windSpeed = parseFloat(data.wind.speed).toFixed(0);
		}

		this.windDirection = this.deg2Cardinal(data.wind.deg);
		this.weatherType = this.config.iconTable[data.weather[0].icon];

		var now = new Date();
		var sunrise = new Date(data.sys.sunrise * 1000);
		var sunset = new Date(data.sys.sunset * 1000);

		// The moment().format('h') method has a bug on the Raspberry Pi.
		// So we need to generate the timestring manually.
		// See issue: https://github.com/MichMich/MagicMirror/issues/181
		var sunriseSunsetDateObject = (sunrise < now && sunset > now) ? sunset : sunrise;
		var timeString = moment(sunriseSunsetDateObject).format('HH:mm');
		if (this.config.timeFormat !== 24) {
			//var hours = sunriseSunsetDateObject.getHours() % 12 || 12;
			if (this.config.showPeriod) {
				if (this.config.showPeriodUpper) {
					//timeString = hours + moment(sunriseSunsetDateObject).format(':mm A');
					timeString = moment(sunriseSunsetDateObject).format('h:mm A');
				} else {
					//timeString = hours + moment(sunriseSunsetDateObject).format(':mm a');
					timeString = moment(sunriseSunsetDateObject).format('h:mm a');
				}
			} else {
				//timeString = hours + moment(sunriseSunsetDateObject).format(':mm');
				timeString = moment(sunriseSunsetDateObject).format('h:mm');
			}
		}

		this.sunriseSunsetTime = timeString;
		this.sunriseSunsetIcon = (sunrise < now && sunset > now) ? "wi-sunset" : "wi-sunrise";

		this.loaded = true;
		this.updateDom(this.config.animationSpeed);
	},

	/* scheduleUpdate()
	 * Schedule next update.
	 *
	 * argument delay number - Milliseconds before next update. If empty, this.config.updateInterval is used.
	 */
	scheduleUpdate: function(delay) {
		var nextLoad = this.config.updateInterval;
		if (typeof delay !== "undefined" && delay >= 0) {
			nextLoad = delay;
		}

		var self = this;
		setTimeout(function() {
			self.updateWeather();
		}, nextLoad);
	},

	/* ms2Beaufort(ms)
	 * Converts m2 to beaufort (windspeed).
	 *
	 * argument ms number - Windspeed in m/s.
	 *
	 * return number - Windspeed in beaufort.
	 */
	ms2Beaufort: function(ms) {
		var kmh = ms * 60 * 60 / 1000;
		var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
		for (var beaufort in speeds) {
			var speed = speeds[beaufort];
			if (speed > kmh) {
				return beaufort;
			}
		}
		return 12;
	},

	/* function(temperature)
	 * Rounds a temperature to 1 decimal.
	 *
	 * argument temperature number - Temperature.
	 *
	 * return number - Rounded Temperature.
	 */

	deg2Cardinal: function(deg) {
                if (deg>11.25 && deg<=33.75){
                        return "NNE";
                } else if (deg > 33.75 && deg <= 56.25) {
                        return "NE";
                } else if (deg > 56.25 && deg <= 78.75) {
                        return "ENE";
                } else if (deg > 78.75 && deg <= 101.25) {
                        return "E";
                } else if (deg > 101.25 && deg <= 123.75) {
                        return "ESE";
                } else if (deg > 123.75 && deg <= 146.25) {
                        return "SE";
                } else if (deg > 146.25 && deg <= 168.75) {
                        return "SSE";
                } else if (deg > 168.75 && deg <= 191.25) {
                        return "S";
                } else if (deg > 191.25 && deg <= 213.75) {
                        return "SSW";
                } else if (deg > 213.75 && deg <= 236.25) {
                        return "SW";
                } else if (deg > 236.25 && deg <= 258.75) {
                        return "WSW";
                } else if (deg > 258.75 && deg <= 281.25) {
                        return "W";
                } else if (deg > 281.25 && deg <= 303.75) {
                        return "WNW";
                } else if (deg > 303.75 && deg <= 326.25) {
                        return "NW";
                } else if (deg > 326.25 && deg <= 348.75) {
                        return "NNW";
                } else {
                         return "N";
                }
	},

	roundValue: function(temperature) {
		return parseFloat(temperature).toFixed(1);
	}
});
<|endoftext|>


<commit_before>'use strict';

module.exports = function (app) {
  // Root routing
  var core = require('../controllers/core.server.controller');

  // Define error pages
  app.route('/server-error').get(core.renderServerError);

  // Return a 404 for all undefined api, module or lib routes
  app.route('/:url(api|modules|lib)/*').get(core.renderNotFound);

  // Define application route
  app.route('/*').get(core.renderIndex);
  console.log(app.locals);
};
<commit_msg>Commited from lenh at 2017年 6月  9日 金曜日 13:48:02<commit_after>'use strict';

module.exports = function (app) {
  // Root routing
  var core = require('../controllers/core.server.controller');

  // Define error pages
  app.route('/server-error').get(core.renderServerError);

  // Return a 404 for all undefined api, module or lib routes
  app.route('/:url(api|modules|lib)/*').get(core.renderNotFound);

  // Define application route
  app.route('/*').get(core.renderIndex);
};
<|endoftext|>


<commit_before>/*!
{
  "name" : "HTML5 Audio Element",
  "property": "audio",
  "aliases" : [],
  "tags" : ["html5", "audio", "media"],
  "doc" : "/docs/#audio",
  "knownBugs": [],
  "authors" : []
}
!*/
define(['Modernizr', 'createElement'], function( Modernizr, createElement ) {
  // This tests evaluates support of the audio element, as well as
  // testing what types of content it supports.
  //
  // We're using the Boolean constructor here, so that we can extend the value
  // e.g.  Modernizr.audio     // true
  //       Modernizr.audio.ogg // 'probably'
  //
  // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
  //                     thx to NielsLeenheer and zcorpan

  // Note: in some older browsers, "no" was a return value instead of empty string.
  //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
  //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
  Modernizr.addTest('audio', function() {
    /* jshint -W053 */
    var elem = createElement('audio');
    var bool = false;

    try {
      if ( bool = !!elem.canPlayType ) {
        bool      = new Boolean(bool);
        bool.ogg  = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
        bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');

        // Mimetypes accepted:
        //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
        //   bit.ly/iphoneoscodecs
        bool.wav  = elem.canPlayType('audio/wav; codecs="1"')     .replace(/^no$/,'');
        bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||
                     elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');
      }
    } catch(e) { }

    return bool;
  });
});
<commit_msg>add opus detection - fixes #699<commit_after>/*!
{
  "name" : "HTML5 Audio Element",
  "property": "audio",
  "aliases" : [],
  "tags" : ["html5", "audio", "media"],
  "doc" : "/docs/#audio",
  "knownBugs": [],
  "authors" : []
}
!*/
define(['Modernizr', 'createElement'], function( Modernizr, createElement ) {
  // This tests evaluates support of the audio element, as well as
  // testing what types of content it supports.
  //
  // We're using the Boolean constructor here, so that we can extend the value
  // e.g.  Modernizr.audio     // true
  //       Modernizr.audio.ogg // 'probably'
  //
  // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
  //                     thx to NielsLeenheer and zcorpan

  // Note: in some older browsers, "no" was a return value instead of empty string.
  //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
  //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
  Modernizr.addTest('audio', function() {
    /* jshint -W053 */
    var elem = createElement('audio');
    var bool = false;

    try {
      if ( bool = !!elem.canPlayType ) {
        bool      = new Boolean(bool);
        bool.ogg  = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
        bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');
        bool.opus  = elem.canPlayType('audio/ogg; codecs="opus"') .replace(/^no$/,'');

        // Mimetypes accepted:
        //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
        //   bit.ly/iphoneoscodecs
        bool.wav  = elem.canPlayType('audio/wav; codecs="1"')     .replace(/^no$/,'');
        bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||
                     elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');
      }
    } catch(e) { }

    return bool;
  });
});
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Audio file player with start, loop, stop.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string=} url if a url is passed in, it will be loaded
	 *                       and invoke the callback if it also passed
	 *                       in.
	 *  @param {function(Tone.Player)=} onload callback to be invoked
	 *                                     once the url is loaded
	 */
	Tone.Player = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  the duration of the buffer once it's been loaded
		 *  @type {number}
		 *  @readOnly
		 */
		this.duration = 0;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 */
		this.loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = 1;

		/**
		 *  enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing
		 *
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		//if there is a url, load it.
		if (!this.isUndef(options.url)){
			this.load(options.url, options.onload);
		}
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onended" : function(){},
		"loop" : false,
		"loopStart" : 0,
		"loopEnd" : -1,
		"retrigger" : false
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 * @param {string} url the url of the buffer to load.
	 *        filetype support depends on the
	 *        browser.
	 * @param  {function(Tone.Player)=} callback
	 */
	Tone.Player.prototype.load = function(url, callback){
		var self = this;
		if (!self._buffer){
			new Tone.Buffer({
				"url"  : url,
				"callback" :  function (buffer){
					self.setBuffer(buffer);
					if (callback){
						callback(self);
					}
				}
			});
		} else if (callback){
			callback(self);
		}
	};

	/**
	 *  set the buffer
	 *
	 *  @param {AudioBuffer} buffer the buffer which the player will play.
	 *                              note: if you switch the buffer after
	 *                              the player is already started, it will not
	 *                              take effect until the next time the player
	 *                              is started.
	 */
	Tone.Player.prototype.setBuffer = function(buffer){
		this._buffer = buffer;
		this.duration = buffer.duration;
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @param  {Tone.Time=} startTime
	 *  @param  {Tone.Time=} offset
	 *  @param  {Tone.Time=} duration
	 */
	Tone.Player.prototype.start = function(startTime, offset, duration){
		if (this.state === Tone.Source.State.STOPPED || this.retrigger){
			if (this._buffer){
				this.state = Tone.Source.State.STARTED;
				//if it's a loop the default offset is the loopstart point
				if (this.loop){
					offset = this.defaultArg(offset, this.loopStart);
				} else {
					//otherwise the default offset is 0
					offset = this.defaultArg(offset, 0);
				}
				duration = this.defaultArg(duration, this._buffer.duration - offset);
				//make the source
				this._source = this.context.createBufferSource();
				this._source.buffer = this._buffer;
				//set the looping properties
				if (this.loop){
					this._source.loop = this.loop;
					this._source.loopStart = this.toSeconds(this.loopStart);
					if (this.loopEnd !== -1){
						this._source.loopEnd = this.toSeconds(this.loopEnd);
					}
				}
				//and other properties
				this._source.playbackRate.value = this._playbackRate;
				this._source.onended = this._onended.bind(this);
				this.chain(this._source, this.output);
				//start it
				this._source.start(this.toSeconds(startTime), this.toSeconds(offset), this.toSeconds(duration));
			}
		}
	};

	/**
	 *  Stop playback.
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.Player.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				this.state = Tone.Source.State.STOPPED;
				this._source.stop(this.toSeconds(time));
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Player.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  set the rate at which the file plays
	 *
	 *  @param {number} rate
	 *  @param {Tone.Time=} rampTime (optional) the amount of time it takes to
	 *                               reach the rate
	 */
	Tone.Player.prototype.setPlaybackRate = function(rate, rampTime){
		this._playbackRate = rate;
		if (this._source) {
			this._source.playbackRate.exponentialRampToValueAtTime(rate, this.toSeconds(rampTime));
		}
	};

	/**
	 *  set the loop start position
	 *  @param {Tone.Time} loopStart the start time
	 */
	Tone.Player.prototype.setLoopStart = function(loopStart){
		this.loopStart = loopStart;
	};

	/**
	 *  set the loop end position
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopEnd = function(loopEnd){
		this.loopEnd = loopEnd;
	};

	/**
	 *  set the loop start and end
	 *  @param {Tone.Time} loopStart the loop end time
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.setLoopStart(loopStart);
		this.setLoopEnd(loopEnd);
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Player.prototype.set = function(params){
		if (!this.isUndef(params.playbackRate)) this.setPlaybackRate(params.playbackRate);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		if (!this.isUndef(params.loop)) this.loop = params.loop;
		if (!this.isUndef(params.loopStart)) this.setLoopStart(params.loopStart);
		if (!this.isUndef(params.loopEnd)) this.setLoopEnd(params.loopEnd);
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  dispose and disconnect
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	return Tone.Player;
});
<commit_msg>simplify buffer constructor<commit_after>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Audio file player with start, loop, stop.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string=} url if a url is passed in, it will be loaded
	 *                       and invoke the callback if it also passed
	 *                       in.
	 *  @param {function(Tone.Player)=} onload callback to be invoked
	 *                                     once the url is loaded
	 */
	Tone.Player = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  the duration of the buffer once it's been loaded
		 *  @type {number}
		 *  @readOnly
		 */
		this.duration = 0;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 */
		this.loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = 1;

		/**
		 *  enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing
		 *
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		//if there is a url, load it.
		if (!this.isUndef(options.url)){
			this.load(options.url, options.onload);
		}
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onended" : function(){},
		"loop" : false,
		"loopStart" : 0,
		"loopEnd" : -1,
		"retrigger" : false
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 * @param {string} url the url of the buffer to load.
	 *        filetype support depends on the
	 *        browser.
	 * @param  {function(Tone.Player)=} callback
	 */
	Tone.Player.prototype.load = function(url, callback){
		var self = this;
		if (!self._buffer){
			new Tone.Buffer(url, function (buffer){
				self.setBuffer(buffer);
				if (callback){
					callback(self);
				}
			});
		} else if (callback){
			callback(self);
		}
	};

	/**
	 *  set the buffer
	 *
	 *  @param {AudioBuffer} buffer the buffer which the player will play.
	 *                              note: if you switch the buffer after
	 *                              the player is already started, it will not
	 *                              take effect until the next time the player
	 *                              is started.
	 */
	Tone.Player.prototype.setBuffer = function(buffer){
		this._buffer = buffer;
		this.duration = buffer.duration;
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @param  {Tone.Time=} startTime
	 *  @param  {Tone.Time=} offset
	 *  @param  {Tone.Time=} duration
	 */
	Tone.Player.prototype.start = function(startTime, offset, duration){
		if (this.state === Tone.Source.State.STOPPED || this.retrigger){
			if (this._buffer){
				this.state = Tone.Source.State.STARTED;
				//if it's a loop the default offset is the loopstart point
				if (this.loop){
					offset = this.defaultArg(offset, this.loopStart);
				} else {
					//otherwise the default offset is 0
					offset = this.defaultArg(offset, 0);
				}
				duration = this.defaultArg(duration, this._buffer.duration - offset);
				//make the source
				this._source = this.context.createBufferSource();
				this._source.buffer = this._buffer;
				//set the looping properties
				if (this.loop){
					this._source.loop = this.loop;
					this._source.loopStart = this.toSeconds(this.loopStart);
					if (this.loopEnd !== -1){
						this._source.loopEnd = this.toSeconds(this.loopEnd);
					}
				}
				//and other properties
				this._source.playbackRate.value = this._playbackRate;
				this._source.onended = this._onended.bind(this);
				this.chain(this._source, this.output);
				//start it
				this._source.start(this.toSeconds(startTime), this.toSeconds(offset), this.toSeconds(duration));
			}
		}
	};

	/**
	 *  Stop playback.
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.Player.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				this.state = Tone.Source.State.STOPPED;
				this._source.stop(this.toSeconds(time));
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Player.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  set the rate at which the file plays
	 *
	 *  @param {number} rate
	 *  @param {Tone.Time=} rampTime (optional) the amount of time it takes to
	 *                               reach the rate
	 */
	Tone.Player.prototype.setPlaybackRate = function(rate, rampTime){
		this._playbackRate = rate;
		if (this._source) {
			this._source.playbackRate.exponentialRampToValueAtTime(rate, this.toSeconds(rampTime));
		}
	};

	/**
	 *  set the loop start position
	 *  @param {Tone.Time} loopStart the start time
	 */
	Tone.Player.prototype.setLoopStart = function(loopStart){
		this.loopStart = loopStart;
	};

	/**
	 *  set the loop end position
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopEnd = function(loopEnd){
		this.loopEnd = loopEnd;
	};

	/**
	 *  set the loop start and end
	 *  @param {Tone.Time} loopStart the loop end time
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.setLoopStart(loopStart);
		this.setLoopEnd(loopEnd);
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Player.prototype.set = function(params){
		if (!this.isUndef(params.playbackRate)) this.setPlaybackRate(params.playbackRate);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		if (!this.isUndef(params.loop)) this.loop = params.loop;
		if (!this.isUndef(params.loopStart)) this.setLoopStart(params.loopStart);
		if (!this.isUndef(params.loopEnd)) this.setLoopEnd(params.loopEnd);
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  dispose and disconnect
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	return Tone.Player;
});
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var tasks = require('../task/12-katas-3-tasks');
it.optional = require('../extensions/it-optional');

describe('12-katas-3-tasks', function() {

    it.optional('findStringInSnakingPuzzle shoud return true if word occurrs in the specified puzzle', () => {
        var puzzle = [
            'ANGULAR',
            'REDNCAE',
            'RFIDTCL',
            'AGNEGSA',
            'YTIRTSP',
        ];
        var puzzleToString = (p) => p.map(x=>'       '+x).join('\n');
        [
            'ANGULAR', 'REACT', 'UNDEFINED', 'RED', 'STRING', 'CLASS', 'ARRAY'
        ].forEach(word => {
            assert(
                tasks.findStringInSnakingPuzzle(puzzle, word),
                `Word "${word}" occurrs in puzzle\n${puzzleToString(puzzle)}`
            );
        });

        [
            'FUNCTION', 'NULL', 'EMBER', 'HOISTING', 'GIT', 'ARENA'
        ].forEach(word => {
            assert(
                !tasks.findStringInSnakingPuzzle(puzzle, word),
                `Word "${word}" does not occurr in puzzle\n${puzzleToString(puzzle)}`
            );
        });
    });

    it.optional('getPermutations should return all possible string permutations', () => {
        [
            {
                chars:    'a',
                expected: [ 'a' ]
            },{
                chars:    'ab',
                expected: [ 'ab', 'ba' ]
            },{
                chars:    'abc',
                expected: [ 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' ]
            },{
                chars:    'abcd',
                expected: [
                    'abcd', 'abdc', 'acbd', 'acdb', 'adbc', 'adcb',
                    'bacd', 'badc', 'bdac', 'bdca', 'bcad', 'bcda',
                    'cabd', 'cadb', 'cbad', 'cbda', 'cdab', 'cdba',
                    'dabc', 'dacb', 'dbac', 'dbca', 'dcab', 'dcba'
                ]
            }
        ].forEach(data => {
            assert.deepEqual(
                Array.from(tasks.getPermutations(data.chars)).sort(),
                data.expected,
                `Incorrect permutations of "${data.chars}"`
            );
        });
        assert.equal(
            Array.from(tasks.getPermutations('12345')).length,
            120,
            'Number of 5 chars permutations should be 120.'
        );
    });

    it.optional('getMostProfitFromStockQuotes should return the max profit from stock trading', () => {
        [
            {
                quotes:   [ 1, 2, 3, 4, 5, 6 ],
                expected: 15
            },{
                quotes:   [ 6, 5, 4, 3, 2, 1 ],
                expected: 0
            },{
                quotes:   [ 1, 6, 5, 10, 8, 7 ],
                expected: 18
            },{
                quotes:   [ 31, 312, 3, 35, 33, 3, 44, 123, 126, 2, 4, 1 ],
                expected: 798
            },{
                quotes:   [ 1, 20, 1, 30, 1, 40, 1, 50, 1, 40, 1, 30, 1, 20, 1 ],
                expected: 343
            }
        ].forEach(data => {
            var actual = tasks.getMostProfitFromStockQuotes(data.quotes);
            assert.equal(
                actual,
                data.expected,
                `Most profit for [${data.quotes}] quotes is ${data.expected} but actually ${actual}`
            );
        });
    });

    it.optional('urlShortener should return encoded string shorter than original url', () => {
        [
            'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul',
            'https://en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters',
            'https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_plain_text'
        ].forEach(data => {
            var urlShortener = new tasks.UrlShortener();
            var actual = urlShortener.encode(data);
            assert(
                data.length / actual.length > 1.5,
                `urlShortener.encode for "${data}" returns "${actual}" that is only ${data.length/actual.length} times less than original url`
            );
        });
    });

    it.optional('urlShortener should decode shorten link to to the original url', () => {
        [
            'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul',
            'https://www.example.com/catalog.html?search=mobile+phones&price=100-200&year=2016#top_links',
        ].forEach(data => {
            var urlShortener = new tasks.UrlShortener();
            var encoded = urlShortener.encode(data);
            var actual = urlShortener.decode(encoded);
            assert.equal(
                data,
                actual,
                `urlShortener.encode for "${data}" returns "${encoded}" but decode returns "${actual}"`
            );
        });
    });

});
<commit_msg>Fix test for getPermutations kata<commit_after>'use strict';

var assert = require('assert');
var tasks = require('../task/12-katas-3-tasks');
it.optional = require('../extensions/it-optional');

describe('12-katas-3-tasks', function() {

    it.optional('findStringInSnakingPuzzle shoud return true if word occurrs in the specified puzzle', () => {
        var puzzle = [
            'ANGULAR',
            'REDNCAE',
            'RFIDTCL',
            'AGNEGSA',
            'YTIRTSP',
        ];
        var puzzleToString = (p) => p.map(x=>'       '+x).join('\n');
        [
            'ANGULAR', 'REACT', 'UNDEFINED', 'RED', 'STRING', 'CLASS', 'ARRAY'
        ].forEach(word => {
            assert(
                tasks.findStringInSnakingPuzzle(puzzle, word),
                `Word "${word}" occurrs in puzzle\n${puzzleToString(puzzle)}`
            );
        });

        [
            'FUNCTION', 'NULL', 'EMBER', 'HOISTING', 'GIT', 'ARENA'
        ].forEach(word => {
            assert(
                !tasks.findStringInSnakingPuzzle(puzzle, word),
                `Word "${word}" does not occurr in puzzle\n${puzzleToString(puzzle)}`
            );
        });
    });

    it.optional('getPermutations should return all possible string permutations', () => {
        [
            {
                chars:    'a',
                expected: [ 'a' ]
            },{
                chars:    'ab',
                expected: [ 'ab', 'ba' ]
            },{
                chars:    'abc',
                expected: [ 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' ]
            },{
                chars:    'abcd',
                expected: [
                    'abcd', 'abdc', 'acbd', 'acdb', 'adbc', 'adcb',
                    'bacd', 'badc', 'bcad', 'bcda', 'bdac', 'bdca',
                    'cabd', 'cadb', 'cbad', 'cbda', 'cdab', 'cdba',
                    'dabc', 'dacb', 'dbac', 'dbca', 'dcab', 'dcba'
                ]
            }
        ].forEach(data => {
            assert.deepEqual(
                Array.from(tasks.getPermutations(data.chars)).sort(),
                data.expected,
                `Incorrect permutations of "${data.chars}"`
            );
        });
        assert.equal(
            Array.from(tasks.getPermutations('12345')).length,
            120,
            'Number of 5 chars permutations should be 120.'
        );
    });

    it.optional('getMostProfitFromStockQuotes should return the max profit from stock trading', () => {
        [
            {
                quotes:   [ 1, 2, 3, 4, 5, 6 ],
                expected: 15
            },{
                quotes:   [ 6, 5, 4, 3, 2, 1 ],
                expected: 0
            },{
                quotes:   [ 1, 6, 5, 10, 8, 7 ],
                expected: 18
            },{
                quotes:   [ 31, 312, 3, 35, 33, 3, 44, 123, 126, 2, 4, 1 ],
                expected: 798
            },{
                quotes:   [ 1, 20, 1, 30, 1, 40, 1, 50, 1, 40, 1, 30, 1, 20, 1 ],
                expected: 343
            }
        ].forEach(data => {
            var actual = tasks.getMostProfitFromStockQuotes(data.quotes);
            assert.equal(
                actual,
                data.expected,
                `Most profit for [${data.quotes}] quotes is ${data.expected} but actually ${actual}`
            );
        });
    });

    it.optional('urlShortener should return encoded string shorter than original url', () => {
        [
            'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul',
            'https://en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters',
            'https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_plain_text'
        ].forEach(data => {
            var urlShortener = new tasks.UrlShortener();
            var actual = urlShortener.encode(data);
            assert(
                data.length / actual.length > 1.5,
                `urlShortener.encode for "${data}" returns "${actual}" that is only ${data.length/actual.length} times less than original url`
            );
        });
    });

    it.optional('urlShortener should decode shorten link to to the original url', () => {
        [
            'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul',
            'https://www.example.com/catalog.html?search=mobile+phones&price=100-200&year=2016#top_links',
        ].forEach(data => {
            var urlShortener = new tasks.UrlShortener();
            var encoded = urlShortener.encode(data);
            var actual = urlShortener.decode(encoded);
            assert.equal(
                data,
                actual,
                `urlShortener.encode for "${data}" returns "${encoded}" but decode returns "${actual}"`
            );
        });
    });

});
<|endoftext|>


<commit_before>'use strict';
const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const fs = require('fs');
const git = require('git-rev-sync');
const exec = require('child_process').exec;

exec(`rm -fr ${__dirname}/dist/*`, (err, stdout, stderr) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(stdout);
});

function CreateWebpackConfig(type) {

    let ext = (type == 'js' && 'js' || type == 'scss' && 'css' || type == 'html' && 'html');

    this.entry = {};
    //custom files input
    if (type == 'js') {
        this.entry['app'] = path.join(__dirname, 'app', 'Main');
        //this.entry['app'] = path.join(__dirname, 'app', 'a11');
    } else if (type == 'scss') {
        this.entry['files'] = path.join(__dirname, 'app', 'assets', 'files');
        this.entry['app'] = path.join(__dirname, 'app', 'assets', 'stylesheets', 'app');
        //this.entry['file1'] = path.join(__dirname, folder, 'file1');
    } else if (type == 'html') {
        this.entry['index'] = path.join(__dirname, 'app', 'assets', 'index');
    }

    this.output = {
        filename: '[name].' + ext,
        path: path.join(__dirname, 'dist'),
        publicPath: ''
    }; //publicPath !!

    let outputfile = path.join(this.output.path, `index.${ext}`);

    this.resolve = {
        extensions: ['']
    };

    this.resolve.extensions.push(`.${type}`);

    this.module = {
        loaders: []
    };

    if (type == 'js') {

        this.resolve.extensions.push(".jsx");
        this.resolve.extensions.push(".coffee");
        this.resolve.extensions.push(".json");

        this.resolve.root = [path.resolve(__dirname, "./app"), path.resolve(__dirname, "./lib")];
        this.resolve.modulesDirectories = ["../node_modules"];
        this.resolve.fallback = [path.resolve(__dirname, "../node_modules")];
        this.resolveLoader = {
            root: path.join(__dirname, "../node_modules"),
            fallback: [path.resolve(__dirname, "../node_modules")]
        };

        this.module.loaders.push({
            test: /\.md/,
            loader: 'html?removeAttributeQuotes=false!remarkable'
        });

        this.remarkable = {
            preset: "full",
            typographer: true
        };

        this.module.loaders.push({
            test: /\.jsx{0,1}$/i,
            exclude: /node_modules\/(?!(react-foundation-apps)\/).*/,
            //include: ["../node_modules/react-foundation-apps"],
            loader: 'babel',
            query: {
                presets: ["react", "es2015", "stage-0"],
                plugins: ["transform-decorators-legacy", "transform-decorators"]
            }
        });

        this.module.loaders.push({
            test: /\.json/,
            loader: "json",
            exclude: [
                path.resolve(__dirname, "../dl/src/common"),
                path.resolve(__dirname, "../web/app/assets/locales")
            ]
        });

        this.module.loaders.push({
            test: /\.coffee$/,
            loader: "coffee-loader"
        });

        this.module.loaders.push({
            test: /\.(coffee\.md|litcoffee)$/,
            loader: "coffee-loader?literate"
        });

    } else if (type == 'scss') {

        this.module.loaders.push({
            test: /\.scss$/,
            loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true')
        });

        this.module.loaders.push({
            test: /\.(jpe?g|png|gif|svg|ttf|eot|woff|woff2)$/i,
            loader: 'file?name=[path][name].[ext]'
        });

        this.module.loaders.push({
            test: /\.md/,
            loader: 'html?removeAttributeQuotes=false!remarkable'
        });

        this.module.postcss = function() {
            return [precss, autoprefixer];
        };

    } else if (type == 'html') {

        this.module.loaders.push({
            test: /\.html$/,
            loader: ExtractTextPlugin.extract('html?minimize=false')
        });
    }

    this.plugins = [
        new webpack.DefinePlugin({
            NODE_ENV: JSON.stringify(NODE_ENV),
            APP_VERSION: JSON.stringify(git.tag()),
            __ELECTRON__: false
        }),
        new webpack.NoErrorsPlugin(),
        function() {
            this.plugin("done", function(stats) {
                if (stats.compilation.errors && stats.compilation.errors.length) {
                    console.log(stats.compilation.errors[0].error);
                    if (fs.existsSync(outputfile)) {
                        fs.writeFileSync(outputfile, JSON.stringify(stats.compilation.errors[0].error.details), 'utf8');
                    }
                }
            });
        }
    ];

    if (type == 'scss' || type == 'html') {
        this.plugins.push(new ExtractTextPlugin(`[name].${ext}`))
    }

    this.devtool = (NODE_ENV == 'development' ? "inline-source-map" : '');

    if (NODE_ENV == 'production') {
        this.plugins.push(new webpack.optimize.UglifyJsPlugin({
            beautify: false,
            comments: false,
            compress: {
                sequences: true,
                booleans: true,
                loops: true,
                unused: true,
                warnings: false,
                drop_console: true,
                unsafe: true
            }
        }));
    }
}

module.exports = [
   new CreateWebpackConfig('js'),
   new CreateWebpackConfig('scss'),
   new CreateWebpackConfig('html')
];
<commit_msg>fix webpack path<commit_after>'use strict';
const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const fs = require('fs');
const git = require('git-rev-sync');
const exec = require('child_process').exec;

exec(`rm -fr ${__dirname}/dist/*`, (err, stdout, stderr) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(stdout);
});

function CreateWebpackConfig(type) {

    let ext = (type == 'js' && 'js' || type == 'scss' && 'css' || type == 'html' && 'html');

    this.entry = {};
    //custom files input
    if (type == 'js') {
        this.entry['app'] = path.join(__dirname, 'app', 'Main');
        //this.entry['app'] = path.join(__dirname, 'app', 'a11');
    } else if (type == 'scss') {
        this.entry['files'] = path.join(__dirname, 'app', 'assets', 'files');
        this.entry['app'] = path.join(__dirname, 'app', 'assets', 'stylesheets', 'app');
        //this.entry['file1'] = path.join(__dirname, folder, 'file1');
    } else if (type == 'html') {
        this.entry['index'] = path.join(__dirname, 'app', 'assets', 'index');
    }

    this.output = {
        filename: '[name].' + ext,
        path: path.join(__dirname, 'dist'),
        publicPath: ''
    }; //publicPath !!

    let outputfile = path.join(this.output.path, `index.${ext}`);

    this.resolve = {
        extensions: ['']
    };

    this.resolve.extensions.push(`.${type}`);

    this.module = {
        loaders: []
    };

    if (type == 'js') {

        this.resolve.extensions.push(".jsx");
        this.resolve.extensions.push(".coffee");
        this.resolve.extensions.push(".json");

        this.resolve.root = [path.resolve(__dirname, "./app"), path.resolve(__dirname, "./lib")];
        this.resolve.modulesDirectories = ["../node_modules"];
        this.resolve.fallback = [path.resolve(__dirname, "../node_modules")];
        this.resolveLoader = {
            root: path.join(__dirname, "../node_modules"),
            fallback: [path.resolve(__dirname, "../node_modules")]
        };

        this.module.loaders.push({
            test: /\.md/,
            loader: 'html?removeAttributeQuotes=false!remarkable'
        });

        this.remarkable = {
            preset: "full",
            typographer: true
        };

        this.module.loaders.push({
            test: /\.jsx{0,1}$/i,
            exclude: /node_modules\/(?!(react-foundation-apps)\/).*/,
            //include: ["../node_modules/react-foundation-apps"],
            loader: 'babel',
            query: {
                presets: ["react", "es2015", "stage-0"],
                plugins: ["transform-decorators-legacy", "transform-decorators"]
            }
        });

        this.module.loaders.push({
            test: /\.json/,
            loader: "json",
            exclude: [
                path.resolve(__dirname, "./lib/common"),
                path.resolve(__dirname, "./app/assets/locales")
            ]
        });

        this.module.loaders.push({
            test: /\.coffee$/,
            loader: "coffee-loader"
        });

        this.module.loaders.push({
            test: /\.(coffee\.md|litcoffee)$/,
            loader: "coffee-loader?literate"
        });

    } else if (type == 'scss') {

        this.module.loaders.push({
            test: /\.scss$/,
            loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true')
        });

        this.module.loaders.push({
            test: /\.(jpe?g|png|gif|svg|ttf|eot|woff|woff2)$/i,
            loader: 'file?name=[path][name].[ext]'
        });

        this.module.loaders.push({
            test: /\.md/,
            loader: 'html?removeAttributeQuotes=false!remarkable'
        });

        this.module.postcss = function() {
            return [precss, autoprefixer];
        };

    } else if (type == 'html') {

        this.module.loaders.push({
            test: /\.html$/,
            loader: ExtractTextPlugin.extract('html?minimize=false')
        });
    }

    this.plugins = [
        new webpack.DefinePlugin({
            NODE_ENV: JSON.stringify(NODE_ENV),
            APP_VERSION: JSON.stringify(git.tag()),
            __ELECTRON__: false
        }),
        new webpack.NoErrorsPlugin(),
        function() {
            this.plugin("done", function(stats) {
                if (stats.compilation.errors && stats.compilation.errors.length) {
                    console.log(stats.compilation.errors[0].error);
                    if (fs.existsSync(outputfile)) {
                        fs.writeFileSync(outputfile, JSON.stringify(stats.compilation.errors[0].error.details), 'utf8');
                    }
                }
            });
        }
    ];

    if (type == 'scss' || type == 'html') {
        this.plugins.push(new ExtractTextPlugin(`[name].${ext}`))
    }

    this.devtool = (NODE_ENV == 'development' ? "inline-source-map" : '');

    if (NODE_ENV == 'production') {
        this.plugins.push(new webpack.optimize.UglifyJsPlugin({
            beautify: false,
            comments: false,
            compress: {
                sequences: true,
                booleans: true,
                loops: true,
                unused: true,
                warnings: false,
                drop_console: true,
                unsafe: true
            }
        }));
    }
}

module.exports = [
   new CreateWebpackConfig('js'),
   new CreateWebpackConfig('scss'),
   new CreateWebpackConfig('html')
];
<|endoftext|>


<commit_before>var should    = require("should")
  , config    = require("./config/config")
  , Helpers   = require("./config/helpers")
  , Sequelize = require("../index")

describe('ModelDefinition', function() {
  var sequelize = new Sequelize(config.database, config.username, config.password, { logging: false })
    , User      = sequelize.define('User', { name: Sequelize.STRING, bio: Sequelize.TEXT })

  afterEach(function() {
    Helpers.async(function(done) {
      sequelize.drop().on('success', done)
    })
  })

  describe('.all', function() {
    beforeEach(function() {
      var createUser  = function(num, cb) {
      console.log('create user')
        User.create({name: 'user' + num, bio: 'foobar'}).on('success', function(user){
          --num ? createUser(num, cb) : cb()
        })
      }

      Helpers.async(function(done) {
        User.sync({force: true}).on('success', function() { done() })
      })
      Helpers.async(function(done) { createUser(2, done) })
    })

    it("should return all users", function() {

      Helpers.async(function(done) {
        User.all.on('success', function(users) {
          done()
          expect(users.length).toEqual(2)
        })
      })

    })
  })

  describe('.create with options', function() {
    var Person = sequelize.define('Person', { name: Sequelize.STRING, options: Sequelize.TEXT })

    beforeEach(function() {
      Helpers.async(function(done) {
        Person.sync({force: true}).on('success', function() { done() })
      })
    })

    it('should allow the creation of an object with options as attribute', function() {
      Helpers.async(function(done) {
        var options = JSON.stringify({ foo: 'bar', bar: 'foo' })
        Person.create({name: 'John Doe', options: options}).on('success', function(person) {
          expect(person.options).toEqual(options)
          done()
        })
      })
    })
  })
})
<commit_msg>failure output for tests<commit_after>var should    = require("should")
  , config    = require("./config/config")
  , Helpers   = require("./config/helpers")
  , Sequelize = require("../index")

describe('ModelDefinition', function() {
  var sequelize = new Sequelize(config.database, config.username, config.password, { logging: false })
    , User      = sequelize.define('User', { name: Sequelize.STRING, bio: Sequelize.TEXT })

  afterEach(function() {
    Helpers.async(function(done) {
      sequelize.drop().on('success', done).on('failure', function(err) { console.log(err) })
    })
  })

  describe('.all', function() {
    beforeEach(function() {
      var createUser  = function(num, cb) {
      console.log('create user')
        User.create({name: 'user' + num, bio: 'foobar'}).on('success', function(user){
          --num ? createUser(num, cb) : cb()
        })
      }

      Helpers.async(function(done) {
        User.sync({force: true})
            .on('success', function() { done() })
            .on('failure', function(err) { console.log(err) })
      })
      Helpers.async(function(done) { createUser(2, done) })
    })

    it("should return all users", function() {

      Helpers.async(function(done) {
        User.all.on('success', function(users) {
          done()
          expect(users.length).toEqual(2)
        }).on('failure', function(err) { console.log(err) })
      })

    })
  })

  describe('.create with options', function() {
    var Person = sequelize.define('Person', { name: Sequelize.STRING, options: Sequelize.TEXT })

    beforeEach(function() {
      Helpers.async(function(done) {
        Person.sync({force: true})
              .on('success', function() { done() })
              .on('failure', function(err) { console.log(err) })
      })
    })

    it('should allow the creation of an object with options as attribute', function() {
      Helpers.async(function(done) {
        var options = JSON.stringify({ foo: 'bar', bar: 'foo' })
        Person.create({name: 'John Doe', options: options}).on('success', function(person) {
          expect(person.options).toEqual(options)
          done()
        }).on('failure', function(err) { console.log(err) })
      })
    })
  })
})
<|endoftext|>


<commit_before>jQuery.extend({highlight:function(a,b,c,d){if(a.nodeType===3){var e=a.data.match(b);if(e){var f=document.createElement(c||"span");f.className=d||"highlight";var g=a.splitText(e.index);g.splitText(e[0].length);var h=g.cloneNode(true);f.appendChild(h);g.parentNode.replaceChild(f,g);return 1}}else if(a.nodeType===1&&a.childNodes&&!/(script|style)/i.test(a.tagName)&&!(a.tagName===c.toUpperCase()&&a.className===d)){for(var i=0;i<a.childNodes.length;i++){i+=jQuery.highlight(a.childNodes[i],b,c,d)}}return 0}});jQuery.fn.unhighlight=function(a){var b={className:"highlight",element:"span"};jQuery.extend(b,a);return this.find(b.element+"."+b.className).each(function(){var a=this.parentNode;a.replaceChild(this.firstChild,this);a.normalize()}).end()};jQuery.fn.highlight=function(a,b){var c={className:"highlight",element:"span",caseSensitive:false,wordsOnly:false};jQuery.extend(c,b);if(a.constructor===String){a=[a]}a=jQuery.grep(a,function(a,b){return a!=""});a=jQuery.map(a,function(a,b){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")});if(a.length==0){return this}var d=c.caseSensitive?"":"i";var e="("+a.join("|")+")";if(c.wordsOnly){e="\\b"+e+"\\b"}var f=new RegExp(e,d);return this.each(function(){jQuery.highlight(this,f,c.element,c.className)})}

$(window).load(function(){

// Config
    var SearchBox = "#search-box";
    var SearchableElements = "#searchable blockquote";
    var SearchResultCount = "#filter-count";

    $(SearchResultCount).text($(SearchableElements).length);

// SearchBox
    $(SearchBox).keyup(function() {

        $(SearchResultCount).text("Searching ...");

        var filter = $(this).val();
        var count = 0;
        $('#searchable').unhighlight()

        $(SearchableElements).each(function() {
            if ($(this).text().search(new RegExp(filter, "i")) < 0) {

                $(this).parent().parent().animate({
                    opacity: 0
                }, 100, function() {
                    $(this).css('overflow', 'hidden').hide(100);
                });

            } else {
                $(this).parent().parent().animate({
                    opacity: 1,
                    height: '100%',
                }, 100, function() {
                    $(this).show(100);
                });
                $('#searchable').highlight(filter);
                count++;
            }
        });

        var numberItems = count;
        $(SearchResultCount).text(count);

    });
});<commit_msg>Working on adding a search box to the main page<commit_after>jQuery.extend({highlight:function(a,b,c,d){if(a.nodeType===3){var e=a.data.match(b);if(e){var f=document.createElement(c||"span");f.className=d||"highlight";var g=a.splitText(e.index);g.splitText(e[0].length);var h=g.cloneNode(true);f.appendChild(h);g.parentNode.replaceChild(f,g);return 1}}else if(a.nodeType===1&&a.childNodes&&!/(script|style)/i.test(a.tagName)&&!(a.tagName===c.toUpperCase()&&a.className===d)){for(var i=0;i<a.childNodes.length;i++){i+=jQuery.highlight(a.childNodes[i],b,c,d)}}return 0}});jQuery.fn.unhighlight=function(a){var b={className:"highlight",element:"span"};jQuery.extend(b,a);return this.find(b.element+"."+b.className).each(function(){var a=this.parentNode;a.replaceChild(this.firstChild,this);a.normalize()}).end()};jQuery.fn.highlight=function(a,b){var c={className:"highlight",element:"span",caseSensitive:false,wordsOnly:false};jQuery.extend(c,b);if(a.constructor===String){a=[a]}a=jQuery.grep(a,function(a,b){return a!=""});a=jQuery.map(a,function(a,b){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")});if(a.length==0){return this}var d=c.caseSensitive?"":"i";var e="("+a.join("|")+")";if(c.wordsOnly){e="\\b"+e+"\\b"}var f=new RegExp(e,d);return this.each(function(){jQuery.highlight(this,f,c.element,c.className)})}

$(window).load(function(){
alert('running');
// Config
    var SearchBox = "#search-box";
    var SearchableElements = "#searchable blockquote";
    var SearchResultCount = "#filter-count";

    $(SearchResultCount).text($(SearchableElements).length);

// SearchBox
    $(SearchBox).keyup(function() {

        $(SearchResultCount).text("Searching ...");

        var filter = $(this).val();
        var count = 0;
        $('#searchable').unhighlight()

        $(SearchableElements).each(function() {
            if ($(this).text().search(new RegExp(filter, "i")) < 0) {

                $(this).parent().parent().animate({
                    opacity: 0
                }, 100, function() {
                    $(this).css('overflow', 'hidden').hide(100);
                });

            } else {
                $(this).parent().parent().animate({
                    opacity: 1,
                    height: '100%',
                }, 100, function() {
                    $(this).show(100);
                });
                $('#searchable').highlight(filter);
                count++;
            }
        });

        var numberItems = count;
        $(SearchResultCount).text(count);

    });
});<|endoftext|>


<commit_before>import './tooltip.css'
import 'rc-tooltip/assets/bootstrap.css'
import PropTypes from 'prop-types'
import RcTooltip from 'rc-tooltip'
import React from 'react'

export default class Tooltip extends React.Component {
    placement() {
        const {left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight} = this.props
        return left ? 'left' :
            right ? 'right' :
                top ? 'top' :
                    bottom ? 'bottom' :
                        topLeft ? 'topLeft' :
                            topRight ? 'topRight' :
                                bottomLeft ? 'bottomLeft' :
                                    bottomRight ? 'bottomRight' :
                                        'top'
    }

    render() {
        const {msg, disabled = false, delay = .5, children, ...otherProps} = this.props
        return (
            !disabled ? (
                <RcTooltip
                    overlay={msg}
                    placement={this.placement()}
                    mouseEnterDelay={delay}
                    trigger={['hover']}
                    {...otherProps}>
                    {children}
                </RcTooltip>
            ) : <React.Fragment>{children}</React.Fragment>)
    }
}

Tooltip.propTypes = {
    msg: PropTypes.any.isRequired,
    bottom: PropTypes.bool,
    bottomLeft: PropTypes.bool,
    bottomRight: PropTypes.bool,
    children: PropTypes.object,
    delay: PropTypes.number,
    disabled: PropTypes.bool,
    left: PropTypes.bool,
    right: PropTypes.bool,
    top: PropTypes.bool,
    topLeft: PropTypes.bool,
    topRight: PropTypes.bool
}
<commit_msg>Disabled rendering of tooltip when message is empty.<commit_after>import './tooltip.css'
import 'rc-tooltip/assets/bootstrap.css'
import PropTypes from 'prop-types'
import RcTooltip from 'rc-tooltip'
import React from 'react'

export default class Tooltip extends React.Component {
    placement() {
        const {left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight} = this.props
        return left ? 'left' :
            right ? 'right' :
                top ? 'top' :
                    bottom ? 'bottom' :
                        topLeft ? 'topLeft' :
                            topRight ? 'topRight' :
                                bottomLeft ? 'bottomLeft' :
                                    bottomRight ? 'bottomRight' :
                                        'top'
    }

    render() {
        const {msg, disabled = false, delay = .5, children, ...otherProps} = this.props
        return (
            msg && !disabled
                ? (
                    <RcTooltip
                        overlay={msg}
                        placement={this.placement()}
                        mouseEnterDelay={delay}
                        trigger={['hover']}
                        {...otherProps}>
                        {children}
                    </RcTooltip>
                )
                : <React.Fragment>{children}</React.Fragment>)
    }
}

Tooltip.propTypes = {
    bottom: PropTypes.bool,
    bottomLeft: PropTypes.bool,
    bottomRight: PropTypes.bool,
    children: PropTypes.object,
    delay: PropTypes.number,
    disabled: PropTypes.bool,
    left: PropTypes.bool,
    msg: PropTypes.any,
    right: PropTypes.bool,
    top: PropTypes.bool,
    topLeft: PropTypes.bool,
    topRight: PropTypes.bool
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var path = require('path'),
    facebookNotificationService = require(path.resolve('./modules/core/server/services/facebook-notification.server.service')),
    core = require('../controllers/core.server.controller'),
    userProfile = require(path.resolve('./modules/users/server/controllers/users.profile.server.controller')),
    tribes = require(path.resolve('./modules/tribes/server/controllers/tribes.server.controller'));

module.exports = function (app) {

  var redirect = function(src, dst) {
    app.route(src).get(function (req, res) {
      res.redirect(301, dst);
    });
  }

  redirect('/invite', '/signup');
  redirect('/tribes/lgbt', '/tribes/lgbtq');
  redirect('/tribes/vegans-vegetarians', '/tribes/veg');

  // Gives the service worker access to any config it needs
  app.route('/config/sw.js').get(core.renderServiceWorkerConfig);

  // CSP Violations
  // Note: If you’re using a CSRF module like csurf, you might have problems
  // handling these violations without a valid CSRF token. The fix is to put
  // your CSP report route above csurf middleware.
  // See `config/lib/express.js` and `initHelmetHeaders()` for more
  app.route('/api/report-csp-violation').post(core.receiveCSPViolationReport);

  // Excect CT Violations
  // Note: If you’re using a CSRF module like csurf, you might have problems
  // handling these violations without a valid CSRF token. The fix is to put
  // your CSP report route above csurf middleware.
  // See `config/lib/express.js` and `initHelmetHeaders()` for more
  app.route('/api/report-expect-ct-violation').post(core.receiveExpectCTViolationReport);

  // Return a 404 for all undefined api, module or lib routes
  app.route('/:url(api|modules|lib|developers)/*').get(core.renderNotFound);

  // Define a tribes route to ensure we'll pass tribe object to index
  // Object is passed to layout at `core.renderIndex()`
  app.route('/tribes/:tribe').get(core.renderIndex);

  // Short URL for invite codes
  app.route('/c/:code').get(userProfile.redirectInviteShortUrl);

  // Define application route
  app.route('/*').get(core.renderIndex);

  // When Facebook notifications are enabled
  // Embedding app in Facebook canvas iframe is enabled, but it uses `POST`

  if (facebookNotificationService.isNotificationsEnabled()) {
    app.route('/*').post(core.renderIndex);
  }

  // Finish by binding the tribes middleware
  app.param('tribe', tribes.tribeBySlug);

};
<commit_msg>Fix eslint<commit_after>'use strict';

/**
 * Module dependencies.
 */
var path = require('path'),
    facebookNotificationService = require(path.resolve('./modules/core/server/services/facebook-notification.server.service')),
    core = require('../controllers/core.server.controller'),
    userProfile = require(path.resolve('./modules/users/server/controllers/users.profile.server.controller')),
    tribes = require(path.resolve('./modules/tribes/server/controllers/tribes.server.controller'));

module.exports = function (app) {

  var redirect = function (src, dst) {
    app.route(src).get(function (req, res) {
      res.redirect(301, dst);
    });
  };

  redirect('/invite', '/signup');
  redirect('/tribes/lgbt', '/tribes/lgbtq');
  redirect('/tribes/vegans-vegetarians', '/tribes/veg');

  // Gives the service worker access to any config it needs
  app.route('/config/sw.js').get(core.renderServiceWorkerConfig);

  // CSP Violations
  // Note: If you’re using a CSRF module like csurf, you might have problems
  // handling these violations without a valid CSRF token. The fix is to put
  // your CSP report route above csurf middleware.
  // See `config/lib/express.js` and `initHelmetHeaders()` for more
  app.route('/api/report-csp-violation').post(core.receiveCSPViolationReport);

  // Excect CT Violations
  // Note: If you’re using a CSRF module like csurf, you might have problems
  // handling these violations without a valid CSRF token. The fix is to put
  // your CSP report route above csurf middleware.
  // See `config/lib/express.js` and `initHelmetHeaders()` for more
  app.route('/api/report-expect-ct-violation').post(core.receiveExpectCTViolationReport);

  // Return a 404 for all undefined api, module or lib routes
  app.route('/:url(api|modules|lib|developers)/*').get(core.renderNotFound);

  // Define a tribes route to ensure we'll pass tribe object to index
  // Object is passed to layout at `core.renderIndex()`
  app.route('/tribes/:tribe').get(core.renderIndex);

  // Short URL for invite codes
  app.route('/c/:code').get(userProfile.redirectInviteShortUrl);

  // Define application route
  app.route('/*').get(core.renderIndex);

  // When Facebook notifications are enabled
  // Embedding app in Facebook canvas iframe is enabled, but it uses `POST`

  if (facebookNotificationService.isNotificationsEnabled()) {
    app.route('/*').post(core.renderIndex);
  }

  // Finish by binding the tribes middleware
  app.param('tribe', tribes.tribeBySlug);

};
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Audio file player with start, loop, stop.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string=} url if a url is passed in, it will be loaded
	 *                       and invoke the callback if it also passed
	 *                       in.
	 *  @param {function(Tone.Player)=} onload callback to be invoked
	 *                                     once the url is loaded
	 */
	Tone.Player = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  the duration of the buffer once it's been loaded
		 *  @type {number}
		 *  @readOnly
		 */
		this.duration = 0;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 */
		this.loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = 1;

		/**
		 *  enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing
		 *
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		//if there is a url, load it.
		if (!this.isUndef(options.url)){
			this.load(options.url, options.onload);
		}
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onended" : function(){},
		"loop" : false,
		"loopStart" : 0,
		"loopEnd" : -1,
		"retrigger" : false
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 * @param {string} url the url of the buffer to load.
	 *        filetype support depends on the
	 *        browser.
	 * @param  {function(Tone.Player)=} callback
	 */
	Tone.Player.prototype.load = function(url, callback){
		var self = this;
		if (!self._buffer){
			new Tone.Buffer({
				"url"  : url,
				"callback" :  function (buffer){
					self.setBuffer(buffer);
					if (callback){
						callback(self);
					}
				}
			});
		} else if (callback){
			callback(self);
		}
	};

	/**
	 *  set the buffer
	 *
	 *  @param {AudioBuffer} buffer the buffer which the player will play.
	 *                              note: if you switch the buffer after
	 *                              the player is already started, it will not
	 *                              take effect until the next time the player
	 *                              is started.
	 */
	Tone.Player.prototype.setBuffer = function(buffer){
		this._buffer = buffer;
		this.duration = buffer.duration;
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @param  {Tone.Time=} startTime
	 *  @param  {Tone.Time=} offset
	 *  @param  {Tone.Time=} duration
	 */
	Tone.Player.prototype.start = function(startTime, offset, duration){
		if (this.state === Tone.Source.State.STOPPED || this.retrigger){
			if (this._buffer){
				this.state = Tone.Source.State.STARTED;
				//if it's a loop the default offset is the loopstart point
				if (this.loop){
					offset = this.defaultArg(offset, this.loopStart);
				} else {
					//otherwise the default offset is 0
					offset = this.defaultArg(offset, 0);
				}
				duration = this.defaultArg(duration, this._buffer.duration - offset);
				//make the source
				this._source = this.context.createBufferSource();
				this._source.buffer = this._buffer;
				//set the looping properties
				if (this.loop){
					this._source.loop = this.loop;
					this._source.loopStart = this.toSeconds(this.loopStart);
					if (this.loopEnd !== -1){
						this._source.loopEnd = this.toSeconds(this.loopEnd);
					}
				}
				//and other properties
				this._source.playbackRate.value = this._playbackRate;
				this._source.onended = this._onended.bind(this);
				this.chain(this._source, this.output);
				//start it
				this._source.start(this.toSeconds(startTime), this.toSeconds(offset), this.toSeconds(duration));
			}
		}
	};

	/**
	 *  Stop playback.
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.Player.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				this.state = Tone.Source.State.STOPPED;
				this._source.stop(this.toSeconds(time));
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Player.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  set the rate at which the file plays
	 *
	 *  @param {number} rate
	 *  @param {Tone.Time=} rampTime (optional) the amount of time it takes to
	 *                               reach the rate
	 */
	Tone.Player.prototype.setPlaybackRate = function(rate, rampTime){
		this._playbackRate = rate;
		if (this._source) {
			if (rampTime){
				this._source.playbackRate.exponentialRampToValueAtTime(rate, this.toSeconds(rampTime));
			} else {
				this._source.playbackRate.value = rampTime;
			}
		}
	};

	/**
	 *  set the loop start position
	 *  @param {Tone.Time} loopStart the start time
	 */
	Tone.Player.prototype.setLoopStart = function(loopStart){
		this.loopStart = loopStart;
	};

	/**
	 *  set the loop end position
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopEnd = function(loopEnd){
		this.loopEnd = loopEnd;
	};

	/**
	 *  set the loop start and end
	 *  @param {Tone.Time} loopStart the loop end time
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.setLoopStart(loopStart);
		this.setLoopEnd(loopEnd);
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Player.prototype.set = function(params){
		if (!this.isUndef(params.playbackRate)) this.setPlaybackRate(params.playbackRate);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		if (!this.isUndef(params.loop)) this.loop = params.loop;
		if (!this.isUndef(params.loopStart)) this.setLoopStart(params.loopStart);
		if (!this.isUndef(params.loopEnd)) this.setLoopEnd(params.loopEnd);
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  dispose and disconnect
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	return Tone.Player;
});
<commit_msg>fixes buffer initialization in Player.js<commit_after>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Audio file player with start, loop, stop.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string=} url if a url is passed in, it will be loaded
	 *                       and invoke the callback if it also passed
	 *                       in.
	 *  @param {function(Tone.Player)=} onload callback to be invoked
	 *                                     once the url is loaded
	 */
	Tone.Player = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  the duration of the buffer once it's been loaded
		 *  @type {number}
		 *  @readOnly
		 */
		this.duration = 0;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 */
		this.loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *
		 *  @type {Tone.Time}
		 */
		this.loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = 1;

		/**
		 *  enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing
		 *
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		//if there is a url, load it.
		if (!this.isUndef(options.url)){
			this.load(options.url, options.onload);
		}
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onended" : function(){},
		"loop" : false,
		"loopStart" : 0,
		"loopEnd" : -1,
		"retrigger" : false
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 * @param {string} url the url of the buffer to load.
	 *        filetype support depends on the
	 *        browser.
	 * @param  {function(Tone.Player)=} callback
	 */
	Tone.Player.prototype.load = function(url, callback){
		var self = this;
		if (!self._buffer){
			new Tone.Buffer({
				"url"  : url,
				"callback" :  function (buffer){
					self.setBuffer(buffer);
					if (callback){
						callback(self);
					}
				}
			});
		} else if (callback){
			callback(self);
		}
	};

	/**
	 *  set the buffer
	 *
	 *  @param {AudioBuffer} buffer the buffer which the player will play.
	 *                              note: if you switch the buffer after
	 *                              the player is already started, it will not
	 *                              take effect until the next time the player
	 *                              is started.
	 */
	Tone.Player.prototype.setBuffer = function(buffer){
		this._buffer = buffer;
		this.duration = buffer.duration;
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @param  {Tone.Time=} startTime
	 *  @param  {Tone.Time=} offset
	 *  @param  {Tone.Time=} duration
	 */
	Tone.Player.prototype.start = function(startTime, offset, duration){
		if (this.state === Tone.Source.State.STOPPED || this.retrigger){
			if (this._buffer){
				this.state = Tone.Source.State.STARTED;
				//if it's a loop the default offset is the loopstart point
				if (this.loop){
					offset = this.defaultArg(offset, this.loopStart);
				} else {
					//otherwise the default offset is 0
					offset = this.defaultArg(offset, 0);
				}
				duration = this.defaultArg(duration, this._buffer.duration - offset);
				//make the source
				this._source = this.context.createBufferSource();
				this._source.buffer = this._buffer;
				//set the looping properties
				if (this.loop){
					this._source.loop = this.loop;
					this._source.loopStart = this.toSeconds(this.loopStart);
					if (this.loopEnd !== -1){
						this._source.loopEnd = this.toSeconds(this.loopEnd);
					}
				}
				//and other properties
				this._source.playbackRate.value = this._playbackRate;
				this._source.onended = this._onended.bind(this);
				this.chain(this._source, this.output);
				//start it
				this._source.start(this.toSeconds(startTime), this.toSeconds(offset), this.toSeconds(duration));
			}
		}
	};

	/**
	 *  Stop playback.
	 *
	 *  @param  {Tone.Time} time
	 */
	Tone.Player.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				this.state = Tone.Source.State.STOPPED;
				this._source.stop(this.toSeconds(time));
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Player.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  set the rate at which the file plays
	 *
	 *  @param {number} rate
	 *  @param {Tone.Time=} rampTime (optional) the amount of time it takes to
	 *                               reach the rate
	 */
	Tone.Player.prototype.setPlaybackRate = function(rate, rampTime){
		this._playbackRate = rate;
		if (this._source) {
			this._source.playbackRate.exponentialRampToValueAtTime(rate, this.toSeconds(rampTime));
		}
	};

	/**
	 *  set the loop start position
	 *  @param {Tone.Time} loopStart the start time
	 */
	Tone.Player.prototype.setLoopStart = function(loopStart){
		this.loopStart = loopStart;
	};

	/**
	 *  set the loop end position
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopEnd = function(loopEnd){
		this.loopEnd = loopEnd;
	};

	/**
	 *  set the loop start and end
	 *  @param {Tone.Time} loopStart the loop end time
	 *  @param {Tone.Time} loopEnd the loop end time
	 */
	Tone.Player.prototype.setLoopPoints = function(loopStart, loopEnd){
		this.setLoopStart(loopStart);
		this.setLoopEnd(loopEnd);
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Player.prototype.set = function(params){
		if (!this.isUndef(params.playbackRate)) this.setPlaybackRate(params.playbackRate);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		if (!this.isUndef(params.loop)) this.loop = params.loop;
		if (!this.isUndef(params.loopStart)) this.setLoopStart(params.loopStart);
		if (!this.isUndef(params.loopEnd)) this.setLoopEnd(params.loopEnd);
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  dispose and disconnect
	 */
	Tone.Player.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	return Tone.Player;
});
<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular
        .module('app')
        .directive('fileList', fileList);

    function fileList() {
        // Runs during compile
        return {
            restrict: 'EA', // E = Element, A = Attribute, C = Class, M = Comment
            templateUrl: 'files/FileList.html',
            controller: 'FileController',
            controllerAs: 'file',
        };
    }
})();<commit_msg>Remove unnecessary restrict<commit_after>(function() {
    'use strict';

    angular
        .module('app')
        .directive('fileList', fileList);

    function fileList() {
        // Runs during compile
        return {
            restrict: 'A',
            templateUrl: 'files/FileList.html',
            controller: 'FileController',
            controllerAs: 'file',
        };
    }
})();
<|endoftext|>