ChessboardInterface.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import React from 'react/addons';
  2. import omit from 'lodash.omit';
  3. import GameStore from '../stores/GameStore';
  4. import GameActions from '../actions/GameActions';
  5. import onGameChange from '../mixins/onGameChange';
  6. import Chessboard from './Chessboard';
  7. import CapturedPieces from './CapturedPieces';
  8. import TableOfMoves from './TableOfMoves';
  9. const ChessboardInterface = React.createClass({
  10. propTypes: {
  11. io: React.PropTypes.object.isRequired,
  12. token: React.PropTypes.string.isRequired,
  13. soundsEnabled: React.PropTypes.bool.isRequired,
  14. color: React.PropTypes.oneOf(['white', 'black']).isRequired,
  15. gameOver: React.PropTypes.object.isRequired,
  16. isOpponentAvailable: React.PropTypes.bool.isRequired
  17. },
  18. mixins: [React.addons.PureRenderMixin, onGameChange],
  19. getInitialState() {
  20. return GameStore.getState();
  21. },
  22. componentDidUpdate(prevProps) {
  23. if (this.props.gameOver.get('status') &&
  24. !prevProps.gameOver.get('status')) {
  25. this.props.openModal('info', this._getGameOverMessage());
  26. }
  27. },
  28. render() {
  29. const {promotion, turn, gameOver, check} = this.state;
  30. return (
  31. <div id="board-moves-wrapper" className="clearfix">
  32. <audio preload="auto" ref="moveSnd">
  33. <source src="/snd/move.mp3" />
  34. </audio>
  35. <audio preload="auto" ref="checkSnd">
  36. <source src="/snd/check.mp3" />
  37. </audio>
  38. <div id="board-wrapper">
  39. <CapturedPieces />
  40. <Chessboard
  41. {...omit(this.props, 'soundsEnabled', 'gameOver')}
  42. gameOver={gameOver.get('status')}
  43. maybePlaySound={this._maybePlaySound} />
  44. </div>
  45. <TableOfMoves />
  46. <span className="promotion">
  47. <label>
  48. <span>Promotion: </span>
  49. <select value={promotion}
  50. onChange={this._onPromotionChange}>
  51. <option value="q">Queen</option>
  52. <option value="r">Rook</option>
  53. <option value="b">Bishop</option>
  54. <option value="n">Knight</option>
  55. </select>
  56. </label>
  57. </span>
  58. <span className="feedback">
  59. {!gameOver.get('status') ?
  60. <span>
  61. <span className="icon">
  62. {/* F -> white king, f -> black king*/
  63. turn === 'w' ? 'F' : 'f'}
  64. </span>
  65. {`${turn === 'w' ? 'White' : 'Black'} to move.`}
  66. {check ? <strong> Check.</strong> : null}
  67. </span> :
  68. <strong>
  69. <span className="icon">
  70. {gameOver.get('winner') === 'White' ? 'F' : 'f'}
  71. </span>
  72. {this._getGameOverMessage()}
  73. </strong>
  74. }
  75. </span>
  76. </div>
  77. );
  78. },
  79. _onGameChange() {
  80. this.setState(GameStore.getState());
  81. },
  82. _onPromotionChange(e) {
  83. GameActions.changePromotion(e.target.value);
  84. },
  85. _maybePlaySound() {
  86. if (this.props.soundsEnabled) {
  87. this.refs[this.state.check ? 'checkSnd' : 'moveSnd'].getDOMNode().play();
  88. }
  89. },
  90. _getGameOverMessage() {
  91. const type = this.props.gameOver.get('type');
  92. const winner = this.props.gameOver.get('winner');
  93. const loser = winner === 'White' ? 'Black' : 'White';
  94. return type === 'checkmate' ? `Checkmate. ${winner} wins!` :
  95. type === 'timeout' ? `${loser}‘s time is out. ${winner} wins!` :
  96. type === 'resign' ? `${loser} has resigned. ${winner} wins!` :
  97. type === 'draw' ? 'Draw.' :
  98. type === 'stalemate' ? 'Draw (Stalemate).' :
  99. type === 'threefoldRepetition' ? 'Draw (Threefold Repetition).' :
  100. type === 'insufficientMaterial' ? 'Draw (Insufficient Material)' : '';
  101. }
  102. });
  103. export default ChessboardInterface;