<commit_before>'use strict';

define(['angular', 'angular-sanitize', 'angular-loading-bar', 'angular-animate',
        'text-angular'
        /*,'angular-form-controls','angular-storage', 'angular-route', 'angular-cookies', */
    ],
    function(angular) {

        var dependencies = ['ngRoute', 'ngCookies', 'chieffancypants.loadingBar', 'ngAnimate',
            'ngSanitize', 'angular-intro', 'scbdControls', 'ngLocalizer',
            'textAngular', 'cbd-forums', 'LocalStorageModule',
            'ng-breadcrumbs', 'scbdServices', 'scbdFilters'
        ];
        angular.defineModules(dependencies);
        var app = angular.module('app', dependencies);

        app.config(['$controllerProvider', '$compileProvider', '$provide', '$filterProvider', '$httpProvider',
            function($controllerProvider, $compileProvider, $provide, $filterProvider, $httpProvider) {
                // console.log($routeProvider);
                //app.controllerProvider = $controllerProvider;
                //app.routeProvider      = $routeProvider;
                //app.compileProvider    = $compileProvider;
                app.filter = function(name, param1, param2, param3, param4) {
                    return (fromCache('filter', name) ||
                        toCache('filter', name, $filterProvider.register(name, param1, param2, param3, param4))).data;
                };

                app.factory = function(name, param1, param2, param3, param4) {
                    return (fromCache('factory', name) ||
                        toCache('factory', name, $provide.factory(name, param1, param2, param3, param4))).data;
                };

                app.value = function(name, param1, param2, param3, param4) {
                    return (fromCache('value', name) ||
                        toCache('value', name, $provide.value(name, param1, param2, param3, param4))).data;
                };

                app.controller = function(name, param1, param2, param3, param4) {
                    return (fromCache('controller', name) ||
                        toCache('controller', name, $controllerProvider.register(name, param1, param2, param3, param4))).data;
                };

                app.directive = function(name, param1, param2, param3, param4) {
                    return (fromCache('directive', name) ||
                        toCache('directive', name, $compileProvider.directive(name, param1, param2, param3, param4))).data;
                };

                $httpProvider.interceptors.push('authenticationHttpIntercepter');
                $httpProvider.interceptors.push('realmHttpIntercepter');

                //==========================================
                //==========================================
                //==========================================
                //==========================================

                var lazyCache = {};

                function fromCache(type, name) {

                    var key = type + ':' + name;

                    if (lazyCache[key])
                        console.log('Already defined: ' + key);

                    return lazyCache[key];
                }

                function toCache(type, name, data) {

                    var key = type + ':' + name;

                    if (lazyCache[key])
                        throw 'Cannot cache: Already defined: ' + key;

                    lazyCache[key] = {
                        data: data
                    };

                    return lazyCache[key];
                }

            }
        ]);

        app.run(function($rootScope, $location) {
            $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
                //padding route attributes to the rootscope
                if (current.$$route && current.$$route.subTemplateUrl)
                    $rootScope.subTemplateUrl = current.$$route.subTemplateUrlFull;
            });

        });

        return app;
    });
<commit_msg>remove interceptors<commit_after>'use strict';

define(['angular', 'angular-sanitize', 'angular-loading-bar', 'angular-animate',
        'text-angular'
        /*,'angular-form-controls','angular-storage', 'angular-route', 'angular-cookies', */
    ],
    function(angular) {

        var dependencies = ['ngRoute', 'ngCookies', 'chieffancypants.loadingBar', 'ngAnimate',
            'ngSanitize', 'angular-intro', 'scbdControls', 'ngLocalizer',
            'textAngular', 'cbd-forums', 'LocalStorageModule',
            'ng-breadcrumbs', 'scbdServices', 'scbdFilters'
        ];
        angular.defineModules(dependencies);
        var app = angular.module('app', dependencies);

        app.config(['$controllerProvider', '$compileProvider', '$provide', '$filterProvider', '$httpProvider',
            function($controllerProvider, $compileProvider, $provide, $filterProvider, $httpProvider) {
                // console.log($routeProvider);
                //app.controllerProvider = $controllerProvider;
                //app.routeProvider      = $routeProvider;
                //app.compileProvider    = $compileProvider;
                app.filter = function(name, param1, param2, param3, param4) {
                    return (fromCache('filter', name) ||
                        toCache('filter', name, $filterProvider.register(name, param1, param2, param3, param4))).data;
                };

                app.factory = function(name, param1, param2, param3, param4) {
                    return (fromCache('factory', name) ||
                        toCache('factory', name, $provide.factory(name, param1, param2, param3, param4))).data;
                };

                app.value = function(name, param1, param2, param3, param4) {
                    return (fromCache('value', name) ||
                        toCache('value', name, $provide.value(name, param1, param2, param3, param4))).data;
                };

                app.controller = function(name, param1, param2, param3, param4) {
                    return (fromCache('controller', name) ||
                        toCache('controller', name, $controllerProvider.register(name, param1, param2, param3, param4))).data;
                };

                app.directive = function(name, param1, param2, param3, param4) {
                    return (fromCache('directive', name) ||
                        toCache('directive', name, $compileProvider.directive(name, param1, param2, param3, param4))).data;
                };

                //==========================================
                //==========================================
                //==========================================
                //==========================================

                var lazyCache = {};

                function fromCache(type, name) {

                    var key = type + ':' + name;

                    if (lazyCache[key])
                        console.log('Already defined: ' + key);

                    return lazyCache[key];
                }

                function toCache(type, name, data) {

                    var key = type + ':' + name;

                    if (lazyCache[key])
                        throw 'Cannot cache: Already defined: ' + key;

                    lazyCache[key] = {
                        data: data
                    };

                    return lazyCache[key];
                }

            }
        ]);

        app.run(function($rootScope, $location) {
            $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
                //padding route attributes to the rootscope
                if (current.$$route && current.$$route.subTemplateUrl)
                    $rootScope.subTemplateUrl = current.$$route.subTemplateUrlFull;
            });

        });

        return app;
    });
<|endoftext|>


<commit_before>_.templateSettings = {
  interpolate: /\{\{\=(.+?)\}\}/g,
  evaluate: /\{\{(.+?)\}\}/g
};

var AnyGood = {
  mainView: {},
  router: {}
};

AnyGood.Router = Backbone.Router.extend({
  routes: {
    "movies/:year/:name" : "showMovie",
    "search/:term" : "searchMovie"
  },
  showMovie: function(year, name) {
    AnyGood.mainView.getAndDisplayMovie(name.split('_').join(' '), year);
  },
  searchMovie: AnyGood.mainView.getAndDisplaySearchResult
});

AnyGood.Movie = Backbone.Model.extend({
  defaults: {
    name: '',
    year: 0,
    info: '',
    ratings: [],
    combined_rating: 0
  },
  url: function () {
    return '/api/movies/' + this.get('year') + '/' + this.get('name');
  },
  getScoresToCalculate: function() {
    var scoresToCalculate = [];
    var ratings           = this.get('ratings');

    for (var i = 0; i < ratings.length; i++) {
      if (ratings[i].ignored === false || ratings[i].ignored === undefined) {
        if (ratings[i].score !== 0.0) {
          scoresToCalculate.push(ratings[i].score);
        }
      }
    }
    return scoresToCalculate;
  },

  calculateCombinedRating: function() {
    var scores         = this.getScoresToCalculate();
    var scoresSum      = 0;
    var combinedRating = 0;

    if (scores.length > 0) {
      for (var i = 0; i < scores.length; i++) {
        scoresSum += scores[i];
      }
      combinedRating = scoresSum / scores.length;
    }

    this.set('combined_rating', combinedRating);
    this.trigger('change');
  },

  toggleRatingIgnoreStatus: function(ratingIndex) {
    var ratings = this.get('ratings');

    if (ratings[ratingIndex] && ratings[ratingIndex].ignored === true) {
      ratings[ratingIndex].ignored = false;
    } else {
      ratings[ratingIndex].ignored = true;
    }
    this.set('ratings', ratings);
    this.calculateCombinedRating();
  }
});

AnyGood.SearchResult = Backbone.Model.extend({
  defaults: {
    movies: []
  }
});

AnyGood.AddMovieView = Backbone.View.extend({
  template: _.template($('#add-movie-template').html()),

  events: {
    'submit #add-movie': 'addMovie',
  },

  initialize: function() {
    _.bindAll(this, 'render', 'addMovie');
  },

  render: function() {
    this.$el.html(this.template());
    return this;
  },

  addMovie: function(event) {
    event.preventDefault();
    var movieName = this.$('#new-movie-name').val();
    var movieYear = this.$('#new-movie-year').val();

    if (movieName === '' || movieYear === '') {
      this.$('.not-valid').show();
    } else {
      this.makeRequest(this.capitalizeFirstLetters(movieName), movieYear);
    }
  },

  capitalizeFirstLetters: function(movieName) {
    var _words            = movieName.split(' ');
    var _transformedWords = [];
    for (var i = 0; i < _words.length; i++) {
      _transformedWords.push(_words[i].charAt(0).toUpperCase() + _words[i].slice(1));
    }
    return _transformedWords.join(' ');
  },

  makeRequest: function(movieName, movieYear) {
    $.ajax({
      url: '/api/search',
      type: 'POST',
      data: {
        movie: {name: movieName, year: movieYear}
      },
      success: function(data) {
        AnyGood.mainView.renderAddMovieSuccessView(movieName, movieYear);
      },
    });
  }
});

AnyGood.AddMovieSuccessView = Backbone.View.extend({
  template: _.template($('#add-movie-success-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
  },

  render: function() {
    this.$el.html(this.template(this.model));
    return this;
  }
});

AnyGood.NoSearchResultView = Backbone.View.extend({
  template: _.template($('#no-search-result-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
  },

  render: function() {
    this.$el.html(this.template());
    this.addMovieView = new AnyGood.AddMovieView({ el: this.$('.add-to-index-form') });
    this.addMovieView.render();
    return this;
  },
});

AnyGood.SearchResultView = Backbone.View.extend({
  template: _.template($('#search-result-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.on('change', this.render);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    this.addMovieView = new AnyGood.AddMovieView({ el: this.$('.add-to-index-form') });
    this.addMovieView.render();
    return this;
  },
});

AnyGood.LoadingMovieView = Backbone.View.extend({
  template: _.template($('#loading-template').html()),

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  },
});

AnyGood.MovieView = Backbone.View.extend({
  template: _.template($('#movie-template').html()),

  events: {
    'click .ignore-button': 'toggleRatingIgnore'
  },

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.on('change', this.render);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  },

  toggleRatingIgnore: function(event) {
    event.preventDefault();

    var ratingIndex = $(event.target).parents('.rating').attr('data-rating-index');

    this.model.toggleRatingIgnoreStatus(ratingIndex);
  }
});

AnyGood.MainView = Backbone.View.extend({
  el: $('#anygood'),

  events: {
    'submit #search_movie': 'searchMovie',
  },

  initialize: function() {
    this.$form             = this.$('#search_movie');
    this.$nameInput        = this.$form.children('#movie-name-input');
    this.$yearInput        = this.$form.children('#movie-year-input');
  },

  searchMovie: function(event) {
    event.preventDefault();

    if (this.$yearInput.val() != '') {
      var url = "movies/" + this.$yearInput.val() + "/" + this.$nameInput.val().split(' ').join('_');
      this.$yearInput.val('');
      this.$nameInput.val('');
    } else {
      var url = "search/" + this.$nameInput.val();
    }

    AnyGood.router.navigate(url, {trigger: true});
    AnyGood.mainView.$nameInput.autocomplete('close');
    AnyGood.mainView.$nameInput.blur();
  },

  getAndDisplaySearchResult: function(term) {
    $.ajax({
      url: '/api/search',
      data: {
        term: term
      },
      success: function(data) {
        if (data.movies.length > 0) {
          var searchResult = new AnyGood.SearchResult({movies: data.movies});
          var view         = new AnyGood.SearchResultView({model: searchResult});
        } else {
          var view = new AnyGood.NoSearchResultView({});
        }
        $("#content").html(view.render().el);
      },
    });
  },

  getAndDisplayMovie: function(name, year) {
    this.renderLoadingMovieView();

    var movie = new AnyGood.Movie({name: name, year: year});
    movie.fetch({
      success: AnyGood.mainView.renderMovie,
      error: AnyGood.mainView.renderError
    });
  },

  renderMovie: function(movie) {
    var view = new AnyGood.MovieView({model: movie});
    this.$("#content").html(view.render().el);
  },

  renderError: function() {
    var template = _.template($('#500-template').html());
    this.$("#content").html(template());
  },

  renderLoadingMovieView: function() {
    var template = _.template($('#loading-template').html());
    this.$("#content").html(template());
  },

  renderAddMovieSuccessView: function(movieName, movieYear) {
    var view = new AnyGood.AddMovieSuccessView({model: { name: movieName, year: movieYear}});
    this.$("#content").html(view.render().el);
  }
});

$(function(AnyGood) {
  AnyGood.router   = new AnyGood.Router();
  AnyGood.mainView = new AnyGood.MainView;

  AnyGood.mainView.$nameInput.autocomplete({
    source: function(request, response) {
      $.ajax({
        url: '/api/search',
        data: {
          term: request.term
        },
        success: function(data) {
          response($.map(data.movies, function(movie) {
            return {
              label: movie.name + ' (' + movie.year + ')',
              value: movie.name,
              year: movie.year
            }
          }));
        },
      });
    },
    select: function(event,ui) {
      $('#movie-year-input').val(ui.item.year);
      $('#movie-name-input').val(ui.item.value);
      $(this).parents('form').submit();
      $(this).blur();
    },
    minLength: 2
  }).focus(function() {
    $(this).val('');
  });

  Backbone.history.start()
}(AnyGood));
<commit_msg>Fix client router<commit_after>_.templateSettings = {
  interpolate: /\{\{\=(.+?)\}\}/g,
  evaluate: /\{\{(.+?)\}\}/g
};

var AnyGood = {
  mainView: {},
  router: {}
};

AnyGood.Router = Backbone.Router.extend({
  routes: {
    "movies/:year/:name" : "showMovie",
    "search/:term" : "searchMovie"
  },
  showMovie: function(year, name) {
    AnyGood.mainView.getAndDisplayMovie(name.split('_').join(' '), year);
  },
  searchMovie: function(term) {
    AnyGood.mainView.getAndDisplaySearchResult(term);
  }
});

AnyGood.Movie = Backbone.Model.extend({
  defaults: {
    name: '',
    year: 0,
    info: '',
    ratings: [],
    combined_rating: 0
  },
  url: function () {
    return '/api/movies/' + this.get('year') + '/' + this.get('name');
  },
  getScoresToCalculate: function() {
    var scoresToCalculate = [];
    var ratings           = this.get('ratings');

    for (var i = 0; i < ratings.length; i++) {
      if (ratings[i].ignored === false || ratings[i].ignored === undefined) {
        if (ratings[i].score !== 0.0) {
          scoresToCalculate.push(ratings[i].score);
        }
      }
    }
    return scoresToCalculate;
  },

  calculateCombinedRating: function() {
    var scores         = this.getScoresToCalculate();
    var scoresSum      = 0;
    var combinedRating = 0;

    if (scores.length > 0) {
      for (var i = 0; i < scores.length; i++) {
        scoresSum += scores[i];
      }
      combinedRating = scoresSum / scores.length;
    }

    this.set('combined_rating', combinedRating);
    this.trigger('change');
  },

  toggleRatingIgnoreStatus: function(ratingIndex) {
    var ratings = this.get('ratings');

    if (ratings[ratingIndex] && ratings[ratingIndex].ignored === true) {
      ratings[ratingIndex].ignored = false;
    } else {
      ratings[ratingIndex].ignored = true;
    }
    this.set('ratings', ratings);
    this.calculateCombinedRating();
  }
});

AnyGood.SearchResult = Backbone.Model.extend({
  defaults: {
    movies: []
  }
});

AnyGood.AddMovieView = Backbone.View.extend({
  template: _.template($('#add-movie-template').html()),

  events: {
    'submit #add-movie': 'addMovie',
  },

  initialize: function() {
    _.bindAll(this, 'render', 'addMovie');
  },

  render: function() {
    this.$el.html(this.template());
    return this;
  },

  addMovie: function(event) {
    event.preventDefault();
    var movieName = this.$('#new-movie-name').val();
    var movieYear = this.$('#new-movie-year').val();

    if (movieName === '' || movieYear === '') {
      this.$('.not-valid').show();
    } else {
      this.makeRequest(this.capitalizeFirstLetters(movieName), movieYear);
    }
  },

  capitalizeFirstLetters: function(movieName) {
    var _words            = movieName.split(' ');
    var _transformedWords = [];
    for (var i = 0; i < _words.length; i++) {
      _transformedWords.push(_words[i].charAt(0).toUpperCase() + _words[i].slice(1));
    }
    return _transformedWords.join(' ');
  },

  makeRequest: function(movieName, movieYear) {
    $.ajax({
      url: '/api/search',
      type: 'POST',
      data: {
        movie: {name: movieName, year: movieYear}
      },
      success: function(data) {
        AnyGood.mainView.renderAddMovieSuccessView(movieName, movieYear);
      },
    });
  }
});

AnyGood.AddMovieSuccessView = Backbone.View.extend({
  template: _.template($('#add-movie-success-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
  },

  render: function() {
    this.$el.html(this.template(this.model));
    return this;
  }
});

AnyGood.NoSearchResultView = Backbone.View.extend({
  template: _.template($('#no-search-result-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
  },

  render: function() {
    this.$el.html(this.template());
    this.addMovieView = new AnyGood.AddMovieView({ el: this.$('.add-to-index-form') });
    this.addMovieView.render();
    return this;
  },
});

AnyGood.SearchResultView = Backbone.View.extend({
  template: _.template($('#search-result-template').html()),

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.on('change', this.render);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    this.addMovieView = new AnyGood.AddMovieView({ el: this.$('.add-to-index-form') });
    this.addMovieView.render();
    return this;
  },
});

AnyGood.LoadingMovieView = Backbone.View.extend({
  template: _.template($('#loading-template').html()),

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  },
});

AnyGood.MovieView = Backbone.View.extend({
  template: _.template($('#movie-template').html()),

  events: {
    'click .ignore-button': 'toggleRatingIgnore'
  },

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.on('change', this.render);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  },

  toggleRatingIgnore: function(event) {
    event.preventDefault();

    var ratingIndex = $(event.target).parents('.rating').attr('data-rating-index');

    this.model.toggleRatingIgnoreStatus(ratingIndex);
  }
});

AnyGood.MainView = Backbone.View.extend({
  el: $('#anygood'),

  events: {
    'submit #search_movie': 'searchMovie',
  },

  initialize: function() {
    this.$form             = this.$('#search_movie');
    this.$nameInput        = this.$form.children('#movie-name-input');
    this.$yearInput        = this.$form.children('#movie-year-input');
  },

  searchMovie: function(event) {
    event.preventDefault();

    if (this.$yearInput.val() != '') {
      var url = "movies/" + this.$yearInput.val() + "/" + this.$nameInput.val().split(' ').join('_');
      this.$yearInput.val('');
      this.$nameInput.val('');
    } else {
      var url = "search/" + this.$nameInput.val();
    }

    AnyGood.router.navigate(url, {trigger: true});
    AnyGood.mainView.$nameInput.autocomplete('close');
    AnyGood.mainView.$nameInput.blur();
  },

  getAndDisplaySearchResult: function(term) {
    $.ajax({
      url: '/api/search',
      data: {
        term: term
      },
      success: function(data) {
        if (data.movies.length > 0) {
          var searchResult = new AnyGood.SearchResult({movies: data.movies});
          var view         = new AnyGood.SearchResultView({model: searchResult});
        } else {
          var view = new AnyGood.NoSearchResultView({});
        }
        $("#content").html(view.render().el);
      },
    });
  },

  getAndDisplayMovie: function(name, year) {
    this.renderLoadingMovieView();

    var movie = new AnyGood.Movie({name: name, year: year});
    movie.fetch({
      success: AnyGood.mainView.renderMovie,
      error: AnyGood.mainView.renderError
    });
  },

  renderMovie: function(movie) {
    var view = new AnyGood.MovieView({model: movie});
    this.$("#content").html(view.render().el);
  },

  renderError: function() {
    var template = _.template($('#500-template').html());
    this.$("#content").html(template());
  },

  renderLoadingMovieView: function() {
    var template = _.template($('#loading-template').html());
    this.$("#content").html(template());
  },

  renderAddMovieSuccessView: function(movieName, movieYear) {
    var view = new AnyGood.AddMovieSuccessView({model: { name: movieName, year: movieYear}});
    this.$("#content").html(view.render().el);
  }
});

$(function(AnyGood) {
  AnyGood.router   = new AnyGood.Router();
  AnyGood.mainView = new AnyGood.MainView;

  AnyGood.mainView.$nameInput.autocomplete({
    source: function(request, response) {
      $.ajax({
        url: '/api/search',
        data: {
          term: request.term
        },
        success: function(data) {
          response($.map(data.movies, function(movie) {
            return {
              label: movie.name + ' (' + movie.year + ')',
              value: movie.name,
              year: movie.year
            }
          }));
        },
      });
    },
    select: function(event,ui) {
      $('#movie-year-input').val(ui.item.year);
      $('#movie-name-input').val(ui.item.value);
      $(this).parents('form').submit();
      $(this).blur();
    },
    minLength: 2
  }).focus(function() {
    $(this).val('');
  });

  Backbone.history.start()
}(AnyGood));
<|endoftext|>


<commit_before>import { TiledPixiTrack } from './TiledPixiTrack';

// Services
import { tileProxy } from './services';

// Utils
import { colorToHex } from './utils';

export class ArrowheadDomainsTrack extends TiledPixiTrack {
  constructor(scene, server, uid, handleTilesetInfoReceived, option, animate) {
    super(scene, server, uid, handleTilesetInfoReceived, option, animate);

    this.drawnRects = {};
  }

  tileToLocalId(tile) {
    /*
         * The local tile identifier
         */

    // tile contains [zoomLevel, xPos, yPos]
    return `${this.tilesetUid}.${tile.join('.')}`;
  }

  tileToRemoteId(tile) {
    /**
         * The tile identifier used on the server
         */

    // tile contains [zoomLevel, xPos, yPos]
    return `${this.tilesetUid}.${tile.join('.')}`;
  }

  localToRemoteId(remoteId) {
    const idParts = remoteId.split('.');
    return idParts.slice(0, idParts.length - 1).join('.');
  }

  calculateZoomLevel() {
    const xZoomLevel = tileProxy.calculateZoomLevel(this._xScale,
      this.tilesetInfo.min_pos[0],
      this.tilesetInfo.max_pos[0]);
    const yZoomLevel = tileProxy.calculateZoomLevel(this._xScale,
      this.tilesetInfo.min_pos[1],
      this.tilesetInfo.max_pos[1]);

    let zoomLevel = Math.max(xZoomLevel, yZoomLevel);
    zoomLevel = Math.min(zoomLevel, this.maxZoom);

    return zoomLevel;
  }

  setVisibleTiles(tilePositions) {
    /**
         * Set which tiles are visible right now.
         *
         * @param tiles: A set of tiles which will be considered the currently visible
         * tile positions.
         */
    this.visibleTiles = tilePositions.map(x => ({
      tileId: this.tileToLocalId(x),
      remoteId: this.tileToRemoteId(x),
    }));

    this.visibleTileIds = new Set(this.visibleTiles.map(x => x.tileId));
  }

  calculateVisibleTiles(mirrorTiles = true) {
    // if we don't know anything about this dataset, no point
    // in trying to get tiles
    if (!this.tilesetInfo) { return; }

    this.zoomLevel = this.calculateZoomLevel();
    // this.zoomLevel = 0;

    this.xTiles = tileProxy.calculateTiles(this.zoomLevel, this._xScale,
      this.tilesetInfo.min_pos[0],
      this.tilesetInfo.max_pos[0],
      this.tilesetInfo.max_zoom,
      this.tilesetInfo.max_width);

    this.yTiles = tileProxy.calculateTiles(this.zoomLevel, this._yScale,
      this.tilesetInfo.min_pos[1],
      this.tilesetInfo.max_pos[1],
      this.tilesetInfo.max_zoom,
      this.tilesetInfo.max_width);

    const rows = this.xTiles;
    const cols = this.yTiles;
    const zoomLevel = this.zoomLevel;

    // if we're mirroring tiles, then we only need tiles along the diagonal
    const tiles = [];

    // calculate the ids of the tiles that should be visible
    for (let i = 0; i < rows.length; i++) {
      for (let j = 0; j < cols.length; j++) {
        const newTile = [zoomLevel, rows[i], cols[j]];

        tiles.push(newTile);
      }
    }

    //
    this.setVisibleTiles(tiles);
  }

  initTile(tile) {
    /**
         * Create whatever is needed to draw this tile.
         */

    // this.drawTile(tile);
  }

  destroyTile(tile, graphics) {

  }

  draw() {
    this.drawnRects = {};

    super.draw();
  }

  drawTile(tile) {
    if (!tile.graphics) { return; }

    // console.log('tile:', tile);
    // console.log('Id2DTiled drawTile...');
    const graphics = tile.graphics;
    graphics.clear();

    const stroke = colorToHex(this.options.rectangleDomainStrokeColor || 'black');
    const fill = colorToHex(this.options.rectangleDomainFillColor || 'grey');

    graphics.lineStyle(
      typeof this.options.rectangleDomainStrokeWidth !== 'undefined'
        ? this.options.rectangleDomainStrokeWidth
        : 1,
      stroke,
      typeof this.options.rectangleDomainStrokeOpacity !== 'undefined'
        ? this.options.rectangleDomainStrokeOpacity
        : 1,
    );
    graphics.beginFill(
      fill,
      typeof this.options.rectangleDomainFillOpacity !== 'undefined'
        ? this.options.rectangleDomainFillOpacity
        : 0.4,
    );

    graphics.alpha = this.options.rectangleDomainOpacity || 0.5;

    // line needs to be scaled down so that it doesn't become huge
    for (const td of tile.tileData) {
      const line = td.fields;

      const startX = this._xScale(td.xStart);
      const endX = this._xScale(td.xEnd);

      const startY = this._yScale(td.yStart);
      const endY = this._yScale(td.yEnd);

      const uid = td.uid;

      const width = endX - startX;
      const height = endY - startY;

      if (uid in this.drawnRects) { continue; } // we've already drawn this rectangle in another tile

      let drawnRect = { x: startX, y: startY, width: endY - startY, height: endX - startX };

      if (this.options.minSquareSize && this.options.minSquareSize != 'none') {
        if (width < +this.options.minSquareSize || height < +this.options.minSquareSize) {
          const newWidth = this.options.minSquareSize;
          const newHeight = this.options.minSquareSize;

          drawnRect = {x: (startX + endX) / 2, y: (startY + endY) / 2,
            width: newWidth, height: newHeight};
        }
      }

      this.drawnRects[uid] = drawnRect;

      graphics.drawRect(drawnRect.x, drawnRect.y, drawnRect.width, drawnRect.height);
    }
  }

  exportSVG() {
    let track = null,
      base = null;

    if (super.exportSVG) {
      [base, track] = super.exportSVG();
    } else {
      base = document.createElement('g');
      track = base;
    }
    const output = document.createElement('g');
    output.setAttribute('transform',
      `translate(${this.position[0]},${this.position[1]})`);

    track.appendChild(output);

    for (let tile of this.visibleAndFetchedTiles()) {
      tile.tileData.forEach((td, i) => {
        let gTile = document.createElement('g')
        gTile.setAttribute('transform',
          `translate(${tile.graphics.position.x},${tile.graphics.position.y})scale(${tile.graphics.scale.x},${tile.graphics.scale.y})`);
        output.appendChild(gTile);

        if (td.uid in this.drawnRects) {
          let rect = this.drawnRects[td.uid];

          let r = document.createElement('rect');
          r.setAttribute('x', rect.x);
          r.setAttribute('y', rect.y);
          r.setAttribute('width', rect.width);
          r.setAttribute('height', rect.height);

          r.setAttribute('fill',  this.options.fillColor ? this.options.fillColor : 'grey')
          r.setAttribute('opacity', 0.3);

          r.style.stroke = this.options.fillColor ? this.options.fillColor : 'grey';
          r.style.strokeWidth = "1px";

          gTile.appendChild(r);
        }
      });
    }

    return [base, base];
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    this.xScale(newXScale);
    this.yScale(newYScale);

    this.refreshTiles();

    this.draw();
  }
}

export default ArrowheadDomainsTrack;
<commit_msg>Add two placeholder functions for callbacks. Avoid drawing too small annotations or annotations outside the view port. Avoid updating on zoom when the domain hasn't changed.<commit_after>import { TiledPixiTrack } from './TiledPixiTrack';

// Services
import { tileProxy } from './services';

// Utils
import { colorToHex } from './utils';

export class ArrowheadDomainsTrack extends TiledPixiTrack {
  constructor(
    scene,
    server,
    uid,
    handleTilesetInfoReceived,
    option,
    animate
  ) {
    super(scene, server, uid, handleTilesetInfoReceived, option, animate);

    this.drawnRects = {};

    this.drawn = () => {};
    this.annotationDrawn = () => {};
  }

  /*
   * The local tile identifier
   */
  tileToLocalId(tile) {
    // tile contains [zoomLevel, xPos, yPos]
    return `${this.tilesetUid}.${tile.join('.')}`;
  }

  /**
   * The tile identifier used on the server
   */
  tileToRemoteId(tile) {
    // tile contains [zoomLevel, xPos, yPos]
    return `${this.tilesetUid}.${tile.join('.')}`;
  }

  localToRemoteId(remoteId) {
    const idParts = remoteId.split('.');
    return idParts.slice(0, idParts.length - 1).join('.');
  }

  calculateZoomLevel() {
    const xZoomLevel = tileProxy.calculateZoomLevel(
      this._xScale,
      this.tilesetInfo.min_pos[0],
      this.tilesetInfo.max_pos[0]
    );
    const yZoomLevel = tileProxy.calculateZoomLevel(
      this._xScale,
      this.tilesetInfo.min_pos[1],
      this.tilesetInfo.max_pos[1]
    );

    let zoomLevel = Math.max(xZoomLevel, yZoomLevel);
    zoomLevel = Math.min(zoomLevel, this.maxZoom);

    return zoomLevel;
  }

  /**
   * Set which tiles are visible right now.
   *
   * @param tiles: A set of tiles which will be considered the currently visible
   * tile positions.
   */
  setVisibleTiles(tilePositions) {
    this.visibleTiles = tilePositions.map(x => ({
      tileId: this.tileToLocalId(x),
      remoteId: this.tileToRemoteId(x),
    }));

    this.visibleTileIds = new Set(this.visibleTiles.map(x => x.remoteId));
  }

  calculateVisibleTiles(mirrorTiles = true) {
    // if we don't know anything about this dataset, no point
    // in trying to get tiles
    if (!this.tilesetInfo) { return; }

    this.zoomLevel = this.calculateZoomLevel();
    // this.zoomLevel = 0;

    this.xTiles = tileProxy.calculateTiles(
      this.zoomLevel,
      this._xScale,
      this.tilesetInfo.min_pos[0],
      this.tilesetInfo.max_pos[0],
      this.tilesetInfo.max_zoom,
      this.tilesetInfo.max_width
    );

    this.yTiles = tileProxy.calculateTiles(
      this.zoomLevel,
      this._yScale,
      this.tilesetInfo.min_pos[1],
      this.tilesetInfo.max_pos[1],
      this.tilesetInfo.max_zoom,
      this.tilesetInfo.max_width
    );

    const rows = this.xTiles;
    const cols = this.yTiles;
    const zoomLevel = this.zoomLevel;

    // if we're mirroring tiles, then we only need tiles along the diagonal
    const tiles = [];

    // calculate the ids of the tiles that should be visible
    for (let i = 0; i < rows.length; i++) {
      for (let j = 0; j < cols.length; j++) {
        const newTile = [zoomLevel, rows[i], cols[j]];

        tiles.push(newTile);
      }
    }

    this.setVisibleTiles(tiles);
  }

  /**
   * Create whatever is needed to draw this tile.
   */
  initTile(/* tile */) {
    // this.drawTile(tile);
  }

  destroyTile(tile, graphics) {

  }

  draw() {
    this.drawnRects = {};

    super.draw();

    this.drawn(this.uuid);
  }

  drawTile(tile) {
    const graphics = tile.graphics;

    if (!graphics) { return; }

    graphics.clear();

    const stroke = colorToHex(this.options.rectangleDomainStrokeColor || 'black');
    const fill = colorToHex(this.options.rectangleDomainFillColor || 'grey');

    graphics.lineStyle(
      typeof this.options.rectangleDomainStrokeWidth !== 'undefined'
        ? this.options.rectangleDomainStrokeWidth
        : 1,
      stroke,
      typeof this.options.rectangleDomainStrokeOpacity !== 'undefined'
        ? this.options.rectangleDomainStrokeOpacity
        : 1,
    );
    graphics.beginFill(
      fill,
      typeof this.options.rectangleDomainFillOpacity !== 'undefined'
        ? this.options.rectangleDomainFillOpacity
        : 0.4,
    );

    graphics.alpha = this.options.rectangleDomainOpacity || 0.5;

    const minSquareSize = this.options.minSquareSize && this.options.minSquareSize !== 'none'
      ? +this.options.minSquareSize
      : 0;

    const minThres = this.options.rectanlgeMinSize
      ? +this.options.rectanlgeMinSize
      : 0;

    const xMin = this._xScale.range()[0];
    const xMax = this._xScale.range()[1];
    const yMin = this._yScale.range()[0];
    const yMax = this._yScale.range()[1];

    // line needs to be scaled down so that it doesn't become huge
    for (const td of tile.tileData) {
      const startX = this._xScale(td.xStart);
      const endX = this._xScale(td.xEnd);

      const startY = this._yScale(td.yStart);
      const endY = this._yScale(td.yEnd);

      const uid = td.uid;

      const width = endX - startX;
      const height = endY - startY;

      // we've already drawn this rectangle in another tile
      if (uid in this.drawnRects) { continue; }

      let drawnRect = {
        x: startX,
        y: startY,
        width,
        height
      };

      if (minSquareSize) {
        if (width < minSquareSize || height < minSquareSize) {
          drawnRect = {
            x: startX - (minSquareSize / 2),
            y: startY - (minSquareSize / 2),
            width: minSquareSize,
            height: minSquareSize
          };
        }
      }

      this.drawnRects[uid] = drawnRect;

      const dRxMax = drawnRect.x + drawnRect.width;
      const dRyMax = drawnRect.y + drawnRect.height;

      // Only draw annotations that falls somehow within the viewport
      if (
        (drawnRect.x > xMin && drawnRect.x < xMax) ||
        (dRxMax > xMin && dRxMax < xMax) ||
        (drawnRect.y > yMin && drawnRect.y < yMax) ||
        (dRyMax > yMin && dRyMax < yMax)
      ) {
        if (drawnRect.width > minThres || drawnRect.height > minThres) {
          graphics.drawRect(
            drawnRect.x, drawnRect.y, drawnRect.width, drawnRect.height
          );

          this.annotationDrawn(
            drawnRect.x, drawnRect.y, drawnRect.width, drawnRect.height
          );
        }
      }
    }
  }

  exportSVG() {
    let track = null;
    let base = null;

    if (super.exportSVG) {
      [base, track] = super.exportSVG();
    } else {
      base = document.createElement('g');
      track = base;
    }
    const output = document.createElement('g');
    output.setAttribute('transform',
      `translate(${this.position[0]},${this.position[1]})`);

    track.appendChild(output);

    for (let tile of this.visibleAndFetchedTiles()) {
      tile.tileData.forEach((td, i) => {
        let gTile = document.createElement('g')
        gTile.setAttribute('transform',
          `translate(${tile.graphics.position.x},${tile.graphics.position.y})scale(${tile.graphics.scale.x},${tile.graphics.scale.y})`);
        output.appendChild(gTile);

        if (td.uid in this.drawnRects) {
          let rect = this.drawnRects[td.uid];

          let r = document.createElement('rect');
          r.setAttribute('x', rect.x);
          r.setAttribute('y', rect.y);
          r.setAttribute('width', rect.width);
          r.setAttribute('height', rect.height);

          r.setAttribute('fill',  this.options.fillColor ? this.options.fillColor : 'grey')
          r.setAttribute('opacity', 0.3);

          r.style.stroke = this.options.fillColor ? this.options.fillColor : 'grey';
          r.style.strokeWidth = "1px";

          gTile.appendChild(r);
        }
      });
    }

    return [base, base];
  }

  setPosition(newPosition) {
    super.setPosition(newPosition);

    this.pMain.position.y = this.position[1];
    this.pMain.position.x = this.position[0];
  }

  zoomed(newXScale, newYScale) {
    if (
      this.xScale().domain()[0] === newXScale.domain()[0] &&
      this.xScale().domain()[1] === newXScale.domain()[1] &&
      this.yScale().domain()[0] === newYScale.domain()[0] &&
      this.yScale().domain()[1] === newYScale.domain()[1]
    ) return;

    this.xScale(newXScale);
    this.yScale(newYScale);

    this.refreshTiles();

    this.draw();
  }
}

export default ArrowheadDomainsTrack;
<|endoftext|>


<commit_before>define([
	'goo/entities/Entity',
	'goo/entities/managers/EntityManager',
	'goo/entities/components/TransformComponent',
	'goo/entities/managers/Manager',
	'goo/entities/systems/System',
	'goo/entities/components/Component',
	'goo/entities/EntitySelection'
],
/** @lends */
function (
	Entity,
	EntityManager,
	TransformComponent,
	Manager,
	System,
	Component,
	EntitySelection
) {
	'use strict';

	/**
	 * @class Main handler for an entity world. The World keeps track of managers and systems,
	 * and also provides methods to create, select and remove entities.
	 * Note that process() has to be called manually if objects need to be added and retrieved within the same update loop.
	 * See [this engine overview article]{@link http://www.gootechnologies.com/learn/tutorials/engine/engine-overview/} for more info.
	 * @param {GooRunner} gooRunner GooRunner for updating the world and calling the renderers.
	 */
	function World (gooRunner) {

		/** GooRunner for updating the world and calling the renderers.
		 * @type {GooRunner}
		 */
		this.gooRunner = gooRunner;

		this._managers = [];
		this._systems = [];

		this._addedEntities = [];
		this._changedEntities = [];
		this._removedEntities = [];

		this.by = {};
		this._installDefaultSelectors();

		/** Main keeper of entities.
		 * @type {EntityManager}
		 */
		this.entityManager = new EntityManager();
		this.setManager(this.entityManager);

		/** Accumulated time per frames(tpf) the world has been running.  Calculated at the start of each frame.
		 * @type {number}
		 */
		this.time = 0.0;

		/** Time since last frame in seconds.
		 * @type {number}
		 */
		this.tpf = 1.0;

		this._components = [];
	}

	World.time = 0.0;
	World.tpf = 1.0;

	/** Entity selector. Its methods return an {@link EntitySelection}. Can select by system, component, attribute or tag. See examples for usage.
	 *
Will get additional methods when an {@link EntityManager} is attached.
	 * @member by
	 * @memberOf World.prototype
	 * @example
	 * var bySystem = gooRunner.world.by.system("RenderSystem").toArray();
	 * var byComponent = gooRunner.world.by.component("cameraComponent").toArray();
	 * var byTag = gooRunner.world.by.tag("monster").toArray()
	 * var byAttribute = gooRunner.world.by.attribute("hit-points").toArray();
	 */
	World.prototype._installDefaultSelectors = function () {
		this.by.system = function (systemType) {
			var system = this.getSystem(systemType);
			return new EntitySelection(system._activeEntities);
		}.bind(this);

		this.by.component = function (componentType) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return !!entity[componentType];
			}));
		}.bind(this);

		//! AT: this will be relocated into the Tag Manager once it gets implemented
		this.by.tag = function (tag) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return entity.hasTag(tag);
			}));
		}.bind(this);

		//! AT: this will be relocated into the Attribute Manager once it gets implemented
		this.by.attribute = function (attribute) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return entity.hasAttribute(attribute);
			}));
		}.bind(this);
	};

	/**
	 * Universal shorthand for adding managers, systems, entities and registering components.
	 * Arguments can be of types Entity, Manager, System or Component and added in any order or combination.
	 * @param {Entity} [entity]
	 * @param {Manager} [manager]
	 * @param {System} [system]
	 * @param {Component} [component]
	 * @example
	 * // Add two entities and register a component, all in one swoop
	 * var entity1 = new Entity(gooRunner.world, 'Entity 1');
	 * var entity2 = new Entity(gooRunner.world, 'Entity 2');
	 * var animationComponent = new AnimationComponent();
	 * gooRunner.world.add(entity1, animationComponent, entity2);
	 *
	 * @returns {World} Returns self to allow chaining
	 */
	//! AT: again, 'set' vs 'add' - entities are added to the world, systems/managers are set
	World.prototype.add = function () {
		for (var i = 0; i < arguments.length; i++) {
			var argument = arguments[i];

			if (argument instanceof Entity) {
				this.addEntity(argument);
			} else if (argument instanceof Manager) {
				this.setManager(argument);
			} else if (argument instanceof System) {
				this.setSystem(argument);
			} else if (argument instanceof Component) {
			    this.registerComponent(argument);
			}
		}

		return this;
	};

	/**
	 * Registers a component type. This is necessary to allow automatic creation of components
	 * from 'basic' data types (CameraComponents from Cameras, MeshRendererComponents from materials and so on).
	 * When a {@link GooRunner} is created, it registers {@link TransformComponent}, {@link MeshDataComponent},
	 * {@link MeshRendererComponent}, {@link CameraComponent}, {@link LightComponent} and {@link ScriptComponent} automatically.
	 * @example
	 * // Register the animation component type so that animations
	 * // can be automatically created.
	 * gooRunner.world.registerComponent(AnimationComponent);
	 *
	 * @param {Component} componentConstructor
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.registerComponent = function (componentConstructor) {
		if (this._components.indexOf(componentConstructor) === -1) {
			this._components.push(componentConstructor);
		}
		return this;
	};

	/**
	 * Adds a {@link Manager} to the world.
	 *
	 * @param {Manager} manager
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.setManager = function (manager) {
		this._managers.push(manager);
		manager.applyAPI(this.by);
		return this;
	};

	/**
	 * Retrieves a {@link Manager} of a certain type.
	 *
	 * @param {String} type Type of manager to retrieve eg. 'EntityManager'.
	 * @returns {Manager}
	 */
	World.prototype.getManager = function (type) {
		for (var i = 0; i < this._managers.length; i++) {
			var manager = this._managers[i];
			if (manager.type === type) {
				return manager;
			}
		}
	};

	/**
	 * Adds a {@link System} to the world.
	 *
	 * @param {System} system
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.setSystem = function (system) {
		var priority = system.priority;

		for (var i = 0; i < this._systems.length; i++) {
			if (this._systems[i].priority > priority) {
				break;
			}
		}
		this._systems.splice(i, 0, system);

		return this;
	};

	/**
	 * Retrieve a {@link System} of type 'type'.
	 *
	 * @param {String} type Type of system to retrieve.
	 * @returns {System}
	 */
	World.prototype.getSystem = function (type) {
		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (system.type === type) {
				return system;
			}
		}
	};

	/**
	 * Removes the {@link System} of type 'type'.
	 * Entities tracked by the removed system will not get handled properly when they are removed from the world
	 * or when their components (that are tracked by this system) change.
	 *
	 * @param {String} type Type of system to remove.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.clearSystem = function (type) {
		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (system.type === type) {
				this._systems.splice(i, 1);
			}
		}
		return this;
	};

	/**
	 * Creates a new {@link Entity} with an optional MeshData, MeshRenderer, Camera, Script and Light component, placed optionally at a location. Parameters can be given in any order.
	 * @example
	 * // Create a sphere entity and add it to the world
	 * var sphereEntity = world.createEntity(new Sphere(32, 32), material, [0, 0, 5]).addToWorld();
	 * // Create a camera entity and add it to the world
	 * var cameraEntity = world.createEntity(new Camera(), [0, 0, 3]).lookAt(new Vector3(0, 0, 0)).addToWorld();
	 *
	 * @param {MeshData} [meshData]
	 * @param {Material} [material]
	 * @param {String} [name]
	 * @param {Camera} [camera]
	 * @param {Light} [light]
	 * @returns {Entity}
	 */
	World.prototype.createEntity = function () {
		var entity = new Entity(this);
		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] === 'string') { // does not cover new String()
				entity.name = arguments[i];
			} else {
				entity.set(arguments[i]);
			}
		}

		// separate treatment
		if (!entity.transformComponent) {
			entity.setComponent(new TransformComponent());
		}

		return entity;
	};

	/**
	 * Get an array of all entities in world.
	 *
	 * @returns {Entity[]} All entities existing in world.
	 */
	World.prototype.getEntities = function () {
		return this.entityManager.getEntities();
	};

	/**
	 * Add an {@link Entity} to the world.
	 *
	 * @param {Entity} entity Entity to add.
	 * @param {boolean} [recursive=true] If entity hierarchy should be added recursively.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.addEntity = function (entity, recursive) {
		if (this._addedEntities.indexOf(entity) === -1) {
			this._addedEntities.push(entity);
		}

		if (entity.transformComponent && (recursive === undefined || recursive === true)) {
			var children = entity.transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this.addEntity(children[i].entity, recursive);
			}
		}

		return this;
	};

	/**
	 * Remove an {@link Entity} from the world.
	 *
	 * @param {Entity} entity Entity to remove.
	 * @param {boolean} [recursive=true] If entity hierarchy should be removed recursively.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.removeEntity = function (entity, recursive) {
		if (this._removedEntities.indexOf(entity) === -1) {
			this._removedEntities.push(entity);
		}

		var transformComponent = entity.transformComponent;
		if (transformComponent.parent) {
			transformComponent.parent.detachChild(transformComponent);
			transformComponent.parent = null;
		}

		if (recursive === false) {
			var children = transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				children[i].parent = null;
			}

			transformComponent.children = [];
		} else {
			var children = transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this._recursiveRemoval(children[i].entity, recursive);
			}
		}

		return this;
	};

	World.prototype._recursiveRemoval = function (entity, recursive) {
		if (this._removedEntities.indexOf(entity) === -1) {
			this._removedEntities.push(entity);
		}

		if (entity.transformComponent && (recursive === undefined || recursive === true)) {
			var children = entity.transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this._recursiveRemoval(children[i].entity, recursive);
			}
		}
	};

	/**
	 * Let the world and its systems know that an entity has been changed/updated.
	 *
	 * @param entity
	 * @param component
	 * @param eventType
	 */
	World.prototype.changedEntity = function (entity, component, eventType) {
		var event = {
			entity: entity
		};
		if (component !== undefined) {
			event.component = component;
		}
		if (eventType !== undefined) {
			event.eventType = eventType;
		}
		this._changedEntities.push(event);
	};

	/**
	 * Process all added/changed/removed entities and callback to active systems and managers. Usually called automatically each frame.
	 * Has to be called between adding an entity to the world and getting it back.
	 */
	World.prototype.process = function () {
		this._check(this._addedEntities, function (observer, entity) {
			if (observer.added) {
				observer.added(entity);
			}

			// not in use by any system
			if (observer.addedComponent) {
				for (var i = 0; i < entity._components.length; i++) {
					observer.addedComponent(entity, entity._components[i]);
				}
			}
		});
		this._check(this._changedEntities, function (observer, event) {
			if (observer.changed) {
				observer.changed(event.entity);
			}
			if (event.eventType !== undefined) {
				if (observer[event.eventType]) {
					observer[event.eventType](event.entity, event.component);
				}
			}
		});
		this._check(this._removedEntities, function (observer, entity) {
			if (observer.removed) {
				observer.removed(entity);
			}

			// not in use by any system
			if (observer.removedComponent) {
				for (var i = 0; i < entity._components.length; i++) {
					observer.removedComponent(entity, entity._components[i]);
				}
			}
		});

		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (!system.passive) {
				system._process(this.tpf);
			}
		}
	};

	World.prototype._check = function (entities, callback) {
		for (var i = 0; i < entities.length; i++) {
			var entity = entities[i];
			for (var managerIndex = 0; managerIndex < this._managers.length; managerIndex++) {
				var manager = this._managers[managerIndex];
				callback(manager, entity);
			}
			for (var systemIndex = 0; systemIndex < this._systems.length; systemIndex++) {
				var system = this._systems[systemIndex];
				callback(system, entity);
			}
		}
		entities.length = 0;
	};

	return World;
});<commit_msg>Separated adding entities from running thorugh the systems<commit_after>define([
	'goo/entities/Entity',
	'goo/entities/managers/EntityManager',
	'goo/entities/components/TransformComponent',
	'goo/entities/managers/Manager',
	'goo/entities/systems/System',
	'goo/entities/components/Component',
	'goo/entities/EntitySelection'
],
/** @lends */
function (
	Entity,
	EntityManager,
	TransformComponent,
	Manager,
	System,
	Component,
	EntitySelection
) {
	'use strict';

	/**
	 * @class Main handler for an entity world. The World keeps track of managers and systems,
	 * and also provides methods to create, select and remove entities.
	 * Note that process() has to be called manually if objects need to be added and retrieved within the same update loop.
	 * See [this engine overview article]{@link http://www.gootechnologies.com/learn/tutorials/engine/engine-overview/} for more info.
	 * @param {GooRunner} gooRunner GooRunner for updating the world and calling the renderers.
	 */
	function World (gooRunner) {

		/** GooRunner for updating the world and calling the renderers.
		 * @type {GooRunner}
		 */
		this.gooRunner = gooRunner;

		this._managers = [];
		this._systems = [];

		this._addedEntities = [];
		this._changedEntities = [];
		this._removedEntities = [];

		this.by = {};
		this._installDefaultSelectors();

		/** Main keeper of entities.
		 * @type {EntityManager}
		 */
		this.entityManager = new EntityManager();
		this.setManager(this.entityManager);

		/** Accumulated time per frames(tpf) the world has been running.  Calculated at the start of each frame.
		 * @type {number}
		 */
		this.time = 0.0;

		/** Time since last frame in seconds.
		 * @type {number}
		 */
		this.tpf = 1.0;

		this._components = [];
	}

	World.time = 0.0;
	World.tpf = 1.0;

	/** Entity selector. Its methods return an {@link EntitySelection}. Can select by system, component, attribute or tag. See examples for usage.
	 *
Will get additional methods when an {@link EntityManager} is attached.
	 * @member by
	 * @memberOf World.prototype
	 * @example
	 * var bySystem = gooRunner.world.by.system("RenderSystem").toArray();
	 * var byComponent = gooRunner.world.by.component("cameraComponent").toArray();
	 * var byTag = gooRunner.world.by.tag("monster").toArray()
	 * var byAttribute = gooRunner.world.by.attribute("hit-points").toArray();
	 */
	World.prototype._installDefaultSelectors = function () {
		this.by.system = function (systemType) {
			var system = this.getSystem(systemType);
			return new EntitySelection(system._activeEntities);
		}.bind(this);

		this.by.component = function (componentType) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return !!entity[componentType];
			}));
		}.bind(this);

		//! AT: this will be relocated into the Tag Manager once it gets implemented
		this.by.tag = function (tag) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return entity.hasTag(tag);
			}));
		}.bind(this);

		//! AT: this will be relocated into the Attribute Manager once it gets implemented
		this.by.attribute = function (attribute) {
			var entities = this.entityManager.getEntities();

			return new EntitySelection(entities.filter(function (entity) {
				return entity.hasAttribute(attribute);
			}));
		}.bind(this);
	};

	/**
	 * Universal shorthand for adding managers, systems, entities and registering components.
	 * Arguments can be of types Entity, Manager, System or Component and added in any order or combination.
	 * @param {Entity} [entity]
	 * @param {Manager} [manager]
	 * @param {System} [system]
	 * @param {Component} [component]
	 * @example
	 * // Add two entities and register a component, all in one swoop
	 * var entity1 = new Entity(gooRunner.world, 'Entity 1');
	 * var entity2 = new Entity(gooRunner.world, 'Entity 2');
	 * var animationComponent = new AnimationComponent();
	 * gooRunner.world.add(entity1, animationComponent, entity2);
	 *
	 * @returns {World} Returns self to allow chaining
	 */
	//! AT: again, 'set' vs 'add' - entities are added to the world, systems/managers are set
	World.prototype.add = function () {
		for (var i = 0; i < arguments.length; i++) {
			var argument = arguments[i];

			if (argument instanceof Entity) {
				this.addEntity(argument);
			} else if (argument instanceof Manager) {
				this.setManager(argument);
			} else if (argument instanceof System) {
				this.setSystem(argument);
			} else if (argument instanceof Component) {
			    this.registerComponent(argument);
			}
		}

		return this;
	};

	/**
	 * Registers a component type. This is necessary to allow automatic creation of components
	 * from 'basic' data types (CameraComponents from Cameras, MeshRendererComponents from materials and so on).
	 * When a {@link GooRunner} is created, it registers {@link TransformComponent}, {@link MeshDataComponent},
	 * {@link MeshRendererComponent}, {@link CameraComponent}, {@link LightComponent} and {@link ScriptComponent} automatically.
	 * @example
	 * // Register the animation component type so that animations
	 * // can be automatically created.
	 * gooRunner.world.registerComponent(AnimationComponent);
	 *
	 * @param {Component} componentConstructor
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.registerComponent = function (componentConstructor) {
		if (this._components.indexOf(componentConstructor) === -1) {
			this._components.push(componentConstructor);
		}
		return this;
	};

	/**
	 * Adds a {@link Manager} to the world.
	 *
	 * @param {Manager} manager
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.setManager = function (manager) {
		this._managers.push(manager);
		manager.applyAPI(this.by);
		return this;
	};

	/**
	 * Retrieves a {@link Manager} of a certain type.
	 *
	 * @param {String} type Type of manager to retrieve eg. 'EntityManager'.
	 * @returns {Manager}
	 */
	World.prototype.getManager = function (type) {
		for (var i = 0; i < this._managers.length; i++) {
			var manager = this._managers[i];
			if (manager.type === type) {
				return manager;
			}
		}
	};

	/**
	 * Adds a {@link System} to the world.
	 *
	 * @param {System} system
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.setSystem = function (system) {
		var priority = system.priority;

		for (var i = 0; i < this._systems.length; i++) {
			if (this._systems[i].priority > priority) {
				break;
			}
		}
		this._systems.splice(i, 0, system);

		return this;
	};

	/**
	 * Retrieve a {@link System} of type 'type'.
	 *
	 * @param {String} type Type of system to retrieve.
	 * @returns {System}
	 */
	World.prototype.getSystem = function (type) {
		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (system.type === type) {
				return system;
			}
		}
	};

	/**
	 * Removes the {@link System} of type 'type'.
	 * Entities tracked by the removed system will not get handled properly when they are removed from the world
	 * or when their components (that are tracked by this system) change.
	 *
	 * @param {String} type Type of system to remove.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.clearSystem = function (type) {
		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (system.type === type) {
				this._systems.splice(i, 1);
			}
		}
		return this;
	};

	/**
	 * Creates a new {@link Entity} with an optional MeshData, MeshRenderer, Camera, Script and Light component, placed optionally at a location. Parameters can be given in any order.
	 * @example
	 * // Create a sphere entity and add it to the world
	 * var sphereEntity = world.createEntity(new Sphere(32, 32), material, [0, 0, 5]).addToWorld();
	 * // Create a camera entity and add it to the world
	 * var cameraEntity = world.createEntity(new Camera(), [0, 0, 3]).lookAt(new Vector3(0, 0, 0)).addToWorld();
	 *
	 * @param {MeshData} [meshData]
	 * @param {Material} [material]
	 * @param {String} [name]
	 * @param {Camera} [camera]
	 * @param {Light} [light]
	 * @returns {Entity}
	 */
	World.prototype.createEntity = function () {
		var entity = new Entity(this);
		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] === 'string') { // does not cover new String()
				entity.name = arguments[i];
			} else {
				entity.set(arguments[i]);
			}
		}

		// separate treatment
		if (!entity.transformComponent) {
			entity.setComponent(new TransformComponent());
		}

		return entity;
	};

	/**
	 * Get an array of all entities in world.
	 *
	 * @returns {Entity[]} All entities existing in world.
	 */
	World.prototype.getEntities = function () {
		return this.entityManager.getEntities();
	};

	/**
	 * Add an {@link Entity} to the world.
	 *
	 * @param {Entity} entity Entity to add.
	 * @param {boolean} [recursive=true] If entity hierarchy should be added recursively.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.addEntity = function (entity, recursive) {
		if (this._addedEntities.indexOf(entity) === -1) {
			this._addedEntities.push(entity);
		}

		if (entity.transformComponent && (recursive === undefined || recursive === true)) {
			var children = entity.transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this.addEntity(children[i].entity, recursive);
			}
		}

		return this;
	};

	/**
	 * Remove an {@link Entity} from the world.
	 *
	 * @param {Entity} entity Entity to remove.
	 * @param {boolean} [recursive=true] If entity hierarchy should be removed recursively.
	 * @returns {World} Returns self to allow chaining.
	 */
	World.prototype.removeEntity = function (entity, recursive) {
		if (this._removedEntities.indexOf(entity) === -1) {
			this._removedEntities.push(entity);
		}

		var transformComponent = entity.transformComponent;
		if (transformComponent.parent) {
			transformComponent.parent.detachChild(transformComponent);
			transformComponent.parent = null;
		}

		if (recursive === false) {
			var children = transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				children[i].parent = null;
			}

			transformComponent.children = [];
		} else {
			var children = transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this._recursiveRemoval(children[i].entity, recursive);
			}
		}

		return this;
	};

	World.prototype._recursiveRemoval = function (entity, recursive) {
		if (this._removedEntities.indexOf(entity) === -1) {
			this._removedEntities.push(entity);
		}

		if (entity.transformComponent && (recursive === undefined || recursive === true)) {
			var children = entity.transformComponent.children;
			for (var i = 0; i < children.length; i++) {
				this._recursiveRemoval(children[i].entity, recursive);
			}
		}
	};

	/**
	 * Let the world and its systems know that an entity has been changed/updated.
	 *
	 * @param entity
	 * @param component
	 * @param eventType
	 */
	World.prototype.changedEntity = function (entity, component, eventType) {
		var event = {
			entity: entity
		};
		if (component !== undefined) {
			event.component = component;
		}
		if (eventType !== undefined) {
			event.eventType = eventType;
		}
		this._changedEntities.push(event);
	};

	/**
	 * Handle newly added entities, changed entities and removed entities.
	 */
	World.prototype.handleEntityChanges = function () {
		this._check(this._addedEntities, function (observer, entity) {
			if (observer.added) {
				observer.added(entity);
			}

			// not in use by any system
			if (observer.addedComponent) {
				for (var i = 0; i < entity._components.length; i++) {
					observer.addedComponent(entity, entity._components[i]);
				}
			}
		});
		this._check(this._changedEntities, function (observer, event) {
			if (observer.changed) {
				observer.changed(event.entity);
			}
			if (event.eventType !== undefined) {
				if (observer[event.eventType]) {
					observer[event.eventType](event.entity, event.component);
				}
			}
		});
		this._check(this._removedEntities, function (observer, entity) {
			if (observer.removed) {
				observer.removed(entity);
			}

			// not in use by any system
			if (observer.removedComponent) {
				for (var i = 0; i < entity._components.length; i++) {
					observer.removedComponent(entity, entity._components[i]);
				}
			}
		});
	};

	/**
	 * Process all added/changed/removed entities and callback to active systems and managers. Usually called automatically each frame.
	 * Has to be called between adding an entity to the world and getting it back.
	 */
	World.prototype.process = function () {
		this.handleEntityChanges();

		for (var i = 0; i < this._systems.length; i++) {
			var system = this._systems[i];
			if (!system.passive) {
				system._process(this.tpf);
			}
		}
	};

	World.prototype._check = function (entities, callback) {
		for (var i = 0; i < entities.length; i++) {
			var entity = entities[i];
			for (var managerIndex = 0; managerIndex < this._managers.length; managerIndex++) {
				var manager = this._managers[managerIndex];
				callback(manager, entity);
			}
			for (var systemIndex = 0; systemIndex < this._systems.length; systemIndex++) {
				var system = this._systems[systemIndex];
				callback(system, entity);
			}
		}
		entities.length = 0;
	};

	return World;
});<|endoftext|>


<commit_before>// @flow
import * as Constants from '../../constants/profile'
import * as ProfileGen from '../profile-gen'
import * as RPCTypes from '../../constants/types/rpc-gen'
import * as RouteTreeGen from '../../actions/route-tree-gen'
import * as Saga from '../../util/saga'
import * as SearchConstants from '../../constants/search'
import * as TrackerConstants from '../../constants/tracker2'
import * as TrackerGen from '../tracker-gen'
import * as Tracker2Gen from '../tracker2-gen'
import keybaseUrl from '../../constants/urls'
import logger from '../../logger'
import openURL from '../../util/open-url'
import {getPathProps} from '../../route-tree'
import type {RPCError} from '../../util/errors'
import {peopleTab} from '../../constants/tabs'
import {pgpSaga} from './pgp'
import {proofsSaga} from './proofs'
import flags from '../../util/feature-flags'
import {isMobile} from '../../constants/platform'

const editProfile = (state, action) =>
  RPCTypes.userProfileEditRpcPromise(
    {
      bio: action.payload.bio,
      fullName: action.payload.fullname,
      location: action.payload.location,
    },
    TrackerConstants.waitingKey
  ).then(() => {
    if (flags.identify3) {
      return Tracker2Gen.createLoad({
        assertion: state.config.username,
        guiID: TrackerConstants.generateGUIID(),
        ignoreCache: true,
        inTracker: false,
        reason: '',
      })
    } else {
      return RouteTreeGen.createNavigateUp()
    }
  })

const uploadAvatar = (_, action) =>
  RPCTypes.userUploadUserAvatarRpcPromise(
    {
      crop: action.payload.crop,
      filename: action.payload.filename,
    },
    Constants.uploadAvatarWaitingKey
  )
    .then(() => RouteTreeGen.createNavigateUp())
    .catch(e => {
      // error displayed in component
      logger.warn(`Error uploading user avatar: ${e.message}`)
    })

const finishRevoking = () => [
  TrackerGen.createGetMyProfile({ignoreCache: true}),
  ProfileGen.createRevokeFinish(),
  RouteTreeGen.createNavigateUp(),
]

const showUserProfile = (state, action) => {
  const {username: userId} = action.payload
  // TODO search itself should handle this
  const username = SearchConstants.maybeUpgradeSearchResultIdToKeybaseId(
    state.entities.search.searchResults,
    userId
  )
  // Get the peopleTab path
  const peopleRouteProps = getPathProps(state.routeTree.routeState, [peopleTab])
  const path = Constants.getProfilePath(peopleRouteProps, username, state.config.username, state)
  // $FlowIssue
  return path && RouteTreeGen.createNavigateTo({path})
}

const onClickAvatar = (_, action) => {
  if (!action.payload.username) {
    return
  }

  if (!action.payload.openWebsite) {
    return ProfileGen.createShowUserProfile({username: action.payload.username})
  } else {
    openURL(`${keybaseUrl}/${action.payload.username}`)
  }
}

const submitRevokeProof = (_, action) =>
  RPCTypes.revokeRevokeSigsRpcPromise({sigIDQueries: [action.payload.proofId]}, Constants.waitingKey)
    .then(() => ProfileGen.createFinishRevoking())
    .catch((error: RPCError) => {
      logger.warn(`Error when revoking proof ${action.payload.proofId}`, error)
      return ProfileGen.createRevokeFinishError({
        error: 'There was an error revoking your proof. You can click the button to try again.',
      })
    })

const openURLIfNotNull = (nullableThing, url, metaText) => {
  if (nullableThing == null) {
    logger.warn("Can't open URL because we have a null", metaText)
    return
  }
  openURL(url)
}

const outputInstructionsActionLink = (state, action) => {
  const profile = state.profile
  switch (profile.platform) {
    case 'twitter':
      openURLIfNotNull(
        profile.proofText,
        `https://twitter.com/home?status=${profile.proofText || ''}`,
        'twitter url'
      )
      break
    case 'github':
      openURL('https://gist.github.com/')
      break
    case 'reddit':
      openURLIfNotNull(profile.proofText, profile.proofText, 'reddit url')
      break
    case 'facebook':
      openURLIfNotNull(profile.proofText, profile.proofText, 'facebook url')
      break
    case 'hackernews':
      openURL(`https://news.ycombinator.com/user?id=${profile.username}`)
      break
    default:
      break
  }
}

const editAvatar = () =>
  isMobile
    ? undefined // handled in platform specific
    : RouteTreeGen.createNavigateAppend({path: [{props: {image: null}, selected: 'editAvatar'}]})

const backToProfile = () => [
  TrackerGen.createGetMyProfile({}),
  RouteTreeGen.createNavigateTo({parentPath: [peopleTab], path: ['profile']}),
]

function* _profileSaga() {
  yield* Saga.chainAction<ProfileGen.SubmitRevokeProofPayload>(
    ProfileGen.submitRevokeProof,
    submitRevokeProof
  )
  yield* Saga.chainAction<ProfileGen.BackToProfilePayload>(ProfileGen.backToProfile, backToProfile)
  yield* Saga.chainAction<ProfileGen.EditProfilePayload>(ProfileGen.editProfile, editProfile)
  yield* Saga.chainAction<ProfileGen.UploadAvatarPayload>(ProfileGen.uploadAvatar, uploadAvatar)
  yield* Saga.chainAction<ProfileGen.FinishRevokingPayload>(ProfileGen.finishRevoking, finishRevoking)
  yield* Saga.chainAction<ProfileGen.OnClickAvatarPayload>(ProfileGen.onClickAvatar, onClickAvatar)
  yield* Saga.chainAction<ProfileGen.OutputInstructionsActionLinkPayload>(
    ProfileGen.outputInstructionsActionLink,
    outputInstructionsActionLink
  )
  yield* Saga.chainAction<ProfileGen.ShowUserProfilePayload>(ProfileGen.showUserProfile, showUserProfile)
  yield* Saga.chainAction<ProfileGen.EditAvatarPayload>(ProfileGen.editAvatar, editAvatar)
}

function* profileSaga(): Saga.SagaGenerator<any, any> {
  yield Saga.spawn(_profileSaga)
  yield Saga.spawn(pgpSaga)
  yield Saga.spawn(proofsSaga)
}

export default profileSaga
<commit_msg>reload profile on revoking proof (#16384)<commit_after>// @flow
import * as Constants from '../../constants/profile'
import * as ProfileGen from '../profile-gen'
import * as RPCTypes from '../../constants/types/rpc-gen'
import * as RouteTreeGen from '../../actions/route-tree-gen'
import * as Saga from '../../util/saga'
import * as SearchConstants from '../../constants/search'
import * as TrackerConstants from '../../constants/tracker2'
import * as TrackerGen from '../tracker-gen'
import * as Tracker2Gen from '../tracker2-gen'
import keybaseUrl from '../../constants/urls'
import logger from '../../logger'
import openURL from '../../util/open-url'
import {getPathProps} from '../../route-tree'
import type {RPCError} from '../../util/errors'
import {peopleTab} from '../../constants/tabs'
import {pgpSaga} from './pgp'
import {proofsSaga} from './proofs'
import flags from '../../util/feature-flags'
import {isMobile} from '../../constants/platform'

const editProfile = (state, action) =>
  RPCTypes.userProfileEditRpcPromise(
    {
      bio: action.payload.bio,
      fullName: action.payload.fullname,
      location: action.payload.location,
    },
    TrackerConstants.waitingKey
  ).then(() => {
    if (flags.identify3) {
      return Tracker2Gen.createLoad({
        assertion: state.config.username,
        guiID: TrackerConstants.generateGUIID(),
        ignoreCache: true,
        inTracker: false,
        reason: '',
      })
    } else {
      return RouteTreeGen.createNavigateUp()
    }
  })

const uploadAvatar = (_, action) =>
  RPCTypes.userUploadUserAvatarRpcPromise(
    {
      crop: action.payload.crop,
      filename: action.payload.filename,
    },
    Constants.uploadAvatarWaitingKey
  )
    .then(() => RouteTreeGen.createNavigateUp())
    .catch(e => {
      // error displayed in component
      logger.warn(`Error uploading user avatar: ${e.message}`)
    })

const finishRevoking = state => [
  TrackerGen.createGetMyProfile({ignoreCache: true}),
  Tracker2Gen.createLoad({
    assertion: state.config.username,
    guiID: TrackerConstants.generateGUIID(),
    inTracker: false,
    reason: 'justRevoked',
  }),
  ProfileGen.createRevokeFinish(),
  RouteTreeGen.createNavigateUp(),
]

const showUserProfile = (state, action) => {
  const {username: userId} = action.payload
  // TODO search itself should handle this
  const username = SearchConstants.maybeUpgradeSearchResultIdToKeybaseId(
    state.entities.search.searchResults,
    userId
  )
  // Get the peopleTab path
  const peopleRouteProps = getPathProps(state.routeTree.routeState, [peopleTab])
  const path = Constants.getProfilePath(peopleRouteProps, username, state.config.username, state)
  // $FlowIssue
  return path && RouteTreeGen.createNavigateTo({path})
}

const onClickAvatar = (_, action) => {
  if (!action.payload.username) {
    return
  }

  if (!action.payload.openWebsite) {
    return ProfileGen.createShowUserProfile({username: action.payload.username})
  } else {
    openURL(`${keybaseUrl}/${action.payload.username}`)
  }
}

const submitRevokeProof = (_, action) =>
  RPCTypes.revokeRevokeSigsRpcPromise({sigIDQueries: [action.payload.proofId]}, Constants.waitingKey)
    .then(() => ProfileGen.createFinishRevoking())
    .catch((error: RPCError) => {
      logger.warn(`Error when revoking proof ${action.payload.proofId}`, error)
      return ProfileGen.createRevokeFinishError({
        error: 'There was an error revoking your proof. You can click the button to try again.',
      })
    })

const openURLIfNotNull = (nullableThing, url, metaText) => {
  if (nullableThing == null) {
    logger.warn("Can't open URL because we have a null", metaText)
    return
  }
  openURL(url)
}

const outputInstructionsActionLink = (state, action) => {
  const profile = state.profile
  switch (profile.platform) {
    case 'twitter':
      openURLIfNotNull(
        profile.proofText,
        `https://twitter.com/home?status=${profile.proofText || ''}`,
        'twitter url'
      )
      break
    case 'github':
      openURL('https://gist.github.com/')
      break
    case 'reddit':
      openURLIfNotNull(profile.proofText, profile.proofText, 'reddit url')
      break
    case 'facebook':
      openURLIfNotNull(profile.proofText, profile.proofText, 'facebook url')
      break
    case 'hackernews':
      openURL(`https://news.ycombinator.com/user?id=${profile.username}`)
      break
    default:
      break
  }
}

const editAvatar = () =>
  isMobile
    ? undefined // handled in platform specific
    : RouteTreeGen.createNavigateAppend({path: [{props: {image: null}, selected: 'editAvatar'}]})

const backToProfile = () => [
  TrackerGen.createGetMyProfile({}),
  RouteTreeGen.createNavigateTo({parentPath: [peopleTab], path: ['profile']}),
]

function* _profileSaga() {
  yield* Saga.chainAction<ProfileGen.SubmitRevokeProofPayload>(
    ProfileGen.submitRevokeProof,
    submitRevokeProof
  )
  yield* Saga.chainAction<ProfileGen.BackToProfilePayload>(ProfileGen.backToProfile, backToProfile)
  yield* Saga.chainAction<ProfileGen.EditProfilePayload>(ProfileGen.editProfile, editProfile)
  yield* Saga.chainAction<ProfileGen.UploadAvatarPayload>(ProfileGen.uploadAvatar, uploadAvatar)
  yield* Saga.chainAction<ProfileGen.FinishRevokingPayload>(ProfileGen.finishRevoking, finishRevoking)
  yield* Saga.chainAction<ProfileGen.OnClickAvatarPayload>(ProfileGen.onClickAvatar, onClickAvatar)
  yield* Saga.chainAction<ProfileGen.OutputInstructionsActionLinkPayload>(
    ProfileGen.outputInstructionsActionLink,
    outputInstructionsActionLink
  )
  yield* Saga.chainAction<ProfileGen.ShowUserProfilePayload>(ProfileGen.showUserProfile, showUserProfile)
  yield* Saga.chainAction<ProfileGen.EditAvatarPayload>(ProfileGen.editAvatar, editAvatar)
}

function* profileSaga(): Saga.SagaGenerator<any, any> {
  yield Saga.spawn(_profileSaga)
  yield Saga.spawn(pgpSaga)
  yield Saga.spawn(proofsSaga)
}

export default profileSaga
<|endoftext|>


<commit_before>(function() {
     function ModalCtrl($uibModal) {
        var modal = this;
		modal.open = function (size, parentSelector) {
			var parentElem = parentSelector ? angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;

			var modalInstance = $uibModal.open({
				ariaLabelledBy: 'modal-title',
				ariaDescripedBy: 'modal-body',
				templateUrl: 'modal.html'
				controller: 'ModalCtrl',
				controllerAs: 'modal'
				size: size,
				appendTo: parentElem,
				resolve: {
					return modal,
				}
			});

		}

     }

     angular
         .module('blocChat')
         .controller('ModalCtrl', ['RoomCtrl', 'Room', 'ui.bootstrap', ModalCtrl]);
 })();
<commit_msg>updated ModalCtrl<commit_after>(function() {
     function ModalCtrl($uibModal) {
        var modal = this;
		modal.open = function (size, parentSelector) {
			var parentElem = parentSelector ? angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;

			var modalInstance = $uibModal.open({
				ariaLabelledBy: 'modal-title',
				ariaDescripedBy: 'modal-body',
				templateUrl: 'modal.html'
				controller: 'ModalCtrl',
				controllerAs: 'modal'
				size: size,
				appendTo: parentElem,
				resolve: {
					return modal,
				}
			});

		}

     }

     angular
         .module('blocChat')
         .controller('ModalCtrl', ModalCtrl);
 })();
<|endoftext|>


<commit_before>function scatterChart() {
  /*
   * Based on Mike Bostock's system for creating reusable charts, described
   * here: http://bost.ocks.org/mike/chart/
   *
   * My particular instance is based on the example used in that page
   * located here: http://bost.ocks.org/mike/chart/time-series-chart.js
   *
   * I added a Y axis, multiple lines.
   */
  var margin = {
    top : 20,
    right : 20,
    bottom : 30,
    left : 50
  };
  var width = 760;
  var height = 120;
  var xValue = function(d) {
    return +d[0];
  };
  var yValue = function(d) {
    return +d[1];
  };
  //var xScale = d3.scale.linear();
  var xScale = d3.time.scale();
  //var yScale = d3.scale.linear();
  var yScale = d3.scale.log();
  var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0);
  var yAxis = d3.svg.axis().scale(yScale).orient("left").tickSize(6, 0).ticks(5).tickFormat(function (d) {
    return yScale.tickFormat(10, d3.format(",d"))(d);
  });

  //var color = d3.scaleOrdinal(d3.schemeCategory10);
  var color = d3.scale.category10();

  //NEW
  //var area = d3.svg.area().x(X).y1(Y);
  var line = d3.svg.line()
      .interpolate("step-before")
      .x(X)
      .y(Y)
      .defined(function (d) { return d[1] !== null; });//This allows the line to break at null values.

  var xDomain = [];
  //leave empty. First time data are loaded, it will calculate the full x domain.
  var fullxDomain = [];
  var fullyDomain = [];

  function chart(selection) {
    selection.each(function(dataArray) {

      if (!xDomain.length) {//if xDomain hasn't been set yet, set it to the full domain.
        //xDomain = d3.extent(dataArray[0], function(d) { return d[0]; });
        xDomain = setFullxDomain();
      }

      // Update the full x & y domain.
      fullxDomain = setFullxDomain();
      fullyDomain = setFullyDomain();

      // Update the x-scale.
      xScale.domain(xDomain)//don't change the xDomain. Why not fullxDomain????
      .range([0, width - margin.left - margin.right]);

      // Update the y-scale.
      yScale
      //.domain([0, d3.max(dataArray[0], function(d) { return d[1]; })])//need to set extent in a new way, since some lines will have a different max.
      .domain(fullyDomain).range([height - margin.top - margin.bottom, 0]);

      // Select the svg element, if it exists.
      var svg = d3.select(this).selectAll("svg").data([dataArray]);
      //bind data to svg if it exists. IF it doesn't, then a new one will be made in the next line with the .enter(); WE only want one graph, so we should only have one element in the array.
      // Otherwise, create the skeletal chart.
      var gEnter = svg.enter().append("svg").append("g");
      //took out when I took out .data() above.

      var lineGroup = gEnter.append("g").attr("class", "lineGroup");
      var lineEnter = lineGroup.selectAll("path").data(dataArray).enter().append("path").attr("class", "line");
      //.attr("d", line);//don't draw the line yet. update the size of the svg first.

      gEnter.append("g").attr("class", "x axis");//is this name okay? It has a space!
      gEnter.append("g").attr("class", "y axis");

      var titleGroup = gEnter.append("g").attr("class", "titleGroup");
      titleGroup.append("svg:text").attr("class", "title").text("Stream Hydrograph");
      titleGroup.append("svg:text").attr("class", "subtitle").attr("dy", "1em");

      // Update the outer dimensions.
      svg.attr("width", width).attr("height", height);

      // Update the inner dimensions.
      var g = svg.select("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      // Update the lines.
      g.selectAll(".line").attr("d", line).attr("stroke", function(d, i) {return color(i);});

      // Update the x-axis.
      g.select(".x.axis").attr("transform", "translate(0," + yScale.range()[0] + ")").call(xAxis).on("click", myClickFunction);

      // Update the y-axis.
      g.select(".y.axis").attr("transform", "translate(0," + xScale.range()[0] + ")").call(yAxis).on("click", myRClickFunction);

      //title block
      // Update the title.
      g.select(".titleGroup").attr("transform", "translate(10,-10)");
      g.select(".subtitle").text(dataArray.length + " lines");
      //title.on("click", myRClickFunction);

      //NEW click function for handling mouseclicks on an object.
      function myClickFunction() {//just a silly function taken from http://bl.ocks.org/mbostock/1166403
        console.log("click");

        var n = dataArray[0].length - 1, i = Math.floor(Math.random() * n / 2), j = i + Math.floor(Math.random() * n / 2) + 1;
        xDomain = [xValue(dataArray[0][i]), xValue(dataArray[0][j])];
        xScale.domain(xDomain);
        var t = g.transition().duration(750);
        t.select(".x.axis").call(xAxis);
        t.selectAll(".line").attr("d", line);
      }

      function myRClickFunction() {
        xDomain = setFullxDomain();
        console.log("myRClickFunction");
        xScale.domain(xDomain);
        var t = g.transition().duration(750);
        t.select(".x.axis").call(xAxis);
        t.selectAll(".line").attr("d", line);
      }

      function setFullxDomain() {
        //console.log("setFullxDomain");
        //set xmax and xmin to x value in first element in first array.
        var xmax = dataArray[0][0][0];
        var xmin = xmax;
        //console.log("xmax: " + xmax + " xmin: " + xmin);
        //d3.min(dataArray[0], xValue);
        var localxMax = xmax;
        var localxMin = xmax;
        var domain = [];

        //console.log("domain: " + domain);
        //console.log(domain);
        //domain = d3.extent(dataArray[0].map(function(d) {return d.date;}));
        //console.log("new domain: " );
        //console.log(domain);
        //x.domain(d3.extent(data.map(function(d) {return d.date;})));
        for ( i = 0; i < dataArray.length; i++) {
          //loop through each of the arrays.
          //console.log("localxMax before search: " + localxMax);
          localxMax = d3.max(dataArray[i], function(d) {
            return d[0];
          });
          //console.log("localxMax of dataArray[" + i + "] is: " + localxMax);
          if (localxMax > xmax) {
            xmax = localxMax;
          }
          localxMin = d3.min(dataArray[i], function(d) {
            return d[0];
          });
          if (localxMin < xmin) {
            xmin = localxMin;
          }//it will never be smaller than zero.

        }

        domain = [xmin, xmax];
        //console.log(domain);
        return domain;
      }

      function setFullyDomain() {
        //console.log("setFullyDomain");
        //set xmax and xmin to x value in first element in first array.
        var max = dataArray[0][0][1];
        var min = max;
        //console.log("max: " + max + " min: " + min);
        //d3.min(dataArray[0], xValue);
        var localMax = max;
        var localMin = max;
        var domain = [];

        //console.log("y domain: " + domain);
        //console.log(domain);
        //domain = d3.extent(dataArray[0].map(function(d) {return d.date;}));
        //console.log("new domain: " );
        //console.log(domain);
        //x.domain(d3.extent(data.map(function(d) {return d.date;})));
        for ( i = 0; i < dataArray.length; i++) {
          //loop through each of the arrays.
          //console.log("localyMax before search: " + localMax);
          localMax = d3.max(dataArray[i], function(d) {
            return d[1];
          });
          //console.log("localyMax of dataArray[" + i + "] is: " + localMax);
          if (localMax > max) {
            max = localMax;
          }
          localMin = d3.min(dataArray[i], function(d) {
            return d[1];
          });
          if (localMin < min) {
            min = localMin;
          }//it will never be smaller than zero unless it finds a negative value..

        }

        domain = [min, max];
        //console.log("domain min: " + domain[0] + ",  max: " + domain[1]);
        return domain;
      }

    });
  }

  // The x-accessor for the path generator; xScale âˆ˜ xValue.
  function X(d) {
    return xScale(d[0]);
  }

  // The x-accessor for the path generator; yScale âˆ˜ yValue.
  function Y(d) {
    return yScale(d[1]);
  }

  chart.margin = function(a) {
    if (!arguments.length)
      return margin;
    margin = a;
    return chart;
  };

  chart.width = function(a) {
    if (!arguments.length)
      return width;
    width = a;
    return chart;
  };

  chart.height = function(a) {
    if (!arguments.length)
      return height;
    height = a;
    return chart;
  };

  chart.x = function(a) {//Do we need this?
    if (!arguments.length)
      return xValue;
    xValue = a;
    return chart;
  };

  chart.y = function(a) {
    if (!arguments.length)
      return yValue;
    yValue = a;
    return chart;
  };

  chart.xscale = function(a) {
    if (!arguments.length){
      console.log(xScale);
      return xScale;
    }
    if (a ==="linear"){
      console.log("x:linear");
      xScale = d3.scale.linear();
    } else if (a === "log") {
      console.log("x:log");
      xScale = d3.scale.log();
    } else if (a === "time") {
      xScale = d3.time.scale();
      console.log("x:time");
    }
    return chart;
  };

  chart.yscale = function(a) {
    if (!arguments.length){
      console.log(yScale);
      return yScale;
    }
    if (a ==="linear"){
      console.log("y:linear");
      yScale = d3.scale.linear();
      yAxis.scale(yScale).orient("left").tickSize(6, 0).ticks(5);
    } else if (a === "log") {
      console.log("y:log");
      yScale = d3.scale.log();
      yAxis.tickFormat(function (d) {return yScale.tickFormat(10, d3.format(",d"))(d);});
    } else if (a === "time") {
      yScale = d3.time.scale();
      console.log("y:time");
    }
    return chart;
  };
  return chart;
}
<commit_msg>fix up title group for scatter.<commit_after>function scatterChart() {
  /*
   * Based on Mike Bostock's system for creating reusable charts, described
   * here: http://bost.ocks.org/mike/chart/
   *
   * My particular instance is based on the example used in that page
   * located here: http://bost.ocks.org/mike/chart/time-series-chart.js
   *
   * I added a Y axis, multiple lines.
   */
  var margin = {
    top : 20,
    right : 20,
    bottom : 30,
    left : 50
  };
  var width = 760;
  var height = 120;
  var xValue = function(d) {
    return +d[0];
  };
  var yValue = function(d) {
    return +d[1];
  };
  //var xScale = d3.scale.linear();
  var xScale = d3.time.scale();
  //var yScale = d3.scale.linear();
  var yScale = d3.scale.log();
  var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0);
  var yAxis = d3.svg.axis().scale(yScale).orient("left").tickSize(6, 0).ticks(5).tickFormat(function (d) {
    return yScale.tickFormat(10, d3.format(",d"))(d);
  });

  //var color = d3.scaleOrdinal(d3.schemeCategory10);
  var color = d3.scale.category10();

  //NEW
  //var area = d3.svg.area().x(X).y1(Y);
  var line = d3.svg.line()
      .interpolate("step-before")
      .x(X)
      .y(Y)
      .defined(function (d) { return d[1] !== null; });//This allows the line to break at null values.

  var xDomain = [];
  //leave empty. First time data are loaded, it will calculate the full x domain.
  var fullxDomain = [];
  var fullyDomain = [];

  function chart(selection) {
    selection.each(function(dataArray) {

      if (!xDomain.length) {//if xDomain hasn't been set yet, set it to the full domain.
        //xDomain = d3.extent(dataArray[0], function(d) { return d[0]; });
        xDomain = setFullxDomain();
      }

      // Update the full x & y domain.
      fullxDomain = setFullxDomain();
      fullyDomain = setFullyDomain();

      // Update the x-scale.
      xScale.domain(xDomain)//don't change the xDomain. Why not fullxDomain????
      .range([0, width - margin.left - margin.right]);

      // Update the y-scale.
      yScale
      //.domain([0, d3.max(dataArray[0], function(d) { return d[1]; })])//need to set extent in a new way, since some lines will have a different max.
      .domain(fullyDomain).range([height - margin.top - margin.bottom, 0]);

      // Select the svg element, if it exists.
      var svg = d3.select(this).selectAll("svg").data([dataArray]);
      //bind data to svg if it exists. IF it doesn't, then a new one will be made in the next line with the .enter(); WE only want one graph, so we should only have one element in the array.
      // Otherwise, create the skeletal chart.
      var gEnter = svg.enter().append("svg").append("g");
      //took out when I took out .data() above.

      var lineGroup = gEnter.append("g").attr("class", "lineGroup");
      var lineEnter = lineGroup.selectAll("path").data(dataArray).enter().append("path").attr("class", "line");
      //.attr("d", line);//don't draw the line yet. update the size of the svg first.

      gEnter.append("g").attr("class", "x axis");//is this name okay? It has a space!
      gEnter.append("g").attr("class", "y axis");

      var titleGroup = gEnter.append("g").attr("class", "titleGroup");
      titleGroup.append("svg:text").attr("class", "Title").text("Stream Hydrograph");
      titleGroup.append("svg:text").attr("class", "subtitle").attr("dy", "1em");
      titleGroup.append("svg:text").attr("class", "subtitle2").attr("dy", "2.2em");

      // Update the outer dimensions.
      svg.attr("width", width).attr("height", height);

      // Update the inner dimensions.
      var g = svg.select("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      // Update the lines.
      g.selectAll(".line").attr("d", line).attr("stroke", function(d, i) {return color(i);});

      // Update the x-axis.
      g.select(".x.axis").attr("transform", "translate(0," + yScale.range()[0] + ")").call(xAxis).on("click", myClickFunction);

      // Update the y-axis.
      g.select(".y.axis").attr("transform", "translate(0," + xScale.range()[0] + ")").call(yAxis).on("click", myRClickFunction);

      //title block
      // Update the title.
      g.select(".titleGroup").attr("transform", "translate(10,0)");
      g.select(".subtitle").text(dataArray.length + " lines");
      g.select(".subtitle2").text(dataArray[0].length + " measurements per line")
      //title.on("click", myRClickFunction);

      //NEW click function for handling mouseclicks on an object.
      function myClickFunction() {//just a silly function taken from http://bl.ocks.org/mbostock/1166403
        console.log("click");

        var n = dataArray[0].length - 1, i = Math.floor(Math.random() * n / 2), j = i + Math.floor(Math.random() * n / 2) + 1;
        xDomain = [xValue(dataArray[0][i]), xValue(dataArray[0][j])];
        xScale.domain(xDomain);
        var t = g.transition().duration(750);
        t.select(".x.axis").call(xAxis);
        t.selectAll(".line").attr("d", line);
      }

      function myRClickFunction() {
        xDomain = setFullxDomain();
        console.log("myRClickFunction");
        xScale.domain(xDomain);
        var t = g.transition().duration(750);
        t.select(".x.axis").call(xAxis);
        t.selectAll(".line").attr("d", line);
      }

      function setFullxDomain() {
        //console.log("setFullxDomain");
        //set xmax and xmin to x value in first element in first array.
        var xmax = dataArray[0][0][0];
        var xmin = xmax;
        //console.log("xmax: " + xmax + " xmin: " + xmin);
        //d3.min(dataArray[0], xValue);
        var localxMax = xmax;
        var localxMin = xmax;
        var domain = [];

        //console.log("domain: " + domain);
        //console.log(domain);
        //domain = d3.extent(dataArray[0].map(function(d) {return d.date;}));
        //console.log("new domain: " );
        //console.log(domain);
        //x.domain(d3.extent(data.map(function(d) {return d.date;})));
        for ( i = 0; i < dataArray.length; i++) {
          //loop through each of the arrays.
          //console.log("localxMax before search: " + localxMax);
          localxMax = d3.max(dataArray[i], function(d) {
            return d[0];
          });
          //console.log("localxMax of dataArray[" + i + "] is: " + localxMax);
          if (localxMax > xmax) {
            xmax = localxMax;
          }
          localxMin = d3.min(dataArray[i], function(d) {
            return d[0];
          });
          if (localxMin < xmin) {
            xmin = localxMin;
          }//it will never be smaller than zero.

        }

        domain = [xmin, xmax];
        //console.log(domain);
        return domain;
      }

      function setFullyDomain() {
        //console.log("setFullyDomain");
        //set xmax and xmin to x value in first element in first array.
        var max = dataArray[0][0][1];
        var min = max;
        //console.log("max: " + max + " min: " + min);
        //d3.min(dataArray[0], xValue);
        var localMax = max;
        var localMin = max;
        var domain = [];

        //console.log("y domain: " + domain);
        //console.log(domain);
        //domain = d3.extent(dataArray[0].map(function(d) {return d.date;}));
        //console.log("new domain: " );
        //console.log(domain);
        //x.domain(d3.extent(data.map(function(d) {return d.date;})));
        for ( i = 0; i < dataArray.length; i++) {
          //loop through each of the arrays.
          //console.log("localyMax before search: " + localMax);
          localMax = d3.max(dataArray[i], function(d) {
            return d[1];
          });
          //console.log("localyMax of dataArray[" + i + "] is: " + localMax);
          if (localMax > max) {
            max = localMax;
          }
          localMin = d3.min(dataArray[i], function(d) {
            return d[1];
          });
          if (localMin < min) {
            min = localMin;
          }//it will never be smaller than zero unless it finds a negative value..

        }

        domain = [min, max];
        //console.log("domain min: " + domain[0] + ",  max: " + domain[1]);
        return domain;
      }

    });
  }

  // The x-accessor for the path generator; xScale âˆ˜ xValue.
  function X(d) {
    return xScale(d[0]);
  }

  // The x-accessor for the path generator; yScale âˆ˜ yValue.
  function Y(d) {
    return yScale(d[1]);
  }

  chart.margin = function(a) {
    if (!arguments.length)
      return margin;
    margin = a;
    return chart;
  };

  chart.width = function(a) {
    if (!arguments.length)
      return width;
    width = a;
    return chart;
  };

  chart.height = function(a) {
    if (!arguments.length)
      return height;
    height = a;
    return chart;
  };

  chart.x = function(a) {//Do we need this?
    if (!arguments.length)
      return xValue;
    xValue = a;
    return chart;
  };

  chart.y = function(a) {
    if (!arguments.length)
      return yValue;
    yValue = a;
    return chart;
  };

  chart.xscale = function(a) {
    if (!arguments.length){
      console.log(xScale);
      return xScale;
    }
    if (a ==="linear"){
      console.log("x:linear");
      xScale = d3.scale.linear();
    } else if (a === "log") {
      console.log("x:log");
      xScale = d3.scale.log();
    } else if (a === "time") {
      xScale = d3.time.scale();
      console.log("x:time");
    }
    return chart;
  };

  chart.yscale = function(a) {
    if (!arguments.length){
      console.log(yScale);
      return yScale;
    }
    if (a ==="linear"){
      console.log("y:linear");
      yScale = d3.scale.linear();
      yAxis.scale(yScale).orient("left").tickSize(6, 0).ticks(5);
    } else if (a === "log") {
      console.log("y:log");
      yScale = d3.scale.log();
      yAxis.tickFormat(function (d) {return yScale.tickFormat(10, d3.format(",d"))(d);});
    } else if (a === "time") {
      yScale = d3.time.scale();
      console.log("y:time");
    }
    return chart;
  };
  return chart;
}
<|endoftext|>