<commit_before>/*
    These two variables get replaced with the respective values during the
    entrypoint script of the Docker container and depend on the environment variables
*/
var MC_BASE_HOST = ':base_host';
var MC_BASE_PORT = ':base_port';

/*
    Documents API
*/
function DocumentsApi(Converter) {
    if(MC_BASE_HOST.charAt(0) == ':') {
        MC_BASE_HOST='http://mc-server.kohn.io';
    }
    if(MC_BASE_PORT.charAt(0) == ':') {
        MC_BASE_PORT='80';
    }
    this.baseUrl = MC_BASE_HOST + ':' + MC_BASE_PORT;
};

DocumentsApi.prototype.queryDocumentsAsync = function(profileIds, fieldIds, orderAttr, orderDir, offset, limit, onlyCount) {
    var self = this;
    var url = this.baseUrl;
    url += '/documents/';

    var arguments = []

    if(profileIds) {
        arguments.push('profile-ids=' + profileIds.join(','));
    }
    if(fieldIds) {
        arguments.push('field-ids=' + fieldIds.join(','));
    }
    if(orderAttr) {
        if(orderAttr == 'pub_year') {
            orderAttr = 'year';
        }
        arguments.push('order-attr=' + orderAttr);
    }
    if(orderDir) {
        arguments.push('order-dir=' + orderDir);
    }
    if(offset) {
        arguments.push('offset='+offset);
    }
    if(limit) {
        arguments.push('limit='+limit);
    }
    if(onlyCount) {
        arguments.push('only-count='+onlyCount);
    }
    var argumentString = '?' + arguments.join('&');
    url += argumentString;

    // Log url request
    window.console&&console.log('GET ' + url);

    // Return ajax promise
    return jQuery.getJSON(url);
}

/*
  Profiles Api
*/
function ProfilesApi() {
  if(MC_BASE_HOST.charAt(0) == ':') {
      MC_BASE_HOST='http://mc-server.kohn.io';
  }
  if(MC_BASE_PORT.charAt(0) == ':') {
      MC_BASE_PORT='80';
  }
  this.baseUrl = MC_BASE_HOST + ':' + MC_BASE_PORT;
}

ProfilesApi.prototype.querySlimProfilesAsync = function() {
	var url = this.baseUrl;
	url += "/profiles/?slim=true";

  // Log url request
  window.console&&console.log('GET ' + url);

  // Return ajax promise
  return jQuery.getJSON(url);
}

var documentsApi = new DocumentsApi();
var profilesApi = new ProfilesApi();

// Object that will be used later to store the fetched slim profiles with their names
var profilePages = {};

/*
  For each .mc-documents tag, query the documents and add them to the page
*/
function queryDocuments() {
  // Loop through mc-documents
  jQuery('.mc-documents').each(function() {
      // Prepare target div && parent
      var target = jQuery(this);
      target.addClass('mc-loading');

      // Fetch all the data variables
      var profileIds = null;
      if(typeof jQuery(this).data('profileids') !== 'undefined'){
          var data = jQuery(this).data('profileids');
          if(data) {
              // Kill whitespace
              profileIds = data.replace(/[ \n\t]+/, '');
              // Split by comma
              profileIds = profileIds.split(',');
          }
      }
      var fieldIds = null;
      if(typeof jQuery(this).data('fieldids') !== 'undefined'){
          var data = jQuery(this).data('fieldids');
          if(data) {
              // Kill whitespace
              fieldIds = data.replace(/[ \n\t]+/, '');
              // Split by comma
              fieldIds = fieldIds.split(',');
          }
      }
      var orderAttr = 'year';
      if(typeof jQuery(this).data('orderattr') !== 'undefined'){
          var data = jQuery(this).data('orderattr');
          if(data) {
              orderAttr = data;
          }
      }
      var orderDir = 'desc';
      if(typeof jQuery(this).data('orderdir') !== 'undefined'){
          var data = jQuery(this).data('orderdir');
          if(data) {
              orderDir = data;
          }
      }
      var limit = '20';
      if(typeof jQuery(this).data('limit') !== 'undefined'){
          var data = jQuery(this).data('limit');
          if(data) {
              limit = data;
          }
      }

      // Trigger async fetch
      documentsApi.queryDocumentsAsync(profileIds, fieldIds, orderAttr, orderDir, 0, limit)
          .done(function(data) {
              var docs = '
';
              // loop through docs
              for (var i = 0; i < data.length; i++) {
                  docs += '
';
                  if(typeof data[i].title !== 'undefined') {
                    if(data[i].website) {
                      docs += '' + data[i].title + '';
                    } else {
                      docs += '' + data[i].title + '';
                    }
                    docs += '
';
                  }
                  if(typeof data[i].authors !== 'undefined') {
                    // Now try to find the profile pages for the different authors
                    // First prepare the authors string
                    var authors = data[i].authors.split(',');
                    authors = authors.map(function(author) {
                      return author.replace(/(^[,\s]+)|([,\s]+$)/g, '');
                    });
                    // Then probe with the previously fetched profilePages dict
                    for(var j = 0; j < authors.length; j++) {
                      var name = authors[j];
                      if(j > 0) {
                        docs += ', ';
                      }
                      if(name in profilePages) {
                        docs += '' + name + '';
                      } else {
                        docs += name;
                      }
                    }
                  }
                  if(typeof data[i].source !== "undefined" &&
                          typeof data[i].pub_year !== "undefined" &&
                          data[i].source != "" &&
                          data[i].pub_year != "") {
                      docs += '
' + data[i].source + ', ' + data[i].pub_year + '.
';
                  } else {
                      docs += '.
';
                  }
              }
              docs += '
';

              // update target
              target.removeClass('mc-loading');
              target.addClass('mc-loaded');
              setTimeout(function() { target.empty(); target.append(docs);}, 1100);
          })
          .fail(function(jqXHR, textStatus) {
              window.console&&console.log(textStatus);
          });
    });
}

// Function that is executed as soon as jquery is loaded
jQuery(document).ready(function() {
    // Dont use the cache in Ajax calls
    jQuery.ajaxSetup({ cache: false });

    // Check if there is a single mc-documents tag in the page
    if(jQuery('.mc-documents').length) {

      // Fetch the slim profiles for the page links
      profilesApi.querySlimProfilesAsync()
        .done(function(data) {
          for(var i=0; i<data.length; i++) {
            var slimProfile = data[i]
            profilePages[slimProfile["name"]] = slimProfile["page"];
          }
        })
        .fail(function(jqXHR, textStatus) {
          window.console&&console.log("Failed to fetch slim profiles!");
          window.console&&console.log("Proceeding with document download.");
          window.console&&console.log(textStatus);
        })
        .always(function() {
          queryDocuments();
        })
      }
});
<commit_msg>Added target blank to title hyperref<commit_after>/*
    These two variables get replaced with the respective values during the
    entrypoint script of the Docker container and depend on the environment variables
*/
var MC_BASE_HOST = ':base_host';
var MC_BASE_PORT = ':base_port';

/*
    Documents API
*/
function DocumentsApi(Converter) {
    if(MC_BASE_HOST.charAt(0) == ':') {
        MC_BASE_HOST='http://mc-server.kohn.io';
    }
    if(MC_BASE_PORT.charAt(0) == ':') {
        MC_BASE_PORT='80';
    }
    this.baseUrl = MC_BASE_HOST + ':' + MC_BASE_PORT;
};

DocumentsApi.prototype.queryDocumentsAsync = function(profileIds, fieldIds, orderAttr, orderDir, offset, limit, onlyCount) {
    var self = this;
    var url = this.baseUrl;
    url += '/documents/';

    var arguments = []

    if(profileIds) {
        arguments.push('profile-ids=' + profileIds.join(','));
    }
    if(fieldIds) {
        arguments.push('field-ids=' + fieldIds.join(','));
    }
    if(orderAttr) {
        if(orderAttr == 'pub_year') {
            orderAttr = 'year';
        }
        arguments.push('order-attr=' + orderAttr);
    }
    if(orderDir) {
        arguments.push('order-dir=' + orderDir);
    }
    if(offset) {
        arguments.push('offset='+offset);
    }
    if(limit) {
        arguments.push('limit='+limit);
    }
    if(onlyCount) {
        arguments.push('only-count='+onlyCount);
    }
    var argumentString = '?' + arguments.join('&');
    url += argumentString;

    // Log url request
    window.console&&console.log('GET ' + url);

    // Return ajax promise
    return jQuery.getJSON(url);
}

/*
  Profiles Api
*/
function ProfilesApi() {
  if(MC_BASE_HOST.charAt(0) == ':') {
      MC_BASE_HOST='http://mc-server.kohn.io';
  }
  if(MC_BASE_PORT.charAt(0) == ':') {
      MC_BASE_PORT='80';
  }
  this.baseUrl = MC_BASE_HOST + ':' + MC_BASE_PORT;
}

ProfilesApi.prototype.querySlimProfilesAsync = function() {
	var url = this.baseUrl;
	url += "/profiles/?slim=true";

  // Log url request
  window.console&&console.log('GET ' + url);

  // Return ajax promise
  return jQuery.getJSON(url);
}

var documentsApi = new DocumentsApi();
var profilesApi = new ProfilesApi();

// Object that will be used later to store the fetched slim profiles with their names
var profilePages = {};

/*
  For each .mc-documents tag, query the documents and add them to the page
*/
function queryDocuments() {
  // Loop through mc-documents
  jQuery('.mc-documents').each(function() {
      // Prepare target div && parent
      var target = jQuery(this);
      target.addClass('mc-loading');

      // Fetch all the data variables
      var profileIds = null;
      if(typeof jQuery(this).data('profileids') !== 'undefined'){
          var data = jQuery(this).data('profileids');
          if(data) {
              // Kill whitespace
              profileIds = data.replace(/[ \n\t]+/, '');
              // Split by comma
              profileIds = profileIds.split(',');
          }
      }
      var fieldIds = null;
      if(typeof jQuery(this).data('fieldids') !== 'undefined'){
          var data = jQuery(this).data('fieldids');
          if(data) {
              // Kill whitespace
              fieldIds = data.replace(/[ \n\t]+/, '');
              // Split by comma
              fieldIds = fieldIds.split(',');
          }
      }
      var orderAttr = 'year';
      if(typeof jQuery(this).data('orderattr') !== 'undefined'){
          var data = jQuery(this).data('orderattr');
          if(data) {
              orderAttr = data;
          }
      }
      var orderDir = 'desc';
      if(typeof jQuery(this).data('orderdir') !== 'undefined'){
          var data = jQuery(this).data('orderdir');
          if(data) {
              orderDir = data;
          }
      }
      var limit = '20';
      if(typeof jQuery(this).data('limit') !== 'undefined'){
          var data = jQuery(this).data('limit');
          if(data) {
              limit = data;
          }
      }

      // Trigger async fetch
      documentsApi.queryDocumentsAsync(profileIds, fieldIds, orderAttr, orderDir, 0, limit)
          .done(function(data) {
              var docs = '
';
              // loop through docs
              for (var i = 0; i < data.length; i++) {
                  docs += '
';
                  if(typeof data[i].title !== 'undefined') {
                    if(data[i].website) {
                      docs += '' + data[i].title + '';
                    } else {
                      docs += '' + data[i].title + '';
                    }
                    docs += '
';
                  }
                  if(typeof data[i].authors !== 'undefined') {
                    // Now try to find the profile pages for the different authors
                    // First prepare the authors string
                    var authors = data[i].authors.split(',');
                    authors = authors.map(function(author) {
                      return author.replace(/(^[,\s]+)|([,\s]+$)/g, '');
                    });
                    // Then probe with the previously fetched profilePages dict
                    for(var j = 0; j < authors.length; j++) {
                      var name = authors[j];
                      if(j > 0) {
                        docs += ', ';
                      }
                      if(name in profilePages) {
                        docs += '' + name + '';
                      } else {
                        docs += name;
                      }
                    }
                  }
                  if(typeof data[i].source !== "undefined" &&
                          typeof data[i].pub_year !== "undefined" &&
                          data[i].source != "" &&
                          data[i].pub_year != "") {
                      docs += '
' + data[i].source + ', ' + data[i].pub_year + '.
';
                  } else {
                      docs += '.
';
                  }
              }
              docs += '
';

              // update target
              target.removeClass('mc-loading');
              target.addClass('mc-loaded');
              setTimeout(function() { target.empty(); target.append(docs);}, 1100);
          })
          .fail(function(jqXHR, textStatus) {
              window.console&&console.log(textStatus);
          });
    });
}

// Function that is executed as soon as jquery is loaded
jQuery(document).ready(function() {
    // Dont use the cache in Ajax calls
    jQuery.ajaxSetup({ cache: false });

    // Check if there is a single mc-documents tag in the page
    if(jQuery('.mc-documents').length) {

      // Fetch the slim profiles for the page links
      profilesApi.querySlimProfilesAsync()
        .done(function(data) {
          for(var i=0; i<data.length; i++) {
            var slimProfile = data[i]
            profilePages[slimProfile["name"]] = slimProfile["page"];
          }
        })
        .fail(function(jqXHR, textStatus) {
          window.console&&console.log("Failed to fetch slim profiles!");
          window.console&&console.log("Proceeding with document download.");
          window.console&&console.log(textStatus);
        })
        .always(function() {
          queryDocuments();
        })
      }
});
<|endoftext|>


<commit_before>"use strict";

var CityTour = CityTour || {};

CityTour.SceneView = function(containerEl, initialWorldData, messageBroker) {
  var sceneBuilder = new CityTour.Scene.Builder();
  var scene = sceneBuilder.buildEmptyScene();
  var renderView = new CityTour.RenderView(containerEl, scene);
  var camera = renderView.camera();

  var reset = function(newWorldData) {
    var masterStartTime, masterEndTime;
    var terrainStartTime, terrainEndTime;
    var roadStartTime, roadEndTime;
    var buildingsStartTime, buildingsEndTime;

    destroyPreviousMeshes();

    masterStartTime = new Date();

    terrainStartTime = new Date();
    scene.add(sceneBuilder.buildTerrainMeshes(newWorldData.terrain, newWorldData.roadNetwork));
    terrainEndTime = new Date();

    roadStartTime = new Date();
    scene.add(sceneBuilder.buildRoadNetworkMeshes(newWorldData.terrain, newWorldData.roadNetwork));
    roadEndTime = new Date();

    buildingsStartTime = new Date();
    scene.add(sceneBuilder.buildBuildingMeshes(newWorldData.buildings, newWorldData.roadNetwork));
    buildingsEndTime = new Date();

    masterEndTime = new Date();

    console.log("Time to generate scene geometry: " + (masterEndTime - masterStartTime) + "ms");
    console.log("  Terrain:   " + (terrainEndTime - terrainStartTime) + "ms");
    console.log("  Roads:     " + (roadEndTime - roadStartTime) + "ms");
    console.log("  Buildings: " + (buildingsEndTime - buildingsStartTime) + "ms");

    renderView.resize();
  };

  var destroyPreviousMeshes = function() {
    var terrainMeshes = scene.getObjectByName("terrainMeshes");
    var roadNetworkMeshes = scene.getObjectByName("roadNetworkMeshes");
    var buildingMeshes = scene.getObjectByName("buildingMeshes");

    if (terrainMeshes !== undefined) {
      removeChildFromScene(terrainMeshes);
    }

    if (roadNetworkMeshes !== undefined) {
      removeChildFromScene(roadNetworkMeshes);
    }

    if (buildingMeshes !== undefined) {
      removeChildFromScene(buildingMeshes);
    }
  };

  // See https://stackoverflow.com/questions/25126352/deallocating-buffergeometry
  var removeChildFromScene = function(obj) {
    var i;
    for (i = obj.children.length - 1; i >= 0; i--) {
      removeChildFromScene(obj.children[i]);
    }

    scene.remove(obj);
    if (obj instanceof THREE.Mesh) {
      obj.geometry.dispose();
      obj.geometry = null;
      obj.material.dispose();
      obj.material = null;
    }

    obj = null;
  };

  var render = function() {
    renderView.render();
  };

  window.addEventListener('resize', renderView.resize, false);

  reset(initialWorldData);

  return {
    reset: reset,
    render: render,
    camera: function() { return camera; },
    domElement: function() { return renderView.domElement(); },
  };
};
<commit_msg>Add marker for center of city coordinates, for debugging<commit_after>"use strict";

var CityTour = CityTour || {};

CityTour.SceneView = function(containerEl, initialWorldData, messageBroker) {
  var SHOW_MARKERS = false;

  var sceneBuilder = new CityTour.Scene.Builder();
  var scene = sceneBuilder.buildEmptyScene();
  var renderView = new CityTour.RenderView(containerEl, scene);
  var camera = renderView.camera();

  var reset = function(newWorldData) {
    var masterStartTime, masterEndTime;
    var terrainStartTime, terrainEndTime;
    var roadStartTime, roadEndTime;
    var buildingsStartTime, buildingsEndTime;
    var markersStartTime, markersEndTime;

    destroyPreviousMeshes();

    masterStartTime = new Date();

    terrainStartTime = new Date();
    scene.add(sceneBuilder.buildTerrainMeshes(newWorldData.terrain, newWorldData.roadNetwork));
    terrainEndTime = new Date();

    roadStartTime = new Date();
    scene.add(sceneBuilder.buildRoadNetworkMeshes(newWorldData.terrain, newWorldData.roadNetwork));
    roadEndTime = new Date();

    buildingsStartTime = new Date();
    scene.add(sceneBuilder.buildBuildingMeshes(newWorldData.buildings, newWorldData.roadNetwork));
    buildingsEndTime = new Date();

    markersStartTime = new Date();
    if (SHOW_MARKERS) {
      scene.add(buildMarkerMeshes(newWorldData));
    }
    markersEndTime = new Date();

    masterEndTime = new Date();

    console.log("Time to generate scene geometry: " + (masterEndTime - masterStartTime) + "ms");
    console.log("  Terrain:   " + (terrainEndTime - terrainStartTime) + "ms");
    console.log("  Roads:     " + (roadEndTime - roadStartTime) + "ms");
    console.log("  Buildings: " + (buildingsEndTime - buildingsStartTime) + "ms");
    console.log("  Markers:   " + (markersEndTime - markersStartTime) + "ms");

    renderView.resize();
  };

  var buildMarkerMeshes = function(newWorldData) {
    var group = new THREE.Group();
    group.name = "markerMeshes";

    var centerOfCityMarkerMesh = new THREE.Mesh(new THREE.BoxGeometry(5, 200, 5),
                                                new THREE.MeshBasicMaterial({ color: 0xff00ff }));

    centerOfCityMarkerMesh.position.x = newWorldData.centerX;
    centerOfCityMarkerMesh.position.z = newWorldData.centerZ;

    group.add(centerOfCityMarkerMesh);

    return group;
  };

  var destroyPreviousMeshes = function() {
    var terrainMeshes = scene.getObjectByName("terrainMeshes");
    var roadNetworkMeshes = scene.getObjectByName("roadNetworkMeshes");
    var buildingMeshes = scene.getObjectByName("buildingMeshes");
    var markerMeshes = scene.getObjectByName("markerMeshes");

    if (terrainMeshes !== undefined) {
      removeChildFromScene(terrainMeshes);
    }

    if (roadNetworkMeshes !== undefined) {
      removeChildFromScene(roadNetworkMeshes);
    }

    if (buildingMeshes !== undefined) {
      removeChildFromScene(buildingMeshes);
    }

    if (markerMeshes !== undefined) {
      removeChildFromScene(markerMeshes);
    }
  };

  // See https://stackoverflow.com/questions/25126352/deallocating-buffergeometry
  var removeChildFromScene = function(obj) {
    var i;
    for (i = obj.children.length - 1; i >= 0; i--) {
      removeChildFromScene(obj.children[i]);
    }

    scene.remove(obj);
    if (obj instanceof THREE.Mesh) {
      obj.geometry.dispose();
      obj.geometry = null;
      obj.material.dispose();
      obj.material = null;
    }

    obj = null;
  };

  var render = function() {
    renderView.render();
  };

  window.addEventListener('resize', renderView.resize, false);

  reset(initialWorldData);

  return {
    reset: reset,
    render: render,
    camera: function() { return camera; },
    domElement: function() { return renderView.domElement(); },
  };
};
<|endoftext|>


<commit_before>import path from 'path';

import assert from 'yeoman-assert';
import helpers from 'yeoman-test';

describe('Generator', () => {
  beforeAll(() =>
    helpers.run(path.join(__dirname, '../app')).inTmpDir().withPrompts({
      moduleName: 'bunny module',
      description: 'as cute as bunny',
      githubUsername: 'bunny',
      website: 'www.wewww.com',
      name: 'yo',
      email: 'hi@bunny.io',
    })
  );

  it('can be required without throwing', () => {
    const app = require('./'); // eslint-disable-line
    assert(app);
  });

  it('generates files', () => {
    assert.file([
      '.all-contributorsrc',
      '.babelrc',
      '.editorconfig',
      '.eslintignore',
      '.eslintrc.json',
      '.flowconfig',
      '.gitattributes',
      '.gitignore',
      '.npmrc',
      '.travis.yml',
      'changelog.md',
      'contributing.md',
      'license',
      'package-scripts.js',
      'package.json',
      'readme.md',
      'src/index.js',
      'src/index.test.js',
    ]);
    assert.noFile('yo-rc.json');
  });

  describe('templating', () => {
    it('fills package.json with correct informations', () => {
      assert.JSONFileContent('package.json', {
        name: 'bunny-module',
        description: 'as cute as bunny',
        repository: {
          type: 'git',
          url: 'git+https://github.com/bunny/bunny-module.git',
        },
        author: {
          name: 'yo',
          email: 'hi@bunny.io',
          url: 'www.wewww.com',
        },
      });
    });

    describe('readme.md', () => {
      it('fills the title & description', () => {
        assert.fileContent('readme.md', '# bunny-module');
        assert.fileContent('readme.md', '> as cute as bunny');
      });

      describe('badges', () => {
        it('package version', () => {
          assert.fileContent(
            'readme.md',
            '[![npm](https://img.shields.io/npm/v/bunny-module.svg?style=flat-square)](https://www.npmjs.com/package/bunny-module)'
          );
        });

        it('download stats', () => {
          assert.fileContent(
            'readme.md',
            '[![npm](https://img.shields.io/npm/dt/bunny-module.svg?style=flat-square)](https://npm-stat.com/charts.html?package=bunny-module&from=2016-04-01)'
          );
        });

        it('build status', () => {
          assert.fileContent(
            'readme.md',
            '[![Travis branch](https://img.shields.io/travis/bunny-module/rust/master.svg?style=flat-square)](https://travis-ci.org/bunny/bunny-module)'
          );
        });

        it('coverage', () => {
          assert.fileContent(
            'readme.md',
            '[![Codecov branch](https://img.shields.io/codecov/c/github/bunny/bunny-module/master.svg?style=flat-square)](https://codecov.io/github/bunny/bunny-module)'
          );
        });

        it('COC', () => {
          assert.fileContent(
            'readme.md',
            '[![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](./other/code_of_conduct.md)'
          );
        });

        it('roadmap', () => {
          assert.fileContent(
            'readme.md',
            '[![Roadmap](https://img.shields.io/badge/%F0%9F%93%94-roadmap-CD9523.svg?style=flat-square)](./other/roadmap.md)'
          );
        });
      });

      it('fills the installation instructions', () => {
        assert.fileContent('readme.md', 'npm install --save bunny-module');
      });

      it('fills the usage instructions', () => {
        assert.fileContent(
          'readme.md',
          'import bunnyModule from \'bunny-module\''
        );
      });

      it('fills the FAQ', () => {
        assert.fileContent('readme.md', '### Why should I use `bunny-module`?');
      });

      it('fills the license', () => {
        assert.fileContent('readme.md', 'MIT © [yo](www.wewww.com)');
      });
    });

    it('fiils the license', () => {
      assert.fileContent(
        'license',
        'Copyright (c) yo <hi@bunny.io>'
      );
    });
  });
});
<commit_msg>test: update specs for `license`<commit_after>import path from 'path';

import assert from 'yeoman-assert';
import helpers from 'yeoman-test';

describe('Generator', () => {
  beforeAll(() =>
    helpers.run(path.join(__dirname, '../app')).inTmpDir().withPrompts({
      moduleName: 'bunny module',
      description: 'as cute as bunny',
      githubUsername: 'bunny',
      website: 'www.wewww.com',
      name: 'yo',
      email: 'hi@bunny.io',
    })
  );

  it('can be required without throwing', () => {
    const app = require('./'); // eslint-disable-line
    assert(app);
  });

  it('generates files', () => {
    assert.file([
      '.all-contributorsrc',
      '.babelrc',
      '.editorconfig',
      '.eslintignore',
      '.eslintrc.json',
      '.flowconfig',
      '.gitattributes',
      '.gitignore',
      '.npmrc',
      '.travis.yml',
      'changelog.md',
      'contributing.md',
      'license',
      'package-scripts.js',
      'package.json',
      'readme.md',
      'src/index.js',
      'src/index.test.js',
    ]);
    assert.noFile('yo-rc.json');
  });

  describe('templating', () => {
    it('fills package.json with correct informations', () => {
      assert.JSONFileContent('package.json', {
        name: 'bunny-module',
        description: 'as cute as bunny',
        repository: {
          type: 'git',
          url: 'git+https://github.com/bunny/bunny-module.git',
        },
        author: {
          name: 'yo',
          email: 'hi@bunny.io',
          url: 'www.wewww.com',
        },
      });
    });

    describe('readme.md', () => {
      it('fills the title & description', () => {
        assert.fileContent('readme.md', '# bunny-module');
        assert.fileContent('readme.md', '> as cute as bunny');
      });

      describe('badges', () => {
        it('package version', () => {
          assert.fileContent(
            'readme.md',
            '[![npm](https://img.shields.io/npm/v/bunny-module.svg?style=flat-square)](https://www.npmjs.com/package/bunny-module)'
          );
        });

        it('download stats', () => {
          assert.fileContent(
            'readme.md',
            '[![npm](https://img.shields.io/npm/dt/bunny-module.svg?style=flat-square)](https://npm-stat.com/charts.html?package=bunny-module&from=2016-04-01)'
          );
        });

        it('build status', () => {
          assert.fileContent(
            'readme.md',
            '[![Travis branch](https://img.shields.io/travis/bunny-module/rust/master.svg?style=flat-square)](https://travis-ci.org/bunny/bunny-module)'
          );
        });

        it('coverage', () => {
          assert.fileContent(
            'readme.md',
            '[![Codecov branch](https://img.shields.io/codecov/c/github/bunny/bunny-module/master.svg?style=flat-square)](https://codecov.io/github/bunny/bunny-module)'
          );
        });

        it('COC', () => {
          assert.fileContent(
            'readme.md',
            '[![Code of Conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square)](./other/code_of_conduct.md)'
          );
        });

        it('roadmap', () => {
          assert.fileContent(
            'readme.md',
            '[![Roadmap](https://img.shields.io/badge/%F0%9F%93%94-roadmap-CD9523.svg?style=flat-square)](./other/roadmap.md)'
          );
        });
      });

      it('fills the installation instructions', () => {
        assert.fileContent('readme.md', 'npm install --save bunny-module');
      });

      it('fills the usage instructions', () => {
        assert.fileContent(
          'readme.md',
          'import bunnyModule from \'bunny-module\''
        );
      });

      it('fills the FAQ', () => {
        assert.fileContent('readme.md', '### Why should I use `bunny-module`?');
      });

      it('fills the license', () => {
        assert.fileContent('readme.md', 'MIT © [yo](www.wewww.com)');
      });
    });

    describe('license', () => {
      it('fiils the authors & email', () => {
        assert.fileContent(
          'license',
          'Copyright (c) yo <hi@bunny.io>'
        );
      });
    });
  });
});
<|endoftext|>


<commit_before>var $Q, $, Globalize, _, Backbone, Highcharts, L, Piwik;
(function() {
  var environment = 'dev', // 'dev' (development) or 'pr' (production)
    defaultLanguage = 'en',
    getNavigatorLanguage = function () {
      var language = defaultLanguage;
      if (window.navigator) {
        language = (window.navigator.language || window.navigator.userLanguage).split('-')[0]
      }
      return language;
    },
    getCulture = function () {
      var availableLanguages = ['es', 'en'],
        clientLanguage = getNavigatorLanguage(),
        selectedLanguage = (availableLanguages.indexOf(clientLanguage) !== -1) ? clientLanguage : defaultLanguage;
      document.getElementsByTagName('html')[0].lang = selectedLanguage;
      return selectedLanguage;
    },
    getFirefoxOS = function () {
      var manifestUrl = window.location.origin + window.location.pathname + 'platforms/firefoxOS/manifest.webapp',
        installCheck,
        isInstalled = false,
        config = {
          enabled: false,
          installed: isInstalled,
          url: manifestUrl
        };
      if (navigator.mozApps !== undefined) {
        installCheck = navigator.mozApps.checkInstalled(manifestUrl);
        installCheck.onsuccess = function() {
          if(installCheck.result.installState === 'installed') {
            isInstalled = true;
          }
        };
        config = {
          enabled: true,
          installed: isInstalled,
          url: manifestUrl
        };
      }
      return config;
    };

  $Q = {
    appName: 'Borrasca-Next',
    appTitle: 'Borrasca-Next - ',
    version: (environment === 'pr') ? '2.3.1.0' : Date.now(),
    servicePath: (document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1) ? 'http://borrasca-next.digitalpapyrus.es/' : '',
    server: (window.location.port === '9000') ? 'node' : 'php', // 'node' or 'php'
    waitOnInitialize: 40,
    culture: getCulture(),
    compressed: false,
    legacy: true,
    geolocation: null,
    templatesReady: false,
    jsLibs: {
      route: (!this.compressed) ? 'libs/': 'libs/min/',
      versions: {
        jquery: (this.legacy) ? '1.10.2' : '2.0.3',
        underscore: '1.5.1',
        lodash: '2.1.0',
        backbone: '1.1.0',
        requireText: '2.0.7',
        requireAsync: '0.1.1',
        highcharts: '3.0.2',
        bootstrap: '3.0.0',
        jquery_sliceSlide: '4.0',
        leaflet: '0.6.4'
      },
      equivalent: {
        underscore: 'lodash' // 'lodash' or 'underscore'
      }
    },
    templates: {
      route: '../tmpl/',
      routeCultures: '../cultures/'
    },
    images: {
      route: 'img'
    },
    maps: {
      autoStart: false
    },
    platforms: {
      firefoxOS: getFirefoxOS()
    },
    links: {
      github: 'https://github.com/jervert/borrasca-next',
      googlePlay: 'https://play.google.com/store/apps/details?id=com.phonegap.borrasca_v2'
    },
    piwik: {
      enabled: false,
      ready: false,
      url: null,
      id: '2'
    },
    adsense: {
      enabled: true
    },
    views: {},
    removableViews: ['detail', 'nowAndHere']
  };

  $Q.alternateCulture = ($Q.culture === 'es') ? 'sp' : $Q.culture;

  $Q.services = {
    main: ($Q.server === 'php') ? $Q.servicePath + 'services/main.php?lang=' + $Q.alternateCulture + '&geolocation=' : $Q.servicePath + '?lang=' + $Q.alternateCulture + '&geolocation=',
    search: ($Q.server === 'php') ? $Q.servicePath + 'services/search.php?location_name=' : $Q.servicePath + '?location_name=',
    detail: ($Q.server === 'php') ? $Q.servicePath + 'services/detail.php?lang=' + $Q.alternateCulture + '&location_name=' : $Q.servicePath + '?detail=true&lang=' + $Q.alternateCulture + '&version=' + Date.now() + '&location_name=',
    xml: ($Q.server === 'php') ? $Q.servicePath + 'services/xml.php?location_id=' : $Q.servicePath + '?xml='
  }

  require.config({
    paths: {
      text: 'libs/require.text-' + $Q.jsLibs.versions.requireText,
      async: 'libs/require.async-' + $Q.jsLibs.versions.requireAsync,
      'jquery': $Q.jsLibs.route + 'jquery-' + $Q.jsLibs.versions.jquery,
      'globalize': 'libs/globalize',
      'globalize_culture': $Q.templates.routeCultures + 'globalize/globalize.culture.' + $Q.culture,
      'underscore': ($Q.jsLibs.equivalent.underscore === 'lodash') ? $Q.jsLibs.route + 'lodash.underscore-' + $Q.jsLibs.versions.lodash : $Q.jsLibs.route + 'underscore-' + $Q.jsLibs.versions.underscore,
      'backbone': $Q.jsLibs.route + 'backbone-' + $Q.jsLibs.versions.backbone,
      'highcharts': $Q.jsLibs.route + 'highcharts-' + $Q.jsLibs.versions.highcharts,
      'bootstrap': $Q.jsLibs.route + 'bootstrap-' + $Q.jsLibs.versions.bootstrap,
      'jquery_sliceSlide': $Q.jsLibs.route + 'slice-slide/jquery.sliceslide-' + $Q.jsLibs.versions.jquery_sliceSlide,
      'leaflet': $Q.jsLibs.route + 'leaflet-' + $Q.jsLibs.versions.leaflet,
      'adsense': window.location.protocol + '//pagead2.googlesyndication.com/pagead/js/adsbygoogle',
      'piwik': window.location.protocol + '//' + $Q.piwik.url + '/piwik',
      'mixins': 'br.mixins',
      'br_ui': 'br.ui',
      'br_utils': 'br.utils',
      'br_routes': 'br.routes',
      'br_extend_view': 'br.extendView',
      'mvc_main': 'mvc/main.mvc',
      'mvc_search': 'mvc/search.mvc',
      'mvc_bookmarks': 'mvc/bookmarks.mvc',
      'mvc_nowAndHere': 'mvc/nowAndHere.mvc',
      'mvc_detail': 'mvc/detail.mvc',
      'mvc_install': 'mvc/install.mvc'
    },
    shim: {
      'underscore': {
        deps: [],
        exports: '_'
      },
      'backbone': {
        deps: ['jquery', 'underscore'],
        exports: 'Backbone'
      },
      'highcharts': {
        deps: ['jquery'],
        exports: 'Highcharts'
      },
      'globalize': {
        deps: ['jquery'],
        exports: 'Globalize'
      },
      'globalize_culture': {
        deps: ['globalize']
      },
      'bootstrap': {
        deps: ['jquery']
      },
      'jquery_sliceSlide': {
        deps: ['jquery', 'underscore']
      },
      'leaflet': {
        exports: 'L'
      },
      'mixins': {
        deps: ['jquery', 'underscore']
      },
      'br_ui': {
        deps: ['jquery', 'underscore']
      },
      'br_utils': {
        deps: ['jquery', 'underscore']
      },
      'br_routes': {
        deps: ['backbone']
      },
      'br_extend_view': {
        deps: ['br_utils', 'br_routes', 'globalize', 'mixins', 'br_ui', 'bootstrap']
      },
      'mvc_main': {
        deps: ['br_extend_view']
      },
      'mvc_search': {
        deps: ['mvc_main']
      },
      'mvc_bookmarks': {
        deps: ['mvc_main']
      },
      'mvc_nowAndHere': {
        deps: ['mvc_main']
      },
      'mvc_detail': {
        deps: ['mvc_main', 'leaflet']
      },
      'mvc_install': {
        deps: ['mvc_main']
      }
    },
    waitSeconds: 40,
    urlArgs: $Q.version
  });

  $Q.resourcesJs = [
    'jquery',
    'globalize',
    'underscore',
    'backbone',
    'highcharts',
    'leaflet',
    'jquery_sliceSlide',
    'globalize_culture',
    'mixins',
    'br_ui',
    'br_utils',
    'br_routes',
    'br_extend_view',
    'mvc_main',
    'mvc_search',
    'mvc_bookmarks',
    'mvc_nowAndHere',
    'mvc_detail',
    'mvc_install',
    'br.app.aemet'
  ];
  if ($Q.adsense.enabled) {
    $Q.resourcesJs.push('adsense');
  }
  if ($Q.piwik.enabled) {
    $Q.resourcesJs.push('piwik');
  }

  $Q.resourcesText = [
    'text!' + $Q.templates.routeCultures + 'text_' + $Q.culture + '.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_loading.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_messages_error.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_map_layers.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_current_weather.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_buttons_refresh.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_map_container.html',
    'text!' + $Q.templates.route + 'tmpl_main.html',
    'text!' + $Q.templates.route + 'tmpl_search.html',
    'text!' + $Q.templates.route + 'tmpl_bookmarks.html',
    'text!' + $Q.templates.route + 'tmpl_now_and_here.html',
    'text!' + $Q.templates.route + 'tmpl_detail.html',
    'text!' + $Q.templates.route + 'tmpl_install.html'
  ];

  $Q.initialize = function () {
    $Q.utils.getGeolocation();
    $(document).on('geolocated', function () {
      $Q.app_router = new $Q.AppRouter();
      $Q.views.mainView = new $Q.MainView();
      Backbone.history.start();
    });
  }

  define($Q.resourcesJs.concat($Q.resourcesText), function () {
    var templates = '',
      l = arguments.length,
      i;
    $ = arguments[0];
    Globalize = arguments[1];
    _ = arguments[2];
    Backbone = arguments[3];
    Highcharts = arguments[4];
    L = arguments[5];
    for (i = 5; i < l; i += 1) {
      if (typeof arguments[i] === 'string') {
        templates += arguments[i];
      }
    }

    Globalize.culture($Q.culture);
    $('title').text($Q.appTitle + $Q.version);

    $Q.supported = {
      html5: {
        storage: _.support_html5_storage()
      }
    };
    if ($Q.supported.html5.storage) {
      if (_.isEmpty(localStorage.getItem('appData'))) {
        localStorage.setItem('appData', JSON.stringify({locations: [], locationsName: []}));
      }
    }

    $.when($('#templates-area').append(templates)).then(function () {
      $Q.templatesReady = true;
      if ($Q.piwik.enabled) {
        $Q.utils.piwikStats.start();
        $Q.utils.piwikStats.trackPageView(window.location.hash);
      }
      $Q.initialize();
    });
  });

}());
<commit_msg>verify if is Phonegap app<commit_after>var $Q, $, Globalize, _, Backbone, Highcharts, L, Piwik;
(function() {
  var environment = 'dev', // 'dev' (development) or 'pr' (production)
    defaultLanguage = 'en',
    guessIfIsPhonegapApp = function () {
      return (document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1)
    },
    isPhonegapApp = guessIfIsPhonegapApp(),
    getNavigatorLanguage = function () {
      var language = defaultLanguage;
      if (window.navigator) {
        language = (window.navigator.language || window.navigator.userLanguage).split('-')[0]
      }
      return language;
    },
    getCulture = function () {
      var availableLanguages = ['es', 'en'],
        clientLanguage = getNavigatorLanguage(),
        selectedLanguage = (availableLanguages.indexOf(clientLanguage) !== -1) ? clientLanguage : defaultLanguage;
      document.getElementsByTagName('html')[0].lang = selectedLanguage;
      return selectedLanguage;
    },
    getFirefoxOS = function () {
      var manifestUrl = window.location.origin + window.location.pathname + 'platforms/firefoxOS/manifest.webapp',
        installCheck,
        isInstalled = false,
        config = {
          enabled: false,
          installed: isInstalled,
          url: manifestUrl
        };
      if (navigator.mozApps !== undefined) {
        installCheck = navigator.mozApps.checkInstalled(manifestUrl);
        installCheck.onsuccess = function() {
          if(installCheck.result.installState === 'installed') {
            isInstalled = true;
          }
        };
        config = {
          enabled: true,
          installed: isInstalled,
          url: manifestUrl
        };
      }
      return config;
    };

  $Q = {
    appName: 'Borrasca-Next',
    appTitle: 'Borrasca-Next - ',
    version: (environment === 'pr' || isPhonegapApp) ? '2.3.1.0' : Date.now(),
    servicePath: (isPhonegapApp) ? 'http://borrasca-next.digitalpapyrus.es/' : '',
    server: (window.location.port === '9000') ? 'node' : 'php', // 'node' or 'php'
    waitOnInitialize: 40,
    culture: getCulture(),
    compressed: false,
    legacy: true,
    geolocation: null,
    templatesReady: false,
    jsLibs: {
      route: (!this.compressed) ? 'libs/': 'libs/min/',
      versions: {
        jquery: (this.legacy) ? '1.10.2' : '2.0.3',
        underscore: '1.5.1',
        lodash: '2.1.0',
        backbone: '1.1.0',
        requireText: '2.0.7',
        requireAsync: '0.1.1',
        highcharts: '3.0.2',
        bootstrap: '3.0.0',
        jquery_sliceSlide: '4.0',
        leaflet: '0.6.4'
      },
      equivalent: {
        underscore: 'lodash' // 'lodash' or 'underscore'
      }
    },
    templates: {
      route: '../tmpl/',
      routeCultures: '../cultures/'
    },
    images: {
      route: 'img'
    },
    maps: {
      autoStart: false
    },
    platforms: {
      firefoxOS: getFirefoxOS()
    },
    links: {
      github: 'https://github.com/jervert/borrasca-next',
      googlePlay: 'https://play.google.com/store/apps/details?id=com.phonegap.borrasca_v2'
    },
    piwik: {
      enabled: false,
      ready: false,
      url: null,
      id: '2'
    },
    adsense: {
      enabled: true
    },
    views: {},
    removableViews: ['detail', 'nowAndHere']
  };

  if (isPhonegapApp) {
    $Q.piwik.enabled = false;
    $Q.adsense.enabled = false;
  }

  $Q.alternateCulture = ($Q.culture === 'es') ? 'sp' : $Q.culture;

  $Q.services = {
    main: ($Q.server === 'php') ? $Q.servicePath + 'services/main.php?lang=' + $Q.alternateCulture + '&geolocation=' : $Q.servicePath + '?lang=' + $Q.alternateCulture + '&geolocation=',
    search: ($Q.server === 'php') ? $Q.servicePath + 'services/search.php?location_name=' : $Q.servicePath + '?location_name=',
    detail: ($Q.server === 'php') ? $Q.servicePath + 'services/detail.php?lang=' + $Q.alternateCulture + '&location_name=' : $Q.servicePath + '?detail=true&lang=' + $Q.alternateCulture + '&version=' + Date.now() + '&location_name=',
    xml: ($Q.server === 'php') ? $Q.servicePath + 'services/xml.php?location_id=' : $Q.servicePath + '?xml='
  }

  require.config({
    paths: {
      text: 'libs/require.text-' + $Q.jsLibs.versions.requireText,
      async: 'libs/require.async-' + $Q.jsLibs.versions.requireAsync,
      'jquery': $Q.jsLibs.route + 'jquery-' + $Q.jsLibs.versions.jquery,
      'globalize': 'libs/globalize',
      'globalize_culture': $Q.templates.routeCultures + 'globalize/globalize.culture.' + $Q.culture,
      'underscore': ($Q.jsLibs.equivalent.underscore === 'lodash') ? $Q.jsLibs.route + 'lodash.underscore-' + $Q.jsLibs.versions.lodash : $Q.jsLibs.route + 'underscore-' + $Q.jsLibs.versions.underscore,
      'backbone': $Q.jsLibs.route + 'backbone-' + $Q.jsLibs.versions.backbone,
      'highcharts': $Q.jsLibs.route + 'highcharts-' + $Q.jsLibs.versions.highcharts,
      'bootstrap': $Q.jsLibs.route + 'bootstrap-' + $Q.jsLibs.versions.bootstrap,
      'jquery_sliceSlide': $Q.jsLibs.route + 'slice-slide/jquery.sliceslide-' + $Q.jsLibs.versions.jquery_sliceSlide,
      'leaflet': $Q.jsLibs.route + 'leaflet-' + $Q.jsLibs.versions.leaflet,
      'adsense': window.location.protocol + '//pagead2.googlesyndication.com/pagead/js/adsbygoogle',
      'piwik': window.location.protocol + '//' + $Q.piwik.url + '/piwik',
      'mixins': 'br.mixins',
      'br_ui': 'br.ui',
      'br_utils': 'br.utils',
      'br_routes': 'br.routes',
      'br_extend_view': 'br.extendView',
      'mvc_main': 'mvc/main.mvc',
      'mvc_search': 'mvc/search.mvc',
      'mvc_bookmarks': 'mvc/bookmarks.mvc',
      'mvc_nowAndHere': 'mvc/nowAndHere.mvc',
      'mvc_detail': 'mvc/detail.mvc',
      'mvc_install': 'mvc/install.mvc'
    },
    shim: {
      'underscore': {
        deps: [],
        exports: '_'
      },
      'backbone': {
        deps: ['jquery', 'underscore'],
        exports: 'Backbone'
      },
      'highcharts': {
        deps: ['jquery'],
        exports: 'Highcharts'
      },
      'globalize': {
        deps: ['jquery'],
        exports: 'Globalize'
      },
      'globalize_culture': {
        deps: ['globalize']
      },
      'bootstrap': {
        deps: ['jquery']
      },
      'jquery_sliceSlide': {
        deps: ['jquery', 'underscore']
      },
      'leaflet': {
        exports: 'L'
      },
      'mixins': {
        deps: ['jquery', 'underscore']
      },
      'br_ui': {
        deps: ['jquery', 'underscore']
      },
      'br_utils': {
        deps: ['jquery', 'underscore']
      },
      'br_routes': {
        deps: ['backbone']
      },
      'br_extend_view': {
        deps: ['br_utils', 'br_routes', 'globalize', 'mixins', 'br_ui', 'bootstrap']
      },
      'mvc_main': {
        deps: ['br_extend_view']
      },
      'mvc_search': {
        deps: ['mvc_main']
      },
      'mvc_bookmarks': {
        deps: ['mvc_main']
      },
      'mvc_nowAndHere': {
        deps: ['mvc_main']
      },
      'mvc_detail': {
        deps: ['mvc_main', 'leaflet']
      },
      'mvc_install': {
        deps: ['mvc_main']
      }
    },
    waitSeconds: 40,
    urlArgs: $Q.version
  });

  $Q.resourcesJs = [
    'jquery',
    'globalize',
    'underscore',
    'backbone',
    'highcharts',
    'leaflet',
    'jquery_sliceSlide',
    'globalize_culture',
    'mixins',
    'br_ui',
    'br_utils',
    'br_routes',
    'br_extend_view',
    'mvc_main',
    'mvc_search',
    'mvc_bookmarks',
    'mvc_nowAndHere',
    'mvc_detail',
    'mvc_install',
    'br.app.aemet'
  ];
  if ($Q.adsense.enabled) {
    $Q.resourcesJs.push('adsense');
  }
  if ($Q.piwik.enabled) {
    $Q.resourcesJs.push('piwik');
  }

  $Q.resourcesText = [
    'text!' + $Q.templates.routeCultures + 'text_' + $Q.culture + '.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_loading.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_messages_error.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_map_layers.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_current_weather.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_buttons_refresh.html',
    'text!' + $Q.templates.route + 'mixin_tmpl_map_container.html',
    'text!' + $Q.templates.route + 'tmpl_main.html',
    'text!' + $Q.templates.route + 'tmpl_search.html',
    'text!' + $Q.templates.route + 'tmpl_bookmarks.html',
    'text!' + $Q.templates.route + 'tmpl_now_and_here.html',
    'text!' + $Q.templates.route + 'tmpl_detail.html',
    'text!' + $Q.templates.route + 'tmpl_install.html'
  ];

  $Q.initialize = function () {
    $Q.utils.getGeolocation();
    $(document).on('geolocated', function () {
      $Q.app_router = new $Q.AppRouter();
      $Q.views.mainView = new $Q.MainView();
      Backbone.history.start();
    });
  }

  define($Q.resourcesJs.concat($Q.resourcesText), function () {
    var templates = '',
      l = arguments.length,
      i;
    $ = arguments[0];
    Globalize = arguments[1];
    _ = arguments[2];
    Backbone = arguments[3];
    Highcharts = arguments[4];
    L = arguments[5];
    for (i = 5; i < l; i += 1) {
      if (typeof arguments[i] === 'string') {
        templates += arguments[i];
      }
    }

    Globalize.culture($Q.culture);
    $('title').text($Q.appTitle + $Q.version);

    $Q.supported = {
      html5: {
        storage: _.support_html5_storage()
      }
    };
    if ($Q.supported.html5.storage) {
      if (_.isEmpty(localStorage.getItem('appData'))) {
        localStorage.setItem('appData', JSON.stringify({locations: [], locationsName: []}));
      }
    }

    $.when($('#templates-area').append(templates)).then(function () {
      $Q.templatesReady = true;
      if ($Q.piwik.enabled) {
        $Q.utils.piwikStats.start();
        $Q.utils.piwikStats.trackPageView(window.location.hash);
      }
      $Q.initialize();
    });
  });

}());
<|endoftext|>


<commit_before>define(['jquery',
        'underscore',
        'backbone',
        'base',
        'SQL',
        'text!views/cluster.html',
        'text!views/nodelistitem.html',
        'text!views/nodeinfo.html',
        'bootstrap',
    ], function ($, _, Backbone, base, SQL, ClusterTemplate, NodeListItemTemplate, NodeInfoTemplate) {

    var Cluster = {};

    Cluster.Node = Backbone.Model.extend({

        health: function () {
            return _.max([this.get('fs').used_percent, this.get('mem').used_percent]);
        },

        healthStatus: function () {
            var health = this.health();
            if (health>98) {
                return 'critical';
            } else if (health>90) {
                return 'warning';
            }
            return 'good';
        },

        httpLink: function () {
            return 'http://' + this.get('hostname') + ':' + this.get('port').http;
        }

    });

    Cluster.Cluster = Backbone.Collection.extend({

        model: Cluster.Node,

        fetch: function () {
            var self = this,
                sqInfo, sqShardInfo, dInfo, dShardInfo, d;

            d = $.Deferred();
            sqNodes = new SQL.Query('select id, name, hostname, port, load, mem, fs from sys.nodes');
            dNodes = sqNodes.execute();

            dNodes.done(function (res) {
                var nodes = _.map(res.rows, function (row) {
                    return _.object(['id', 'name', 'hostname', 'port', 'load', 'mem', 'fs'], row);
                });
                self.reset(nodes);
            });

            return d.promise();
        }

    });

    Cluster.ClusterView = base.CrateView.extend({

        initialize: function () {
            this.listenTo(this.collection, 'reset', this.render);
        },

        template: _.template(ClusterTemplate),

        deactivateAll: function () {
            this.$('li').removeClass('active');
        },

        showDetails: function (name) {
            var n = this.collection.get(name),
            v = new Cluster.NodeInfoView({model: n});
            this.$('#node-info').html(v.render().$el);
        },

        render: function () {
            var self = this;

            this.$el.html(this.template());
            _.each(this.collection.models, function (node) {
                var v = new Cluster.NodeListItemView({model: node});
                self.$('ul').append(v.render().$el);
                self.addView(node.get('name'), v);
            });
            return this;
        }
    });

    Cluster.NodeListItemView = base.CrateView.extend({

        tagName: 'li',

        template: _.template(NodeListItemTemplate),

        events: {
            'click ': 'selectNode'
        },

        selectNode: function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            this.parentView.deactivateAll();
            this.$el.addClass('active');
            this.parentView.showDetails(this.model.id);
        },

        render: function () {
            var data = this.model.toJSON();
            data.httpLink = this.model.httpLink();
            data.health = this.model.healthStatus();
            this.$el.html(this.template(data));
            return this;
        }
    });

    Cluster.NodeInfoView = base.CrateView.extend({

        template: _.template(NodeInfoTemplate),

        render: function () {
            var data = this.model.toJSON();
            debugger;
            data.httpLink = this.model.httpLink();
            this.$el.html(this.template(data));
            return this;
        }

    });

    return Cluster;
});
<commit_msg>remove stray debug statement<commit_after>define(['jquery',
        'underscore',
        'backbone',
        'base',
        'SQL',
        'text!views/cluster.html',
        'text!views/nodelistitem.html',
        'text!views/nodeinfo.html',
        'bootstrap',
    ], function ($, _, Backbone, base, SQL, ClusterTemplate, NodeListItemTemplate, NodeInfoTemplate) {

    var Cluster = {};

    Cluster.Node = Backbone.Model.extend({

        health: function () {
            return _.max([this.get('fs').used_percent, this.get('mem').used_percent]);
        },

        healthStatus: function () {
            var health = this.health();
            if (health>98) {
                return 'critical';
            } else if (health>90) {
                return 'warning';
            }
            return 'good';
        },

        httpLink: function () {
            return 'http://' + this.get('hostname') + ':' + this.get('port').http;
        }

    });

    Cluster.Cluster = Backbone.Collection.extend({

        model: Cluster.Node,

        fetch: function () {
            var self = this,
                sqInfo, sqShardInfo, dInfo, dShardInfo, d;

            d = $.Deferred();
            sqNodes = new SQL.Query('select id, name, hostname, port, load, mem, fs from sys.nodes');
            dNodes = sqNodes.execute();

            dNodes.done(function (res) {
                var nodes = _.map(res.rows, function (row) {
                    return _.object(['id', 'name', 'hostname', 'port', 'load', 'mem', 'fs'], row);
                });
                self.reset(nodes);
            });

            return d.promise();
        }

    });

    Cluster.ClusterView = base.CrateView.extend({

        initialize: function () {
            this.listenTo(this.collection, 'reset', this.render);
        },

        template: _.template(ClusterTemplate),

        deactivateAll: function () {
            this.$('li').removeClass('active');
        },

        showDetails: function (name) {
            var n = this.collection.get(name),
            v = new Cluster.NodeInfoView({model: n});
            this.$('#node-info').html(v.render().$el);
        },

        render: function () {
            var self = this;

            this.$el.html(this.template());
            _.each(this.collection.models, function (node) {
                var v = new Cluster.NodeListItemView({model: node});
                self.$('ul').append(v.render().$el);
                self.addView(node.get('name'), v);
            });
            return this;
        }
    });

    Cluster.NodeListItemView = base.CrateView.extend({

        tagName: 'li',

        template: _.template(NodeListItemTemplate),

        events: {
            'click ': 'selectNode'
        },

        selectNode: function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            this.parentView.deactivateAll();
            this.$el.addClass('active');
            this.parentView.showDetails(this.model.id);
        },

        render: function () {
            var data = this.model.toJSON();
            data.httpLink = this.model.httpLink();
            data.health = this.model.healthStatus();
            this.$el.html(this.template(data));
            return this;
        }
    });

    Cluster.NodeInfoView = base.CrateView.extend({

        template: _.template(NodeInfoTemplate),

        render: function () {
            var data = this.model.toJSON();
            data.httpLink = this.model.httpLink();
            this.$el.html(this.template(data));
            return this;
        }

    });

    return Cluster;
});
<|endoftext|>


<commit_before>import * as t from 'babel-types'

import { STYLE_COMPONENT } from './_constants'

import {
  getJSXStyleInfo,
  processCss,
  cssToBabelType,
  validateExternalExpressions,
  getScope,
  computeClassNames,
  makeStyledJsxTag,
  createReactComponentImportDeclaration,
  setStateOptions
} from './_utils'

const isModuleExports = t.buildMatchMemberExpression('module.exports')

export function processTaggedTemplateExpression({
  type,
  path,
  file,
  splitRules,
  plugins,
  vendorPrefixes
}) {
  const templateLiteral = path.get('quasi')
  let scope

  // Check whether there are undefined references or
  // references to this.something (e.g. props or state).
  // We allow dynamic styles only when resolving styles.
  if (type !== 'resolve') {
    validateExternalExpressions(templateLiteral)
  } else if (!path.scope.path.isProgram()) {
    scope = getScope(path)
  }

  const stylesInfo = getJSXStyleInfo(templateLiteral, scope)

  const { staticClassName, className } = computeClassNames([stylesInfo])

  const styles = processCss(
    {
      ...stylesInfo,
      staticClassName,
      file,
      isGlobal: type === 'global',
      plugins,
      vendorPrefixes
    },
    { splitRules }
  )

  if (type === 'resolve') {
    const { hash, css, expressions } = styles
    path.replaceWith(
      // {
      //   styles: <_JSXStyle ... />,
      //   className: 'jsx-123'
      // }
      t.objectExpression([
        t.objectProperty(
          t.identifier('styles'),
          makeStyledJsxTag(hash, css, expressions)
        ),
        t.objectProperty(t.identifier('className'), className)
      ])
    )
    return
  }

  const id = path.parentPath.node.id
  const baseExportName = id ? id.name : 'default'
  let parentPath =
    baseExportName === 'default'
      ? path.parentPath
      : path.findParent(
          path =>
            path.isVariableDeclaration() ||
            (path.isAssignmentExpression() &&
              isModuleExports(path.get('left').node))
        )

  if (baseExportName !== 'default' && !parentPath.parentPath.isProgram()) {
    parentPath = parentPath.parentPath
  }

  const css = cssToBabelType(styles.css)
  const newPath = t.isArrayExpression(css)
    ? css
    : t.newExpression(t.identifier('String'), [css])

  // default exports

  if (baseExportName === 'default') {
    const defaultExportIdentifier = path.scope.generateUidIdentifier(
      'defaultExport'
    )
    parentPath.insertBefore(
      t.variableDeclaration('const', [
        t.variableDeclarator(defaultExportIdentifier, newPath)
      ])
    )

    parentPath.insertBefore(addHash(defaultExportIdentifier, styles.hash))
    path.replaceWith(defaultExportIdentifier)
    return
  }

  // local and named exports

  parentPath.insertAfter(addHash(t.identifier(baseExportName), styles.hash))
  path.replaceWith(newPath)
}

function addHash(exportIdentifier, hash) {
  const value = typeof hash === 'string' ? t.stringLiteral(hash) : hash
  return t.expressionStatement(
    t.assignmentExpression(
      '=',
      t.memberExpression(exportIdentifier, t.identifier('__hash')),
      value
    )
  )
}

export const visitor = {
  ImportDeclaration(path, state) {
    // import css from 'styled-jsx/css'
    if (path.node.source.value !== 'styled-jsx/css') {
      return
    }

    // Find all the imported specifiers.
    // e.g import css, { global, resolve } from 'styled-jsx/css'
    // -> ['css', 'global', 'resolve']
    const specifiersNames = path.node.specifiers.map(
      specifier => specifier.local.name
    )
    specifiersNames.forEach(tagName => {
      // Get all the reference paths i.e. the places that use the tagName above
      // eg.
      // css`div { color: red }`
      // css.global`div { color: red }`
      // global`div { color: red `
      const binding = path.scope.getBinding(tagName)

      if (!binding || !Array.isArray(binding.referencePaths)) {
        return
      }

      // Produces an object containing all the TaggedTemplateExpression paths detected.
      // The object contains { scoped, global, resolve }
      const taggedTemplateExpressions = binding.referencePaths
        .map(ref => ref.parentPath)
        .reduce(
          (result, path) => {
            let taggedTemplateExpression
            if (path.isTaggedTemplateExpression()) {
              // css`` global`` resolve``
              taggedTemplateExpression = path
            } else if (
              path.parentPath &&
              path.isMemberExpression() &&
              path.parentPath.isTaggedTemplateExpression()
            ) {
              // This part is for css.global`` or css.resolve``
              // using the default import css
              taggedTemplateExpression = path.parentPath
            } else {
              return result
            }

            const tag = taggedTemplateExpression.get('tag')
            const id = tag.isIdentifier()
              ? tag.node.name
              : tag.get('property').node.name

            if (result[id]) {
              result[id].push(taggedTemplateExpression)
            } else {
              result.scoped.push(taggedTemplateExpression)
            }

            return result
          },
          {
            scoped: [],
            global: [],
            resolve: []
          }
        )

      let hasJSXStyle = false

      const { vendorPrefixes, sourceMaps } = state.opts

      Object.keys(taggedTemplateExpressions).forEach(type =>
        taggedTemplateExpressions[type].forEach(path => {
          hasJSXStyle = true
          // Process each css block
          processTaggedTemplateExpression({
            type,
            path,
            file: state.file,
            splitRules:
              typeof state.opts.optimizeForSpeed === 'boolean'
                ? state.opts.optimizeForSpeed
                : process.env.NODE_ENV === 'production',
            plugins: state.plugins,
            vendorPrefixes,
            sourceMaps
          })
        })
      )

      // When using the `resolve` helper we need to add an import
      // for the _JSXStyle component `styled-jsx/style`
      if (
        hasJSXStyle &&
        taggedTemplateExpressions.resolve.length > 0 &&
        !state.hasInjectedJSXStyle &&
        !path.scope.hasBinding(STYLE_COMPONENT)
      ) {
        state.hasInjectedJSXStyle = true
        const importDeclaration = createReactComponentImportDeclaration()
        path.scope.path.node.body.unshift(importDeclaration)
      }
    })

    // Finally remove the import
    path.remove()
  }
}

export default function() {
  return {
    Program(path, state) {
      setStateOptions(state)
    },
    ...visitor
  }
}
<commit_msg>Fix source maps pt. 2 (#572)<commit_after>import * as t from 'babel-types'

import { STYLE_COMPONENT } from './_constants'

import {
  getJSXStyleInfo,
  processCss,
  cssToBabelType,
  validateExternalExpressions,
  getScope,
  computeClassNames,
  makeStyledJsxTag,
  createReactComponentImportDeclaration,
  setStateOptions
} from './_utils'

const isModuleExports = t.buildMatchMemberExpression('module.exports')

export function processTaggedTemplateExpression({
  type,
  path,
  file,
  splitRules,
  plugins,
  vendorPrefixes,
  sourceMaps
}) {
  const templateLiteral = path.get('quasi')
  let scope

  // Check whether there are undefined references or
  // references to this.something (e.g. props or state).
  // We allow dynamic styles only when resolving styles.
  if (type !== 'resolve') {
    validateExternalExpressions(templateLiteral)
  } else if (!path.scope.path.isProgram()) {
    scope = getScope(path)
  }

  const stylesInfo = getJSXStyleInfo(templateLiteral, scope)

  const { staticClassName, className } = computeClassNames([stylesInfo])

  const styles = processCss(
    {
      ...stylesInfo,
      staticClassName,
      file,
      isGlobal: type === 'global',
      plugins,
      vendorPrefixes,
      sourceMaps
    },
    { splitRules }
  )

  if (type === 'resolve') {
    const { hash, css, expressions } = styles
    path.replaceWith(
      // {
      //   styles: <_JSXStyle ... />,
      //   className: 'jsx-123'
      // }
      t.objectExpression([
        t.objectProperty(
          t.identifier('styles'),
          makeStyledJsxTag(hash, css, expressions)
        ),
        t.objectProperty(t.identifier('className'), className)
      ])
    )
    return
  }

  const id = path.parentPath.node.id
  const baseExportName = id ? id.name : 'default'
  let parentPath =
    baseExportName === 'default'
      ? path.parentPath
      : path.findParent(
          path =>
            path.isVariableDeclaration() ||
            (path.isAssignmentExpression() &&
              isModuleExports(path.get('left').node))
        )

  if (baseExportName !== 'default' && !parentPath.parentPath.isProgram()) {
    parentPath = parentPath.parentPath
  }

  const css = cssToBabelType(styles.css)
  const newPath = t.isArrayExpression(css)
    ? css
    : t.newExpression(t.identifier('String'), [css])

  // default exports

  if (baseExportName === 'default') {
    const defaultExportIdentifier = path.scope.generateUidIdentifier(
      'defaultExport'
    )
    parentPath.insertBefore(
      t.variableDeclaration('const', [
        t.variableDeclarator(defaultExportIdentifier, newPath)
      ])
    )

    parentPath.insertBefore(addHash(defaultExportIdentifier, styles.hash))
    path.replaceWith(defaultExportIdentifier)
    return
  }

  // local and named exports

  parentPath.insertAfter(addHash(t.identifier(baseExportName), styles.hash))
  path.replaceWith(newPath)
}

function addHash(exportIdentifier, hash) {
  const value = typeof hash === 'string' ? t.stringLiteral(hash) : hash
  return t.expressionStatement(
    t.assignmentExpression(
      '=',
      t.memberExpression(exportIdentifier, t.identifier('__hash')),
      value
    )
  )
}

export const visitor = {
  ImportDeclaration(path, state) {
    // import css from 'styled-jsx/css'
    if (path.node.source.value !== 'styled-jsx/css') {
      return
    }

    // Find all the imported specifiers.
    // e.g import css, { global, resolve } from 'styled-jsx/css'
    // -> ['css', 'global', 'resolve']
    const specifiersNames = path.node.specifiers.map(
      specifier => specifier.local.name
    )
    specifiersNames.forEach(tagName => {
      // Get all the reference paths i.e. the places that use the tagName above
      // eg.
      // css`div { color: red }`
      // css.global`div { color: red }`
      // global`div { color: red `
      const binding = path.scope.getBinding(tagName)

      if (!binding || !Array.isArray(binding.referencePaths)) {
        return
      }

      // Produces an object containing all the TaggedTemplateExpression paths detected.
      // The object contains { scoped, global, resolve }
      const taggedTemplateExpressions = binding.referencePaths
        .map(ref => ref.parentPath)
        .reduce(
          (result, path) => {
            let taggedTemplateExpression
            if (path.isTaggedTemplateExpression()) {
              // css`` global`` resolve``
              taggedTemplateExpression = path
            } else if (
              path.parentPath &&
              path.isMemberExpression() &&
              path.parentPath.isTaggedTemplateExpression()
            ) {
              // This part is for css.global`` or css.resolve``
              // using the default import css
              taggedTemplateExpression = path.parentPath
            } else {
              return result
            }

            const tag = taggedTemplateExpression.get('tag')
            const id = tag.isIdentifier()
              ? tag.node.name
              : tag.get('property').node.name

            if (result[id]) {
              result[id].push(taggedTemplateExpression)
            } else {
              result.scoped.push(taggedTemplateExpression)
            }

            return result
          },
          {
            scoped: [],
            global: [],
            resolve: []
          }
        )

      let hasJSXStyle = false

      const { vendorPrefixes, sourceMaps } = state.opts

      Object.keys(taggedTemplateExpressions).forEach(type =>
        taggedTemplateExpressions[type].forEach(path => {
          hasJSXStyle = true
          // Process each css block
          processTaggedTemplateExpression({
            type,
            path,
            file: state.file,
            splitRules:
              typeof state.opts.optimizeForSpeed === 'boolean'
                ? state.opts.optimizeForSpeed
                : process.env.NODE_ENV === 'production',
            plugins: state.plugins,
            vendorPrefixes,
            sourceMaps
          })
        })
      )

      // When using the `resolve` helper we need to add an import
      // for the _JSXStyle component `styled-jsx/style`
      if (
        hasJSXStyle &&
        taggedTemplateExpressions.resolve.length > 0 &&
        !state.hasInjectedJSXStyle &&
        !path.scope.hasBinding(STYLE_COMPONENT)
      ) {
        state.hasInjectedJSXStyle = true
        const importDeclaration = createReactComponentImportDeclaration()
        path.scope.path.node.body.unshift(importDeclaration)
      }
    })

    // Finally remove the import
    path.remove()
  }
}

export default function() {
  return {
    Program(path, state) {
      setStateOptions(state)
    },
    ...visitor
  }
}
<|endoftext|>


<commit_before>import { app, remote, ipcRenderer } from 'electron'
import fs from 'fs'
import { memoize } from 'cerebro-tools'
import { trackEvent } from './trackEvent'
import loadThemes from './loadThemes'

const electronApp = remote ? remote.app : app

// initiate portable mode
// set data directory to ./userdata
process.argv.forEach((arg) => {
  if (arg.toLowerCase() === '-p' || arg.toLowerCase() === '--portable') {
    electronApp.setPath('userData', process.cwd() + '/userdata')
  }
})

const CONFIG_FILE = `${electronApp.getPath('userData')}/config.json`

const defaultSettings = memoize(() => {
  const locale = electronApp.getLocale() || 'en-US'
  const [lang, country] = locale.split('-')
  return {
    locale,
    lang,
    country,
    // use first theme from loadThemes by default
    theme: loadThemes()[0].value,
    hotkey: 'Control+Space',
    showInTray: true,
    firstStart: true,
    developerMode: false,
    cleanOnHide: true,
    skipDonateDialog: false,
    lastShownDonateDialog: null,
    plugins: {},
    isMigratedPlugins: false,
    openAtLogin: true
  }
})

const readConfig = () => {
  try {
    return JSON.parse(fs.readFileSync(CONFIG_FILE).toString())
  } catch (err) {
    return defaultSettings()
  }
}

/**
 * Get a value from global configuration
 * @param  {String} key
 * @return {Any}
 */
const get = (key) => {
  let config
  if (!fs.existsSync(CONFIG_FILE)) {
    // Save default config to local storage
    config = defaultSettings()
    fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2))
  } else {
    config = readConfig()
  }
  return config[key]
}

/**
 * Write a value to global config. It immedately rewrites global config
 * and notifies all listeners about changes
 *
 * @param  {String} key
 * @param  {Any} value
 */
const set = (key, value) => {
  const config = {
    // If after app update some keys were added to config
    // we use default values for that keys
    ...defaultSettings(),
    ...readConfig()
  }
  config[key] = value
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2))
  // Track settings changes
  trackEvent({
    category: 'Settings',
    event: `Change ${key}`,
    label: value
  })
  if (ipcRenderer) {
    console.log('notify main process', key, value)
    // Notify main process about settings changes
    ipcRenderer.send('updateSettings', key, value)
  }
}

export default { get, set }
<commit_msg>Update config.js<commit_after>import { app, remote, ipcRenderer } from 'electron'
import fs from 'fs'
import { memoize } from 'cerebro-tools'
import { trackEvent } from './trackEvent'
import loadThemes from './loadThemes'

const electronApp = remote ? remote.app : app

// initiate portable mode
// set data directory to ./userdata
process.argv.forEach((arg) => {
  if (arg.toLowerCase() === '-p' || arg.toLowerCase() === '--portable') {
    electronApp.setPath('userData', `${process.cwd()}/userdata`)
  }
})

const CONFIG_FILE = `${electronApp.getPath('userData')}/config.json`

const defaultSettings = memoize(() => {
  const locale = electronApp.getLocale() || 'en-US'
  const [lang, country] = locale.split('-')
  return {
    locale,
    lang,
    country,
    // use first theme from loadThemes by default
    theme: loadThemes()[0].value,
    hotkey: 'Control+Space',
    showInTray: true,
    firstStart: true,
    developerMode: false,
    cleanOnHide: true,
    skipDonateDialog: false,
    lastShownDonateDialog: null,
    plugins: {},
    isMigratedPlugins: false,
    openAtLogin: true
  }
})

const readConfig = () => {
  try {
    return JSON.parse(fs.readFileSync(CONFIG_FILE).toString())
  } catch (err) {
    return defaultSettings()
  }
}

/**
 * Get a value from global configuration
 * @param  {String} key
 * @return {Any}
 */
const get = (key) => {
  let config
  if (!fs.existsSync(CONFIG_FILE)) {
    // Save default config to local storage
    config = defaultSettings()
    fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2))
  } else {
    config = readConfig()
  }
  return config[key]
}

/**
 * Write a value to global config. It immedately rewrites global config
 * and notifies all listeners about changes
 *
 * @param  {String} key
 * @param  {Any} value
 */
const set = (key, value) => {
  const config = {
    // If after app update some keys were added to config
    // we use default values for that keys
    ...defaultSettings(),
    ...readConfig()
  }
  config[key] = value
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2))
  // Track settings changes
  trackEvent({
    category: 'Settings',
    event: `Change ${key}`,
    label: value
  })
  if (ipcRenderer) {
    console.log('notify main process', key, value)
    // Notify main process about settings changes
    ipcRenderer.send('updateSettings', key, value)
  }
}

export default { get, set }
<|endoftext|>


<commit_before>import { DraggableBar } from './draggable_bar';

import { ViewportRange } from './ranges';

import * as PhaserObjects from '../phaserObjects';

/**
 * A bar that moves along a track.
 * The bar is resized relative to the size of the track and size of the content to be scrolled.
 * @extends DraggableBar
 */
export class Scrollbar extends DraggableBar {
    /**
     * @param {Object} game - Current game instance.
     * @param {Object} content - Anything that you want to move via the scrollbar.
     * @param {boolean} draggable - Determines if the scrollbar responds to mouse clicks.
     * @param {boolean} vertical - Determines if the scrollbar should be vertical or horizontal.
     * @param {string} trackKey - The key to use for the track.
     * @param {string} barKey - The key to use for the bar.
     * @param {Object} tweenParams - Object with duration and easing function for the scrolling tween.
     */
    constructor(game, content, draggable, vertical = false, trackKey = '', barKey = '', tweenParams = null) {
        super(game, 0, 0, vertical, trackKey, barKey);

        this.game = game;

        this.content = content;

        this.valueRange = new ViewportRange(content, vertical);

        this.draggable = draggable || false;

        // The smallest pixel size allowed for the bar.
        this.minBarSize = 1;

        this.tweenParams = tweenParams || { duration: 300, ease: PhaserObjects.Easing.Quadratic.Out };

        // Flag switched on when the track is clicked, switched off after the bar movement is finished.
        this.trackClicked = false;
        this.barMoving = false;

        // Records mouse pointer when clicking the bar.
        this.mousePointer = null;

        // The track is the static area the bar will move along.
        this.track = new PhaserObjects.Sprite(
            game,
            this.x,
            this.y,
            this.trackKey,
        );

        // Phaser 3:
        // Anchor the track to 0 instead of 0.5
        this.track.displayOriginX = 0;
        this.track.displayOriginY = 0;

        this.add(this.track);

        if (this.draggable) {
        // If the bar is draggable, clicking the track will move the bar up or down.
            this.enableTrackClick();
        }

        this.createBar();
        this.add(this.bar);

        this.minY = this.track.y;
        this.maxY = (this.track.y + this.track.height) - this.bar.displayHeight;
        this.minX = this.track.x;
        this.maxX = (this.track.x + this.track.width) - this.bar.displayWidth;

        this.create();

        // Maximum value for the mouse position.
        if (this.vertical) {
            this.maxValue = this.track.displayHeight + this.worldPosition.y;

            if (this.version === undefined) {
                this.maxValue += this.bar.displayHeight;
            }
        } else {
            this.maxValue = this.track.displayWidth + this.worldPosition.x;

            if (this.version === undefined) {
                this.maxValue += this.bar.displayWidth;
            }
        }
    }

    /**
     * @private
     * The bar is the part that moves, controlling the value of the scrollbar.
    */
    createBar() {
        const bar = new PhaserObjects.Button(
            this.game,
            this.x,
            this.y,
            this.barKey,
            this.moveContent,
            this,
            1,
            0,
        );

        // Phaser 3:
        // Anchor the bar to 0 instead of 0.5
        bar.displayOriginX = 0;
        bar.displayOriginY = 0;

        this.bar = bar;

        this.resizeBar();

        return bar;
    }

    /**
     * @private
     * Given a ratio between total content size and viewport size,
     * resize the bar sprite to the appropriate percentage of the track.
     */
    resizeBar() {
        let barSize;
        if (this.vertical) {
            barSize = this.track.height * this.valueRange.ratio;
        } else {
            barSize = this.track.width * this.valueRange.ratio;
        }

        // Prevents bar from becoming zero pixels.
        if (barSize < this.minBarSize) {
            barSize = this.minBarSize;
        }

        // Resizes the bar.
        if (this.vertical) {
            this.bar.displayHeight = barSize;
        } else {
            this.bar.displayWidth = barSize;
        }
    }

    create() {
        this.centerStaticAxis();

        if (this.draggable) {
            this.enableBarDrag();
        }

        // Determine the distance the window can scroll over
        this.windowScrollAreaSize = this.valueRange.maxValue - this.valueRange.step;

        // Represents one fraction of the track.
        this.vslice = (this.track.displayHeight * this.valueRange.ratio);
        this.hslice = (this.track.displayWidth * this.valueRange.ratio);

        this.setTrackScrollAreaSize();

        // Initial position for the bar.
        this.mousePointer = { x: this.bar.x, y: this.bar.y };

        this.setInitialBarPosition();
    }

    /**
     * @private
     * Sets the draggable area of the bar.
     */
    setDraggableArea() {
        let vh = this.track.displayHeight;

        if (this.version === 3) {
            vh -= this.bar.displayHeight;
        }

        this.verticalDraggableArea = {
            x: this.track.x - ((this.bar.displayWidth - this.track.width) / 2),
            y: this.track.y,
            w: this.bar.displayWidth,
            h: vh,
        };

        this.horizontalDraggableArea = {
            x: this.track.x,
            y: this.track.y - ((this.bar.displayHeight - this.track.height) / 2),
            w: this.track.width,
            h: this.bar.displayHeight,
        };
    }

    /**
     * @private
     * Ensure the bar starts off where it should be, according to the bar's logical position.
     */
    setInitialBarPosition() {
        const gripPositionOnTrack = this.getBarPosition();

        // Make sure the bar is physically where it should be.
        if (this.vertical) {
            this.bar.y = gripPositionOnTrack + this.track.y;
        } else {
            this.bar.x = gripPositionOnTrack + this.track.x;
        }
    }

    getGripPositionRatio() {
        const gripPositionOnTrack = this.getBarPosition();
        const mousePositionDelta = this.getMouseDelta();

        let newGripPosition = gripPositionOnTrack + mousePositionDelta;

        // Don't let the content scroll above or below the track's size
        if (newGripPosition > 0) {
            newGripPosition = 0;
        } else if (newGripPosition <= -this.trackScrollAreaSize) {
            newGripPosition = -this.trackScrollAreaSize;
        }

        // When the scrollbar is at the top or bottom, prevent a mouse movement that
        // doesn't move the scrollbar from moving the content.
        if (this.vertical) {
            if (this.bar.y <= this.track.y) {
                newGripPosition = 0;
            } else if (this.bar.y + this.bar.displayHeight >= this.track.y + this.track.displayHeight) {
                newGripPosition = -this.trackScrollAreaSize;
            }
        } else {
            if (this.bar.x <= this.track.x) {
                newGripPosition = 0;
            } else if (this.bar.x + this.bar.displayWidth >= this.track.x + this.track.displayWidth) {
                newGripPosition = -this.trackScrollAreaSize;
            }
        }

        let newGripPositionRatio = newGripPosition / this.trackScrollAreaSize;

        // If the scrollable area is less than the size of the scrollbar,
        // the bar and track will be the same size.
        // In this scenario, a divide by zero occurs. Capture that and turn it into zero.
        if (Number.isNaN(newGripPositionRatio)) {
            newGripPositionRatio = 0;
        }

        return newGripPositionRatio;
    }
}
<commit_msg>Tweak docstring<commit_after>import { DraggableBar } from './draggable_bar';

import { ViewportRange } from './ranges';

import * as PhaserObjects from '../phaserObjects';

/**
 * A bar that moves along a track.
 * The bar is resized relative to the size of the track and size of the content to be scrolled.
 * @extends DraggableBar
 */
export class Scrollbar extends DraggableBar {
    /**
     * @param {Object} game - Current game instance.
     * @param {Object} content - An object to adjust via the scrollbar.
     * @param {boolean} draggable - Determines if the scrollbar responds to mouse clicks.
     * @param {boolean} vertical - Determines if the scrollbar should be vertical or horizontal.
     * @param {string} trackKey - The key to use for the track.
     * @param {string} barKey - The key to use for the bar.
     * @param {Object} tweenParams - Object with duration and easing function for the scrolling tween.
     */
    constructor(game, content, draggable, vertical = false, trackKey = '', barKey = '', tweenParams = null) {
        super(game, 0, 0, vertical, trackKey, barKey);

        this.game = game;

        this.content = content;

        this.valueRange = new ViewportRange(content, vertical);

        this.draggable = draggable || false;

        // The smallest pixel size allowed for the bar.
        this.minBarSize = 1;

        this.tweenParams = tweenParams || { duration: 300, ease: PhaserObjects.Easing.Quadratic.Out };

        // Flag switched on when the track is clicked, switched off after the bar movement is finished.
        this.trackClicked = false;
        this.barMoving = false;

        // Records mouse pointer when clicking the bar.
        this.mousePointer = null;

        // The track is the static area the bar will move along.
        this.track = new PhaserObjects.Sprite(
            game,
            this.x,
            this.y,
            this.trackKey,
        );

        // Phaser 3:
        // Anchor the track to 0 instead of 0.5
        this.track.displayOriginX = 0;
        this.track.displayOriginY = 0;

        this.add(this.track);

        if (this.draggable) {
        // If the bar is draggable, clicking the track will move the bar up or down.
            this.enableTrackClick();
        }

        this.createBar();
        this.add(this.bar);

        this.minY = this.track.y;
        this.maxY = (this.track.y + this.track.height) - this.bar.displayHeight;
        this.minX = this.track.x;
        this.maxX = (this.track.x + this.track.width) - this.bar.displayWidth;

        this.create();

        // Maximum value for the mouse position.
        if (this.vertical) {
            this.maxValue = this.track.displayHeight + this.worldPosition.y;

            if (this.version === undefined) {
                this.maxValue += this.bar.displayHeight;
            }
        } else {
            this.maxValue = this.track.displayWidth + this.worldPosition.x;

            if (this.version === undefined) {
                this.maxValue += this.bar.displayWidth;
            }
        }
    }

    /**
     * @private
     * The bar is the part that moves, controlling the value of the scrollbar.
    */
    createBar() {
        const bar = new PhaserObjects.Button(
            this.game,
            this.x,
            this.y,
            this.barKey,
            this.moveContent,
            this,
            1,
            0,
        );

        // Phaser 3:
        // Anchor the bar to 0 instead of 0.5
        bar.displayOriginX = 0;
        bar.displayOriginY = 0;

        this.bar = bar;

        this.resizeBar();

        return bar;
    }

    /**
     * @private
     * Given a ratio between total content size and viewport size,
     * resize the bar sprite to the appropriate percentage of the track.
     */
    resizeBar() {
        let barSize;
        if (this.vertical) {
            barSize = this.track.height * this.valueRange.ratio;
        } else {
            barSize = this.track.width * this.valueRange.ratio;
        }

        // Prevents bar from becoming zero pixels.
        if (barSize < this.minBarSize) {
            barSize = this.minBarSize;
        }

        // Resizes the bar.
        if (this.vertical) {
            this.bar.displayHeight = barSize;
        } else {
            this.bar.displayWidth = barSize;
        }
    }

    create() {
        this.centerStaticAxis();

        if (this.draggable) {
            this.enableBarDrag();
        }

        // Determine the distance the window can scroll over
        this.windowScrollAreaSize = this.valueRange.maxValue - this.valueRange.step;

        // Represents one fraction of the track.
        this.vslice = (this.track.displayHeight * this.valueRange.ratio);
        this.hslice = (this.track.displayWidth * this.valueRange.ratio);

        this.setTrackScrollAreaSize();

        // Initial position for the bar.
        this.mousePointer = { x: this.bar.x, y: this.bar.y };

        this.setInitialBarPosition();
    }

    /**
     * @private
     * Sets the draggable area of the bar.
     */
    setDraggableArea() {
        let vh = this.track.displayHeight;

        if (this.version === 3) {
            vh -= this.bar.displayHeight;
        }

        this.verticalDraggableArea = {
            x: this.track.x - ((this.bar.displayWidth - this.track.width) / 2),
            y: this.track.y,
            w: this.bar.displayWidth,
            h: vh,
        };

        this.horizontalDraggableArea = {
            x: this.track.x,
            y: this.track.y - ((this.bar.displayHeight - this.track.height) / 2),
            w: this.track.width,
            h: this.bar.displayHeight,
        };
    }

    /**
     * @private
     * Ensure the bar starts off where it should be, according to the bar's logical position.
     */
    setInitialBarPosition() {
        const gripPositionOnTrack = this.getBarPosition();

        // Make sure the bar is physically where it should be.
        if (this.vertical) {
            this.bar.y = gripPositionOnTrack + this.track.y;
        } else {
            this.bar.x = gripPositionOnTrack + this.track.x;
        }
    }

    getGripPositionRatio() {
        const gripPositionOnTrack = this.getBarPosition();
        const mousePositionDelta = this.getMouseDelta();

        let newGripPosition = gripPositionOnTrack + mousePositionDelta;

        // Don't let the content scroll above or below the track's size
        if (newGripPosition > 0) {
            newGripPosition = 0;
        } else if (newGripPosition <= -this.trackScrollAreaSize) {
            newGripPosition = -this.trackScrollAreaSize;
        }

        // When the scrollbar is at the top or bottom, prevent a mouse movement that
        // doesn't move the scrollbar from moving the content.
        if (this.vertical) {
            if (this.bar.y <= this.track.y) {
                newGripPosition = 0;
            } else if (this.bar.y + this.bar.displayHeight >= this.track.y + this.track.displayHeight) {
                newGripPosition = -this.trackScrollAreaSize;
            }
        } else {
            if (this.bar.x <= this.track.x) {
                newGripPosition = 0;
            } else if (this.bar.x + this.bar.displayWidth >= this.track.x + this.track.displayWidth) {
                newGripPosition = -this.trackScrollAreaSize;
            }
        }

        let newGripPositionRatio = newGripPosition / this.trackScrollAreaSize;

        // If the scrollable area is less than the size of the scrollbar,
        // the bar and track will be the same size.
        // In this scenario, a divide by zero occurs. Capture that and turn it into zero.
        if (Number.isNaN(newGripPositionRatio)) {
            newGripPositionRatio = 0;
        }

        return newGripPositionRatio;
    }
}
<|endoftext|>


<commit_before>var m = require('mithril');
var opposite = require('chessground/util').opposite;

module.exports = function(ctrl) {
  var states = ctrl.data.game.clockStates;
  var bottomColor = ctrl.bottomColor();
  if (!states) return;
  return [
    renderClock(ctrl, states, bottomColor === 'black', 'top'),
    renderClock(ctrl, states, bottomColor === 'white', 'bottom')
  ];
}

function renderClock(ctrl, states, isWhite, position) {
  var ply = ctrl.vm.node.ply;
  var i = Math.max(0, ply - ctrl.tree.root.ply - 2);
  i = Math.floor(i / 2) * 2;
  if (!isWhite) i++;
  var tenths = states[i];
  return m('div', {
    class: 'clock ' + position + (ply % 2 === (isWhite ? 0 : 1) ? ' active' : '')
  }, clockContent(tenths));
}

function clockContent(tenths) {
  var date = new Date(tenths * 100);
  var millis = date.getUTCMilliseconds();
  var sep = ':';
  var baseStr = pad2(date.getUTCMinutes()) + sep + pad2(date.getUTCSeconds());
  if (tenths >= 36000) {
    var hours = pad2(Math.floor(tenths / 36000));
    return hours + sep + baseStr;
  }
  var tenthsStr = Math.floor(millis / 100).toString();
  return baseStr + '.' + tenthsStr;
}

function pad2(num) {
  return (num < 10 ? '0' : '') + num;
}
<commit_msg>fix analysis clock state<commit_after>var m = require('mithril');
var opposite = require('chessground/util').opposite;

module.exports = function(ctrl) {
  var states = ctrl.data.game.clockStates;
  var bottomColor = ctrl.bottomColor();
  if (!states) return;
  return [
    renderClock(ctrl, states, bottomColor === 'black', 'top'),
    renderClock(ctrl, states, bottomColor === 'white', 'bottom')
  ];
}

// ply white black
// 0   0     1
// 1   0     1
// 2   0     1
// 3   2     1
// 4   2     3
// 5   4     3
// 6   4     5
// 7   6     5
// 8   6     7
// 9   8     7

function renderClock(ctrl, states, isWhite, position) {
  var ply = ctrl.vm.node.ply, i;
  var i = ply - ctrl.tree.root.ply;
  if (isWhite) i = Math.floor((i - 1) / 2) * 2;
  else i = Math.floor(i / 2) * 2 - 1;
  if (i < 0) i = isWhite ? 0 : 1;
  var tenths = states[i];
  return m('div', {
    class: 'clock ' + position + (ply % 2 === (isWhite ? 0 : 1) ? ' active' : '')
  }, clockContent(tenths));
}

function clockContent(tenths) {
  var date = new Date(tenths * 100);
  var millis = date.getUTCMilliseconds();
  var sep = ':';
  var baseStr = pad2(date.getUTCMinutes()) + sep + pad2(date.getUTCSeconds());
  if (tenths >= 36000) {
    var hours = pad2(Math.floor(tenths / 36000));
    return hours + sep + baseStr;
  }
  var tenthsStr = Math.floor(millis / 100).toString();
  return baseStr + '.' + tenthsStr;
}

function pad2(num) {
  return (num < 10 ? '0' : '') + num;
}
<|endoftext|>