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

	// Declare app level module which depends on filters, and services
	angular.module('isaac.router', [
        'ui.router',
	])

	.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

        var getLoggedInPromise = function($rootScope) {
                    return $rootScope.user.$promise.catch(function(r) {
                        if (r.status == 401)
                            return Promise.reject("require_login");
                        return Promise.reject("Something went wrong:", r);
                    });
        }

        getLoggedInPromise['$inject'] = ["$rootScope"];

        /*
         * Function that can be used to ensure that a user belongs to one of a set of roles.
         * If the current user does not belong to a supplied role the promise will be rejected.
         *
         */
        var getRolePromiseInjectableFunction = function(roles) {
            var result = function($rootScope) {
                return getLoggedInPromise($rootScope).then(function(u){
                    if (roles.indexOf(u.role) > -1) {
                        return Promise.resolve(u);
                    } else {
                        return Promise.reject("This route requires the user to have one of the following roles: " + roles);
                    }
                })
            }
            result["$inject"] = ['$rootScope']
            return result;
        }

        $urlRouterProvider.when("", "/");
        $urlRouterProvider.otherwise(function($injector, $location) {
            var $state = $injector.get("$state");
            $state.go("404", {target: $location.url()});
        });

        var genericPageState = function(url, id) {
            return {
                url: url,
                resolve: {
                    "page": ["api", function(api) {
                        return api.pages.get({id: id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/generic_page.html",
                        controller: "GenericPageController",
                    }
                }
            };
        }

        var staticPageState = function(url, state, controller) {
            return {
                url: url,
                views: {
                    "body": {
                        templateUrl: "/partials/states/" + state + ".html",
                        controller: controller
                    },
                },
            }
        }

        $stateProvider
            .state('home', staticPageState("/", "home", "HomePageController"))
            .state('about', genericPageState("/about", "about_us_index"))
            .state('teachers', genericPageState("/teachers", "mission_teachers"))
            .state('mission', genericPageState("/mission", "mission"))
            .state('mission_teachers', genericPageState("/mission_teachers", "mission_teachers"))
            .state('mission_students', genericPageState("/mission_students", "mission_students"))
            .state('events', genericPageState("/events", "events_index"))
            .state('glossary', genericPageState("/glossary", "glossary"))
            .state('cookies', genericPageState("/cookies", "cookie_policy"))
            .state('apply_uni', genericPageState("/apply_uni", "apply_uni"))
            .state('solving_problems', genericPageState("/solving_problems", "solving_problems"))
            .state('extraordinary_problems', genericPageState("/extraordinary_problems", "extraordinary_problems_index"))
	        .state('challenge_problems', genericPageState("/challenge_problems", "challenge_problems_index"))
            .state('bios', genericPageState("/bios", "bios"))
            .state('why_physics', genericPageState("/why_physics", "why_physics"))
	        .state('privacy', genericPageState("/privacy", "privacy_policy"))
            .state('fast_track_14', genericPageState("/fast_track_14", "fast_track_14_index"))
            .state('physics_skills_14', genericPageState("/physics_skills_14", "physics_skills_14_index"))

	        .state('contact', {
		        url: "/contact",
		        views: {
			        "body": {
				        templateUrl: "/partials/states/contact.html",
				        controller: "ContactController",
			        }
		        }
	        })

            .state('conceptIndex', {
                url: "/concepts?page",
                resolve: {
                    "conceptList" : ['api', function(api){
                        return api.getConceptList().$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/concept_index.html",
                        controller: "ConceptIndexController",
                    }
                }
            })
            .state('questionIndex', {
                url: "/questions?page",
                resolve: {
                    "pageIndex" :['$stateParams', function($stateParams){
                        return parseInt($stateParams.page || "1") - 1;
                    }],
                    "list" : ['api', 'pageIndex', function(api, pageIndex){
                        return api.getQuestionList(pageIndex).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/question_index.html",
                        controller: "QuestionIndexController",
                    }
                }
            })

            .state('concept', {
                url: "/concepts/:id",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.conceptPages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/concept.html",
                        controller: "ConceptPageController",
                    }
                }
            })

            .state('question', {
                url: "/questions/:id?board",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.questionPages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/question.html",
                        controller: "QuestionPageController",
                    }
                }
            })
            .state('pages', {
                url: "/pages/:id",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.pages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/generic_page.html",
                        controller: ["$scope", "page", function($scope, page) {
                            $scope.title = "Content object: " + page.id;
                            $scope.doc = page;
                        }]
                    }
                }
            })
            .state('contentErrors', {
                url: "/admin/content_errors",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.contentProblems.get().$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/content_error.html",
                        controller: "ContentErrorController",
                    }
                }
            })
            .state('login', {
                url: "/login?target",
                views: {
                    "body": {
                        templateUrl: "/partials/states/login_page.html",
                        controller: "LoginPageController",
                    }
                }
            })
	        .state('resetPassword', {
		        url: "/resetpassword/*token",
		        views: {
			        "body": {
				        templateUrl: "/partials/states/reset_password.html",
				        controller: "ResetPasswordPageController",
			        }
		        }
	        })
            .state('boards', {
                url: "/boards",
                resolve: {
                    requireLogin: getLoggedInPromise
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/my_boards.html",
                        controller: "MyBoardsPageController",
                    }
                }
            })
            .state('board', {
                url: "/board/:id",
                onEnter: ["$stateParams", "$location", function($stateParams, $location) {
                    $location.url("/#" + $stateParams.id);
                    throw "Prevent entering board redirect state."
                }],
            })
            .state('searchResults', {
                url: "/search?query&types&page",
                resolve: {
                    "query" :['$stateParams', function($stateParams){
                        return $stateParams.query;
                    }],

                    "types" :['$stateParams', function($stateParams){
                        if ($stateParams.types != null && $stateParams.types.length > 0) {
                            return $stateParams.types.split(",");
                        } else {
                            return [];
                        }
                    }],

                    "pageIndex" :['$stateParams', function($stateParams){
                        return parseInt($stateParams.page || "1") - 1;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/search_results.html",
                        controller: "SearchController",
                    }
                },
                reloadOnSearch: false,
            })
            .state('logout', {
                url: "/logout",
                resolve: {
                    done: ["auth", function(auth) {
                        window.foo = auth.logout();
                        return window.foo;
                    }],
                },
                onEnter: ["$state", function($state) {
                    document.location.href = "/";
                }]
            })
            .state('shareLink', {
                url: "/s/:shortCode",
                onEnter: ["$stateParams", "api", function($stateParams, api) {
                    var redirectURL = "http://goo.gl/" + $stateParams.shortCode;
                    var doRedirect = function(){
                        document.location.href = redirectURL;
                    }

                    api.logger.log({
                        type : "USE_SHARE_LINK",
                        shortURL : redirectURL,
                    }).$promise.then(function(){
                        doRedirect();
                    }).catch(function(){
                        doRedirect();
                    })
                }]
            })

            .state('404', {
                params: ["target"],
                views: {
                    "body": {
                        templateUrl: "/partials/states/404.html",
                        controller: ["$scope", "$stateParams", function($scope, $stateParams) {
                            $scope.target = $stateParams.target;
                        }],
                    },
                },

            })
            .state('403', {
                params: ["target"],
                views: {
                    "body": {
                        templateUrl: "/partials/states/403.html",
                        controller: ["$scope", "$stateParams", function($scope, $stateParams) {
                            $scope.target = $stateParams.target;
                        }],
                    },
                },
            })

	        .state('accountSettings', {
		        url: "/account?next&userId",
                resolve: {
                    "userOfInterest" : ["$stateParams", "api", function($stateParams, api) {
                        if ($stateParams.userId) {
                            return api.adminUserSearch.get({"userId" : $stateParams.userId})
                        } else {
                            return null;
                        }
                    }],
                    requireLogin: getLoggedInPromise,
                },
		        views: {
			        "body": {
				        templateUrl: "/partials/states/account_settings.html",
				        controller: "AccountSettingsPageController",
			        }
		        }
	        })

	        .state('register', {
		        url: "/register",
                resolve: {
                    "userOfInterest" : function(){return undefined},
                },
		        views: {
			        "body": {
				        templateUrl: "/partials/states/register.html",
				        controller: "AccountSettingsPageController",
			        }
		        }
	        })

            .state('authCallback', {
                url: "/auth/:provider/callback",
                onEnter: ["$stateParams", "$location", "auth", function($stateParams, $location, auth) {
                    console.debug("Auth callback from", $stateParams.provider, "with params:", $location.search());

                    auth.providerCallback($stateParams.provider, $location.search());
                }]
            })

            .state('authError', {
                url: "/auth_error?errorMessage&statusText",
                views: {
                    "body": {
                        templateUrl: "/partials/states/auth_error.html",
                        controller: "AuthErrorPageController",
                    }
                }
            })

            .state('admin', {
                url: "/admin",
                resolve: {
                    requireRole: getRolePromiseInjectableFunction(["ADMIN", "STAFF", "CONTENT_EDITOR"]),
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/admin.html",
                        controller: "AdminPageController",
                    }
                }
            })

             .state('gameEditor', {
                url: "/game_builder",
                resolve: {
                    requireRole: getRolePromiseInjectableFunction(["ADMIN", "TEACHER", "CONTENT_EDITOR"]),
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/game_board_editor.html",
                        controller: "GameEditorControllers",
                    }
                }
            })

            .state('groupManagment', {
                url: "/groups",
                resolve: {
                    requireLogin: getLoggedInPromise,
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/group_management.html",
                        controller: "GroupManagmentPageController",
                    }
                }
            })

            .state('assignBoards', {
                url: "/set_assignments",
                resolve: {
                    requireLogin: getLoggedInPromise,
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/assign_boards.html",
                    }
                }
            })
	}])

    .run(['$rootScope', '$state', function($rootScope, $state) {
        $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
            console.warn("State change error:", error);

            if (error == "require_login")
                $state.go('login', {target: $state.href(toState, toParams)});

            if (error == "require_role")
                $state.go('403', {target: $state.href(toState, toParams)});

            if (error.status == 404)
                $state.go('404', {target: $state.href(toState, toParams)});
        });

    }])
})<commit_msg>Restricted groups page to content editors and admin for the moment as we don't want this live yet.<commit_after>/**
 * Copyright 2014 Ian Davies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
define(["angular-ui-router"], function() {

	// Declare app level module which depends on filters, and services
	angular.module('isaac.router', [
        'ui.router',
	])

	.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

        var getLoggedInPromise = function($rootScope) {
                    return $rootScope.user.$promise.catch(function(r) {
                        if (r.status == 401)
                            return Promise.reject("require_login");
                        return Promise.reject("Something went wrong:", r);
                    });
        }

        getLoggedInPromise['$inject'] = ["$rootScope"];

        /*
         * Function that can be used to ensure that a user belongs to one of a set of roles.
         * If the current user does not belong to a supplied role the promise will be rejected.
         *
         */
        var getRolePromiseInjectableFunction = function(roles) {
            var result = function($rootScope) {
                return getLoggedInPromise($rootScope).then(function(u){
                    if (roles.indexOf(u.role) > -1) {
                        return Promise.resolve(u);
                    } else {
                        return Promise.reject("This route requires the user to have one of the following roles: " + roles);
                    }
                })
            }
            result["$inject"] = ['$rootScope']
            return result;
        }

        $urlRouterProvider.when("", "/");
        $urlRouterProvider.otherwise(function($injector, $location) {
            var $state = $injector.get("$state");
            $state.go("404", {target: $location.url()});
        });

        var genericPageState = function(url, id) {
            return {
                url: url,
                resolve: {
                    "page": ["api", function(api) {
                        return api.pages.get({id: id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/generic_page.html",
                        controller: "GenericPageController",
                    }
                }
            };
        }

        var staticPageState = function(url, state, controller) {
            return {
                url: url,
                views: {
                    "body": {
                        templateUrl: "/partials/states/" + state + ".html",
                        controller: controller
                    },
                },
            }
        }

        $stateProvider
            .state('home', staticPageState("/", "home", "HomePageController"))
            .state('about', genericPageState("/about", "about_us_index"))
            .state('teachers', genericPageState("/teachers", "mission_teachers"))
            .state('mission', genericPageState("/mission", "mission"))
            .state('mission_teachers', genericPageState("/mission_teachers", "mission_teachers"))
            .state('mission_students', genericPageState("/mission_students", "mission_students"))
            .state('events', genericPageState("/events", "events_index"))
            .state('glossary', genericPageState("/glossary", "glossary"))
            .state('cookies', genericPageState("/cookies", "cookie_policy"))
            .state('apply_uni', genericPageState("/apply_uni", "apply_uni"))
            .state('solving_problems', genericPageState("/solving_problems", "solving_problems"))
            .state('extraordinary_problems', genericPageState("/extraordinary_problems", "extraordinary_problems_index"))
	        .state('challenge_problems', genericPageState("/challenge_problems", "challenge_problems_index"))
            .state('bios', genericPageState("/bios", "bios"))
            .state('why_physics', genericPageState("/why_physics", "why_physics"))
	        .state('privacy', genericPageState("/privacy", "privacy_policy"))
            .state('fast_track_14', genericPageState("/fast_track_14", "fast_track_14_index"))
            .state('physics_skills_14', genericPageState("/physics_skills_14", "physics_skills_14_index"))

	        .state('contact', {
		        url: "/contact",
		        views: {
			        "body": {
				        templateUrl: "/partials/states/contact.html",
				        controller: "ContactController",
			        }
		        }
	        })

            .state('conceptIndex', {
                url: "/concepts?page",
                resolve: {
                    "conceptList" : ['api', function(api){
                        return api.getConceptList().$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/concept_index.html",
                        controller: "ConceptIndexController",
                    }
                }
            })
            .state('questionIndex', {
                url: "/questions?page",
                resolve: {
                    "pageIndex" :['$stateParams', function($stateParams){
                        return parseInt($stateParams.page || "1") - 1;
                    }],
                    "list" : ['api', 'pageIndex', function(api, pageIndex){
                        return api.getQuestionList(pageIndex).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/question_index.html",
                        controller: "QuestionIndexController",
                    }
                }
            })

            .state('concept', {
                url: "/concepts/:id",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.conceptPages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/concept.html",
                        controller: "ConceptPageController",
                    }
                }
            })

            .state('question', {
                url: "/questions/:id?board",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.questionPages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/question.html",
                        controller: "QuestionPageController",
                    }
                }
            })
            .state('pages', {
                url: "/pages/:id",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.pages.get({id: $stateParams.id}).$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/generic_page.html",
                        controller: ["$scope", "page", function($scope, page) {
                            $scope.title = "Content object: " + page.id;
                            $scope.doc = page;
                        }]
                    }
                }
            })
            .state('contentErrors', {
                url: "/admin/content_errors",
                resolve: {
                    "page": ["api", "$stateParams", function(api, $stateParams) {
                        return api.contentProblems.get().$promise;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/content_error.html",
                        controller: "ContentErrorController",
                    }
                }
            })
            .state('login', {
                url: "/login?target",
                views: {
                    "body": {
                        templateUrl: "/partials/states/login_page.html",
                        controller: "LoginPageController",
                    }
                }
            })
	        .state('resetPassword', {
		        url: "/resetpassword/*token",
		        views: {
			        "body": {
				        templateUrl: "/partials/states/reset_password.html",
				        controller: "ResetPasswordPageController",
			        }
		        }
	        })
            .state('boards', {
                url: "/boards",
                resolve: {
                    requireLogin: getLoggedInPromise
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/my_boards.html",
                        controller: "MyBoardsPageController",
                    }
                }
            })
            .state('board', {
                url: "/board/:id",
                onEnter: ["$stateParams", "$location", function($stateParams, $location) {
                    $location.url("/#" + $stateParams.id);
                    throw "Prevent entering board redirect state."
                }],
            })
            .state('searchResults', {
                url: "/search?query&types&page",
                resolve: {
                    "query" :['$stateParams', function($stateParams){
                        return $stateParams.query;
                    }],

                    "types" :['$stateParams', function($stateParams){
                        if ($stateParams.types != null && $stateParams.types.length > 0) {
                            return $stateParams.types.split(",");
                        } else {
                            return [];
                        }
                    }],

                    "pageIndex" :['$stateParams', function($stateParams){
                        return parseInt($stateParams.page || "1") - 1;
                    }]
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/search_results.html",
                        controller: "SearchController",
                    }
                },
                reloadOnSearch: false,
            })
            .state('logout', {
                url: "/logout",
                resolve: {
                    done: ["auth", function(auth) {
                        window.foo = auth.logout();
                        return window.foo;
                    }],
                },
                onEnter: ["$state", function($state) {
                    document.location.href = "/";
                }]
            })
            .state('shareLink', {
                url: "/s/:shortCode",
                onEnter: ["$stateParams", "api", function($stateParams, api) {
                    var redirectURL = "http://goo.gl/" + $stateParams.shortCode;
                    var doRedirect = function(){
                        document.location.href = redirectURL;
                    }

                    api.logger.log({
                        type : "USE_SHARE_LINK",
                        shortURL : redirectURL,
                    }).$promise.then(function(){
                        doRedirect();
                    }).catch(function(){
                        doRedirect();
                    })
                }]
            })

            .state('404', {
                params: ["target"],
                views: {
                    "body": {
                        templateUrl: "/partials/states/404.html",
                        controller: ["$scope", "$stateParams", function($scope, $stateParams) {
                            $scope.target = $stateParams.target;
                        }],
                    },
                },

            })
            .state('403', {
                params: ["target"],
                views: {
                    "body": {
                        templateUrl: "/partials/states/403.html",
                        controller: ["$scope", "$stateParams", function($scope, $stateParams) {
                            $scope.target = $stateParams.target;
                        }],
                    },
                },
            })

	        .state('accountSettings', {
		        url: "/account?next&userId",
                resolve: {
                    "userOfInterest" : ["$stateParams", "api", function($stateParams, api) {
                        if ($stateParams.userId) {
                            return api.adminUserSearch.get({"userId" : $stateParams.userId})
                        } else {
                            return null;
                        }
                    }],
                    requireLogin: getLoggedInPromise,
                },
		        views: {
			        "body": {
				        templateUrl: "/partials/states/account_settings.html",
				        controller: "AccountSettingsPageController",
			        }
		        }
	        })

	        .state('register', {
		        url: "/register",
                resolve: {
                    "userOfInterest" : function(){return undefined},
                },
		        views: {
			        "body": {
				        templateUrl: "/partials/states/register.html",
				        controller: "AccountSettingsPageController",
			        }
		        }
	        })

            .state('authCallback', {
                url: "/auth/:provider/callback",
                onEnter: ["$stateParams", "$location", "auth", function($stateParams, $location, auth) {
                    console.debug("Auth callback from", $stateParams.provider, "with params:", $location.search());

                    auth.providerCallback($stateParams.provider, $location.search());
                }]
            })

            .state('authError', {
                url: "/auth_error?errorMessage&statusText",
                views: {
                    "body": {
                        templateUrl: "/partials/states/auth_error.html",
                        controller: "AuthErrorPageController",
                    }
                }
            })

            .state('admin', {
                url: "/admin",
                resolve: {
                    requireRole: getRolePromiseInjectableFunction(["ADMIN", "STAFF", "CONTENT_EDITOR"]),
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/admin.html",
                        controller: "AdminPageController",
                    }
                }
            })

             .state('gameEditor', {
                url: "/game_builder",
                resolve: {
                    requireRole: getRolePromiseInjectableFunction(["ADMIN", "TEACHER", "CONTENT_EDITOR"]),
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/game_board_editor.html",
                        controller: "GameEditorControllers",
                    }
                }
            })

            .state('groupManagment', {
                url: "/groups",
                resolve: {
                    //requireLogin: getLoggedInPromise,
                    requireRole: getRolePromiseInjectableFunction(["ADMIN", "CONTENT_EDITOR"]), // temporary fix to stop people using it.
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/group_management.html",
                        controller: "GroupManagmentPageController",
                    }
                }
            })

            .state('assignBoards', {
                url: "/set_assignments",
                resolve: {
                    requireLogin: getLoggedInPromise,
                },
                views: {
                    "body": {
                        templateUrl: "/partials/states/assign_boards.html",
                    }
                }
            })
	}])

    .run(['$rootScope', '$state', function($rootScope, $state) {
        $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
            console.warn("State change error:", error);

            if (error == "require_login")
                $state.go('login', {target: $state.href(toState, toParams)});

            if (error == "require_role")
                $state.go('403', {target: $state.href(toState, toParams)});

            if (error.status == 404)
                $state.go('404', {target: $state.href(toState, toParams)});
        });

    }])
})<|endoftext|>


<commit_before>/**
 * @constructor
 */
function Background() {
  this.entriesToOpen_ = [];
  this.windows_ = [];
}

/**
 * @return {boolean}
 * True if the system window frame should be shown. It is on the systems where
 * borderless window can't be dragged or resized.
 */
Background.prototype.ifShowFrame_ = function() {
  var version = parseInt(navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
  var os = 'other';
  if (navigator.appVersion.indexOf('Linux') != -1) {
    os = 'linux';
  } else if (navigator.appVersion.indexOf('CrOS') != -1) {
    os = 'cros';
  } else if (navigator.appVersion.indexOf('Mac OS X') != -1) {
    os = 'mac';
  }

  return os === 'linux' && version < 27 ||
         os === 'mac' && version < 25;
};

/**
 * @param {Object.<string, Object>} launchData
 * Handle onLaunch event.
 */
Background.prototype.launch = function(launchData) {
  var options = {
    frame: (this.ifShowFrame_() ? 'chrome' : 'none'),
    minWidth: 400,
    minHeight: 400,
    width: 700,
    height: 700,
    left: 0,
    top: 0
  };

  var entries = [];
  if (launchData && launchData['items']) {
    for (var i = 0; i < launchData['items'].length; i++) {
      entries.push(launchData['items'][i]['entry']);
    }
  }

  if (entries.length > 0 && this.windows_.length > 0) {
    console.log('Opening files in existing window.');
    this.windows_[0].openEntries(entries);
  } else {
    this.entriesToOpen_.push.apply(this.entriesToOpen_, entries);
    console.log('Files to open:', this.entriesToOpen_);
    chrome.app.window.create('index.html', options, function(win) {
      console.log('Window opened:', win);
      win.onClosed.addListener(this.onWindowClosed.bind(this, win));
    }.bind(this));
  }
};

/**
 * @param {Window} win
 * Handle onClosed.
 */
Background.prototype.onWindowClosed = function(win) {
  console.log('Window closed:', win);
  if (!win.contentWindow || !win.contentWindow.textDrive)
    return;
  var td = win.contentWindow.textDrive;
  for (var i = 0; i < this.windows_.length; i++) {
    if (td === this.windows_[i]) {
      this.windows_.splice(i, 1);
    }
  }

  var toSave = td.getFilesToSave();
  console.log('Got ' + toSave.length + ' files to save:', toSave);
  for (var i = 0; i < toSave.length; i++) {
    var entry = toSave[i].entry;
    var contents = toSave[i].contents;
    this.saveFile_(entry, contents);
  }
};

/**
 * @param {FileEntry} entry
 * @param {string} contents
 */
Background.prototype.saveFile_ = function(entry, contents) {
  var blob = new Blob([contents], {type: 'text/plain'});
  chrome.fileSystem.getWritableEntry(
      entry,
      function(entry2) {
        entry2.createWriter(function(writer) {
          writer.onerror = util.handleFSError;

          writer.onwriteend = function(e) {
            // File truncated.
            writer.onwriteend = function(e) {
              console.log('Saved', entry.name);
            };

            writer.write(blob);
          }.bind(this);

          writer.truncate(blob.size);
        }.bind(this));
      }.bind(this));
};

/**
 * @param {TextDrive} td
 * Called by the TextDrive object in the window when the window is ready.
 */
Background.prototype.onWindowReady = function(td) {
  this.windows_.push(td);
  td.setHasChromeFrame(this.ifShowFrame_());

  if (this.entriesToOpen_.length > 0) {
    td.openEntries(this.entriesToOpen_);
    this.entriesToOpen_ = [];
  } else {
    td.openNew();
  }
};

var background = new Background();
chrome.app.runtime.onLaunched.addListener(background.launch.bind(background));

/* Exports */
window['background'] = background;
Background.prototype['onWindowReady'] = Background.prototype.onWindowReady;
<commit_msg>Let Chrome decide where to place a new TextDrive window instead of always showing it in the top left corner.<commit_after>/**
 * @constructor
 */
function Background() {
  this.entriesToOpen_ = [];
  this.windows_ = [];
}

/**
 * @return {boolean}
 * True if the system window frame should be shown. It is on the systems where
 * borderless window can't be dragged or resized.
 */
Background.prototype.ifShowFrame_ = function() {
  var version = parseInt(navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
  var os = 'other';
  if (navigator.appVersion.indexOf('Linux') != -1) {
    os = 'linux';
  } else if (navigator.appVersion.indexOf('CrOS') != -1) {
    os = 'cros';
  } else if (navigator.appVersion.indexOf('Mac OS X') != -1) {
    os = 'mac';
  }

  return os === 'linux' && version < 27 ||
         os === 'mac' && version < 25;
};

/**
 * @param {Object.<string, Object>} launchData
 * Handle onLaunch event.
 */
Background.prototype.launch = function(launchData) {
  var options = {
    frame: (this.ifShowFrame_() ? 'chrome' : 'none'),
    minWidth: 400,
    minHeight: 400,
    width: 700,
    height: 700
  };

  var entries = [];
  if (launchData && launchData['items']) {
    for (var i = 0; i < launchData['items'].length; i++) {
      entries.push(launchData['items'][i]['entry']);
    }
  }

  if (entries.length > 0 && this.windows_.length > 0) {
    console.log('Opening files in existing window.');
    this.windows_[0].openEntries(entries);
  } else {
    this.entriesToOpen_.push.apply(this.entriesToOpen_, entries);
    console.log('Files to open:', this.entriesToOpen_);
    chrome.app.window.create('index.html', options, function(win) {
      console.log('Window opened:', win);
      win.onClosed.addListener(this.onWindowClosed.bind(this, win));
    }.bind(this));
  }
};

/**
 * @param {Window} win
 * Handle onClosed.
 */
Background.prototype.onWindowClosed = function(win) {
  console.log('Window closed:', win);
  if (!win.contentWindow || !win.contentWindow.textDrive)
    return;
  var td = win.contentWindow.textDrive;
  for (var i = 0; i < this.windows_.length; i++) {
    if (td === this.windows_[i]) {
      this.windows_.splice(i, 1);
    }
  }

  var toSave = td.getFilesToSave();
  console.log('Got ' + toSave.length + ' files to save:', toSave);
  for (var i = 0; i < toSave.length; i++) {
    var entry = toSave[i].entry;
    var contents = toSave[i].contents;
    this.saveFile_(entry, contents);
  }
};

/**
 * @param {FileEntry} entry
 * @param {string} contents
 */
Background.prototype.saveFile_ = function(entry, contents) {
  var blob = new Blob([contents], {type: 'text/plain'});
  chrome.fileSystem.getWritableEntry(
      entry,
      function(entry2) {
        entry2.createWriter(function(writer) {
          writer.onerror = util.handleFSError;

          writer.onwriteend = function(e) {
            // File truncated.
            writer.onwriteend = function(e) {
              console.log('Saved', entry.name);
            };

            writer.write(blob);
          }.bind(this);

          writer.truncate(blob.size);
        }.bind(this));
      }.bind(this));
};

/**
 * @param {TextDrive} td
 * Called by the TextDrive object in the window when the window is ready.
 */
Background.prototype.onWindowReady = function(td) {
  this.windows_.push(td);
  td.setHasChromeFrame(this.ifShowFrame_());

  if (this.entriesToOpen_.length > 0) {
    td.openEntries(this.entriesToOpen_);
    this.entriesToOpen_ = [];
  } else {
    td.openNew();
  }
};

var background = new Background();
chrome.app.runtime.onLaunched.addListener(background.launch.bind(background));

/* Exports */
window['background'] = background;
Background.prototype['onWindowReady'] = Background.prototype.onWindowReady;
<|endoftext|>


<commit_before>var entriesToOpen = [];
var instances = [];

function ifShowFrame() {
  var version = parseInt(navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
  var os = 'other';
  if (navigator.appVersion.indexOf('Linux') != -1) {
    os = 'linux';
  } else if (navigator.appVersion.indexOf('CrOS') != -1) {
    os = 'cros';
  }

  return (os === 'linux' && version < 26) ||
         (os === 'cros' && version < 24);
}

function launch(launchData) {
  var options = {
    frame: (ifShowFrame() ? 'chrome' : 'none'),
    minWidth: 400,
    minHeight: 400,
    width: 700,
    height: 750,
    left: 0,
    top: 0
  };

  var entries = [];
  if (launchData && launchData.items) {
    for (var i = 0; i < launchData.items.length; i++) {
      entries.push(launchData.items[i].entry);
    }
  }

  if (entries.length > 0 && instances.length > 0) {
    console.log('Opening files in existing window.');
    instances[0].openEntries(entries);
  } else {
    entriesToOpen.push.apply(entriesToOpen, entries);
    console.log('Files to open:', entriesToOpen);
    chrome.app.window.create('index.html', options, function(win) {
      console.log('Window opened:', win);
      win.onClosed.addListener(onWindowClosed.bind(undefined, win));
    });
  }
}

function onWindowClosed(win) {
  console.log('Window closed:', win);
  if (!win.contentWindow || !win.contentWindow.textDrive)
    return;
  var td = win.contentWindow.textDrive;
  for (var i = 0; i < instances.length; i++) {
    if (td === instances[i]) {
      instances.splice(i, 1);
    }
  }
};

function onWindowReady(td) {
  instances.push(td);
  td.setHasChromeFrame(ifShowFrame());
  openEntriesInWindow(td);
};

function openEntriesInWindow(td) {
  if (entriesToOpen.length > 0) {
    td.openEntries(entriesToOpen);
    entriesToOpen = [];
  } else {
    td.openNew();
  }
};

chrome.app.runtime.onLaunched.addListener(launch);
<commit_msg>Do not show window border on M23 ChromeOS.<commit_after>var entriesToOpen = [];
var instances = [];

function ifShowFrame() {
  var version = parseInt(navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
  var os = 'other';
  if (navigator.appVersion.indexOf('Linux') != -1) {
    os = 'linux';
  } else if (navigator.appVersion.indexOf('CrOS') != -1) {
    os = 'cros';
  }

  return os === 'linux' && version < 26;
}

function launch(launchData) {
  var options = {
    frame: (ifShowFrame() ? 'chrome' : 'none'),
    minWidth: 400,
    minHeight: 400,
    width: 700,
    height: 750,
    left: 0,
    top: 0
  };

  var entries = [];
  if (launchData && launchData.items) {
    for (var i = 0; i < launchData.items.length; i++) {
      entries.push(launchData.items[i].entry);
    }
  }

  if (entries.length > 0 && instances.length > 0) {
    console.log('Opening files in existing window.');
    instances[0].openEntries(entries);
  } else {
    entriesToOpen.push.apply(entriesToOpen, entries);
    console.log('Files to open:', entriesToOpen);
    chrome.app.window.create('index.html', options, function(win) {
      console.log('Window opened:', win);
      win.onClosed.addListener(onWindowClosed.bind(undefined, win));
    });
  }
}

function onWindowClosed(win) {
  console.log('Window closed:', win);
  if (!win.contentWindow || !win.contentWindow.textDrive)
    return;
  var td = win.contentWindow.textDrive;
  for (var i = 0; i < instances.length; i++) {
    if (td === instances[i]) {
      instances.splice(i, 1);
    }
  }
};

function onWindowReady(td) {
  instances.push(td);
  td.setHasChromeFrame(ifShowFrame());
  openEntriesInWindow(td);
};

function openEntriesInWindow(td) {
  if (entriesToOpen.length > 0) {
    td.openEntries(entriesToOpen);
    entriesToOpen = [];
  } else {
    td.openNew();
  }
};

chrome.app.runtime.onLaunched.addListener(launch);
<|endoftext|>


<commit_before>/**
 * constants
 */

let {NODE_ENV} = process.env

module.exports = {
  isDev: NODE_ENV === 'development',
  defaultLang: 'zh_cn'
}

<commit_msg>change default language to en_us<commit_after>/**
 * constants
 */

let {NODE_ENV} = process.env

module.exports = {
  isDev: NODE_ENV === 'development',
  defaultLang: 'en_us'
}

<|endoftext|>


<commit_before>"use strict";
const co = require('co');
const moment = require('moment');
const hashf = require('./../ucp/hashf');
const dos2unix = require('./../system/dos2unix');
const querablep = require('./../querablep');
const rules = require('./../rules/index');
const constants = require('./../constants');
const keyring = require('./../crypto/keyring');
const rawer = require('./../ucp/rawer');

let AUTOKILL_TIMEOUT_DELAY = 10 * 1000;
const TURN_DURATION_IN_MILLISEC = 1000;
const PAUSES_PER_TURN = 5;

let timeoutAutoKill = null;
let computing = querablep(Promise.resolve(null));
let askedStop = false;

// By default, we do not prefix the PoW by any number
let prefix = 0;

let signatureFunc, id, lastPub, lastSecret, currentCPU = 1;

process.on('uncaughtException', (err) => {
  console.error(err.stack || Error(err));
  process.send({error: err});
});

autoKillIfNoContact();

process.on('message', (message) => co(function*() {

  switch (message.command) {

    case 'state':
      answer(message, computing.isFulfilled() ? 'ready' : 'computing');
      break;

    case 'autokillTimeout':
      AUTOKILL_TIMEOUT_DELAY = message.value;
      answer(message, 'OK');
      break;

    case 'identify':
      lastPub = message.value.pubkey;
      id = message.value.identifier;
      answer(message, 'OK');
      break;

    case 'pubkey': answer(message, lastPub);    break;
    case 'id':     answer(message, id);         break;
    case 'cpu':    answer(message, currentCPU); break;
    case 'prefix': answer(message, prefix);     break;

    case 'newPoW':
      co(function*() {
        yield computing;
        const res = yield beginNewProofOfWork(message.value);
        answer(message, res);
      });
      break;

    case 'cancel':
      if (computing.isFulfilled()) {
        answer(message, 'ready');
      } else {
        askedStop = true;
        answer(message, 'cancelling');
      }
      break;

    case 'conf':
      if (message.value.cpu !== undefined) {
        currentCPU = message.value.cpu;
      }
      if (message.value.prefix !== undefined) {
        prefix = parseInt(message.value.prefix) * 10 * constants.NONCE_RANGE;
      }
      answer(message, { currentCPU, prefix });
      break;
  }

  // We received a message, we postpone the autokill protection trigger
  autoKillIfNoContact();

}));

function beginNewProofOfWork(stuff) {
  askedStop = false;
  computing = querablep(co(function*() {
    pSend({ powStatus: 'started block#' + stuff.block.number });
    let nonce = 0;
    let foundBlock = null;
    const conf = stuff.conf;
    const block = stuff.block;
    const nonceBeginning = stuff.nonceBeginning;
    const nbZeros = stuff.zeros;
    const pair = stuff.pair;
    const forcedTime = stuff.forcedTime;
    currentCPU = conf.cpu || constants.DEFAULT_CPU;
    prefix = conf.prefix || prefix;
    const highMark = stuff.highMark;
    let sigFunc = null;
    if (signatureFunc && lastSecret == pair.sec) {
      sigFunc = signatureFunc;
    }
    else {
      lastSecret = pair.sec;
      lastPub = pair.pub;
      sigFunc = keyring.Key(pair.pub, pair.sec).signSync;
    }
    signatureFunc = sigFunc;
    let pow = "", sig = "", raw = "";

    block.time = getBlockTime(block, conf, forcedTime);

    // Really start now
    let testsCount = 0;
    if (nbZeros == 0) {
      block.time = block.medianTime;
    }
    // Compute block's hash
    block.inner_hash = getBlockInnerHash(block);
    let found = false;
    let score = 0;
    let turn = 0;
    while (!found && !askedStop) {

      // We make a bunch of tests every second
      yield Promise.race([
        countDown(TURN_DURATION_IN_MILLISEC),
        co(function*() {
          try {

            /*****
             * A NEW TURN
             */
            // Prove
            let i = 0;
            const thisTurn = turn;
            const pausePeriod = score ? score / PAUSES_PER_TURN : 10; // number of pauses per turn
            // We limit the number of t
            const testsPerRound = score ? Math.floor(score * currentCPU) : 1000 * 1000 * 1000;
            // Time is updated regularly during the proof
            block.time = getBlockTime(block, conf, forcedTime);
            if (block.number == 0) {
              block.medianTime = block.time;
            }
            block.inner_hash = getBlockInnerHash(block);
            while(!found && i < testsPerRound && thisTurn == turn && !askedStop) {
              nonce++;
              // The final nonce is composed of 3 parts
              block.nonce = prefix + nonceBeginning + nonce;
              raw = dos2unix("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n");
              sig = dos2unix(sigFunc(raw));
              pow = hashf("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n" + sig + "\n").toUpperCase();
              let j = 0, charOK = true;
              while (j < nbZeros && charOK) {
                charOK = pow[j] == '0';
                j++;
              }
              if (charOK) {
                found = pow[nbZeros].match(new RegExp('[0-' + highMark + ']'));
              }
              if (!found && nbZeros > 0 && j - 1 >= constants.PROOF_OF_WORK.MINIMAL_TO_SHOW) {
                pSend({ pow: { pow: pow, block: block, nbZeros: nbZeros }});
              }
              if (!found) {
                i++;
                testsCount++;
                if (i % pausePeriod == 0) {
                  yield countDown(0); // Very low pause, just the time to process eventual end of the turn
                }
              }
            }
            if (!found) {
              if (turn > 0 && !score) {
                score = testsCount;
              }
              // We wait for main "while" countdown to end the turn. This gives of a bit of breath to the CPU (the amount
              // of "breath" depends on the "cpu" parameter.
              yield countDown(TURN_DURATION_IN_MILLISEC);
            }
          } catch (e) {
            console.error(e);
          }
        })
      ]);
      turn++;
    }
    block.hash = pow;
    block.signature = sig;
    if (askedStop) {
      askedStop = false;
      yield pSend({ pow: { canceled: true }});
      pSend({ powStatus: 'canceled block#' + block.number });
      pSend({ powStatus: 'ready' });
    } else {
      foundBlock = {
        pow: {
          block: block,
          testsCount: testsCount,
          pow: pow
        }
      };
      pSend({ powStatus: 'found' });
    }
    return foundBlock;
  }));
  return computing;
}

function countDown(duration) {
  return new Promise((resolve) => setTimeout(resolve, duration));
}

function getBlockInnerHash(block) {
  const raw = rawer.getBlockInnerPart(block);
  return hash(raw);
}

function hash(str) {
  return hashf(str).toUpperCase();
}

function getBlockTime (block, conf, forcedTime) {
  if (forcedTime) {
    return forcedTime;
  }
  const now = moment.utc().unix();
  const maxAcceleration = rules.HELPERS.maxAcceleration(block, conf);
  const timeoffset = block.number >= conf.medianTimeBlocks ? 0 : conf.rootoffset || 0;
  const medianTime = block.medianTime;
  const upperBound = block.number == 0 ? medianTime : Math.min(medianTime + maxAcceleration, now - timeoffset);
  return Math.max(medianTime, upperBound);
}

function answer(message, answer) {
  return new Promise(function (resolve, reject) {
    process.send({
      uuid: message.uuid,
      answer,
      pubkey: lastPub
    }, function (error) {
      !error && resolve();
      error && reject();
    });
  });
}

function pSend(stuff) {
  stuff.pubkey = lastPub;
  return new Promise(function (resolve, reject) {
    process.send(stuff, function (error) {
      !error && resolve();
      error && reject();
    });
  });
}

function autoKillIfNoContact() {
  if (timeoutAutoKill) {
    clearTimeout(timeoutAutoKill);
  }
  // If the timeout is not cleared in some way, the process exits
  timeoutAutoKill = setTimeout(() => {
    process.exit();
  }, AUTOKILL_TIMEOUT_DELAY);
}
<commit_msg>[fix] Engine prefix was incorrect<commit_after>"use strict";
const co = require('co');
const moment = require('moment');
const hashf = require('./../ucp/hashf');
const dos2unix = require('./../system/dos2unix');
const querablep = require('./../querablep');
const rules = require('./../rules/index');
const constants = require('./../constants');
const keyring = require('./../crypto/keyring');
const rawer = require('./../ucp/rawer');

let AUTOKILL_TIMEOUT_DELAY = 10 * 1000;
const TURN_DURATION_IN_MILLISEC = 1000;
const PAUSES_PER_TURN = 5;

let timeoutAutoKill = null;
let computing = querablep(Promise.resolve(null));
let askedStop = false;

// By default, we do not prefix the PoW by any number
let prefix = 0;

let signatureFunc, id, lastPub, lastSecret, currentCPU = 1;

process.on('uncaughtException', (err) => {
  console.error(err.stack || Error(err));
  process.send({error: err});
});

autoKillIfNoContact();

process.on('message', (message) => co(function*() {

  switch (message.command) {

    case 'state':
      answer(message, computing.isFulfilled() ? 'ready' : 'computing');
      break;

    case 'autokillTimeout':
      AUTOKILL_TIMEOUT_DELAY = message.value;
      answer(message, 'OK');
      break;

    case 'identify':
      lastPub = message.value.pubkey;
      id = message.value.identifier;
      answer(message, 'OK');
      break;

    case 'pubkey': answer(message, lastPub);    break;
    case 'id':     answer(message, id);         break;
    case 'cpu':    answer(message, currentCPU); break;
    case 'prefix': answer(message, prefix);     break;

    case 'newPoW':
      co(function*() {
        yield computing;
        const res = yield beginNewProofOfWork(message.value);
        answer(message, res);
      });
      break;

    case 'cancel':
      if (computing.isFulfilled()) {
        answer(message, 'ready');
      } else {
        askedStop = true;
        answer(message, 'cancelling');
      }
      break;

    case 'conf':
      if (message.value.cpu !== undefined) {
        currentCPU = message.value.cpu;
      }
      if (message.value.prefix !== undefined) {
        prefix = parseInt(message.value.prefix) * 10 * constants.NONCE_RANGE;
      }
      answer(message, { currentCPU, prefix });
      break;
  }

  // We received a message, we postpone the autokill protection trigger
  autoKillIfNoContact();

}));

function beginNewProofOfWork(stuff) {
  askedStop = false;
  computing = querablep(co(function*() {
    pSend({ powStatus: 'started block#' + stuff.block.number });
    let nonce = 0;
    let foundBlock = null;
    const conf = stuff.conf;
    const block = stuff.block;
    const nonceBeginning = stuff.nonceBeginning;
    const nbZeros = stuff.zeros;
    const pair = stuff.pair;
    const forcedTime = stuff.forcedTime;
    currentCPU = conf.cpu || constants.DEFAULT_CPU;
    prefix = parseInt(conf.prefix || prefix) * 10 * constants.NONCE_RANGE;
    const highMark = stuff.highMark;
    let sigFunc = null;
    if (signatureFunc && lastSecret == pair.sec) {
      sigFunc = signatureFunc;
    }
    else {
      lastSecret = pair.sec;
      lastPub = pair.pub;
      sigFunc = keyring.Key(pair.pub, pair.sec).signSync;
    }
    signatureFunc = sigFunc;
    let pow = "", sig = "", raw = "";

    block.time = getBlockTime(block, conf, forcedTime);

    // Really start now
    let testsCount = 0;
    if (nbZeros == 0) {
      block.time = block.medianTime;
    }
    // Compute block's hash
    block.inner_hash = getBlockInnerHash(block);
    let found = false;
    let score = 0;
    let turn = 0;
    while (!found && !askedStop) {

      // We make a bunch of tests every second
      yield Promise.race([
        countDown(TURN_DURATION_IN_MILLISEC),
        co(function*() {
          try {

            /*****
             * A NEW TURN
             */
            // Prove
            let i = 0;
            const thisTurn = turn;
            const pausePeriod = score ? score / PAUSES_PER_TURN : 10; // number of pauses per turn
            // We limit the number of t
            const testsPerRound = score ? Math.floor(score * currentCPU) : 1000 * 1000 * 1000;
            // Time is updated regularly during the proof
            block.time = getBlockTime(block, conf, forcedTime);
            if (block.number == 0) {
              block.medianTime = block.time;
            }
            block.inner_hash = getBlockInnerHash(block);
            while(!found && i < testsPerRound && thisTurn == turn && !askedStop) {
              nonce++;
              // The final nonce is composed of 3 parts
              block.nonce = prefix + nonceBeginning + nonce;
              raw = dos2unix("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n");
              sig = dos2unix(sigFunc(raw));
              pow = hashf("InnerHash: " + block.inner_hash + "\nNonce: " + block.nonce + "\n" + sig + "\n").toUpperCase();
              let j = 0, charOK = true;
              while (j < nbZeros && charOK) {
                charOK = pow[j] == '0';
                j++;
              }
              if (charOK) {
                found = pow[nbZeros].match(new RegExp('[0-' + highMark + ']'));
              }
              if (!found && nbZeros > 0 && j - 1 >= constants.PROOF_OF_WORK.MINIMAL_TO_SHOW) {
                pSend({ pow: { pow: pow, block: block, nbZeros: nbZeros }});
              }
              if (!found) {
                i++;
                testsCount++;
                if (i % pausePeriod == 0) {
                  yield countDown(0); // Very low pause, just the time to process eventual end of the turn
                }
              }
            }
            if (!found) {
              if (turn > 0 && !score) {
                score = testsCount;
              }
              // We wait for main "while" countdown to end the turn. This gives of a bit of breath to the CPU (the amount
              // of "breath" depends on the "cpu" parameter.
              yield countDown(TURN_DURATION_IN_MILLISEC);
            }
          } catch (e) {
            console.error(e);
          }
        })
      ]);
      turn++;
    }
    block.hash = pow;
    block.signature = sig;
    if (askedStop) {
      askedStop = false;
      yield pSend({ pow: { canceled: true }});
      pSend({ powStatus: 'canceled block#' + block.number });
      pSend({ powStatus: 'ready' });
    } else {
      foundBlock = {
        pow: {
          block: block,
          testsCount: testsCount,
          pow: pow
        }
      };
      pSend({ powStatus: 'found' });
    }
    return foundBlock;
  }));
  return computing;
}

function countDown(duration) {
  return new Promise((resolve) => setTimeout(resolve, duration));
}

function getBlockInnerHash(block) {
  const raw = rawer.getBlockInnerPart(block);
  return hash(raw);
}

function hash(str) {
  return hashf(str).toUpperCase();
}

function getBlockTime (block, conf, forcedTime) {
  if (forcedTime) {
    return forcedTime;
  }
  const now = moment.utc().unix();
  const maxAcceleration = rules.HELPERS.maxAcceleration(block, conf);
  const timeoffset = block.number >= conf.medianTimeBlocks ? 0 : conf.rootoffset || 0;
  const medianTime = block.medianTime;
  const upperBound = block.number == 0 ? medianTime : Math.min(medianTime + maxAcceleration, now - timeoffset);
  return Math.max(medianTime, upperBound);
}

function answer(message, answer) {
  return new Promise(function (resolve, reject) {
    process.send({
      uuid: message.uuid,
      answer,
      pubkey: lastPub
    }, function (error) {
      !error && resolve();
      error && reject();
    });
  });
}

function pSend(stuff) {
  stuff.pubkey = lastPub;
  return new Promise(function (resolve, reject) {
    process.send(stuff, function (error) {
      !error && resolve();
      error && reject();
    });
  });
}

function autoKillIfNoContact() {
  if (timeoutAutoKill) {
    clearTimeout(timeoutAutoKill);
  }
  // If the timeout is not cleared in some way, the process exits
  timeoutAutoKill = setTimeout(() => {
    process.exit();
  }, AUTOKILL_TIMEOUT_DELAY);
}
<|endoftext|>


<commit_before>var log = new Log('fuse.handlebars');
//TODO: create a different set of helpers for init parsing

var Handlebars = require('handlebars-v2.0.0.js').Handlebars;

var getScope = function (unit) {
    var jsFile = fuse.getFile(unit, '', '.js');
    var viewModel = {};
    if (jsFile.isExists()) {
        log.error(jsFile.getPath());
        viewModel = require(jsFile.getPath()).onRequest();
    }
    viewModel.app = {
        url: '/' + fuseState.appName
    };
    viewModel.self = {
        publicURL: '/' + fuseState.appName + '/public/' + unit,
        "class": unit + '-unit'
    };
    return viewModel;
};

Handlebars.innerZones = [];
Handlebars.innerZonesFromUnit = null;

Handlebars.registerHelper('defineZone', function (zoneName, zoneContent) {
    var result = '';
    var zone = Handlebars.Utils.escapeExpression(zoneName);
    fuseState.currentZone.push(zone);
    var unitsToRender = fuseState.zones[zone] || [];

    if (Handlebars.innerZones.length > 0) {
        unitsToRender = fuseState.zones[Handlebars.innerZones[0]] || [];
    }

    // if there is no one overriding, then display inline zone
    if (zoneContent['fn'] && unitsToRender.length == 0) {
        return zoneContent.fn(this).trim();
    }

    for (var i = 0; i < unitsToRender.length; i++) {
        var unit = unitsToRender[i];
        if (Handlebars.innerZonesFromUnit == null || Handlebars.innerZonesFromUnit.unitName == unit.unitName) {
            var template = fuse.getFile(unit.originUnitName || unit.unitName, '', '.hbs');
            log.debug('[' + requestId + '] for zone "' + zone + '" including template :"' + template.getPath() + '"');
            result += Handlebars.compileFile(template)(getScope(unit.unitName));
        }
    }

    // we go to inner zones if result is empty, what we should really do it
    // if matched zone is fully made of sub-zones. this is a hack to
    // make it easy to implement.
    if (result.trim().length == 0 && zoneContent['fn']) {
        Handlebars.innerZones.push(zoneName);
        for (i = 0; i < unitsToRender.length; i++) {
            unit = unitsToRender[i];
            Handlebars.innerZonesFromUnit = unit;
            result += zoneContent.fn(this).trim();
            Handlebars.innerZonesFromUnit = null;
        }
        Handlebars.innerZones.pop();
        return result;
    }

    fuseState.currentZone.pop();
    return new Handlebars.SafeString(result);
});

Handlebars.registerHelper('zone', function (zoneName, zoneContent) {
    var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1];
    if (currentZone == null) {
        return 'zone_' + zoneName;
    }

    // if it's exact zone match or if any in inner zone matches we render zone.
    // this second condition is a hack. what we should really do is to keep another stack,
    // and only match with the peek of that stack and always fill it with next in innerZone stack.
    if (zoneName == currentZone || Handlebars.innerZones.indexOf(zoneName) >= 0) {
        return zoneContent.fn(this).trim();
    } else {
        return '';
    }
});

Handlebars.registerHelper('layout', function (layoutName) {
    var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1];
    if (currentZone == null) {
        return 'layout_' + layoutName;
    } else {
        return '';
    }
});

Handlebars.registerHelper('unit', function (unitName) {
    //TODO warn when unspecified decencies are included.
    fuseState.currentZone.push('main');
    var template = fuse.getFile(unitName, '', '.hbs');
    log.info('[' + requestId + '] including "' + unitName + '"');
    var result = new Handlebars.SafeString(Handlebars.compileFile(template)(getScope(unitName)))
    fuseState.currentZone.pop();
    return result;
});

Handlebars.compileFile = function (file) {
    //TODO: remove this overloaded argument
    var f = (typeof file === 'string') ? new File(file) : file;

    if (!Handlebars.cache) {
        Handlebars.cache = {};
    }

    if (Handlebars.cache[f.getPath()] != null) {
        return Handlebars.cache[f.getPath()];
    }

    f.open('r');
    log.debug('[' + requestId + '] reading file "' + f.getPath() + '"');
    var content = f.readAll().trim();
    f.close();
    var compiled = Handlebars.compile(content);
    Handlebars.cache[f.getPath()] = compiled;
    return compiled;
};
<commit_msg>Fix to fuse<commit_after>var log = new Log('fuse.handlebars');
//TODO: create a different set of helpers for init parsing

var Handlebars = require('handlebars-v2.0.0.js').Handlebars;

var getScope = function (unit) {
    var jsFile = fuse.getFile(unit, '', '.js');
    var viewModel = {};
    if (jsFile.isExists()) {
        log.error(jsFile.getPath());
        viewModel = require(jsFile.getPath()).onRequest();
    }
    viewModel.app = {
        url: '/' + fuseState.appName
    };
    viewModel.self = {
        publicURL: '/' + fuseState.appName + '/public/' + unit,
        "class": unit + '-unit'
    };
    return viewModel;
};

Handlebars.innerZones = [];
Handlebars.innerZonesFromUnit = null;

Handlebars.registerHelper('defineZone', function (zoneName, zoneContent) {
    var result = '';
    var zone = Handlebars.Utils.escapeExpression(zoneName);
    fuseState.currentZone.push(zone);
    var unitsToRender = fuseState.zones[zone] || [];

    if (Handlebars.innerZones.length > 0) {
        unitsToRender = fuseState.zones[Handlebars.innerZones[0]] || [];
    }

    // if there is no one overriding, then display inline zone
    if (zoneContent['fn'] && unitsToRender.length == 0) {
        return zoneContent.fn(this).trim();
    }

    for (var i = 0; i < unitsToRender.length; i++) {
        var unit = unitsToRender[i];
        if (Handlebars.innerZonesFromUnit == null || Handlebars.innerZonesFromUnit.unitName == unit.unitName) {
            var template = fuse.getFile(unit.originUnitName || unit.unitName, '', '.hbs');
            log.debug('[' + requestId + '] for zone "' + zone + '" including template :"' + template.getPath() + '"');
            result += Handlebars.compileFile(template)(getScope(unit.unitName));
        }
    }

    // we go to inner zones if result is empty, what we should really do it
    // if matched zone is fully made of sub-zones. this is a hack to
    // make it easy to implement.
    if (result.trim().length == 0 && zoneContent['fn']) {
        Handlebars.innerZones.push(zoneName);
        for (i = 0; i < unitsToRender.length; i++) {
            unit = unitsToRender[i];
            Handlebars.innerZonesFromUnit = unit;
            result += zoneContent.fn(this).trim();
            Handlebars.innerZonesFromUnit = null;
        }
        Handlebars.innerZones.pop();
        return result;
    }

    fuseState.currentZone.pop();
    return new Handlebars.SafeString(result);
});

Handlebars.registerHelper('zone', function (zoneName, zoneContent) {
    var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1];
    if (currentZone == null) {
        return 'zone_' + zoneName + ' ';
    }

    // if it's exact zone match or if any in inner zone matches we render zone.
    // this second condition is a hack. what we should really do is to keep another stack,
    // and only match with the peek of that stack and always fill it with next in innerZone stack.
    if (zoneName == currentZone || Handlebars.innerZones.indexOf(zoneName) >= 0) {
        return zoneContent.fn(this).trim();
    } else {
        return '';
    }
});

Handlebars.registerHelper('layout', function (layoutName) {
    var currentZone = fuseState.currentZone[fuseState.currentZone.length - 1];
    if (currentZone == null) {
        return 'layout_' + layoutName;
    } else {
        return '';
    }
});

Handlebars.registerHelper('unit', function (unitName) {
    //TODO warn when unspecified decencies are included.
    fuseState.currentZone.push('main');
    var template = fuse.getFile(unitName, '', '.hbs');
    log.info('[' + requestId + '] including "' + unitName + '"');
    var result = new Handlebars.SafeString(Handlebars.compileFile(template)(getScope(unitName)))
    fuseState.currentZone.pop();
    return result;
});

Handlebars.compileFile = function (file) {
    //TODO: remove this overloaded argument
    var f = (typeof file === 'string') ? new File(file) : file;

    if (!Handlebars.cache) {
        Handlebars.cache = {};
    }

    if (Handlebars.cache[f.getPath()] != null) {
        return Handlebars.cache[f.getPath()];
    }

    f.open('r');
    log.debug('[' + requestId + '] reading file "' + f.getPath() + '"');
    var content = f.readAll().trim();
    f.close();
    var compiled = Handlebars.compile(content);
    Handlebars.cache[f.getPath()] = compiled;
    return compiled;
};
<|endoftext|>


<commit_before>// Rebuild all messages
//
'use strict';

const Promise  = require('bluebird');
const _        = require('lodash');
const Queue    = require('ido');

const CHUNKS_TO_ADD    = 100;
const CHUNKS_MIN_COUNT = 50;
const MSG_PER_CHUNK    = 100;

module.exports = function (N) {
  N.wire.on('init:jobs', function register_messages_rebuild() {
    // Iterator
    //
    N.queue.registerTask({
      name: 'messages_rebuild',
      pool: 'hard',
      baseClass: Queue.IteratorTemplate,
      taskID: () => 'messages_rebuild',

      iterate: Promise.coroutine(function* (state) {
        let active_chunks = this.children_created - this.children_finished;

        // Idle if we still have more than `CHUNKS_MIN_COUNT` chunks
        //
        if (active_chunks >= CHUNKS_MIN_COUNT) return {};

        // Fetch posts _id
        //
        let query = N.models.users.DlgMessage.find()
                        .where('_id').gte(this.args[0]) // min
                        .select('_id')
                        .sort({ _id: -1 })
                        .limit(MSG_PER_CHUNK * CHUNKS_TO_ADD)
                        .lean(true);

        // If state is present it is always smaller than max _id
        if (state) {
          query.where('_id').lt(state);
        } else {
          query.where('_id').lte(this.args[1]); // max
        }

        let msgs = yield query;

        // Check finished
        //
        if (!msgs.length) return;

        // Add chunks
        //
        let chunks = _.chunk(msgs.map(p => String(p._id)), MSG_PER_CHUNK)
                      .map(ids => N.queue.messages_rebuild_chunk(ids));

        return {
          tasks: chunks,
          state: String(msgs[msgs.length - 1]._id)
        };
      }),

      init: Promise.coroutine(function* () {
        // if no min _id
        if (this.args.length < 1 || !this.args[0]) {
          let min_topic = yield N.models.users.DlgMessage.findOne()
                                    .select('_id')
                                    .sort({ _id: 1 })
                                    .lean(true);

          this.args[0] = String(min_topic._id);
        }

        // if no max _id
        if (this.args.length < 2 || !this.args[1]) {
          let max_topic = yield N.models.users.DlgMessage.findOne()
                                    .select('_id')
                                    .sort({ _id: -1 })
                                    .lean(true);

          this.args[1] = String(max_topic._id);
        }

        let msg_count = yield N.models.users.DlgMessage.count()
                                  .where('_id').gte(this.args[0])
                                  .where('_id').lte(this.args[1]);

        this.total = Math.ceil(msg_count / MSG_PER_CHUNK);
      })
    });

    // Chunk
    //
    N.queue.registerTask({
      name: 'messages_rebuild_chunk',
      pool: 'hard',
      removeDelay: 3600,
      process: Promise.coroutine(function* (ids) {
        let start_time = Date.now();

        N.logger.info(`Rebuilding dialogs ${ids[0]}-${ids[ids.length - 1]} - ${ids.length} found`);

        yield Promise.map(
          ids,
          id => N.wire.emit('internal:users.message_rebuild', id)
                      .catch(err => N.logger.error('Failed to rebuild message id=' + id + ': ' + (err.stack || err))),
          // TODO: is this needed?
          { concurrency: 50 }
        );

        N.logger.info(`Rebuilding dialogs ${ids[0]}-${ids[ids.length - 1]} - finished (${
          ((Date.now() - start_time) / 1000).toFixed(1)
          }s)`);
      })
    });

    N.queue.on('task:progress:messages_rebuild', function (task_info) {
      N.live.debounce('admin.core.rebuild.messages', {
        uid:     task_info.uid,
        current: task_info.progress,
        total:   task_info.total
      });
    });

    N.queue.on('task:end:messages_rebuild', function (task_info) {
      N.live.emit('admin.core.rebuild.messages', {
        uid:      task_info.uid,
        finished: true
      });
    });
  });
};
<commit_msg>Reduce chunk size in rebuild task<commit_after>// Rebuild all messages
//
'use strict';

const Promise  = require('bluebird');
const _        = require('lodash');
const Queue    = require('ido');

const CHUNKS_TO_ADD    = 100;
const CHUNKS_MIN_COUNT = 50;
const MSG_PER_CHUNK    = 50;

module.exports = function (N) {
  N.wire.on('init:jobs', function register_messages_rebuild() {
    // Iterator
    //
    N.queue.registerTask({
      name: 'messages_rebuild',
      pool: 'hard',
      baseClass: Queue.IteratorTemplate,
      taskID: () => 'messages_rebuild',

      iterate: Promise.coroutine(function* (state) {
        let active_chunks = this.children_created - this.children_finished;

        // Idle if we still have more than `CHUNKS_MIN_COUNT` chunks
        //
        if (active_chunks >= CHUNKS_MIN_COUNT) return {};

        // Fetch posts _id
        //
        let query = N.models.users.DlgMessage.find()
                        .where('_id').gte(this.args[0]) // min
                        .select('_id')
                        .sort({ _id: -1 })
                        .limit(MSG_PER_CHUNK * CHUNKS_TO_ADD)
                        .lean(true);

        // If state is present it is always smaller than max _id
        if (state) {
          query.where('_id').lt(state);
        } else {
          query.where('_id').lte(this.args[1]); // max
        }

        let msgs = yield query;

        // Check finished
        //
        if (!msgs.length) return;

        // Add chunks
        //
        let chunks = _.chunk(msgs.map(p => String(p._id)), MSG_PER_CHUNK)
                      .map(ids => N.queue.messages_rebuild_chunk(ids));

        return {
          tasks: chunks,
          state: String(msgs[msgs.length - 1]._id)
        };
      }),

      init: Promise.coroutine(function* () {
        // if no min _id
        if (this.args.length < 1 || !this.args[0]) {
          let min_topic = yield N.models.users.DlgMessage.findOne()
                                    .select('_id')
                                    .sort({ _id: 1 })
                                    .lean(true);

          this.args[0] = String(min_topic._id);
        }

        // if no max _id
        if (this.args.length < 2 || !this.args[1]) {
          let max_topic = yield N.models.users.DlgMessage.findOne()
                                    .select('_id')
                                    .sort({ _id: -1 })
                                    .lean(true);

          this.args[1] = String(max_topic._id);
        }

        let msg_count = yield N.models.users.DlgMessage.count()
                                  .where('_id').gte(this.args[0])
                                  .where('_id').lte(this.args[1]);

        this.total = Math.ceil(msg_count / MSG_PER_CHUNK);
      })
    });

    // Chunk
    //
    N.queue.registerTask({
      name: 'messages_rebuild_chunk',
      pool: 'hard',
      removeDelay: 3600,
      process: Promise.coroutine(function* (ids) {
        let start_time = Date.now();

        N.logger.info(`Rebuilding dialogs ${ids[0]}-${ids[ids.length - 1]} - ${ids.length} found`);

        yield Promise.map(
          ids,
          id => N.wire.emit('internal:users.message_rebuild', id)
                      .catch(err => N.logger.error('Failed to rebuild message id=' + id + ': ' + (err.stack || err)))
        );

        N.logger.info(`Rebuilding dialogs ${ids[0]}-${ids[ids.length - 1]} - finished (${
          ((Date.now() - start_time) / 1000).toFixed(1)
          }s)`);
      })
    });

    N.queue.on('task:progress:messages_rebuild', function (task_info) {
      N.live.debounce('admin.core.rebuild.messages', {
        uid:     task_info.uid,
        current: task_info.progress,
        total:   task_info.total
      });
    });

    N.queue.on('task:end:messages_rebuild', function (task_info) {
      N.live.emit('admin.core.rebuild.messages', {
        uid:      task_info.uid,
        finished: true
      });
    });
  });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';

import * as FetchAPI from '../../fetch_data'

function ChangesetInfo({ index, push, pushId, visibility, onClick }) {
  const { author, node, desc } = push.changesets[index]
  // XXX: For author remove the email address
  // XXX: For desc display only the first line
  // XXX: linkify bug numbers
  // The tipmost changeset should always be visible
  const changesetClass = (index === 0 || visibility) ? 'changeset': 'hidden_changeset'
  const toggleText = (visibility) ? '[Collapse]' : '[Expand]'
  const numChangesets = push.changesets.length - 1
  return (

        {author.substring(0, 16)}

        {node.substring(0, 12)}

        {desc.substring(0, 30)}

        {(index === 0 && numChangesets > 0) ?
          {numChangesets} changesets in push -
            {toggleText}
            :

        }

  )
}

export class ChangesetsViewer extends Component {
  state = {
    'pushes': {},
    'errorMessage': '',
    'hiddenChangesets': {}
  }

  componentDidMount() {
    // XXX: If the fetched data is the same as in the state do
    //      no call setSate to prevent one more render
    FetchAPI.getJsonPushes(this.props.repoName).then(response =>
      response.json()
    ).then(text => {
      let hiddenChangesets = {}
      Object.keys(text.pushes).forEach(pushId => {
        hiddenChangesets[pushId] = false
      })
      this.setState({
        pushes: text.pushes,
        hiddenChangesets: hiddenChangesets
      })}
    ).catch(error => {
      this.setState({
        pushes: [],
        errorMessage: 'We have failed to fetch pushes. See the log console for more details'
      })
      console.error(error)
    })
  }

  toggleRowVisibility(pushId) {
    this.setState((prevState, props) => {
      let newHiddenChangesets = {}
      Object.assign(newHiddenChangesets, prevState.hiddenChangesets)
      newHiddenChangesets[pushId] = ! newHiddenChangesets[pushId]
      return {
        hiddenChangesets: newHiddenChangesets
      }
    })
  }

  render() {
    if (this.state.errorMessage) {
      return (
{this.state.errorMessage}
)
    } else {
      return (

              Author
              Changeset
              Description
              Collapsed csets

            {Object.keys(this.state.pushes).reverse().filter(pushId => {
              const csets = this.state.pushes[pushId].changesets
              if (csets[csets.length - 1].author !== 'ffxbld') {
                return this.state.pushes[pushId]
              }
            }).map(pushId => {
              const push = this.state.pushes[pushId]
              return push.changesets.map((cset, index) => {
                return (
                  <ChangesetInfo
                    key={push.node}
                    index={index}
                    push={push}
                    pushId={pushId}
                    visibility={this.state.hiddenChangesets[pushId]}
                    onClick={(event) => this.toggleRowVisibility(event.target.id)}
                  />
                )
              })
            })}

      )
    }
  }
}
<commit_msg>feat: link code coverage diff viewer<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router-dom'

import * as FetchAPI from '../../fetch_data'

function ChangesetInfo({ index, push, pushId, visibility, onClick }) {
  const { author, node, desc } = push.changesets[index]
  // XXX: For author remove the email address
  // XXX: For desc display only the first line
  // XXX: linkify bug numbers
  // The tipmost changeset should always be visible
  const changesetClass = (index === 0 || visibility) ? 'changeset': 'hidden_changeset'
  const toggleText = (visibility) ? '[Collapse]' : '[Expand]'
  const numChangesets = push.changesets.length - 1
  return (

        {author.substring(0, 16)}

        <Link to={`/changeset/${node}`}>
          {node.substring(0, 12)}
        </Link>

        {desc.substring(0, 30)}

        {(index === 0 && numChangesets > 0) ?
          {numChangesets} changesets in push -
            {toggleText}
            :

        }

  )
}

export class ChangesetsViewer extends Component {
  state = {
    'pushes': {},
    'errorMessage': '',
    'hiddenChangesets': {}
  }

  componentDidMount() {
    // XXX: If the fetched data is the same as in the state do
    //      no call setSate to prevent one more render
    FetchAPI.getJsonPushes(this.props.repoName).then(response =>
      response.json()
    ).then(text => {
      let hiddenChangesets = {}
      Object.keys(text.pushes).forEach(pushId => {
        hiddenChangesets[pushId] = false
      })
      this.setState({
        pushes: text.pushes,
        hiddenChangesets: hiddenChangesets
      })}
    ).catch(error => {
      this.setState({
        pushes: [],
        errorMessage: 'We have failed to fetch pushes. See the log console for more details'
      })
      console.error(error)
    })
  }

  toggleRowVisibility(pushId) {
    this.setState((prevState, props) => {
      let newHiddenChangesets = {}
      Object.assign(newHiddenChangesets, prevState.hiddenChangesets)
      newHiddenChangesets[pushId] = ! newHiddenChangesets[pushId]
      return {
        hiddenChangesets: newHiddenChangesets
      }
    })
  }

  render() {
    if (this.state.errorMessage) {
      return (
{this.state.errorMessage}
)
    } else {
      return (

              Author
              Changeset
              Description
              Collapsed csets

            {Object.keys(this.state.pushes).reverse().filter(pushId => {
              const csets = this.state.pushes[pushId].changesets
              if (csets[csets.length - 1].author !== 'ffxbld') {
                return this.state.pushes[pushId]
              }
            }).map(pushId => {
              const push = this.state.pushes[pushId]
              return push.changesets.map((cset, index) => {
                return (
                  <ChangesetInfo
                    key={push.node}
                    index={index}
                    push={push}
                    pushId={pushId}
                    visibility={this.state.hiddenChangesets[pushId]}
                    onClick={(event) => this.toggleRowVisibility(event.target.id)}
                  />
                )
              })
            })}

      )
    }
  }
}
<|endoftext|>


<commit_before>(function (B) {
    // B.multicastClient.log = function (msg) {
    //     console.log(msg);
    // }

    B.multicastClient.enforceEmitOrder = true;

    B.multicastClient.triggerEvents = [
        "ready", "test:success", "test:failure",
        "test:error", "test:timeout", "suite:end"];

    window.onerror = function (message) {
        B.multicastClient.emit("uncaughtException", {
            name: "UncaughtError", message: message
        });

        return true;
    };

    // TMP!!!
    buster.env = buster.env || {};
    buster.env.path = window.location.href;

    // Format assertion messages nicely
    B.assert.format = B.format.ascii;

    // Format log messages with unquoted strings
    // Means that log("One", "Two") -> "One Two", not "\"One\" \"Two\""
    var logFormatter = buster.create(B.format);
    logFormatter.quoteStrings = false;

    // Console and buster.log shorthand
    B.console = B.eventedLogger.create({
        formatter: buster.bind(logFormatter, "ascii")
    });

    B.log = buster.bind(B.console, "log");

    // Ship log messages over the wire
    B.console.on("log", function (msg) {
        B.multicastClient.emit("log", msg);
    });

    // Keep a reference to test cases and specs
    var contexts = [];
    B.addTestContext = function (context) { contexts.push(context); };
    B.testCase.onCreate = B.addTestContext;
    B.spec.describe.onCreate = B.addTestContext;

    // Listen to events from buster.assert to make the test runner count
    // assertions correctly
    function setUpAssertionCounting(runner) {
        var assertions = 0;
        buster.assert.bind(runner, { "failure": "assertionFailure" });

        buster.assert.on("pass", function () {
            assertions += 1;
        });

        runner.on("test:start", function () {
            assertions = 0;
        });

        buster.testRunner.assertionCount = function () {
            return assertions;
        };
    }

    // Some test contexts may not be ready to run at create time
    // Make sure these get parsed before running them
    function parsedContexts(testContexts) {
        var ctxs = [];

        for (var i = 0, l = testContexts.length; i < l; ++i) {
            if (!testContexts[i].tests &&
                typeof testContexts[i].parse == "function") {
                ctxs.push(testContexts[i].parse());
            } else {
                ctxs.push(testContexts[i]);
            }
        }

        return ctxs;
    }

    // Run tests on the signal
    B.multicastClient.on("tests:run", function (msg) {
        var runner = B.testRunner.create(msg.data);
        var reporter = B.reporters.jsonProxy.create(B.multicastClient);
        reporter.listen(runner);
        buster.assert.throwOnFailure = false;
        setUpAssertionCounting(runner);

        // runner.on("suite:start", function (res) {
        //     delete B.multicastClient.triggerEvents;
        // });

        runner.on("suite:end", function (res) {
            delete B.multicastClient.triggerEvents;
        });

        runner.runSuite(parsedContexts(contexts));
        contexts = [];
    });

    B.multicastClient.emit("ready", window.navigator.userAgent);
}(buster));

// TMP Performance fix
(function () {
    var i = 0;

    buster.nextTick = function (cb) {
        i += 1;

        if (i == 20) {
            setTimeout(function () {
                cb();
            }, 0);

            i = 0;
        } else {
            cb();
        }
    };
}());
<commit_msg>tweak wiring (to be replaced)<commit_after>(function (B) {
    // B.multicastClient.log = function (msg) {
    //     console.log("LOG", msg);
    // }

    B.multicastClient.enforceEmitOrder = true;

    B.multicastClient.triggerEvents = [
        "ready", "test:success", "test:failure",
        "test:error", "test:timeout", "suite:end"];

    window.onerror = function (message) {
        B.multicastClient.emit("uncaughtException", {
            name: "UncaughtError", message: message
        });

        return true;
    };

    // TMP!!!
    buster.env = buster.env || {};
    buster.env.path = window.location.href;

    // Format assertion messages nicely
    B.assertions.format = B.format.ascii;

    // Format log messages with unquoted strings
    // Means that log("One", "Two") -> "One Two", not "\"One\" \"Two\""
    var logFormatter = buster.create(B.format);
    logFormatter.quoteStrings = false;

    // Console and buster.log shorthand
    B.console = B.eventedLogger.create({
        formatter: buster.bind(logFormatter, "ascii")
    });

    B.log = buster.bind(B.console, "log");

    // Ship log messages over the wire
    B.console.on("log", function (msg) {
        B.multicastClient.emit("log", msg);
    });

    // Keep a reference to test cases and specs
    var contexts = [];
    B.addTestContext = function (context) { contexts.push(context); };
    B.testCase.onCreate = B.addTestContext;
    B.spec.describe.onCreate = B.addTestContext;

    // Listen to events from buster.assert to make the test runner count
    // assertions correctly
    function setUpAssertionCounting(runner) {
        var assertions = 0;
        buster.assertions.bind(runner, { "failure": "assertionFailure" });

        buster.assertions.on("pass", function () {
            assertions += 1;
        });

        runner.on("test:start", function () {
            assertions = 0;
        });

        buster.testRunner.assertionCount = function () {
            return assertions;
        };
    }

    // Some test contexts may not be ready to run at create time
    // Make sure these get parsed before running them
    function parsedContexts(testContexts) {
        var ctxs = [];

        for (var i = 0, l = testContexts.length; i < l; ++i) {
            if (!testContexts[i].tests &&
                typeof testContexts[i].parse == "function") {
                ctxs.push(testContexts[i].parse());
            } else {
                ctxs.push(testContexts[i]);
            }
        }

        return ctxs;
    }

    // Run tests on the signal
    B.multicastClient.on("tests:run", function (msg) {
        var runner = B.testRunner.create(msg.data);
        var reporter = B.reporters.jsonProxy.create(B.multicastClient);
        reporter.listen(runner);
        buster.assertions.throwOnFailure = false;
        setUpAssertionCounting(runner);

        buster.assert = buster.assertions.assert;
        buster.refute = buster.assertions.refute;

        runner.on("suite:end", function (res) {
            delete B.multicastClient.triggerEvents;
        });

        runner.runSuite(parsedContexts(contexts));
        contexts = [];
    });

    B.multicastClient.emit("ready", window.navigator.userAgent);
}(buster));

// TMP Performance fix
(function () {
    var i = 0;

    buster.nextTick = function (cb) {
        i += 1;

        if (i == 50) {
            setTimeout(function () {
                cb();
            }, 0);

            i = 0;
        } else {
            cb();
        }
    };
}());
<|endoftext|>


<commit_before>/*
    * Calculate registration type based on
    *    Age,
    *    registration type,
    *    accommodations, and
    *    days
    *    date created (early or late discount)
    */
calculateRegistrationPrice = function (registration) {
    var accommodationsFee; // Used for accommodations price
    var calculatedDiscount; // Used for discount price
    var linens; // used for overnight registrations
    var earlyDiscountOrLateFee; // holds early discount or late fee, if any

    // Calculate accommodations fee
    accommodationsFee = calculateAccommodationsFee(registration);

    // Calculate linens fee, if applicable
    linens = calculateLinensFee(registration);

    // Calculate discount based on half days
    calculatedDiscount = calculateDiscount(registration.firstTimeAttender, registration.days);

    // Calculate the percentage-based fee used for early discount or late fee, if applicable
    var earlyOrLateFee = calculateEarlyOrLatePercentage(accommodationsFee);

    // Determine if the registration qualifies for early discount or late fee
    var earlyOrLate = determineEarlyOrLate(registration.createdAt);

    // Get the subtotal used for final calculations
    // based on accommodations, linens, and first time attender/half day discounts
    var subtotal = accommodationsFee + linens - calculatedDiscount;

    // Calculate total to include early or late fee, if applicable
    if (earlyOrLate === 'early') {
        // subtract early discount from subtotal
        var total = subtotal - earlyOrLateFee;
    } else if (earlyOrLate === 'late') {
        // add late fee to subtotal
        var total = subtotal + earlyOrLateFee;
    } else if (earlyOrLate === 'regular') {
        // regular registration fee calculation
        var total = accommodationsFee + linens - calculatedDiscount;
    }

    // Make sure we don't have a negative total
    if (total < 0) {
        return 0;
    } else {
        return total;
    }
};
<commit_msg>Added try/catch statements.<commit_after>/*
    * Calculate registration type based on
    *    Age,
    *    registration type,
    *    accommodations, and
    *    days
    *    date created (early or late discount)
    */
calculateRegistrationPrice = function (registration) {
    var accommodationsFee; // Used for accommodations price
    var calculatedDiscount; // Used for discount price
    var linens; // used for overnight registrations
    var earlyDiscountOrLateFee; // holds early discount or late fee, if any
    var subtotal; // Hold subtotal prior to discount
    var total; // Hold total registration price

    // Calculate accommodations fee
    try {
        accommodationsFee = calculateAccommodationsFee(registration);
    } catch (error) {
        console.log(error.message);
    }

    // Calculate linens fee, if applicable
    try {
        linens = calculateLinensFee(registration);
    } catch (error) {
        console.log(error.message);
    }

    // Calculate discount based on half days
    try {
        calculatedDiscount = calculateDiscount(registration.firstTimeAttender, registration.days);
    } catch (error) {
        console.log(error.message);
    }

    // Calculate the percentage-based fee used for early discount or late fee, if applicable
    try {
        var earlyOrLateFee = calculateEarlyOrLatePercentage(accommodationsFee);
    } catch (error) {
        console.log(error.message);
    }

    // Determine if the registration qualifies for early discount or late fee
    try {
        var earlyOrLate = determineEarlyOrLate(registration.createdAt);
    } catch (error) {
        console.log(error.message);
    }

    // Get the subtotal used for final calculations
    // based on accommodations, linens, and first time attender/half day discounts
    subtotal = accommodationsFee + linens - calculatedDiscount;

    // Calculate total to include early or late fee, if applicable
    if (earlyOrLate === 'early') {
        // subtract early discount from subtotal
        total = subtotal - earlyOrLateFee;
    } else if (earlyOrLate === 'late') {
        // add late fee to subtotal
        total = subtotal + earlyOrLateFee;
    } else if (earlyOrLate === 'regular') {
        // regular registration fee calculation
        total = accommodationsFee + linens - calculatedDiscount;
    }

    // Make sure we don't have a negative, or undefined total
    if (!total || total < 0) {
        return 0;
    } else {
        return total;
    }
};
<|endoftext|>