<commit_before>/**
 * @fileOverview Ensures that modules contain exports and/or all
 * modules are consumed within other modules.
 * @author René Fermann
 */

import Exports from '../ExportMap'
import { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
import { listFilesToProcess } from 'eslint/lib/util/glob-util'
import resolve from 'eslint-module-utils/resolve'
import docsUrl from '../docsUrl'

const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration'
const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'
const IMPORT_DECLARATION = 'ImportDeclaration'
const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
const IMPORT_SPECIFIER = 'ImportSpecifier'
const VARIABLE_DECLARATION = 'VariableDeclaration'
const FUNCTION_DECLARATION = 'FunctionDeclaration'
const DEFAULT = 'default'
const UNDEFINED = 'undefined'

let preparationDone = false
const importList = new Map()
const exportList = new Map()
const ignoredFiles = new Set()

const isNodeModule = path => {
  return path.indexOf('node_modules') > -1
}

/**
 * read all files matching the patterns in src and ignore
 *
 * return all files matching src pattern, which are not matching the ignore pattern
 */
const resolveFiles = (src, ignore) => {
  const srcFiles = new Set()
  const srcFileList = listFilesToProcess(src)

  // prepare list of ignored files
  const ignoredFilesList =  listFilesToProcess(ignore)
  ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename))

  // prepare list of source files, don't consider files from node_modules
  srcFileList.forEach(({ filename }) => {
    if (isNodeModule(filename)) {
      return
    }
    srcFiles.add(filename)
  })
  return srcFiles
}

/**
 * parse all source files and build up 2 maps containing the existing imports and exports
 */
const prepareImportsAndExports = (srcFiles, context) => {
  srcFiles.forEach(file => {
    if (isNodeModule(file)) {
      return
    }
    const exports = new Map()
    const imports = new Map()
    const currentExports = Exports.get(file, context)
    if (!currentExports) {
      return
    }
    const { imports: localImportList, namespace } = currentExports
    localImportList.forEach((value, key) => {
      if (isNodeModule(key)) {
        return
      }
      imports.set(key, value.importedSpecifiers)
    })
    importList.set(file, imports)

    // build up export list only, if file is not ignored
    if (ignoredFiles.has(file)) {
      return
    }
    namespace.forEach((value, key) => {
      exports.set(key, { whereUsed: new Set() })
    })
    exportList.set(file, exports)
  })
}

/**
 * traverse through all imports and add the respective path to the whereUsed-list
 * of the corresponding export
 */
const determineUsage = () => {
  importList.forEach((listValue, listKey) => {
    listValue.forEach((value, key) => {
      const exports = exportList.get(key)
      if (typeof exports !== UNDEFINED) {
        value.forEach(currentImport => {
          let specifier
          if (currentImport === IMPORT_DEFAULT_SPECIFIER) {
            specifier = DEFAULT
          } else {
            specifier = currentImport
          }
          if (typeof specifier !== UNDEFINED) {
            const exportStatement = exports.get(specifier)
            if (typeof exportStatement !== UNDEFINED) {
              const {whereUsed} = exportStatement
              whereUsed.add(listKey)
              exports.set(specifier, { whereUsed })
            }
          }
        })
      }
    })
  })
}

/**
 * prepare the lists of existing imports and exports - should only be executed once at
 * the start of a new eslint run
 */
const doPreparation = (src, ignore, context) => {
  const { id } = context

  // do some sanity checks
  if (!Array.isArray(src)) {
    throw new Error(`Rule ${id}: src option must be an array`)
  }

  if (!Array.isArray(ignore)) {
    throw new Error(`Rule ${id}: ignore option must be an array`)
  }

  if (src.length < 1) {
    throw new Error(`Rule ${id}: src option must be defined`)
  }

  // no empty patterns for paths, as this will cause issues during path resolution
  src.forEach(file => {
    if (file.length < 1) {
      throw new Error(`Rule ${id}: src option must not contain empty strings`)
    }
  })

  ignore.forEach(file => {
    if (file.length < 1) {
      throw new Error(`Rule ${id}: ignore option must not contain empty strings`)
    }
  })

  const srcFiles = resolveFiles(src, ignore)
  prepareImportsAndExports(srcFiles, context)
  determineUsage()
  preparationDone = true
}

const oldDefaultImportExists = imports => {
  return imports.has(IMPORT_DEFAULT_SPECIFIER)
}

const newDefaultImportExists = specifiers => {
  let hasNewDefaultImport = false
  specifiers.forEach(specifier => {
    if (specifier.type === IMPORT_DEFAULT_SPECIFIER) {
      hasNewDefaultImport = true
    }
  })
  return hasNewDefaultImport
}

module.exports = {
  meta: {
    docs: { url: docsUrl('no-unused-modules') },
    schema: [
      makeOptionsSchema({
        src: {
          description: 'files/paths to be analyzed (only for unused exports)',
          type: 'array',
        },
        ignore: {
          description: 'files/paths to be ignored (only for unused exports)',
          type: 'array',
        },
        missingExports: {
          description: 'report modules without any exports',
          type: 'boolean',
        },
        unusedExports: {
          description: 'report exports without any usage',
          type: 'boolean',
        },
      }),
    ],
  },

  create: context => {
    const { getFilename } = context
    const { src, ignore, missingExports = false, unusedExports = false } = context.options[0]

    if (unusedExports && !preparationDone) {
      doPreparation(src, ignore, context)
    }

    const file = getFilename()

    const checkExportPresence = node => {
      if (ignoredFiles.has(file)) {
        return
      }

      const exportCount = exportList.get(file)
      if (missingExports && exportCount.size < 1) {
        // node.body[0] === 'undefined' only happens, if everything is commented out in the file
        // being linted
        context.report(node.body[0] ? node.body[0] : node, 'No exports found')
      }
    }

    const checkUsage = (node, exportedValue) => {
      if (!unusedExports) {
        return
      }

      if (ignoredFiles.has(file)) {
        return
      }
      const exports = exportList.get(file)
      const exportStatement = exports.get(exportedValue)
      if (typeof exportStatement !== UNDEFINED){
        const { whereUsed } = exportStatement
        if ( whereUsed.size < 1) {
          context.report(
            node,
            `exported declaration '${exportedValue}' not used within other modules`
          )
        }
      }
    }

    /**
     * only useful for tools like vscode-eslint
     *
     * update lists of existing exports during runtime
     */
    const updateExportUsage = node => {
      if (ignoredFiles.has(file)) {
        return
      }

      let exports = exportList.get(file)

      // new module has been created during runtime
      // include it in further processing
      if (typeof exports === UNDEFINED) {
        exports = new Map()
      }

      const newExports = new Map()
      const newExportIdentifiers = new Set()

      node.body.forEach(({ type, declaration, specifiers }) => {
        if (type === EXPORT_DEFAULT_DECLARATION) {
          newExportIdentifiers.add(DEFAULT)
        }
        if (type === EXPORT_NAMED_DECLARATION) {
          if (specifiers.length > 0) {
            specifiers.forEach(specifier => {
              newExportIdentifiers.add(specifier.local.name)
            })
          }
          if (declaration) {
            if (declaration.type === FUNCTION_DECLARATION) {
              newExportIdentifiers.add(declaration.id.name)
            }
            if (declaration.type === VARIABLE_DECLARATION) {
              declaration.declarations.forEach(({ id }) => {
                newExportIdentifiers.add(id.name)
              })
            }
          }
        }
      })

      // old exports exist within list of new exports identifiers: add to map of new exports
      exports.forEach((value, key) => {
        if (newExportIdentifiers.has(key)) {
          newExports.set(key, value)
        }
      })

      // new export identifiers added: add to map of new exports
      newExportIdentifiers.forEach(key => {
        if (!exports.has(key)) {
          newExports.set(key, {whereUsed: new Set()})
        }
      })
      exportList.set(file, newExports)
    }

    /**
     * only useful for tools like vscode-eslint
     *
     * update lists of existing imports during runtime
     */
    const updateImportUsage = node => {
      if (!unusedExports) {
        return
      }
      const oldImportPaths = importList.get(file)

      node.body.forEach(astNode => {
        if (astNode.type === IMPORT_DECLARATION) {
          const resolvedPath = resolve(astNode.source.value, context)

          if (!resolvedPath) {
            return
          }

          if (isNodeModule(resolvedPath)) {
            return
          }
          let imports = oldImportPaths.get(resolvedPath)
          const exports = exportList.get(resolvedPath)

          // unknown module
          if (typeof exports === UNDEFINED) {
            return
          }
          if (typeof imports === UNDEFINED) {
            imports = new Set()
          }

          const tmpImports = new Set()
          imports.forEach((value, key) => {
            if (key !== IMPORT_DEFAULT_SPECIFIER) {
              tmpImports.add(key)
            }
          })

          // update usage of default import/export
          const defaultExport = exports.get(DEFAULT)
          const hasOldDefaultImport = oldDefaultImportExists(imports)
          const hasNewDefaultImport = newDefaultImportExists(astNode.specifiers)

          if (hasNewDefaultImport && !hasOldDefaultImport) {
            imports.add(IMPORT_DEFAULT_SPECIFIER)
            if (typeof defaultExport !== UNDEFINED) {
              const { whereUsed } = defaultExport
              whereUsed.add(file)
            }
          }

          if (!hasNewDefaultImport && hasOldDefaultImport) {
            imports.delete(IMPORT_DEFAULT_SPECIFIER)
            if (typeof defaultExport !== UNDEFINED) {
              const { whereUsed } = defaultExport
              whereUsed.delete(file)
            }
          }

          // update usage of named imports/export
          astNode.specifiers.forEach(specifier => {
            imports.add(specifier.local.name)
            tmpImports.delete(specifier.local.name)

            const currentExport = exports.get(specifier.local.name)
            if (specifier.type === IMPORT_SPECIFIER) {
              if (typeof currentExport !== UNDEFINED) {
                currentExport.whereUsed.add(file)
              }
            }
          })

          // one or more imports have been removed: update usage list of exports
          if (tmpImports.size > 0) {
            tmpImports.forEach(key => {
              const currentExport = exports.get(key)
              if (typeof currentExport !== UNDEFINED) {
                const { whereUsed } = currentExport
                whereUsed.delete(file)
              }
            })
          }
        }
      })
    }

    return {
      'Program:exit': node => {
        updateExportUsage(node)
        updateImportUsage(node)
        checkExportPresence(node)
      },
      'ExportDefaultDeclaration': node => {
        checkUsage(node, DEFAULT)
      },
      'ExportNamedDeclaration': node => {
        if (node.specifiers) {
          node.specifiers.forEach(specifier => {
            if (specifier.exported) {
              checkUsage(node, specifier.exported.name)
            }
          })
        }
        if (node.declaration) {
          if (node.declaration.type === FUNCTION_DECLARATION) {
            checkUsage(node, node.declaration.id.name)
          }
          if (node.declaration.type === VARIABLE_DECLARATION) {
            node.declaration.declarations.forEach(declaration => {
              checkUsage(node, declaration.id.name)
            })
          }
        }
      },
    }
  },
}
<commit_msg>New: `no-unused-modules` rule - removed destructoring of context.getFilename<commit_after>/**
 * @fileOverview Ensures that modules contain exports and/or all
 * modules are consumed within other modules.
 * @author René Fermann
 */

import Exports from '../ExportMap'
import { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor'
import { listFilesToProcess } from 'eslint/lib/util/glob-util'
import resolve from 'eslint-module-utils/resolve'
import docsUrl from '../docsUrl'

const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration'
const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration'
const IMPORT_DECLARATION = 'ImportDeclaration'
const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
const IMPORT_SPECIFIER = 'ImportSpecifier'
const VARIABLE_DECLARATION = 'VariableDeclaration'
const FUNCTION_DECLARATION = 'FunctionDeclaration'
const DEFAULT = 'default'
const UNDEFINED = 'undefined'

let preparationDone = false
const importList = new Map()
const exportList = new Map()
const ignoredFiles = new Set()

const isNodeModule = path => {
  return path.indexOf('node_modules') > -1
}

/**
 * read all files matching the patterns in src and ignore
 *
 * return all files matching src pattern, which are not matching the ignore pattern
 */
const resolveFiles = (src, ignore) => {
  const srcFiles = new Set()
  const srcFileList = listFilesToProcess(src)

  // prepare list of ignored files
  const ignoredFilesList =  listFilesToProcess(ignore)
  ignoredFilesList.forEach(({ filename }) => ignoredFiles.add(filename))

  // prepare list of source files, don't consider files from node_modules
  srcFileList.forEach(({ filename }) => {
    if (isNodeModule(filename)) {
      return
    }
    srcFiles.add(filename)
  })
  return srcFiles
}

/**
 * parse all source files and build up 2 maps containing the existing imports and exports
 */
const prepareImportsAndExports = (srcFiles, context) => {
  srcFiles.forEach(file => {
    if (isNodeModule(file)) {
      return
    }
    const exports = new Map()
    const imports = new Map()
    const currentExports = Exports.get(file, context)
    if (!currentExports) {
      return
    }
    const { imports: localImportList, namespace } = currentExports
    localImportList.forEach((value, key) => {
      if (isNodeModule(key)) {
        return
      }
      imports.set(key, value.importedSpecifiers)
    })
    importList.set(file, imports)

    // build up export list only, if file is not ignored
    if (ignoredFiles.has(file)) {
      return
    }
    namespace.forEach((value, key) => {
      exports.set(key, { whereUsed: new Set() })
    })
    exportList.set(file, exports)
  })
}

/**
 * traverse through all imports and add the respective path to the whereUsed-list
 * of the corresponding export
 */
const determineUsage = () => {
  importList.forEach((listValue, listKey) => {
    listValue.forEach((value, key) => {
      const exports = exportList.get(key)
      if (typeof exports !== UNDEFINED) {
        value.forEach(currentImport => {
          let specifier
          if (currentImport === IMPORT_DEFAULT_SPECIFIER) {
            specifier = DEFAULT
          } else {
            specifier = currentImport
          }
          if (typeof specifier !== UNDEFINED) {
            const exportStatement = exports.get(specifier)
            if (typeof exportStatement !== UNDEFINED) {
              const {whereUsed} = exportStatement
              whereUsed.add(listKey)
              exports.set(specifier, { whereUsed })
            }
          }
        })
      }
    })
  })
}

/**
 * prepare the lists of existing imports and exports - should only be executed once at
 * the start of a new eslint run
 */
const doPreparation = (src, ignore, context) => {
  const { id } = context

  // do some sanity checks
  if (!Array.isArray(src)) {
    throw new Error(`Rule ${id}: src option must be an array`)
  }

  if (!Array.isArray(ignore)) {
    throw new Error(`Rule ${id}: ignore option must be an array`)
  }

  if (src.length < 1) {
    throw new Error(`Rule ${id}: src option must be defined`)
  }

  // no empty patterns for paths, as this will cause issues during path resolution
  src.forEach(file => {
    if (file.length < 1) {
      throw new Error(`Rule ${id}: src option must not contain empty strings`)
    }
  })

  ignore.forEach(file => {
    if (file.length < 1) {
      throw new Error(`Rule ${id}: ignore option must not contain empty strings`)
    }
  })

  const srcFiles = resolveFiles(src, ignore)
  prepareImportsAndExports(srcFiles, context)
  determineUsage()
  preparationDone = true
}

const oldDefaultImportExists = imports => {
  return imports.has(IMPORT_DEFAULT_SPECIFIER)
}

const newDefaultImportExists = specifiers => {
  let hasNewDefaultImport = false
  specifiers.forEach(specifier => {
    if (specifier.type === IMPORT_DEFAULT_SPECIFIER) {
      hasNewDefaultImport = true
    }
  })
  return hasNewDefaultImport
}

module.exports = {
  meta: {
    docs: { url: docsUrl('no-unused-modules') },
    schema: [
      makeOptionsSchema({
        src: {
          description: 'files/paths to be analyzed (only for unused exports)',
          type: 'array',
        },
        ignore: {
          description: 'files/paths to be ignored (only for unused exports)',
          type: 'array',
        },
        missingExports: {
          description: 'report modules without any exports',
          type: 'boolean',
        },
        unusedExports: {
          description: 'report exports without any usage',
          type: 'boolean',
        },
      }),
    ],
  },

  create: context => {
    const { src, ignore, missingExports = false, unusedExports = false } = context.options[0]

    if (unusedExports && !preparationDone) {
      doPreparation(src, ignore, context)
    }

    const file = context.getFilename()

    const checkExportPresence = node => {
      if (ignoredFiles.has(file)) {
        return
      }

      const exportCount = exportList.get(file)
      if (missingExports && exportCount.size < 1) {
        // node.body[0] === 'undefined' only happens, if everything is commented out in the file
        // being linted
        context.report(node.body[0] ? node.body[0] : node, 'No exports found')
      }
    }

    const checkUsage = (node, exportedValue) => {
      if (!unusedExports) {
        return
      }

      if (ignoredFiles.has(file)) {
        return
      }
      const exports = exportList.get(file)
      const exportStatement = exports.get(exportedValue)
      if (typeof exportStatement !== UNDEFINED){
        const { whereUsed } = exportStatement
        if ( whereUsed.size < 1) {
          context.report(
            node,
            `exported declaration '${exportedValue}' not used within other modules`
          )
        }
      }
    }

    /**
     * only useful for tools like vscode-eslint
     *
     * update lists of existing exports during runtime
     */
    const updateExportUsage = node => {
      if (ignoredFiles.has(file)) {
        return
      }

      let exports = exportList.get(file)

      // new module has been created during runtime
      // include it in further processing
      if (typeof exports === UNDEFINED) {
        exports = new Map()
      }

      const newExports = new Map()
      const newExportIdentifiers = new Set()

      node.body.forEach(({ type, declaration, specifiers }) => {
        if (type === EXPORT_DEFAULT_DECLARATION) {
          newExportIdentifiers.add(DEFAULT)
        }
        if (type === EXPORT_NAMED_DECLARATION) {
          if (specifiers.length > 0) {
            specifiers.forEach(specifier => {
              newExportIdentifiers.add(specifier.local.name)
            })
          }
          if (declaration) {
            if (declaration.type === FUNCTION_DECLARATION) {
              newExportIdentifiers.add(declaration.id.name)
            }
            if (declaration.type === VARIABLE_DECLARATION) {
              declaration.declarations.forEach(({ id }) => {
                newExportIdentifiers.add(id.name)
              })
            }
          }
        }
      })

      // old exports exist within list of new exports identifiers: add to map of new exports
      exports.forEach((value, key) => {
        if (newExportIdentifiers.has(key)) {
          newExports.set(key, value)
        }
      })

      // new export identifiers added: add to map of new exports
      newExportIdentifiers.forEach(key => {
        if (!exports.has(key)) {
          newExports.set(key, {whereUsed: new Set()})
        }
      })
      exportList.set(file, newExports)
    }

    /**
     * only useful for tools like vscode-eslint
     *
     * update lists of existing imports during runtime
     */
    const updateImportUsage = node => {
      if (!unusedExports) {
        return
      }
      const oldImportPaths = importList.get(file)

      node.body.forEach(astNode => {
        if (astNode.type === IMPORT_DECLARATION) {
          const resolvedPath = resolve(astNode.source.value, context)

          if (!resolvedPath) {
            return
          }

          if (isNodeModule(resolvedPath)) {
            return
          }
          let imports = oldImportPaths.get(resolvedPath)
          const exports = exportList.get(resolvedPath)

          // unknown module
          if (typeof exports === UNDEFINED) {
            return
          }
          if (typeof imports === UNDEFINED) {
            imports = new Set()
          }

          const tmpImports = new Set()
          imports.forEach((value, key) => {
            if (key !== IMPORT_DEFAULT_SPECIFIER) {
              tmpImports.add(key)
            }
          })

          // update usage of default import/export
          const defaultExport = exports.get(DEFAULT)
          const hasOldDefaultImport = oldDefaultImportExists(imports)
          const hasNewDefaultImport = newDefaultImportExists(astNode.specifiers)

          if (hasNewDefaultImport && !hasOldDefaultImport) {
            imports.add(IMPORT_DEFAULT_SPECIFIER)
            if (typeof defaultExport !== UNDEFINED) {
              const { whereUsed } = defaultExport
              whereUsed.add(file)
            }
          }

          if (!hasNewDefaultImport && hasOldDefaultImport) {
            imports.delete(IMPORT_DEFAULT_SPECIFIER)
            if (typeof defaultExport !== UNDEFINED) {
              const { whereUsed } = defaultExport
              whereUsed.delete(file)
            }
          }

          // update usage of named imports/export
          astNode.specifiers.forEach(specifier => {
            imports.add(specifier.local.name)
            tmpImports.delete(specifier.local.name)

            const currentExport = exports.get(specifier.local.name)
            if (specifier.type === IMPORT_SPECIFIER) {
              if (typeof currentExport !== UNDEFINED) {
                currentExport.whereUsed.add(file)
              }
            }
          })

          // one or more imports have been removed: update usage list of exports
          if (tmpImports.size > 0) {
            tmpImports.forEach(key => {
              const currentExport = exports.get(key)
              if (typeof currentExport !== UNDEFINED) {
                const { whereUsed } = currentExport
                whereUsed.delete(file)
              }
            })
          }
        }
      })
    }

    return {
      'Program:exit': node => {
        updateExportUsage(node)
        updateImportUsage(node)
        checkExportPresence(node)
      },
      'ExportDefaultDeclaration': node => {
        checkUsage(node, DEFAULT)
      },
      'ExportNamedDeclaration': node => {
        if (node.specifiers) {
          node.specifiers.forEach(specifier => {
            if (specifier.exported) {
              checkUsage(node, specifier.exported.name)
            }
          })
        }
        if (node.declaration) {
          if (node.declaration.type === FUNCTION_DECLARATION) {
            checkUsage(node, node.declaration.id.name)
          }
          if (node.declaration.type === VARIABLE_DECLARATION) {
            node.declaration.declarations.forEach(declaration => {
              checkUsage(node, declaration.id.name)
            })
          }
        }
      },
    }
  },
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React, { Component, PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Tetris.css';
import classNames from 'classnames/bind';
import {List, ListItem} from 'material-ui/List';
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import NavigationArrowDownward from 'material-ui/svg-icons/navigation/arrow-downward';
import NavigationArrowUpward from 'material-ui/svg-icons/navigation/arrow-upward';
import EditorSpaceBar from 'material-ui/svg-icons/editor/space-bar';
import FlatButton from 'material-ui/FlatButton';
import FontIcon from 'material-ui/FontIcon';
import AvPause from 'material-ui/svg-icons/av/pause';
import AvPlayArrow from 'material-ui/svg-icons/av/play-arrow';
import AvStop from  'material-ui/svg-icons/av/stop';
import HardwareGamepad from  'material-ui/svg-icons/hardware/gamepad';
import * as game from './TetrisGame';
import _ from 'underscore';
import {
  GridService,
  Piece,
  Coordinate,
  getBoardWidth,
  GameData
} from './TetrisGame';
class Tetris extends Component {

  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.setState({
      grid: GridService.getSingleton().grid,
      pieces: _.range(16),
    })
  }

  componentDidMount() {
    this.gameOn();
  }

  componentWillUnmount() {
    this.gameOver();
  }

  gameOn() {
    window.requestAnimationFrame(() => this.gameOn()); // use arrow functions to lexically capture this
    if(!this.isGamePause() && this.isGameStart()) {
        this.loop();
    }
  }

  loop = _.throttle(this.gameLoop, this.getGameSpeed(), {
      leading: false,
      trailing: false
  })

  gameLoop() {
    this.moveCurrentPiece();
    this.updateCurrentPiece();
    this.updateGhostPiece();
    this.setState({
      grid: GridService.getSingleton().grid,
      currentPiece: this.currentPiece
    })
    console.log('Game loops');
  }

  moveCurrentPiece() {
    var speedY = this.getPositionY() + 1;
    this.currentPiece.updatePosition({
        y: speedY
    }, () => this.insertAndClearRow());
  }

  updateCurrentPiece() {
    if(this.currentPiece) {
      this.currentPiece.updateCurrentPiece();
    }
  }

  insertAndClearRow() {
    this.insertPiece();
    GridService.checkAndClearFilledRow(function() {
        GameData.score += 100;
    });
  }

  insertPiece() {
    GridService.insertPiece(this.currentPiece, () => this.gameOver());
    this.currentPiece.destroy();
    this.currentPiece = null;
    this.createNewPiece();
  }

  updateGhostPiece() {
    if (this.currentPiece) {
        this.currentPiece.updateGhostPiece();
    }
  }

  startGame() {
    GridService.buildEmptyGameBoard();
    this.createNewPiece();
    this.setState({
      grid: GridService.getSingleton().grid,
      currentPiece: this.currentPiece,
      isPause: false,
      isStart: true
    })
  }
  resetGame() {
    GridService.buildEmptyGameBoard();
  }

  createNewPiece() {
    this.currentPiece = new Piece({
        x: 4,
        y: 0
    });
    let collisionPoint = this.currentPiece.calculateCollisionPoint();
    if(collisionPoint.y <= this.currentPiece.PositionY) {
      this.gameOver();
      this.currentPiece = null;
    }
  }

  getGameSpeed() {
    return GameData.getGameSpeed();
  }

  isGamePause() {
    return this.state.isPause;
  }

  isGameStart() {
    return this.state.isStart;
  }

  setGamePause(pause) {
    this.setState({
      isPause: pause
    })
  }

  setGameStart(start) {
    this.setState({
      isStart: start
    })
  }

  gameOver() {
    this.setGameStart(false);
  }

  getPositionX() {
      return this.currentPiece.PositionX;
  }

  getPositionY() {
      return this.currentPiece.PositionY;
  }

  getCurrentPiece() {
    return this.currentPiece;
  }

  getFilledCustomColor(cell) {
    if (cell.filled && cell.shape === 7) {
        return {
            'backgroundColor': GameData.getColor()
        };
    }else {
      return {};
    }
  }

  getFilledClass(cell) {
    var pieceClass = ['dy-grid-cell'];
    if (cell.filled || cell.current) {
        switch(cell.shape) {
            case 0: pieceClass.push('dy-L-filled');
                break;
            case 1: pieceClass.push('dy-O-filled');
                break;
            case 2: pieceClass.push('dy-I-filled');
                break;
            case 3: pieceClass.push('dy-T-filled');
                break;
            case 4: pieceClass.push('dy-J-filled');
                break;
            case 5: pieceClass.push('dy-S-filled');
                break;
            case 6: pieceClass.push('dy-Z-filled');
                break;
            default: pieceClass.push('dy-X-filled');
                break;
        }
    }
    if (cell.ghost) {
        if (pieceClass.length > 0) {
          pieceClass.push('dy-ghost-piece')
        }else {
          pieceClass.push('dy-ghost-piece')
        }
    }
    return pieceClass;
  }

  render() {
    let cx = classNames.bind(s);
    let cells = this.state.grid.map((cell, i) => {
      let styles = this.getFilledCustomColor(cell);
      let pieceClasses = this.getFilledClass(cell).map((c) => {
        return s[c];
      })
      return (

      )
    })
    let pauseText = this.state.isPause ? 'Resume' : 'Pause';

    let pauseIcon = this.state.isPause ? <AvPause /> : <AvPlayArrow />
    return (

              {cells}

              <FlatButton
                onClick={() => this.startGame()}
                label="New Game"
                icon={<HardwareGamepad />}
              />
              <FlatButton
                onClick={() => this.setGamePause(!this.state.isPause)}
                label={pauseText}
                icon={pauseIcon}
              />
              <FlatButton
                onClick={() => this.gameOver()}
                label="Stop"
                icon={<AvStop />}
              />

Instructions

          <List>
            <ListItem primaryText="Move to the right" rightIcon={<NavigationArrowForward />} />
            <ListItem primaryText="Rotate left" rightIcon={<NavigationArrowDownward />} />
            <ListItem primaryText="Rotate right" rightIcon={<NavigationArrowUpward />} />
            <ListItem primaryText="Move to the left" rightIcon={<NavigationArrowBack />} />
            <ListItem primaryText="All the way to the bottom" rightIcon={<EditorSpaceBar />} />
          </List>

    );
  }

}

export default withStyles(s)(Tetris);
<commit_msg>game start<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React, { Component, PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Tetris.css';
import classNames from 'classnames/bind';
import {List, ListItem} from 'material-ui/List';
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import NavigationArrowDownward from 'material-ui/svg-icons/navigation/arrow-downward';
import NavigationArrowUpward from 'material-ui/svg-icons/navigation/arrow-upward';
import EditorSpaceBar from 'material-ui/svg-icons/editor/space-bar';
import FlatButton from 'material-ui/FlatButton';
import FontIcon from 'material-ui/FontIcon';
import AvPause from 'material-ui/svg-icons/av/pause';
import AvPlayArrow from 'material-ui/svg-icons/av/play-arrow';
import AvStop from  'material-ui/svg-icons/av/stop';
import HardwareGamepad from  'material-ui/svg-icons/hardware/gamepad';
import * as game from './TetrisGame';
import _ from 'underscore';
import {
  GridService,
  Piece,
  Coordinate,
  getBoardWidth,
  GameData
} from './TetrisGame';
class Tetris extends Component {

  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.setState({
      grid: GridService.getSingleton().grid,
      pieces: _.range(16),
    })
  }

  componentDidMount() {
    this.gameOn();
    window.addEventListener('keydown', this.boundKeypressHandler);
  }

  rotatePiece(direction) {
    let oldRotation = this.currentPiece.Rotation,
        newRotation = oldRotation + direction;
    this.currentPiece.Rotation = newRotation < 0 ? newRotation + GameData.rotationLimit : newRotation % GameData.rotationLimit;
    let coord = this.currentPiece.convertPatternToCoordinates();
    for(let i = 0, len = coord.length; i < len; i++) {
        if (!this.currentPiece.withinGrid(coord[i])) {
            if (coord[i].x < 0) {
                this.movePieceInLevel('right');
                break;
            }
            if (coord[i].x >= getBoardWidth() ) {
                this.movePieceInLevel('left');
                if (this.currentPiece.patterns === 2) {
                    if (coord[i+1] && coord[i+1].x >= getBoardWidth()) {
                        this.moveCustomInLevel(-2);
                    }
                    break;
                } else {
                    break;
                }
            }
            if(!this.currentPiece.verifyPiece()) {
                this.currentPiece.Rotation = oldRotation;
                break;
            }
        }
    }
  }

  movePieceInLevel(direction) {
    let velocity = (direction === 'left') ? -1 : 1;
    let  speedX = this.currentPiece.PositionX + velocity;
    this.currentPiece.updatePosition({
        x: speedX
    });
  }

  hardDrop() {
      let cell = this.currentPiece.calculateCollisionPoint();
      this.currentPiece.updatePosition(cell, () => this.insertAndClearRow());
  }

  handleKeypress(event) {
    let key = event.keyCode;
    let rotateRight = 1,
        rotateLeft = -1;
    switch (key) {
        case 38:
            this.rotatePiece(rotateRight);
            break;
        case 37:
            this.movePieceInLevel('left');
            break;
        case 39:
            this.movePieceInLevel('right');
            break;
        case 40:
            this.rotatePiece(rotateLeft);
            break;
        case 32:
            this.hardDrop();
            break;
        case 27:
            this.setGamePause(!this.isPause);
            break;
        default:
            break;
    }
    this.updateGhostPiece();
  }

  boundKeypressHandler = this.handleKeypress.bind(this);

  componentWillUnmount() {
    this.gameOver();
    window.removeEventListener('keydown', this.boundKeypressHandler);
  }

  gameOn() {
    window.requestAnimationFrame(() => this.gameOn()); // use arrow functions to lexically capture this
    if(!this.isGamePause() && this.isGameStart()) {
        this.loop();
    }
  }

  loop = _.throttle(this.gameLoop, this.getGameSpeed(), {
      leading: false,
      trailing: false
  })

  gameLoop() {
    this.moveCurrentPiece();
    this.updateCurrentPiece();
    this.updateGhostPiece();
    this.setState({
      grid: GridService.getSingleton().grid,
      currentPiece: this.currentPiece
    })
  }

  moveCurrentPiece() {
    let speedY = this.getPositionY() + 1;
    this.currentPiece.updatePosition({
        y: speedY
    }, () => this.insertAndClearRow());
  }

  updateCurrentPiece() {
    if(this.currentPiece) {
      this.currentPiece.updateCurrentPiece();
    }
  }

  insertAndClearRow() {
    this.insertPiece();
    GridService.checkAndClearFilledRow(function() {
        GameData.score += 100;
    });
  }

  insertPiece() {
    GridService.insertPiece(this.currentPiece, () => this.gameOver());
    this.currentPiece.destroy();
    this.currentPiece = null;
    this.createNewPiece();
  }

  updateGhostPiece() {
    if (this.currentPiece) {
        this.currentPiece.updateGhostPiece();
    }
  }

  startGame() {
    GridService.buildEmptyGameBoard();
    this.createNewPiece();
    this.setState({
      grid: GridService.getSingleton().grid,
      currentPiece: this.currentPiece,
    });
    this.setGameStart(true);
  }
  resetGame() {
    GridService.buildEmptyGameBoard();
  }

  createNewPiece() {
    this.currentPiece = new Piece({
        x: 4,
        y: 0
    });
    let collisionPoint = this.currentPiece.calculateCollisionPoint();
    if(collisionPoint.y <= this.currentPiece.PositionY) {
      this.gameOver();
      this.currentPiece = null;
    }
  }

  getGameSpeed() {
    return GameData.getGameSpeed();
  }

  isGamePause() {
    return this.isPause;
  }

  isGameStart() {
    return this.isStart;
  }

  setGamePause(pause) {
    this.isPause = pause;
  }

  setGameStart(start) {
    this.isStart = start;
  }

  gameOver() {
    this.setGameStart(false);
  }

  getPositionX() {
      return this.currentPiece.PositionX;
  }

  getPositionY() {
      return this.currentPiece.PositionY;
  }

  getCurrentPiece() {
    return this.currentPiece;
  }

  getFilledCustomColor(cell) {
    if (cell.filled && cell.shape === 7) {
        return {
            'backgroundColor': GameData.getColor()
        };
    }else {
      return {};
    }
  }

  getFilledClass(cell) {
    let pieceClass = ['dy-grid-cell'];
    if (cell.filled || cell.current) {
        switch(cell.shape) {
            case 0: pieceClass.push('dy-L-filled');
                break;
            case 1: pieceClass.push('dy-O-filled');
                break;
            case 2: pieceClass.push('dy-I-filled');
                break;
            case 3: pieceClass.push('dy-T-filled');
                break;
            case 4: pieceClass.push('dy-J-filled');
                break;
            case 5: pieceClass.push('dy-S-filled');
                break;
            case 6: pieceClass.push('dy-Z-filled');
                break;
            default: pieceClass.push('dy-X-filled');
                break;
        }
    }
    if (cell.ghost) {
        if (pieceClass.length > 0) {
          pieceClass.push('dy-ghost-piece')
        }else {
          pieceClass.push('dy-ghost-piece')
        }
    }
    return pieceClass;
  }

  render() {
    let cx = classNames.bind(s);
    let cells = this.state.grid.map((cell, i) => {
      let styles = this.getFilledCustomColor(cell);
      let pieceClasses = this.getFilledClass(cell).map((c) => {
        return s[c];
      })
      return (

      )
    })
    let pauseText = this.isPause ? 'Resume' : 'Pause';

    let pauseIcon = this.isPause ? <AvPause /> : <AvPlayArrow />
    return (

              {cells}

              <FlatButton
                onClick={() => this.startGame()}
                label="New Game"
                icon={<HardwareGamepad />}
              />
              <FlatButton
                onClick={() => this.setGamePause(!this.isPause)}
                label={pauseText}
                icon={pauseIcon}
              />
              <FlatButton
                onClick={() => this.gameOver()}
                label="Stop"
                icon={<AvStop />}
              />

Instructions

          <List>
            <ListItem primaryText="Move to the right" rightIcon={<NavigationArrowForward />} />
            <ListItem primaryText="Rotate left" rightIcon={<NavigationArrowDownward />} />
            <ListItem primaryText="Rotate right" rightIcon={<NavigationArrowUpward />} />
            <ListItem primaryText="Move to the left" rightIcon={<NavigationArrowBack />} />
            <ListItem primaryText="All the way to the bottom" rightIcon={<EditorSpaceBar />} />
          </List>

    );
  }

}

export default withStyles(s)(Tetris);
<|endoftext|>


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

import {LitElement, html} from "lit";
import FormUtils from "../../commons/forms/form-utils";
import AnalysisUtils from "../../commons/analysis/analysis-utils";
import UtilsNew from "../../../core/utilsNew.js";
import "../../commons/forms/data-form.js";
import "../../commons/filters/catalog-search-autocomplete.js";

export default class IndividualMendelianErrorAnalysis extends LitElement {

    constructor() {
        super();

        this.#init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            toolParams: {
                type: Object,
            },
            opencgaSession: {
                type: Object,
            },
            title: {
                type: String,
            }
        };
    }

    #init() {
        this.ANALYSIS_TOOL = "mendelian-error";
        this.ANALYSIS_TITLE = "Mendelian Error";
        this.ANALYSIS_DESCRIPTION = "Compute a score to quantify Mendelian Error";

        this.DEFAULT_TOOLPARAMS = {};
        // Make a deep copy to avoid modifying default object.
        this.toolParams = {
            ...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
        };

        this.config = this.getDefaultConfig();
    }

    check() {
        return !!this.toolParams.individuals || !!this.toolParams.samples;
    }

    onFieldChange(e, field) {
        const param = field || e.detail.param;
        if (param) {
            this.toolParams = FormUtils.createObject(this.toolParams, param, e.detail.value);
        }
        // Enable this only when a dynamic property in the config can change
        this.config = this.getDefaultConfig();
        this.requestUpdate();
    }

    onSubmit() {
        const toolParams = {
            family: this.toolParams.family || "",
            individual: this.toolParams.individual || "",
            // sample: this.toolParams.sample || "",
        };
        const params = {
            study: this.opencgaSession.study.fqn,
            ...AnalysisUtils.fillJobParams(this.toolParams, this.ANALYSIS_TOOL)
        };
        AnalysisUtils.submit(
            this.ANALYSIS_TITLE,
            this.opencgaSession.opencgaClient.variants()
                .runMendelianError(toolParams, params),
            this,
        );
    }

    onClear() {
        this.toolParams = {
            ...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
        };
        this.config = this.getDefaultConfig();
    }

    render() {
        return html`
            <data-form
                .data="${this.toolParams}"
                .config="${this.config}"
                @fieldChange="${e => this.onFieldChange(e)}"
                @clear="${this.onClear}"
                @submit="${this.onSubmit}">
            </data-form>
        `;
    }

    getDefaultConfig() {
        const params = [
            {
                title: "Input Parameters",
                elements: [
                    {
                        title: "Select families",
                        field: "families",
                        type: "custom",
                        display: {
                            helpMessage: "Family IDs",
                            render: individuals => html `
                                <catalog-search-autocomplete
                                    .value="${individuals}"
                                    .resource="${"FAMILY"}"
                                    .opencgaSession="${this.opencgaSession}"
                                    .config="${{multiple: true, disabled: !!this.toolParams?.individual}}"
                                    @filterChange="${e => this.onFieldChange(e, "individuals")}">
                                </catalog-search-autocomplete>
                            `,
                        },
                    },
                    {
                        title: "Select individuals",
                        field: "individuals",
                        type: "custom",
                        display: {
                            helpMessage: "Individual IDs",
                            render: individuals => html `
                                <catalog-search-autocomplete
                                    .value="${individuals}"
                                    .resource="${"INDIVIDUAL"}"
                                    .opencgaSession="${this.opencgaSession}"
                                    .config="${{multiple: true, disabled: !!this.toolParams?.family}}"
                                    @filterChange="${e => this.onFieldChange(e, "individuals")}">
                                </catalog-search-autocomplete>
                            `,
                        },
                    },
                    // {
                    //     title: "Select samples",
                    //     field: "samples",
                    //     type: "custom",
                    //     display: {
                    //         render: samples => html `
                    //             <catalog-search-autocomplete
                    //                 .value="${samples}"
                    //                 .resource="${"SAMPLE"}"
                    //                 .opencgaSession="${this.opencgaSession}"
                    //                 .config="${{multiple: true, disabled: !!this.toolParams?.individuals}}"
                    //                 @filterChange="${e => this.onFieldChange(e, "samples")}">
                    //             </catalog-search-autocomplete>
                    //         `,
                    //     },
                    // },
                ],
            },
        ];

        return AnalysisUtils.getAnalysisConfiguration(
            this.ANALYSIS_TOOL,
            this.title ?? this.ANALYSIS_TITLE,
            this.ANALYSIS_DESCRIPTION,
            params,
            this.check()
        );
    }

}

customElements.define("mendelian-error-analysis", IndividualMendelianErrorAnalysis);
<commit_msg>wc: fix issues in mendelian-error analysis #TASK-2139<commit_after>/*
 * Copyright 2015-2016 OpenCB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {LitElement, html} from "lit";
import FormUtils from "../../commons/forms/form-utils";
import AnalysisUtils from "../../commons/analysis/analysis-utils";
import UtilsNew from "../../../core/utilsNew.js";
import "../../commons/forms/data-form.js";
import "../../commons/filters/catalog-search-autocomplete.js";

export default class IndividualMendelianErrorAnalysis extends LitElement {

    constructor() {
        super();

        this.#init();
    }

    createRenderRoot() {
        return this;
    }

    static get properties() {
        return {
            toolParams: {
                type: Object,
            },
            opencgaSession: {
                type: Object,
            },
            title: {
                type: String,
            }
        };
    }

    #init() {
        this.ANALYSIS_TOOL = "mendelian-error";
        this.ANALYSIS_TITLE = "Mendelian Error";
        this.ANALYSIS_DESCRIPTION = "Compute a score to quantify Mendelian Error";

        this.DEFAULT_TOOLPARAMS = {};
        // Make a deep copy to avoid modifying default object.
        this.toolParams = {
            ...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
        };

        this.config = this.getDefaultConfig();
    }

    check() {
        return !!this.toolParams.individual || !!this.toolParams.family;
    }

    onFieldChange(e, field) {
        const param = field || e.detail.param;
        if (param) {
            this.toolParams = FormUtils.createObject(this.toolParams, param, e.detail.value);
        }
        // Enable this only when a dynamic property in the config can change
        this.config = this.getDefaultConfig();
        this.requestUpdate();
    }

    onSubmit() {
        const toolParams = {
            family: this.toolParams.family || "",
            individual: this.toolParams.individual || "",
            // sample: this.toolParams.sample || "",
        };
        const params = {
            study: this.opencgaSession.study.fqn,
            ...AnalysisUtils.fillJobParams(this.toolParams, this.ANALYSIS_TOOL)
        };
        AnalysisUtils.submit(
            this.ANALYSIS_TITLE,
            this.opencgaSession.opencgaClient.variants()
                .runMendelianError(toolParams, params),
            this,
        );
    }

    onClear() {
        this.toolParams = {
            ...UtilsNew.objectClone(this.DEFAULT_TOOLPARAMS),
        };
        this.config = this.getDefaultConfig();
    }

    render() {
        return html`
            <data-form
                .data="${this.toolParams}"
                .config="${this.config}"
                @fieldChange="${e => this.onFieldChange(e)}"
                @clear="${this.onClear}"
                @submit="${this.onSubmit}">
            </data-form>
        `;
    }

    getDefaultConfig() {
        const params = [
            {
                title: "Input Parameters",
                elements: [
                    {
                        title: "Select family",
                        field: "family",
                        type: "custom",
                        display: {
                            helpMessage: "Family ID",
                            render: family => html `
                                <catalog-search-autocomplete
                                    .value="${family}"
                                    .resource="${"FAMILY"}"
                                    .opencgaSession="${this.opencgaSession}"
                                    .config="${{multiple: false, disabled: !!this.toolParams?.individual}}"
                                    @filterChange="${e => this.onFieldChange(e, "family")}">
                                </catalog-search-autocomplete>
                            `,
                        },
                    },
                    {
                        title: "Select individual",
                        field: "individual",
                        type: "custom",
                        display: {
                            helpMessage: "Individual ID",
                            render: individual => html `
                                <catalog-search-autocomplete
                                    .value="${individual}"
                                    .resource="${"INDIVIDUAL"}"
                                    .opencgaSession="${this.opencgaSession}"
                                    .config="${{multiple: false, disabled: !!this.toolParams?.family}}"
                                    @filterChange="${e => this.onFieldChange(e, "individual")}">
                                </catalog-search-autocomplete>
                            `,
                        },
                    },
                    // {
                    //     title: "Select samples",
                    //     field: "samples",
                    //     type: "custom",
                    //     display: {
                    //         render: samples => html `
                    //             <catalog-search-autocomplete
                    //                 .value="${samples}"
                    //                 .resource="${"SAMPLE"}"
                    //                 .opencgaSession="${this.opencgaSession}"
                    //                 .config="${{multiple: true, disabled: !!this.toolParams?.individuals}}"
                    //                 @filterChange="${e => this.onFieldChange(e, "samples")}">
                    //             </catalog-search-autocomplete>
                    //         `,
                    //     },
                    // },
                ],
            },
        ];

        return AnalysisUtils.getAnalysisConfiguration(
            this.ANALYSIS_TOOL,
            this.title ?? this.ANALYSIS_TITLE,
            this.ANALYSIS_DESCRIPTION,
            params,
            this.check()
        );
    }

}

customElements.define("mendelian-error-analysis", IndividualMendelianErrorAnalysis);
<|endoftext|>


<commit_before>define([ "Pilot", "Ship", "Team", "ui/FactionUI", "ui/ShipSilhouetteUI" ], function(Pilot, Ship, Team, FactionUI,
        ShipSilhouetteUI)
{
    "use strict";
    var PilotColumns = [
    {
        key: "faction",
        label: "Faction",
    },
    {
        key: "pilot",
        label: "Pilot",
        className: "textCell",
    },
    {
        key: "ship",
        label: "Ship",
        className: "textCell",
    },
    {
        key: "description",
        label: "Description",
        className: "textCell",
    },
    {
        key: "isImplemented",
        label: "Implemented",
    },
    {
        key: "pilotSkill",
        label: "Pilot Skill",
        className: "numberCell",
    },
    {
        key: "primaryWeapon",
        label: "Primary Weapon",
        className: "numberCell",
    },
    {
        key: "energy",
        label: "Energy",
        className: "numberCell",
    },
    {
        key: "agility",
        label: "Agility",
        className: "numberCell",
    },
    {
        key: "hull",
        label: "Hull",
        className: "numberCell",
    },
    {
        key: "shield",
        label: "Shield",
        className: "numberCell",
    },
    {
        key: "squadPointCost",
        label: "Squad Point Cost",
        className: "numberCell",
    },
    {
        key: "sumStats",
        label: "Sum Stats",
        className: "numberCell",
    },
    {
        key: "ratioPrimaryWeaponAgility",
        label: "Primary Weapon / Agility",
        className: "numberCell",
    },
    {
        key: "hullPlusShield",
        label: "Hull + Shield",
        className: "numberCell",
    },
    {
        key: "ratioSumStatsSquadPointCost",
        label: "Sum Stats / Squad Point Cost",
        className: "numberCell",
    }, ];

    var PilotStatisticsTable = React.createClass(
    {
        // Factories.
        Table: React.createFactory(Reactable.Table),
        Tr: React.createFactory(Reactable.Tr),
        Td: React.createFactory(Reactable.Td),
        Tfoot: React.createFactory(Reactable.Tfoot),

        filterColumns: [],

        componentWillMount: function()
        {
            for (var i = 5; i < 11; i++)
            {
                this.filterColumns.push(PilotColumns[i]);
            }
        },

        render: function()
        {
            var rows = [];

            this.filterColumns.forEach(function(column)
            {
                rows.push(this.createFilterRow(rows.length, column));
            }, this);

            rows.push(React.DOM.tr(
            {
                key: rows.length,
            }, this.createFilterUI()));

            rows.push(React.DOM.tr(
            {
                key: rows.length,
            }, this.createPilotTable()));

            return React.DOM.table(
            {
                id: "mainTable",
            }, React.DOM.tbody({}, rows));
        },

        createCell: function(key, column, value)
        {
            return this.Td(
            {
                key: key,
                className: column.className,
                column: column.key,
            }, (value !== undefined && value !== null ? value : " "));
        },

        createEntityTable: function(clientProps, entities, selectedValues)
        {
            if (entities && entities.length > 0)
            {
                var labelFunction = function(value)
                {
                    return value.name;
                }
                var checkboxPanel = React.createElement(CheckboxInputPanel,
                {
                    values: entities,
                    labelFunction: labelFunction,
                    initialValues: selectedValues,
                    onChange: this.handleChange,
                    panelClass: "entitiesTable",
                    clientProps: clientProps,
                });

                return React.DOM.div(
                {
                    className: "entitiesContainer",
                }, checkboxPanel);
            }
            else
            {
                return React.DOM.span({}, " ");
            }
        },

        createFilterRow: function(key, column)
        {
            var cells = [];
            LOGGER.info("key = " + key + " column = " + JSON.stringify(column));
            var filter = this.state[column.key];
            if (!filter) { throw "ERROR: missing filter for column = " + column.key; }

            cells.push(this.createCell(cells.length, column, React.DOM.input(
            {
                key: cells.length,
                id: column.key + "MinChecked",
                type: "checkbox",
                checked: filter.isMinEnabled,
                onChange: this.handleChange,
            })));
            cells.push(this.createCell(cells.length, column, React.DOM.input(
            {
                key: cells.length,
                id: column.key + "Min",
                type: "number",
                className: "filterField",
                value: filter.minValue,
                onChange: this.handleChange,
            })));

            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: "filterLabel",
                column: column.key,
            }, "\u2264 " + column.label + " \u2264"));

            cells.push(this.createCell(cells.length, column, React.DOM.input(
            {
                key: cells.length,
                id: column.key + "MaxChecked",
                type: "checkbox",
                checked: filter.isMaxEnabled,
                onChange: this.handleChange,
            })));
            cells.push(this.createCell(cells.length, column, React.DOM.input(
            {
                key: cells.length,
                id: column.key + "Max",
                type: "number",
                className: "filterField",
                value: filter.maxValue,
                onChange: this.handleChange,
            })));

            return React.DOM.tr(
            {
                key: key
            }, cells);
        },

        createFilterUI: function()
        {
            var factions = Team.values().map(function(teamKey)
            {
                return Team.properties[teamKey];
            });
            var ships = Ship.values().map(function(shipKey)
            {
                return Ship.properties[shipKey];
            });

            var rows = [];

            var cells = [];
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: "entityFilterContainer",
            }, "Faction"));
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: "entityFilterContainer",
            }, "Ship"));
            rows.push(React.DOM.tr(
            {
                key: rows.length,
            }, cells));

            var cells = [];
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: "entityFilterContainer",
            }, this.createEntityTable(
            {
                "data-entitytype": "faction",
            }, factions, [])));
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: "entityFilterContainer",
            }, this.createEntityTable(
            {
                "data-entitytype": "ship",
            }, ships, [])));
            rows.push(React.DOM.tr(
            {
                key: rows.length,
            }, cells));

            return React.DOM.table(
            {
                id: "mainTable",
                className: "entitiesTable",
            }, React.DOM.tbody({}, rows));
        },

        createImplementedImage: function(isImplemented, key)
        {
            InputValidator.validateNotNull("isImplemented", isImplemented);

            var implementedName = (isImplemented ? "accept" : "delete");
            var fileString = iconBase + implementedName + ".png";
            var myKey = (key ? key : 0);

            return React.DOM.img(
            {
                key: myKey,
                className: "isImplementedImage",
                src: fileString,
                title: isImplemented,
            });
        },

        createPilotTable: function()
        {
            var rows = [];

            var pilotKeys = Pilot.values();
            var self = this;

            pilotKeys.forEach(function(pilotKey, i)
            {
                var pilot = Pilot.properties[pilotKey];

                if (pilot.fore || pilot.aft)
                {
                    rows.push(self.createRow(pilot.fore, "fore" + i));
                    rows.push(self.createRow(pilot.aft, "aft" + i));
                }
                else
                {
                    rows.push(self.createRow(pilot, i));
                }
            });

            return this.Table(
            {
                id: "pilotTable",
                columns: PilotColumns,
                sortable: true,
            }, rows);
        },

        createRow: function(pilot, i)
        {
            var cells = [];

            var shipTeam = pilot.shipTeam;
            var ship = shipTeam.ship;
            var j = 0;

            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: shipTeam.team.name, // this allows sorting
            }, React.createElement(FactionUI,
            {
                factionKey: shipTeam.teamKey,
                isSmall: true,
            })));

            cells.push(this.createCell(cells.length, PilotColumns[j++], pilot.name));

            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: shipTeam.ship.name, // this allows sorting
            }, React.createElement(ShipSilhouetteUI,
            {
                shipKey: shipTeam.shipKey,
                showName: true,
            })));

            if (pilot.isFlavorText)
            {
                cells.push(this.Td(
                {
                    key: cells.length,
                    className: PilotColumns[j].className,
                    style:
                    {
                        fontStyle: "italic",
                    },
                    column: PilotColumns[j++].key,
                }, pilot.description));
            }
            else
            {
                cells.push(this.createCell(cells.length, PilotColumns[j++], pilot.description));
            }

            var isImplemented = (pilot.isImplemented !== undefined ? pilot.isImplemented : false);
            var implementedImage = this.createImplementedImage(isImplemented);
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: isImplemented, // this allows sorting
            }, implementedImage));

            var pilotSkill = pilot.pilotSkillValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], (pilotSkill ? pilotSkill : " ")));

            var primaryWeapon = ship.primaryWeaponValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], primaryWeapon));

            var energy = ship.energyValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], energy));

            var agility = ship.agilityValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], agility));

            var hull = ship.hullValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], hull));

            var shield = ship.shieldValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], shield));

            var squadPointCost = pilot.squadPointCost;
            cells.push(this.createCell(cells.length, PilotColumns[j++], (squadPointCost ? squadPointCost : " ")));

            var sum = (pilotSkill ? pilotSkill : 0) + (primaryWeapon ? primaryWeapon : 0) + agility + hull + shield;
            cells.push(this.createCell(cells.length, PilotColumns[j++], sum));

            var ratio0 = (agility ? primaryWeapon / agility : "");
            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: ratio0, // this allows sorting
            }, Math.vizziniFormat(ratio0, 2)));

            cells.push(this.createCell(cells.length, PilotColumns[j++], hull + shield));

            var ratio1 = (squadPointCost ? sum / squadPointCost : " ");
            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: ratio1, // this allows sorting
            }, Math.vizziniFormat(ratio1, 4)));

            return this.Tr(
            {
                key: i
            }, cells);
        },

        handleChange: function(event)
        {
            LOGGER.info("PilotStatisticsTable.handleChange()");
        },
    });

    return PilotStatisticsTable;
});
<commit_msg>Fixed missing data for huge ships. Removed filter stuff (didn't work).<commit_after>define(["Pilot", "Ship", "Team", "ui/FactionUI", "ui/ShipSilhouetteUI"], function(Pilot, Ship, Team, FactionUI,
    ShipSilhouetteUI)
{
    "use strict";
    var PilotColumns = [
        {
            key: "faction",
            label: "Faction",
    },
        {
            key: "pilot",
            label: "Pilot",
            className: "textCell",
    },
        {
            key: "ship",
            label: "Ship",
            className: "textCell",
    },
        {
            key: "description",
            label: "Description",
            className: "textCell",
    },
        {
            key: "isImplemented",
            label: "Implemented",
    },
        {
            key: "pilotSkill",
            label: "Pilot Skill",
            className: "numberCell",
    },
        {
            key: "primaryWeapon",
            label: "Primary Weapon",
            className: "numberCell",
    },
        {
            key: "energy",
            label: "Energy",
            className: "numberCell",
    },
        {
            key: "agility",
            label: "Agility",
            className: "numberCell",
    },
        {
            key: "hull",
            label: "Hull",
            className: "numberCell",
    },
        {
            key: "shield",
            label: "Shield",
            className: "numberCell",
    },
        {
            key: "squadPointCost",
            label: "Squad Point Cost",
            className: "numberCell",
    },
        {
            key: "sumStats",
            label: "Sum Stats",
            className: "numberCell",
    },
        {
            key: "ratioPrimaryWeaponAgility",
            label: "Primary Weapon / Agility",
            className: "numberCell",
    },
        {
            key: "hullPlusShield",
            label: "Hull + Shield",
            className: "numberCell",
    },
        {
            key: "ratioSumStatsSquadPointCost",
            label: "Sum Stats / Squad Point Cost",
            className: "numberCell",
    }, ];

    var PilotStatisticsTable = React.createClass(
    {
        // Factories.
        Table: React.createFactory(Reactable.Table),
        Tr: React.createFactory(Reactable.Tr),
        Td: React.createFactory(Reactable.Td),
        Tfoot: React.createFactory(Reactable.Tfoot),

        filterColumns: [],

        componentWillMount: function()
        {
            for (var i = 5; i < 11; i++)
            {
                this.filterColumns.push(PilotColumns[i]);
            }
        },

        render: function()
        {
            var rows = [];

            rows.push(React.DOM.tr(
            {
                key: rows.length,
            }, React.DOM.td(
            {}, this.createPilotTable())));

            return React.DOM.table(
            {
                id: "mainTable",
            }, React.DOM.tbody(
            {}, rows));
        },

        createCell: function(key, column, value)
        {
            return this.Td(
            {
                key: key,
                className: column.className,
                column: column.key,
            }, (value !== undefined && value !== null ? value : " "));
        },

        createEntityTable: function(clientProps, entities, selectedValues)
        {
            if (entities && entities.length > 0)
            {
                var labelFunction = function(value)
                {
                    return value.name;
                };
                var checkboxPanel = React.createElement(CheckboxInputPanel,
                {
                    values: entities,
                    labelFunction: labelFunction,
                    initialValues: selectedValues,
                    onChange: this.handleChange,
                    panelClass: "entitiesTable",
                    clientProps: clientProps,
                });

                return React.DOM.div(
                {
                    className: "entitiesContainer",
                }, checkboxPanel);
            }
            else
            {
                return React.DOM.span(
                {}, " ");
            }
        },

        createImplementedImage: function(isImplemented, key)
        {
            InputValidator.validateNotNull("isImplemented", isImplemented);

            var implementedName = (isImplemented ? "accept" : "delete");
            var fileString = iconBase + implementedName + ".png";
            var myKey = (key ? key : 0);

            return React.DOM.img(
            {
                key: myKey,
                className: "isImplementedImage",
                src: fileString,
                title: isImplemented,
            });
        },

        createPilotTable: function()
        {
            var rows = [];

            var pilotKeys = Pilot.values();
            var self = this;

            pilotKeys.forEach(function(pilotKey, i)
            {
                var pilot = Pilot.properties[pilotKey];

                if (pilot.fore || pilot.aft)
                {
                    rows.push(self.createRow(pilot.fore, "fore" + i));
                    rows.push(self.createRow(pilot.aft, "aft" + i));
                }
                else
                {
                    rows.push(self.createRow(pilot, i));
                }
            });

            return this.Table(
            {
                id: "pilotTable",
                columns: PilotColumns,
                sortable: true,
            }, rows);
        },

        createRow: function(pilot, i)
        {
            var cells = [];

            var shipTeam = pilot.shipTeam;
            var ship = shipTeam.ship;

            if (pilot.parent)
            {
                if (pilot.name.endsWith("(fore)"))
                {
                    ship = ship.fore;
                }
                else if (pilot.name.endsWith("(aft)"))
                {
                    ship = ship.aft;
                }
            }
            else if (ship.fore)
            {
                ship = ship.fore;
            }

            var j = 0;

            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: shipTeam.team.name, // this allows sorting
            }, React.createElement(FactionUI,
            {
                factionKey: shipTeam.teamKey,
                isSmall: true,
            })));

            cells.push(this.createCell(cells.length, PilotColumns[j++], pilot.name));

            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: shipTeam.ship.name, // this allows sorting
            }, React.createElement(ShipSilhouetteUI,
            {
                shipKey: shipTeam.shipKey,
                showName: true,
            })));

            if (pilot.isFlavorText)
            {
                cells.push(this.Td(
                {
                    key: cells.length,
                    className: PilotColumns[j].className,
                    style:
                    {
                        fontStyle: "italic",
                    },
                    column: PilotColumns[j++].key,
                }, pilot.description));
            }
            else
            {
                cells.push(this.createCell(cells.length, PilotColumns[j++], pilot.description));
            }

            var isImplemented = (pilot.isImplemented !== undefined ? pilot.isImplemented : false);
            var implementedImage = this.createImplementedImage(isImplemented);
            cells.push(React.DOM.td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: isImplemented, // this allows sorting
            }, implementedImage));

            var pilotSkill = pilot.pilotSkillValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], (pilotSkill ? pilotSkill : " ")));

            var primaryWeapon = ship.primaryWeaponValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], primaryWeapon));

            var energy = ship.energyValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], energy));

            var agility = ship.agilityValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], agility));

            var hull = ship.hullValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], hull));

            var shield = ship.shieldValue;
            cells.push(this.createCell(cells.length, PilotColumns[j++], shield));

            var squadPointCost = pilot.squadPointCost;
            cells.push(this.createCell(cells.length, PilotColumns[j++], (squadPointCost ? squadPointCost : " ")));

            var sum = (pilotSkill ? pilotSkill : 0) + (primaryWeapon ? primaryWeapon : 0) + agility + hull + shield;
            cells.push(this.createCell(cells.length, PilotColumns[j++], sum));

            var ratio0 = (agility ? primaryWeapon / agility : "");
            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: ratio0, // this allows sorting
            }, Math.vizziniFormat(ratio0, 2)));

            cells.push(this.createCell(cells.length, PilotColumns[j++], hull + shield));

            var ratio1 = (squadPointCost ? sum / squadPointCost : " ");
            cells.push(this.Td(
            {
                key: cells.length,
                className: PilotColumns[j].className,
                column: PilotColumns[j++].key,
                value: ratio1, // this allows sorting
            }, Math.vizziniFormat(ratio1, 4)));

            return this.Tr(
            {
                key: i
            }, cells);
        },

        handleChange: function(event)
        {
            LOGGER.info("PilotStatisticsTable.handleChange()");
        },
    });

    return PilotStatisticsTable;
});
<|endoftext|>


<commit_before>// https://github.com/marado/TalkerNode

"use strict";
var net = require('net');

var sockets = [];

var port = process.env.PORT || 8888;

var talkername = "Moosville";

/*
 * Cleans the input of carriage return, newline and control characters
 */
function cleanInput(data) {
	var newString = data.toString().replace("[\u0000-\u001f]", "");
	return newString.replace(/(\r\n|\n|\r)/gm,"");
}

/*
 * Method executed when data is received from a socket
 */
function receiveData(socket, data) {

	var cleanData = cleanInput(data);

	if(cleanData.length == 0)
		return;

	// Useful when in debug mode, you don't want this otherwise... it wouldn't be nice for your users' privacy, would it?
	// console.log("Moo [" + cleanData + "]");

	// TODO: We're just filtering out IAC commands. We should be dealing with them instead...
	// IAC commands
	var IAC = [
		1 , // Telnet IAC - Echo
		3 , // Telnet IAC - Suppress Go Ahead
		5 , // Telnet IAC - Status
		6 , // Telnet IAC - Timing Mark
		24, // Telnet IAC - Terminal Type
		31, // Telnet IAC - Window Size
		32, // Telnet IAC - Window Speed
		33, // Telnet IAC - Remote Flow Control
		34, // Telnet IAC - Linemode
		36  // Telnet IAC - Environment Variables
	];
	if (IAC.indexOf(cleanData.charCodeAt(0)) !== -1) {
		// This is IAC, not an user input
		console.log("Moo: IAC: [" + cleanData.charCodeAt(0) +"]");
		return;
	}

	if(socket.username == undefined) {
		// TODO: check if username is valid. We will probably only want a-Z characters, with a minimum and maximum length.
		// TODO: check if the username isn't reserved. Names like who, quit and version are usually reserved.
		// TODO: check if the username is already in use
		socket.username = cleanData;
		allButMe(socket,function(me,to){to.write("[Entering is: "+ me.username + " ]\r\n");});
		socket.write("\r\n\r\nWelcome " + socket.username + "\r\n");
		return;
	}

	// if we have a command...
	if (cleanData.charAt(0) === ".") {
		doCommand(socket, cleanData);
	} else {
		doCommand(socket, ".say " + cleanData);
	}

}

/*
 * Method for commands. In future this should be elsewhere, but for now we must start already separating this from the rest...
 */
function doCommand(socket, command) {
	switch(command.split(' ')[0]) {
		case ".quit":
			socket.end('Goodbye!\n');
			break;
		case ".say":
			allButMe(socket,function(me,to){to.write(me.username + ": " + command.split(' ').slice(1).join(" ") + "\r\n");});
			socket.write("You said: " + command.split(' ').slice(1).join(" ") + "\r\n");
			break;
		default:
			socket.write("There's no such thing as a " + command.split(' ')[0] + " command.\r\n");
			break;
	}
}

/*
 * Method executed when a socket ends
 */
function closeSocket(socket) {
	var i = sockets.indexOf(socket);
	if (i != -1) {
		sockets.splice(i, 1);
	}
}

/*
 * Callback method executed when a new TCP socket is opened.
 */
function newSocket(socket) {
	sockets.push(socket);
	socket.write('Welcome to the '+talkername+'!\r\n\r\nGive me a name:  ');
	socket.on('data', function(data) {
		receiveData(socket, data);
	})
	socket.on('end', function() {
		closeSocket(socket);
	})
}

/*
 * Execute function to all connected users *but* the triggering one
 */
function allButMe(socket,fn) {
	for(var i = 0; i<sockets.length; i++) {
		if (sockets[i] !== socket) {
			if (typeof sockets[i].username != 'undefined') fn(socket,sockets[i]);
		}
	}
}

// Create a new server and provide a callback for when a connection occurs
var server = net.createServer(newSocket);

// Listen on defined port
server.listen(port);
console.log(talkername + " initialized on port "+ port);
<commit_msg>usernames can only contain letters, have at least two characters and be no longer than 16 characters<commit_after>// https://github.com/marado/TalkerNode

"use strict";
var net = require('net');

var sockets = [];

var port = process.env.PORT || 8888;

var talkername = "Moosville";

/*
 * Cleans the input of carriage return, newline and control characters
 */
function cleanInput(data) {
	var newString = data.toString().replace("[\u0000-\u001f]", "");
	return newString.replace(/(\r\n|\n|\r)/gm,"");
}

/*
 * Method executed when data is received from a socket
 */
function receiveData(socket, data) {

	var cleanData = cleanInput(data);

	if(cleanData.length == 0)
		return;

	// Useful when in debug mode, you don't want this otherwise... it wouldn't be nice for your users' privacy, would it?
	// console.log("Moo [" + cleanData + "]");

	// TODO: We're just filtering out IAC commands. We should be dealing with them instead...
	// IAC commands
	var IAC = [
		1 , // Telnet IAC - Echo
		3 , // Telnet IAC - Suppress Go Ahead
		5 , // Telnet IAC - Status
		6 , // Telnet IAC - Timing Mark
		24, // Telnet IAC - Terminal Type
		31, // Telnet IAC - Window Size
		32, // Telnet IAC - Window Speed
		33, // Telnet IAC - Remote Flow Control
		34, // Telnet IAC - Linemode
		36  // Telnet IAC - Environment Variables
	];
	if (IAC.indexOf(cleanData.charCodeAt(0)) !== -1) {
		// This is IAC, not an user input
		console.log("Moo: IAC: [" + cleanData.charCodeAt(0) +"]");
		return;
	}

	if(socket.username == undefined) {
		// TODO: check if the username isn't reserved. Names like who, quit and version are usually reserved.
		// TODO: check if the username is already in use
		if ((cleanData.match(/^[a-zA-Z]+$/) !== null) && (1 < cleanData.length) && (cleanData.length < 17)) {
			socket.username = cleanData;
			allButMe(socket,function(me,to){to.write("[Entering is: "+ me.username + " ]\r\n");});
			socket.write("\r\nWelcome " + socket.username + "\r\n");
		} else {
			socket.write("\r\nInvalid username: it can only contain letters, have at least two characters and be no longer than 16 characters.\r\nGive me a name:  ");
		}
		return;
	}

	// if we have a command...
	if (cleanData.charAt(0) === ".") {
		doCommand(socket, cleanData);
	} else {
		doCommand(socket, ".say " + cleanData);
	}

}

/*
 * Method for commands. In future this should be elsewhere, but for now we must start already separating this from the rest...
 */
function doCommand(socket, command) {
	switch(command.split(' ')[0]) {
		case ".quit":
			socket.end('Goodbye!\n');
			break;
		case ".say":
			allButMe(socket,function(me,to){to.write(me.username + ": " + command.split(' ').slice(1).join(" ") + "\r\n");});
			socket.write("You said: " + command.split(' ').slice(1).join(" ") + "\r\n");
			break;
		default:
			socket.write("There's no such thing as a " + command.split(' ')[0] + " command.\r\n");
			break;
	}
}

/*
 * Method executed when a socket ends
 */
function closeSocket(socket) {
	var i = sockets.indexOf(socket);
	if (i != -1) {
		sockets.splice(i, 1);
	}
}

/*
 * Callback method executed when a new TCP socket is opened.
 */
function newSocket(socket) {
	sockets.push(socket);
	socket.write('Welcome to the '+talkername+'!\r\n\r\nGive me a name:  ');
	socket.on('data', function(data) {
		receiveData(socket, data);
	})
	socket.on('end', function() {
		closeSocket(socket);
	})
}

/*
 * Execute function to all connected users *but* the triggering one
 */
function allButMe(socket,fn) {
	for(var i = 0; i<sockets.length; i++) {
		if (sockets[i] !== socket) {
			if (typeof sockets[i].username != 'undefined') fn(socket,sockets[i]);
		}
	}
}

// Create a new server and provide a callback for when a connection occurs
var server = net.createServer(newSocket);

// Listen on defined port
server.listen(port);
console.log(talkername + " initialized on port "+ port);
<|endoftext|>