import "./style.scss"; import "./style-cards.css"; import Alpine from "alpinejs"; // import 'bootstrap/dist/js/bootstrap' Alpine.store('global', { cardsToSolve: Array(52).fill(0) }) Alpine.data("playingCardsPreview", () => ({ rankText: { 'A': 'Ace', '2': 'Two', '3': 'Three', '4': 'Four', '5': 'Five', '6': 'Six', '7': 'Seven', '8': 'Eight', '9': 'Nine', 'T': 'Ten', 'J': 'Jack', 'Q': 'Queen', 'K': 'King' }, suitText: { 'C': 'Clubs', 'D': 'Diamonds', 'H': 'Hearts', 'S': 'Spades' }, rankSlug(rank) { return `rank-${rank === 'T' ? '10' : rank}` }, suitSlug: { 'C': 'clubs', 'D': 'diams', 'H': 'hearts', 'S': 'spades' }, cardHtml(card, index) { if (card === '0' || card === 0) { return `<abbr title="Unknown" class="card" style="z-index:${this.stockCard(index)};"></abbr>` } else { return `<abbr title="${this.rankText[card[0]]} of ${this.suitText[card[1]]}" class="card ${this.rankSlug(card[0])} ${this.suitSlug[card[1]]}" style="z-index:${this.stockCard(index)};"><abbr class="rank" aria-hidden="true">${card[0]}</abbr><abbr class="suit" aria-hidden="true">&${this.suitSlug[card[1]]};</abbr><abbr class="suit-b" aria-hidden="true">&${this.suitSlug[card[1]]};</abbr><abbr class="rank-b" aria-hidden="true">${card[0]}</abbr></abbr>` } }, stockCard(index) { return 500 - (10 * index) } })); Alpine.data("cardsInputForm", () => ({ // "constants" for validation etc nonAlphaNumRegEx: /[\W_]+/g, suits: [], ranks: [], deck: [], minCards: 34, stockCount: 24, peaksCount: 28, onInit() { this.suits = "CDHS".split(""); this.ranks = "A23456789TJQK".split(""); this.deck = this.suits.flatMap((suit) => { return this.ranks.map((cval) => { return cval + suit; }); }); console.log(this.deck.join(", ")); console.log(`deck size: ${this.deck.length}`); }, // input validation inputValue: "", validCards: [], dupedCards: [], invalidCards: [], validMessages: [], invalidMessages: [], cardsToSolve: [], get isFormValid() { return this.isValidCardsLengthInRange && this.invalidMessages.length === 0; }, get isValidCardsLengthTooSmall() { return this.validCards.length < this.minCards; }, get isValidCardsLengthTooBig() { return this.validCards.length > this.deck.length; }, get isValidCardsLengthInRange() { return !this.isValidCardsLengthTooSmall && !this.isValidCardsLengthTooBig; }, validateCardsInput() { // reset arrays and parse the input this.validCards = []; this.invalidCards = []; this.dupedCards = []; this.validMessages = []; this.invalidMessages = []; // handle if input has alphanum chars - treat them as delimeters // if no alphanum chars, split by 2 chars except for 0 let userCards = this.nonAlphaNumRegEx.test(this.inputValue) ? this.inputValue .toUpperCase() .replace(this.nonAlphaNumRegEx,' ') .split(' ') .filter((c) => c) : this.inputValue .toUpperCase() .split(/0|(..)/g) .filter(c => c !== '') .map(c => !c ? '0' : c); // check the input userCards.forEach((card) => { if (card === "0") { // user marking a slot with an unknown card this.validCards.push(card); } else if (this.validCards.includes(card)) { // this card was already seen in user's input, now it's a duplicate this.dupedCards.push(card); } else if (this.deck.includes(card)) { // not a duplicate, and in the reference deck? Valid, add to valid cards this.validCards.push(card); } else { // not a dupe, but not in reference deck: invalid, add to invalid cards this.invalidCards.push(card); } }); // set validation messages based on length if (this.isValidCardsLengthTooSmall) { this.invalidMessages.push(`Must enter at least ${this.minCards} cards`); } else if (this.isValidCardsLengthTooBig) { this.invalidMessages.push( `Must not enter more than ${this.deck.length} cards` ); } if (this.validCards.slice(this.validCards.length - 34).includes("0")) { this.invalidMessages.push( `Stock + bottom row (last 34 cards) must not contain unknown ('0') cards` ); } // set other validation messages if (this.dupedCards.length > 0) { let s = this.dupedCards.length > 1 ? "s" : ""; this.invalidMessages.push( `${this.dupedCards.length} duplicate card${s}: ${this.dupedCards.join( " " )}` ); } if (this.invalidCards.length > 0) { let s = this.invalidCards.length > 1 ? "s" : ""; this.invalidMessages.push( `${this.invalidCards.length} invalid card${s}: ${this.invalidCards.join( " " )}` ); } if (this.validCards.length > 0) { let s = this.validCards.length > 1 ? "s" : ""; this.validMessages.push( `${this.validCards.length} valid card${s}: ${this.validCards.join(" ")}` ); } // set the game cards to try solving, based on current input this.$store.global.cardsToSolve = Array(this.deck.length - this.validCards.length) .fill(0) .concat(this.validCards) .map((c) => (c === "0" ? 0 : c)); }, })); window.Alpine = Alpine; Alpine.start();