lpaulger/cribbage-the-game

View on GitHub
app/scripts/modules/PlayerModule.js

Summary

Maintainability
A
3 hrs
Test Coverage
define(['modules/PlayRulesModule', 'modules/PlayScoreKeeper', 'modules/PubSub'], function(PlayRules, ScoreKeeper, PubSub){
  'use strict';
  function Player(options){
    this.name = options.name; //required
    this.possessive = options.possessive; //required
    this.hand = options.hand || [];
    this.handInMemory = options.handInMemory || [];
    this.crib = options.crib || [];
    this.currentPoints = options.currentPoints || 0;
    this.points = options.points || 0;
    this.selectedScore = options.selectedScore;
    this.board = options.board;//required
    this.playRules = new PlayRules({board:options.board});
    this.scoreKeeper = new ScoreKeeper();
    this.mediator = PubSub;
  }

  Player.prototype.getSelectedCards = function(){
    return this.hand.filter(function(card){
      return card.selected === 'selected';
    });
  };

  Player.prototype.placeCardsInCrib = function(cribOwner){

    function removeFromHand(card){
      unselectCurrentCard.call(this, card);
      cribOwner.crib.push(this.hand.splice(this.hand.indexOf(card), 1)[0]);
    }

    function unselectCurrentCard(card){
      delete this.hand[this.hand.indexOf(card)].selected;
    }

    if(this.getSelectedCards().length === 2){
      this.getSelectedCards().forEach(removeFromHand.bind(this));
      cribOwner.crib.sort(sortByValue);
    }
  };

  Player.prototype.selectOneFromDeck = function(deck, cardIndex){
    var card = deck.selectOne(cardIndex);
    this.scoreKeeper.TwoForHisHeels(this, card);
    return card;
  };

  Player.prototype.selectCard = function(index){
    var _tempHand = this.hand.slice();
    var card = _tempHand.splice(index, 1)[0];//selectCardFromHand


    var hand = this.hand;

    if(this.playRules.isCardPlayable(this, card)){
      if(HandHelper.isOneSelected(hand, index))
        HandHelper.replaceOldCard(hand, index);
      else HandHelper.selectCard(hand, index);
    } else if(!this.playRules.hasPlayableCards(this)){
      throw new Error('No Playable Cards');
    } else {
      throw new Error('Invalid Playable Card');
    }
  };

  Player.prototype.placeCardOnTable = function(index){
    var _tempHand = this.hand.slice();
    var card = _tempHand.splice(index, 1)[0];//selectCardFromHand

    if(this.playRules.isCardPlayable(this, card)){
      this.board.placeCard(card, this);
      this.hand.splice(index, 1);
    }
  };

  Player.prototype.playCard = function(index){
    var _tempHand = this.hand.slice();
    var card = _tempHand.splice(index, 1)[0];//selectCardFromHand
    if(this.selectedScore !== undefined){
      evaluatePlayForSelectedCard.call(this);
      delete this.selectedScore;
    } else if(this.playRules.isCardPlayable(this, card)){
      this.placeCardOnTable(index);
      evaluatePlayForSelectedCard.call(this);
    } else if(!this.playRules.hasPlayableCards(this)){
      throw new Error('No Playable Cards');
    } else {
      throw new Error('Invalid Playable Card');
    }
  };

  Player.prototype.announceGo = function(){
    if(!this.playRules.hasPlayableCards(this)){
      this.mediator.publish('messages-add', this.name + ' said GO');
      this.board.announceGo(this);
    } else {
      throw new Error('Playable Cards');
    }
  };

  Player.prototype.isWinner = function(){
    var isWinner = this.points >= 121;
    if(isWinner)
      this.mediator.publish('winner', this);
    return isWinner;
  };

  Player.prototype.restoreHand = function(){
    this.hand = this.handInMemory;
    this.hand.forEach(function(card){
      delete card.selected;
    });
  };



  Player.prototype.selectCribCard = function(index){
    var hand = this.hand;

    if(HandHelper.isSelected(hand, index))
      HandHelper.unSelectCard(hand, index);
    else if(HandHelper.areTwoCardsSelected(hand, index))
      HandHelper.replaceOldCard(hand, index);
    else HandHelper.selectCard(hand, index);

    return this.getSelectedCards();
  };

  function sortByValue(a,b){
    return a.faceValue - b.faceValue;
  }

  function evaluatePlayForSelectedCard(){
    this.scoreKeeper.evaluatePlay(this, this.board.playedCards, this.board.totalPlayedCardsForRound);
    if(this.board.currentBoardValue === 31){
      this.board.resetBoard();
    }
  }

  var HandHelper = {
    selectCard: function(hand, index){
      hand[index].selected = 'selected';
      return hand;
    },
    unSelectCard: function(hand, index){
      delete hand[index].selected;
      return hand;
    },
    isSelected: function(hand, index){
      return hand[index].selected !== undefined;
    },
    isOneSelected: function(hand, index){
      var selectedCards = hand.filter(function(card){
        return card.selected === 'selected';
      });

      return selectedCards.length >= 1 && selectedCards.indexOf(index) === -1;
    },
    areTwoCardsSelected: function(hand, index){
      var selectedCards = hand.filter(function(card){
        return card.selected === 'selected';
      });

      return selectedCards.length > 1 && selectedCards.indexOf(index) === -1;
    },
    replaceOldCard: function(hand, index){
      var oldCard = hand.filter(function(card){
              return card.selected === 'selected';
            })[0];

      this.unSelectCard(hand, hand.indexOf(oldCard));
      return this.selectCard(hand, index);
    }
  };



  return Player;
});