hench/module/cards/hench-cards.mjs
2024-12-29 13:10:58 -05:00

162 lines
4.3 KiB
JavaScript

import { CARD_ZONES } from "./hench-card.mjs";
const { StringField } = foundry.data.fields;
// Data Model
export class HenchCardsDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {};
}
}
// Document Class
export class HenchCards extends Cards {
/** @override */
static get TYPES() {
return [
'deck',
];
}
// Getters
get allCards() {
return this.cards.contents;
}
get deck() {
return this.cardsInZone(CARD_ZONES.DECK);
}
get discard() {
return this.allCards.filter(
c => c.system.zone === CARD_ZONES.DISCARD
);
}
get spread() {
return this.allCards.filter(
c => c.system.zone === CARD_ZONES.SPREAD
);
}
get held() {
return this.allCards.filter(
c => c.system.zone === CARD_ZONES.HELD
);
}
cardsInZone(zone) {
return this.allCards.filter(
c => c.system.zone === zone
).sort((a, b) => a.sort - b.sort);
}
// Mutations
async updateCards(mutation) {
await this.update({
cards: mutation,
});
}
// After moving cards, re-assign sorting to minimal required values
async realignSorting() {
await this.realignSubstackSorting(CARD_ZONES.DECK);
await this.realignSubstackSorting(CARD_ZONES.SPREAD);
await this.realignSubstackSorting(CARD_ZONES.HELD);
await this.realignSubstackSorting(CARD_ZONES.DISCARD);
}
async realignSubstackSorting(zone) {
const cards = this.cardsInZone(zone);
const sortedCards = cards.sort((a, b) => a.sort - b.sort);
const mutation = sortedCards.map(
(c, i) => ({
_id: c._id,
sort: i
})
);
await this.updateCards(mutation);
}
// Randomize sorting of cards, only in deck.
async shuffleDeck() {
const cards = this.cardsInZone(CARD_ZONES.DECK);
const shuffleMutation = cards.map(
c => ({
_id: c._id,
sort: Math.floor(Math.random() * cards.length)
})
);
await this.updateCards(shuffleMutation);
await this.realignSorting();
}
// Send all cards back to the deck, and shuffle.
async resetDeck() {
await this.sendCards(this.discard, CARD_ZONES.DECK);
await this.sendCards(this.held, CARD_ZONES.DECK);
await this.sendCards(this.spread, CARD_ZONES.DECK);
await this.shuffleDeck();
}
async sendCards(cards, zone, dest = CONST.CARD_DRAW_MODES.BOTTOM) {
const existingZone = this.cardsInZone(zone);
const mutation = cards.map(
(c, i) => {
let destIndex;
switch(dest) {
case CONST.CARD_DRAW_MODES.BOTTOM:
case CONST.CARD_DRAW_MODES.LAST:
destIndex = existingZone.length + i;
break;
case CONST.CARD_DRAW_MODES.TOP:
case CONST.CARD_DRAW_MODES.FIRST:
destIndex = (-1 * cards.length) + i;
break;
default: // Random
destIndex = Math.floor(Math.random() * existingZone.length);
}
return {
_id: c._id,
['system.zone']: zone,
sort: destIndex
};
}
);
await this.updateCards(mutation);
await this.realignSorting();
}
async drawSpread(amount, from = CONST.CARD_DRAW_MODES.TOP) {
let cardsToGrab = [];
switch(from) {
case CONST.CARD_DRAW_MODES.BOTTOM:
case CONST.CARD_DRAW_MODES.LAST:
cardsToGrab = this.deck.slice(this.deck.length - amount, this.deck.length);
break;
case CONST.CARD_DRAW_MODES.TOP:
case CONST.CARD_DRAW_MODES.FIRST:
cardsToGrab = this.deck.slice(0, amount);
break;
default: // Random
const randomized = this.deck.toSorted((a, b) => (Math.random() - 0.5));
cardsToGrab = randomized.slice(0, amount);
}
await this.sendCards(cardsToGrab, CARD_ZONES.SPREAD);
}
}