<commit_before>/*
 * Spreed Speak Freely.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed Speak Freely.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/audiovideopeer.html', 'bigscreen', 'injectCSS', 'webrtc.adapter', 'rAF'], function($, _, template, templatePeer, BigScreen) {

    return ["$window", "$compile", "$filter", "mediaStream", "safeApply", "desktopNotify", "buddyData", "videoWaiter", "videoLayout", function($window, $compile, $filter, mediaStream, safeApply, desktopNotify, buddyData, videoWaiter, videoLayout) {

        var requestAnimationFrame = $window.requestAnimationFrame;
        var peerTemplate = $compile(templatePeer);

        var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {

            var peers = {};
            var events = $({});

            $scope.card = $element;
            $scope.container = $element.parent().get(0);
            $scope.layoutparent = $element.parent().parent();

            $scope.remoteVideos = $element.find("#remoteVideos").get(0);
            $scope.localVideo = $element.find("#localVideo").get(0);
            $scope.miniVideo = $element.find("#miniVideo").get(0);
            $scope.mini = $element.find("#mini");

            $scope.hasUsermedia = false;
            $scope.isActive = false;
            //console.log("audiovideo", localVideo, miniVideo);

            $scope.addRemoteStream = function(stream, currentcall) {

                //console.log("Add remote stream to scope", pc.id, stream);
                var subscope = $scope.$new(true);
                var peerid = subscope.peerid = currentcall.id;
                buddyData.push(peerid);
                subscope.withvideo = false;
                subscope.onlyaudio = false;
                subscope.talking = false;
                subscope.applyTalking = function(talking) {
                    subscope.talking = !!talking;
                    safeApply(subscope);
                };
                subscope.$on("active", function() {
                    console.log("Stream scope is now active", peerid);
                    events.triggerHandler("active."+peerid, [subscope, currentcall, stream]);
                });
                console.log("Created stream scope", peerid);

                peerTemplate(subscope, function(clonedElement, scope) {
                    $($scope.remoteVideos).append(clonedElement);
                    clonedElement.data("peerid", scope.peerid);
                    scope.element = clonedElement;
                    var video = clonedElement.find("video").get(0);
                    $window.attachMediaStream(video, stream);
                    // Waiter callbacks also count as connected, as browser support (FireFox 25) is not setting state changes properly.
                    videoWaiter.wait(video, stream, function(withvideo) {
                        peers[peerid] = scope;
                        if (withvideo) {
                            scope.$apply(function($scope) {
                                $scope.withvideo = true;
                            });
                        } else {
                            console.info("Incoming stream has no video tracks.");
                            scope.$apply(function($scope) {
                                $scope.onlyaudio = true;
                            });
                        }
                        scope.$emit("active", currentcall);
                        $scope.redraw();
                    }, function() {
                        peers[peerid] = scope;
                        console.warn("We did not receive video data for remote stream", currentcall, stream, video);
                        scope.$emit("active", currentcall);
                        $scope.redraw();
                    });
                    scope.doChat = function() {
                        $scope.$emit("startchat", currentcall.id, {autofocus: true, restore: true});
                    };
                });

            };

            $scope.removeRemoteStream = function(stream, currentcall) {

                var subscope = peers[currentcall.id];
                if (subscope) {
                    buddyData.pop(currentcall.id);
                    delete peers[currentcall.id];
                    //console.log("remove scope", subscope);
                    if (subscope.element) {
                        subscope.element.remove();
                    }
                    subscope.$destroy();
                    $scope.redraw();
                }

            };

            // Talking updates receiver.
            mediaStream.api.e.on("received.talking", function(event, id, from, talking) {
                var scope = peers[from];
                //console.log("received.talking", talking, scope);
                if (scope) {
                    scope.applyTalking(talking);
                } else {
                    console.log("Received talking state without scope -> adding event.", from, talking);
                    events.one("active."+from, function(event, scope) {
                        console.log("Applying previously received talking state", from, talking);
                        scope.applyTalking(talking);
                    });
                }
            });

            $scope.$on("active", function(currentcall) {

                //console.log("active 2");
                if (!$scope.isActive) {
                    $scope.isActive = true;
                    $scope.remoteVideos.style.opacity = 1;
                    $scope.card.addClass("active");
                    //console.log("active 3");
                    _.delay(function() {
                        $scope.localVideo.style.opacity = 0;
                        $scope.localVideo.src = "";
                    }, 500);
                    _.delay(function() {
                        //console.log("active 4", $scope.mini);
                        $scope.mini.addClass("visible"); //.style.opacity = 1;
                    }, 1000);
                }

            });

            $scope.toggleFullscreen = function() {
                //console.log("Toggle full screen", BigScreen.enabled, $scope.isActive, $scope.hasUsermedia);
                if (BigScreen.enabled && ($scope.isActive || $scope.hasUsermedia)) {
                    $scope.layoutparent.toggleClass("fullscreen");
                    BigScreen.toggle($scope.layoutparent.get(0));
                }
            };

            mediaStream.webrtc.e.on("usermedia", function(event, usermedia) {

                //console.log("XXXXXXXXXXXXXXXXXXXXXXXXX usermedia event", usermedia);
                $scope.hasUsermedia = true;
                usermedia.attachMediaStream($scope.localVideo);
                var count = 0;
                var waitForLocalVideo = function() {
                    if (!$scope.hasUsermedia) {
                      return;
                    }
                    if ($scope.localVideo.videoWidth > 0) {
                        $scope.localVideo.style.opacity = 1;
                        $scope.redraw();
                    } else {
                        count++;
                        if (count < 100) {
                            setTimeout(waitForLocalVideo, 100);
                        } else {
                            console.warn("Timeout while waiting for local video.")
                        }
                    }
                };
                waitForLocalVideo();

            });

            mediaStream.webrtc.e.on("done", function() {

                $scope.hasUsermedia = false;
                $scope.isActive = false;
                if (BigScreen.enabled) {
                    BigScreen.exit();
                }
                _.delay(function() {
                    if ($scope.isActive) {
                        return;
                    }
                    $scope.localVideo.src = '';
                    $scope.miniVideo.src = '';
                    $($scope.remoteVideos).empty();
                }, 1500);
                $scope.mini.removeClass("visible");
                $scope.localVideo.style.opacity = 0;
                $scope.remoteVideos.style.opacity = 0;
                $scope.card.removeClass('active');
                _.each(peers, function(scope, k) {
                    scope.$destroy();
                    delete peers[k];
                });

            });

            mediaStream.webrtc.e.on("streamadded", function(event, stream, currentcall) {

                console.log("Remote stream added.", stream, currentcall);
                if (_.isEmpty(peers)) {
                    //console.log("First stream");
                    $window.reattachMediaStream($scope.miniVideo, $scope.localVideo);
                }
                $scope.addRemoteStream(stream, currentcall);

            });

            mediaStream.webrtc.e.on("streamremoved", function(event, stream, currentcall) {

                console.log("Remote stream removed.", stream, currentcall);
                $scope.removeRemoteStream(stream, currentcall);

            });

            return {
                peers: peers
            };

        }];

        var compile = function(tElement, tAttr) {

            return function(scope, iElement, iAttrs, controller) {

                //console.log("compile", arguments)

                $(scope.card).on("doubletap dblclick", _.debounce(scope.toggleFullscreen, 100, true));

                scope.rendererName = "onepeople";
                scope.renderersAvailable = videoLayout.layouts();

                var rendererName = null;
                var getRendererName = function() {
                    // Return name of current renderer.
                    if (rendererName !== null) {
                        return rendererName;
                    } else {
                        return scope.rendererName;
                    }
                };

                scope.setRenderer = function(name) {
                    scope.rendererName = name;
                };

                var needsRedraw = false;
                scope.redraw = function() {
                    needsRedraw = true;
                };

                var redraw = function() {
                    var size = {
                        width: scope.layoutparent.width(),
                        height: scope.layoutparent.height()
                    }
                    var again = videoLayout.update(getRendererName(), size, scope, controller);
                    if (again) {
                        // Layout needs a redraw.
                        needsRedraw = true;
                    }
                };

                // Make sure we draw on resize.
                $($window).on("resize", scope.redraw);
                scope.$on("mainresize", function(event, main) {
                    if (main) {
                        // Force smally renderer when we have a main view.
                        rendererName = "smally"
                    } else if (rendererName) {
                        rendererName = null;
                    }
                    _.defer(scope.redraw);
                });
                scope.redraw();

                // Make sure we draw when the renderer was changed.
                scope.$watch("rendererName", function() {
                    _.defer(scope.redraw);
                });

                // Update function run in rendering thread.
                var update = function() {
                    if (needsRedraw) {
                        needsRedraw =false;
                        redraw();
                    }
                    requestAnimationFrame(update);
                }
                _.defer(update);

            }

        };

        return {
            restrict: 'E',
            replace: true,
            scope: true,
            template: template,
            controller: controller,
            compile: compile
        }

    }];

});
<commit_msg>Make sure to reset renderer to default renderer when finished.<commit_after>/*
 * Spreed Speak Freely.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed Speak Freely.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/audiovideopeer.html', 'bigscreen', 'injectCSS', 'webrtc.adapter', 'rAF'], function($, _, template, templatePeer, BigScreen) {

    return ["$window", "$compile", "$filter", "mediaStream", "safeApply", "desktopNotify", "buddyData", "videoWaiter", "videoLayout", function($window, $compile, $filter, mediaStream, safeApply, desktopNotify, buddyData, videoWaiter, videoLayout) {

        var requestAnimationFrame = $window.requestAnimationFrame;
        var peerTemplate = $compile(templatePeer);

        var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {

            var peers = {};
            var events = $({});

            $scope.card = $element;
            $scope.container = $element.parent().get(0);
            $scope.layoutparent = $element.parent().parent();

            $scope.remoteVideos = $element.find("#remoteVideos").get(0);
            $scope.localVideo = $element.find("#localVideo").get(0);
            $scope.miniVideo = $element.find("#miniVideo").get(0);
            $scope.mini = $element.find("#mini");

            $scope.hasUsermedia = false;
            $scope.isActive = false;

            $scope.rendererName = $scope.defaultRendererName = "onepeople";

            //console.log("audiovideo", localVideo, miniVideo);

            $scope.addRemoteStream = function(stream, currentcall) {

                //console.log("Add remote stream to scope", pc.id, stream);
                var subscope = $scope.$new(true);
                var peerid = subscope.peerid = currentcall.id;
                buddyData.push(peerid);
                subscope.withvideo = false;
                subscope.onlyaudio = false;
                subscope.talking = false;
                subscope.applyTalking = function(talking) {
                    subscope.talking = !!talking;
                    safeApply(subscope);
                };
                subscope.$on("active", function() {
                    console.log("Stream scope is now active", peerid);
                    events.triggerHandler("active."+peerid, [subscope, currentcall, stream]);
                });
                console.log("Created stream scope", peerid);

                peerTemplate(subscope, function(clonedElement, scope) {
                    $($scope.remoteVideos).append(clonedElement);
                    clonedElement.data("peerid", scope.peerid);
                    scope.element = clonedElement;
                    var video = clonedElement.find("video").get(0);
                    $window.attachMediaStream(video, stream);
                    // Waiter callbacks also count as connected, as browser support (FireFox 25) is not setting state changes properly.
                    videoWaiter.wait(video, stream, function(withvideo) {
                        peers[peerid] = scope;
                        if (withvideo) {
                            scope.$apply(function($scope) {
                                $scope.withvideo = true;
                            });
                        } else {
                            console.info("Incoming stream has no video tracks.");
                            scope.$apply(function($scope) {
                                $scope.onlyaudio = true;
                            });
                        }
                        scope.$emit("active", currentcall);
                        $scope.redraw();
                    }, function() {
                        peers[peerid] = scope;
                        console.warn("We did not receive video data for remote stream", currentcall, stream, video);
                        scope.$emit("active", currentcall);
                        $scope.redraw();
                    });
                    scope.doChat = function() {
                        $scope.$emit("startchat", currentcall.id, {autofocus: true, restore: true});
                    };
                });

            };

            $scope.removeRemoteStream = function(stream, currentcall) {

                var subscope = peers[currentcall.id];
                if (subscope) {
                    buddyData.pop(currentcall.id);
                    delete peers[currentcall.id];
                    //console.log("remove scope", subscope);
                    if (subscope.element) {
                        subscope.element.remove();
                    }
                    subscope.$destroy();
                    $scope.redraw();
                }

            };

            // Talking updates receiver.
            mediaStream.api.e.on("received.talking", function(event, id, from, talking) {
                var scope = peers[from];
                //console.log("received.talking", talking, scope);
                if (scope) {
                    scope.applyTalking(talking);
                } else {
                    console.log("Received talking state without scope -> adding event.", from, talking);
                    events.one("active."+from, function(event, scope) {
                        console.log("Applying previously received talking state", from, talking);
                        scope.applyTalking(talking);
                    });
                }
            });

            $scope.$on("active", function(currentcall) {

                //console.log("active 2");
                if (!$scope.isActive) {
                    $scope.isActive = true;
                    $scope.remoteVideos.style.opacity = 1;
                    $scope.card.addClass("active");
                    //console.log("active 3");
                    _.delay(function() {
                        $scope.localVideo.style.opacity = 0;
                        $scope.localVideo.src = "";
                    }, 500);
                    _.delay(function() {
                        //console.log("active 4", $scope.mini);
                        $scope.mini.addClass("visible"); //.style.opacity = 1;
                    }, 1000);
                }

            });

            $scope.toggleFullscreen = function() {
                //console.log("Toggle full screen", BigScreen.enabled, $scope.isActive, $scope.hasUsermedia);
                if (BigScreen.enabled && ($scope.isActive || $scope.hasUsermedia)) {
                    $scope.layoutparent.toggleClass("fullscreen");
                    BigScreen.toggle($scope.layoutparent.get(0));
                }
            };

            mediaStream.webrtc.e.on("usermedia", function(event, usermedia) {

                //console.log("XXXXXXXXXXXXXXXXXXXXXXXXX usermedia event", usermedia);
                $scope.hasUsermedia = true;
                usermedia.attachMediaStream($scope.localVideo);
                var count = 0;
                var waitForLocalVideo = function() {
                    if (!$scope.hasUsermedia) {
                      return;
                    }
                    if ($scope.localVideo.videoWidth > 0) {
                        $scope.localVideo.style.opacity = 1;
                        $scope.redraw();
                    } else {
                        count++;
                        if (count < 100) {
                            setTimeout(waitForLocalVideo, 100);
                        } else {
                            console.warn("Timeout while waiting for local video.")
                        }
                    }
                };
                waitForLocalVideo();

            });

            mediaStream.webrtc.e.on("done", function() {

                $scope.hasUsermedia = false;
                $scope.isActive = false;
                if (BigScreen.enabled) {
                    BigScreen.exit();
                }
                _.delay(function() {
                    if ($scope.isActive) {
                        return;
                    }
                    $scope.localVideo.src = '';
                    $scope.miniVideo.src = '';
                    $($scope.remoteVideos).empty();
                }, 1500);
                $scope.mini.removeClass("visible");
                $scope.localVideo.style.opacity = 0;
                $scope.remoteVideos.style.opacity = 0;
                $scope.card.removeClass('active');
                _.each(peers, function(scope, k) {
                    scope.$destroy();
                    delete peers[k];
                });
                $scope.rendererName = $scope.defaultRendererName;

            });

            mediaStream.webrtc.e.on("streamadded", function(event, stream, currentcall) {

                console.log("Remote stream added.", stream, currentcall);
                if (_.isEmpty(peers)) {
                    //console.log("First stream");
                    $window.reattachMediaStream($scope.miniVideo, $scope.localVideo);
                }
                $scope.addRemoteStream(stream, currentcall);

            });

            mediaStream.webrtc.e.on("streamremoved", function(event, stream, currentcall) {

                console.log("Remote stream removed.", stream, currentcall);
                $scope.removeRemoteStream(stream, currentcall);

            });

            return {
                peers: peers
            };

        }];

        var compile = function(tElement, tAttr) {

            return function(scope, iElement, iAttrs, controller) {

                //console.log("compile", arguments)

                $(scope.card).on("doubletap dblclick", _.debounce(scope.toggleFullscreen, 100, true));

                var rendererName = null;
                var getRendererName = function() {
                    // Return name of current renderer.
                    if (rendererName !== null) {
                        return rendererName;
                    } else {
                        return scope.rendererName;
                    }
                };

                scope.setRenderer = function(name) {
                    scope.rendererName = name;
                };

                var needsRedraw = false;
                scope.redraw = function() {
                    needsRedraw = true;
                };

                var redraw = function() {
                    var size = {
                        width: scope.layoutparent.width(),
                        height: scope.layoutparent.height()
                    }
                    var again = videoLayout.update(getRendererName(), size, scope, controller);
                    if (again) {
                        // Layout needs a redraw.
                        needsRedraw = true;
                    }
                };

                // Make sure we draw on resize.
                $($window).on("resize", scope.redraw);
                scope.$on("mainresize", function(event, main) {
                    if (main) {
                        // Force smally renderer when we have a main view.
                        rendererName = "smally"
                    } else if (rendererName) {
                        rendererName = null;
                    }
                    _.defer(scope.redraw);
                });
                scope.redraw();

                // Make sure we draw when the renderer was changed.
                scope.$watch("rendererName", function() {
                    _.defer(scope.redraw);
                });

                // Update function run in rendering thread.
                var update = function() {
                    if (needsRedraw) {
                        needsRedraw =false;
                        redraw();
                    }
                    requestAnimationFrame(update);
                }
                _.defer(update);

            }

        };

        return {
            restrict: 'E',
            replace: true,
            scope: true,
            template: template,
            controller: controller,
            compile: compile
        }

    }];

});
<|endoftext|>


<commit_before>/*global jQuery, window, document, console, google, MarkerClusterer */
var Codeweek = window.Codeweek || {};

(function ($, Codeweek) {

	'use strict';

	var init = function (url) {

		$(function () {

			$.endlessPaginate({
				paginateOnScroll: false,
			});

			$('.search-form-element').on('change', function (e) {
				var container = $('#events-container');
				var search_counter_container = $('#search-counter-container');
				var data = $('#faceted-search-events').serialize();
				var url = $('#faceted-search-events').attr('action');

				if (is_modern_browser()) {
					$.get(url, data, function(fragment) {
						history.replaceState({}, document.title, '?' + data);
						container.empty();
						container.html(fragment);
						var no_results = $('body').data('all_results');
						var result_string = '';

						if (no_results > 0 ) {
							result_string = (no_results > 1 ? ' events match ' : ' event matches ');
							search_counter_container.html(no_results + result_string + 'your search criteria: ');
							search_counter_container.show();
						} else {
							search_counter_container.hide();
						}

					});
				} else {
					document.getElementById('faceted-search-events').submit();
				}

			});
		});
	};

	function is_modern_browser() {

		var ie_version = msieversion();

		if('querySelector' in document
		     && 'localStorage' in window
		     && 'addEventListener' in window
		     && ( ie_version==0 || ie_version > 9)) {
		     // bootstrap the javascript application
		 	return true;
		}

		return false;
	}

	function msieversion() {

		var ua = window.navigator.userAgent;
		var msie = ua.indexOf("MSIE ");

		if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer, return version number
			return parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)));
		return 0;
	}

	Codeweek.FacetedSearch = {};
	Codeweek.FacetedSearch.init = init;

}(jQuery, Codeweek));
<commit_msg>Modernized search<commit_after>/*global jQuery, window, document, console, google, MarkerClusterer */
var Codeweek = window.Codeweek || {};

(function ($, Codeweek) {

	'use strict';

	var init = function (url) {

		$(function () {

			$.endlessPaginate({
				paginateOnScroll: false,
			});

			$('.search-form-element').on('change', function (e) {
				var container = $('#events-container');
				var search_counter_container = $('#search-counter-container');
				var data = $('#faceted-search-events').serialize();
				var url = $('#faceted-search-events').attr('action');

				if (!Modernizr.history) {
					document.getElementById('faceted-search-events').submit();
				} else {
					$.get(url, data, function(fragment) {
						history.replaceState({}, document.title, '?' + data);
						container.empty();
						container.html(fragment);
						var no_results = $('body').data('all_results');
						var result_string = '';

						if (no_results > 0 ) {
							result_string = (no_results > 1 ? ' events match ' : ' event matches ');
							search_counter_container.html(no_results + result_string + 'your search criteria: ');
							search_counter_container.show();
						} else {
							search_counter_container.hide();
						}
					});

				}
			});
		});
	};

	function is_modern_browser() {

		var ie_version = msieversion();

		if('querySelector' in document
		     && 'localStorage' in window
		     && 'addEventListener' in window
		     && ( ie_version==0 || ie_version > 9)) {
		     // bootstrap the javascript application
		 	return true;
		}

		return false;
	}

	function msieversion() {

		var ua = window.navigator.userAgent;
		var msie = ua.indexOf("MSIE ");

		if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer, return version number
			return parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)));
		return 0;
	}

	Codeweek.FacetedSearch = {};
	Codeweek.FacetedSearch.init = init;

}(jQuery, Codeweek));
<|endoftext|>


<commit_before>import L from 'leaflet'
import 'leaflet-rotatedmarker'

// LeafletWidget

export class LeafletWidget {

    constructor(options) {

        this.options = {
            url: 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=',
            options: {
                attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
                maxZoom: 18,
                id: 'mapbox.streets'
            },

            lat: 32.53530431898372,
            lng: -116.9165934003241,
            zoom: 15,
            location_icon_url: '/static/icons/pin/blue.svg',
            location_icon_size: [32, 32],
            add_marker_control: false,
        };

        // Altering using user-provided options
        for (const property in options) {
            if (options.hasOwnProperty(property)) {
                this.options[property] = options[property];
            }
        }

        // create map
        this.map = L.map(this.options.map_id).setView(L.latLng(this.options.lat,
            this.options.lng),
            this.options.zoom);
        // add reference to parent object
        this.map.parent = this;

        // create title layer
        L.tileLayer(this.options.url + this.options.access_token,
            this.options.options).addTo(this.map);

        // add location controls
        const locateControl = L.Control.extend({

            options: {
                position: 'topleft'
            },

            onAdd: function (map) {

                const container = L.DomUtil.create('div',
                    'leaflet-bar leaflet-control leaflet-control-custom');

                container.style.width = '32px';
                container.style.height = '32px';
                container.style.backgroundImage = "url('/static/icons/mouse-pointer.svg')";
                container.style.backgroundPosition = 'center';
                container.style.backgroundSize = '20px 20px';
                container.style.backgroundColor = 'white';
                container.style.backgroundRepeat = 'no-repeat';

                /* tooltip */
                container.title = 'Go to your location';

                L.DomEvent
                    .addListener(container, 'click', L.DomEvent.stopPropagation)
                    .addListener(container, 'click', L.DomEvent.preventDefault)
                    .addListener(container, 'click', function () {
                        map.locate({setView: true, maxZoom: 14});
                    });

                return container;
            },

        });

        this.map.addControl(new locateControl());

        this.map.on('locationerror', function (e) {
            alert('Could not find location
 ' + e.message);
        });

        // location marker
        const location_icon = L.icon({
            iconUrl: this.options.location_icon_url,
            iconSize: this.options.location_icon_size,
        });

        // locate
        this.map.on('locationfound', function (e) {
            const parent = e.target.parent;
            if (typeof parent.current_location === 'undefined') {
                // create marker
                parent.current_location =
                    L.marker(parent.map.getCenter(),
                        {icon: location_icon}).addTo(parent.map);
            } else {
                // move marker
                parent.current_location.setLatLng(e.latlng);
            }
        });
    }

    fitBounds(bounds) {

        // Get bounds if not given
        bounds = bounds || this.map.getBounds();
        console.log('bounds = ' + bounds);

        // Fit map to bounds
        this.map.fitBounds(bounds);

    }

    center(position, zoom) {

        // Get zoom from map if not given
        zoom = zoom || this.map.getZoom();

        // center map
        this.map.setView([position.latitude, position.longitude], zoom);

    }

}

// LeafletMultiPointWidget

export class LeafletMultiPointWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options)

        // store all marker id's
        this.markerIdMap = {};
        this.pointIdMap = {};

        // create layer
        this.markers = L.layerGroup();

        this.options.add_marker_control = true;
        if (this.options.add_marker_control) {

            this.clickToAddPoint = false;

            // add add marker control
            const addMarkerControl = L.Control.extend({

                options: {
                    position: 'topleft'
                },

                onAdd: function (map) {
                    const container = L.DomUtil.create('div',
                        'leaflet-bar leaflet-control leaflet-control-custom leaflet-add-marker leaflet-tooltip');

                    const tooltip = L.DomUtil.create('span',
                        'leaflet-tooltiptext',
                        container);
                    tooltip.textContent = 'Add AED';

                    map.parent.addControlCheckbox =
                        L.DomUtil.create('input',
                            'leaflet-add-marker-input',
                            container);
                    map.parent.addControlCheckbox.type = 'checkbox';
                    map.parent.addControlCheckbox.id = 'leaflet-add-marker-id';
                    map.parent.addControlCheckbox.map = this;

                    const label = L.DomUtil.create('label',
                        '',
                        container);
                    label.htmlFor = 'leaflet-add-marker-id';

                    L.DomEvent
                        .addListener(map.parent.addControlCheckbox,
                            'click', L.DomEvent.stopPropagation)
                        .addListener(map.parent.addControlCheckbox,
                            'click',
                            function (e) {
                                if (e.target.checked) {
                                    // enable click to add point
                                    e.target.map._map.parent.clickToAddPoint = true;
                                } else {
                                    // disable click to add point
                                    e.target.map._map.parent.clickToAddPoint = false;
                                }
                            });

                    return container;
                },

            });

            this.map.addControl(new addMarkerControl());

            // listen to click
            this.map.on('click', function (e) {
                const map = e.target.parent;
                if (map.clickToAddPoint) {
                    // add marker?
                    map.addPoint(e.latlng.lat, e.latlng.lng,
                        -1, map.options.newPointFunction);
                    // disable add marker mode
                    map.addControlCheckbox.click();
                }

            });
        }
    }

    // MEMBER FUNCTIONS

    // add point
    addPoint(lat, lng, id, fun) {

        // add marker
        const marker = L.marker([lat, lng])
            .addTo(this.map);

        if (fun) {
            marker.on('click', fun);
        }

        L.stamp(marker);
        this.markers.addLayer(marker);

        if (id >= 0) {
            this.markerIdMap[marker._leaflet_id] = id;
            this.pointIdMap[id] = marker._leaflet_id;
        }

        // TODO: Disable add marker mode

        return marker;
    }

}

// LeafletPointWidget

export class LeafletPointWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options);

        if (!this.options.point) {
            this.options.point = [options.lat, options.lng];
        }

        // add marker
        this.point = L.marker(L.latLng(this.options.point[0], this.options.point[1]),
            {draggable: true});
        this.point.addTo(this.map);

        // add reference to parent object
        this.point.parent = this;

        // call set point to update fields
        this.setPoint(L.latLng(this.options.point[0], this.options.point[1]));

        // set coordinates when dragged
        this.point.on('dragend', function (e) {
            e.target.parent.setPoint(e.target.getLatLng());
        });

        // set coordinates when map is click
        this.map.on('click',
            function (e) {
                e.target.parent.setPoint(e.latlng);
            });

    }

    // MEMBER FUNCTIONS

    // update point
    setPoint(p) {

        // set point coordinates
        this.point.setLatLng(p);

        // update fields
        if (this.options.id) {
            document.getElementById(this.options.id).value =
                'POINT(' + p.lng + ' ' + p.lat + ')';
        }
        if (this.options.id_lat) {
            document.getElementById(this.options.id_lat).value = p.lat;
        }
        if (this.options.id_lng) {
            document.getElementById(this.options.id_lng).value = p.lng;
        }
    }

}

// Polyline Widget

export class LeafletPolylineWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options);

        // store all markers and lines id's
        this.polylineIdMap = {}
        this.markerIdMap = {};
        this.pointIdMap = {};

        // create layers
        this.layers = {};

        // create default layer
        this.createLayer('default');

        //this.map.createPane('defaultLeafletPolylineWidgetPane');
        //this.layers['default'] = {
        //        'markers': L.layerGroup({'pane': 'defaultLeafletPolylineWidget'}),
        //        'lines': L.layerGroup({'pane': 'defaultLeafletPolylineWidget'})
        //    };

    }

    createLayer(layer) {

        var layerName = layer + 'LeafletPolylineWidgetPane';
        this.map.createPane(layerName);
        this.layers[layer] = {
            'markers': L.layerGroup({'pane': layerName}),
            'lines': L.layerGroup({'pane': layerName})
        };

    }

    getLayerPane(layer) {

        var layerName = layer + 'LeafletPolylineWidgetPane';
        return this.map.getPane(layerName);

    }

    addLine(points, id, color, fun, layer) {

        fun = fun || null;
        layer = layer || 'default';

        // Create polyline
        var layerName = layer + 'LeafletPolylineWidgetPane';
        var polyline = L.polyline(points, {color: color, pane: layerName})
            .addTo(this.map);

        // Add click callback
        if (fun) {
            polyline.on('click', fun);
        }

        // Add marker
        L.stamp(polyline);
        this.layers[layer]['lines'].addLayer(polyline);

        // Track ids
        if (id >= 0) {
            this.polylineIdMap[polyline._leaflet_id] = id;
        }

        return polyline;
    }

    // add point
    addPoint(lat, lng, id, fun, layer) {

        fun = fun || null;
        layer = layer || 'default';

        // Create marker without a shaddow
        var icon = new L.Icon.Default();
        icon.options.shadowSize = [0, 0];
        var layerName = layer + 'LeafletPolylineWidgetPane';
        var marker = L.marker([lat, lng], {icon: icon, pane: layerName})
            .addTo(this.map);

        // Add click callback
        if (fun) {
            marker.on('click', fun);
        }

        // Add marker
        L.stamp(marker);
        this.layers[layer]['markers'].addLayer(marker);

        // Track ids
        if (id >= 0) {
            this.markerIdMap[marker._leaflet_id] = id;
            this.pointIdMap[id] = marker._leaflet_id;
        }

        return marker;
    }

}

<commit_msg>Bundling ambulance detail frontend.<commit_after>import L from 'leaflet'
import 'leaflet-rotatedmarker'
import "leaflet/dist/leaflet.css";

// LeafletWidget

export class LeafletWidget {

    constructor(options) {

        this.options = {
            url: 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=',
            options: {
                attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
                maxZoom: 18,
                id: 'mapbox.streets'
            },

            lat: 32.53530431898372,
            lng: -116.9165934003241,
            zoom: 15,
            location_icon_url: '/static/icons/pin/blue.svg',
            location_icon_size: [32, 32],
            add_marker_control: false,
        };

        // Altering using user-provided options
        for (const property in options) {
            if (options.hasOwnProperty(property)) {
                this.options[property] = options[property];
            }
        }

        // create map
        this.map = L.map(this.options.map_id).setView(L.latLng(this.options.lat,
            this.options.lng),
            this.options.zoom);
        // add reference to parent object
        this.map.parent = this;

        // create title layer
        L.tileLayer(this.options.url + this.options.access_token,
            this.options.options).addTo(this.map);

        // add location controls
        const locateControl = L.Control.extend({

            options: {
                position: 'topleft'
            },

            onAdd: function (map) {

                const container = L.DomUtil.create('div',
                    'leaflet-bar leaflet-control leaflet-control-custom');

                container.style.width = '32px';
                container.style.height = '32px';
                container.style.backgroundImage = "url('/static/icons/mouse-pointer.svg')";
                container.style.backgroundPosition = 'center';
                container.style.backgroundSize = '20px 20px';
                container.style.backgroundColor = 'white';
                container.style.backgroundRepeat = 'no-repeat';

                /* tooltip */
                container.title = 'Go to your location';

                L.DomEvent
                    .addListener(container, 'click', L.DomEvent.stopPropagation)
                    .addListener(container, 'click', L.DomEvent.preventDefault)
                    .addListener(container, 'click', function () {
                        map.locate({setView: true, maxZoom: 14});
                    });

                return container;
            },

        });

        this.map.addControl(new locateControl());

        this.map.on('locationerror', function (e) {
            alert('Could not find location
 ' + e.message);
        });

        // location marker
        const location_icon = L.icon({
            iconUrl: this.options.location_icon_url,
            iconSize: this.options.location_icon_size,
        });

        // locate
        this.map.on('locationfound', function (e) {
            const parent = e.target.parent;
            if (typeof parent.current_location === 'undefined') {
                // create marker
                parent.current_location =
                    L.marker(parent.map.getCenter(),
                        {icon: location_icon}).addTo(parent.map);
            } else {
                // move marker
                parent.current_location.setLatLng(e.latlng);
            }
        });
    }

    fitBounds(bounds) {

        // Get bounds if not given
        bounds = bounds || this.map.getBounds();
        console.log('bounds = ' + bounds);

        // Fit map to bounds
        this.map.fitBounds(bounds);

    }

    center(position, zoom) {

        // Get zoom from map if not given
        zoom = zoom || this.map.getZoom();

        // center map
        this.map.setView([position.latitude, position.longitude], zoom);

    }

}

// LeafletMultiPointWidget

export class LeafletMultiPointWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options)

        // store all marker id's
        this.markerIdMap = {};
        this.pointIdMap = {};

        // create layer
        this.markers = L.layerGroup();

        this.options.add_marker_control = true;
        if (this.options.add_marker_control) {

            this.clickToAddPoint = false;

            // add add marker control
            const addMarkerControl = L.Control.extend({

                options: {
                    position: 'topleft'
                },

                onAdd: function (map) {
                    const container = L.DomUtil.create('div',
                        'leaflet-bar leaflet-control leaflet-control-custom leaflet-add-marker leaflet-tooltip');

                    const tooltip = L.DomUtil.create('span',
                        'leaflet-tooltiptext',
                        container);
                    tooltip.textContent = 'Add AED';

                    map.parent.addControlCheckbox =
                        L.DomUtil.create('input',
                            'leaflet-add-marker-input',
                            container);
                    map.parent.addControlCheckbox.type = 'checkbox';
                    map.parent.addControlCheckbox.id = 'leaflet-add-marker-id';
                    map.parent.addControlCheckbox.map = this;

                    const label = L.DomUtil.create('label',
                        '',
                        container);
                    label.htmlFor = 'leaflet-add-marker-id';

                    L.DomEvent
                        .addListener(map.parent.addControlCheckbox,
                            'click', L.DomEvent.stopPropagation)
                        .addListener(map.parent.addControlCheckbox,
                            'click',
                            function (e) {
                                if (e.target.checked) {
                                    // enable click to add point
                                    e.target.map._map.parent.clickToAddPoint = true;
                                } else {
                                    // disable click to add point
                                    e.target.map._map.parent.clickToAddPoint = false;
                                }
                            });

                    return container;
                },

            });

            this.map.addControl(new addMarkerControl());

            // listen to click
            this.map.on('click', function (e) {
                const map = e.target.parent;
                if (map.clickToAddPoint) {
                    // add marker?
                    map.addPoint(e.latlng.lat, e.latlng.lng,
                        -1, map.options.newPointFunction);
                    // disable add marker mode
                    map.addControlCheckbox.click();
                }

            });
        }
    }

    // MEMBER FUNCTIONS

    // add point
    addPoint(lat, lng, id, fun) {

        // add marker
        const marker = L.marker([lat, lng])
            .addTo(this.map);

        if (fun) {
            marker.on('click', fun);
        }

        L.stamp(marker);
        this.markers.addLayer(marker);

        if (id >= 0) {
            this.markerIdMap[marker._leaflet_id] = id;
            this.pointIdMap[id] = marker._leaflet_id;
        }

        // TODO: Disable add marker mode

        return marker;
    }

}

// LeafletPointWidget

export class LeafletPointWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options);

        if (!this.options.point) {
            this.options.point = [options.lat, options.lng];
        }

        // add marker
        this.point = L.marker(L.latLng(this.options.point[0], this.options.point[1]),
            {draggable: true});
        this.point.addTo(this.map);

        // add reference to parent object
        this.point.parent = this;

        // call set point to update fields
        this.setPoint(L.latLng(this.options.point[0], this.options.point[1]));

        // set coordinates when dragged
        this.point.on('dragend', function (e) {
            e.target.parent.setPoint(e.target.getLatLng());
        });

        // set coordinates when map is click
        this.map.on('click',
            function (e) {
                e.target.parent.setPoint(e.latlng);
            });

    }

    // MEMBER FUNCTIONS

    // update point
    setPoint(p) {

        // set point coordinates
        this.point.setLatLng(p);

        // update fields
        if (this.options.id) {
            document.getElementById(this.options.id).value =
                'POINT(' + p.lng + ' ' + p.lat + ')';
        }
        if (this.options.id_lat) {
            document.getElementById(this.options.id_lat).value = p.lat;
        }
        if (this.options.id_lng) {
            document.getElementById(this.options.id_lng).value = p.lng;
        }
    }

}

// Polyline Widget

export class LeafletPolylineWidget extends LeafletWidget {

    constructor(options) {

        // Call parent
        super(options);

        // store all markers and lines id's
        this.polylineIdMap = {}
        this.markerIdMap = {};
        this.pointIdMap = {};

        // create layers
        this.layers = {};

        // create default layer
        this.createLayer('default');

        //this.map.createPane('defaultLeafletPolylineWidgetPane');
        //this.layers['default'] = {
        //        'markers': L.layerGroup({'pane': 'defaultLeafletPolylineWidget'}),
        //        'lines': L.layerGroup({'pane': 'defaultLeafletPolylineWidget'})
        //    };

    }

    createLayer(layer) {

        var layerName = layer + 'LeafletPolylineWidgetPane';
        this.map.createPane(layerName);
        this.layers[layer] = {
            'markers': L.layerGroup({'pane': layerName}),
            'lines': L.layerGroup({'pane': layerName})
        };

    }

    getLayerPane(layer) {

        var layerName = layer + 'LeafletPolylineWidgetPane';
        return this.map.getPane(layerName);

    }

    addLine(points, id, color, fun, layer) {

        fun = fun || null;
        layer = layer || 'default';

        // Create polyline
        var layerName = layer + 'LeafletPolylineWidgetPane';
        var polyline = L.polyline(points, {color: color, pane: layerName})
            .addTo(this.map);

        // Add click callback
        if (fun) {
            polyline.on('click', fun);
        }

        // Add marker
        L.stamp(polyline);
        this.layers[layer]['lines'].addLayer(polyline);

        // Track ids
        if (id >= 0) {
            this.polylineIdMap[polyline._leaflet_id] = id;
        }

        return polyline;
    }

    // add point
    addPoint(lat, lng, id, fun, layer) {

        fun = fun || null;
        layer = layer || 'default';

        // Create marker without a shaddow
        var icon = new L.Icon.Default();
        icon.options.shadowSize = [0, 0];
        var layerName = layer + 'LeafletPolylineWidgetPane';
        var marker = L.marker([lat, lng], {icon: icon, pane: layerName})
            .addTo(this.map);

        // Add click callback
        if (fun) {
            marker.on('click', fun);
        }

        // Add marker
        L.stamp(marker);
        this.layers[layer]['markers'].addLayer(marker);

        // Track ids
        if (id >= 0) {
            this.markerIdMap[marker._leaflet_id] = id;
            this.pointIdMap[id] = marker._leaflet_id;
        }

        return marker;
    }

}

<|endoftext|>


<commit_before>/*
 * (c) Copyright 2014 LinkedIn Corp. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var Location = Backbone.Model.extend({

    COOKIE: 'location',

    defaults: {
        location: {
            name: '',
            id: '',
            timezoneOffset: 0
        }
    },

    initialize: function () {
        _.bindAll(this, 'init', 'onChange', 'setById', 'getById', 'getTimezoneOffsetById', 'getDayForLocation', 'adjustTime', 'getCurrentTimeForLocation', 'getCurrentSiteId');
        this.get('filterValues').bind('change:location', this.onChange);
        this.init();
    },

    init: function () {
        this.setById($.cookie(this.COOKIE));
    },

    comparator: function (value) {
        return function (i) {
            return i.id === value;
        };
    },

    setById: function (siteId) {
        var exists = _.any(this.get('config'), this.comparator(siteId));
        var id = exists ? siteId : this.get('defaultLocationId');
        this.get('filterValues').set('location', id);
    },

    getById: function (siteId) {
        var location = _.find(this.get('config'), this.comparator(siteId));
        return _.isUndefined(location) ? this.get('config')[0] : location;
    },

    getCurrentSiteId: function () {
        return this.get('filterValues').get('location');
    },

    getTimezoneOffsetById: function (siteId) {
        return parseInt(this.getById(siteId).timezoneOffset);
    },

    getDayForLocation: function () {
        var day = this.get('filterValues').get('day');
        return this.adjustTime(day, true);
    },

    getCurrentTimeForLocation: function () {
        return this.adjustTime(new Date().getTime(), false);
    },

    adjustTime: function (time, backward) {
        var siteId = this.get('filterValues').get('location');
        var locationOffset = this.getTimezoneOffsetById(siteId);
        var timezoneCorrection = (locationOffset + new Date().getTimezoneOffset()) * 60 * 1000;
        return time + (backward ? -timezoneCorrection : timezoneCorrection);
    },

    onChange: function () {
        var siteId = this.get('filterValues').get('location');

        $.cookie(this.COOKIE, siteId, {
            expires: new Date('January 1, 2061'),
            path: '/'
        });
    }
});<commit_msg>Timezones logic updated to always display the same timeframe (in the browser timezone) whenever you switch the location.<commit_after>/*
 * (c) Copyright 2014 LinkedIn Corp. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var Location = Backbone.Model.extend({

    COOKIE: 'location',

    defaults: {
        location: {
            name: '',
            id: '',
            timezoneOffset: 0
        }
    },

    initialize: function () {
        _.bindAll(this, 'init', 'onChange', 'setById', 'getById', 'getTimezoneOffsetById', 'getDayForLocation', 'adjustTime', 'getCurrentTimeForLocation', 'getCurrentSiteId');
        this.get('filterValues').bind('change:location', this.onChange);
        this.init();
    },

    init: function () {
        this.setById($.cookie(this.COOKIE));
    },

    comparator: function (value) {
        return function (i) {
            return i.id === value;
        };
    },

    setById: function (siteId) {
        var exists = _.any(this.get('config'), this.comparator(siteId));
        var id = exists ? siteId : this.get('defaultLocationId');
        this.get('filterValues').set('location', id);
    },

    getById: function (siteId) {
        var location = _.find(this.get('config'), this.comparator(siteId));
        return _.isUndefined(location) ? this.get('config')[0] : location;
    },

    getCurrentSiteId: function () {
        return this.get('filterValues').get('location');
    },

    getTimezoneOffsetById: function (siteId) {
        return parseInt(this.getById(siteId).timezoneOffset);
    },

    getDayForLocation: function () {
        var day = this.get('filterValues').get('day');
        return this.adjustTime(day, true);
    },

    getCurrentTimeForLocation: function () {
        return this.adjustTime(new Date().getTime(), false);
    },

    adjustTime: function (time, backward) {
        // As per new logic we are not doing any time adjustments:
        // if you switch the location we are still gonna keep the same time
        // frame in the timezone of your browser.
        return time;
    },

    onChange: function () {
        var siteId = this.get('filterValues').get('location');

        $.cookie(this.COOKIE, siteId, {
            expires: new Date('January 1, 2061'),
            path: '/'
        });
    }
});<|endoftext|>


<commit_before>var vows = require('vows');
var assert = require('assert');
var suite = vows.describe('jStat.distribution');

require('../env.js');

suite.addBatch({
  'beta pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      // Non-log form of the Beta pdf
      function pdf(x, alpha, beta) {
        if (x > 1 || x < 0)
          return 0;
        return (Math.pow(x, alpha - 1) * Math.pow(1 - x, beta - 1)) /
            jStat.betafn(alpha, beta);
      }

      var tol = 0.0000001;
      var args = [0, 0.1, 0.3, 0.5, 0.7, 0.9, 1];
      var arg;

      for (var i = 0; i < args.length; i++) {
        arg = args[i];
        assert.epsilon(tol, jStat.beta.pdf(arg, 0.1, 0.1), pdf(arg, 0.1, 0.1));
        assert.epsilon(tol, jStat.beta.pdf(arg, 1, 1), pdf(arg, 1, 1));
        assert.epsilon(tol, jStat.beta.pdf(arg, 10, 50), pdf(arg, 10, 50));

        // Show that the log form of the pdf performs better for
        // large parameter values.
        assert(!isNaN(jStat.beta.pdf(arg, 1000, 5000)),
               'New Beta pdf is NaN for large parameter values.');
        assert(isNaN(pdf(arg, 1000, 5000)),
               'Old Beta pdf is not NaN for large parameter values.');
      }

      assert.equal(jStat.beta.pdf(0, 1, 4), 4);
      assert.equal(jStat.beta.pdf(1, 4, 1), 4);
    }
  },

  'gamma pdf': {
    'topic': function() {
      return jStat;
    },
    'check instance and static pdf method': function (jStat) {
      var shape = 5;
      var scale = 1;
      var gamma = jStat.gamma(shape, scale);
      var xValues = [-1, 0, 1];
      var x;
      for (var i = 0; i < xValues.length; i++) {
        x = xValues[i];
        pStatic = jStat.gamma.pdf(x, shape, scale);
        pInstance = gamma.pdf(x);
        if (isNaN(pStatic)) {
          assert(isNaN(pInstance));
        } else {
          assert(pStatic === pInstance,
                 'Gamma pdf evaluated at ' +
                   x + ' should be equal for instance and static methods.');
        }
      }
    }
  },

  'binomial pdf': {
    'topic': function() {
      return jStat;
    },
    //checked against R's dbinom(k, n, p)
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.pdf(10, 25, 0.5), 0.09741664);
      assert.epsilon(tol, jStat.binomial.pdf(50, 1000, 0.05), 0.05778798);
    },
    //Checked against r's pbinom(k, n, p)
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.cdf(10, 25, 0.5), 0.2121781);
      assert.epsilon(tol, jStat.binomial.cdf(50, 1000, 0.05), 0.537529);
    }
  },

  'binomial pdf': {
    'topic': function() {
      return jStat;
    },
    //checked against R's dbinom(k, n, p)
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.pdf(10, 25, 0.5), 0.09741664);
      assert.epsilon(tol, jStat.binomial.pdf(50, 1000, 0.05), 0.05778798);
    },
    //Checked against r's pbinom(k, n, p)
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.cdf(10, 25, 0.5), 0.2121781);
      assert.epsilon(tol, jStat.binomial.cdf(50, 1000, 0.05), 0.537529);
    }
  },

  'studentt pdf': {
    'topic': function() {
      return jStat;
    },
    //Checked against R dt(x,df)
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      var x = 0.5;
      var df = 40;
      assert.epsilon(tol, jStat.studentt.pdf(x, df), 0.3489195);
    },
    //Checked against R's pt(x, df)
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      var x = 0.5;
      var df = 40;
      assert.epsilon(tol, jStat.studentt.cdf(x, df), 0.6900926);
    },
    //Checked against R's qt(x, df)
    'check inv calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.studentt.inv(0.5, 40), 0);
      assert.epsilon(tol, jStat.studentt.inv(0.7, 20), 0.5328628);
      assert.epsilon(tol, jStat.studentt.inv(0.2, 10), -0.8790578);
    }
  },
});

suite.addBatch({
  'negbin pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var k = 10; // number of failures
      var r = 5; // threshold number of successes
      var p = 0.25; // probability of a success
      assert(jStat.negbin.pdf(k, r, p), 0.05504866037517786);
    }
  },

  'negbin cdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var k = 10; // number of failures
      var r = 5; // threshold number of successes
      var p = 0.25; // probability of a success
      assert(jStat.negbin.cdf(k, r, p), 0.3135140584781766);
    }
  },
});

suite.addBatch({
  'hypergeometric pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [10, 16];
      // How big was the source population?
      var population = [100, 3589];
      // How many 1s were in it?
      var available = [20, 16];
      // How big a sample was taken?
      var draws = [15, 2290];
      // What was the probability of exactly this many 1s?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [0.000017532028090435493, 0.0007404996809672229];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.
        var calculated = jStat.hypgeom.pdf(successes[i],
                                           population[i],
                                           available[i],
                                           draws[i]);
        // None of the answers should be NaN
        assert(!isNaN(calculated));
        // And they should all match
        assert.epsilon(tol, calculated, answers[i]);
      }
    }
  }
});

suite.addBatch({
  'hypergeometric pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf agreement': function(jStat) {
      var tol = 0.0000001;

      // Define an easy pdf
      var easyPDF = function pdf(k, N, m, n) {
        if (k !== (k | 0))
          return false;
        if (k < 0)
          return 0;
        return jStat.combination(m, k) * jStat.combination(N - m , n - k) /
            jStat.combination(N, n);
      }

      // Now test the easy PDF agaisnt the real one.
      for (var N = 0; N < 10; N++) {
        // For several population sizes
        for (var m = 0; m < N; m++) {
          // For all possible success counts
          for (var n = 0; n < N; n++) {
            // For all possible sample sizes
            for (var x = 0; x < n; x++) {
              // For all subset sizes of the sampled set

              // Get the probability be each method
              var probEasy = easyPDF(x, N, m, n);

              if (!isNaN(probEasy)) {
                // The easy PDF worked for this situation. Compare it to the
                // real one.

                var probReal = jStat.hypgeom.pdf(x, N, m, n);

                assert(!isNaN(probReal), 'Hypergeometric PDF returned NaN');
                assert.epsilon(tol,
                    probReal,
                    probEasy,
                    'Hypergeometric PDF didn\'t match naive implementation');
              }
            }
          }
        }
      }

    },

    'check cdf agreement': function(jStat) {
      var tol = 0.0000001;

      // Define an easy pdf
      function easyPDF(k, N, m, n) {
        if (k !== (k | 0))
          return false;
        if (k < 0)
          return 0;
        return jStat.combination(m, k) * jStat.combination(N - m , n - k) /
            jStat.combination(N, n);
      }

      // Define a summation cdf based on it
      function easyCDF(x, N, m, n) {
        // Sum up the total probability of every number of successes <= x, and
        // put it here.
        var sum = 0;
        for (var i = 0; i <= x; i++)
          sum += easyPDF(i, N, m, n);
        return sum;
      }

      // Now test the easy CDF agaisnt the real one.
      for (var N = 0; N < 10; N++) {
        // For several population sizes
        for (var m = 0; m < N; m++) {
          // For all possible success counts
          for (var n = 0; n < N; n++) {
            // For all possible sample sizes
            for (var x = 0; x < n; x++) {
              // For all subset sizes of the sampled set

              // Get the probability be each method
              var probEasy = easyCDF(x, N, m, n);

              if (!isNaN(probEasy)) {
                // The easy CDF worked for this situation. Compare it to the
                // real one.

                var probReal = jStat.hypgeom.cdf(x, N, m, n);
                assert(!isNaN(probReal), 'Hypergeometric CDF returned NaN');
                assert.epsilon(tol,
                    probReal,
                    probEasy,
                    'Hypergeometric CDF didn\'t match naive implementation');
              }
            }
          }
        }
      }
    },

    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [ 10, 16, 252 ];
      // How big was the source population?
      var population = [ 100, 3589, 3589 ];
      // How many 1s were in it?
      var available = [ 20, 16, 252 ];
      // How big a sample was taken?
      var draws = [ 15, 2290, 252 ];
      // What was the probability of exactly this many 1s?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [ 0.000017532028090435493, 0.0007404996809672229, 0 ];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.

        var calculated = jStat.hypgeom.pdf(successes[i], population[i],
                                           available[i], draws[i]);

        // None of the answers should be NaN
        assert(!isNaN(calculated), "Hypergeometric PDF returned NaN");

        // And they should all match
        assert.epsilon(tol, calculated, answers[i],
          "Hypergeometric PDF returned incorrect answer");
      }
    },
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [ 10, 16, 10 ];
      // How big was the source population?
      var population = [ 100, 3589, 3589 ];
      // How many 1s were in it?
      var available = [ 20, 16, 16 ];
      // How big a sample was taken?
      var draws = [ 15, 2290, 2290 ];
      // What was the probability of this many 1s or fewer?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [ 0.9999989096, 1, 0.55047323949 ];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.

        var calculated = jStat.hypgeom.cdf(successes[i], population[i],
                                           available[i], draws[i]);

        // None of the answers should be NaN
        assert(!isNaN(calculated), "Hypergeometric CDF returned NaN");

        // And they should all match
        assert.epsilon(tol, calculated, answers[i],
          "Hypergeometric CDF returned incorrect answer");
      }
    }
  }
});

suite.export(module);
<commit_msg>Removing duplicate distribution tests<commit_after>var vows = require('vows');
var assert = require('assert');
var suite = vows.describe('jStat.distribution');

require('../env.js');

suite.addBatch({
  'beta pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      // Non-log form of the Beta pdf
      function pdf(x, alpha, beta) {
        if (x > 1 || x < 0)
          return 0;
        return (Math.pow(x, alpha - 1) * Math.pow(1 - x, beta - 1)) /
            jStat.betafn(alpha, beta);
      }

      var tol = 0.0000001;
      var args = [0, 0.1, 0.3, 0.5, 0.7, 0.9, 1];
      var arg;

      for (var i = 0; i < args.length; i++) {
        arg = args[i];
        assert.epsilon(tol, jStat.beta.pdf(arg, 0.1, 0.1), pdf(arg, 0.1, 0.1));
        assert.epsilon(tol, jStat.beta.pdf(arg, 1, 1), pdf(arg, 1, 1));
        assert.epsilon(tol, jStat.beta.pdf(arg, 10, 50), pdf(arg, 10, 50));

        // Show that the log form of the pdf performs better for
        // large parameter values.
        assert(!isNaN(jStat.beta.pdf(arg, 1000, 5000)),
               'New Beta pdf is NaN for large parameter values.');
        assert(isNaN(pdf(arg, 1000, 5000)),
               'Old Beta pdf is not NaN for large parameter values.');
      }

      assert.equal(jStat.beta.pdf(0, 1, 4), 4);
      assert.equal(jStat.beta.pdf(1, 4, 1), 4);
    }
  },

  'gamma pdf': {
    'topic': function() {
      return jStat;
    },
    'check instance and static pdf method': function (jStat) {
      var shape = 5;
      var scale = 1;
      var gamma = jStat.gamma(shape, scale);
      var xValues = [-1, 0, 1];
      var x;
      for (var i = 0; i < xValues.length; i++) {
        x = xValues[i];
        pStatic = jStat.gamma.pdf(x, shape, scale);
        pInstance = gamma.pdf(x);
        if (isNaN(pStatic)) {
          assert(isNaN(pInstance));
        } else {
          assert(pStatic === pInstance,
                 'Gamma pdf evaluated at ' +
                   x + ' should be equal for instance and static methods.');
        }
      }
    }
  },

  'binomial pdf': {
    'topic': function() {
      return jStat;
    },
    //checked against R's dbinom(k, n, p)
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.pdf(10, 25, 0.5), 0.09741664);
      assert.epsilon(tol, jStat.binomial.pdf(50, 1000, 0.05), 0.05778798);
    },
    //Checked against r's pbinom(k, n, p)
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.binomial.cdf(10, 25, 0.5), 0.2121781);
      assert.epsilon(tol, jStat.binomial.cdf(50, 1000, 0.05), 0.537529);
    }
  },

  'studentt pdf': {
    'topic': function() {
      return jStat;
    },
    //Checked against R dt(x,df)
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      var x = 0.5;
      var df = 40;
      assert.epsilon(tol, jStat.studentt.pdf(x, df), 0.3489195);
    },
    //Checked against R's pt(x, df)
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      var x = 0.5;
      var df = 40;
      assert.epsilon(tol, jStat.studentt.cdf(x, df), 0.6900926);
    },
    //Checked against R's qt(x, df)
    'check inv calculation': function(jStat) {
      var tol = 0.0000001;
      assert.epsilon(tol, jStat.studentt.inv(0.5, 40), 0);
      assert.epsilon(tol, jStat.studentt.inv(0.7, 20), 0.5328628);
      assert.epsilon(tol, jStat.studentt.inv(0.2, 10), -0.8790578);
    }
  },
});

suite.addBatch({
  'negbin pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var k = 10; // number of failures
      var r = 5; // threshold number of successes
      var p = 0.25; // probability of a success
      assert(jStat.negbin.pdf(k, r, p), 0.05504866037517786);
    }
  },

  'negbin cdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var k = 10; // number of failures
      var r = 5; // threshold number of successes
      var p = 0.25; // probability of a success
      assert(jStat.negbin.cdf(k, r, p), 0.3135140584781766);
    }
  },
});

suite.addBatch({
  'hypergeometric pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [10, 16];
      // How big was the source population?
      var population = [100, 3589];
      // How many 1s were in it?
      var available = [20, 16];
      // How big a sample was taken?
      var draws = [15, 2290];
      // What was the probability of exactly this many 1s?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [0.000017532028090435493, 0.0007404996809672229];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.
        var calculated = jStat.hypgeom.pdf(successes[i],
                                           population[i],
                                           available[i],
                                           draws[i]);
        // None of the answers should be NaN
        assert(!isNaN(calculated));
        // And they should all match
        assert.epsilon(tol, calculated, answers[i]);
      }
    }
  }
});

suite.addBatch({
  'hypergeometric pdf': {
    'topic': function() {
      return jStat;
    },
    'check pdf agreement': function(jStat) {
      var tol = 0.0000001;

      // Define an easy pdf
      var easyPDF = function pdf(k, N, m, n) {
        if (k !== (k | 0))
          return false;
        if (k < 0)
          return 0;
        return jStat.combination(m, k) * jStat.combination(N - m , n - k) /
            jStat.combination(N, n);
      }

      // Now test the easy PDF agaisnt the real one.
      for (var N = 0; N < 10; N++) {
        // For several population sizes
        for (var m = 0; m < N; m++) {
          // For all possible success counts
          for (var n = 0; n < N; n++) {
            // For all possible sample sizes
            for (var x = 0; x < n; x++) {
              // For all subset sizes of the sampled set

              // Get the probability be each method
              var probEasy = easyPDF(x, N, m, n);

              if (!isNaN(probEasy)) {
                // The easy PDF worked for this situation. Compare it to the
                // real one.

                var probReal = jStat.hypgeom.pdf(x, N, m, n);

                assert(!isNaN(probReal), 'Hypergeometric PDF returned NaN');
                assert.epsilon(tol,
                    probReal,
                    probEasy,
                    'Hypergeometric PDF didn\'t match naive implementation');
              }
            }
          }
        }
      }

    },

    'check cdf agreement': function(jStat) {
      var tol = 0.0000001;

      // Define an easy pdf
      function easyPDF(k, N, m, n) {
        if (k !== (k | 0))
          return false;
        if (k < 0)
          return 0;
        return jStat.combination(m, k) * jStat.combination(N - m , n - k) /
            jStat.combination(N, n);
      }

      // Define a summation cdf based on it
      function easyCDF(x, N, m, n) {
        // Sum up the total probability of every number of successes <= x, and
        // put it here.
        var sum = 0;
        for (var i = 0; i <= x; i++)
          sum += easyPDF(i, N, m, n);
        return sum;
      }

      // Now test the easy CDF agaisnt the real one.
      for (var N = 0; N < 10; N++) {
        // For several population sizes
        for (var m = 0; m < N; m++) {
          // For all possible success counts
          for (var n = 0; n < N; n++) {
            // For all possible sample sizes
            for (var x = 0; x < n; x++) {
              // For all subset sizes of the sampled set

              // Get the probability be each method
              var probEasy = easyCDF(x, N, m, n);

              if (!isNaN(probEasy)) {
                // The easy CDF worked for this situation. Compare it to the
                // real one.

                var probReal = jStat.hypgeom.cdf(x, N, m, n);
                assert(!isNaN(probReal), 'Hypergeometric CDF returned NaN');
                assert.epsilon(tol,
                    probReal,
                    probEasy,
                    'Hypergeometric CDF didn\'t match naive implementation');
              }
            }
          }
        }
      }
    },

    'check pdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [ 10, 16, 252 ];
      // How big was the source population?
      var population = [ 100, 3589, 3589 ];
      // How many 1s were in it?
      var available = [ 20, 16, 252 ];
      // How big a sample was taken?
      var draws = [ 15, 2290, 252 ];
      // What was the probability of exactly this many 1s?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [ 0.000017532028090435493, 0.0007404996809672229, 0 ];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.

        var calculated = jStat.hypgeom.pdf(successes[i], population[i],
                                           available[i], draws[i]);

        // None of the answers should be NaN
        assert(!isNaN(calculated), "Hypergeometric PDF returned NaN");

        // And they should all match
        assert.epsilon(tol, calculated, answers[i],
          "Hypergeometric PDF returned incorrect answer");
      }
    },
    'check cdf calculation': function(jStat) {
      var tol = 0.0000001;
      // How many 1s were obtained by sampling?
      var successes = [ 10, 16, 10 ];
      // How big was the source population?
      var population = [ 100, 3589, 3589 ];
      // How many 1s were in it?
      var available = [ 20, 16, 16 ];
      // How big a sample was taken?
      var draws = [ 15, 2290, 2290 ];
      // What was the probability of this many 1s or fewer?
      // Obtained from the calculator at
      // <http://www.geneprof.org/GeneProf/tools/hypergeometric.jsp>
      var answers = [ 0.9999989096, 1, 0.55047323949 ];

      for (var i = 0; i < answers.length; i++) {
        // See if we get the right answer for each calculation.

        var calculated = jStat.hypgeom.cdf(successes[i], population[i],
                                           available[i], draws[i]);

        // None of the answers should be NaN
        assert(!isNaN(calculated), "Hypergeometric CDF returned NaN");

        // And they should all match
        assert.epsilon(tol, calculated, answers[i],
          "Hypergeometric CDF returned incorrect answer");
      }
    }
  }
});

suite.export(module);
<|endoftext|>