import Card from './Card.js';
import State from './State.js';
/**
* @class Deck
* @module Deck
* @see State
*/
export default class Deck {
/**
* @class
*/
constructor () {
// Set the internal cards to an empty array.
this.cards = [];
// Set the internal state to a new State().
this._state = new State();
}
/**
* @type {State}
*/
get state () {
return this._state;
}
set state (s) {
if (s instanceof State) {
this._state = s;
} else {
throw new Error('Passed value is not an instance of State');
}
}
/**
* Get a card based on position.
*
* @function getCard
* @param {number} index - Position of card within deck.
* @returns {Card|null} Returns Card or null.
* @memberof Deck
*/
getCard (index = -1) {
// Set a default.
let card = null;
// If index is less than cards.length.
if (index >= 0 && index < this.cards.length) {
card = this.cards[index];
}
// Return Card or null.
return card;
}
/**
* Update card based on its internal hash.
*
* @function updateCard
* @param {Card} c - Card to update in deck.
*/
updateCard (c) {
if (c instanceof Card) {
this.cards.forEach((card) => {
if (card.hash === c.hash) {
card = c;
}
});
} else {
throw new Error('Updated card must be Card!');
}
}
/**
* Size of Deck.
*
* @function size
* @returns {number} Returns number of cards.
*/
size () {
return this.cards.length;
}
/**
* Add a Card to the Deck.
*
* @function addCard
* @param {string} content - Text of card.
* @param {Array} qualities - Array of Expressions.
*/
addCard (content, qualities = []) {
// Can't add non-String content.
if (typeof content !== 'string') {
throw new Error('Card content must be string!');
}
// Can't pass non-array qualities.
if (!Array.isArray(qualities)) {
throw new Error('Qualities must be passed as array!');
}
// Create a new card and pass it the current state.
const c = new Card(content, qualities);
// Add a card to the existing deck.
this.cards.push(c);
}
/**
* Remove a Card from the Deck.
*
* @function removeCard
* @param {object} c - Card to remove from deck.
*/
removeCard (c) {
this.cards = this.cards.filter((entry) => {
return entry !== c;
});
}
/**
* Shuffle cards in Deck.
*
* @function shuffle
*/
shuffle () {
// Fisher-Yates shuffle.
for (let i = this.cards.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
// Swap positions using destructuring assignment.
[this.cards[i], this.cards[j]] = [this.cards[j], this.cards[i]];
}
}
/**
* Draw card from Deck.
*
* @function draw
* @param {number} size - Size of hand to draw from Deck.
* @returns {Array} Hand of cards.
*/
draw (size = 1) {
// Create a hand.
let hand = [];
// Prevent negative sizes.
if (size > 0) {
// Find all available cards.
hand = this.cards.filter((card) => {
// Pass the current state to the card.
return card.isAvailable(this.state);
});
// Slice out a sub-set of available cards.
hand = hand.slice(0, size);
}
return hand;
}
}