<commit_before>// Generated on 2015-07-10 using generator-angular 0.11.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }

    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp',
      css: {
         src: [ 'styles/' ]
      }
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '!<%= yeoman.dist %>/scripts/ckeditor/**/*',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['concat','cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: '<%= yeoman.dist %>/scripts/{,*/}*.js',
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles',
          '<%= yeoman.dist %>/scripts'
        ],
        blockReplacements: {
          css: function (block) {
            return '<link rel="stylesheet" href="' + block.dest + '"/>';
          },
          js: function (block) {
            return '<script src="' + block.dest + '"></script>';
          }
        }
      }
    },

    cssmin: {
      combine: {
        files: {
          '<%= yeoman.dist %>/styles/combined.css': ['.tmp/concat/styles/*.css']
        }
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: [
            '*.html',
            'templates/{,*/}*.html'
          ],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: [
          '<%= yeoman.dist %>/*.html'
        ]
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'templates/**/*',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'scripts/ckeditor/**/*',
            'CNAME'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: 'bower_components/bootstrap/dist',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: 'bower_components/font-awesome',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    },
/*https://github.com/robwierzbowski/grunt-build-control*/
    buildcontrol: {
      options: {
        dir: 'dist',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      pages: {
        options: {
          remote: 'git@github.com:kaflan/nasha_lepta.git',
          branch: 'gh-pages'
        }
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin',
    'cssmin:combine'
  ]);
 grunt.registerTask('bildProject',[
   'clean:dist',
   'wiredep',
   'useminPrepare',
   'concurrent:dist',
   'autoprefixer',
   'concat',
   'ngAnnotate',
   'copy:dist',
   'cdnify',
   'cssmin',
   'uglify',
   'filerev',
   'usemin',
   'htmlmin',
   'buildcontrol'
 ]);
  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>chenges un grunt file add<commit_after>// Generated on 2015-07-10 using generator-angular 0.11.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }

    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp',
      css: {
        src: [ 'styles/' ]
      }
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
            detect: {
              js: /'(.*\.js)'/gi
            },
            replace: {
              js: '\'{{filePath}}\','
            }
          }
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '!<%= yeoman.dist %>/scripts/ckeditor/**/*',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['concat','cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: '<%= yeoman.dist %>/scripts/{,*/}*.js',
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles',
          '<%= yeoman.dist %>/scripts'
        ]
      }
    },

    cssmin: {
      combine: {
        files: {
          '<%= yeoman.dist %>/styles/combined.css': ['.tmp/concat/styles/vendor.css', '.tmp/concat/styles/main.css']
        }
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: [
            '*.html',
            'templates/{,*/}*.html'
          ],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: [
          '<%= yeoman.dist %>/*.html'
        ]
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'templates/**/*',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'scripts/ckeditor/**/*',
            'CNAME'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: 'bower_components/bootstrap/dist',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: 'bower_components/font-awesome',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    },
    /*https://github.com/robwierzbowski/grunt-build-control*/
    buildcontrol: {
      options: {
        dir: 'dist',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      pages: {
        options: {
          remote: 'git@github.com:kaflan/nasha_lepta.git',
          branch: 'gh-pages'
        }
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin',
    'cssmin:combine'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>const childProcess = require('child_process');
const escapeRegExp = require('lodash.escaperegexp');
const minimatch = require('minimatch');
const sortBy = require('lodash.sortby');
const uniqBy = require('lodash.uniqby');

const JsModule = require('./JsModule');

/**
 * Takes a string in any of the following four formats:
 *   dash-separated
 *   snake_case
 *   camelCase
 *   PascalCase
 * and turns it into a star-separated lower case format, like so:
 *   star*separated
 *
 * @param {String} string
 * @return {String}
 */
function formattedToRegex(string) {
  // Based on
  // http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby

  // The pattern to match in between words. The "es" and "s" match is there
  // to catch pluralized folder names. There is a risk that this is overly
  // aggressive and will lead to trouble down the line. In that case, we can
  // consider adding a configuration option to control mapping a singular
  // variable name to a plural folder name (suggested by @lencioni in #127).
  // E.g.
  //
  // {
  //   "^mock": "./mocks/"
  // }
  const splitPattern = '(es|s)?.?';

  // Split up the string, allow pluralizing and a single (any) character
  // in between. This will make e.g. 'fooBar' match 'foos/bar', 'foo_bar',
  // and 'foobar'.
  return string
    .replace(/([a-z\d])([A-Z])/g, `$1${splitPattern}$2`) // camelCase
    .replace(/[-_]/g, splitPattern)
    .toLowerCase();
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @return {Array<JsModule>}
 */
function findEnvironmentCoreModules(config, variableName) {
  return config.environmentCoreModules()
    .filter(dep => dep.toLowerCase() === variableName.toLowerCase())
    .map(dep => new JsModule({ importPath: dep }));
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @return {Array<JsModule>}
 */
function findImportsFromPackageJson(config, variableName) {
  const formattedVarName = formattedToRegex(variableName);

  const ignorePrefixes = config.get('ignore_package_prefixes')
    .map(prefix => escapeRegExp(prefix));

  const depRegex = RegExp(
    `^(?:${ignorePrefixes.join('|')})?${formattedVarName}$`
  );

  return config.packageDependencies()
    .filter(dep => dep.match(depRegex))
    .map(dep => (
      JsModule.construct({
        lookupPath: 'node_modules',
        relativeFilePath: `node_modules/${dep}/package.json`,
        stripFileExtensions: [],
      })
    ))
    .filter(jsModule => !!jsModule);
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @param {String} pathToCurrentFile
 * @return {Array<JsModule>}
 */
function findImportsFromLocalFiles(config, variableName, pathToCurrentFile) {
  const formattedVarName = formattedToRegex(variableName);
  const egrepCommand =
    `egrep -i \"(/|^)${formattedVarName}(/index)?(/package)?\.js.*\"`;

  const matchedModules = [];

  config.get('lookup_paths').forEach((lookupPath) => {
    if (lookupPath === '') {
      // If lookupPath is an empty string, the `find` command will not work
      // as desired so we bail early.
      throw new Error(`lookup path cannot be empty (${lookupPath})`);
    }

    const findCommand = [
      `find ${lookupPath}`,
      '-name "**.js*"',
      '-not -path "./node_modules/*"',
    ].join(' ');
    const command = `${findCommand} | ${egrepCommand}`;

    // TODO switch to spawn so we can start processing the stream as it comes
    // in.
    let out = '';
    let err = '';
    try {
      out = String(childProcess.execSync(command));
    } catch (error) {
      err = String(error.stderr);
    }

    if (err !== '') {
      throw new Error(err);
    }

    out.split('\n').forEach((f) => {
      // TODO: it looks like we process empty strings here too (f === '')
      if (config.get('excludes').some(
        (globPattern) => minimatch(f, globPattern))) {
        return;
      }

      const module = JsModule.construct({
        lookupPath,
        relativeFilePath: f,
        stripFileExtensions:
          config.get('strip_file_extensions', { fromFile: f }),
        makeRelativeTo:
          config.get('use_relative_paths', { fromFile: f }) &&
          pathToCurrentFile,
        stripFromPath: config.get('strip_from_path', { fromFile: f }),
      });

      if (module) {
        matchedModules.push(module);
      }
    });
  });

  return matchedModules;
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @param {String} pathToCurrentFile
 * @return {Array}
 */
function findJsModulesFor(config, variableName, pathToCurrentFile) {
  const aliasModule = config.resolveAlias(variableName, pathToCurrentFile);
  if (aliasModule) {
    return [aliasModule];
  }

  const namedImportsModule = config.resolveNamedExports(variableName);
  if (namedImportsModule) {
    return [namedImportsModule];
  }

  let matchedModules = [];

  matchedModules.push(...findEnvironmentCoreModules(config, variableName));
  matchedModules.push(...findImportsFromPackageJson(config, variableName));
  matchedModules.push(
    ...findImportsFromLocalFiles(config, variableName, pathToCurrentFile)
  );

  // If you have overlapping lookup paths, you might end up seeing the same
  // module to import twice. In order to dedupe these, we remove the module
  // with the longest path
  matchedModules = sortBy(matchedModules,
    (module) => module.importPath.length);
  matchedModules = uniqBy(matchedModules,
    (module) => module.filePath);
  return sortBy(matchedModules, (module) => module.displayName());
}

module.exports = findJsModulesFor;
<commit_msg>Rename findEnvironmentCoreModules to findImportsFromEnvironment<commit_after>const childProcess = require('child_process');
const escapeRegExp = require('lodash.escaperegexp');
const minimatch = require('minimatch');
const sortBy = require('lodash.sortby');
const uniqBy = require('lodash.uniqby');

const JsModule = require('./JsModule');

/**
 * Takes a string in any of the following four formats:
 *   dash-separated
 *   snake_case
 *   camelCase
 *   PascalCase
 * and turns it into a star-separated lower case format, like so:
 *   star*separated
 *
 * @param {String} string
 * @return {String}
 */
function formattedToRegex(string) {
  // Based on
  // http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby

  // The pattern to match in between words. The "es" and "s" match is there
  // to catch pluralized folder names. There is a risk that this is overly
  // aggressive and will lead to trouble down the line. In that case, we can
  // consider adding a configuration option to control mapping a singular
  // variable name to a plural folder name (suggested by @lencioni in #127).
  // E.g.
  //
  // {
  //   "^mock": "./mocks/"
  // }
  const splitPattern = '(es|s)?.?';

  // Split up the string, allow pluralizing and a single (any) character
  // in between. This will make e.g. 'fooBar' match 'foos/bar', 'foo_bar',
  // and 'foobar'.
  return string
    .replace(/([a-z\d])([A-Z])/g, `$1${splitPattern}$2`) // camelCase
    .replace(/[-_]/g, splitPattern)
    .toLowerCase();
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @return {Array<JsModule>}
 */
function findImportsFromEnvironment(config, variableName) {
  return config.environmentCoreModules()
    .filter(dep => dep.toLowerCase() === variableName.toLowerCase())
    .map(dep => new JsModule({ importPath: dep }));
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @return {Array<JsModule>}
 */
function findImportsFromPackageJson(config, variableName) {
  const formattedVarName = formattedToRegex(variableName);

  const ignorePrefixes = config.get('ignore_package_prefixes')
    .map(prefix => escapeRegExp(prefix));

  const depRegex = RegExp(
    `^(?:${ignorePrefixes.join('|')})?${formattedVarName}$`
  );

  return config.packageDependencies()
    .filter(dep => dep.match(depRegex))
    .map(dep => (
      JsModule.construct({
        lookupPath: 'node_modules',
        relativeFilePath: `node_modules/${dep}/package.json`,
        stripFileExtensions: [],
      })
    ))
    .filter(jsModule => !!jsModule);
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @param {String} pathToCurrentFile
 * @return {Array<JsModule>}
 */
function findImportsFromLocalFiles(config, variableName, pathToCurrentFile) {
  const formattedVarName = formattedToRegex(variableName);
  const egrepCommand =
    `egrep -i \"(/|^)${formattedVarName}(/index)?(/package)?\.js.*\"`;

  const matchedModules = [];

  config.get('lookup_paths').forEach((lookupPath) => {
    if (lookupPath === '') {
      // If lookupPath is an empty string, the `find` command will not work
      // as desired so we bail early.
      throw new Error(`lookup path cannot be empty (${lookupPath})`);
    }

    const findCommand = [
      `find ${lookupPath}`,
      '-name "**.js*"',
      '-not -path "./node_modules/*"',
    ].join(' ');
    const command = `${findCommand} | ${egrepCommand}`;

    // TODO switch to spawn so we can start processing the stream as it comes
    // in.
    let out = '';
    let err = '';
    try {
      out = String(childProcess.execSync(command));
    } catch (error) {
      err = String(error.stderr);
    }

    if (err !== '') {
      throw new Error(err);
    }

    out.split('\n').forEach((f) => {
      // TODO: it looks like we process empty strings here too (f === '')
      if (config.get('excludes').some(
        (globPattern) => minimatch(f, globPattern))) {
        return;
      }

      const module = JsModule.construct({
        lookupPath,
        relativeFilePath: f,
        stripFileExtensions:
          config.get('strip_file_extensions', { fromFile: f }),
        makeRelativeTo:
          config.get('use_relative_paths', { fromFile: f }) &&
          pathToCurrentFile,
        stripFromPath: config.get('strip_from_path', { fromFile: f }),
      });

      if (module) {
        matchedModules.push(module);
      }
    });
  });

  return matchedModules;
}

/**
 * @param {Configuration} config
 * @param {String} variableName
 * @param {String} pathToCurrentFile
 * @return {Array}
 */
function findJsModulesFor(config, variableName, pathToCurrentFile) {
  const aliasModule = config.resolveAlias(variableName, pathToCurrentFile);
  if (aliasModule) {
    return [aliasModule];
  }

  const namedImportsModule = config.resolveNamedExports(variableName);
  if (namedImportsModule) {
    return [namedImportsModule];
  }

  let matchedModules = [];

  matchedModules.push(...findImportsFromEnvironment(config, variableName));
  matchedModules.push(...findImportsFromPackageJson(config, variableName));
  matchedModules.push(
    ...findImportsFromLocalFiles(config, variableName, pathToCurrentFile)
  );

  // If you have overlapping lookup paths, you might end up seeing the same
  // module to import twice. In order to dedupe these, we remove the module
  // with the longest path
  matchedModules = sortBy(matchedModules,
    (module) => module.importPath.length);
  matchedModules = uniqBy(matchedModules,
    (module) => module.filePath);
  return sortBy(matchedModules, (module) => module.displayName());
}

module.exports = findJsModulesFor;
<|endoftext|>


<commit_before>import React from "react";
import classes from "./CompetitionCard.module.css";
import LinkButton from "../UI/LinkButton/LinkButton";
import Rank from "../Rank/Rank";

const CompetitionCard = (props) => {
  return (

{props.name}

            Organised by {props.organiser} ({props.organiserLdap}@)

Competition Details

            Start date:
            {new Date(props.startDate).toLocaleString()}

            End date:
            {new Date(props.endDate).toLocaleString()}

          Current ranking:
          <Rank>{props.rank}</Rank>

            Initial worth:
            t$???

            Current net worth:
            t${props.netWorth}

            Currently available:
            t${props.currentlyAvailable}

        <LinkButton
          onClick={() => props.onCompSelect(props.id)}
          inverted="true"
        >
          View Competition
        </LinkButton>

  );
};

export default CompetitionCard;
<commit_msg>Change initial worth display on compselect page and add styling to netwroth<commit_after>import React from "react";
import classes from "./CompetitionCard.module.css";
import LinkButton from "../UI/LinkButton/LinkButton";
import Rank from "../Rank/Rank";
import { INITIAL_WORTH } from "../../App";

const CompetitionCard = (props) => {
  return (

{props.name}

            Organised by {props.organiser} ({props.organiserLdap}@)

Competition Details

            Start date:
            {new Date(props.startDate).toLocaleString()}

            End date:
            {new Date(props.endDate).toLocaleString()}

          Current ranking:
          <Rank>{props.rank}</Rank>

            Initial worth:
            t${INITIAL_WORTH}

            Current net worth:
             INITIAL_WORTH
                  ? { color: "green" }
                  : { color: "red" }
              }
            >
              t${props.netWorth}

            Currently available:
            t${props.currentlyAvailable}

        <LinkButton
          onClick={() => props.onCompSelect(props.id)}
          inverted="true"
        >
          View Competition
        </LinkButton>

  );
};

export default CompetitionCard;
<|endoftext|>


<commit_before>/* global module:false */
module.exports = function(grunt) {
	var port = grunt.option('port') || 8000;
	var base = grunt.option('base') || '.';

	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		meta: {
			banner:
				'/*!\n' +
				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
				' * http://lab.hakim.se/reveal-js\n' +
				' * MIT licensed\n' +
				' *\n' +
				' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' +
				' */'
		},

		qunit: {
			files: [ 'test/*.html' ]
		},

		uglify: {
			options: {
				banner: '<%= meta.banner %>\n'
			},
			build: {
				src: 'js/reveal.js',
				dest: 'js/reveal.min.js'
			}
		},

		sass: {
			core: {
				files: {
					'css/reveal.css': 'css/reveal.scss',
				}
			},
			themes: {
				files: [
					{
						expand: true,
						cwd: 'css/theme/source',
						src: ['*.scss'],
						dest: 'css/theme',
						ext: '.css'
					}
				]
			}
		},

		autoprefixer: {
			dist: {
				src: 'css/reveal.css'
			}
		},

		cssmin: {
			compress: {
				files: {
					'css/reveal.min.css': [ 'css/reveal.css' ]
				}
			}
		},

		jshint: {
			options: {
				curly: false,
				eqeqeq: true,
				immed: true,
				latedef: true,
				newcap: true,
				noarg: true,
				sub: true,
				undef: true,
				eqnull: true,
				browser: true,
				expr: true,
				globals: {
					head: false,
					module: false,
					console: false,
					unescape: false,
					define: false,
					exports: false
				}
			},
			files: [ 'Gruntfile.js', 'js/reveal.js' ]
		},

		connect: {
			server: {
				options: {
					port: port,
					base: base,
					livereload: true,
					open: true
				}
			}
		},

		zip: {
			'reveal-js-presentation.zip': [
				'index.html',
				'css/**',
				'js/**',
				'lib/**',
				'images/**',
				'plugin/**',
				'**.md'
			]
		},

		watch: {
			js: {
				files: [ 'Gruntfile.js', 'js/reveal.js' ],
				tasks: 'js'
			},
			theme: {
				files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
				tasks: 'css-themes'
			},
			css: {
				files: [ 'css/reveal.scss' ],
				tasks: 'css-core'
			},
			html: {
				files: [ '*.html']
			},
			markdown: {
				files: [ '*.md' ]
			},
			options: {
				livereload: true
			}
		}

	});

	// Dependencies
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-sass' );
	grunt.loadNpmTasks( 'grunt-contrib-connect' );
	grunt.loadNpmTasks( 'grunt-autoprefixer' );
	grunt.loadNpmTasks( 'grunt-zip' );

	// Default task
	grunt.registerTask( 'default', [ 'css', 'js' ] );

	// JS task
	grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] );

	// Theme CSS
	grunt.registerTask( 'css-themes', [ 'sass:themes' ] );

	// Core framework CSS
	grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] );

	// All CSS
	grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] );

	// Package presentation to archive
	grunt.registerTask( 'package', [ 'default', 'zip' ] );

	// Serve presentation locally
	grunt.registerTask( 'serve', [ 'connect', 'watch' ] );

	// Run tests
	grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );

};
<commit_msg>temporarily remove jshint and tests from grunt flow because they fail terribly<commit_after>/* global module:false */
module.exports = function(grunt) {
	var port = grunt.option('port') || 8000;
	var base = grunt.option('base') || '.';

	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		meta: {
			banner:
				'/*!\n' +
				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
				' * http://lab.hakim.se/reveal-js\n' +
				' * MIT licensed\n' +
				' *\n' +
				' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' +
				' */'
		},

		qunit: {
			files: [ 'test/*.html' ]
		},

		uglify: {
			options: {
				banner: '<%= meta.banner %>\n'
			},
			build: {
				src: 'js/reveal.js',
				dest: 'js/reveal.min.js'
			}
		},

		sass: {
			core: {
				files: {
					'css/reveal.css': 'css/reveal.scss',
				}
			},
			themes: {
				files: [
					{
						expand: true,
						cwd: 'css/theme/source',
						src: ['*.scss'],
						dest: 'css/theme',
						ext: '.css'
					}
				]
			}
		},

		autoprefixer: {
			dist: {
				src: 'css/reveal.css'
			}
		},

		cssmin: {
			compress: {
				files: {
					'css/reveal.min.css': [ 'css/reveal.css' ]
				}
			}
		},

		jshint: {
			options: {
				curly: false,
				eqeqeq: true,
				immed: true,
				latedef: true,
				newcap: true,
				noarg: true,
				sub: true,
				undef: true,
				eqnull: true,
				browser: true,
				expr: true,
				globals: {
					head: false,
					module: false,
					console: false,
					unescape: false,
					define: false,
					exports: false
				}
			},
			files: [ 'Gruntfile.js', 'js/reveal.js' ]
		},

		connect: {
			server: {
				options: {
					port: port,
					base: base,
					livereload: true,
					open: true
				}
			}
		},

		zip: {
			'reveal-js-presentation.zip': [
				'index.html',
				'css/**',
				'js/**',
				'lib/**',
				'images/**',
				'plugin/**',
				'**.md'
			]
		},

		watch: {
			js: {
				files: [ 'Gruntfile.js', 'js/reveal.js' ],
				tasks: 'js'
			},
			theme: {
				files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ],
				tasks: 'css-themes'
			},
			css: {
				files: [ 'css/reveal.scss' ],
				tasks: 'css-core'
			},
			html: {
				files: [ '*.html']
			},
			markdown: {
				files: [ '*.md' ]
			},
			options: {
				livereload: true
			}
		}

	});

	// Dependencies
	grunt.loadNpmTasks( 'grunt-contrib-qunit' );
	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
	grunt.loadNpmTasks( 'grunt-contrib-watch' );
	grunt.loadNpmTasks( 'grunt-sass' );
	grunt.loadNpmTasks( 'grunt-contrib-connect' );
	grunt.loadNpmTasks( 'grunt-autoprefixer' );
	grunt.loadNpmTasks( 'grunt-zip' );

	// Default task
	grunt.registerTask( 'default', [ 'css', 'js' ] );

	// JS task
	grunt.registerTask( 'js', [ /*'jshint',*/ 'uglify'/*, 'qunit'*/ ] );

	// Theme CSS
	grunt.registerTask( 'css-themes', [ 'sass:themes' ] );

	// Core framework CSS
	grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] );

	// All CSS
	grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] );

	// Package presentation to archive
	grunt.registerTask( 'package', [ 'default', 'zip' ] );

	// Serve presentation locally
	grunt.registerTask( 'serve', [ 'connect', 'watch' ] );

	// Run tests
	grunt.registerTask( 'test', [ 'jshint', 'qunit' ] );

};
<|endoftext|>


<commit_before>// Require React
React = require('react/addons');
const createDOMPurify = require('dompurify');
const classNames = require('classnames');

// Material UI
import mui from 'material-ui';
const Colors = mui.Styles.Colors;

// Define component
const MemberStatus= React.createClass({

  render() {

    const paragraphStyles = {
      height: 'auto',
      margin: '5px',
      marginLeft: '0px'
    }

    const bioStyles = {
      fontSize: '14px',
      maxWidth: '100%',
    };

    const badgeStyles = {
      fontSize: '11px',
      lineHeight: '22px',
      padding: '5px 8px',
      marginRight: '5px',
      color: Colors.white,
      overflow: 'hidden',
      fontWeight: 'bold',
      width: '100%',
      borderRadius: 2
    }

    const emailStyles = {
      backgroundColor: '#555',
      cursor: 'pointer'
    }

    const bio = createDOMPurify.sanitize(this.props.member.bio, {ALLOWED_TAGS: ['b', 'i']});
    const isHireable = !this.props.member.company || this.props.member.hireable;

    return (

            {this.props.member.location}

          {this.props.member.bio?

 : ""}

            {this.props.member.email ?
              Email
             : '' }
            {this.props.member.hireable ?
              Hireable
             : !this.props.member.company ?
              May be hireable
             : ''}

            {this.props.member.company ?
              {this.props.member.company}
             : "" }

      );
  },

  _openMail(e) {
    e.preventDefault();
    window.location.href = 'mailto:' + this.props.member.email
    e.stopPropagation();
  }

});

module.exports = MemberStatus;
<commit_msg>Fix minor syntax issues<commit_after>// Require React
React = require('react/addons');
const createDOMPurify = require('dompurify');
const classNames = require('classnames');

// Material UI
import mui from 'material-ui';
const Colors = mui.Styles.Colors;

// Define component
const MemberStatus= React.createClass({
  render() {
    const paragraphStyles = {
      height: 'auto',
      margin: '5px',
      marginLeft: '0px'
    };

    const bioStyles = {
      fontSize: '14px',
      maxWidth: '100%',
    };

    const badgeStyles = {
      fontSize: '11px',
      lineHeight: '22px',
      padding: '5px 8px',
      marginRight: '5px',
      color: Colors.white,
      overflow: 'hidden',
      fontWeight: 'bold',
      width: '100%',
      borderRadius: 2
    };

    const emailStyles = {
      backgroundColor: '#555',
      cursor: 'pointer'
    };

    const bio = createDOMPurify.sanitize(
      this.props.member.bio,
      { ALLOWED_TAGS: ['b', 'i'] }
    );

    return (

            {this.props.member.location}

          {this.props.member.bio?

 : ""}

            {this.props.member.email ?
              Email
             : '' }
            {this.props.member.hireable ?
              Hireable
             : !this.props.member.company ?
              May be hireable
             : ''}

            {this.props.member.company ?
              {this.props.member.company}
             : "" }

      );
  },

  _openMail(e) {
    e.preventDefault();
    window.location.href = 'mailto:' + this.props.member.email
    e.stopPropagation();
  }

});

module.exports = MemberStatus;
<|endoftext|>


<commit_before>// Generated on 2014-11-01 using generator-angular 0.9.8
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist',
    server: 'server'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      },
      express: {
        files: ['<%= yeoman.server %>/**/*.js', '<%= yeoman.server %>/*.js'],
        tasks: ['express:dev'],
        options: {
          spawn: false
        }
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    express: {
      options: {
        port: 4004
      },
      dev: {
        options: {
          script: '<%= yeoman.server %>/server.js'
        }
      }
    },
    shell: {
      mongo: {
        command: 'mongod --port=27018',
        options: {
          async: true
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images']
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: ['*.js', '!oldieshim.js'],
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'shell:mongo',
      'express:dev',
      'wiredep',
      'concurrent:server',
      'autoprefixer',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>Do not start mongod by default<commit_after>// Generated on 2014-11-01 using generator-angular 0.9.8
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist',
    server: 'server'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      },
      express: {
        files: ['<%= yeoman.server %>/**/*.js', '<%= yeoman.server %>/*.js'],
        tasks: ['express:dev'],
        options: {
          spawn: false
        }
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    express: {
      options: {
        port: 4004
      },
      dev: {
        options: {
          script: '<%= yeoman.server %>/server.js'
        }
      }
    },
    shell: {
      mongo: {
        command: 'mongod --port=27018',
        options: {
          async: true
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images']
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: ['*.js', '!oldieshim.js'],
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'express:dev',
      'wiredep',
      'concurrent:server',
      'autoprefixer',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>socket.on('chat message', function (msg) {
    appendMessage(msg + "\n");
});

socket.on('renamed', function (msg) {
    playerName = msg;
});

socket.on('opponent disconnected', function (msg) {
    endGame(msg);
});

socket.on('make a move', function (msg) {
    setValue(msg.x, msg.y, msg.value);
    if (msg.isWinningMove.status) {
        drawResultLine(msg.isWinningMove.data);
        setTimeout(function () {
            endGame(msg.value);
        }, 500);
        return;
    }
    currentTurn = msg.nextTurn;
    currentTurnStyle();
    canMove = true;
});

socket.on('join table', function (msg) {
    currentTurn = msg.currentTurn;
    playerType = msg.playerX === playerName ? "x" : "o";
    $("#player" + playerType.toUpperCase()).removeClass("list-group-item-danger").addClass("list-group-item-success");
    $("#playerX").text("[X] " + msg.playerX);
    $("#playerO").text("[O] " + msg.playerO);
    $("#player" + currentTurn.toUpperCase()).addClass("current");
    $("ul").first().show();
    $("#leaveBtn").show();
    $("#messagePanel").show();
    $("#loadingTxt").hide();
    removeOverlay();
});

$(document).ready(function () {
    $("#joinBtn").on("click", function (e) {
        var name = $("#nameTxt").val();
        if (name.length < 4) {
            alert('Error! Your name must contains at least 4 characters!');
            return;
        }
        var $this = $(this);
        socket.emit('join queue', name);
        playerName = name;
        $("#loadingTxt").show();
        $("#leaveBtn").show();
        $this.parents("div").first().hide();
    });

    $("#leaveBtn").on("click", function (e) {
        if (overlayContainter !== null)
            return;
        socket.emit("leave game", null);
    });

    $("#sendBtn").on("click", function (e) {
        sendMessage();
    });

    $("#messageTxt").keypress(function (e) {
        var code = e.keyCode || e.which;
        if (code === 13) {
            e.preventDefault();
            sendMessage();
        }
    });
});

var sidebarInit = function () {
    //side bar (re)init
    $("#loadingTxt").show();
    $("#messageTxt").val("");
    $("#logPanel").val("");
    $("ul").first().hide();
    $("#messagePanel").hide();
    $(".current").first().removeClass("current");
};

var endGame = function (value) {
    alert("YOU " + (value === playerType ? " WIN!" : "LOSE!"));
    socket.emit('join queue', playerName);
    stage.clear();
    stage.removeAllChildren();
    init();
    sidebarInit();
};

var makeAMove = function (x, y) {
    socket.emit('make a move', {x: x, y: y}, function (msg) {
        if (!msg.ok) {
            alert('ERROR: CANNOT MAKE A MOVE');
            canMove = true;
        }
    });
};

var currentTurnStyle = function () {
    $("#playerX").toggleClass("current");
    $("#playerO").toggleClass("current");
};

var sendMessage = function (e) {
    var $messageTxt = $("#messageTxt");
    var msg = $messageTxt.val();
    $messageTxt.val("");
    appendMessage(playerName + ": " + msg + "\n");
    socket.emit('chat message', msg);
};

var appendMessage = function (msg) {
    var $logPanel = $("#logPanel");
    $logPanel.val($logPanel.val() + msg);
    if ($logPanel.length)
        $logPanel.scrollTop($logPanel[0].scrollHeight - $logPanel.height());
};<commit_msg>Add 'leave game' function. Improve UI. Syntax corrected.<commit_after>socket.on('chat message', function (msg) {
    appendMessage(msg + "\n");
});

socket.on('renamed', function (msg) {
    playerName = msg;
});

socket.on('opponent disconnected', function (msg) {
    endGame(msg);
});

socket.on('make a move', function (msg) {
    setValue(msg.x, msg.y, msg.value);
    if (msg.isWinningMove.status) {
        drawResultLine(msg.isWinningMove.data);
        setTimeout(function () {
            endGame(msg.value);
        }, 500);
        return;
    }
    currentTurn = msg.nextTurn;
    currentTurnStyle();
    canMove = true;
});

socket.on('join table', function (msg) {
    currentTurn = msg.currentTurn;
    playerType = msg.playerX === playerName ? "x" : "o";
    $("#player" + playerType.toUpperCase()).removeClass("list-group-item-danger").addClass("list-group-item-success");
    $("#playerX").text("[X] " + msg.playerX);
    $("#playerO").text("[O] " + msg.playerO);
    $("#player" + currentTurn.toUpperCase()).addClass("current");
    $("ul").first().show();
    $("#leaveBtn").show();
    $("#messagePanel").show();
    $("#loadingTxt").hide();
    removeOverlay();
});

$(document).ready(function () {
    $("#joinBtn").on("click", function (e) {
        var name = $("#nameTxt").val();
        if (name.length < 4) {
            alert('Error! Your name must contains at least 4 characters!');
            return;
        }
        var $this = $(this);
        socket.emit('join queue', name);
        playerName = name;
        $("#loadingTxt").show();
        $this.parents("div").first().hide();
    });

    $("#leaveBtn").on("click", function (e) {
        if (overlayContainter !== null)
            return;
        socket.emit("leave game", null);
    });

    $("#sendBtn").on("click", function (e) {
        sendMessage();
    });

    $("#messageTxt").keypress(function (e) {
        var code = e.keyCode || e.which;
        if (code === 13) {
            e.preventDefault();
            sendMessage();
        }
    });
});

var sidebarInit = function () {
    //side bar (re)init
    $("#loadingTxt").show();
    $("#messageTxt").val("");
    $("#logPanel").val("");
    $("ul").first().hide();
    $("#leaveBtn").hide();
    $("#messagePanel").hide();
    $(".current").first().removeClass("current");
};

var endGame = function (value) {
    alert("YOU " + (value === playerType ? " WIN!" : "LOSE!"));
    socket.emit('join queue', playerName);
    stage.clear();
    stage.removeAllChildren();
    init();
    sidebarInit();
};

var makeAMove = function (x, y) {
    socket.emit('make a move', {x: x, y: y}, function (msg) {
        if (!msg.ok) {
            alert('ERROR: CANNOT MAKE A MOVE');
            canMove = true;
        }
    });
};

var currentTurnStyle = function () {
    $("#playerX").toggleClass("current");
    $("#playerO").toggleClass("current");
};

var sendMessage = function (e) {
    var $messageTxt = $("#messageTxt");
    var msg = $messageTxt.val();
    $messageTxt.val("");
    appendMessage(playerName + ": " + msg + "\n");
    socket.emit('chat message', msg);
};

var appendMessage = function (msg) {
    var $logPanel = $("#logPanel");
    $logPanel.val($logPanel.val() + msg);
    if ($logPanel.length)
        $logPanel.scrollTop($logPanel[0].scrollHeight - $logPanel.height());
};<|endoftext|>


<commit_before>define([
  'require',
  'extensions/views/view',
  'd3loader!',
  './xaxis',
  './yaxis',
  './line',
  './stack',
  './linelabel',
  './hover',
  './callout',
  './tooltip'
],
function (require, View, d3, XAxis, YAxis, Line, Stack, LineLabel, Hover, Callout, Tooltip) {

  function scaleFromStartAndEndDates (dateFunction) {
    return {
      getXPos: function(groupIndex, modelIndex) {
        groupIndex = groupIndex || 0;
        var model = this.collection.at(groupIndex, modelIndex);
        return dateFunction(model);
      },
      calcXScale: function () {
        var start, end, xScale;
        var total = this.collection.first().get('values');
        start = dateFunction(total.first());
        end = dateFunction(total.last());
        xScale = this.d3.time.scale();
        xScale.domain([start.toDate(), end.toDate()]);
        xScale.range([0, this.innerWidth]);
        return xScale;
      }
    };
  };

  function hourlyScale () {
    return scaleFromStartAndEndDates(function (model) {
      return this.moment(model.get('_timestamp'));
    });
  };

  function dailyScale () {
    return scaleFromStartAndEndDates(function (model) {
      return this.moment(model.get('_end_at')).subtract(1, 'days');
    });
  };

  var Graph = View.extend({

    d3: d3,

    valueAttr: '_count',

    minYDomainExtent: 6,
    numYTicks: 7,

    sharedComponents: {
      xaxis: XAxis,
      yaxis: YAxis,
      line: Line,
      stack: Stack,
      linelabel: LineLabel,
      callout: Callout,
      hover: Hover,
      tooltip: Tooltip
    },

    initialize: function (options) {
      View.prototype.initialize.apply(this, arguments);

      var collection = this.collection = options.collection;
      collection.on('reset add remove', this.render, this);

      this.prepareGraphArea();

      this.scales = {};
      this.margin = {};

      // initialize graph components
      var componentInstances = this.componentInstances = [];
      var defaultComponentOptions = this.getDefaultComponentOptions();
      _.each(this.prop('components'), function (definition) {
        var options = _.extend({}, defaultComponentOptions, definition.options);
        componentInstances.push(new definition.view(options));
      }, this);

      $(window).on('resize', _.bind(this.render, this));
    },

    /**
     * Defines default options that get passed to all graph components.
     * This object will be extended with component-specific options.
     * @returns {Object} Default options that get passed to components
     */
    getDefaultComponentOptions: function () {
      return {
        graph: this,
        collection: this.collection,
        el: this.el,
        svg: this.svg,
        wrapper: this.wrapper,
        margin: this.margin,
        scales: this.scales
      }
    },

    prepareGraphArea: function () {
      this.innerEl = $('

');
      this.innerEl.appendTo(this.$el);

      var svg = this.svg = this.d3.select(this.$el[0]).append('svg');

      this.wrapper = svg.append('g')
        .classed('wrapper', true);
    },

    /**
     * Calculates current factor between size in displayed pixels and logical
     * size.
     */
    scaleFactor: function () {
      return this.$el.width() / this.width;
    },

    // Not implemented; override in configuration or subclass
    calcXScale: function () {
      throw('No x scale defined.');
    },

    // Not implemented; override in configuration or subclass
    calcYScale: function () {
      throw('No y scale defined.');
    },

    getConfigNames: function () {
      return ['overlay'];
    },

    pxToValue: function (cssVal) {
      if (!_.isString(cssVal)) {
        return null;
      }
      var matches = cssVal.match(/([0-9\.]+)px/);
      return matches ? parseFloat(matches[1]) : null;
    },

    resize: function () {
      var width = this.width = this.$el.width();

      // when both max-width and max-height are defined, scale graph according
      // to this aspect ratio
      var maxWidth = this.pxToValue(this.$el.css('max-width'));
      var maxHeight = this.pxToValue(this.$el.css('max-height'));
      var minHeight = this.pxToValue(this.$el.css('min-height'));
      if (maxWidth != null && maxHeight != null) {
        var aspectRatio = maxWidth / maxHeight;
        height = width / aspectRatio;
        if (minHeight != null) {
          height = Math.max(height, minHeight);
        }
      } else {
        height = this.$el.height();
      }
      this.height = height;

      // configure SVG for automatic resize
      this.svg.attr({
        width: '100%',
        height: '100%',
        viewBox: '0 0 ' + width + ' ' + height,
        style: 'max-width:' + width + 'px; max-height:' + height + 'px; display:block;'
      });
      $(this.svg.node()).height(height);

      var innerEl = this.innerEl;
      this.margin.top = innerEl.position().top;
      this.margin.left = innerEl.position().left;

      this.innerWidth = innerEl.outerWidth();
      this.innerHeight = innerEl.outerHeight();

      this.margin.bottom = height - this.margin.top - this.innerHeight;
      this.margin.right = width - this.margin.left - this.innerWidth;

      this.wrapper.attr('transform', [
        'translate(',
        this.margin.left,
        ', ',
        this.margin.top,
        ')'
      ].join(''));
    },

    applyConfig: function (name) {
      var config = this.configs[name];
      if (!config) {
        return;
      }

      if (config.initialize) {
        config.initialize.call(this);
      }

      _.each(config, function (value, key) {
        if (key === 'initialize') {
          return;
        }
        this[key] = value;
      }, this);
    },

    /**
     * Hide callout during resize if present. Works around bug in iOS Webkit
     * that incorrectly calculates height of inner element.
     */
    resizeWithCalloutHidden: function () {
      var callout = this.$el.find('.callout');
      var calloutHidden = callout.hasClass('performance-hidden');
      callout.addClass('performance-hidden');

      this.resize();

      if (!calloutHidden) {
        callout.removeClass('performance-hidden');
      }
    },

    /**
     * Applies current configuration, then renders components in defined order
     */
    render: function () {
      View.prototype.render.apply(this, arguments);

      this.resizeWithCalloutHidden();

      var configNames = this.getConfigNames();
      if (_.isString(configNames)) {
        configNames = [configNames];
      }

      _.each(configNames, function(configName) {
        this.applyConfig(configName);
      }, this);

      this.scales.x = this.calcXScale();
      this.scales.y = this.calcYScale();

      _.each(this.componentInstances, function (component) {
        _.each(configNames, function(configName) {
          component.applyConfig(configName);
        });
        component.render();
      }, this);
    },

    configs: {
      hour: hourlyScale(),
      day: dailyScale(),
      week: dailyScale(),
      month: {
        getXPos: function(groupIndex, modelIndex) {
          return modelIndex;
        },
        calcXScale: function () {
          var start, end, xScale;
          var total = this.collection.first().get('values');
          xScale = this.d3.scale.linear();
          xScale.domain([0, total.length - 1]);
          xScale.range([0, this.innerWidth]);
          return xScale;
        }
      },

      overlay: {
        getYPos: function (groupIndex, modelIndex) {
          var group = this.collection.at(groupIndex);
          var model = group.get('values').at(modelIndex);
          return model.get(this.valueAttr);
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var max = d3.max(this.collection.models, function (group) {
            return d3.max(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });

          var yScale = this.d3.scale.linear();
          var tickValues = this.calculateLinearTicks([0, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValues = tickValues.values;
          return yScale;
        }
      },

      stack: {
        initialize: function() {
          var valueAttr = this.valueAttr;
          var stack = this.d3.layout.stack()
            .values(function (group) {
              return group.get('values').models;
            })
            .y(function (model, index) {
              return model.get(valueAttr);
            });
          if (this.outStack) {
            stack.out(_.bind(this.outStack, this));
          }

          this.layers = stack(this.collection.models.slice().reverse());
        },
        getYPos: function (groupIndex, modelIndex) {
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          var yProperty = this.stackYProperty || 'y';
          if (model[yProperty] === null) {
            return null;
          }
          var y0Property = this.stackY0Property || 'y0';
          return model[y0Property] + model[yProperty];
        },
        getY0Pos: function (groupIndex, modelIndex) {
          var y0Property = this.stackY0Property || 'y0';
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          return model[y0Property];
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var sums = [];
          for (var i = 0; i < this.collection.at(0).get('values').length; i++) {
            sums.push(this.collection.reduce(function (memo, group) {
              return memo + group.get('values').at(i).get(valueAttr);
            }, 0));
          }
          var max = d3.max(sums);
          var yScale = this.d3.scale.linear();
          var tickValues = this.calculateLinearTicks([0, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValues = tickValues.values;
          return yScale;
        }
      }
    }
  });

  return Graph;
});
<commit_msg>Cleanup function<commit_after>define([
  'require',
  'extensions/views/view',
  'd3loader!',
  './xaxis',
  './yaxis',
  './line',
  './stack',
  './linelabel',
  './hover',
  './callout',
  './tooltip'
],
function (require, View, d3, XAxis, YAxis, Line, Stack, LineLabel, Hover, Callout, Tooltip) {

  function scaleFromStartAndEndDates (modelToDate) {
    return {
      getXPos: function(groupIndex, modelIndex) {
        groupIndex = groupIndex || 0;
        var model = this.collection.at(groupIndex, modelIndex);
        return modelToDate(model);
      },
      calcXScale: function () {
        var total = this.collection.first().get('values'),
            start = modelToDate(total.first()).toDate(),
            end = modelToDate(total.last()).toDate();

        return this.d3.time.scale()
                .domain([start, end])
                .range([0, this.innerWidth]);
      }
    };
  };

  function hourlyScale () {
    return scaleFromStartAndEndDates(function (model) {
      return this.moment(model.get('_timestamp'));
    });
  };

  function dailyScale () {
    return scaleFromStartAndEndDates(function (model) {
      return this.moment(model.get('_end_at')).subtract(1, 'days');
    });
  };

  var Graph = View.extend({

    d3: d3,

    valueAttr: '_count',

    minYDomainExtent: 6,
    numYTicks: 7,

    sharedComponents: {
      xaxis: XAxis,
      yaxis: YAxis,
      line: Line,
      stack: Stack,
      linelabel: LineLabel,
      callout: Callout,
      hover: Hover,
      tooltip: Tooltip
    },

    initialize: function (options) {
      View.prototype.initialize.apply(this, arguments);

      var collection = this.collection = options.collection;
      collection.on('reset add remove', this.render, this);

      this.prepareGraphArea();

      this.scales = {};
      this.margin = {};

      // initialize graph components
      var componentInstances = this.componentInstances = [];
      var defaultComponentOptions = this.getDefaultComponentOptions();
      _.each(this.prop('components'), function (definition) {
        var options = _.extend({}, defaultComponentOptions, definition.options);
        componentInstances.push(new definition.view(options));
      }, this);

      $(window).on('resize', _.bind(this.render, this));
    },

    /**
     * Defines default options that get passed to all graph components.
     * This object will be extended with component-specific options.
     * @returns {Object} Default options that get passed to components
     */
    getDefaultComponentOptions: function () {
      return {
        graph: this,
        collection: this.collection,
        el: this.el,
        svg: this.svg,
        wrapper: this.wrapper,
        margin: this.margin,
        scales: this.scales
      }
    },

    prepareGraphArea: function () {
      this.innerEl = $('

');
      this.innerEl.appendTo(this.$el);

      var svg = this.svg = this.d3.select(this.$el[0]).append('svg');

      this.wrapper = svg.append('g')
        .classed('wrapper', true);
    },

    /**
     * Calculates current factor between size in displayed pixels and logical
     * size.
     */
    scaleFactor: function () {
      return this.$el.width() / this.width;
    },

    // Not implemented; override in configuration or subclass
    calcXScale: function () {
      throw('No x scale defined.');
    },

    // Not implemented; override in configuration or subclass
    calcYScale: function () {
      throw('No y scale defined.');
    },

    getConfigNames: function () {
      return ['overlay'];
    },

    pxToValue: function (cssVal) {
      if (!_.isString(cssVal)) {
        return null;
      }
      var matches = cssVal.match(/([0-9\.]+)px/);
      return matches ? parseFloat(matches[1]) : null;
    },

    resize: function () {
      var width = this.width = this.$el.width();

      // when both max-width and max-height are defined, scale graph according
      // to this aspect ratio
      var maxWidth = this.pxToValue(this.$el.css('max-width'));
      var maxHeight = this.pxToValue(this.$el.css('max-height'));
      var minHeight = this.pxToValue(this.$el.css('min-height'));
      if (maxWidth != null && maxHeight != null) {
        var aspectRatio = maxWidth / maxHeight;
        height = width / aspectRatio;
        if (minHeight != null) {
          height = Math.max(height, minHeight);
        }
      } else {
        height = this.$el.height();
      }
      this.height = height;

      // configure SVG for automatic resize
      this.svg.attr({
        width: '100%',
        height: '100%',
        viewBox: '0 0 ' + width + ' ' + height,
        style: 'max-width:' + width + 'px; max-height:' + height + 'px; display:block;'
      });
      $(this.svg.node()).height(height);

      var innerEl = this.innerEl;
      this.margin.top = innerEl.position().top;
      this.margin.left = innerEl.position().left;

      this.innerWidth = innerEl.outerWidth();
      this.innerHeight = innerEl.outerHeight();

      this.margin.bottom = height - this.margin.top - this.innerHeight;
      this.margin.right = width - this.margin.left - this.innerWidth;

      this.wrapper.attr('transform', [
        'translate(',
        this.margin.left,
        ', ',
        this.margin.top,
        ')'
      ].join(''));
    },

    applyConfig: function (name) {
      var config = this.configs[name];
      if (!config) {
        return;
      }

      if (config.initialize) {
        config.initialize.call(this);
      }

      _.each(config, function (value, key) {
        if (key === 'initialize') {
          return;
        }
        this[key] = value;
      }, this);
    },

    /**
     * Hide callout during resize if present. Works around bug in iOS Webkit
     * that incorrectly calculates height of inner element.
     */
    resizeWithCalloutHidden: function () {
      var callout = this.$el.find('.callout');
      var calloutHidden = callout.hasClass('performance-hidden');
      callout.addClass('performance-hidden');

      this.resize();

      if (!calloutHidden) {
        callout.removeClass('performance-hidden');
      }
    },

    /**
     * Applies current configuration, then renders components in defined order
     */
    render: function () {
      View.prototype.render.apply(this, arguments);

      this.resizeWithCalloutHidden();

      var configNames = this.getConfigNames();
      if (_.isString(configNames)) {
        configNames = [configNames];
      }

      _.each(configNames, function(configName) {
        this.applyConfig(configName);
      }, this);

      this.scales.x = this.calcXScale();
      this.scales.y = this.calcYScale();

      _.each(this.componentInstances, function (component) {
        _.each(configNames, function(configName) {
          component.applyConfig(configName);
        });
        component.render();
      }, this);
    },

    configs: {
      hour: hourlyScale(),
      day: dailyScale(),
      week: dailyScale(),
      month: {
        getXPos: function(groupIndex, modelIndex) {
          return modelIndex;
        },
        calcXScale: function () {
          var start, end, xScale;
          var total = this.collection.first().get('values');
          xScale = this.d3.scale.linear();
          xScale.domain([0, total.length - 1]);
          xScale.range([0, this.innerWidth]);
          return xScale;
        }
      },

      overlay: {
        getYPos: function (groupIndex, modelIndex) {
          var group = this.collection.at(groupIndex);
          var model = group.get('values').at(modelIndex);
          return model.get(this.valueAttr);
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var max = d3.max(this.collection.models, function (group) {
            return d3.max(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });

          var yScale = this.d3.scale.linear();
          var tickValues = this.calculateLinearTicks([0, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValues = tickValues.values;
          return yScale;
        }
      },

      stack: {
        initialize: function() {
          var valueAttr = this.valueAttr;
          var stack = this.d3.layout.stack()
            .values(function (group) {
              return group.get('values').models;
            })
            .y(function (model, index) {
              return model.get(valueAttr);
            });
          if (this.outStack) {
            stack.out(_.bind(this.outStack, this));
          }

          this.layers = stack(this.collection.models.slice().reverse());
        },
        getYPos: function (groupIndex, modelIndex) {
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          var yProperty = this.stackYProperty || 'y';
          if (model[yProperty] === null) {
            return null;
          }
          var y0Property = this.stackY0Property || 'y0';
          return model[y0Property] + model[yProperty];
        },
        getY0Pos: function (groupIndex, modelIndex) {
          var y0Property = this.stackY0Property || 'y0';
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          return model[y0Property];
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var sums = [];
          for (var i = 0; i < this.collection.at(0).get('values').length; i++) {
            sums.push(this.collection.reduce(function (memo, group) {
              return memo + group.get('values').at(i).get(valueAttr);
            }, 0));
          }
          var max = d3.max(sums);
          var yScale = this.d3.scale.linear();
          var tickValues = this.calculateLinearTicks([0, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValues = tickValues.values;
          return yScale;
        }
      }
    }
  });

  return Graph;
});
<|endoftext|>