<commit_before>// FacebookService service
NGApp.factory( 'FacebookService', function( $http, $location, $rootScope, AccountService, ReferralService) {

	var service = {
		token : false,
		_order_uuid : false,
		orderStatus : false,
		logged : false,
		doAuth : true,
		wait : false,
		running : false,
		error : { unknown : false, userExists : false, login : false }
	}

	service.referral = ReferralService;

	service.account = AccountService;

	// This method pre load the order info that could be posted
	service.preLoadOrderStatus = function(uuid){
		$http.get(App.service + 'facebook/status/order/' + service._order_uuid).success( function( data ) {
			if (data.success) {
				service.orderStatus = data.success;
			} else {
				service.orderStatus = false;
			}
		});
	}

	// This method let the user type his message before post
	service.postOrder = function(){
		if( service.orderStatus ){
			var status = service.orderStatus;
			status.link = service.referral.cleaned_url();
			App.share({
				url: 'http://' + status.link,
				name: status.name,
				caption: status.caption,
				description: status.description,
				picture: status.picture,
				success : function( success ){
					$http( {
						method: 'POST',
						url: App.service + 'facebook/reward/',
						data: $.param( { 'post_id': success.post_id, 'uuid': service._order_uuid } ),
						headers: {'Content-Type': 'application/x-www-form-urlencoded'}
					} ).success( function(){
						$rootScope.$broadcast( 'orderSharedFacebook' );
					} );
				}
			});
		} else {
			service.preLoadOrderStatus();
			App.alert( 'Oops, please try again!' );
			return;
		}
	}

	service.postInvite = function(url, code) {
		var description = App.AB.get('share-facebook-description').replace('%c', code);
		var title = App.AB.get('share-facebook-title');
		var url = ( App.AB.get('share-facebook-url') != '' ) ? App.AB.get('share-facebook-url') : url;
		App.share({
			url: url,
			name: title,
			caption: ' ',
			description: description
		});
	}

	service.shareOrder = function( url, code ) {
		var text = App.AB.get('share-text-twitter').replace('%c', code);
		App.share({
			url: url,
			name: 'Crunchbutton',
			caption: 'Crunchbutton',
			description: text,
			url: url,
			picture: status.picture,
			success : function( success ){
				$http( {
					method: 'POST',
					url: App.service + 'facebook/reward/',
					data: $.param( { 'post_id': success.post_id, 'uuid': service._order_uuid } ),
					headers: {'Content-Type': 'application/x-www-form-urlencoded'}
				} ).success( function(){
					$rootScope.$broadcast( 'orderSharedFacebook' );
				} );
			}
		});
	}

	// request permission to post on a users timeline
	service.requestPermission = function(callback) {
		callback = typeof callback === 'function' ? callback : function(){};
		FB.ui({
			method: 'permissions.request',
			perms: serviceScope,
			display: 'iframe'
		}, callback);
	}

	// process status is called any time a status change event is triggered with facebook
	service.processStatus = function(status) {

		if (status.status === 'connected' && status.authResponse) {

			service.logged = true;
			service.error.unknown = false;
			service.error.userExists = false;
			service.error.login = false;

			service.token = status.authResponse.accessToken;
			$.totalStorage('fbtoken', service.token);

			// if the app already has a user, we dont give a crap about facebook
			if ( App.config.user.id_user && App.config.user.facebook ) {
				return;
			}

			// android's returns this variable as userId
			if( status.authResponse.userId ){
				status.authResponse.userID = status.authResponse.userId;
			}

			if (status.authResponse.userID) {

				App.log.account({'userID': status.authResponse.userID}, 'facebook login');

				// make sure we dont double call the authentication and user creation service
				if (!service.running) {
					service.running = true;
					App.log.account({'userID': status.authResponse.userID, 'running': service.running}, 'facebook running');

					// if it is phonegap call a special facebook connection
					var data = {};

					url = App.service + 'user/facebook?fbrtoken=' + service.token;

					// Just call the user api, this will create a facebook user
					$http( { method: 'GET', url: url, cache: false } ).success(function( data ) {

						App.log.account({'userID': status.authResponse.userID, 'running': service.running, 'data': data }, 'facebook ajax');

						if (data.error) {
							if (data.error == 'facebook id already in use') {
								$rootScope.$broadcast( 'facebookIdAlreadyUsed', true );
								App.log.account({'error': data.error}, 'facebook error');
								service.error.userExists = true;
							}
							service.running = false;
							return;
						} else {
							service.account.updateInfo();
							service.account.user = data;

							if (service.account.callback) {
								service.account.callback();
								service.account.callback = false;
							} else {
								try {
									$.magnificPopup.close();
								} catch (e) {}
							}

						}

						App.log.account({'userID': status.authResponse.userID} , 'facebook currentPage');
						$rootScope.$broadcast('userAuth', service.account.user);
						service.running = false;
						service.wait = false;
					});
				}
			}

		} else {
			// the service is notConnected. reset everything
			service.logged = false;
			service.error.unknown = false;
			service.error.userExists = false;
			service.error.login = false;
			service.token = null;
			$.totalStorage('fbtoken', null);
		}

	}

	// sign out of facebook
	service.signout = function(callback) {
		var complete = function() {
			service.logged = false;
			if (typeof callback === 'function') {
				callback();
			}
		};
		try {
			FB.logout(complete);
		} catch (e) {
			complete();
		}
	}

	return service;
});<commit_msg>fixes #6774<commit_after>// FacebookService service
NGApp.factory( 'FacebookService', function( $http, $location, $rootScope, AccountService, ReferralService) {

	var service = {
		token : false,
		_order_uuid : false,
		orderStatus : false,
		logged : false,
		doAuth : true,
		wait : false,
		running : false,
		error : { unknown : false, userExists : false, login : false }
	}

	service.referral = ReferralService;

	service.account = AccountService;

	// This method pre load the order info that could be posted
	service.preLoadOrderStatus = function(uuid){
		$http.get(App.service + 'facebook/status/order/' + service._order_uuid).success( function( data ) {
			if (data.success) {
				service.orderStatus = data.success;
			} else {
				service.orderStatus = false;
			}
		});
	}

	// This method let the user type his message before post
	service.postOrder = function(){
		if( service.orderStatus ){
			var status = service.orderStatus;
			status.link = service.referral.cleaned_url();
			App.share({
				url: 'http://' + status.link,
				name: status.name,
				caption: status.caption,
				description: status.description,
				picture: status.picture,
				success : function( success ){
					$http( {
						method: 'POST',
						url: App.service + 'facebook/reward/',
						data: $.param( { 'post_id': success.post_id, 'uuid': service._order_uuid } ),
						headers: {'Content-Type': 'application/x-www-form-urlencoded'}
					} ).success( function(){
						$rootScope.$broadcast( 'orderSharedFacebook' );
					} );
				}
			});
		} else {
			service.preLoadOrderStatus();
			App.alert( 'Oops, please try again!' );
			return;
		}
	}

	service.postInvite = function(url, code) {
		var description = App.AB.get('share-facebook-description').replace('%c', code);
		var title = App.AB.get('share-facebook-title');
		var url = ( App.AB.get('share-facebook-url') != '' ) ? App.AB.get('share-facebook-url') : url;
		App.share({
			url: url,
			name: title,
			caption: ' ',
			description: description
		});
	}

	service.shareOrder = function( url, code ) {
		var text = App.AB.get('share-text-twitter').replace('%c', code);
		App.share({
			url: url,
			name: 'Crunchbutton',
			caption: 'Crunchbutton',
			description: text,
			url: url,
			picture: status.picture,
			success : function( success ){
				$http( {
					method: 'POST',
					url: App.service + 'facebook/reward/',
					data: $.param( { 'post_id': success.post_id, 'uuid': service._order_uuid } ),
					headers: {'Content-Type': 'application/x-www-form-urlencoded'}
				} ).success( function(){
					$rootScope.$broadcast( 'orderSharedFacebook' );
				} );
			}
		});
	}

	// request permission to post on a users timeline
	service.requestPermission = function(callback) {
		callback = typeof callback === 'function' ? callback : function(){};
		FB.ui({
			method: 'permissions.request',
			perms: serviceScope,
			display: 'iframe'
		}, callback);
	}

	// process status is called any time a status change event is triggered with facebook
	service.processStatus = function(status) {

		if (status.status === 'connected' && status.authResponse) {

			service.logged = true;
			service.error.unknown = false;
			service.error.userExists = false;
			service.error.login = false;

			service.token = status.authResponse.accessToken;
			$.totalStorage('fbtoken', service.token);

			// if the app already has a user, we dont give a crap about facebook
			if ( App.config.user.id_user && App.config.user.facebook ) {
				return;
			}

			// android's returns this variable as userId
			if( status.authResponse.userId ){
				status.authResponse.userID = status.authResponse.userId;
			}

			if (status.authResponse.userID) {

				App.log.account({'userID': status.authResponse.userID}, 'facebook login');

				// make sure we dont double call the authentication and user creation service
				if (!service.running) {
					service.running = true;
					App.log.account({'userID': status.authResponse.userID, 'running': service.running}, 'facebook running');

					// if it is phonegap call a special facebook connection
					var data = {};

					url = App.service + 'user/facebook?fbrtoken=' + service.token;

					// Just call the user api, this will create a facebook user
					$http( { method: 'GET', url: url, cache: false } ).success(function( data ) {

						App.log.account({'userID': status.authResponse.userID, 'running': service.running, 'data': data }, 'facebook ajax');

						if (data.error) {
							if (data.error == 'facebook id already in use') {
								$rootScope.$broadcast( 'facebookIdAlreadyUsed', true );
								App.log.account({'error': data.error}, 'facebook error');
								service.error.userExists = true;
							}
							service.running = false;
							return;
						} else {
							service.account.updateInfo();
							service.account.user = data;

							if (service.account.callback) {
								service.account.callback();
								service.account.callback = false;
							} else {
								try {
									$.magnificPopup.close();
								} catch (e) {}
							}

						}

						App.log.account({'userID': status.authResponse.userID} , 'facebook currentPage');
						$rootScope.$broadcast('userAuth', service.account.user);
						service.running = false;
						service.wait = false;
					});
				}
			}

		} else {
			// the service is notConnected. reset everything
			service.logged = false;
			service.error.unknown = false;
			service.error.userExists = false;
			service.error.login = false;
			service.token = null;
			$.totalStorage('fbtoken', null);
		}

	}

	// sign out of facebook
	service.signout = function(callback) {
		var complete = function() {
			service.logged = false;
			if (typeof callback === 'function') {
				callback();
			}
		};

		try {
			if( FB.getUserID() != '' ){
				FB.logout(complete);
			} else {
				complete();
			}
		} catch (e) {
			complete();
		}
	}

	return service;
});<|endoftext|>


<commit_before>import Ember from 'ember';
import ValidationEngine from 'ghost/mixins/validation-engine';
import {request as ajax} from 'ic-ajax';

export default Ember.Controller.extend(ValidationEngine, {
    submitting: false,
    loggingIn: false,
    authProperties: ['identification', 'password'],

    ghostPaths: Ember.inject.service('ghost-paths'),
    notifications: Ember.inject.service(),
    flowErrors: '',

    // ValidationEngine settings
    validationType: 'signin',

    actions: {
        authenticate: function () {
            var self = this,
                model = this.get('model'),
                authStrategy = 'ghost-authenticator:oauth2-password-grant',
                data = model.getProperties(this.authProperties);

            this.get('session').authenticate(authStrategy, data).then(function () {
                self.toggleProperty('loggingIn');
            }).catch(function (err) {
                self.toggleProperty('loggingIn');

                if (err.errors) {
                    self.set('flowErrors', err.errors[0].message.string);

                    // this catches both 'no user' and 'user inactive' errors
                    // long term, we probably need to introduce error codes from the server
                    if (err.errors[0].message.string.match(/user with that email/)) {
                        self.get('model.errors').add('identification', '');
                    }

                    if (err.errors[0].message.string.match(/password is incorrect/)) {
                        self.get('model.errors').add('password', '');
                    }
                }
                // if authentication fails a rejected promise will be returned.
                // it needs to be caught so it doesn't generate an exception in the console,
                // but it's actually "handled" by the sessionAuthenticationFailed action handler.
            });
        },

        validateAndAuthenticate: function () {
            var self = this;
            this.set('flowErrors', '');
            // Manually trigger events for input fields, ensuring legacy compatibility with
            // browsers and password managers that don't send proper events on autofill
            $('#login').find('input').trigger('change');

            // This is a bit dirty, but there's no other way to ensure the properties are set as well as 'signin'
            this.get('hasValidated').addObjects(this.authProperties);
            this.validate({property: 'signin'}).then(function () {
                self.toggleProperty('loggingIn');
                self.send('authenticate');
            }).catch(function (error) {
                if (error) {
                    self.get('notifications').showAPIError(error);
                } else {
                    self.set('flowErrors', 'Please fill out the form to sign in.');
                }
            });
        },

        forgotten: function () {
            var email = this.get('model.identification'),
                notifications = this.get('notifications'),
                self = this;

            this.set('flowErrors', '');
            // This is a bit dirty, but there's no other way to ensure the properties are set as well as 'forgotPassword'
            this.get('hasValidated').addObject('identification');
            this.validate({property: 'forgotPassword'}).then(function () {
                self.toggleProperty('submitting');

                ajax({
                    url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
                    type: 'POST',
                    data: {
                        passwordreset: [{
                            email: email
                        }]
                    }
                }).then(function () {
                    self.toggleProperty('submitting');
                    notifications.showAlert('Please check your email for instructions.', {type: 'info'});
                }).catch(function (resp) {
                    self.toggleProperty('submitting');
                    if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.errors) {
                        var message = resp.jqXHR.responseJSON.errors[0].message;

                        self.set('flowErrors', message);

                        if (message.match(/no user with that email/)) {
                            self.get('model.errors').add('identification', '');
                        }
                    } else {
                        notifications.showAPIError(resp, {defaultErrorText: 'There was a problem with the reset, please try again.'});
                    }
                });
            }).catch(function () {
                self.set('flowErrors', 'Please enter an email address then click "Forgot?".');
            });
        }
    }
});
<commit_msg>Keep spinner running on successful signin<commit_after>import Ember from 'ember';
import ValidationEngine from 'ghost/mixins/validation-engine';
import {request as ajax} from 'ic-ajax';

export default Ember.Controller.extend(ValidationEngine, {
    submitting: false,
    loggingIn: false,
    authProperties: ['identification', 'password'],

    ghostPaths: Ember.inject.service('ghost-paths'),
    notifications: Ember.inject.service(),
    flowErrors: '',

    // ValidationEngine settings
    validationType: 'signin',

    actions: {
        authenticate: function () {
            var self = this,
                model = this.get('model'),
                authStrategy = 'ghost-authenticator:oauth2-password-grant',
                data = model.getProperties(this.authProperties);

            // Authentication transitions to posts.index, we can leave spinner running unless there is an error
            this.get('session').authenticate(authStrategy, data).catch(function (err) {
                self.toggleProperty('loggingIn');

                if (err.errors) {
                    self.set('flowErrors', err.errors[0].message.string);

                    // this catches both 'no user' and 'user inactive' errors
                    // long term, we probably need to introduce error codes from the server
                    if (err.errors[0].message.string.match(/user with that email/)) {
                        self.get('model.errors').add('identification', '');
                    }

                    if (err.errors[0].message.string.match(/password is incorrect/)) {
                        self.get('model.errors').add('password', '');
                    }
                }
                // if authentication fails a rejected promise will be returned.
                // it needs to be caught so it doesn't generate an exception in the console,
                // but it's actually "handled" by the sessionAuthenticationFailed action handler.
            });
        },

        validateAndAuthenticate: function () {
            var self = this;
            this.set('flowErrors', '');
            // Manually trigger events for input fields, ensuring legacy compatibility with
            // browsers and password managers that don't send proper events on autofill
            $('#login').find('input').trigger('change');

            // This is a bit dirty, but there's no other way to ensure the properties are set as well as 'signin'
            this.get('hasValidated').addObjects(this.authProperties);
            this.validate({property: 'signin'}).then(function () {
                self.toggleProperty('loggingIn');
                self.send('authenticate');
            }).catch(function (error) {
                if (error) {
                    self.get('notifications').showAPIError(error);
                } else {
                    self.set('flowErrors', 'Please fill out the form to sign in.');
                }
            });
        },

        forgotten: function () {
            var email = this.get('model.identification'),
                notifications = this.get('notifications'),
                self = this;

            this.set('flowErrors', '');
            // This is a bit dirty, but there's no other way to ensure the properties are set as well as 'forgotPassword'
            this.get('hasValidated').addObject('identification');
            this.validate({property: 'forgotPassword'}).then(function () {
                self.toggleProperty('submitting');

                ajax({
                    url: self.get('ghostPaths.url').api('authentication', 'passwordreset'),
                    type: 'POST',
                    data: {
                        passwordreset: [{
                            email: email
                        }]
                    }
                }).then(function () {
                    self.toggleProperty('submitting');
                    notifications.showAlert('Please check your email for instructions.', {type: 'info'});
                }).catch(function (resp) {
                    self.toggleProperty('submitting');
                    if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.errors) {
                        var message = resp.jqXHR.responseJSON.errors[0].message;

                        self.set('flowErrors', message);

                        if (message.match(/no user with that email/)) {
                            self.get('model.errors').add('identification', '');
                        }
                    } else {
                        notifications.showAPIError(resp, {defaultErrorText: 'There was a problem with the reset, please try again.'});
                    }
                });
            }).catch(function () {
                self.set('flowErrors', 'Please enter an email address then click "Forgot?".');
            });
        }
    }
});
<|endoftext|>


<commit_before>'use strict';

/* App Module */

var mldsApp = angular.module('MLDS', ['http-auth-interceptor', 'tmh.dynamicLocale',
    'ngResource', 'ngRoute', 'ngCookies', 'mldsAppUtils', 'pascalprecht.translate', 'truncate', 'ui.bootstrap']);

mldsApp
    .config(['$routeProvider', '$httpProvider', '$translateProvider',  'tmhDynamicLocaleProvider', 'USER_ROLES',
        function ($routeProvider, $httpProvider, $translateProvider, tmhDynamicLocaleProvider, USER_ROLES) {
            $routeProvider
                .when('/register', {
                    templateUrl: 'views/register.html',
                    controller: 'RegisterController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/emailVerification', {
                    templateUrl: 'views/registration/emailVerification.html',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/affiliateRegistration', {
                    templateUrl: 'views/registration/affiliateRegistration.html',
                    controller: 'AffiliateRegistrationController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/activate', {
                    templateUrl: 'views/activate.html',
                    controller: 'ActivationController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/dashboard', {
                    templateUrl: 'views/user/Dashboard.html',
                    controller: 'UserDashboardController',
                    access: {
                        authorizedRoles: [USER_ROLES.user]
                    }
                })
                .when('/usage-log/:usageReportId', {
                    templateUrl: 'views/user/fullPageUsageLog.html',
                    controller: 'FullPageUsageLogController',
                    access: {
                        authorizedRoles: [USER_ROLES.user]
                    }
                })
                .when('/login', {
                    templateUrl: 'views/login.html',
                    controller: 'LoginController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/error', {
                    templateUrl: 'views/error.html',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/contactInfo', {
                    templateUrl: 'views/contactInfo.html',
                    controller: 'ContactInfoController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/password', {
                    templateUrl: 'views/password.html',
                    controller: 'PasswordController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/requestPasswordReset', {
                	templateUrl: 'views/requestPasswordReset.html',
                	controller: 'RequestPasswordResetController',
                	access: {
                		authorizedRoles: [USER_ROLES.all]
                	}
                })
                .when('/resetPassword', {
                	templateUrl: 'views/resetPassword.html',
                	controller: 'ResetPasswordController',
                	access: {
                		authorizedRoles: [USER_ROLES.all]
                	}
                })
                .when('/sessions', {
                    templateUrl: 'views/sessions.html',
                    controller: 'SessionsController',
                    resolve:{
                        resolvedSessions:['Sessions', function (Sessions) {
                            return Sessions.get();
                        }]
                    },
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/adminDashboard', {
                    templateUrl: 'views/admin/dashboard.html',
                    controller: 'AdminDashboardController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/packageManagement', {
                    templateUrl: 'views/admin/packageManagement.html',
                    controller: 'PackageManagementController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                // FIXME MLDS-50 MB can we push these routes down to /admin and leave these names for the user?
                .when('/package/:packageId', {
                    templateUrl: 'views/admin/package.html',
                    controller: 'PackageController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/package/:packageId/:edit', {
                    templateUrl: 'views/admin/package.html',
                    controller: 'PackageController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                // FIXME MLDS-50 MB can we push these routes down to /admin and leave these names for the user?
                .when('/viewPackages', {
                    templateUrl: 'views/user/viewPackages.html',
                    controller: 'ViewPackagesController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/viewPackage/:releasePackageId', {
                    templateUrl: 'views/user/viewPackage.html',
                    controller: 'ViewPackageController',
                    access: {
                    	authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/pendingApplications', {
                    templateUrl: 'views/admin/pendingApplications.html',
                    controller: 'PendingApplicationsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/applicationReview/:applicationId', {
                    templateUrl: 'views/admin/applicationReview.html',
                    controller: 'ApplicationReviewController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/metrics', {
                    templateUrl: 'views/admin/metrics.html',
                    controller: 'MetricsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/logs', {
                    templateUrl: 'views/admin/logs.html',
                    controller: 'LogsController',
                    resolve:{
                        resolvedLogs:['LogsService', function (LogsService) {
                            return LogsService.findAll();
                        }]
                    },
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/audits', {
                    templateUrl: 'views/admin/audits.html',
                    controller: 'AuditsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/logout', {
                    templateUrl: 'views/main.html',
                    controller: 'LogoutController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/docs', {
                    templateUrl: 'views/admin/docs.html',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/styleguide/:template*', {
                    templateUrl: function(params){
                    	return 'views/styleguide/'+params.template+'.html';},
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .otherwise({
                    templateUrl: 'views/landingPage.html',
                    controller: 'MainController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                });

            // Initialize angular-translate
            $translateProvider.useStaticFilesLoader({
                prefix: 'i18n/',
                suffix: '.json'
            });

            $translateProvider.preferredLanguage('en');

            $translateProvider.useCookieStorage();

            tmhDynamicLocaleProvider.localeLocationPattern('bower_components/angular-i18n/angular-locale_{{locale}}.js')
            tmhDynamicLocaleProvider.useCookieStorage('NG_TRANSLATE_LANG_KEY');

//            var apiDelay = 1000;
//            var otherDelay = 0;
//            var errorMethodMatches = /PUT|xDELETE|xPOST/;
//            var delayHandlerFactory = function($q, $timeout) {
//                return function(promise) {
//                    return promise.then(function(response) {
//                        return $timeout(function() {
//                        	if (errorMethodMatches.test(response.config.method)) {
//                        		return $q.reject(response);
//                        	} else {
//                        		return response;
//                        	}
//                        }, (response.config.url.indexOf('/rest') !== -1 || response.config.url.indexOf('/api') !== -1   ? apiDelay : otherDelay));
//                    }, function(response) {
//                        return $q.reject(response);
//                    });
//                };
//            };
//            $httpProvider.responseInterceptors.push(delayHandlerFactory);

        }])
        .run(['$rootScope', '$location', '$http', '$log', 'AuthenticationSharedService', 'Session', 'USER_ROLES',
            function($rootScope, $location, $http, $log, AuthenticationSharedService, Session, USER_ROLES) {
                $rootScope.$on('$routeChangeStart', function (event, next) {
                    $rootScope.isAuthorized = AuthenticationSharedService.isAuthorized;
                    $rootScope.userRoles = USER_ROLES;
                    AuthenticationSharedService.valid(next.access.authorizedRoles);
                });

                // Call when the the client is confirmed
                $rootScope.$on('event:auth-loginConfirmed', function(data) {
                    $rootScope.authenticated = true;
                    if ($location.path() === "/login") {
                    	if (AuthenticationSharedService.isAuthorized(USER_ROLES.staffOrAdmin)) {
                    		$location.path('/adminDashboard').replace();
                    	} else {
                    		$location.path('/dashboard').replace();
                    	}
                    }
                });

                // Call when the 401 response is returned by the server
                $rootScope.$on('event:auth-loginRequired', function(rejection) {
                    Session.invalidate();
                    $rootScope.authenticated = false;

                    if ($location.path() !== "/" &&
                    		$location.path() !== "" &&
                    		$location.path() !== "/register" &&
                    		// FIXME MB is there a better way to register anonymous pages?
                    		$location.path() !== "/requestPasswordReset" &&
                    		$location.path() !== "/resetPassword" &&
                    		$location.path().indexOf("/viewPackage") == -1 &&
                    		$location.path() !== "/viewPackages" &&
                    		$location.path() !== "/emailVerification" &&
                            $location.path() !== "/activate") {
                        $location.path('/login').replace();
                    }
                });

                // Call when the 403 response is returned by the server
                $rootScope.$on('event:auth-notAuthorized', function(rejection) {
                    $rootScope.errorMessage = 'errors.403';
                    $location.path('/error').replace();
                });

                // Call when the user logs out
                $rootScope.$on('event:auth-loginCancelled', function() {
                    $location.path('');
                });
        }]);
<commit_msg>MLDS-259 MLDS-357 Use routes to protect contact info to only users<commit_after>'use strict';

/* App Module */

var mldsApp = angular.module('MLDS', ['http-auth-interceptor', 'tmh.dynamicLocale',
    'ngResource', 'ngRoute', 'ngCookies', 'mldsAppUtils', 'pascalprecht.translate', 'truncate', 'ui.bootstrap']);

mldsApp
    .config(['$routeProvider', '$httpProvider', '$translateProvider',  'tmhDynamicLocaleProvider', 'USER_ROLES',
        function ($routeProvider, $httpProvider, $translateProvider, tmhDynamicLocaleProvider, USER_ROLES) {
            $routeProvider
                .when('/register', {
                    templateUrl: 'views/register.html',
                    controller: 'RegisterController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/emailVerification', {
                    templateUrl: 'views/registration/emailVerification.html',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/affiliateRegistration', {
                    templateUrl: 'views/registration/affiliateRegistration.html',
                    controller: 'AffiliateRegistrationController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/activate', {
                    templateUrl: 'views/activate.html',
                    controller: 'ActivationController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/dashboard', {
                    templateUrl: 'views/user/Dashboard.html',
                    controller: 'UserDashboardController',
                    access: {
                        authorizedRoles: [USER_ROLES.user]
                    }
                })
                .when('/usage-log/:usageReportId', {
                    templateUrl: 'views/user/fullPageUsageLog.html',
                    controller: 'FullPageUsageLogController',
                    access: {
                        authorizedRoles: [USER_ROLES.user]
                    }
                })
                .when('/login', {
                    templateUrl: 'views/login.html',
                    controller: 'LoginController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/error', {
                    templateUrl: 'views/error.html',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/contactInfo', {
                    templateUrl: 'views/contactInfo.html',
                    controller: 'ContactInfoController',
                    access: {
                    	authorizedRoles: [USER_ROLES.user]
                    }
                })
                .when('/password', {
                    templateUrl: 'views/password.html',
                    controller: 'PasswordController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/requestPasswordReset', {
                	templateUrl: 'views/requestPasswordReset.html',
                	controller: 'RequestPasswordResetController',
                	access: {
                		authorizedRoles: [USER_ROLES.all]
                	}
                })
                .when('/resetPassword', {
                	templateUrl: 'views/resetPassword.html',
                	controller: 'ResetPasswordController',
                	access: {
                		authorizedRoles: [USER_ROLES.all]
                	}
                })
                .when('/sessions', {
                    templateUrl: 'views/sessions.html',
                    controller: 'SessionsController',
                    resolve:{
                        resolvedSessions:['Sessions', function (Sessions) {
                            return Sessions.get();
                        }]
                    },
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/adminDashboard', {
                    templateUrl: 'views/admin/dashboard.html',
                    controller: 'AdminDashboardController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/packageManagement', {
                    templateUrl: 'views/admin/packageManagement.html',
                    controller: 'PackageManagementController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                // FIXME MLDS-50 MB can we push these routes down to /admin and leave these names for the user?
                .when('/package/:packageId', {
                    templateUrl: 'views/admin/package.html',
                    controller: 'PackageController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/package/:packageId/:edit', {
                    templateUrl: 'views/admin/package.html',
                    controller: 'PackageController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                // FIXME MLDS-50 MB can we push these routes down to /admin and leave these names for the user?
                .when('/viewPackages', {
                    templateUrl: 'views/user/viewPackages.html',
                    controller: 'ViewPackagesController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/viewPackage/:releasePackageId', {
                    templateUrl: 'views/user/viewPackage.html',
                    controller: 'ViewPackageController',
                    access: {
                    	authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/pendingApplications', {
                    templateUrl: 'views/admin/pendingApplications.html',
                    controller: 'PendingApplicationsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/applicationReview/:applicationId', {
                    templateUrl: 'views/admin/applicationReview.html',
                    controller: 'ApplicationReviewController',
                    access: {
                    	authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/metrics', {
                    templateUrl: 'views/admin/metrics.html',
                    controller: 'MetricsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/logs', {
                    templateUrl: 'views/admin/logs.html',
                    controller: 'LogsController',
                    resolve:{
                        resolvedLogs:['LogsService', function (LogsService) {
                            return LogsService.findAll();
                        }]
                    },
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/audits', {
                    templateUrl: 'views/admin/audits.html',
                    controller: 'AuditsController',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/logout', {
                    templateUrl: 'views/main.html',
                    controller: 'LogoutController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                })
                .when('/docs', {
                    templateUrl: 'views/admin/docs.html',
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .when('/styleguide/:template*', {
                    templateUrl: function(params){
                    	return 'views/styleguide/'+params.template+'.html';},
                    access: {
                        authorizedRoles: USER_ROLES.staffOrAdmin
                    }
                })
                .otherwise({
                    templateUrl: 'views/landingPage.html',
                    controller: 'MainController',
                    access: {
                        authorizedRoles: [USER_ROLES.all]
                    }
                });

            // Initialize angular-translate
            $translateProvider.useStaticFilesLoader({
                prefix: 'i18n/',
                suffix: '.json'
            });

            $translateProvider.preferredLanguage('en');

            $translateProvider.useCookieStorage();

            tmhDynamicLocaleProvider.localeLocationPattern('bower_components/angular-i18n/angular-locale_{{locale}}.js')
            tmhDynamicLocaleProvider.useCookieStorage('NG_TRANSLATE_LANG_KEY');

//            var apiDelay = 1000;
//            var otherDelay = 0;
//            var errorMethodMatches = /PUT|xDELETE|xPOST/;
//            var delayHandlerFactory = function($q, $timeout) {
//                return function(promise) {
//                    return promise.then(function(response) {
//                        return $timeout(function() {
//                        	if (errorMethodMatches.test(response.config.method)) {
//                        		return $q.reject(response);
//                        	} else {
//                        		return response;
//                        	}
//                        }, (response.config.url.indexOf('/rest') !== -1 || response.config.url.indexOf('/api') !== -1   ? apiDelay : otherDelay));
//                    }, function(response) {
//                        return $q.reject(response);
//                    });
//                };
//            };
//            $httpProvider.responseInterceptors.push(delayHandlerFactory);

        }])
        .run(['$rootScope', '$location', '$http', '$log', 'AuthenticationSharedService', 'Session', 'USER_ROLES',
            function($rootScope, $location, $http, $log, AuthenticationSharedService, Session, USER_ROLES) {
                $rootScope.$on('$routeChangeStart', function (event, next) {
                    $rootScope.isAuthorized = AuthenticationSharedService.isAuthorized;
                    $rootScope.userRoles = USER_ROLES;
                    AuthenticationSharedService.valid(next.access.authorizedRoles);
                });

                // Call when the the client is confirmed
                $rootScope.$on('event:auth-loginConfirmed', function(data) {
                    $rootScope.authenticated = true;
                    if ($location.path() === "/login") {
                    	if (AuthenticationSharedService.isAuthorized(USER_ROLES.staffOrAdmin)) {
                    		$location.path('/adminDashboard').replace();
                    	} else {
                    		$location.path('/dashboard').replace();
                    	}
                    }
                });

                // Call when the 401 response is returned by the server
                $rootScope.$on('event:auth-loginRequired', function(rejection) {
                    Session.invalidate();
                    $rootScope.authenticated = false;

                    if ($location.path() !== "/" &&
                    		$location.path() !== "" &&
                    		$location.path() !== "/register" &&
                    		// FIXME MB is there a better way to register anonymous pages?
                    		$location.path() !== "/requestPasswordReset" &&
                    		$location.path() !== "/resetPassword" &&
                    		$location.path().indexOf("/viewPackage") == -1 &&
                    		$location.path() !== "/viewPackages" &&
                    		$location.path() !== "/emailVerification" &&
                            $location.path() !== "/activate") {
                        $location.path('/login').replace();
                    }
                });

                // Call when the 403 response is returned by the server
                $rootScope.$on('event:auth-notAuthorized', function(rejection) {
                    $rootScope.errorMessage = 'errors.403';
                    $location.path('/error').replace();
                });

                // Call when the user logs out
                $rootScope.$on('event:auth-loginCancelled', function() {
                    $location.path('');
                });
        }]);
<|endoftext|>


<commit_before>$(".document").ready(function() {

  let data = {
    sequence: null,
    compSeq: [],
    humanSeq: [],
    ms: [800, 400, 200],
    colors: ['green', 'red', 'yellow', 'blue'],
    turns: 0
  };

  let controller = {
    init: function() {
      view.init();
    },
    play: function() {
      data.compSeq.push(data.sequence[data.turns]);
      data.turns++;
      console.log("compSeq", data.compSeq, "turns", data.turns);
      // Add function: Check for winner, call victory() and return true
      simon.playSeq(data.compSeq);
    },
    start: function() {
      data.sequence = simon.sequence();
      controller.play();
    },
    strict: function() {
      $('#strict-display').toggleClass('strict-on');
    }
  };

  let events = {
     activateEvents: function() {
      // $('#test').on('click', controller.init);
      $('#start-button').on('mousedown', controller.start);
      $('#strict-button').on('click', controller.strict);
      $('#green').on('mousedown', press.green);
      $('#red').on('mousedown', press.red);
      $('#yellow').on('mousedown', press.yellow);
      $('#blue').on('mousedown', press.blue);
    },
    deactivateEvents: function() {
      $('#start-button').off('click');
      $('#strict-button').off('click');
      $('#green').off('mousedown');
      $('#red').off('mousedown');
      $('#yellow').off('mousedown');
      $('#blue').off('mousedown');
    },
    togglePower: function() {
      this.checked ? events.activateEvents() : events.deactivateEvents();
    }
  };

  let press = {
    green: function() {
      let that = this;
      let greenSound = document.getElementById('green-sound');
      let newSound = greenSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200);
    },

    red: function() {
      let that = this;
      let redSound = document.getElementById('red-sound');
      let newSound = redSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    yellow: function() {
      let that = this;
      let yellowSound = document.getElementById('yellow-sound');
      let newSound = yellowSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    blue: function() {
      let that = this;
      let blueSound = document.getElementById('blue-sound');
      let newSound = blueSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    removeOpacity: function(x) {
      $(x).removeClass('press').bind(press.green);
    }
  };

  // The 'simon' object contains helper functions
  let simon = {

    hasWinner: function(humArr, compArr){
      return humArr.every((value, index) => compArr[index] === humArr[index]);
    },

    translateToColor: function(num) {
      return data.colors[num];
    },

    playSeq: function(arr) { // arr is data.compSeq
      let sTime = 1000;
      events.deactivateEvents();
      $.each(arr, function(index, value){

      });
    },

    sequence: function() {
      //Return an array of 20 numbers between 0 and 3
      let arr = new Array(20)
      for (let i = 0; i < arr.length; i++) {
        let rand = Math.floor(Math.random() * 4);
        arr[i] = rand;
      }
      return arr;
    },

    regGame: (function() {
      if (data.humanMoves > 20) {
        simon.victory;
        return;
      } else {

      }
    }())
  }

  let view = {
    init: function() {
      $('#power').change(events.togglePower);
    }
  };

  controller.init();
});
<commit_msg>Add playSeq setTimeout function<commit_after>$(".document").ready(function() {

  let data = {
    sequence: null,
    compSeq: [],
    humanSeq: [],
    ms: [800, 400, 200],
    colors: ['green', 'red', 'yellow', 'blue'],
    turns: 0
  };

  let controller = {
    init: function() {
      view.init();
    },
    play: function() {
      data.compSeq.push(data.sequence[data.turns]);
      data.turns++;
      console.log("compSeq", data.compSeq, "turns", data.turns);
      // Add function: Check for winner, call victory() and return true
      simon.playSeq(data.compSeq);
    },
    start: function() {
      data.sequence = simon.sequence();
      controller.play();
    },
    strict: function() {
      $('#strict-display').toggleClass('strict-on');
    }
  };

  let events = {
     activateEvents: function() {
      // $('#test').on('click', controller.init);
      $('#start-button').on('mousedown', controller.start);
      $('#strict-button').on('click', controller.strict);
      $('#green').on('mousedown', press.green);
      $('#red').on('mousedown', press.red);
      $('#yellow').on('mousedown', press.yellow);
      $('#blue').on('mousedown', press.blue);
    },
    deactivateEvents: function() {
      $('#start-button').off('click');
      $('#strict-button').off('click');
      $('#green').off('mousedown');
      $('#red').off('mousedown');
      $('#yellow').off('mousedown');
      $('#blue').off('mousedown');
    },
    togglePower: function() {
      this.checked ? events.activateEvents() : events.deactivateEvents();
    }
  };

  let press = {
    green: function() {
      let that = this;
      let greenSound = document.getElementById('green-sound');
      let newSound = greenSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200);
    },

    red: function() {
      let that = this;
      let redSound = document.getElementById('red-sound');
      let newSound = redSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    yellow: function() {
      let that = this;
      let yellowSound = document.getElementById('yellow-sound');
      let newSound = yellowSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    blue: function() {
      let that = this;
      let blueSound = document.getElementById('blue-sound');
      let newSound = blueSound.cloneNode();
      newSound.play();
      $(this).addClass('press');
      setTimeout(() => {press.removeOpacity(that)}, 200)
    },

    removeOpacity: function(x) {
      $(x).removeClass('press').bind(press.green);
    }
  };

  // The 'simon' object contains helper functions
  let simon = {

    hasWinner: function(humArr, compArr){
      return humArr.every((value, index) => compArr[index] === humArr[index]);
    },

    translateToColor: function(num) {
      return data.colors[num];
    },

    playSeq: function(arr) { // arr is data.compSeq
      // Adjust playback speed, depending on number of turns
      if (data.turns < 10) {
        let sTime = data.ms[0];
      } else if (data.turns > 9 && data.turns < 15) {
        let sTime = data.ms[1];
      } else {
        let sTime = data.ms[2];
      }
      let sTime = data.ms[0];
      events.deactivateEvents();
      $.each(arr, function(index, value){
        console.log("value", value, 'index', index);
        setTimeout(function seqTimer() {
          simon.pushButton(value);
        }, (index + 1) * sTime);
      });
    },

    pushButton: function(value, index, array) {
      console.log(value, index, array);
      if (value === 0) press.green();
      else if (value === 1) press.red();
      else if (value === 2) press.yellow();
      else press.blue();
    },

    sequence: function() {
      //Return an array of 20 numbers between 0 and 3
      let arr = new Array(20)
      for (let i = 0; i < arr.length; i++) {
        let rand = Math.floor(Math.random() * 4);
        arr[i] = rand;
      }
      return arr;
    },

    regGame: (function() {
      if (data.humanMoves > 20) {
        simon.victory;
        return;
      } else {

      }
    }())
  }

  let view = {
    init: function() {
      $('#power').change(events.togglePower);
    }
  };

  controller.init();
});
<|endoftext|>


<commit_before>	var firebase = require('firebase');

	var constFile = process.argv[2]
	var constStr = './'+constFile
	var constants = require(constStr)
	var test = require('./test')

	firebase.initializeApp({
  		serviceAccount: constants.serviceAccount,
  		databaseURL: constants.databaseURL
	});

	var db = firebase.database();

	var ref = db.ref();
	var weight = ref.child('trainingWeights');
	var params = ref.child('parameters');
	var users = ref.child('users');

	var D = constants.D;
	var maxWeightBatchSize = 1;
	var maxGradBatchSize = constants.maxGradBatchSize;
	var c = constants.naughtRate;
	var eps = constants.eps;
	var K = constants.K;
	var descentAlg = constants.descentAlg;
	var testType = constants.testType;
	var testFreq = constants.testFrequency;
	var nh = 200;

	var testNum = 0;
	var changeiter = 0;
	var D = constants.D;
	var weightBatchSize = 0;
	var weightBatch = [];
	var gradBatchSize = 0;
	var gradBatch = [];
	var iter = 1;
	var learningRate = c;

	var auth = firebase.auth();
	var token = auth.createCustomToken("Server");

	//reset weights to 0 for testing, initialize learning rate matrices
	var length = D;
	if (K > 2){
		length = D*K;}
	if (constants.lossFunction = 'SoftmaxNN'){
		length = D*nh + nh + nh*nh + nh + nh*K + K;}
	var adaG = new Array(length);
	var rms = new Array(length);

	var zeroWeight = new Array(length);
	for(i = 0; i < length; i++){
		zeroWeight[i] = 0;
		adaG[i] = 0;
		rms[i] = 0;}
	weight.update({
		weights: zeroWeight,
		iteration: iter
		});
	console.log('zeroes set');

	//send parameters to clients
	params.update({
		paramIter: constants.paramIter,
		L: constants.L,
		noiseScale: constants.noiseScale,
		noiseDistribution: constants.noiseDistribution,
		K: K,
		lossFunction: constants.lossFunction,
		labelSource: constants.labelSource,
		featureSource: constants.featureSource,
		D: D,
		N: constants.N,
		clientBatchSize: constants.clientBatchSize
		})
	console.log('parameters set');

	var currentWeight;
	var currentIter;

	weight.on("value", function(snapshot, prevChildKey) {
		var currentWeights = snapshot.val();
		currentWeight = currentWeights.weights;
		currentIter = currentWeights.iteration;
	});

	users.on("child_changed", function(snapshot) {
		changeiter++;
  		var user = snapshot.val();
        	var grad = user.gradients;
		var processed = user.gradientProcessed;
		var userWeightIter = user.weightIter;
		var userParamIter = user.paramIter;
		var uid = snapshot.key;
		var userID = users.child(uid);
		if(uid && !processed){
			if(userWeightIter == iter && userParamIter == constants.paramIter){
				addToGradBatch(grad);
			}

			userID.update({
				gradientProcessed: true
				});
		}

    });

function addToGradBatch(gradient){
	gradBatch.push(gradient);
	gradBatchSize++;
	if(gradBatchSize == maxGradBatchSize){
		var avgGradient = [];
		for(i = 0; i < gradient.length; i++){
			var sum = 0;
			for(j = 0; j < maxGradBatchSize; j++){
				sum += gradBatch[j][i];
				}
			avgGradient[i] = sum/maxGradBatchSize;
			}
		gradBatchSize = 0;
		gradBatch = [];

		var newWeight = [];
		if(descentAlg=='constant'){
			learningRate = c;
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		if(descentAlg=='simple'){
			learningRate = c/iter;
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='sqrt'){
			learningRate = c/Math.sqrt(iter);
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='adagrad'){
			for (i = 0; i < length; i++) {
				adaG[i] += gradient[i]*gradient[i];
				learningRate = c/Math.sqrt(adaG[i]+eps);
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='rmsProp'){
			for (i = 0; i < length; i++) {
				rms[i] = 0.9*rms[i] + 0.1*gradient[i]*gradient[i];
				learningRate = c/Math.sqrt(rms[i]+eps);
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}

		addToWeightBatch(newWeight);

	}
}

function addToWeightBatch(weightArray){
	weightBatch.push(weightArray);
	weightBatchSize++;
	if(weightBatchSize == maxWeightBatchSize){
		var newWeight = [];
		for(i = 0; i < weightArray.length; i++){
			var sum = 0;
			for(j = 0; j < maxWeightBatchSize; j++){
				sum += weightBatch[j][i];
				}
			newWeight[i] = sum/maxWeightBatchSize;
			}

		testNum++;
		if(testNum == testFreq && testType == 'multiTest'){
			testNum = 0;
			//console.log('Weight iteration ',iter)
			test.multiTest(newWeight);}
		if(testNum == testFreq && testType == 'binary'){
			testNum = 0;
			console.log('Weight iteration ',iter)
			test.binaryTest(newWeight);}

		iter++;
		weight.update({
			iteration: iter
			});
		weight.update({
			weights: newWeight
			});
		weightBatchSize = 0;
		weightBatch = [];
	}
}

<commit_msg>Update crowdML-server.js<commit_after>	var firebase = require('firebase');

	var constFile = process.argv[2]
	var constStr = './'+constFile
	var constants = require(constStr)
	var test = require('./test')

	firebase.initializeApp({
  		serviceAccount: constants.serviceAccount,
  		databaseURL: constants.databaseURL
	});

	var db = firebase.database();

	var ref = db.ref();
	var weight = ref.child('trainingWeights');
	var params = ref.child('parameters');
	var users = ref.child('users');

	var D = constants.D;
	var maxWeightBatchSize = 1;
	var maxGradBatchSize = constants.maxGradBatchSize;
	var c = constants.naughtRate;
	var eps = constants.eps;
	var K = constants.K;
	var descentAlg = constants.descentAlg;
	var testType = constants.testType;
	var testFreq = constants.testFrequency;
	var nh = 200;

	var testNum = 0;
	var changeiter = 0;
	var D = constants.D;
	var weightBatchSize = 0;
	var weightBatch = [];
	var gradBatchSize = 0;
	var gradBatch = [];
	var iter = 1;
	var learningRate = c;

	var auth = firebase.auth();
	var token = auth.createCustomToken("Server");

	//reset weights to 0 for testing, initialize learning rate matrices
	var length = D;
	if (K > 2){
		length = D*K;}
	if (constants.lossFunction = 'SoftmaxNN'){
		length = D*nh + nh + nh*nh + nh + nh*K + K;}
	var adaG = new Array(length);
	var rms = new Array(length);

	var zeroWeight = new Array(length);
	for(i = 0; i < length; i++){
		zeroWeight[i] = 0;
		adaG[i] = 0;
		rms[i] = 0;}
	weight.update({
		weights: zeroWeight,
		iteration: iter
		});
	console.log('zeroes set');

	//send parameters to clients
	params.update({
		paramIter: constants.paramIter,
		L: constants.L,
		noiseScale: constants.noiseScale,
		noiseDistribution: constants.noiseDistribution,
		K: K,
		lossFunction: constants.lossFunction,
		labelSource: constants.labelSource,
		featureSource: constants.featureSource,
		D: D,
		N: constants.N,
		clientBatchSize: constants.clientBatchSize
		})
	console.log('parameters set');

	var currentWeight;
	var currentIter;

	weight.on("value", function(snapshot, prevChildKey) {
		var currentWeights = snapshot.val();
		currentWeight = currentWeights.weights;
		currentIter = currentWeights.iteration;
	});

	users.on("child_changed", function(snapshot) {
		changeiter++;
  		var user = snapshot.val();
        	var grad = user.gradients;
		var processed = user.gradientProcessed;
		var userWeightIter = user.weightIter;
		var userParamIter = user.paramIter;
		var uid = snapshot.key;
		var userID = users.child(uid);
		if(uid && !processed){
			if(userWeightIter == iter && userParamIter == constants.paramIter){
				addToGradBatch(grad);
			}

			userID.update({
				gradientProcessed: true
				});
		}

    });

function addToGradBatch(gradient){
	gradBatch.push(gradient);
	gradBatchSize++;
	if(gradBatchSize == maxGradBatchSize){
		var avgGradient = [];
		for(i = 0; i < gradient.length; i++){
			var sum = 0;
			for(j = 0; j < maxGradBatchSize; j++){
				sum += gradBatch[j][i];
				}
			avgGradient[i] = sum/maxGradBatchSize;
			}
		gradBatchSize = 0;
		gradBatch = [];

		var newWeight = [];
		if(descentAlg=='constant'){
			learningRate = c;
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		if(descentAlg=='simple'){
			learningRate = c/iter;
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='sqrt'){
			learningRate = c/Math.sqrt(iter);
			for (i = 0; i < length; i++) {
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='adagrad'){
			for (i = 0; i < length; i++) {
				adaG[i] += gradient[i]*gradient[i];
				learningRate = c/Math.sqrt(adaG[i]+eps);
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}
		else if(descentAlg=='rmsProp'){
			for (i = 0; i < length; i++) {
				rms[i] = 0.9*rms[i] + 0.1*gradient[i]*gradient[i];
				learningRate = c/Math.sqrt(rms[i]+eps);
				newWeight[i] = currentWeight[i] - (learningRate * gradient[i]);
			}
		}

		addToWeightBatch(newWeight);

	}
}

function addToWeightBatch(weightArray){
	weightBatch.push(weightArray);
	weightBatchSize++;
	if(weightBatchSize == maxWeightBatchSize){
		var newWeight = [];
		for(i = 0; i < weightArray.length; i++){
			var sum = 0;
			for(j = 0; j < maxWeightBatchSize; j++){
				sum += weightBatch[j][i];
				}
			newWeight[i] = sum/maxWeightBatchSize;
			}

		testNum++;
		if(testNum == testFreq && testType == 'multiTest'){
			testNum = 0;
			//console.log('Weight iteration ',iter)
			test.multiTest(newWeight);}
		if(testNum == testFreq && testType == 'binary'){
			testNum = 0;
			console.log('Weight iteration ',iter)
			test.binaryTest(newWeight);}
		if(testNum == testFreq && testType == 'NNTest'){
			testNum = 0;
			console.log('Weight iteration ',iter)
			test.NNTest(newWeight);}

		iter++;
		weight.update({
			iteration: iter
			});
		weight.update({
			weights: newWeight
			});
		weightBatchSize = 0;
		weightBatch = [];
	}
}

<|endoftext|>


<commit_before>/*global yaajs*/
define(function(require, exports, module) {
  var simple = require('data/simple-plugin!./flux');

  var ctx = module.ctx;
  var Module = module.constructor;

  return function (expect) {

    describe(module.id, function () {
      afterEach(function () {
        ctx.constructor.remove("my ctx");
      });

      it("uses normalizeId by default", function () {
        expect(simple).to.be("simple flux");
      });

      it("handles errors", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        myCtx.require('data/error-plugin!foo', function () {
          done(new Error("unexpected"));
        }, function (error) {
          try {
            expect(error.message).to.be("Module: data/error-plugin!foo - foo");
            done();
          } catch(ex) {
            done(ex);
          }
        });
      });

      it("can double require a plugin", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var count = 2;
        myCtx.require('data/simple-plugin!foo', assertOk);

        myCtx.require('data/simple-plugin!foo', assertOk);

        function assertOk(result) {
          try {
            expect(result).to.be("simple foo");
            --count || done();
          }
          catch (ex) {
            done(ex);
          }
        }

      });

      it("maps un-normalized correctly", function () {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var pmod = new Module(myCtx, 'foo');
        var caller = new Module(myCtx, 'baz');
        var loadCount = 0;
        pmod.exports = {load: function (name, req, onLoad) {
          ++loadCount;
        }};
        var plugin = new Module.Plugin(pmod);
        var myMod = plugin.fetch("./unnorm", caller);
        var myMod2 = plugin.fetch("unnorm");
        expect(myCtx.resolvingCount).to.be(4);
        expect(myMod.id).to.equal('');
        expect(plugin.waiting['baz']['./unnorm'][0]).to.be(caller);
        expect(plugin.waiting['baz']['./unnorm'][1]).to.be(myMod);
        expect(plugin.waiting['']['unnorm'][0]).to.be(undefined);
        expect(plugin.waiting['']['unnorm'][1]).to.be(myMod2);

        plugin.ready();

        expect(loadCount).to.equal(1);

        expect(myCtx.resolvingCount).to.equal(4);
        expect(myCtx.depCount).to.equal(0);
      });

      it("calls callbacks", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var waitCount = 2;
        myCtx.require('data/foo-plugin!junk/here/fuzz', function (fuzz) {
          try {
            expect(fuzz).to.eql("hello fuzz");
            --waitCount || done();
          } catch(ex) {
            done(ex);
          }
        }, done);

        myCtx.require('data/foo-plugin', function (plugin) {
          var oCtx = Module.currentCtx;
          try {
            Module.currentCtx = myCtx;
            define("foo5", ['data/foo-plugin!fuzz'], function (fuzz1) {
              try {
                expect(fuzz1).to.eql("hello fuzz");
                expect(Module.currentCtx).to.be(myCtx);
                --waitCount || done();
              } catch(ex) {
                done(ex);
              }
            });
            var fuzz = myCtx.modules['data/foo-plugin!fuzz'];
            fuzz.delayLoad();
          } finally {
            Module.currentCtx = oCtx;
          }
        });
      });
    });
  };
});
<commit_msg>test unloads on error<commit_after>/*global yaajs*/
define(function(require, exports, module) {
  var simple = require('data/simple-plugin!./flux');

  var ctx = module.ctx;
  var Module = module.constructor;

  return function (expect) {

    describe(module.id, function () {
      afterEach(function () {
        ctx.constructor.remove("my ctx");
      });

      it("uses normalizeId by default", function () {
        expect(simple).to.be("simple flux");
      });

      it("handles errors", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        myCtx.require('data/error-plugin!foo', function () {
          done(new Error("unexpected"));
        }, function (error) {
          try {
            expect(error.message).to.be("Module: data/error-plugin!foo - foo");
            setTimeout(function () {
              try {
                expect(myCtx.modules['data/error-plugin!foo']).to.be(undefined);
                done();
              } catch(ex) {
                done(ex);
              }
            }, 0);
          } catch(ex) {
            done(ex);
          }
        });
      });

      it("can double require a plugin", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var count = 2;
        myCtx.require('data/simple-plugin!foo', assertOk);

        myCtx.require('data/simple-plugin!foo', assertOk);

        function assertOk(result) {
          try {
            expect(result).to.be("simple foo");
            --count || done();
          }
          catch (ex) {
            done(ex);
          }
        }

      });

      it("maps un-normalized correctly", function () {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var pmod = new Module(myCtx, 'foo');
        var caller = new Module(myCtx, 'baz');
        var loadCount = 0;
        pmod.exports = {load: function (name, req, onLoad) {
          ++loadCount;
        }};
        var plugin = new Module.Plugin(pmod);
        var myMod = plugin.fetch("./unnorm", caller);
        var myMod2 = plugin.fetch("unnorm");
        expect(myCtx.resolvingCount).to.be(4);
        expect(myMod.id).to.equal('');
        expect(plugin.waiting['baz']['./unnorm'][0]).to.be(caller);
        expect(plugin.waiting['baz']['./unnorm'][1]).to.be(myMod);
        expect(plugin.waiting['']['unnorm'][0]).to.be(undefined);
        expect(plugin.waiting['']['unnorm'][1]).to.be(myMod2);

        plugin.ready();

        expect(loadCount).to.equal(1);

        expect(myCtx.resolvingCount).to.equal(4);
        expect(myCtx.depCount).to.equal(0);
      });

      it("calls callbacks", function (done) {
        var myCtx = new ctx.constructor({context: 'my ctx', baseUrl: ctx.baseUrl});
        var waitCount = 2;
        myCtx.require('data/foo-plugin!junk/here/fuzz', function (fuzz) {
          try {
            expect(fuzz).to.eql("hello fuzz");
            --waitCount || done();
          } catch(ex) {
            done(ex);
          }
        }, done);

        myCtx.require('data/foo-plugin', function (plugin) {
          var oCtx = Module.currentCtx;
          try {
            Module.currentCtx = myCtx;
            define("foo5", ['data/foo-plugin!fuzz'], function (fuzz1) {
              try {
                expect(fuzz1).to.eql("hello fuzz");
                expect(Module.currentCtx).to.be(myCtx);
                --waitCount || done();
              } catch(ex) {
                done(ex);
              }
            });
            var fuzz = myCtx.modules['data/foo-plugin!fuzz'];
            fuzz.delayLoad();
          } finally {
            Module.currentCtx = oCtx;
          }
        });
      });
    });
  };
});
<|endoftext|>


<commit_before>/* global Path2D */

let is = require( '../../../is' );

let CRp = {};

CRp.drawNode = function( context, node, shiftToOriginWithBb, drawLabel ){
  let r = this;
  let nodeWidth, nodeHeight;
  let _p = node._private;
  let rs = _p.rscratch;
  let pos = node.position();

  if( !is.number( pos.x ) || !is.number( pos.y ) ){
    return; // can't draw node with undefined position
  }

  if( !node.visible() ){ return; }

  let parentOpacity = node.effectiveOpacity();

  let usePaths = r.usePaths();
  let path;
  let pathCacheHit = false;

  let padding = node.padding();

  nodeWidth = node.width() + 2 * padding;
  nodeHeight = node.height() + 2 * padding;

  //
  // setup shift

  let bb;
  if( shiftToOriginWithBb ){
    bb = shiftToOriginWithBb;

    context.translate( -bb.x1, -bb.y1 );
  }

  //
  // load bg image

  let bgImgProp = node.pstyle( 'background-image' );
  let urls = bgImgProp.value;
  let urlDefined = new Array( urls.length );
  let image = new Array( urls.length );
  let numImages = 0;
  for( let i = 0; i < urls.length; i++ ){
    let url = urls[i];
    let defd = urlDefined[i] = url != null && url !== 'none';

    if( defd ){
      let bgImgCrossOrigin = node.cy().style().getIndexedStyle(node, 'background-image-crossorigin', 'value', i);

      numImages++;

      // get image, and if not loaded then ask to redraw when later loaded
      image[i] = r.getCachedImage( url, bgImgCrossOrigin, function(){
        node.emitAndNotify('background');
      } );
    }
  }

  //
  // setup styles

  let darkness = node.pstyle('background-blacken').value;
  let borderWidth = node.pstyle('border-width').pfValue;
  let bgColor = node.pstyle('background-color').value;
  let bgOpacity = node.pstyle('background-opacity').value * parentOpacity;
  let borderColor = node.pstyle('border-color').value;
  let borderStyle = node.pstyle('border-style').value;
  let borderOpacity = node.pstyle('border-opacity').value * parentOpacity;

  context.lineJoin = 'miter'; // so borders are square with the node shape

  let setupShapeColor = ( bgOpy = bgOpacity ) => {
    r.fillStyle( context, bgColor[0], bgColor[1], bgColor[2], bgOpy );
  };

  let setupBorderColor = ( bdrOpy = borderOpacity ) => {
    r.strokeStyle( context, borderColor[0], borderColor[1], borderColor[2], bdrOpy );
  };

  //
  // setup shape

  let styleShape = node.pstyle('shape').strValue;
  let shapePts = node.pstyle('shape-polygon-points').pfValue;

  if( usePaths ){
    let pathCacheKey = styleShape + '$' + nodeWidth + '$' + nodeHeight + ( styleShape === 'polygon' ? '$' + shapePts.join('$') : '' );

    context.translate( pos.x, pos.y );

    if( rs.pathCacheKey === pathCacheKey ){
      path = rs.pathCache;
      pathCacheHit = true;
    } else {
      path = new Path2D();
      rs.pathCacheKey = pathCacheKey;
      rs.pathCache = path;
    }
  }

  let drawShape = () => {
    if( !pathCacheHit ){

      let npos = pos;

      if( usePaths ){
        npos = {
          x: 0,
          y: 0
        };
      }

      r.nodeShapes[ r.getNodeShape( node ) ].draw(
            ( path || context ),
            npos.x,
            npos.y,
            nodeWidth,
            nodeHeight );
    }

    if( usePaths ){
      context.fill( path );
    } else {
      context.fill();
    }
  };

  let drawImages = ( nodeOpacity = parentOpacity ) => {
    let prevBging = _p.backgrounding;
    let totalCompleted = 0;

    for( let i = 0; i < image.length; i++ ){
      if( urlDefined[i] && image[i].complete && !image[i].error ){
        totalCompleted++;
        r.drawInscribedImage( context, image[i], node, i, nodeOpacity );
      }
    }

    _p.backgrounding = !(totalCompleted === numImages);
    if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed
      node.updateStyle( false );
    }
  };

  let drawPie = ( redrawShape = false, pieOpacity = parentOpacity ) => {
    if( r.hasPie( node ) ){
      r.drawPie( context, node, pieOpacity );

      // redraw/restore path if steps after pie need it
      if( redrawShape ){

        if( !usePaths ){
          r.nodeShapes[ r.getNodeShape( node ) ].draw(
              context,
              pos.x,
              pos.y,
              nodeWidth,
              nodeHeight );
        }
      }
    }
  };

  let darken = ( darkenOpacity = parentOpacity ) => {
    let opacity = ( darkness > 0 ? darkness : -darkness ) * darkenOpacity;
    let c = darkness > 0 ? 0 : 255;

    if( darkness !== 0 ){
      r.fillStyle( context, c, c, c, opacity );

      if( usePaths ){
        context.fill( path );
      } else {
        context.fill();
      }
    }
  };

  let drawBorder = () => {
    if( borderWidth > 0 ){

      context.lineWidth = borderWidth;
      context.lineCap = 'butt';

      if( context.setLineDash ){ // for very outofdate browsers
        switch( borderStyle ){
          case 'dotted':
            context.setLineDash( [ 1, 1 ] );
            break;

          case 'dashed':
            context.setLineDash( [ 4, 2 ] );
            break;

          case 'solid':
          case 'double':
            context.setLineDash( [ ] );
            break;
        }
      }

      if( usePaths ){
        context.stroke( path );
      } else {
        context.stroke();
      }

      if( borderStyle === 'double' ){
        context.lineWidth = borderWidth / 3;

        let gco = context.globalCompositeOperation;
        context.globalCompositeOperation = 'destination-out';

        if( usePaths ){
          context.stroke( path );
        } else {
          context.stroke();
        }

        context.globalCompositeOperation = gco;
      }

      // reset in case we changed the border style
      if( context.setLineDash ){ // for very outofdate browsers
        context.setLineDash( [ ] );
      }

    }
  };

  let drawOverlay = () => {
    let overlayPadding = node.pstyle( 'overlay-padding' ).pfValue;
    let overlayOpacity = node.pstyle( 'overlay-opacity' ).value;
    let overlayColor = node.pstyle( 'overlay-color' ).value;

    if( overlayOpacity > 0 ){
      r.fillStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity );

      r.nodeShapes[ 'roundrectangle' ].draw(
        context,
        pos.x,
        pos.y,
        nodeWidth + overlayPadding * 2,
        nodeHeight + overlayPadding * 2
      );

      context.fill();
    }
  };

  let drawText = () => {
    r.drawElementText( context, node, drawLabel );
  };

  let ghost = node.pstyle('ghost').value === 'yes';

  if( ghost ){
    let gx = node.pstyle('ghost-offset-x').pfValue;
    let gy = node.pstyle('ghost-offset-y').pfValue;
    let ghostOpacity = node.pstyle('ghost-opacity').value;
    let effGhostOpacity = ghostOpacity * parentOpacity;

    context.translate( gx, gy );

    setupShapeColor( ghostOpacity * bgOpacity );
    drawShape();
    drawImages( effGhostOpacity );
    drawPie( darkness !== 0 || borderWidth !== 0 );
    darken( effGhostOpacity );
    setupBorderColor( ghostOpacity * borderOpacity );
    drawBorder();

    context.translate( -gx, -gy );
  }

  setupShapeColor();
  drawShape();
  drawImages();
  drawPie( darkness !== 0 || borderWidth !== 0 );
  darken();
  setupBorderColor();
  drawBorder();

  if( usePaths ){
    context.translate( -pos.x, -pos.y );
  }

  drawText();
  drawOverlay();

  //
  // clean up shift

  if( shiftToOriginWithBb ){
    context.translate( bb.x1, bb.y1 );
  }

};

// does the node have at least one pie piece?
CRp.hasPie = function( node ){
  node = node[0]; // ensure ele ref

  return node._private.hasPie;
};

CRp.drawPie = function( context, node, nodeOpacity, pos ){
  node = node[0]; // ensure ele ref
  pos = pos || node.position();

  let cyStyle = node.cy().style();
  let pieSize = node.pstyle( 'pie-size' );
  let x = pos.x;
  let y = pos.y;
  let nodeW = node.width();
  let nodeH = node.height();
  let radius = Math.min( nodeW, nodeH ) / 2; // must fit in node
  let lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]
  let usePaths = this.usePaths();

  if( usePaths ){
    x = 0;
    y = 0;
  }

  if( pieSize.units === '%' ){
    radius = radius * pieSize.pfValue;
  } else if( pieSize.pfValue !== undefined ){
    radius = pieSize.pfValue / 2;
  }

  for( let i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N
    let size = node.pstyle( 'pie-' + i + '-background-size' ).value;
    let color = node.pstyle( 'pie-' + i + '-background-color' ).value;
    let opacity = node.pstyle( 'pie-' + i + '-background-opacity' ).value * nodeOpacity;
    let percent = size / 100; // map integer range [0, 100] to [0, 1]

    // percent can't push beyond 1
    if( percent + lastPercent > 1 ){
      percent = 1 - lastPercent;
    }

    let angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise
    let angleDelta = 2 * Math.PI * percent;
    let angleEnd = angleStart + angleDelta;

    // ignore if
    // - zero size
    // - we're already beyond the full circle
    // - adding the current slice would go beyond the full circle
    if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){
      continue;
    }

    context.beginPath();
    context.moveTo( x, y );
    context.arc( x, y, radius, angleStart, angleEnd );
    context.closePath();

    this.fillStyle( context, color[0], color[1], color[2], opacity );

    context.fill();

    lastPercent += percent;
  }

};

module.exports = CRp;
<commit_msg>Revise node path caching #2028<commit_after>/* global Path2D */

let is = require('../../../is');
let util = require('../../../util');

let CRp = {};

CRp.drawNode = function( context, node, shiftToOriginWithBb, drawLabel ){
  let r = this;
  let nodeWidth, nodeHeight;
  let _p = node._private;
  let rs = _p.rscratch;
  let pos = node.position();

  if( !is.number( pos.x ) || !is.number( pos.y ) ){
    return; // can't draw node with undefined position
  }

  if( !node.visible() ){ return; }

  let parentOpacity = node.effectiveOpacity();

  let usePaths = r.usePaths();
  let path;
  let pathCacheHit = false;

  let padding = node.padding();

  nodeWidth = node.width() + 2 * padding;
  nodeHeight = node.height() + 2 * padding;

  //
  // setup shift

  let bb;
  if( shiftToOriginWithBb ){
    bb = shiftToOriginWithBb;

    context.translate( -bb.x1, -bb.y1 );
  }

  //
  // load bg image

  let bgImgProp = node.pstyle( 'background-image' );
  let urls = bgImgProp.value;
  let urlDefined = new Array( urls.length );
  let image = new Array( urls.length );
  let numImages = 0;
  for( let i = 0; i < urls.length; i++ ){
    let url = urls[i];
    let defd = urlDefined[i] = url != null && url !== 'none';

    if( defd ){
      let bgImgCrossOrigin = node.cy().style().getIndexedStyle(node, 'background-image-crossorigin', 'value', i);

      numImages++;

      // get image, and if not loaded then ask to redraw when later loaded
      image[i] = r.getCachedImage( url, bgImgCrossOrigin, function(){
        node.emitAndNotify('background');
      } );
    }
  }

  //
  // setup styles

  let darkness = node.pstyle('background-blacken').value;
  let borderWidth = node.pstyle('border-width').pfValue;
  let bgColor = node.pstyle('background-color').value;
  let bgOpacity = node.pstyle('background-opacity').value * parentOpacity;
  let borderColor = node.pstyle('border-color').value;
  let borderStyle = node.pstyle('border-style').value;
  let borderOpacity = node.pstyle('border-opacity').value * parentOpacity;

  context.lineJoin = 'miter'; // so borders are square with the node shape

  let setupShapeColor = ( bgOpy = bgOpacity ) => {
    r.fillStyle( context, bgColor[0], bgColor[1], bgColor[2], bgOpy );
  };

  let setupBorderColor = ( bdrOpy = borderOpacity ) => {
    r.strokeStyle( context, borderColor[0], borderColor[1], borderColor[2], bdrOpy );
  };

  //
  // setup shape

  let styleShape = node.pstyle('shape').strValue;
  let shapePts = node.pstyle('shape-polygon-points').pfValue;

  if( usePaths ){
    context.translate( pos.x, pos.y );

    let pathCache = r.nodePathCache = r.nodePathCache || [];

    let key = util.hashStrings(
      styleShape === 'polygon' ? styleShape + ',' + shapePts.join(',') : styleShape,
      '' + nodeHeight,
      '' + nodeWidth
    );

    let cachedPath = pathCache[ key ];

    if( cachedPath != null ){
      path = cachedPath;
      pathCacheHit = true;
    } else {
      path = new Path2D();
      pathCache[ key ] = path;
    }
  }

  let drawShape = () => {
    if( !pathCacheHit ){

      let npos = pos;

      if( usePaths ){
        npos = {
          x: 0,
          y: 0
        };
      }

      r.nodeShapes[ r.getNodeShape( node ) ].draw(
            ( path || context ),
            npos.x,
            npos.y,
            nodeWidth,
            nodeHeight );
    }

    if( usePaths ){
      context.fill( path );
    } else {
      context.fill();
    }
  };

  let drawImages = ( nodeOpacity = parentOpacity ) => {
    let prevBging = _p.backgrounding;
    let totalCompleted = 0;

    for( let i = 0; i < image.length; i++ ){
      if( urlDefined[i] && image[i].complete && !image[i].error ){
        totalCompleted++;
        r.drawInscribedImage( context, image[i], node, i, nodeOpacity );
      }
    }

    _p.backgrounding = !(totalCompleted === numImages);
    if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed
      node.updateStyle( false );
    }
  };

  let drawPie = ( redrawShape = false, pieOpacity = parentOpacity ) => {
    if( r.hasPie( node ) ){
      r.drawPie( context, node, pieOpacity );

      // redraw/restore path if steps after pie need it
      if( redrawShape ){

        if( !usePaths ){
          r.nodeShapes[ r.getNodeShape( node ) ].draw(
              context,
              pos.x,
              pos.y,
              nodeWidth,
              nodeHeight );
        }
      }
    }
  };

  let darken = ( darkenOpacity = parentOpacity ) => {
    let opacity = ( darkness > 0 ? darkness : -darkness ) * darkenOpacity;
    let c = darkness > 0 ? 0 : 255;

    if( darkness !== 0 ){
      r.fillStyle( context, c, c, c, opacity );

      if( usePaths ){
        context.fill( path );
      } else {
        context.fill();
      }
    }
  };

  let drawBorder = () => {
    if( borderWidth > 0 ){

      context.lineWidth = borderWidth;
      context.lineCap = 'butt';

      if( context.setLineDash ){ // for very outofdate browsers
        switch( borderStyle ){
          case 'dotted':
            context.setLineDash( [ 1, 1 ] );
            break;

          case 'dashed':
            context.setLineDash( [ 4, 2 ] );
            break;

          case 'solid':
          case 'double':
            context.setLineDash( [ ] );
            break;
        }
      }

      if( usePaths ){
        context.stroke( path );
      } else {
        context.stroke();
      }

      if( borderStyle === 'double' ){
        context.lineWidth = borderWidth / 3;

        let gco = context.globalCompositeOperation;
        context.globalCompositeOperation = 'destination-out';

        if( usePaths ){
          context.stroke( path );
        } else {
          context.stroke();
        }

        context.globalCompositeOperation = gco;
      }

      // reset in case we changed the border style
      if( context.setLineDash ){ // for very outofdate browsers
        context.setLineDash( [ ] );
      }

    }
  };

  let drawOverlay = () => {
    let overlayPadding = node.pstyle( 'overlay-padding' ).pfValue;
    let overlayOpacity = node.pstyle( 'overlay-opacity' ).value;
    let overlayColor = node.pstyle( 'overlay-color' ).value;

    if( overlayOpacity > 0 ){
      r.fillStyle( context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity );

      r.nodeShapes[ 'roundrectangle' ].draw(
        context,
        pos.x,
        pos.y,
        nodeWidth + overlayPadding * 2,
        nodeHeight + overlayPadding * 2
      );

      context.fill();
    }
  };

  let drawText = () => {
    r.drawElementText( context, node, drawLabel );
  };

  let ghost = node.pstyle('ghost').value === 'yes';

  if( ghost ){
    let gx = node.pstyle('ghost-offset-x').pfValue;
    let gy = node.pstyle('ghost-offset-y').pfValue;
    let ghostOpacity = node.pstyle('ghost-opacity').value;
    let effGhostOpacity = ghostOpacity * parentOpacity;

    context.translate( gx, gy );

    setupShapeColor( ghostOpacity * bgOpacity );
    drawShape();
    drawImages( effGhostOpacity );
    drawPie( darkness !== 0 || borderWidth !== 0 );
    darken( effGhostOpacity );
    setupBorderColor( ghostOpacity * borderOpacity );
    drawBorder();

    context.translate( -gx, -gy );
  }

  setupShapeColor();
  drawShape();
  drawImages();
  drawPie( darkness !== 0 || borderWidth !== 0 );
  darken();
  setupBorderColor();
  drawBorder();

  if( usePaths ){
    context.translate( -pos.x, -pos.y );
  }

  drawText();
  drawOverlay();

  //
  // clean up shift

  if( shiftToOriginWithBb ){
    context.translate( bb.x1, bb.y1 );
  }

};

// does the node have at least one pie piece?
CRp.hasPie = function( node ){
  node = node[0]; // ensure ele ref

  return node._private.hasPie;
};

CRp.drawPie = function( context, node, nodeOpacity, pos ){
  node = node[0]; // ensure ele ref
  pos = pos || node.position();

  let cyStyle = node.cy().style();
  let pieSize = node.pstyle( 'pie-size' );
  let x = pos.x;
  let y = pos.y;
  let nodeW = node.width();
  let nodeH = node.height();
  let radius = Math.min( nodeW, nodeH ) / 2; // must fit in node
  let lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]
  let usePaths = this.usePaths();

  if( usePaths ){
    x = 0;
    y = 0;
  }

  if( pieSize.units === '%' ){
    radius = radius * pieSize.pfValue;
  } else if( pieSize.pfValue !== undefined ){
    radius = pieSize.pfValue / 2;
  }

  for( let i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N
    let size = node.pstyle( 'pie-' + i + '-background-size' ).value;
    let color = node.pstyle( 'pie-' + i + '-background-color' ).value;
    let opacity = node.pstyle( 'pie-' + i + '-background-opacity' ).value * nodeOpacity;
    let percent = size / 100; // map integer range [0, 100] to [0, 1]

    // percent can't push beyond 1
    if( percent + lastPercent > 1 ){
      percent = 1 - lastPercent;
    }

    let angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise
    let angleDelta = 2 * Math.PI * percent;
    let angleEnd = angleStart + angleDelta;

    // ignore if
    // - zero size
    // - we're already beyond the full circle
    // - adding the current slice would go beyond the full circle
    if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){
      continue;
    }

    context.beginPath();
    context.moveTo( x, y );
    context.arc( x, y, radius, angleStart, angleEnd );
    context.closePath();

    this.fillStyle( context, color[0], color[1], color[2], opacity );

    context.fill();

    lastPercent += percent;
  }

};

module.exports = CRp;
<|endoftext|>